函数源码

Linux Kernel

v5.5.9

Brick Technologies Co., Ltd

Source File:kernel\padata.c Create Date:2022-07-27 15:08:58
首页 Copyright©Brick

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
static void padata_reorder(struct parallel_data *pd)
{
    struct padata_instance *pinst = pd->ps->pinst;
    int cb_cpu;
    struct padata_priv *padata;
    struct padata_serial_queue *squeue;
    struct padata_parallel_queue *next_queue;
 
    /*
     * We need to ensure that only one cpu can work on dequeueing of
     * the reorder queue the time. Calculating in which percpu reorder
     * queue the next object will arrive takes some time. A spinlock
     * would be highly contended. Also it is not clear in which order
     * the objects arrive to the reorder queues. So a cpu could wait to
     * get the lock just to notice that there is nothing to do at the
     * moment. Therefore we use a trylock and let the holder of the lock
     * care for all the objects enqueued during the holdtime of the lock.
     */
    if (!spin_trylock_bh(&pd->lock))
        return;
 
    while (1) {
        padata = padata_find_next(pd, true);
 
        /*
         * If the next object that needs serialization is parallel
         * processed by another cpu and is still on it's way to the
         * cpu's reorder queue, nothing to do for now.
         */
        if (!padata)
            break;
 
        cb_cpu = padata->cb_cpu;
        squeue = per_cpu_ptr(pd->squeue, cb_cpu);
 
        spin_lock(&squeue->serial.lock);
        list_add_tail(&padata->list, &squeue->serial.list);
        spin_unlock(&squeue->serial.lock);
 
        queue_work_on(cb_cpu, pinst->serial_wq, &squeue->work);
    }
 
    spin_unlock_bh(&pd->lock);
 
    /*
     * The next object that needs serialization might have arrived to
     * the reorder queues in the meantime.
     *
     * Ensure reorder queue is read after pd->lock is dropped so we see
     * new objects from another task in padata_do_serial.  Pairs with
     * smp_mb__after_atomic in padata_do_serial.
     */
    smp_mb();
 
    next_queue = per_cpu_ptr(pd->pqueue, pd->cpu);
    if (!list_empty(&next_queue->reorder.list) &&
        padata_find_next(pd, false))
        queue_work(pinst->serial_wq, &pd->reorder_work);
}