
Sometimes we want to initialize completions with sparate lockdep maps to assign lock classes as desired. For example, the workqueue code needs to directly manage lockdep maps, since only the code is aware of how to classify lockdep maps properly. Provide additional macros initializing completions in that way. Signed-off-by: Byungchul Park <byungchul.park@lge.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: amir73il@gmail.com Cc: axboe@kernel.dk Cc: darrick.wong@oracle.com Cc: david@fromorbit.com Cc: hch@infradead.org Cc: idryomov@gmail.com Cc: johan@kernel.org Cc: johannes.berg@intel.com Cc: kernel-team@lge.com Cc: linux-block@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Cc: linux-mm@kvack.org Cc: linux-xfs@vger.kernel.org Cc: oleg@redhat.com Cc: tj@kernel.org Link: http://lkml.kernel.org/r/1508921765-15396-8-git-send-email-byungchul.park@lge.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
167 lines
5.3 KiB
C
167 lines
5.3 KiB
C
#ifndef __LINUX_COMPLETION_H
|
|
#define __LINUX_COMPLETION_H
|
|
|
|
/*
|
|
* (C) Copyright 2001 Linus Torvalds
|
|
*
|
|
* Atomic wait-for-completion handler data structures.
|
|
* See kernel/sched/completion.c for details.
|
|
*/
|
|
|
|
#include <linux/wait.h>
|
|
#ifdef CONFIG_LOCKDEP_COMPLETIONS
|
|
#include <linux/lockdep.h>
|
|
#endif
|
|
|
|
/*
|
|
* struct completion - structure used to maintain state for a "completion"
|
|
*
|
|
* This is the opaque structure used to maintain the state for a "completion".
|
|
* Completions currently use a FIFO to queue threads that have to wait for
|
|
* the "completion" event.
|
|
*
|
|
* See also: complete(), wait_for_completion() (and friends _timeout,
|
|
* _interruptible, _interruptible_timeout, and _killable), init_completion(),
|
|
* reinit_completion(), and macros DECLARE_COMPLETION(),
|
|
* DECLARE_COMPLETION_ONSTACK().
|
|
*/
|
|
struct completion {
|
|
unsigned int done;
|
|
wait_queue_head_t wait;
|
|
#ifdef CONFIG_LOCKDEP_COMPLETIONS
|
|
struct lockdep_map_cross map;
|
|
#endif
|
|
};
|
|
|
|
#ifdef CONFIG_LOCKDEP_COMPLETIONS
|
|
static inline void complete_acquire(struct completion *x)
|
|
{
|
|
lock_acquire_exclusive((struct lockdep_map *)&x->map, 0, 0, NULL, _RET_IP_);
|
|
}
|
|
|
|
static inline void complete_release(struct completion *x)
|
|
{
|
|
lock_release((struct lockdep_map *)&x->map, 0, _RET_IP_);
|
|
}
|
|
|
|
static inline void complete_release_commit(struct completion *x)
|
|
{
|
|
lock_commit_crosslock((struct lockdep_map *)&x->map);
|
|
}
|
|
|
|
#define init_completion_map(x, m) \
|
|
do { \
|
|
lockdep_init_map_crosslock((struct lockdep_map *)&(x)->map, \
|
|
(m)->name, (m)->key, 0); \
|
|
__init_completion(x); \
|
|
} while (0)
|
|
|
|
#define init_completion(x) \
|
|
do { \
|
|
static struct lock_class_key __key; \
|
|
lockdep_init_map_crosslock((struct lockdep_map *)&(x)->map, \
|
|
"(completion)" #x, \
|
|
&__key, 0); \
|
|
__init_completion(x); \
|
|
} while (0)
|
|
#else
|
|
#define init_completion_map(x, m) __init_completion(x)
|
|
#define init_completion(x) __init_completion(x)
|
|
static inline void complete_acquire(struct completion *x) {}
|
|
static inline void complete_release(struct completion *x) {}
|
|
static inline void complete_release_commit(struct completion *x) {}
|
|
#endif
|
|
|
|
#ifdef CONFIG_LOCKDEP_COMPLETIONS
|
|
#define COMPLETION_INITIALIZER(work) \
|
|
{ 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait), \
|
|
STATIC_CROSS_LOCKDEP_MAP_INIT("(completion)" #work, &(work)) }
|
|
#else
|
|
#define COMPLETION_INITIALIZER(work) \
|
|
{ 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
|
|
#endif
|
|
|
|
#define COMPLETION_INITIALIZER_ONSTACK_MAP(work, map) \
|
|
(*({ init_completion_map(&(work), &(map)); &(work); }))
|
|
|
|
#define COMPLETION_INITIALIZER_ONSTACK(work) \
|
|
(*({ init_completion(&work); &work; }))
|
|
|
|
/**
|
|
* DECLARE_COMPLETION - declare and initialize a completion structure
|
|
* @work: identifier for the completion structure
|
|
*
|
|
* This macro declares and initializes a completion structure. Generally used
|
|
* for static declarations. You should use the _ONSTACK variant for automatic
|
|
* variables.
|
|
*/
|
|
#define DECLARE_COMPLETION(work) \
|
|
struct completion work = COMPLETION_INITIALIZER(work)
|
|
|
|
/*
|
|
* Lockdep needs to run a non-constant initializer for on-stack
|
|
* completions - so we use the _ONSTACK() variant for those that
|
|
* are on the kernel stack:
|
|
*/
|
|
/**
|
|
* DECLARE_COMPLETION_ONSTACK - declare and initialize a completion structure
|
|
* @work: identifier for the completion structure
|
|
*
|
|
* This macro declares and initializes a completion structure on the kernel
|
|
* stack.
|
|
*/
|
|
#ifdef CONFIG_LOCKDEP
|
|
# define DECLARE_COMPLETION_ONSTACK(work) \
|
|
struct completion work = COMPLETION_INITIALIZER_ONSTACK(work)
|
|
# define DECLARE_COMPLETION_ONSTACK_MAP(work, map) \
|
|
struct completion work = COMPLETION_INITIALIZER_ONSTACK_MAP(work, map)
|
|
#else
|
|
# define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work)
|
|
# define DECLARE_COMPLETION_ONSTACK_MAP(work, map) DECLARE_COMPLETION(work)
|
|
#endif
|
|
|
|
/**
|
|
* init_completion - Initialize a dynamically allocated completion
|
|
* @x: pointer to completion structure that is to be initialized
|
|
*
|
|
* This inline function will initialize a dynamically created completion
|
|
* structure.
|
|
*/
|
|
static inline void __init_completion(struct completion *x)
|
|
{
|
|
x->done = 0;
|
|
init_waitqueue_head(&x->wait);
|
|
}
|
|
|
|
/**
|
|
* reinit_completion - reinitialize a completion structure
|
|
* @x: pointer to completion structure that is to be reinitialized
|
|
*
|
|
* This inline function should be used to reinitialize a completion structure so it can
|
|
* be reused. This is especially important after complete_all() is used.
|
|
*/
|
|
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 unsigned long wait_for_completion_timeout(struct completion *x,
|
|
unsigned long timeout);
|
|
extern unsigned long wait_for_completion_io_timeout(struct completion *x,
|
|
unsigned long timeout);
|
|
extern long wait_for_completion_interruptible_timeout(
|
|
struct completion *x, unsigned long 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);
|
|
|
|
extern void complete(struct completion *);
|
|
extern void complete_all(struct completion *);
|
|
|
|
#endif
|