diff options
Diffstat (limited to 'kernel/posix-cpu-timers.c')
-rw-r--r-- | kernel/posix-cpu-timers.c | 198 |
1 files changed, 6 insertions, 192 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 4bf82f8..c7f31aa 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -3,7 +3,6 @@ */ #include <linux/sched.h> -#include <linux/sched/rt.h> #include <linux/posix-timers.h> #include <linux/errno.h> #include <linux/math64.h> @@ -664,7 +663,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, /* * Disarm any old timer after extracting its expiry time. */ - BUG_ON_NONRT(!irqs_disabled()); + BUG_ON(!irqs_disabled()); ret = 0; old_incr = timer->it.cpu.incr; @@ -1111,7 +1110,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) /* * Now re-arm for the new expiry time. */ - BUG_ON_NONRT(!irqs_disabled()); + BUG_ON(!irqs_disabled()); arm_timer(timer); spin_unlock(&p->sighand->siglock); @@ -1178,11 +1177,10 @@ static inline int fastpath_timer_check(struct task_struct *tsk) sig = tsk->signal; if (sig->cputimer.running) { struct task_cputime group_sample; - unsigned long flags; - raw_spin_lock_irqsave(&sig->cputimer.lock, flags); + raw_spin_lock(&sig->cputimer.lock); group_sample = sig->cputimer.cputime; - raw_spin_unlock_irqrestore(&sig->cputimer.lock, flags); + raw_spin_unlock(&sig->cputimer.lock); if (task_cputime_expired(&group_sample, &sig->cputime_expires)) return 1; @@ -1196,13 +1194,13 @@ static inline int fastpath_timer_check(struct task_struct *tsk) * already updated our counts. We need to check if any timers fire now. * Interrupts are disabled. */ -static void __run_posix_cpu_timers(struct task_struct *tsk) +void run_posix_cpu_timers(struct task_struct *tsk) { LIST_HEAD(firing); struct k_itimer *timer, *next; unsigned long flags; - BUG_ON_NONRT(!irqs_disabled()); + BUG_ON(!irqs_disabled()); /* * The fast path checks that there are no expired thread or thread @@ -1267,190 +1265,6 @@ static void __run_posix_cpu_timers(struct task_struct *tsk) posix_cpu_timer_kick_nohz(); } -#ifdef CONFIG_PREEMPT_RT_BASE -#include <linux/kthread.h> -#include <linux/cpu.h> -DEFINE_PER_CPU(struct task_struct *, posix_timer_task); -DEFINE_PER_CPU(struct task_struct *, posix_timer_tasklist); - -static int posix_cpu_timers_thread(void *data) -{ - int cpu = (long)data; - - BUG_ON(per_cpu(posix_timer_task,cpu) != current); - - while (!kthread_should_stop()) { - struct task_struct *tsk = NULL; - struct task_struct *next = NULL; - - if (cpu_is_offline(cpu)) - goto wait_to_die; - - /* grab task list */ - raw_local_irq_disable(); - tsk = per_cpu(posix_timer_tasklist, cpu); - per_cpu(posix_timer_tasklist, cpu) = NULL; - raw_local_irq_enable(); - - /* its possible the list is empty, just return */ - if (!tsk) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - __set_current_state(TASK_RUNNING); - continue; - } - - /* Process task list */ - while (1) { - /* save next */ - next = tsk->posix_timer_list; - - /* run the task timers, clear its ptr and - * unreference it - */ - __run_posix_cpu_timers(tsk); - tsk->posix_timer_list = NULL; - put_task_struct(tsk); - - /* check if this is the last on the list */ - if (next == tsk) - break; - tsk = next; - } - } - return 0; - -wait_to_die: - /* Wait for kthread_stop */ - set_current_state(TASK_INTERRUPTIBLE); - while (!kthread_should_stop()) { - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } - __set_current_state(TASK_RUNNING); - return 0; -} - -static inline int __fastpath_timer_check(struct task_struct *tsk) -{ - /* tsk == current, ensure it is safe to use ->signal/sighand */ - if (unlikely(tsk->exit_state)) - return 0; - - if (!task_cputime_zero(&tsk->cputime_expires)) - return 1; - - if (!task_cputime_zero(&tsk->signal->cputime_expires)) - return 1; - - return 0; -} - -void run_posix_cpu_timers(struct task_struct *tsk) -{ - unsigned long cpu = smp_processor_id(); - struct task_struct *tasklist; - - BUG_ON(!irqs_disabled()); - if(!per_cpu(posix_timer_task, cpu)) - return; - /* get per-cpu references */ - tasklist = per_cpu(posix_timer_tasklist, cpu); - - /* check to see if we're already queued */ - if (!tsk->posix_timer_list && __fastpath_timer_check(tsk)) { - get_task_struct(tsk); - if (tasklist) { - tsk->posix_timer_list = tasklist; - } else { - /* - * The list is terminated by a self-pointing - * task_struct - */ - tsk->posix_timer_list = tsk; - } - per_cpu(posix_timer_tasklist, cpu) = tsk; - - wake_up_process(per_cpu(posix_timer_task, cpu)); - } -} - -/* - * posix_cpu_thread_call - callback that gets triggered when a CPU is added. - * Here we can start up the necessary migration thread for the new CPU. - */ -static int posix_cpu_thread_call(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - int cpu = (long)hcpu; - struct task_struct *p; - struct sched_param param; - - switch (action) { - case CPU_UP_PREPARE: - p = kthread_create(posix_cpu_timers_thread, hcpu, - "posixcputmr/%d",cpu); - if (IS_ERR(p)) - return NOTIFY_BAD; - p->flags |= PF_NOFREEZE; - kthread_bind(p, cpu); - /* Must be high prio to avoid getting starved */ - param.sched_priority = MAX_RT_PRIO-1; - sched_setscheduler(p, SCHED_FIFO, ¶m); - per_cpu(posix_timer_task,cpu) = p; - break; - case CPU_ONLINE: - /* Strictly unneccessary, as first user will wake it. */ - wake_up_process(per_cpu(posix_timer_task,cpu)); - break; -#ifdef CONFIG_HOTPLUG_CPU - case CPU_UP_CANCELED: - /* Unbind it from offline cpu so it can run. Fall thru. */ - kthread_bind(per_cpu(posix_timer_task, cpu), - cpumask_any(cpu_online_mask)); - kthread_stop(per_cpu(posix_timer_task,cpu)); - per_cpu(posix_timer_task,cpu) = NULL; - break; - case CPU_DEAD: - kthread_stop(per_cpu(posix_timer_task,cpu)); - per_cpu(posix_timer_task,cpu) = NULL; - break; -#endif - } - return NOTIFY_OK; -} - -/* Register at highest priority so that task migration (migrate_all_tasks) - * happens before everything else. - */ -static struct notifier_block posix_cpu_thread_notifier = { - .notifier_call = posix_cpu_thread_call, - .priority = 10 -}; - -static int __init posix_cpu_thread_init(void) -{ - void *hcpu = (void *)(long)smp_processor_id(); - /* Start one for boot CPU. */ - unsigned long cpu; - - /* init the per-cpu posix_timer_tasklets */ - for_each_possible_cpu(cpu) - per_cpu(posix_timer_tasklist, cpu) = NULL; - - posix_cpu_thread_call(&posix_cpu_thread_notifier, CPU_UP_PREPARE, hcpu); - posix_cpu_thread_call(&posix_cpu_thread_notifier, CPU_ONLINE, hcpu); - register_cpu_notifier(&posix_cpu_thread_notifier); - return 0; -} -early_initcall(posix_cpu_thread_init); -#else /* CONFIG_PREEMPT_RT_BASE */ -void run_posix_cpu_timers(struct task_struct *tsk) -{ - __run_posix_cpu_timers(tsk); -} -#endif /* CONFIG_PREEMPT_RT_BASE */ - /* * Set one of the process-wide special case CPU timers or RLIMIT_CPU. * The tsk->sighand->siglock must be held by the caller. |