diff options
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 36 |
1 files changed, 13 insertions, 23 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index c11edc9c9365..e5cb7faac58e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -468,10 +468,9 @@ static int work_next_color(int color) | |||
468 | } | 468 | } |
469 | 469 | ||
470 | /* | 470 | /* |
471 | * Work data points to the cwq while a work is on queue. Once | 471 | * A work's data points to the cwq with WORK_STRUCT_CWQ set while the |
472 | * execution starts, it points to the cpu the work was last on. This | 472 | * work is on queue. Once execution starts, WORK_STRUCT_CWQ is |
473 | * can be distinguished by comparing the data value against | 473 | * cleared and the work data contains the cpu number it was last on. |
474 | * PAGE_OFFSET. | ||
475 | * | 474 | * |
476 | * set_work_{cwq|cpu}() and clear_work_data() can be used to set the | 475 | * set_work_{cwq|cpu}() and clear_work_data() can be used to set the |
477 | * cwq, cpu or clear work->data. These functions should only be | 476 | * cwq, cpu or clear work->data. These functions should only be |
@@ -494,7 +493,7 @@ static void set_work_cwq(struct work_struct *work, | |||
494 | unsigned long extra_flags) | 493 | unsigned long extra_flags) |
495 | { | 494 | { |
496 | set_work_data(work, (unsigned long)cwq, | 495 | set_work_data(work, (unsigned long)cwq, |
497 | WORK_STRUCT_PENDING | extra_flags); | 496 | WORK_STRUCT_PENDING | WORK_STRUCT_CWQ | extra_flags); |
498 | } | 497 | } |
499 | 498 | ||
500 | static void set_work_cpu(struct work_struct *work, unsigned int cpu) | 499 | static void set_work_cpu(struct work_struct *work, unsigned int cpu) |
@@ -507,25 +506,24 @@ static void clear_work_data(struct work_struct *work) | |||
507 | set_work_data(work, WORK_STRUCT_NO_CPU, 0); | 506 | set_work_data(work, WORK_STRUCT_NO_CPU, 0); |
508 | } | 507 | } |
509 | 508 | ||
510 | static inline unsigned long get_work_data(struct work_struct *work) | ||
511 | { | ||
512 | return atomic_long_read(&work->data) & WORK_STRUCT_WQ_DATA_MASK; | ||
513 | } | ||
514 | |||
515 | static struct cpu_workqueue_struct *get_work_cwq(struct work_struct *work) | 509 | static struct cpu_workqueue_struct *get_work_cwq(struct work_struct *work) |
516 | { | 510 | { |
517 | unsigned long data = get_work_data(work); | 511 | unsigned long data = atomic_long_read(&work->data); |
518 | 512 | ||
519 | return data >= PAGE_OFFSET ? (void *)data : NULL; | 513 | if (data & WORK_STRUCT_CWQ) |
514 | return (void *)(data & WORK_STRUCT_WQ_DATA_MASK); | ||
515 | else | ||
516 | return NULL; | ||
520 | } | 517 | } |
521 | 518 | ||
522 | static struct global_cwq *get_work_gcwq(struct work_struct *work) | 519 | static struct global_cwq *get_work_gcwq(struct work_struct *work) |
523 | { | 520 | { |
524 | unsigned long data = get_work_data(work); | 521 | unsigned long data = atomic_long_read(&work->data); |
525 | unsigned int cpu; | 522 | unsigned int cpu; |
526 | 523 | ||
527 | if (data >= PAGE_OFFSET) | 524 | if (data & WORK_STRUCT_CWQ) |
528 | return ((struct cpu_workqueue_struct *)data)->gcwq; | 525 | return ((struct cpu_workqueue_struct *) |
526 | (data & WORK_STRUCT_WQ_DATA_MASK))->gcwq; | ||
529 | 527 | ||
530 | cpu = data >> WORK_STRUCT_FLAG_BITS; | 528 | cpu = data >> WORK_STRUCT_FLAG_BITS; |
531 | if (cpu == WORK_CPU_NONE) | 529 | if (cpu == WORK_CPU_NONE) |
@@ -3501,14 +3499,6 @@ void __init init_workqueues(void) | |||
3501 | unsigned int cpu; | 3499 | unsigned int cpu; |
3502 | int i; | 3500 | int i; |
3503 | 3501 | ||
3504 | /* | ||
3505 | * The pointer part of work->data is either pointing to the | ||
3506 | * cwq or contains the cpu number the work ran last on. Make | ||
3507 | * sure cpu number won't overflow into kernel pointer area so | ||
3508 | * that they can be distinguished. | ||
3509 | */ | ||
3510 | BUILD_BUG_ON(WORK_CPU_LAST << WORK_STRUCT_FLAG_BITS >= PAGE_OFFSET); | ||
3511 | |||
3512 | hotcpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE); | 3502 | hotcpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE); |
3513 | 3503 | ||
3514 | /* initialize gcwqs */ | 3504 | /* initialize gcwqs */ |