Skip to content

Commit 866b887

Browse files
committed
Merge tag 'wq-for-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
Pull workqueue update from Tejun Heo: "Just one commit to improve lockdep annotation for work_on_cpu() to avoid spurious warnings" * tag 'wq-for-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq: workqueue: Provide one lock class key per work_on_cpu() callsite
2 parents 639409a + 265f3ed commit 866b887

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

include/linux/workqueue.h

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -274,18 +274,16 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
274274
* to generate better code.
275275
*/
276276
#ifdef CONFIG_LOCKDEP
277-
#define __INIT_WORK(_work, _func, _onstack) \
277+
#define __INIT_WORK_KEY(_work, _func, _onstack, _key) \
278278
do { \
279-
static struct lock_class_key __key; \
280-
\
281279
__init_work((_work), _onstack); \
282280
(_work)->data = (atomic_long_t) WORK_DATA_INIT(); \
283-
lockdep_init_map(&(_work)->lockdep_map, "(work_completion)"#_work, &__key, 0); \
281+
lockdep_init_map(&(_work)->lockdep_map, "(work_completion)"#_work, (_key), 0); \
284282
INIT_LIST_HEAD(&(_work)->entry); \
285283
(_work)->func = (_func); \
286284
} while (0)
287285
#else
288-
#define __INIT_WORK(_work, _func, _onstack) \
286+
#define __INIT_WORK_KEY(_work, _func, _onstack, _key) \
289287
do { \
290288
__init_work((_work), _onstack); \
291289
(_work)->data = (atomic_long_t) WORK_DATA_INIT(); \
@@ -294,12 +292,22 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
294292
} while (0)
295293
#endif
296294

295+
#define __INIT_WORK(_work, _func, _onstack) \
296+
do { \
297+
static __maybe_unused struct lock_class_key __key; \
298+
\
299+
__INIT_WORK_KEY(_work, _func, _onstack, &__key); \
300+
} while (0)
301+
297302
#define INIT_WORK(_work, _func) \
298303
__INIT_WORK((_work), (_func), 0)
299304

300305
#define INIT_WORK_ONSTACK(_work, _func) \
301306
__INIT_WORK((_work), (_func), 1)
302307

308+
#define INIT_WORK_ONSTACK_KEY(_work, _func, _key) \
309+
__INIT_WORK_KEY((_work), (_func), 1, _key)
310+
303311
#define __INIT_DELAYED_WORK(_work, _func, _tflags) \
304312
do { \
305313
INIT_WORK(&(_work)->work, (_func)); \
@@ -693,8 +701,32 @@ static inline long work_on_cpu_safe(int cpu, long (*fn)(void *), void *arg)
693701
return fn(arg);
694702
}
695703
#else
696-
long work_on_cpu(int cpu, long (*fn)(void *), void *arg);
697-
long work_on_cpu_safe(int cpu, long (*fn)(void *), void *arg);
704+
long work_on_cpu_key(int cpu, long (*fn)(void *),
705+
void *arg, struct lock_class_key *key);
706+
/*
707+
* A new key is defined for each caller to make sure the work
708+
* associated with the function doesn't share its locking class.
709+
*/
710+
#define work_on_cpu(_cpu, _fn, _arg) \
711+
({ \
712+
static struct lock_class_key __key; \
713+
\
714+
work_on_cpu_key(_cpu, _fn, _arg, &__key); \
715+
})
716+
717+
long work_on_cpu_safe_key(int cpu, long (*fn)(void *),
718+
void *arg, struct lock_class_key *key);
719+
720+
/*
721+
* A new key is defined for each caller to make sure the work
722+
* associated with the function doesn't share its locking class.
723+
*/
724+
#define work_on_cpu_safe(_cpu, _fn, _arg) \
725+
({ \
726+
static struct lock_class_key __key; \
727+
\
728+
work_on_cpu_safe_key(_cpu, _fn, _arg, &__key); \
729+
})
698730
#endif /* CONFIG_SMP */
699731

700732
#ifdef CONFIG_FREEZER

kernel/workqueue.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5622,50 +5622,54 @@ static void work_for_cpu_fn(struct work_struct *work)
56225622
}
56235623

56245624
/**
5625-
* work_on_cpu - run a function in thread context on a particular cpu
5625+
* work_on_cpu_key - run a function in thread context on a particular cpu
56265626
* @cpu: the cpu to run on
56275627
* @fn: the function to run
56285628
* @arg: the function arg
5629+
* @key: The lock class key for lock debugging purposes
56295630
*
56305631
* It is up to the caller to ensure that the cpu doesn't go offline.
56315632
* The caller must not hold any locks which would prevent @fn from completing.
56325633
*
56335634
* Return: The value @fn returns.
56345635
*/
5635-
long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
5636+
long work_on_cpu_key(int cpu, long (*fn)(void *),
5637+
void *arg, struct lock_class_key *key)
56365638
{
56375639
struct work_for_cpu wfc = { .fn = fn, .arg = arg };
56385640

5639-
INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
5641+
INIT_WORK_ONSTACK_KEY(&wfc.work, work_for_cpu_fn, key);
56405642
schedule_work_on(cpu, &wfc.work);
56415643
flush_work(&wfc.work);
56425644
destroy_work_on_stack(&wfc.work);
56435645
return wfc.ret;
56445646
}
5645-
EXPORT_SYMBOL_GPL(work_on_cpu);
5647+
EXPORT_SYMBOL_GPL(work_on_cpu_key);
56465648

56475649
/**
5648-
* work_on_cpu_safe - run a function in thread context on a particular cpu
5650+
* work_on_cpu_safe_key - run a function in thread context on a particular cpu
56495651
* @cpu: the cpu to run on
56505652
* @fn: the function to run
56515653
* @arg: the function argument
5654+
* @key: The lock class key for lock debugging purposes
56525655
*
56535656
* Disables CPU hotplug and calls work_on_cpu(). The caller must not hold
56545657
* any locks which would prevent @fn from completing.
56555658
*
56565659
* Return: The value @fn returns.
56575660
*/
5658-
long work_on_cpu_safe(int cpu, long (*fn)(void *), void *arg)
5661+
long work_on_cpu_safe_key(int cpu, long (*fn)(void *),
5662+
void *arg, struct lock_class_key *key)
56595663
{
56605664
long ret = -ENODEV;
56615665

56625666
cpus_read_lock();
56635667
if (cpu_online(cpu))
5664-
ret = work_on_cpu(cpu, fn, arg);
5668+
ret = work_on_cpu_key(cpu, fn, arg, key);
56655669
cpus_read_unlock();
56665670
return ret;
56675671
}
5668-
EXPORT_SYMBOL_GPL(work_on_cpu_safe);
5672+
EXPORT_SYMBOL_GPL(work_on_cpu_safe_key);
56695673
#endif /* CONFIG_SMP */
56705674

56715675
#ifdef CONFIG_FREEZER

0 commit comments

Comments
 (0)