Pull workqueue updates from Tejun Heo: "rcu_work addition and a couple trivial changes" * 'for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq: workqueue: remove the comment about the old manager_arb mutex workqueue: fix the comments of nr_idle fs/aio: Use rcu_work instead of explicit rcu and work item cgroup: Use rcu_work instead of explicit rcu and work item RCU, workqueue: Implement rcu_work
Showing the changes to kernel/workqueue.c (1 of 5 files). Show all
Unified · Split
| @@ -153,10 +153,9 @@ struct worker_pool { · 152 unmodified lines | |||
| 153 | unsigned long watchdog_ts; /* L: watchdog timestamp */ | 153 | unsigned long watchdog_ts; /* L: watchdog timestamp */ |
| 154 | 154 | ||
| 155 | struct list_head worklist; /* L: list of pending works */ | 155 | struct list_head worklist; /* L: list of pending works */ |
| 156 | int nr_workers; /* L: total number of workers */ | ||
| 157 | 156 | ||
| 158 | /* nr_idle includes the ones off idle_list for rebinding */ | 157 | int nr_workers; /* L: total number of workers */ |
| 159 | int nr_idle; /* L: currently idle ones */ | 158 | int nr_idle; /* L: currently idle workers */ |
| 160 | 159 | ||
| 161 | struct list_head idle_list; /* X: list of idle workers */ | 160 | struct list_head idle_list; /* X: list of idle workers */ |
| 162 | struct timer_list idle_timer; /* L: worker idle timeout */ | 161 | struct timer_list idle_timer; /* L: worker idle timeout */ |
| @@ -166,7 +165,6 @@ struct worker_pool { · 3 unmodified lines | |||
| 166 | DECLARE_HASHTABLE(busy_hash, BUSY_WORKER_HASH_ORDER); | 165 | DECLARE_HASHTABLE(busy_hash, BUSY_WORKER_HASH_ORDER); |
| 167 | /* L: hash of busy workers */ | 166 | /* L: hash of busy workers */ |
| 168 | 167 | ||
| 169 | /* see manage_workers() for details on the two manager mutexes */ | ||
| 170 | struct worker *manager; /* L: purely informational */ | 168 | struct worker *manager; /* L: purely informational */ |
| 171 | struct mutex attach_mutex; /* attach/detach exclusion */ | 169 | struct mutex attach_mutex; /* attach/detach exclusion */ |
| 172 | struct list_head workers; /* A: attached workers */ | 170 | struct list_head workers; /* A: attached workers */ |
| @@ -1604,6 +1602,40 @@ bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq, · 1431 unmodified lines | |||
| 1604 | } | 1602 | } |
| 1605 | EXPORT_SYMBOL_GPL(mod_delayed_work_on); | 1603 | EXPORT_SYMBOL_GPL(mod_delayed_work_on); |
| 1606 | 1604 | ||
| 1605 | static void rcu_work_rcufn(struct rcu_head *rcu) | ||
| 1606 | { | ||
| 1607 | struct rcu_work *rwork = container_of(rcu, struct rcu_work, rcu); | ||
| 1608 | |||
| 1609 | /* read the comment in __queue_work() */ | ||
| 1610 | local_irq_disable(); | ||
| 1611 | __queue_work(WORK_CPU_UNBOUND, rwork->wq, &rwork->work); | ||
| 1612 | local_irq_enable(); | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | /** | ||
| 1616 | * queue_rcu_work - queue work after a RCU grace period | ||
| 1617 | * @wq: workqueue to use | ||
| 1618 | * @rwork: work to queue | ||
| 1619 | * | ||
| 1620 | * Return: %false if @rwork was already pending, %true otherwise. Note | ||
| 1621 | * that a full RCU grace period is guaranteed only after a %true return. | ||
| 1622 | * While @rwork is guarnateed to be executed after a %false return, the | ||
| 1623 | * execution may happen before a full RCU grace period has passed. | ||
| 1624 | */ | ||
| 1625 | bool queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *rwork) | ||
| 1626 | { | ||
| 1627 | struct work_struct *work = &rwork->work; | ||
| 1628 | |||
| 1629 | if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) { | ||
| 1630 | rwork->wq = wq; | ||
| 1631 | call_rcu(&rwork->rcu, rcu_work_rcufn); | ||
| 1632 | return true; | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | return false; | ||
| 1636 | } | ||
| 1637 | EXPORT_SYMBOL(queue_rcu_work); | ||
| 1638 | |||
| 1607 | /** | 1639 | /** |
| 1608 | * worker_enter_idle - enter idle state | 1640 | * worker_enter_idle - enter idle state |
| 1609 | * @worker: worker which is entering idle state | 1641 | * @worker: worker which is entering idle state |
| @@ -3001,6 +3033,26 @@ bool flush_delayed_work(struct delayed_work *dwork) · 1391 unmodified lines | |||
| 3001 | } | 3033 | } |
| 3002 | EXPORT_SYMBOL(flush_delayed_work); | 3034 | EXPORT_SYMBOL(flush_delayed_work); |
| 3003 | 3035 | ||
| 3036 | /** | ||
| 3037 | * flush_rcu_work - wait for a rwork to finish executing the last queueing | ||
| 3038 | * @rwork: the rcu work to flush | ||
| 3039 | * | ||
| 3040 | * Return: | ||
| 3041 | * %true if flush_rcu_work() waited for the work to finish execution, | ||
| 3042 | * %false if it was already idle. | ||
| 3043 | */ | ||
| 3044 | bool flush_rcu_work(struct rcu_work *rwork) | ||
| 3045 | { | ||
| 3046 | if (test_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&rwork->work))) { | ||
| 3047 | rcu_barrier(); | ||
| 3048 | flush_work(&rwork->work); | ||
| 3049 | return true; | ||
| 3050 | } else { | ||
| 3051 | return flush_work(&rwork->work); | ||
| 3052 | } | ||
| 3053 | } | ||
| 3054 | EXPORT_SYMBOL(flush_rcu_work); | ||
| 3055 | |||
| 3004 | static bool __cancel_work(struct work_struct *work, bool is_dwork) | 3056 | static bool __cancel_work(struct work_struct *work, bool is_dwork) |
| 3005 | { | 3057 | { |
| 3006 | unsigned long flags; | 3058 | unsigned long flags; |