Commit f9fc1633 authored by Linus Torvalds's avatar Linus Torvalds

Make in-kernel HZ be 1000 on x86, retaining user-level 100 HZ clock_t.

Stop using "struct tms" internally - always use timer ticks (or one of
the sane timeval/timespec types) instead.

Explicitly convert to clock_t when copying to user space for the old
broken interfaces that still use "clock_t".

Clean up and unify jiffies<->timeval conversion.
parent e48f3a58
......@@ -1124,14 +1124,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid;
psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp;
psinfo.pr_sid = prstatus.pr_sid = current->session;
prstatus.pr_utime.tv_sec = CT_TO_SECS(current->times.tms_utime);
prstatus.pr_utime.tv_usec = CT_TO_USECS(current->times.tms_utime);
prstatus.pr_stime.tv_sec = CT_TO_SECS(current->times.tms_stime);
prstatus.pr_stime.tv_usec = CT_TO_USECS(current->times.tms_stime);
prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->times.tms_cutime);
prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->times.tms_cutime);
prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->times.tms_cstime);
prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->times.tms_cstime);
jiffies_to_timeval(current->utime, &prstatus.pr_utime);
jiffies_to_timeval(current->stime, &prstatus.pr_stime);
jiffies_to_timeval(current->cutime, &prstatus.pr_cutime);
jiffies_to_timeval(current->cstime, &prstatus.pr_cstime);
#ifdef DEBUG
dump_regs("Passed in regs", (elf_greg_t *)regs);
......
......@@ -71,6 +71,7 @@
#include <linux/signal.h>
#include <linux/highmem.h>
#include <linux/file.h>
#include <linux/times.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
......@@ -360,10 +361,10 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
task->cmin_flt,
task->maj_flt,
task->cmaj_flt,
task->times.tms_utime,
task->times.tms_stime,
task->times.tms_cutime,
task->times.tms_cstime,
jiffies_to_clock_t(task->utime),
jiffies_to_clock_t(task->stime),
jiffies_to_clock_t(task->cutime),
jiffies_to_clock_t(task->cstime),
priority,
nice,
0UL /* removed */,
......@@ -692,8 +693,8 @@ int proc_pid_cpu(struct task_struct *task, char * buffer)
len = sprintf(buffer,
"cpu %lu %lu\n",
task->times.tms_utime,
task->times.tms_stime);
task->utime,
task->stime);
for (i = 0 ; i < NR_CPUS; i++) {
if (cpu_online(i))
......
......@@ -98,7 +98,7 @@ static int uptime_read_proc(char *page, char **start, off_t off,
int len;
uptime = jiffies;
idle = init_task.times.tms_utime + init_task.times.tms_stime;
idle = init_task.utime + init_task.stime;
/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
that would overflow about every five days at HZ == 100.
......
#ifndef _ASMi386_PARAM_H
#define _ASMi386_PARAM_H
#ifdef __KERNEL__
# define HZ 1000 /* Internal kernel timer frequency */
# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#endif
#ifndef HZ
#define HZ 100
#endif
......@@ -17,8 +23,4 @@
#define MAXHOSTNAMELEN 64 /* max length of hostname */
#ifdef __KERNEL__
# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */
#endif
#endif
......@@ -10,7 +10,6 @@ extern unsigned long event;
#include <linux/threads.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/times.h>
#include <linux/timex.h>
#include <linux/jiffies.h>
#include <linux/rbtree.h>
......@@ -310,7 +309,7 @@ struct task_struct {
unsigned long it_real_value, it_prof_value, it_virt_value;
unsigned long it_real_incr, it_prof_incr, it_virt_incr;
struct timer_list real_timer;
struct tms times;
unsigned long utime, stime, cutime, cstime;
unsigned long start_time;
long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
......
......@@ -12,6 +12,16 @@ struct timespec {
};
#endif /* _STRUCT_TIMESPEC */
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of dst correction */
};
#ifdef __KERNEL__
/*
......@@ -48,6 +58,27 @@ jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
value->tv_sec = jiffies / HZ;
}
/* Same for "timeval" */
static __inline__ unsigned long
timeval_to_jiffies(struct timeval *value)
{
unsigned long sec = value->tv_sec;
long usec = value->tv_usec;
if (sec >= (MAX_JIFFY_OFFSET / HZ))
return MAX_JIFFY_OFFSET;
usec += 1000000L / HZ - 1;
usec /= 1000000L / HZ;
return HZ * sec + usec;
}
static __inline__ void
jiffies_to_timeval(unsigned long jiffies, struct timeval *value)
{
value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
value->tv_sec = jiffies / HZ;
}
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
......@@ -88,17 +119,6 @@ extern struct timeval xtime;
#endif /* __KERNEL__ */
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of dst correction */
};
#define NFDBITS __NFDBITS
#ifdef __KERNEL__
......
#ifndef _LINUX_TIMES_H
#define _LINUX_TIMES_H
#ifdef __KERNEL__
# define jiffies_to_clock_t(x) ((x) / (HZ / USER_HZ))
#endif
struct tms {
clock_t tms_utime;
clock_t tms_stime;
......
......@@ -319,8 +319,8 @@ static void do_acct_process(long exitcode, struct file *file)
ac.ac_btime = CT_TO_SECS(current->start_time) +
(xtime.tv_sec - (jiffies / HZ));
ac.ac_etime = encode_comp_t(jiffies - current->start_time);
ac.ac_utime = encode_comp_t(current->times.tms_utime);
ac.ac_stime = encode_comp_t(current->times.tms_stime);
ac.ac_utime = encode_comp_t(current->utime);
ac.ac_stime = encode_comp_t(current->stime);
ac.ac_uid = current->uid;
ac.ac_gid = current->gid;
ac.ac_tty = (current->tty) ? kdev_t_to_nr(current->tty->device) : 0;
......
......@@ -648,8 +648,8 @@ asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struc
}
goto end_wait4;
case TASK_ZOMBIE:
current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime;
current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime;
current->cutime += p->utime + p->cutime;
current->cstime += p->stime + p->cstime;
read_unlock(&tasklist_lock);
retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
if (!retval && stat_addr)
......
......@@ -686,8 +686,8 @@ struct task_struct *do_fork(unsigned long clone_flags,
p->leader = 0; /* session leadership doesn't inherit */
p->tty_old_pgrp = 0;
p->times.tms_utime = p->times.tms_stime = 0;
p->times.tms_cutime = p->times.tms_cstime = 0;
p->utime = p->stime = 0;
p->cutime = p->cstime = 0;
#ifdef CONFIG_SMP
{
int i;
......
......@@ -12,34 +12,6 @@
#include <asm/uaccess.h>
/*
* change timeval to jiffies, trying to avoid the
* most obvious overflows..
*
* The tv_*sec values are signed, but nothing seems to
* indicate whether we really should use them as signed values
* when doing itimers. POSIX doesn't mention this (but if
* alarm() uses itimers without checking, we have to use unsigned
* arithmetic).
*/
static unsigned long tvtojiffies(struct timeval *value)
{
unsigned long sec = (unsigned) value->tv_sec;
unsigned long usec = (unsigned) value->tv_usec;
if (sec > (ULONG_MAX / HZ))
return ULONG_MAX;
usec += 1000000 / HZ - 1;
usec /= 1000000 / HZ;
return HZ*sec+usec;
}
static void jiffiestotv(unsigned long jiffies, struct timeval *value)
{
value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
value->tv_sec = jiffies / HZ;
}
int do_getitimer(int which, struct itimerval *value)
{
register unsigned long val, interval;
......@@ -70,8 +42,8 @@ int do_getitimer(int which, struct itimerval *value)
default:
return(-EINVAL);
}
jiffiestotv(val, &value->it_value);
jiffiestotv(interval, &value->it_interval);
jiffies_to_timeval(val, &value->it_value);
jiffies_to_timeval(interval, &value->it_interval);
return 0;
}
......@@ -110,8 +82,8 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
register unsigned long i, j;
int k;
i = tvtojiffies(&value->it_interval);
j = tvtojiffies(&value->it_value);
i = timeval_to_jiffies(&value->it_interval);
j = timeval_to_jiffies(&value->it_value);
if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
return k;
switch (which) {
......
......@@ -779,8 +779,8 @@ void do_notify_parent(struct task_struct *tsk, int sig)
info.si_uid = tsk->uid;
/* FIXME: find out whether or not this is supposed to be c*time. */
info.si_utime = tsk->times.tms_utime;
info.si_stime = tsk->times.tms_stime;
info.si_utime = tsk->utime;
info.si_stime = tsk->stime;
status = tsk->exit_code & 0x7f;
why = SI_KERNEL; /* shouldn't happen */
......
......@@ -18,6 +18,7 @@
#include <linux/fs.h>
#include <linux/tqueue.h>
#include <linux/device.h>
#include <linux/times.h>
#include <asm/uaccess.h>
#include <asm/io.h>
......@@ -833,10 +834,16 @@ asmlinkage long sys_times(struct tms * tbuf)
* atomically safe type this is just fine. Conceptually its
* as if the syscall took an instant longer to occur.
*/
if (tbuf)
if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
if (tbuf) {
struct tms tmp;
tmp.tms_utime = jiffies_to_clock_t(current->utime);
tmp.tms_stime = jiffies_to_clock_t(current->stime);
tmp.tms_cutime = jiffies_to_clock_t(current->cutime);
tmp.tms_cstime = jiffies_to_clock_t(current->cstime);
if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
return -EFAULT;
return jiffies;
}
return jiffies_to_clock_t(jiffies);
}
/*
......@@ -1193,28 +1200,22 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
memset((char *) &r, 0, sizeof(r));
switch (who) {
case RUSAGE_SELF:
r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime);
r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime);
r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime);
r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime);
jiffies_to_timeval(p->utime, &r.ru_utime);
jiffies_to_timeval(p->stime, &r.ru_stime);
r.ru_minflt = p->min_flt;
r.ru_majflt = p->maj_flt;
r.ru_nswap = p->nswap;
break;
case RUSAGE_CHILDREN:
r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_cutime);
r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_cutime);
r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_cstime);
r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_cstime);
jiffies_to_timeval(p->cutime, &r.ru_utime);
jiffies_to_timeval(p->cstime, &r.ru_stime);
r.ru_minflt = p->cmin_flt;
r.ru_majflt = p->cmaj_flt;
r.ru_nswap = p->cnswap;
break;
default:
r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime + p->times.tms_cutime);
r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime + p->times.tms_cutime);
r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime + p->times.tms_cstime);
r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime + p->times.tms_cstime);
jiffies_to_timeval(p->utime + p->cutime, &r.ru_utime);
jiffies_to_timeval(p->stime + p->cstime, &r.ru_stime);
r.ru_minflt = p->min_flt + p->cmin_flt;
r.ru_majflt = p->maj_flt + p->cmaj_flt;
r.ru_nswap = p->nswap + p->cnswap;
......
......@@ -527,8 +527,8 @@ static inline void do_process_times(struct task_struct *p,
{
unsigned long psecs;
psecs = (p->times.tms_utime += user);
psecs += (p->times.tms_stime += system);
psecs = (p->utime += user);
psecs += (p->stime += system);
if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_cur) {
/* Send SIGXCPU every second.. */
if (!(psecs % HZ))
......
......@@ -72,7 +72,7 @@ static int badness(struct task_struct *p)
* very well in practice. This is not safe against jiffie wraps
* but we don't care _that_ much...
*/
cpu_time = (p->times.tms_utime + p->times.tms_stime) >> (SHIFT_HZ + 3);
cpu_time = (p->utime + p->stime) >> (SHIFT_HZ + 3);
run_time = (jiffies - p->start_time) >> (SHIFT_HZ + 10);
points /= int_sqrt(cpu_time);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment