Linux wait返回及timer(6)

/*
    * Found a killable thread.  If the signal will be fatal,
    * then start taking the whole group down immediately.
    */
    if (sig_fatal(p, sig) &&
        !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
        !sigismember(&t->real_blocked, sig) &&
        (sig == SIGKILL || !t->ptrace)) {
        /*
        * This signal will be fatal to the whole group.
        */
        if (!sig_kernel_coredump(sig)) {
            /*
            * Start a group exit and wake everybody up.
            * This way we don't have other threads
            * running and doing things after a slower
            * thread has the fatal signal pending.
            */
            signal->flags = SIGNAL_GROUP_EXIT;
            signal->group_exit_code = sig;
            signal->group_stop_count = 0;
            t = p;
            do {
                task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
                sigaddset(&t->pending.signal, SIGKILL);
                signal_wake_up(t, 1);
            } while_each_thread(p, t);
            return;
        }
    }

/*
    * The signal is already in the shared-pending queue.
    * Tell the chosen thread to wake up and dequeue it.
    */
    signal_wake_up(t, sig == SIGKILL);
    return;
}

kernel\include\linux\Sched.h

static inline void signal_wake_up(struct task_struct *t, bool resume)
{
    signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0);
}
kernel\kernel\Signal.c
void signal_wake_up_state(struct task_struct *t, unsigned int state)
{
    set_tsk_thread_flag(t, TIF_SIGPENDING);
    /*
    * TASK_WAKEKILL also means wake it up in the stopped/traced/killable
    * case. We don't check t->state here because there is a race with it
    * executing another processor and just now entering stopped state.
    * By using wake_up_state, we ensure the process will wake up and
    * handle its death signal.
    */
    if (!wake_up_state(t, state | TASK_INTERRUPTIBLE))
        kick_process(t);
}

kernel\kernel\sched\Core.c

int wake_up_state(struct task_struct *p, unsigned int state)
{
    return try_to_wake_up(p, state, 0);
}
kernel\kernel\sched\Core.c
static int
try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
{
    unsigned long flags;
    int cpu, success = 0;

/*
    * If we are going to wake up a thread waiting for CONDITION we
    * need to ensure that CONDITION=1 done by the caller can not be
    * reordered with p->state check below. This pairs with mb() in
    * set_current_state() the waiting thread does.
    */
    smp_mb__before_spinlock();
    raw_spin_lock_irqsave(&p->pi_lock, flags);
    if (!(p->state & state))
        goto out;

success = 1; /* we're going to change ->state */
    cpu = task_cpu(p);

if (p->on_rq && ttwu_remote(p, wake_flags))
        goto stat;

#ifdef CONFIG_SMP
    /*
    * If the owning (remote) cpu is still in the middle of schedule() with
    * this task as prev, wait until its done referencing the task.
    */
    while (p->on_cpu)
        cpu_relax();
    /*
    * Pairs with the smp_wmb() in finish_lock_switch().
    */
    smp_rmb();

p->sched_contributes_to_load = !!task_contributes_to_load(p);
    p->state = TASK_WAKING;

if (p->sched_class->task_waking)
        p->sched_class->task_waking(p);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/baa9f29ea8eb34fc042dbed89dcbdd91.html