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 | 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 | − * whether a worker was woken up. | |
| 1265 | + * Like kick_pool() but, for a regular (non-BH) pool, returns the picked | |
| 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 | 1275 | struct worker *worker = first_idle_worker(pool); |
| 1270 | 1276 | struct task_struct *p; |
| 1271 | 1277 | |
| 1272 | 1278 | lockdep_assert_held(&pool->lock); |
| 1273 | 1279 | |
| 1280 | + *wakep = NULL; | |
| 1281 | + | |
| 1274 | 1282 | if (!need_more_worker(pool) || !worker) |
| 1275 | 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 | 1320 | #endif |
| 1313 | − wake_up_process(p); | |
| 1321 | + *wakep = p; | |
| 1314 | 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 | 1342 | #ifdef CONFIG_WQ_CPU_INTENSIVE_REPORT |
| 1318 | 1343 | |
| 1319 | 1344 | /* |