函数源码

Linux Kernel

v5.5.9

Brick Technologies Co., Ltd

Source File:kernel\workqueue.c Create Date:2022-07-27 10:27:11
首页 Copyright©Brick

2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
/**
 * insert_wq_barrier - insert a barrier work
 * @pwq: pwq to insert barrier into
 * @barr: wq_barrier to insert
 * @target: target work to attach @barr to
 * @worker: worker currently executing @target, NULL if @target is not executing
 *
 * @barr is linked to @target such that @barr is completed only after
 * @target finishes execution.  Please note that the ordering
 * guarantee is observed only with respect to @target and on the local
 * cpu.
 *
 * Currently, a queued barrier can't be canceled.  This is because
 * try_to_grab_pending() can't determine whether the work to be
 * grabbed is at the head of the queue and thus can't clear LINKED
 * flag of the previous work while there must be a valid next work
 * after a work with LINKED flag set.
 *
 * Note that when @worker is non-NULL, @target may be modified
 * underneath us, so we can't reliably determine pwq from @target.
 *
 * CONTEXT:
 * spin_lock_irq(pool->lock).
 */
static void insert_wq_barrier(struct pool_workqueue *pwq,
                  struct wq_barrier *barr,
                  struct work_struct *target, struct worker *worker)
{
    struct list_head *head;
    unsigned int linked = 0;
 
    /*
     * debugobject calls are safe here even with pool->lock locked
     * as we know for sure that this will not trigger any of the
     * checks and call back into the fixup functions where we
     * might deadlock.
     */
    INIT_WORK_ONSTACK(&barr->work, wq_barrier_func);
    __set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&barr->work));
 
    init_completion_map(&barr->done, &target->lockdep_map);
 
    barr->task = current;
 
    /*
     * If @target is currently being executed, schedule the
     * barrier to the worker; otherwise, put it after @target.
     */
    if (worker)
        head = worker->scheduled.next;
    else {
        unsigned long *bits = work_data_bits(target);
 
        head = target->entry.next;
        /* there can already be other linked works, inherit and set */
        linked = *bits & WORK_STRUCT_LINKED;
        __set_bit(WORK_STRUCT_LINKED_BIT, bits);
    }
 
    debug_work_activate(&barr->work);
    insert_work(pwq, &barr->work, head,
            work_color_to_flags(WORK_NO_COLOR) | linked);
}