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:
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
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.
-- George Anzinger george@mvista.com High-res-timers: http://sourceforge.net/projects/high-res-timers/ Real time sched: http://sourceforge.net/projects/rtsched/ Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml - 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/