aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-01-16 03:51:58 -0500
committerPeter Zijlstra <a.p.zijlstra@chello.nl>2008-01-16 03:51:58 -0500
commiteb13ba873881abd5e15af784756a61af635e665e (patch)
tree228bf4afa2c4418ad09cd50b3ebb762f793ed84a
parent5a26db5bd25cf4bf32ae9fa9f6136b6b6d5b45c5 (diff)
lockdep: fix workqueue creation API lockdep interaction
Dave Young reported warnings from lockdep that the workqueue API can sometimes try to register lockdep classes with the same key but different names. This is not permitted in lockdep. Unfortunately, I was unaware of that restriction when I wrote the code to debug workqueue problems with lockdep and used the workqueue name as the lockdep class name. This can obviously lead to the problem if the workqueue name is dynamic. This patch solves the problem by always using a constant name for the workqueue's lockdep class, namely either the constant name that was passed in or a string consisting of the variable name. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
-rw-r--r--include/linux/workqueue.h14
-rw-r--r--kernel/workqueue.c5
2 files changed, 14 insertions, 5 deletions
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 7daafdc2514b..7f28c32d9aca 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -149,19 +149,27 @@ struct execute_work {
149 149
150extern struct workqueue_struct * 150extern struct workqueue_struct *
151__create_workqueue_key(const char *name, int singlethread, 151__create_workqueue_key(const char *name, int singlethread,
152 int freezeable, struct lock_class_key *key); 152 int freezeable, struct lock_class_key *key,
153 const char *lock_name);
153 154
154#ifdef CONFIG_LOCKDEP 155#ifdef CONFIG_LOCKDEP
155#define __create_workqueue(name, singlethread, freezeable) \ 156#define __create_workqueue(name, singlethread, freezeable) \
156({ \ 157({ \
157 static struct lock_class_key __key; \ 158 static struct lock_class_key __key; \
159 const char *__lock_name; \
160 \
161 if (__builtin_constant_p(name)) \
162 __lock_name = (name); \
163 else \
164 __lock_name = #name; \
158 \ 165 \
159 __create_workqueue_key((name), (singlethread), \ 166 __create_workqueue_key((name), (singlethread), \
160 (freezeable), &__key); \ 167 (freezeable), &__key, \
168 __lock_name); \
161}) 169})
162#else 170#else
163#define __create_workqueue(name, singlethread, freezeable) \ 171#define __create_workqueue(name, singlethread, freezeable) \
164 __create_workqueue_key((name), (singlethread), (freezeable), NULL) 172 __create_workqueue_key((name), (singlethread), (freezeable), NULL, NULL)
165#endif 173#endif
166 174
167#define create_workqueue(name) __create_workqueue((name), 0, 0) 175#define create_workqueue(name) __create_workqueue((name), 0, 0)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 52d5e7c9a8e6..8db0b597509e 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -722,7 +722,8 @@ static void start_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
722struct workqueue_struct *__create_workqueue_key(const char *name, 722struct workqueue_struct *__create_workqueue_key(const char *name,
723 int singlethread, 723 int singlethread,
724 int freezeable, 724 int freezeable,
725 struct lock_class_key *key) 725 struct lock_class_key *key,
726 const char *lock_name)
726{ 727{
727 struct workqueue_struct *wq; 728 struct workqueue_struct *wq;
728 struct cpu_workqueue_struct *cwq; 729 struct cpu_workqueue_struct *cwq;
@@ -739,7 +740,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
739 } 740 }
740 741
741 wq->name = name; 742 wq->name = name;
742 lockdep_init_map(&wq->lockdep_map, name, key, 0); 743 lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
743 wq->singlethread = singlethread; 744 wq->singlethread = singlethread;
744 wq->freezeable = freezeable; 745 wq->freezeable = freezeable;
745 INIT_LIST_HEAD(&wq->list); 746 INIT_LIST_HEAD(&wq->list);