diff options
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 36 | 
1 files changed, 23 insertions, 13 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 3825c14304e..d9a4aeb844d 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1057,6 +1057,25 @@ static void put_pwq(struct pool_workqueue *pwq)  	schedule_work(&pwq->unbound_release_work);  } +/** + * put_pwq_unlocked - put_pwq() with surrounding pool lock/unlock + * @pwq: pool_workqueue to put (can be %NULL) + * + * put_pwq() with locking.  This function also allows %NULL @pwq. + */ +static void put_pwq_unlocked(struct pool_workqueue *pwq) +{ +	if (pwq) { +		/* +		 * As both pwqs and pools are sched-RCU protected, the +		 * following lock operations are safe. +		 */ +		spin_lock_irq(&pwq->pool->lock); +		put_pwq(pwq); +		spin_unlock_irq(&pwq->pool->lock); +	} +} +  static void pwq_activate_delayed_work(struct work_struct *work)  {  	struct pool_workqueue *pwq = get_work_pwq(work); @@ -3759,12 +3778,7 @@ int apply_workqueue_attrs(struct workqueue_struct *wq,  	mutex_unlock(&wq->mutex); -	if (last_pwq) { -		spin_lock_irq(&last_pwq->pool->lock); -		put_pwq(last_pwq); -		spin_unlock_irq(&last_pwq->pool->lock); -	} - +	put_pwq_unlocked(last_pwq);  	ret = 0;  	/* fall through */  out_free: @@ -3979,16 +3993,12 @@ void destroy_workqueue(struct workqueue_struct *wq)  	} else {  		/*  		 * We're the sole accessor of @wq at this point.  Directly -		 * access the first pwq and put the base ref.  As both pwqs -		 * and pools are sched-RCU protected, the lock operations -		 * are safe.  @wq will be freed when the last pwq is -		 * released. +		 * access the first pwq and put the base ref.  @wq will be +		 * freed when the last pwq is released.  		 */  		pwq = list_first_entry(&wq->pwqs, struct pool_workqueue,  				       pwqs_node); -		spin_lock_irq(&pwq->pool->lock); -		put_pwq(pwq); -		spin_unlock_irq(&pwq->pool->lock); +		put_pwq_unlocked(pwq);  	}  }  EXPORT_SYMBOL_GPL(destroy_workqueue);  |