[patch 1/2] Re: What is supposed to replace clock_t?

From: Tim Schmielau (tim@physik3.uni-rostock.de)
Date: Tue Jul 16 2002 - 05:54:21 EST


On Sat, 13 Jul 2002, Linus Torvalds wrote:

> (for example, leave the broken clock_t representation in /proc/<pid>/stat
> alone, and just add a _sane_ seconds-based thing in the much more readable
> and parseable /proc/<pid>/status file.
>
> Not all of the olf clock_t-based stuff is worth trying to fix up, imho.

However, I also don't see a reason not to fix /proc/<pid>/stat, either.
(see my following patch 2/3)

> We should just make the internal jiffies be 64-bit. That's
> already true for the "true" jiffy count, but it's simply not true for some
> other things (process counters etc).
[...]
> Fixing "jiffies_to_timeval()" and friends to do the right thing for 64-bit
> jiffies will make a lot of the binary interfaces (ie gettimeofday/select/
> getrusage etc) just do the right thing.

Do we actually need to correct anything in gettimeofday() and select() ?
The timeout in select() probably shouldn't exceed 24 days, and
gettimeofday() only uses jiffies to account for a few lost jiffies, as far
as I can tell.
The real work seems to be getrusage(), since this requires having 64 bit
per process statistics first.

>
> I'd like to do this gradually, though. If you're interested, how about
> just slowly migrating to a
>
> typedef u64 jiffies_t;
>
> and slowly making the _internal_ stuff be 64-bit clean?

sure, first hunk of patches comes right now. Part 1/2 is simple:

 - introduce jiffies_t as u64
 - introduce jiffies_to_user_HZ()
 - use 64 bit jiffies for uptime

Since we certainly don't want to have a jiffies_64_to_clock_t_64()
function, I made jiffies_to_user_HZ() return an unsigned long long,
which is what we finally want to feed to printk anyways.

Tim
(email: "Tim Schmielau" <tim@physik3.uni-rostock.de>)

--- linux-2.5.25/include/linux/types.h Fri Jun 21 00:53:49 2002
+++ linux-2.5.25-j64/include/linux/types.h Tue Jul 16 08:18:05 2002
@@ -25,6 +25,7 @@
 typedef __kernel_suseconds_t suseconds_t;
 
 #ifdef __KERNEL__
+typedef u64 jiffies_t;
 typedef __kernel_uid32_t uid_t;
 typedef __kernel_gid32_t gid_t;
 typedef __kernel_uid16_t uid16_t;

--- linux-2.5.25/include/linux/times.h Sat Jul 13 08:40:21 2002
+++ linux-2.5.25-j64/include/linux/times.h Tue Jul 16 09:15:32 2002
@@ -1,8 +1,16 @@
 #ifndef _LINUX_TIMES_H
 #define _LINUX_TIMES_H
 
+#include <asm/div64.h>
+
 #ifdef __KERNEL__
 # define jiffies_to_clock_t(x) ((x) / (HZ / USER_HZ))
+
+static inline unsigned long long jiffies_to_user_HZ(jiffies_t x)
+{
+ do_div(x, HZ / USER_HZ);
+ return x;
+}
 #endif
 
 struct tms {

--- linux-2.5.25/include/linux/jiffies.h Fri Jun 21 00:53:42 2002
+++ linux-2.5.25-j64/include/linux/jiffies.h Tue Jul 16 09:47:15 2002
@@ -2,14 +2,37 @@
 #define _LINUX_JIFFIES_H
 
 #include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
 #include <asm/param.h> /* for HZ */
 
 /*
  * The 64-bit value is not volatile - you MUST NOT read it
- * without holding read_lock_irq(&xtime_lock)
+ * without holding read_lock_irq(&xtime_lock).
+ * get_jiffies64() will handle this for you as appropriate.
  */
-extern u64 jiffies_64;
+extern jiffies_t jiffies_64;
 extern unsigned long volatile jiffies;
+
+/*
+ * We assume only 64 bit architectures have BITS_PER_LONG == 64 and
+ * that these access longs atomically.
+ */
+static inline jiffies_t get_jiffies_64(void)
+{
+#if BITS_PER_LONG < 64
+ extern rwlock_t xtime_lock;
+ unsigned long flags;
+ jiffies_t tmp;
+
+ read_lock_irqsave(&xtime_lock, flags);
+ tmp = jiffies_64;
+ read_unlock_irqrestore(&xtime_lock, flags);
+ return tmp;
+#else
+ return (jiffies_t) jiffies;
+#endif
+}
 
 /*
  * These inlines deal with timer wrapping correctly. You are

--- linux-2.5.25/kernel/timer.c Sat Jul 13 08:40:21 2002
+++ linux-2.5.25-j64/kernel/timer.c Tue Jul 16 08:22:12 2002
@@ -24,8 +24,10 @@
 #include <linux/interrupt.h>
 #include <linux/tqueue.h>
 #include <linux/kernel_stat.h>
+#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
+#include <asm/div64.h>
 
 struct kernel_stat kstat;
 
@@ -922,13 +924,16 @@
 asmlinkage long sys_sysinfo(struct sysinfo *info)
 {
         struct sysinfo val;
+ u64 uptime;
         unsigned long mem_total, sav_total;
         unsigned int mem_unit, bitcount;
 
         memset((char *)&val, 0, sizeof(struct sysinfo));
 
         read_lock_irq(&xtime_lock);
- val.uptime = jiffies / HZ;
+ uptime = jiffies_64;
+ do_div(uptime, HZ);
+ val.uptime = (unsigned long) uptime;
 
         val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
         val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);

--- linux-2.5.25/fs/proc/proc_misc.c Sat Jul 13 08:40:20 2002
+++ linux-2.5.25-j64/fs/proc/proc_misc.c Tue Jul 16 09:50:36 2002
@@ -37,10 +37,12 @@
 #include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/times.h>
+#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
+#include <asm/div64.h>
 
 
 #define LOAD_INT(x) ((x) >> FSHIFT)
@@ -94,34 +96,27 @@
 static int uptime_read_proc(char *page, char **start, off_t off,
                                  int count, int *eof, void *data)
 {
- unsigned long uptime;
- unsigned long idle;
+ u64 uptime, idle;
+ unsigned long uptime_remainder, idle_remainder;
         int len;
 
- uptime = jiffies;
- idle = init_task.utime + init_task.stime;
+ uptime = get_jiffies_64();
+ uptime_remainder = (unsigned long) do_div(uptime, HZ);
+ idle = (u64) init_task.utime + init_task.stime;
+ idle_remainder = (unsigned long) do_div(idle, HZ);
 
- /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
- that would overflow about every five days at HZ == 100.
- Therefore the identity a = (a / b) * b + a % b is used so that it is
- calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
- The part in front of the '+' always evaluates as 0 (mod 100). All divisions
- in the above formulas are truncating. For HZ being a power of 10, the
- calculations simplify to the version in the #else part (if the printf
- format is adapted to the same number of digits as zeroes in HZ.
- */
 #if HZ!=100
         len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
- uptime / HZ,
- (((uptime % HZ) * 100) / HZ) % 100,
- idle / HZ,
- (((idle % HZ) * 100) / HZ) % 100);
+ (unsigned long) uptime,
+ (uptime_remainder * 100) / HZ,
+ (unsigned long) idle,
+ (idle_remainder * 100) / HZ);
 #else
         len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
- uptime / HZ,
- uptime % HZ,
- idle / HZ,
- idle % HZ);
+ (unsigned long) uptime,
+ uptime_remainder,
+ (unsigned long) idle,
+ idle_remainder;
 #endif
         return proc_calc_metrics(page, start, off, count, eof, len);
 }
@@ -278,7 +273,7 @@
 {
         int i, len;
         extern unsigned long total_forks;
- unsigned long jif = jiffies;
+ jiffies_t jif = get_jiffies_64();
         unsigned int sum = 0, user = 0, nice = 0, system = 0;
         int major, disk;
 
@@ -295,21 +290,22 @@
 #endif
         }
 
- len = sprintf(page, "cpu %u %u %u %lu\n",
+ len = sprintf(page, "cpu %u %u %u %llu\n",
                 jiffies_to_clock_t(user),
                 jiffies_to_clock_t(nice),
                 jiffies_to_clock_t(system),
- jiffies_to_clock_t(jif * num_online_cpus() - (user + nice + system)));
+ jiffies_to_user_HZ(jif * num_online_cpus()
+ - user - nice - system));
         for (i = 0 ; i < NR_CPUS; i++){
                 if (!cpu_online(i)) continue;
- len += sprintf(page + len, "cpu%d %u %u %u %lu\n",
+ len += sprintf(page + len, "cpu%d %u %u %u %llu\n",
                         i,
                         jiffies_to_clock_t(kstat.per_cpu_user[i]),
                         jiffies_to_clock_t(kstat.per_cpu_nice[i]),
                         jiffies_to_clock_t(kstat.per_cpu_system[i]),
- jiffies_to_clock_t(jif - ( kstat.per_cpu_user[i] \
- + kstat.per_cpu_nice[i] \
- + kstat.per_cpu_system[i])));
+ jiffies_to_user_HZ(jif - kstat.per_cpu_user[i]
+ - kstat.per_cpu_nice[i]
+ - kstat.per_cpu_system[i]));
         }
         len += sprintf(page + len,
                 "page %u %u\n"
@@ -346,12 +342,13 @@
                 }
         }
 
+ do_div(jif, HZ);
         len += sprintf(page + len,
                 "\nctxt %lu\n"
                 "btime %lu\n"
                 "processes %lu\n",
                 nr_context_switches(),
- xtime.tv_sec - jif / HZ,
+ xtime.tv_sec - (unsigned long) jif,
                 total_forks);
 
         return proc_calc_metrics(page, start, off, count, eof, len);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Jul 23 2002 - 22:00:19 EST