This introduces a single wait_queue_t into the task structure. Functions which need to wait, but which do not call other functions that might wait while on the wait queue, may use current->__wq for bookkeeping instead of allocating an instance on the stack. To help ensure that the users are indeed "leaf waiters", make all access through two helper functions.
Signed-off-by: Rasmus Villemoes <[email protected]> --- include/linux/sched.h | 23 +++++++++++++++++++++++ include/linux/wait.h | 1 + kernel/fork.c | 1 + 3 files changed, 25 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 221b2bd..c7c97fe 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1303,6 +1303,15 @@ struct task_struct { struct list_head thread_group; struct list_head thread_node; + /* + * "Leaf" waiters may use this instead of allocating a + * wait_queue_t on the stack. To help ensure exclusive use of + * __wq, one should use the helper functions current_wq_get(), + * current_wq_put() below. Leaf waiters include the + * wait_event_* macros. + */ + wait_queue_t __wq; + struct completion *vfork_done; /* for vfork() */ int __user *set_child_tid; /* CLONE_CHILD_SETTID */ int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */ @@ -1612,6 +1621,20 @@ struct task_struct { #endif }; +static inline wait_queue_t *current_wq_get(void) +{ + wait_queue_t *wq = ¤t->__wq; + BUG_ON(wq->flags != WQ_FLAG_AVAILABLE); + wq->flags = 0; + return wq; +} +static inline void current_wq_put(wait_queue_t *wq) +{ + BUG_ON(wq != ¤t->__wq); + wq->flags = WQ_FLAG_AVAILABLE; +} + + /* Future-safe accessor for struct task_struct's cpus_allowed. */ #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) diff --git a/include/linux/wait.h b/include/linux/wait.h index bd68819..94279be 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -16,6 +16,7 @@ int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *ke struct __wait_queue { unsigned int flags; #define WQ_FLAG_EXCLUSIVE 0x01 +#define WQ_FLAG_AVAILABLE 0x80000000U void *private; wait_queue_func_t func; struct list_head task_list; diff --git a/kernel/fork.c b/kernel/fork.c index 54a8d26..7166955 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1315,6 +1315,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->sequential_io = 0; p->sequential_io_avg = 0; #endif + p->__wq.flags = WQ_FLAG_AVAILABLE; /* Perform scheduler related setup. Assign this task to a CPU. */ retval = sched_fork(clone_flags, p); -- 1.9.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

