Commit b5490077274482efde57a50b060b99bc839acd45
1 parent
bf4ede014e
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
workqueue: introduce WORK_OFFQ_FLAG_*
Low WORK_STRUCT_FLAG_BITS bits of work_struct->data contain WORK_STRUCT_FLAG_* and flush color. If the work item is queued, the rest point to the cpu_workqueue with WORK_STRUCT_CWQ set; otherwise, WORK_STRUCT_CWQ is clear and the bits contain the last CPU number - either a real CPU number or one of WORK_CPU_*. Scheduled addition of mod_delayed_work[_on]() requires an additional flag, which is used only while a work item is off queue. There are more than enough bits to represent off-queue CPU number on both 32 and 64bits. This patch introduces WORK_OFFQ_FLAG_* which occupy the lower part of the @work->data high bits while off queue. This patch doesn't define any actual OFFQ flag yet. Off-queue CPU number is now shifted by WORK_OFFQ_CPU_SHIFT, which adds the number of bits used by OFFQ flags to WORK_STRUCT_FLAG_SHIFT, to make room for OFFQ flags. To avoid shift width warning with large WORK_OFFQ_FLAG_BITS, ulong cast is added to WORK_STRUCT_NO_CPU and, just in case, BUILD_BUG_ON() to check that there are enough bits to accomodate off-queue CPU number is added. This patch doesn't make any functional difference. Signed-off-by: Tejun Heo <tj@kernel.org>
Showing 2 changed files with 16 additions and 6 deletions Side-by-side Diff
include/linux/workqueue.h
... | ... | @@ -68,9 +68,15 @@ |
68 | 68 | WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT + |
69 | 69 | WORK_STRUCT_COLOR_BITS, |
70 | 70 | |
71 | + /* data contains off-queue information when !WORK_STRUCT_CWQ */ | |
72 | + WORK_OFFQ_FLAG_BASE = WORK_STRUCT_FLAG_BITS, | |
73 | + WORK_OFFQ_FLAG_BITS = 0, | |
74 | + WORK_OFFQ_CPU_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS, | |
75 | + | |
76 | + /* convenience constants */ | |
71 | 77 | WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1, |
72 | 78 | WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK, |
73 | - WORK_STRUCT_NO_CPU = WORK_CPU_NONE << WORK_STRUCT_FLAG_BITS, | |
79 | + WORK_STRUCT_NO_CPU = (unsigned long)WORK_CPU_NONE << WORK_OFFQ_CPU_SHIFT, | |
74 | 80 | |
75 | 81 | /* bit mask for work_busy() return values */ |
76 | 82 | WORK_BUSY_PENDING = 1 << 0, |
kernel/workqueue.c
... | ... | @@ -533,9 +533,9 @@ |
533 | 533 | } |
534 | 534 | |
535 | 535 | /* |
536 | - * A work's data points to the cwq with WORK_STRUCT_CWQ set while the | |
537 | - * work is on queue. Once execution starts, WORK_STRUCT_CWQ is | |
538 | - * cleared and the work data contains the cpu number it was last on. | |
536 | + * While queued, %WORK_STRUCT_CWQ is set and non flag bits of a work's data | |
537 | + * contain the pointer to the queued cwq. Once execution starts, the flag | |
538 | + * is cleared and the high bits contain OFFQ flags and CPU number. | |
539 | 539 | * |
540 | 540 | * set_work_cwq(), set_work_cpu_and_clear_pending() and clear_work_data() |
541 | 541 | * can be used to set the cwq, cpu or clear work->data. These functions |
... | ... | @@ -565,7 +565,7 @@ |
565 | 565 | static void set_work_cpu_and_clear_pending(struct work_struct *work, |
566 | 566 | unsigned int cpu) |
567 | 567 | { |
568 | - set_work_data(work, cpu << WORK_STRUCT_FLAG_BITS, 0); | |
568 | + set_work_data(work, (unsigned long)cpu << WORK_OFFQ_CPU_SHIFT, 0); | |
569 | 569 | } |
570 | 570 | |
571 | 571 | static void clear_work_data(struct work_struct *work) |
... | ... | @@ -592,7 +592,7 @@ |
592 | 592 | return ((struct cpu_workqueue_struct *) |
593 | 593 | (data & WORK_STRUCT_WQ_DATA_MASK))->pool->gcwq; |
594 | 594 | |
595 | - cpu = data >> WORK_STRUCT_FLAG_BITS; | |
595 | + cpu = data >> WORK_OFFQ_CPU_SHIFT; | |
596 | 596 | if (cpu == WORK_CPU_NONE) |
597 | 597 | return NULL; |
598 | 598 | |
... | ... | @@ -3723,6 +3723,10 @@ |
3723 | 3723 | { |
3724 | 3724 | unsigned int cpu; |
3725 | 3725 | int i; |
3726 | + | |
3727 | + /* make sure we have enough bits for OFFQ CPU number */ | |
3728 | + BUILD_BUG_ON((1LU << (BITS_PER_LONG - WORK_OFFQ_CPU_SHIFT)) < | |
3729 | + WORK_CPU_LAST); | |
3726 | 3730 | |
3727 | 3731 | cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); |
3728 | 3732 | cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); |