64-bit jiffies, a better solution

Message ID 3CDC3D39.607D1923@mvista.com
State New, archived
Headers show
Series
  • 64-bit jiffies, a better solution
Related show

Commit Message

George Anzinger May 10, 2002, 9:35 p.m. UTC
Linus Torvalds wrote:
> 
> In article <3BD52454.218387D9@mvista.com>,
> george anzinger  <george@mvista.com> wrote:
> >
> >I am beginning to think that defining a u64 and casting, i.e.:
> >
> >#define jiffies (unsigned long volitial)jiffies_u64
> >
> >is the way to go.
> 
> ..except for gcc being bad at even 64->32-bit casts like the above.  It
> will usually still load the full 64-bit value, and then only use the low
> bits.
> 
> The efficient and sane way to do it is:
> 
>         /*
>          * The 64-bit value is not volatile - you MUST NOT read it
>          * without holding the spinlock
>          */
>         u64 jiffies_64;
> 
>         /*
>          * Most people don't necessarily care about the full 64-bit
>          * value, so we can just get the "unstable" low bits without
>          * holding the lock. For historical reasons we also mark
>          * it volatile so that busy-waiting doesn't get optimized
>          * away in old drivers.
>          */
>         #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
> 
> which looks ugly, but the ugliness is confined to that one place, and
> none of the users will ever have to care..
> 
>                 Linus

I tried the above and, aside from the numerous cases where "jiffies"
appears
as a dummy variable or a struct/union member which had to be "fixed", I
got 
flack from some folks who thought that:

extern unsigned long jiffies;

should work.  So here is a solution that does all the above and does 
NOT invade new name spaces:

 unsigned int * prof_buffer;
 unsigned long prof_len;
@@ -664,7 +685,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 */

----------------------------------------------------------------------

And for those who think doing a ++ on 64-bits is too much to do in an
interrupt,
here is the before / after diff of the asm file for timer.c (messed up a
bit so
patch doesn't get confused):

*-* /usr/src/linux-2.5.14-kb/kernel/timer.o	Fri May 10 14:03:07 2002
*+* /usr/src/linux-2.5.14-kb/kernel/timer.s	Fri May 10 14:02:03 2002
** -1371,7 +1371,8 **
 .globl do_timer
 	.type	 do_timer,@function
 do_timer:
-	incl jiffies
+	addl $1,jiffies_64
+	adcl $0,jiffies_64+4
 	xorl %eax,%eax
 #APP
 	lock ; btsl %eax,bh_task_vec+4
-----------------------------
This solution should work for all platforms and long sizes, does not
depend on asm
and does not invade any new name spaces.

Comments

Linus Torvalds May 10, 2002, 9:52 p.m. UTC | #1
On Fri, 10 May 2002, george anzinger wrote:
> 
> should work.  So here is a solution that does all the above and does 
> NOT invade new name spaces:

Ok, looks fine, but I'd really rather move the "jiffies" linker games
into the per-architecture stuff, and get rid of the jiffies_at_jiffies_64 
games.

It's just one line per architecture, after all.

		Linus

-
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/
George Anzinger May 10, 2002, 10:36 p.m. UTC | #2
Linus Torvalds wrote:
> 
> On Fri, 10 May 2002, george anzinger wrote:
> >
> > should work.  So here is a solution that does all the above and does
> > NOT invade new name spaces:
> 
> Ok, looks fine, but I'd really rather move the "jiffies" linker games
> into the per-architecture stuff, and get rid of the jiffies_at_jiffies_64
> games.
> 
> It's just one line per architecture, after all.
> 
>                 Linus
If that were only true.  The problem is that some architectures can be
built with either endian.  Mips, for example, seems to take the endian
stuff in as an environment variable.  The linker seems to know this
stuff, but does not provide the "built in" to allow it to be used.

The info is available from the header files at compile time, but I could
not find a clean way to export it to the Makefile, where we might choose
which linker script to use.  I suppose we could run the linker script
thru cpp if all else fails.  Any ideas?
Linus Torvalds May 10, 2002, 10:40 p.m. UTC | #3
On Fri, 10 May 2002, george anzinger wrote:
>
> If that were only true.  The problem is that some architectures can be
> built with either endian.  Mips, for example, seems to take the endian
> stuff in as an environment variable.  The linker seems to know this
> stuff, but does not provide the "built in" to allow it to be used.

Ignore those for now, and let the architecture maintainer sort it out. 
>From what I can tell, those architectures do things like generate the 
linker script dynamically anyway, so..

		Linus

-
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/
George Anzinger May 11, 2002, 12:42 a.m. UTC | #4
Linus Torvalds wrote:
> 
> On Fri, 10 May 2002, george anzinger wrote:
> >
> > If that were only true.  The problem is that some architectures can be
> > built with either endian.  Mips, for example, seems to take the endian
> > stuff in as an environment variable.  The linker seems to know this
> > stuff, but does not provide the "built in" to allow it to be used.
> 
> Ignore those for now, and let the architecture maintainer sort it out.
> >From what I can tell, those architectures do things like generate the
> linker script dynamically anyway, so..
> 
>                 Linus
Ok, here it is.  The following arch are not covered:
Mips, Mips64 in 32-bit mode, parisc in __LP64__ mode.

In addition, x86_64 mentions jiffies in the existing script.  
This may be a problem.


diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/alpha/vmlinux.lds.in linux/arch/alpha/vmlinux.lds.in
--- linux-2.5.14-org/arch/alpha/vmlinux.lds.in	Tue May  7 16:08:34 2002
+++ linux/arch/alpha/vmlinux.lds.in	Fri May 10 16:56:03 2002
@@ -3,6 +3,7 @@
 OUTPUT_FORMAT("elf64-alpha")
 ENTRY(__start)
 PHDRS { kernel PT_LOAD ; }
+jiffies = jiffies_64;
 SECTIONS
 {
 #ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/arm/vmlinux-armo.lds.in linux/arch/arm/vmlinux-armo.lds.in
--- linux-2.5.14-org/arch/arm/vmlinux-armo.lds.in	Tue May  7 15:59:35 2002
+++ linux/arch/arm/vmlinux-armo.lds.in	Fri May 10 17:07:31 2002
@@ -4,6 +4,7 @@
  */
 OUTPUT_ARCH(arm)
 ENTRY(stext)
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
 	. = TEXTADDR;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in
--- linux-2.5.14-org/arch/arm/vmlinux-armv.lds.in	Tue May  7 15:59:35 2002
+++ linux/arch/arm/vmlinux-armv.lds.in	Fri May 10 17:07:34 2002
@@ -4,6 +4,7 @@
  */
 OUTPUT_ARCH(arm)
 ENTRY(stext)
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
 	. = TEXTADDR;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/cris/cris.ld linux/arch/cris/cris.ld
--- linux-2.5.14-org/arch/cris/cris.ld	Tue May  7 16:06:14 2002
+++ linux/arch/cris/cris.ld	Fri May 10 17:08:39 2002
@@ -8,6 +8,7 @@
  * the kernel has booted. 
  */	
 
+jiffies = jiffies_64;
 SECTIONS
 {
 	. = @CONFIG_ETRAX_DRAM_VIRTUAL_BASE@;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds
--- linux-2.5.14-org/arch/i386/vmlinux.lds	Tue May  7 16:13:12 2002
+++ linux/arch/i386/vmlinux.lds	Fri May 10 16:53:50 2002
@@ -4,6 +4,7 @@
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
 ENTRY(_start)
+jiffies = jiffies_64;
 SECTIONS
 {
   . = 0xC0000000 + 0x100000;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/ia64/vmlinux.lds.S linux/arch/ia64/vmlinux.lds.S
--- linux-2.5.14-org/arch/ia64/vmlinux.lds.S	Tue May  7 16:20:04 2002
+++ linux/arch/ia64/vmlinux.lds.S	Fri May 10 17:10:14 2002
@@ -7,6 +7,7 @@
 OUTPUT_FORMAT("elf64-ia64-little")
 OUTPUT_ARCH(ia64)
 ENTRY(phys_start)
+jiffies = jiffies_64; 
 SECTIONS
 {
   /* Sections to be discarded */
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/m68k/vmlinux-sun3.lds linux/arch/m68k/vmlinux-sun3.lds
--- linux-2.5.14-org/arch/m68k/vmlinux-sun3.lds	Tue May  7 16:06:15 2002
+++ linux/arch/m68k/vmlinux-sun3.lds	Fri May 10 17:12:23 2002
@@ -2,6 +2,7 @@
 OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
 OUTPUT_ARCH(m68k)
 ENTRY(_start)
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
   . = 0xE004000;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/m68k/vmlinux.lds linux/arch/m68k/vmlinux.lds
--- linux-2.5.14-org/arch/m68k/vmlinux.lds	Tue May  7 16:06:15 2002
+++ linux/arch/m68k/vmlinux.lds	Fri May 10 17:11:58 2002
@@ -2,6 +2,7 @@
 OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k")
 OUTPUT_ARCH(m68k)
 ENTRY(_start)
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
   . = 0x1000;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/mips64/ld.script.elf64 linux/arch/mips64/ld.script.elf64
--- linux-2.5.14-org/arch/mips64/ld.script.elf64	Tue May  7 15:59:38 2002
+++ linux/arch/mips64/ld.script.elf64	Fri May 10 17:30:11 2002
@@ -1,5 +1,6 @@
 OUTPUT_ARCH(mips)
 ENTRY(kernel_entry)
+jiffies = jiffies_64;
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/parisc/vmlinux.lds linux/arch/parisc/vmlinux.lds
--- linux-2.5.14-org/arch/parisc/vmlinux.lds	Tue May  7 15:59:38 2002
+++ linux/arch/parisc/vmlinux.lds	Fri May 10 17:17:14 2002
@@ -2,6 +2,7 @@
 OUTPUT_FORMAT("elf32-hppa")
 OUTPUT_ARCH(hppa)
 ENTRY(_stext)
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
 
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds
--- linux-2.5.14-org/arch/ppc/vmlinux.lds	Tue May  7 16:13:12 2002
+++ linux/arch/ppc/vmlinux.lds	Fri May 10 17:18:01 2002
@@ -2,6 +2,7 @@
 SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
 /* Do we need any of these for elf?
    __DYNAMIC = 0;    */
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/ppc64/vmlinux.lds linux/arch/ppc64/vmlinux.lds
--- linux-2.5.14-org/arch/ppc64/vmlinux.lds	Tue May  7 16:18:05 2002
+++ linux/arch/ppc64/vmlinux.lds	Fri May 10 17:19:02 2002
@@ -2,6 +2,7 @@
 SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
 /* Do we need any of these for elf?
    __DYNAMIC = 0;    */
+jiffies = jiffies_64;
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/s390/vmlinux-shared.lds linux/arch/s390/vmlinux-shared.lds
--- linux-2.5.14-org/arch/s390/vmlinux-shared.lds	Tue May  7 16:06:16 2002
+++ linux/arch/s390/vmlinux-shared.lds	Fri May 10 17:19:59 2002
@@ -4,6 +4,7 @@
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
 OUTPUT_ARCH(s390)
 ENTRY(_start)
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
   . = 0x00000000;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/s390/vmlinux.lds linux/arch/s390/vmlinux.lds
--- linux-2.5.14-org/arch/s390/vmlinux.lds	Tue May  7 16:06:16 2002
+++ linux/arch/s390/vmlinux.lds	Fri May 10 17:20:38 2002
@@ -4,6 +4,7 @@
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
 OUTPUT_ARCH(s390)
 ENTRY(_start)
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
   . = 0x00000000;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/s390x/vmlinux-shared.lds linux/arch/s390x/vmlinux-shared.lds
--- linux-2.5.14-org/arch/s390x/vmlinux-shared.lds	Tue May  7 16:06:16 2002
+++ linux/arch/s390x/vmlinux-shared.lds	Fri May 10 17:21:53 2002
@@ -4,6 +4,7 @@
 OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390)
 ENTRY(_start)
+jiffies = jiffies_64;
 SECTIONS
 {
   . = 0x00000000;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/s390x/vmlinux.lds linux/arch/s390x/vmlinux.lds
--- linux-2.5.14-org/arch/s390x/vmlinux.lds	Tue May  7 16:06:16 2002
+++ linux/arch/s390x/vmlinux.lds	Fri May 10 17:22:29 2002
@@ -4,6 +4,7 @@
 OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390)
 ENTRY(_start)
+jiffies = jiffies_64;
 SECTIONS
 {
   . = 0x00000000;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/sh/vmlinux.lds.S linux/arch/sh/vmlinux.lds.S
--- linux-2.5.14-org/arch/sh/vmlinux.lds.S	Tue May  7 16:06:16 2002
+++ linux/arch/sh/vmlinux.lds.S	Fri May 10 17:24:46 2002
@@ -5,8 +5,10 @@
 #include <linux/config.h>
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux")
+jiffies = jiffies_64;        
 #else
 OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux")
+jiffies = jiffies_64 + 4;
 #endif
 OUTPUT_ARCH(sh)
 ENTRY(_start)
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds
--- linux-2.5.14-org/arch/sparc/vmlinux.lds	Tue May  7 16:15:28 2002
+++ linux/arch/sparc/vmlinux.lds	Fri May 10 17:25:31 2002
@@ -2,6 +2,7 @@
 OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc")
 OUTPUT_ARCH(sparc)
 ENTRY(_start)
+jiffies = jiffies_64 + 4;
 SECTIONS
 {
   . = 0x10000 + SIZEOF_HEADERS;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds
--- linux-2.5.14-org/arch/sparc64/vmlinux.lds	Tue May  7 16:15:30 2002
+++ linux/arch/sparc64/vmlinux.lds	Fri May 10 17:26:14 2002
@@ -3,6 +3,7 @@
 OUTPUT_ARCH(sparc:v9a)
 ENTRY(_start)
 
+jiffies = jiffies_64;
 SECTIONS
 {
   swapper_pmd_dir = 0x0000000000402000;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/arch/x86_64/vmlinux.lds linux/arch/x86_64/vmlinux.lds
--- linux-2.5.14-org/arch/x86_64/vmlinux.lds	Tue May  7 16:20:04 2002
+++ linux/arch/x86_64/vmlinux.lds	Fri May 10 17:26:45 2002
@@ -3,6 +3,7 @@
  */
 OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
 OUTPUT_ARCH(i386:x86-64)
+jiffies = jiffies_64;
 ENTRY(_start)
 SECTIONS
 {
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.5.14-org/include/linux/sched.h	Tue May  7 16:57:58 2002
+++ linux/include/linux/sched.h	Thu May  9 17:26:25 2002
@@ -459,6 +459,11 @@
 
 #include <asm/current.h>
 
+/*
+ * The 64-bit value is not volatile - you MUST NOT read it
+ * without holding read_lock_irq(&xtime_lock)
+ */
+extern u64 jiffies_64;
 extern unsigned long volatile jiffies;
 extern unsigned long itimer_ticks;
 extern unsigned long itimer_next;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.5.14-org/kernel/ksyms.c	Tue May  7 16:25:15 2002
+++ linux/kernel/ksyms.c	Thu May  9 17:21:43 2002
@@ -471,6 +471,7 @@
 EXPORT_SYMBOL_GPL(set_cpus_allowed);
 #endif
 EXPORT_SYMBOL(jiffies);
+EXPORT_SYMBOL(jiffies_64);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
 EXPORT_SYMBOL(do_settimeofday);
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.14-org/kernel/timer.c linux/kernel/timer.c
--- linux-2.5.14-org/kernel/timer.c	Tue May  7 16:15:52 2002
+++ linux/kernel/timer.c	Fri May 10 16:35:39 2002
@@ -67,7 +67,12 @@
 
 extern int do_setitimer(int, struct itimerval *, struct itimerval *);
 
-unsigned long volatile jiffies;
+/*
+ * The 64-bit value is not volatile - you MUST NOT read it
+ * without holding read_lock_irq(&xtime_lock).
+ * jiffies is defined in the linker script...
+ */
+u64 jiffies_64;
 
 unsigned int * prof_buffer;
 unsigned long prof_len;
@@ -664,7 +669,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 */
Maciej W. Rozycki May 13, 2002, 11:09 a.m. UTC | #5
On Fri, 10 May 2002, george anzinger wrote:

> If that were only true.  The problem is that some architectures can be
> built with either endian.  Mips, for example, seems to take the endian
> stuff in as an environment variable.  The linker seems to know this
> stuff, but does not provide the "built in" to allow it to be used.

 Huh?  You can use CONFIG_CPU_LITTLE_ENDIAN.  Gcc and the linker for
MIPS/Linux typically support both endiannesses (with a default selected at
their build time) and it's the configuration variable that selects either
of them.

> The info is available from the header files at compile time, but I could
> not find a clean way to export it to the Makefile, where we might choose
> which linker script to use.  I suppose we could run the linker script
> thru cpp if all else fails.  Any ideas?

 CONFIG_CPU_LITTLE_ENDIAN is available to Makefiles.  There used to be
separate linker scripts for different endiannesses for MIPS once.

Patch

diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude
linux-2.5.14-org/Makefile linux/Makefile
--- linux-2.5.14-org/Makefile	Tue May  7 16:25:52 2002
+++ linux/Makefile	Thu May  9 18:18:53 2002
@@ -262,6 +262,7 @@ 
 
 vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o
init/version.o init/do_mounts.o linuxsubdirs
 	$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o
\
+		kernel/jiffies_linker_file.lds \
 		--start-group \
 		$(CORE_FILES) \
 		$(LIBS) \
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude
linux-2.5.14-org/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.5.14-org/include/linux/sched.h	Tue May  7 16:57:58 2002
+++ linux/include/linux/sched.h	Thu May  9 17:26:25 2002
@@ -459,6 +459,11 @@ 
 
 #include <asm/current.h>
 
+/*
+ * The 64-bit value is not volatile - you MUST NOT read it
+ * without holding read_lock_irq(&xtime_lock)
+ */
+extern u64 jiffies_64;
 extern unsigned long volatile jiffies;
 extern unsigned long itimer_ticks;
 extern unsigned long itimer_next;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude
linux-2.5.14-org/kernel/jiffies_linker_file.lds
linux/kernel/jiffies_linker_file.lds
--- linux-2.5.14-org/kernel/jiffies_linker_file.lds	Wed Dec 31 16:00:00
1969
+++ linux/kernel/jiffies_linker_file.lds	Fri May 10 14:10:28 2002
@@ -0,0 +1,14 @@ 
+/*
+ * This linker script defines jiffies to be either the same as 
+ * jiffies_64 (for little endian or 64 bit machines) or
+ * jiffies_64+4 (for big endian machines)
+ * 
+ * It is intended to satisfy external references to a 32 bit jiffies
which
+ * is the low order 32-bits of a 64-bit jiffies.
+ *
+ * jiffies_at_jiffies_64 needs to be defined if this is a little endian
+ * or a 64-bit machine.
+ * Currently this is done in ..../kernel/timer.c
+ *
+ */
+jiffies =DEFINED(jiffies_at_jiffies_64) ? jiffies_64 : (jiffies_64 +
4);
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude
linux-2.5.14-org/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.5.14-org/kernel/ksyms.c	Tue May  7 16:25:15 2002
+++ linux/kernel/ksyms.c	Thu May  9 17:21:43 2002
@@ -471,6 +471,7 @@ 
 EXPORT_SYMBOL_GPL(set_cpus_allowed);
 #endif
 EXPORT_SYMBOL(jiffies);
+EXPORT_SYMBOL(jiffies_64);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
 EXPORT_SYMBOL(do_settimeofday);
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude
linux-2.5.14-org/kernel/timer.c linux/kernel/timer.c
--- linux-2.5.14-org/kernel/timer.c	Tue May  7 16:15:52 2002
+++ linux/kernel/timer.c	Fri May 10 14:08:37 2002
@@ -67,7 +67,28 @@ 
 
 extern int do_setitimer(int, struct itimerval *, struct itimerval *);
 
-unsigned long volatile jiffies;
+/*
+ * The 64-bit value is not volatile - you MUST NOT read it
+ * without holding read_lock_irq(&xtime_lock)
+ */
+u64 jiffies_64;
+/*
+ * Most people don't necessarily care about the full 64-bit
+ * value, so we can just get the "unstable" low bits without
+ * holding the lock. For historical reasons we also mark
+ * it volatile so that busy-waiting doesn't get optimized
+ * away in old drivers.
+ *
+ * This definition depends on the linker defining the actual address of
+ * jiffies using the following (found in
.../kernel/jiffies_linker_file):
+ * jiffies = DEFINED(jiffies_at_jiffies_64) ? jiffies_64 :
jiffies_64+4;
+ */
+#if defined(__LITTLE_ENDIAN) || (BITS_PER_LONG > 32)
+
+char jiffies_at_jiffies_64[0];
+#elif ! defined(__BIG_ENDIAN)
+#ERROR "Neither __LITTLE_ENDIAN nor __BIG_ENDIAN defined "
+#endif