wait_for_completion() can be used at various points in the code and it's very hard to distinguish wait_for_completion()s between different usages. Using a single dept_key for all the wait_for_completion()s could trigger false positive reports.
Assign unique dept_key to each distinct wait_for_completion() caller to avoid false positive reports. Signed-off-by: Byungchul Park <byungc...@sk.com> --- include/linux/completion.h | 100 +++++++++++++++++++++++++++++++------ kernel/sched/completion.c | 60 +++++++++++----------- 2 files changed, 115 insertions(+), 45 deletions(-) diff --git a/include/linux/completion.h b/include/linux/completion.h index 3200b741de28..4d8fb1d95c0a 100644 --- a/include/linux/completion.h +++ b/include/linux/completion.h @@ -27,12 +27,10 @@ struct completion { unsigned int done; struct swait_queue_head wait; - struct dept_map dmap; }; #define init_completion(x) \ do { \ - sdt_map_init(&(x)->dmap); \ __init_completion(x); \ } while (0) @@ -43,17 +41,14 @@ do { \ static inline void complete_acquire(struct completion *x, long timeout) { - sdt_might_sleep_start_timeout(&x->dmap, timeout); } static inline void complete_release(struct completion *x) { - sdt_might_sleep_end(); } #define COMPLETION_INITIALIZER(work) \ - { 0, __SWAIT_QUEUE_HEAD_INITIALIZER((work).wait), \ - .dmap = DEPT_MAP_INITIALIZER(work, NULL), } + { 0, __SWAIT_QUEUE_HEAD_INITIALIZER((work).wait), } #define COMPLETION_INITIALIZER_ONSTACK_MAP(work, map) \ (*({ init_completion_map(&(work), &(map)); &(work); })) @@ -119,18 +114,18 @@ static inline void reinit_completion(struct completion *x) x->done = 0; } -extern void wait_for_completion(struct completion *); -extern void wait_for_completion_io(struct completion *); -extern int wait_for_completion_interruptible(struct completion *x); -extern int wait_for_completion_killable(struct completion *x); -extern int wait_for_completion_state(struct completion *x, unsigned int state); -extern unsigned long wait_for_completion_timeout(struct completion *x, +extern void __wait_for_completion(struct completion *); +extern void __wait_for_completion_io(struct completion *); +extern int __wait_for_completion_interruptible(struct completion *x); +extern int __wait_for_completion_killable(struct completion *x); +extern int __wait_for_completion_state(struct completion *x, unsigned int state); +extern unsigned long __wait_for_completion_timeout(struct completion *x, unsigned long timeout); -extern unsigned long wait_for_completion_io_timeout(struct completion *x, +extern unsigned long __wait_for_completion_io_timeout(struct completion *x, unsigned long timeout); -extern long wait_for_completion_interruptible_timeout( +extern long __wait_for_completion_interruptible_timeout( struct completion *x, unsigned long timeout); -extern long wait_for_completion_killable_timeout( +extern long __wait_for_completion_killable_timeout( struct completion *x, unsigned long timeout); extern bool try_wait_for_completion(struct completion *x); extern bool completion_done(struct completion *x); @@ -139,4 +134,79 @@ extern void complete(struct completion *); extern void complete_on_current_cpu(struct completion *x); extern void complete_all(struct completion *); +#define wait_for_completion(x) \ +({ \ + sdt_might_sleep_start_timeout(NULL, -1L); \ + __wait_for_completion(x); \ + sdt_might_sleep_end(); \ +}) +#define wait_for_completion_io(x) \ +({ \ + sdt_might_sleep_start_timeout(NULL, -1L); \ + __wait_for_completion_io(x); \ + sdt_might_sleep_end(); \ +}) +#define wait_for_completion_interruptible(x) \ +({ \ + int __ret; \ + \ + sdt_might_sleep_start_timeout(NULL, -1L); \ + __ret = __wait_for_completion_interruptible(x); \ + sdt_might_sleep_end(); \ + __ret; \ +}) +#define wait_for_completion_killable(x) \ +({ \ + int __ret; \ + \ + sdt_might_sleep_start_timeout(NULL, -1L); \ + __ret = __wait_for_completion_killable(x); \ + sdt_might_sleep_end(); \ + __ret; \ +}) +#define wait_for_completion_state(x, s) \ +({ \ + int __ret; \ + \ + sdt_might_sleep_start_timeout(NULL, -1L); \ + __ret = __wait_for_completion_state(x, s); \ + sdt_might_sleep_end(); \ + __ret; \ +}) +#define wait_for_completion_timeout(x, t) \ +({ \ + unsigned long __ret; \ + \ + sdt_might_sleep_start_timeout(NULL, t); \ + __ret = __wait_for_completion_timeout(x, t); \ + sdt_might_sleep_end(); \ + __ret; \ +}) +#define wait_for_completion_io_timeout(x, t) \ +({ \ + unsigned long __ret; \ + \ + sdt_might_sleep_start_timeout(NULL, t); \ + __ret = __wait_for_completion_io_timeout(x, t); \ + sdt_might_sleep_end(); \ + __ret; \ +}) +#define wait_for_completion_interruptible_timeout(x, t) \ +({ \ + long __ret; \ + \ + sdt_might_sleep_start_timeout(NULL, t); \ + __ret = __wait_for_completion_interruptible_timeout(x, t); \ + sdt_might_sleep_end(); \ + __ret; \ +}) +#define wait_for_completion_killable_timeout(x, t) \ +({ \ + long __ret; \ + \ + sdt_might_sleep_start_timeout(NULL, t); \ + __ret = __wait_for_completion_killable_timeout(x, t); \ + sdt_might_sleep_end(); \ + __ret; \ +}) #endif diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c index 499b1fee9dc1..247169b26d81 100644 --- a/kernel/sched/completion.c +++ b/kernel/sched/completion.c @@ -4,7 +4,7 @@ * Generic wait-for-completion handler; * * It differs from semaphores in that their default case is the opposite, - * wait_for_completion default blocks whereas semaphore default non-block. The + * __wait_for_completion default blocks whereas semaphore default non-block. The * interface also makes it easy to 'complete' multiple waiting threads, * something which isn't entirely natural for semaphores. * @@ -37,7 +37,7 @@ void complete_on_current_cpu(struct completion *x) * This will wake up a single thread waiting on this completion. Threads will be * awakened in the same order in which they were queued. * - * See also complete_all(), wait_for_completion() and related routines. + * See also complete_all(), __wait_for_completion() and related routines. * * If this function wakes up a task, it executes a full memory barrier before * accessing the task state. @@ -134,23 +134,23 @@ wait_for_common_io(struct completion *x, long timeout, int state) } /** - * wait_for_completion: - waits for completion of a task + * __wait_for_completion: - waits for completion of a task * @x: holds the state of this particular completion * * This waits to be signaled for completion of a specific task. It is NOT * interruptible and there is no timeout. * - * See also similar routines (i.e. wait_for_completion_timeout()) with timeout + * See also similar routines (i.e. __wait_for_completion_timeout()) with timeout * and interrupt capability. Also see complete(). */ -void __sched wait_for_completion(struct completion *x) +void __sched __wait_for_completion(struct completion *x) { wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); } -EXPORT_SYMBOL(wait_for_completion); +EXPORT_SYMBOL(__wait_for_completion); /** - * wait_for_completion_timeout: - waits for completion of a task (w/timeout) + * __wait_for_completion_timeout: - waits for completion of a task (w/timeout) * @x: holds the state of this particular completion * @timeout: timeout value in jiffies * @@ -162,28 +162,28 @@ EXPORT_SYMBOL(wait_for_completion); * till timeout) if completed. */ unsigned long __sched -wait_for_completion_timeout(struct completion *x, unsigned long timeout) +__wait_for_completion_timeout(struct completion *x, unsigned long timeout) { return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE); } -EXPORT_SYMBOL(wait_for_completion_timeout); +EXPORT_SYMBOL(__wait_for_completion_timeout); /** - * wait_for_completion_io: - waits for completion of a task + * __wait_for_completion_io: - waits for completion of a task * @x: holds the state of this particular completion * * This waits to be signaled for completion of a specific task. It is NOT * interruptible and there is no timeout. The caller is accounted as waiting * for IO (which traditionally means blkio only). */ -void __sched wait_for_completion_io(struct completion *x) +void __sched __wait_for_completion_io(struct completion *x) { wait_for_common_io(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); } -EXPORT_SYMBOL(wait_for_completion_io); +EXPORT_SYMBOL(__wait_for_completion_io); /** - * wait_for_completion_io_timeout: - waits for completion of a task (w/timeout) + * __wait_for_completion_io_timeout: - waits for completion of a task (w/timeout) * @x: holds the state of this particular completion * @timeout: timeout value in jiffies * @@ -196,14 +196,14 @@ EXPORT_SYMBOL(wait_for_completion_io); * till timeout) if completed. */ unsigned long __sched -wait_for_completion_io_timeout(struct completion *x, unsigned long timeout) +__wait_for_completion_io_timeout(struct completion *x, unsigned long timeout) { return wait_for_common_io(x, timeout, TASK_UNINTERRUPTIBLE); } -EXPORT_SYMBOL(wait_for_completion_io_timeout); +EXPORT_SYMBOL(__wait_for_completion_io_timeout); /** - * wait_for_completion_interruptible: - waits for completion of a task (w/intr) + * __wait_for_completion_interruptible: - waits for completion of a task (w/intr) * @x: holds the state of this particular completion * * This waits for completion of a specific task to be signaled. It is @@ -211,7 +211,7 @@ EXPORT_SYMBOL(wait_for_completion_io_timeout); * * Return: -ERESTARTSYS if interrupted, 0 if completed. */ -int __sched wait_for_completion_interruptible(struct completion *x) +int __sched __wait_for_completion_interruptible(struct completion *x) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE); @@ -219,10 +219,10 @@ int __sched wait_for_completion_interruptible(struct completion *x) return t; return 0; } -EXPORT_SYMBOL(wait_for_completion_interruptible); +EXPORT_SYMBOL(__wait_for_completion_interruptible); /** - * wait_for_completion_interruptible_timeout: - waits for completion (w/(to,intr)) + * __wait_for_completion_interruptible_timeout: - waits for completion (w/(to,intr)) * @x: holds the state of this particular completion * @timeout: timeout value in jiffies * @@ -233,15 +233,15 @@ EXPORT_SYMBOL(wait_for_completion_interruptible); * or number of jiffies left till timeout) if completed. */ long __sched -wait_for_completion_interruptible_timeout(struct completion *x, +__wait_for_completion_interruptible_timeout(struct completion *x, unsigned long timeout) { return wait_for_common(x, timeout, TASK_INTERRUPTIBLE); } -EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); +EXPORT_SYMBOL(__wait_for_completion_interruptible_timeout); /** - * wait_for_completion_killable: - waits for completion of a task (killable) + * __wait_for_completion_killable: - waits for completion of a task (killable) * @x: holds the state of this particular completion * * This waits to be signaled for completion of a specific task. It can be @@ -249,7 +249,7 @@ EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); * * Return: -ERESTARTSYS if interrupted, 0 if completed. */ -int __sched wait_for_completion_killable(struct completion *x) +int __sched __wait_for_completion_killable(struct completion *x) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE); @@ -257,9 +257,9 @@ int __sched wait_for_completion_killable(struct completion *x) return t; return 0; } -EXPORT_SYMBOL(wait_for_completion_killable); +EXPORT_SYMBOL(__wait_for_completion_killable); -int __sched wait_for_completion_state(struct completion *x, unsigned int state) +int __sched __wait_for_completion_state(struct completion *x, unsigned int state) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, state); @@ -267,10 +267,10 @@ int __sched wait_for_completion_state(struct completion *x, unsigned int state) return t; return 0; } -EXPORT_SYMBOL(wait_for_completion_state); +EXPORT_SYMBOL(__wait_for_completion_state); /** - * wait_for_completion_killable_timeout: - waits for completion of a task (w/(to,killable)) + * __wait_for_completion_killable_timeout: - waits for completion of a task (w/(to,killable)) * @x: holds the state of this particular completion * @timeout: timeout value in jiffies * @@ -282,12 +282,12 @@ EXPORT_SYMBOL(wait_for_completion_state); * or number of jiffies left till timeout) if completed. */ long __sched -wait_for_completion_killable_timeout(struct completion *x, +__wait_for_completion_killable_timeout(struct completion *x, unsigned long timeout) { return wait_for_common(x, timeout, TASK_KILLABLE); } -EXPORT_SYMBOL(wait_for_completion_killable_timeout); +EXPORT_SYMBOL(__wait_for_completion_killable_timeout); /** * try_wait_for_completion - try to decrement a completion without blocking @@ -329,7 +329,7 @@ EXPORT_SYMBOL(try_wait_for_completion); * completion_done - Test to see if a completion has any waiters * @x: completion structure * - * Return: 0 if there are waiters (wait_for_completion() in progress) + * Return: 0 if there are waiters (__wait_for_completion() in progress) * 1 if there are no waiters. * * Note, this will always return true if complete_all() was called on @X. -- 2.17.1