|
@@ -1097,6 +1097,7 @@ struct wait_opts {
|
|
|
int __user *wo_stat;
|
|
|
struct rusage __user *wo_rusage;
|
|
|
|
|
|
+ wait_queue_t child_wait;
|
|
|
int notask_error;
|
|
|
};
|
|
|
|
|
@@ -1570,20 +1571,35 @@ static int ptrace_do_wait(struct wait_opts *wo, struct task_struct *tsk)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int child_wait_callback(wait_queue_t *wait, unsigned mode,
|
|
|
+ int sync, void *key)
|
|
|
+{
|
|
|
+ struct wait_opts *wo = container_of(wait, struct wait_opts,
|
|
|
+ child_wait);
|
|
|
+ struct task_struct *p = key;
|
|
|
+
|
|
|
+ if (!eligible_child(wo, p))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return default_wake_function(wait, mode, sync, key);
|
|
|
+}
|
|
|
+
|
|
|
void __wake_up_parent(struct task_struct *p, struct task_struct *parent)
|
|
|
{
|
|
|
- wake_up_interruptible_sync(&parent->signal->wait_chldexit);
|
|
|
+ __wake_up_sync_key(&parent->signal->wait_chldexit,
|
|
|
+ TASK_INTERRUPTIBLE, 1, p);
|
|
|
}
|
|
|
|
|
|
static long do_wait(struct wait_opts *wo)
|
|
|
{
|
|
|
- DECLARE_WAITQUEUE(wait, current);
|
|
|
struct task_struct *tsk;
|
|
|
int retval;
|
|
|
|
|
|
trace_sched_process_wait(wo->wo_pid);
|
|
|
|
|
|
- add_wait_queue(¤t->signal->wait_chldexit,&wait);
|
|
|
+ init_waitqueue_func_entry(&wo->child_wait, child_wait_callback);
|
|
|
+ wo->child_wait.private = current;
|
|
|
+ add_wait_queue(¤t->signal->wait_chldexit, &wo->child_wait);
|
|
|
repeat:
|
|
|
/*
|
|
|
* If there is nothing that can match our critiera just get out.
|
|
@@ -1624,7 +1640,8 @@ notask:
|
|
|
}
|
|
|
end:
|
|
|
__set_current_state(TASK_RUNNING);
|
|
|
- remove_wait_queue(¤t->signal->wait_chldexit,&wait);
|
|
|
+ remove_wait_queue(¤t->signal->wait_chldexit, &wo->child_wait);
|
|
|
+
|
|
|
if (wo->wo_info) {
|
|
|
struct siginfo __user *infop = wo->wo_info;
|
|
|
|