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.
Showing the changes to kernel/workqueue.c (1 of 2 files). Show all
Unified · Split
| @@ -533,9 +533,9 @@ static int work_next_color(int color) · 532 unmodified lines | |||
| 533 | } | 533 | } |
| 534 | 534 | ||
| 535 | /* | 535 | /* |
| 536 | * A work's data points to the cwq with WORK_STRUCT_CWQ set while the | 536 | * While queued, %WORK_STRUCT_CWQ is set and non flag bits of a work's data |
| 537 | * work is on queue. Once execution starts, WORK_STRUCT_CWQ is | 537 | * contain the pointer to the queued cwq. Once execution starts, the flag |
| 538 | * cleared and the work data contains the cpu number it was last on. | 538 | * is cleared and the high bits contain OFFQ flags and CPU number. |
| 539 | * | 539 | * |
| 540 | * set_work_cwq(), set_work_cpu_and_clear_pending() and clear_work_data() | 540 | * set_work_cwq(), set_work_cpu_and_clear_pending() and clear_work_data() |
| 541 | * can be used to set the cwq, cpu or clear work->data. These functions | 541 | * can be used to set the cwq, cpu or clear work->data. These functions |
| @@ -565,7 +565,7 @@ static void set_work_cwq(struct work_struct *work, · 23 unmodified lines | |||
| 565 | static void set_work_cpu_and_clear_pending(struct work_struct *work, | 565 | static void set_work_cpu_and_clear_pending(struct work_struct *work, |
| 566 | unsigned int cpu) | 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 | static void clear_work_data(struct work_struct *work) | 571 | static void clear_work_data(struct work_struct *work) |
| @@ -592,7 +592,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work) · 20 unmodified lines | |||
| 592 | return ((struct cpu_workqueue_struct *) | 592 | return ((struct cpu_workqueue_struct *) |
| 593 | (data & WORK_STRUCT_WQ_DATA_MASK))->pool->gcwq; | 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 | if (cpu == WORK_CPU_NONE) | 596 | if (cpu == WORK_CPU_NONE) |
| 597 | return NULL; | 597 | return NULL; |
| 598 | 598 | ||
| @@ -3724,6 +3724,10 @@ static int __init init_workqueues(void) · 3125 unmodified lines | |||
| 3724 | unsigned int cpu; | 3724 | unsigned int cpu; |
| 3725 | int i; | 3725 | int i; |
| 3726 | 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); | ||
| 3730 | |||
| 3727 | cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); | 3731 | cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); |
| 3728 | cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); | 3732 | cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); |
| 3729 | 3733 | ||