|
@@ -9,6 +9,9 @@
|
|
|
*/
|
|
|
|
|
|
#include <linux/wait.h>
|
|
|
+#ifdef CONFIG_LOCKDEP_COMPLETE
|
|
|
+#include <linux/lockdep.h>
|
|
|
+#endif
|
|
|
|
|
|
/*
|
|
|
* struct completion - structure used to maintain state for a "completion"
|
|
@@ -25,10 +28,50 @@
|
|
|
struct completion {
|
|
|
unsigned int done;
|
|
|
wait_queue_head_t wait;
|
|
|
+#ifdef CONFIG_LOCKDEP_COMPLETE
|
|
|
+ struct lockdep_map_cross map;
|
|
|
+#endif
|
|
|
};
|
|
|
|
|
|
+#ifdef CONFIG_LOCKDEP_COMPLETE
|
|
|
+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(x) \
|
|
|
+do { \
|
|
|
+ static struct lock_class_key __key; \
|
|
|
+ lockdep_init_map_crosslock((struct lockdep_map *)&(x)->map, \
|
|
|
+ "(complete)" #x, \
|
|
|
+ &__key, 0); \
|
|
|
+ __init_completion(x); \
|
|
|
+} while (0)
|
|
|
+#else
|
|
|
+#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_COMPLETE
|
|
|
+#define COMPLETION_INITIALIZER(work) \
|
|
|
+ { 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait), \
|
|
|
+ STATIC_CROSS_LOCKDEP_MAP_INIT("(complete)" #work, &(work)) }
|
|
|
+#else
|
|
|
#define COMPLETION_INITIALIZER(work) \
|
|
|
{ 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
|
|
|
+#endif
|
|
|
|
|
|
#define COMPLETION_INITIALIZER_ONSTACK(work) \
|
|
|
({ init_completion(&work); work; })
|
|
@@ -70,7 +113,7 @@ struct completion {
|
|
|
* This inline function will initialize a dynamically created completion
|
|
|
* structure.
|
|
|
*/
|
|
|
-static inline void init_completion(struct completion *x)
|
|
|
+static inline void __init_completion(struct completion *x)
|
|
|
{
|
|
|
x->done = 0;
|
|
|
init_waitqueue_head(&x->wait);
|