void xntimer_adjust_all_aperiodic(xnsticks_t delta) { unsigned cpu, nr_cpus; xnqueue_t adjq; initq(&adjq); delta = xnarch_ns_to_tsc(delta); for (cpu = 0, nr_cpus = xnarch_num_online_cpus(); cpu < nr_cpus; cpu++) { xnsched_t *sched = xnpod_sched_slot(cpu); xntimerq_t *q = &sched->timerqueue; xnholder_t *adjholder; xntimerh_t *holder; xntimerq_it_t it; for (holder = xntimerq_it_begin(q, &it); holder; holder = xntimerq_it_next(q, &it, holder)) { xntimer_t *timer = aplink2timer(holder); if (testbits(timer->status, XNTIMER_REALTIME)) { inith(&timer->adjlink); appendq(&adjq, &timer->adjlink); } } while ((adjholder = getq(&adjq))) { xntimer_t *timer = adjlink2timer(adjholder); xntimer_dequeue_aperiodic(timer); xntimer_adjust_aperiodic(timer, delta); } if (sched != xnpod_current_sched()) xntimer_next_remote_shot(sched); else xntimer_next_local_shot(sched); } }
void xnclock_core_local_shot(struct xnsched *sched) { struct xntimerdata *tmd; struct xntimer *timer; xnsticks_t delay; xntimerq_it_t it; xntimerh_t *h; /* * Do not reprogram locally when inside the tick handler - * will be done on exit anyway. Also exit if there is no * pending timer. */ if (sched->status & XNINTCK) return; tmd = xnclock_this_timerdata(&nkclock); h = xntimerq_it_begin(&tmd->q, &it); if (h == NULL) return; /* * Here we try to defer the host tick heading the timer queue, * so that it does not preempt a real-time activity uselessly, * in two cases: * * 1) a rescheduling is pending for the current CPU. We may * assume that a real-time thread is about to resume, so we * want to move the host tick out of the way until the host * kernel resumes, unless there is no other outstanding * timers. * * 2) the current thread is running in primary mode, in which * case we may also defer the host tick until the host kernel * resumes. * * The host tick deferral is cleared whenever Xenomai is about * to yield control to the host kernel (see __xnsched_run()), * or a timer with an earlier timeout date is scheduled, * whichever comes first. */ sched->lflags &= ~XNHDEFER; timer = container_of(h, struct xntimer, aplink); if (unlikely(timer == &sched->htimer)) { if (xnsched_resched_p(sched) || !xnthread_test_state(sched->curr, XNROOT)) { h = xntimerq_it_next(&tmd->q, &it, h); if (h) { sched->lflags |= XNHDEFER; timer = container_of(h, struct xntimer, aplink); } } }
static inline int xntimer_heading_p(struct xntimer *timer) { struct xnsched *sched = timer->sched; xntimerq_it_t it; xntimerh_t *h; h = xntimerq_it_begin(&sched->timerqueue, &it); if (h == &timer->aplink) return 1; if (testbits(sched->status, XNHDEFER)) { h = xntimerq_it_next(&sched->timerqueue, &it, h); if (h == &timer->aplink) return 1; } return 0; }
void xntimer_next_local_shot(xnsched_t *sched) { struct xntimer *timer; xnsticks_t delay; xntimerq_it_t it; xntimerh_t *h; /* * Do not reprogram locally when inside the tick handler - * will be done on exit anyway. Also exit if there is no * pending timer. */ if (testbits(sched->status, XNINTCK)) return; h = xntimerq_it_begin(&sched->timerqueue, &it); if (h == NULL) return; /* * Here we try to defer the host tick heading the timer queue, * so that it does not preempt a real-time activity uselessly, * in two cases: * * 1) a rescheduling is pending for the current CPU. We may * assume that a real-time thread is about to resume, so we * want to move the host tick out of the way until the host * kernel resumes, unless there is no other outstanding * timers. * * 2) the current thread is running in primary mode, in which * case we may also defer the host tick until the host kernel * resumes. * * The host tick deferral is cleared whenever Xenomai is about * to yield control to the host kernel (see * __xnpod_schedule()), or a timer with an earlier timeout * date is scheduled, whichever comes first. */ __clrbits(sched->status, XNHDEFER); timer = aplink2timer(h); if (unlikely(timer == &sched->htimer)) { if (xnsched_self_resched_p(sched) || !xnthread_test_state(sched->curr, XNROOT)) { h = xntimerq_it_next(&sched->timerqueue, &it, h); if (h) { __setbits(sched->status, XNHDEFER); timer = aplink2timer(h); } } } delay = xntimerh_date(&timer->aplink) - (xnarch_get_cpu_tsc() + nklatency); if (delay < 0) delay = 0; else if (delay > ULONG_MAX) delay = ULONG_MAX; xnarch_trace_tick((unsigned)delay); xnarch_program_timer_shot(delay); }