Hi Philippe, trying to decouple the PREEMPT-RT gatekeeper wakeup path from XNATOMIC (to fix the remaining races there), I wondered why we need a waitqueue here at all.
What about an approach like below, i.e. waking up the gatekeeper directly via wake_up_process? That could even be called from interrupt context. We should be able to avoid missing a wakeup by setting the task state to INTERRUPTIBLE before signaling the semaphore. Am I missing something? Jan diff --git a/include/nucleus/sched.h b/include/nucleus/sched.h index e251329..df8853b 100644 --- a/include/nucleus/sched.h +++ b/include/nucleus/sched.h @@ -111,7 +111,6 @@ typedef struct xnsched { #ifdef CONFIG_XENO_OPT_PERVASIVE struct task_struct *gatekeeper; - wait_queue_head_t gkwaitq; struct semaphore gksync; struct xnthread *gktarget; #endif diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c index f6b1e16..238317a 100644 --- a/ksrc/nucleus/shadow.c +++ b/ksrc/nucleus/shadow.c @@ -92,7 +92,6 @@ static struct __lostagerq { #define LO_SIGGRP_REQ 2 #define LO_SIGTHR_REQ 3 #define LO_UNMAP_REQ 4 -#define LO_GKWAKE_REQ 5 int type; struct task_struct *task; int arg; @@ -759,9 +758,6 @@ static void lostage_handler(void *cookie) int cpu, reqnum, type, arg, sig, sigarg; struct __lostagerq *rq; struct task_struct *p; -#ifdef CONFIG_PREEMPT_RT - struct xnsched *sched; -#endif cpu = smp_processor_id(); rq = &lostagerq[cpu]; @@ -819,13 +815,6 @@ static void lostage_handler(void *cookie) case LO_SIGGRP_REQ: kill_proc(p->pid, arg, 1); break; - -#ifdef CONFIG_PREEMPT_RT - case LO_GKWAKE_REQ: - sched = xnpod_sched_slot(cpu); - wake_up_interruptible_sync(&sched->gkwaitq); - break; -#endif } } } @@ -873,7 +862,6 @@ static inline int normalize_priority(int prio) static int gatekeeper_thread(void *data) { struct task_struct *this_task = current; - DECLARE_WAITQUEUE(wait, this_task); int cpu = (long)data; struct xnsched *sched = xnpod_sched_slot(cpu); struct xnthread *target; @@ -886,12 +874,10 @@ static int gatekeeper_thread(void *data) set_cpus_allowed(this_task, cpumask); set_linux_task_priority(this_task, MAX_RT_PRIO - 1); - init_waitqueue_head(&sched->gkwaitq); - add_wait_queue_exclusive(&sched->gkwaitq, &wait); + set_current_state(TASK_INTERRUPTIBLE); up(&sched->gksync); /* Sync with xnshadow_mount(). */ for (;;) { - set_current_state(TASK_INTERRUPTIBLE); up(&sched->gksync); /* Make the request token available. */ schedule(); @@ -937,6 +923,7 @@ static int gatekeeper_thread(void *data) xnlock_put_irqrestore(&nklock, s); xnpod_schedule(); } + set_current_state(TASK_INTERRUPTIBLE); } return 0; @@ -1014,23 +1001,9 @@ redo: thread->gksched = sched; xnthread_set_info(thread, XNATOMIC); set_current_state(TASK_INTERRUPTIBLE | TASK_ATOMICSWITCH); -#ifndef CONFIG_PREEMPT_RT - /* - * We may not hold the preemption lock across calls to - * wake_up_*() services over fully preemptible kernels, since - * tasks might sleep when contending for spinlocks. The wake - * up call for the gatekeeper will happen later, over an APC - * we kick in do_schedule_event() on the way out for the - * hardening task. - * - * We could delay the wake up call over non-RT 2.6 kernels as - * well, but not when running over 2.4 (scheduler innards - * would not allow this, causing weirdnesses when hardening - * tasks). So we always do the early wake up when running - * non-RT, which includes 2.4. - */ - wake_up_interruptible_sync(&sched->gkwaitq); -#endif + + wake_up_process(sched->gatekeeper); + schedule(); /* -- Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux _______________________________________________ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core