Factor the worker selection out of kick_pool() into kick_pool_pick(), which picks and claims the worker under pool->lock but, instead of waking it, returns the worker's task via an out-param so the caller can issue the wakeup after dropping pool->lock. BH kicks and wake_cpu setup still happen under the lock. kick_pool() becomes a thin wrapper that wakes the returned task, so all existing callers keep waking under pool->lock. Pure refactor, no functional change.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -1258,19 +1258,27 @@ static void kick_bh_pool(struct worker_pool *pool) · 1257 unmodified lines | |||
| 1258 | } | 1258 | } |
| 1259 | 1259 | ||
| 1260 | /** | 1260 | /** |
| 1261 | * kick_pool - wake up an idle worker if necessary | 1261 | * kick_pool_pick - select an idle worker to kick, deferring the wakeup |
| 1262 | * @pool: pool to kick | 1262 | * @pool: pool to kick |
| 1263 | * @wakep: out-param, set to the task to wake after pool->lock is dropped | ||
| 1263 | * | 1264 | * |
| 1264 | * @pool may have pending work items. Wake up worker if necessary. Returns | 1265 | * Like kick_pool() but, for a regular (non-BH) pool, returns the picked |
| 1265 | * whether a worker was woken up. | 1266 | * worker's task via @wakep instead of waking it, so the caller can issue the |
| 1267 | * wakeup after dropping pool->lock (the wakeup takes rq->lock). Worker | ||
| 1268 | * selection, wake_cpu setup and the BH kick still happen under the lock. | ||
| 1269 | * Returns whether a worker was selected or kicked. | ||
| 1270 | * | ||
| 1271 | * Must be called with @pool->lock held. | ||
| 1266 | */ | 1272 | */ |
| 1267 | static bool kick_pool(struct worker_pool *pool) | 1273 | static bool kick_pool_pick(struct worker_pool *pool, struct task_struct **wakep) |
| 1268 | { | 1274 | { |
| 1269 | struct worker *worker = first_idle_worker(pool); | 1275 | struct worker *worker = first_idle_worker(pool); |
| 1270 | struct task_struct *p; | 1276 | struct task_struct *p; |
| 1271 | 1277 | ||
| 1272 | lockdep_assert_held(&pool->lock); | 1278 | lockdep_assert_held(&pool->lock); |
| 1273 | 1279 | ||
| 1280 | *wakep = NULL; | ||
| 1281 | |||
| 1274 | if (!need_more_worker(pool) || !worker) | 1282 | if (!need_more_worker(pool) || !worker) |
| 1275 | return false; | 1283 | return false; |
| 1276 | 1284 | ||
| @@ -1310,10 +1318,27 @@ static bool kick_pool(struct worker_pool *pool) · 33 unmodified lines | |||
| 1310 | } | 1318 | } |
| 1311 | } | 1319 | } |
| 1312 | #endif | 1320 | #endif |
| 1313 | wake_up_process(p); | 1321 | *wakep = p; |
| 1314 | return true; | 1322 | return true; |
| 1315 | } | 1323 | } |
| 1316 | 1324 | ||
| 1325 | /** | ||
| 1326 | * kick_pool - wake up an idle worker if necessary | ||
| 1327 | * @pool: pool to kick | ||
| 1328 | * | ||
| 1329 | * @pool may have pending work items. Wake up worker if necessary. Returns | ||
| 1330 | * whether a worker was woken up. | ||
| 1331 | */ | ||
| 1332 | static bool kick_pool(struct worker_pool *pool) | ||
| 1333 | { | ||
| 1334 | struct task_struct *p; | ||
| 1335 | bool kicked = kick_pool_pick(pool, &p); | ||
| 1336 | |||
| 1337 | if (p) | ||
| 1338 | wake_up_process(p); | ||
| 1339 | return kicked; | ||
| 1340 | } | ||
| 1341 | |||
| 1317 | #ifdef CONFIG_WQ_CPU_INTENSIVE_REPORT | 1342 | #ifdef CONFIG_WQ_CPU_INTENSIVE_REPORT |
| 1318 | 1343 | ||
| 1319 | /* | 1344 | /* |