aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/workqueue.h8
-rw-r--r--kernel/workqueue.c14
2 files changed, 16 insertions, 6 deletions
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index ab95fef38d56..f562674db404 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -68,9 +68,15 @@ enum {
68 WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT + 68 WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT +
69 WORK_STRUCT_COLOR_BITS, 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 WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1, 77 WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1,
72 WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK, 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 /* bit mask for work_busy() return values */ 81 /* bit mask for work_busy() return values */
76 WORK_BUSY_PENDING = 1 << 0, 82 WORK_BUSY_PENDING = 1 << 0,
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 0f50f4078e36..eeae77079483 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -533,9 +533,9 @@ static int work_next_color(int color)
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,
565static void set_work_cpu_and_clear_pending(struct work_struct *work, 565static 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
571static void clear_work_data(struct work_struct *work) 571static void clear_work_data(struct work_struct *work)
@@ -592,7 +592,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work)
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)
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