diff options
Diffstat (limited to 'kernel/timer.c')
| -rw-r--r-- | kernel/timer.c | 78 |
1 files changed, 19 insertions, 59 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index d0eed9b563c4..6bb47b0e4983 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -465,7 +465,14 @@ repeat: smp_wmb(); timer->base = NULL; spin_unlock_irq(&base->lock); - fn(data); + { + u32 preempt_count = preempt_count(); + fn(data); + if (preempt_count != preempt_count()) { + printk("huh, entered %p with %08x, exited with %08x?\n", fn, preempt_count, preempt_count()); + BUG(); + } + } spin_lock_irq(&base->lock); goto repeat; } @@ -554,7 +561,7 @@ unsigned long tick_nsec = TICK_NSEC; /* ACTHZ period (nsec) */ /* * The current time * wall_to_monotonic is what we need to add to xtime (or xtime corrected - * for sub jiffie times) to get to monotonic time. Monotonic is pegged at zero + * for sub jiffie times) to get to monotonic time. Monotonic is pegged * at zero at system boot time, so wall_to_monotonic will be negative, * however, we will ALWAYS keep the tv_nsec part positive so we can use * the usual normalization. @@ -799,59 +806,6 @@ static void update_wall_time(unsigned long ticks) } while (ticks); } -static inline void do_process_times(struct task_struct *p, - unsigned long user, unsigned long system) -{ - unsigned long psecs; - - psecs = (p->utime += user); - psecs += (p->stime += system); - if (p->signal && !unlikely(p->state & (EXIT_DEAD|EXIT_ZOMBIE)) && - psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_cur) { - /* Send SIGXCPU every second.. */ - if (!(psecs % HZ)) - send_sig(SIGXCPU, p, 1); - /* and SIGKILL when we go over max.. */ - if (psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_max) - send_sig(SIGKILL, p, 1); - } -} - -static inline void do_it_virt(struct task_struct * p, unsigned long ticks) -{ - unsigned long it_virt = p->it_virt_value; - - if (it_virt) { - it_virt -= ticks; - if (!it_virt) { - it_virt = p->it_virt_incr; - send_sig(SIGVTALRM, p, 1); - } - p->it_virt_value = it_virt; - } -} - -static inline void do_it_prof(struct task_struct *p) -{ - unsigned long it_prof = p->it_prof_value; - - if (it_prof) { - if (--it_prof == 0) { - it_prof = p->it_prof_incr; - send_sig(SIGPROF, p, 1); - } - p->it_prof_value = it_prof; - } -} - -static void update_one_process(struct task_struct *p, unsigned long user, - unsigned long system, int cpu) -{ - do_process_times(p, user, system); - do_it_virt(p, user); - do_it_prof(p); -} - /* * Called from the timer interrupt handler to charge one tick to the current * process. user_tick is 1 if the tick is user time, 0 for system. @@ -859,11 +813,17 @@ static void update_one_process(struct task_struct *p, unsigned long user, void update_process_times(int user_tick) { struct task_struct *p = current; - int cpu = smp_processor_id(), system = user_tick ^ 1; + int cpu = smp_processor_id(); - update_one_process(p, user_tick, system, cpu); + /* Note: this timer irq context must be accounted for as well. */ + if (user_tick) + account_user_time(p, jiffies_to_cputime(1)); + else + account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1)); run_local_timers(); - scheduler_tick(user_tick, system); + if (rcu_pending(cpu)) + rcu_check_callbacks(cpu, user_tick); + scheduler_tick(); } /* @@ -1438,7 +1398,7 @@ void __init init_timers(void) struct time_interpolator *time_interpolator; static struct time_interpolator *time_interpolator_list; -static spinlock_t time_interpolator_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(time_interpolator_lock); static inline u64 time_interpolator_get_cycles(unsigned int src) { |
