public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [Patch] Re: Nasty suprise with uptime
@ 2001-10-31 22:11 Petr Vandrovec
  2001-10-31 21:45 ` Andreas Dilger
  2001-10-31 22:58 ` Tim Schmielau
  0 siblings, 2 replies; 50+ messages in thread
From: Petr Vandrovec @ 2001-10-31 22:11 UTC (permalink / raw)
  To: Richard B. Johnson; +Cc: Andreas Dilger, Tim Schmielau, vda, linux-kernel

On 31 Oct 01 at 15:39, Richard B. Johnson wrote:
> A fix exists, though. The existing, possibly wrong, boot time could
> be grabbed during the set-time sys-call, the difference between the
> existing (wrong) time and the boot time could be calculated, the
> new (correct) time could be set, then the boot-time would be changed
> to the new correct time, minus the calculated difference. This
> would result in a correct boot-time.
> 
>     dif_time = time - boot_time;
>         time = new_time;
>         boot_time = time - dif_time;
> 
> Uptime could then be present time minus boot time. No mucking with
> timer ticks are required.

Hi,
  this reminds me. Year or so ago there was patch from someone, which 
detected jiffies overflow in /proc/uptime proc_read() code, so only thing
you had to do was run 'uptime', 'w', 'top' or something like that
every 497 days - you can schedule it as cron job for Jan 1, 0:00:00,
to find some workoholics.

  Patch was something like:

...  
static unsigned long long jiffies_hi = 0;
static unsigned long old_jiffies = 0;
unsigned long jiffy_cache;

/* some spinlock or inode lock or something like that */
jiffy_cache = jiffies;
if (jiffy_cache < old_jiffies) {
   jiffies_hi += 1ULL << BITS_PER_LONG;
}
old_jiffies = jiffy_cache;
grand_jiffies = jiffies_hi + jiffy_cache;
/* unlock */
/* now do division and all strange things to format number for userspace */
...

Even if you add running uptime every year to your crontab, 
it will consume less than 700,000,000 CPU cycles consumed by just 64bit
inc in timer interrupt.
                                        Best regards,
                                            Petr Vandrovec
                                            vandrove@vc.cvut.cz
                                            

^ permalink raw reply	[flat|nested] 50+ messages in thread
* Re: [Patch] Re: Nasty suprise with uptime
@ 2001-11-01  9:02 Petr Vandrovec
  0 siblings, 0 replies; 50+ messages in thread
From: Petr Vandrovec @ 2001-11-01  9:02 UTC (permalink / raw)
  To: Tim Schmielau; +Cc: linux-kernel, J Sloan, adilger

On  1 Nov 01 at 1:52, Tim Schmielau wrote:

> +   static unsigned long jiffies_hi = 0;
> +   static unsigned long jiffies_last = INITIAL_JIFFIES;
> +   unsigned long jiffies_tmp;
> +
> +   jiffies_tmp = jiffies;   /* avoid races */
> +   if (jiffies_tmp < jiffies_last)   /* We have a wrap */
> +       jiffies_hi++;
> +   jiffies_last = jiffies_tmp;

There is very small race - if two processes will call get_jiffies64()
at same time, they can both happen to test jiffies_tmp < jiffies_last
with old jiffies_last - incrementing jiffies_hi twice :-( This race
window is only few microseconds every 497 days, but if we want
correct kernel... 
                                            Best regards,
                                                Petr Vandrovec
                                                vandrove@vc.cvut.cz
                                                

^ permalink raw reply	[flat|nested] 50+ messages in thread
[parent not found: <01103121070200.01262@nemo>]
* [Patch] Re: Nasty suprise with uptime
@ 2001-10-31 11:35 Tim Schmielau
  2001-10-31 15:39 ` vda
  0 siblings, 1 reply; 50+ messages in thread
From: Tim Schmielau @ 2001-10-31 11:35 UTC (permalink / raw)
  To: linux-kernel; +Cc: george, jjs

The appended patch enables 32 bit linux boxes to display more than
497.1 days of uptime. No user land application changes are needed.

Credit is due to George Anzinger and the High-res-timers project
at https://sourceforge.net/projects/high-res-timers/, where I ripped
out the 64 bit jiffies patch. However, I do claim ownership on
all misdesign and bugs since this is my first kernel patch.

My Intel box just now displays a (faked, of course) uptime of 497 days,
2:38 hours, so the 32 jiffies value has wrapped without problems about 10
minutes ago.

Next step would be to decide what to do with the start_time field of
struct task_struct, which is still 32 bit, so ps on my box believes some
processes to have started 497 days ago. Probably there are tons of other
uses for the upper 32 bit of jiffies as well.

Tim



--- fs/proc/proc_misc.c.orig	Wed Oct 31 04:14:05 2001
+++ fs/proc/proc_misc.c	Wed Oct 31 11:07:31 2001
@@ -39,6 +39,7 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
+#include <asm/div64.h>


 #define LOAD_INT(x) ((x) >> FSHIFT)
@@ -103,15 +104,19 @@
 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;
+	unsigned long idle, remainder;
 	int len;

-	uptime = jiffies;
+	/* On 32 bit platforms there is a tiny window here
+	 * for a race condition every 497.1 days */
+	uptime = jiffies_64;
+	remainder = (unsigned long) do_div(uptime, HZ);
 	idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;

-	/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
-	   that would overflow about every five days at HZ == 100.
+	/* The formula for the fraction part of the idle time 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
@@ -121,14 +126,14 @@
 	 */
 #if HZ!=100
 	len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
-		uptime / HZ,
-		(((uptime % HZ) * 100) / HZ) % 100,
+		(unsigned long) uptime,
+		((remainder * 100) / HZ) % 100,
 		idle / HZ,
 		(((idle % HZ) * 100) / HZ) % 100);
 #else
 	len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
-		uptime / HZ,
-		uptime % HZ,
+	        (unsigned long) uptime,
+	        remainder,
 		idle / HZ,
 		idle % HZ);
 #endif
--- kernel/itimer.c.orig	Wed Oct 31 01:14:19 2001
+++ kernel/itimer.c	Wed Oct 31 01:15:38 2001
@@ -34,10 +34,10 @@
 	return HZ*sec+usec;
 }

-static void jiffiestotv(unsigned long jiffies, struct timeval *value)
+static void jiffiestotv(unsigned long _jiffies, struct timeval *value)
 {
-	value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
-	value->tv_sec = jiffies / HZ;
+	value->tv_usec = (_jiffies % HZ) * (1000000 / HZ);
+	value->tv_sec = _jiffies / HZ;
 }

 int do_getitimer(int which, struct itimerval *value)
--- kernel/timer.c.orig	Tue Oct 30 23:35:44 2001
+++ kernel/timer.c	Wed Oct 31 03:25:12 2001
@@ -65,7 +65,8 @@

 extern int do_setitimer(int, struct itimerval *, struct itimerval *);

-unsigned long volatile jiffies;
+#define INITIAL_JIFFIES 0
+volatile u64 jiffies_64 = INITIAL_JIFFIES;

 unsigned int * prof_buffer;
 unsigned long prof_len;
@@ -117,7 +118,7 @@
 		INIT_LIST_HEAD(tv1.vec + i);
 }

-static unsigned long timer_jiffies;
+static unsigned long timer_jiffies = INITIAL_JIFFIES;

 static inline void internal_add_timer(struct timer_list *timer)
 {
@@ -638,7 +639,7 @@
 }

 /* jiffies at the most recent update of wall time */
-unsigned long wall_jiffies;
+unsigned long wall_jiffies = INITIAL_JIFFIES;

 /*
  * This spinlock protect us from races in SMP while playing with xtime. -arca
@@ -673,7 +674,7 @@

 void do_timer(struct pt_regs *regs)
 {
-	(*(unsigned long *)&jiffies)++;
+	(*(u64 *)&jiffies_64)++;
 #ifndef CONFIG_SMP
 	/* SMP process accounting uses the local APIC timer */

--- kernel/ksyms.c.orig	Wed Oct 31 00:53:08 2001
+++ kernel/ksyms.c	Wed Oct 31 02:22:20 2001
@@ -435,7 +435,7 @@
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 EXPORT_SYMBOL(schedule);
 EXPORT_SYMBOL(schedule_timeout);
-EXPORT_SYMBOL(jiffies);
+EXPORT_SYMBOL(jiffies_64);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
 EXPORT_SYMBOL(do_settimeofday);
--- kernel/info.c.orig	Wed Oct 31 00:57:24 2001
+++ kernel/info.c	Wed Oct 31 10:38:50 2001
@@ -12,15 +12,21 @@
 #include <linux/smp_lock.h>

 #include <asm/uaccess.h>
+#include <asm/div64.h>

 asmlinkage long sys_sysinfo(struct sysinfo *info)
 {
 	struct sysinfo val;
+	u64 uptime;

 	memset((char *)&val, 0, sizeof(struct sysinfo));

 	cli();
-	val.uptime = jiffies / HZ;
+	/* On 32 bit platforms there is a tiny window here
+	 * for a race condition every 497.1 days */
+	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);
--- include/linux/time.h.orig	Wed Oct 31 01:40:39 2001
+++ include/linux/time.h	Wed Oct 31 01:41:33 2001
@@ -42,10 +42,10 @@
 }

 static __inline__ void
-jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
+jiffies_to_timespec(unsigned long _jiffies, struct timespec *value)
 {
-	value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
-	value->tv_sec = jiffies / HZ;
+	value->tv_nsec = (_jiffies % HZ) * (1000000000L / HZ);
+	value->tv_sec = _jiffies / HZ;
 }


--- include/linux/sched.h.orig	Wed Oct 31 00:48:44 2001
+++ include/linux/sched.h	Wed Oct 31 01:49:53 2001
@@ -550,7 +550,15 @@

 #include <asm/current.h>

-extern unsigned long volatile jiffies;
+/*
+ * you MUST NOT read jiffies_64 without holding read_lock_irq(&xtime_lock)
+ */
+#if defined(__LITTLE_ENDIAN) || (BITS_PER_LONG > 32)
+#define jiffies (((volatile unsigned long *)&jiffies_64)[0])
+#else
+#define jiffies (((volatile unsigned long *)&jiffies_64)[1])
+#endif
+extern u64 volatile jiffies_64;
 extern unsigned long itimer_ticks;
 extern unsigned long itimer_next;
 extern struct timeval xtime;
--- include/linux/coda_proc.h.orig	Wed Oct 31 01:29:56 2001
+++ include/linux/coda_proc.h	Wed Oct 31 01:30:24 2001
@@ -14,7 +14,7 @@

 void coda_sysctl_init(void);
 void coda_sysctl_clean(void);
-void coda_upcall_stats(int opcode, unsigned long jiffies);
+void coda_upcall_stats(int opcode, unsigned long _jiffies);

 #include <linux/sysctl.h>
 #include <linux/coda_fs_i.h>
--- net/ipv4/ipconfig.c.orig	Wed Oct 31 01:44:35 2001
+++ net/ipv4/ipconfig.c	Wed Oct 31 01:45:29 2001
@@ -630,7 +630,7 @@
 /*
  *  Send DHCP/BOOTP request to single interface.
  */
-static void __init ic_bootp_send_if(struct ic_device *d, u32 jiffies)
+static void __init ic_bootp_send_if(struct ic_device *d, u32 _jiffies)
 {
 	struct net_device *dev = d->dev;
 	struct sk_buff *skb;
@@ -677,7 +677,7 @@
 	b->your_ip = INADDR_NONE;
 	b->server_ip = INADDR_NONE;
 	memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
-	b->secs = htons(jiffies / HZ);
+	b->secs = htons(_jiffies / HZ);
 	b->xid = d->xid;

 	/* add DHCP options or BOOTP extensions */
--- drivers/net/wan/dscc4.c.orig	Wed Oct 31 01:45:49 2001
+++ drivers/net/wan/dscc4.c	Wed Oct 31 01:46:23 2001
@@ -123,7 +123,7 @@
 	u32 next;
 	u32 data;
 	u32 complete;
-	u32 jiffies; /* more hack to come :o) */
+	u32 _jiffies; /* more hack to come :o) */
 };

 struct RxFD {
--- drivers/block/floppy.c.orig	Wed Oct 31 01:16:05 2001
+++ drivers/block/floppy.c	Wed Oct 31 01:18:17 2001
@@ -635,7 +635,7 @@
 static struct output_log {
 	unsigned char data;
 	unsigned char status;
-	unsigned long jiffies;
+	unsigned long _jiffies;
 } output_log[OLOGSIZE];

 static int output_log_pos;
@@ -1163,7 +1163,7 @@
 #ifdef FLOPPY_SANITY_CHECK
 		output_log[output_log_pos].data = byte;
 		output_log[output_log_pos].status = status;
-		output_log[output_log_pos].jiffies = jiffies;
+		output_log[output_log_pos]._jiffies = jiffies;
 		output_log_pos = (output_log_pos + 1) % OLOGSIZE;
 #endif
 		return 0;
@@ -1851,7 +1851,7 @@
 		printk("%2x %2x %lu\n",
 		       output_log[(i+output_log_pos) % OLOGSIZE].data,
 		       output_log[(i+output_log_pos) % OLOGSIZE].status,
-		       output_log[(i+output_log_pos) % OLOGSIZE].jiffies);
+		       output_log[(i+output_log_pos) % OLOGSIZE]._jiffies);
 	printk("last result at %lu\n", resultjiffies);
 	printk("last redo_fd_request at %lu\n", lastredo);
 	for (i=0; i<resultsize; i++){


^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2001-11-04 18:32 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-10-31 22:11 [Patch] Re: Nasty suprise with uptime Petr Vandrovec
2001-10-31 21:45 ` Andreas Dilger
2001-10-31 22:58 ` Tim Schmielau
2001-10-31 23:56   ` Andreas Dilger
2001-11-01  0:23     ` Tim Schmielau
2001-11-01  0:52       ` Tim Schmielau
2001-11-01 11:21         ` george anzinger
2001-11-01 11:40           ` Tim Schmielau
2001-11-02  0:28             ` Tim Schmielau
2001-11-02  1:23               ` Andreas Dilger
2001-11-02  9:10                 ` Miquel van Smoorenburg
2001-11-02 17:18                 ` Tim Schmielau
2001-11-02 18:48                   ` Andreas Dilger
2001-11-02 21:35                     ` possibly incorrect comparisons of jiffies in linux kernel Tim Schmielau
2001-11-01 16:35         ` [Patch] Re: Nasty suprise with uptime vda
2001-11-01 15:34           ` Richard B. Johnson
2001-11-01 17:02             ` Benjamin LaHaise
2001-11-01 18:03               ` Richard B. Johnson
2001-11-01 18:34                 ` Benjamin LaHaise
2001-11-02 14:46                   ` vda
2001-11-01 17:29             ` george anzinger
  -- strict thread matches above, loose matches on Subject: below --
2001-11-01  9:02 Petr Vandrovec
     [not found] <01103121070200.01262@nemo>
2001-10-31 19:26 ` Tim Schmielau
2001-10-31 19:52   ` Richard B. Johnson
2001-10-31 20:00     ` J Sloan
2001-10-31 20:20     ` Charles Cazabon
2001-10-31 20:33       ` Kurt Roeckx
2001-10-31 20:47 ` Tim Schmielau
2001-10-31 21:07   ` Andreas Dilger
2001-10-31 21:11   ` Richard B. Johnson
2001-11-01 16:09   ` vda
2001-10-31 11:35 Tim Schmielau
2001-10-31 15:39 ` vda
2001-10-31 14:31   ` Richard B. Johnson
2001-10-31 18:16     ` Tim Schmielau
2001-10-31 18:35       ` Tim Schmielau
2001-10-31 18:59         ` Andreas Dilger
2001-10-31 18:40       ` Andreas Dilger
2001-10-31 18:58         ` Gerhard Mack
2001-10-31 19:14           ` Richard B. Johnson
2001-10-31 20:11             ` Gerhard Mack
2001-10-31 20:39               ` Richard B. Johnson
2001-10-31 20:52               ` Andreas Dilger
2001-10-31 21:05                 ` Tim Schmielau
2001-10-31 21:39                   ` Andreas Dilger
2001-10-31 21:17                 ` Richard B. Johnson
2001-11-01  7:45                   ` Ville Herva
2001-10-31 19:06       ` george anzinger
2001-10-31 22:54       ` george anzinger
2001-11-04 18:31         ` Ton Hospel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox