Skip to content

Commit eb13ba8

Browse files
jmbergPeter Zijlstra
authored andcommitted
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 <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Signed-off-by: Peter Zijlstra <[email protected]>
1 parent 5a26db5 commit eb13ba8

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

include/linux/workqueue.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,27 @@ struct execute_work {
149149

150150
extern struct workqueue_struct *
151151
__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);
153154

154155
#ifdef CONFIG_LOCKDEP
155156
#define __create_workqueue(name, singlethread, freezeable) \
156157
({ \
157158
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; \
158165
\
159166
__create_workqueue_key((name), (singlethread), \
160-
(freezeable), &__key); \
167+
(freezeable), &__key, \
168+
__lock_name); \
161169
})
162170
#else
163171
#define __create_workqueue(name, singlethread, freezeable) \
164-
__create_workqueue_key((name), (singlethread), (freezeable), NULL)
172+
__create_workqueue_key((name), (singlethread), (freezeable), NULL, NULL)
165173
#endif
166174

167175
#define create_workqueue(name) __create_workqueue((name), 0, 0)

kernel/workqueue.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,8 @@ static void start_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
722722
struct workqueue_struct *__create_workqueue_key(const char *name,
723723
int singlethread,
724724
int freezeable,
725-
struct lock_class_key *key)
725+
struct lock_class_key *key,
726+
const char *lock_name)
726727
{
727728
struct workqueue_struct *wq;
728729
struct cpu_workqueue_struct *cwq;
@@ -739,7 +740,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
739740
}
740741

741742
wq->name = name;
742-
lockdep_init_map(&wq->lockdep_map, name, key, 0);
743+
lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
743744
wq->singlethread = singlethread;
744745
wq->freezeable = freezeable;
745746
INIT_LIST_HEAD(&wq->list);

0 commit comments

Comments
 (0)