]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'timers/posixtimers' into timers/tracing
authorThomas Gleixner <tglx@linutronix.de>
Sat, 29 Aug 2009 08:34:18 +0000 (10:34 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Sat, 29 Aug 2009 08:34:29 +0000 (10:34 +0200)
Merge reason: timer tracepoint patches depend on both branches

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1  2 
arch/powerpc/kernel/time.c
kernel/fork.c
kernel/posix-cpu-timers.c

index a508388fb87c1993493b22df19b50deb41e9ab65,211d7b0cd370da5c66d1db3159ad5a91165e7c2b..5b1657540a7d22d3343830863ba635748684d5b7
@@@ -193,6 -193,8 +193,8 @@@ EXPORT_SYMBOL(__cputime_clockt_factor)
  DEFINE_PER_CPU(unsigned long, cputime_last_delta);
  DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
  
+ cputime_t cputime_one_jiffy;
  static void calc_cputime_factors(void)
  {
        struct div_result res;
@@@ -500,6 -502,7 +502,7 @@@ static int __init iSeries_tb_recal(void
                                tb_to_xs = divres.result_low;
                                vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
                                vdso_data->tb_to_xs = tb_to_xs;
+                               setup_cputime_one_jiffy();
                        }
                        else {
                                printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
@@@ -769,12 -772,11 +772,12 @@@ int update_persistent_clock(struct time
        return ppc_md.set_rtc_time(&tm);
  }
  
 -unsigned long read_persistent_clock(void)
 +void read_persistent_clock(struct timespec *ts)
  {
        struct rtc_time tm;
        static int first = 1;
  
 +      ts->tv_nsec = 0;
        /* XXX this is a litle fragile but will work okay in the short term */
        if (first) {
                first = 0;
                        timezone_offset = ppc_md.time_init();
  
                /* get_boot_time() isn't guaranteed to be safe to call late */
 -              if (ppc_md.get_boot_time)
 -                      return ppc_md.get_boot_time() -timezone_offset;
 +              if (ppc_md.get_boot_time) {
 +                      ts->tv_sec = ppc_md.get_boot_time() - timezone_offset;
 +                      return;
 +              }
 +      }
 +      if (!ppc_md.get_rtc_time) {
 +              ts->tv_sec = 0;
 +              return;
        }
 -      if (!ppc_md.get_rtc_time)
 -              return 0;
        ppc_md.get_rtc_time(&tm);
 -      return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
 -                    tm.tm_hour, tm.tm_min, tm.tm_sec);
 +      ts->tv_sec = mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
 +                          tm.tm_hour, tm.tm_min, tm.tm_sec);
  }
  
  /* clocksource code */
@@@ -950,6 -948,7 +953,7 @@@ void __init time_init(void
        tb_ticks_per_usec = ppc_tb_freq / 1000000;
        tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
        calc_cputime_factors();
+       setup_cputime_one_jiffy();
  
        /*
         * Calculate the length of each tick in ns.  It will not be
diff --combined kernel/fork.c
index 021e1138556e22ce7b35dbdd06267f67f0057a98,893ab0bf5e397f54fb6cd0e8a8952bd098545328..14cf79f1423739995f19dda0e483d9cc206f8549
@@@ -62,6 -62,7 +62,7 @@@
  #include <linux/fs_struct.h>
  #include <linux/magic.h>
  #include <linux/perf_counter.h>
+ #include <linux/posix-timers.h>
  
  #include <asm/pgtable.h>
  #include <asm/pgalloc.h>
@@@ -568,18 -569,18 +569,18 @@@ void mm_release(struct task_struct *tsk
         * the value intact in a core dump, and to save the unnecessary
         * trouble otherwise.  Userland only wants this done for a sys_exit.
         */
 -      if (tsk->clear_child_tid
 -          && !(tsk->flags & PF_SIGNALED)
 -          && atomic_read(&mm->mm_users) > 1) {
 -              u32 __user * tidptr = tsk->clear_child_tid;
 +      if (tsk->clear_child_tid) {
 +              if (!(tsk->flags & PF_SIGNALED) &&
 +                  atomic_read(&mm->mm_users) > 1) {
 +                      /*
 +                       * We don't check the error code - if userspace has
 +                       * not set up a proper pointer then tough luck.
 +                       */
 +                      put_user(0, tsk->clear_child_tid);
 +                      sys_futex(tsk->clear_child_tid, FUTEX_WAKE,
 +                                      1, NULL, NULL, 0);
 +              }
                tsk->clear_child_tid = NULL;
 -
 -              /*
 -               * We don't check the error code - if userspace has
 -               * not set up a proper pointer then tough luck.
 -               */
 -              put_user(0, tidptr);
 -              sys_futex(tidptr, FUTEX_WAKE, 1, NULL, NULL, 0);
        }
  }
  
@@@ -790,10 -791,10 +791,10 @@@ static void posix_cpu_timers_init_group
        thread_group_cputime_init(sig);
  
        /* Expiration times and increments. */
-       sig->it_virt_expires = cputime_zero;
-       sig->it_virt_incr = cputime_zero;
-       sig->it_prof_expires = cputime_zero;
-       sig->it_prof_incr = cputime_zero;
+       sig->it[CPUCLOCK_PROF].expires = cputime_zero;
+       sig->it[CPUCLOCK_PROF].incr = cputime_zero;
+       sig->it[CPUCLOCK_VIRT].expires = cputime_zero;
+       sig->it[CPUCLOCK_VIRT].incr = cputime_zero;
  
        /* Cached expiration times. */
        sig->cputime_expires.prof_exp = cputime_zero;
@@@ -1269,7 -1270,6 +1270,7 @@@ static struct task_struct *copy_process
        write_unlock_irq(&tasklist_lock);
        proc_fork_connector(p);
        cgroup_post_fork(p);
 +      perf_counter_fork(p);
        return p;
  
  bad_fork_free_pid:
@@@ -1411,6 -1411,9 +1412,6 @@@ long do_fork(unsigned long clone_flags
                        init_completion(&vfork);
                }
  
 -              if (!(clone_flags & CLONE_THREAD))
 -                      perf_counter_fork(p);
 -
                audit_finish_fork(p);
                tracehook_report_clone(regs, clone_flags, nr, p);
  
index e33a21cb9407987a0aa9b46c32baba590302862b,18bdde6f676fa80c9cf64c59ff2f055c7fc4534c..12161f74744e052b09e088c930ca8e5a1a43e397
   */
  void update_rlimit_cpu(unsigned long rlim_new)
  {
-       cputime_t cputime;
+       cputime_t cputime = secs_to_cputime(rlim_new);
+       struct signal_struct *const sig = current->signal;
  
-       cputime = secs_to_cputime(rlim_new);
-       if (cputime_eq(current->signal->it_prof_expires, cputime_zero) ||
-           cputime_gt(current->signal->it_prof_expires, cputime)) {
+       if (cputime_eq(sig->it[CPUCLOCK_PROF].expires, cputime_zero) ||
+           cputime_gt(sig->it[CPUCLOCK_PROF].expires, cputime)) {
                spin_lock_irq(&current->sighand->siglock);
                set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL);
                spin_unlock_irq(&current->sighand->siglock);
@@@ -521,12 -521,11 +521,12 @@@ void posix_cpu_timers_exit(struct task_
  }
  void posix_cpu_timers_exit_group(struct task_struct *tsk)
  {
 -      struct task_cputime cputime;
 +      struct signal_struct *const sig = tsk->signal;
  
 -      thread_group_cputimer(tsk, &cputime);
        cleanup_timers(tsk->signal->cpu_timers,
 -                     cputime.utime, cputime.stime, cputime.sum_exec_runtime);
 +                     cputime_add(tsk->utime, sig->utime),
 +                     cputime_add(tsk->stime, sig->stime),
 +                     tsk->se.sum_exec_runtime + sig->sum_sched_runtime);
  }
  
  static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
                                             now);
  }
  
+ static inline int expires_gt(cputime_t expires, cputime_t new_exp)
+ {
+       return cputime_eq(expires, cputime_zero) ||
+              cputime_gt(expires, new_exp);
+ }
+ static inline int expires_le(cputime_t expires, cputime_t new_exp)
+ {
+       return !cputime_eq(expires, cputime_zero) &&
+              cputime_le(expires, new_exp);
+ }
  /*
   * Insert the timer on the appropriate list before any timers that
   * expire later.  This must be called with the tasklist_lock held
@@@ -586,34 -596,32 +597,32 @@@ static void arm_timer(struct k_itimer *
                 */
  
                if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+                       union cpu_time_count *exp = &nt->expires;
                        switch (CPUCLOCK_WHICH(timer->it_clock)) {
                        default:
                                BUG();
                        case CPUCLOCK_PROF:
-                               if (cputime_eq(p->cputime_expires.prof_exp,
-                                              cputime_zero) ||
-                                   cputime_gt(p->cputime_expires.prof_exp,
-                                              nt->expires.cpu))
-                                       p->cputime_expires.prof_exp =
-                                               nt->expires.cpu;
+                               if (expires_gt(p->cputime_expires.prof_exp,
+                                              exp->cpu))
+                                       p->cputime_expires.prof_exp = exp->cpu;
                                break;
                        case CPUCLOCK_VIRT:
-                               if (cputime_eq(p->cputime_expires.virt_exp,
-                                              cputime_zero) ||
-                                   cputime_gt(p->cputime_expires.virt_exp,
-                                              nt->expires.cpu))
-                                       p->cputime_expires.virt_exp =
-                                               nt->expires.cpu;
+                               if (expires_gt(p->cputime_expires.virt_exp,
+                                              exp->cpu))
+                                       p->cputime_expires.virt_exp = exp->cpu;
                                break;
                        case CPUCLOCK_SCHED:
                                if (p->cputime_expires.sched_exp == 0 ||
-                                   p->cputime_expires.sched_exp >
-                                                       nt->expires.sched)
+                                   p->cputime_expires.sched_exp > exp->sched)
                                        p->cputime_expires.sched_exp =
-                                               nt->expires.sched;
+                                                               exp->sched;
                                break;
                        }
                } else {
+                       struct signal_struct *const sig = p->signal;
+                       union cpu_time_count *exp = &timer->it.cpu.expires;
                        /*
                         * For a process timer, set the cached expiration time.
                         */
                        default:
                                BUG();
                        case CPUCLOCK_VIRT:
-                               if (!cputime_eq(p->signal->it_virt_expires,
-                                               cputime_zero) &&
-                                   cputime_lt(p->signal->it_virt_expires,
-                                              timer->it.cpu.expires.cpu))
+                               if (expires_le(sig->it[CPUCLOCK_VIRT].expires,
+                                              exp->cpu))
                                        break;
-                               p->signal->cputime_expires.virt_exp =
-                                       timer->it.cpu.expires.cpu;
+                               sig->cputime_expires.virt_exp = exp->cpu;
                                break;
                        case CPUCLOCK_PROF:
-                               if (!cputime_eq(p->signal->it_prof_expires,
-                                               cputime_zero) &&
-                                   cputime_lt(p->signal->it_prof_expires,
-                                              timer->it.cpu.expires.cpu))
+                               if (expires_le(sig->it[CPUCLOCK_PROF].expires,
+                                              exp->cpu))
                                        break;
-                               i = p->signal->rlim[RLIMIT_CPU].rlim_cur;
+                               i = sig->rlim[RLIMIT_CPU].rlim_cur;
                                if (i != RLIM_INFINITY &&
-                                   i <= cputime_to_secs(timer->it.cpu.expires.cpu))
+                                   i <= cputime_to_secs(exp->cpu))
                                        break;
-                               p->signal->cputime_expires.prof_exp =
-                                       timer->it.cpu.expires.cpu;
+                               sig->cputime_expires.prof_exp = exp->cpu;
                                break;
                        case CPUCLOCK_SCHED:
-                               p->signal->cputime_expires.sched_exp =
-                                       timer->it.cpu.expires.sched;
+                               sig->cputime_expires.sched_exp = exp->sched;
                                break;
                        }
                }
@@@ -1071,6 -1072,36 +1073,36 @@@ static void stop_process_timers(struct 
        spin_unlock_irqrestore(&cputimer->lock, flags);
  }
  
+ static u32 onecputick;
+ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
+                            cputime_t *expires, cputime_t cur_time, int signo)
+ {
+       if (cputime_eq(it->expires, cputime_zero))
+               return;
+       if (cputime_ge(cur_time, it->expires)) {
+               if (!cputime_eq(it->incr, cputime_zero)) {
+                       it->expires = cputime_add(it->expires, it->incr);
+                       it->error += it->incr_error;
+                       if (it->error >= onecputick) {
+                               it->expires = cputime_sub(it->expires,
+                                                         cputime_one_jiffy);
+                               it->error -= onecputick;
+                       }
+               } else
+                       it->expires = cputime_zero;
+               __group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
+       }
+       if (!cputime_eq(it->expires, cputime_zero) &&
+           (cputime_eq(*expires, cputime_zero) ||
+            cputime_lt(it->expires, *expires))) {
+               *expires = it->expires;
+       }
+ }
  /*
   * Check for any per-thread CPU timers that have fired and move them
   * off the tsk->*_timers list onto the firing list.  Per-thread timers
@@@ -1090,10 -1121,10 +1122,10 @@@ static void check_process_timers(struc
         * Don't sample the current process CPU clocks if there are no timers.
         */
        if (list_empty(&timers[CPUCLOCK_PROF]) &&
-           cputime_eq(sig->it_prof_expires, cputime_zero) &&
+           cputime_eq(sig->it[CPUCLOCK_PROF].expires, cputime_zero) &&
            sig->rlim[RLIMIT_CPU].rlim_cur == RLIM_INFINITY &&
            list_empty(&timers[CPUCLOCK_VIRT]) &&
-           cputime_eq(sig->it_virt_expires, cputime_zero) &&
+           cputime_eq(sig->it[CPUCLOCK_VIRT].expires, cputime_zero) &&
            list_empty(&timers[CPUCLOCK_SCHED])) {
                stop_process_timers(tsk);
                return;
        /*
         * Check for the special case process timers.
         */
-       if (!cputime_eq(sig->it_prof_expires, cputime_zero)) {
-               if (cputime_ge(ptime, sig->it_prof_expires)) {
-                       /* ITIMER_PROF fires and reloads.  */
-                       sig->it_prof_expires = sig->it_prof_incr;
-                       if (!cputime_eq(sig->it_prof_expires, cputime_zero)) {
-                               sig->it_prof_expires = cputime_add(
-                                       sig->it_prof_expires, ptime);
-                       }
-                       __group_send_sig_info(SIGPROF, SEND_SIG_PRIV, tsk);
-               }
-               if (!cputime_eq(sig->it_prof_expires, cputime_zero) &&
-                   (cputime_eq(prof_expires, cputime_zero) ||
-                    cputime_lt(sig->it_prof_expires, prof_expires))) {
-                       prof_expires = sig->it_prof_expires;
-               }
-       }
-       if (!cputime_eq(sig->it_virt_expires, cputime_zero)) {
-               if (cputime_ge(utime, sig->it_virt_expires)) {
-                       /* ITIMER_VIRTUAL fires and reloads.  */
-                       sig->it_virt_expires = sig->it_virt_incr;
-                       if (!cputime_eq(sig->it_virt_expires, cputime_zero)) {
-                               sig->it_virt_expires = cputime_add(
-                                       sig->it_virt_expires, utime);
-                       }
-                       __group_send_sig_info(SIGVTALRM, SEND_SIG_PRIV, tsk);
-               }
-               if (!cputime_eq(sig->it_virt_expires, cputime_zero) &&
-                   (cputime_eq(virt_expires, cputime_zero) ||
-                    cputime_lt(sig->it_virt_expires, virt_expires))) {
-                       virt_expires = sig->it_virt_expires;
-               }
-       }
+       check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_expires, ptime,
+                        SIGPROF);
+       check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime,
+                        SIGVTALRM);
        if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
                unsigned long psecs = cputime_to_secs(ptime);
                cputime_t x;
@@@ -1457,7 -1461,7 +1462,7 @@@ void set_process_cpu_timer(struct task_
                if (!cputime_eq(*oldval, cputime_zero)) {
                        if (cputime_le(*oldval, now.cpu)) {
                                /* Just about to fire. */
-                               *oldval = jiffies_to_cputime(1);
+                               *oldval = cputime_one_jiffy;
                        } else {
                                *oldval = cputime_sub(*oldval, now.cpu);
                        }
@@@ -1703,10 -1707,15 +1708,15 @@@ static __init int init_posix_cpu_timers
                .nsleep = thread_cpu_nsleep,
                .nsleep_restart = thread_cpu_nsleep_restart,
        };
+       struct timespec ts;
  
        register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
        register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
  
+       cputime_to_timespec(cputime_one_jiffy, &ts);
+       onecputick = ts.tv_nsec;
+       WARN_ON(ts.tv_sec != 0);
        return 0;
  }
  __initcall(init_posix_cpu_timers);