Skip to contentSkip to conversation

new timeofday subsystem (v A5)

RFC PATCH New john stultz 9 participants 35 messages May 14, 2005 – May 19, 2005

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 new timeofday subsystem (v A5)

All,
This patch implements the architecture independent portion of the new
time of day subsystem. For a brief description on the rework, see here:
http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that easy to understand writeup!)

I intend this to be the last RFC release and to submit this patch to
Andrew for for testing near the end of this month. So please, if you have any complaints, suggestions, or blocking issues, let me know.

Included below is timeofday.c (which includes all the time of day
management and accessor functions), ntp.c (which includes the ntp adjustment code, leapsecond processing, and ntp kernel state machine code), timesource.c (for timesource specific management functions), interface definition .h files, the example jiffies timesource (lowest common denominator time source, mainly for use as example code) and minimal hooks into arch independent code.

The patch does not function without minimal architecture specific hooks (i386, x86-64, ppc32, ppc64, ia64 and s390 examples to follow), and it should be able to be applied to a tree without affecting the existing code.

New in this version:
o clock_was_set calls
o proper suspend/resume sysfs hooks
o boot time timesource override
o warp_clock implementation
o improved jiffies timesource accuracy from using ACTHZ
o number of minor comment cleanups

Items still on the TODO list:
o Continued Testing
o Final cleanup for submission to Andrew.

Once again, I look forward to your comments and feedback.

thanks
-john

linux-2.6.12-rc4_timeofday-core_A5.patch
========================================

drivers/Makefile (mode:100644) +1 -0
Index: drivers/Makefile
===================================================================
@@ -64,3 +64,4 @@
 obj-$(CONFIG_BLK_DEV_SGIIOC4)	+= sn/
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
+obj-$(CONFIG_NEWTOD)		+= timesource/
drivers/char/hangcheck-timer.c (mode:100644) +5 -0
Index: drivers/char/hangcheck-timer.c
===================================================================
@@ -49,6 +49,7 @@
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <linux/sysrq.h>
+#include <linux/timeofday.h>
 
 
 #define VERSION_STR "0.9.0"
@@ -130,8 +131,12 @@
 #endif
 
 #ifdef HAVE_MONOTONIC
+#ifndef CONFIG_NEWTOD
 extern unsigned long long monotonic_clock(void);
 #else
+#define monotonic_clock() do_monotonic_clock()
+#endif
+#else
 static inline unsigned long long monotonic_clock(void)
 {
 # ifdef __s390__
drivers/timesource/Makefile (mode:100644) renamed from dev/null (tree:eed337ef5e9ae7d62caa84b7974a11fddc7f06e0) +1 -0
Index: drivers/timesource/Makefile
===================================================================
@@ -0,0 +1 @@
+obj-y += jiffies.o
drivers/timesource/jiffies.c (mode:100644) renamed from dev/null (tree:eed337ef5e9ae7d62caa84b7974a11fddc7f06e0) +69 -0

69 lines not on this page · raw message

include/linux/ntp.h (mode:100644) renamed from dev/null (tree:eed337ef5e9ae7d62caa84b7974a11fddc7f06e0) +20 -0
Index: include/linux/ntp.h
===================================================================
@@ -0,0 +1,20 @@
+/*  linux/include/linux/ntp.h
+ *
+ *  This file NTP state machine accessor functions.
+ */
+
+#ifndef _LINUX_NTP_H
+#define _LINUX_NTP_H
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+/* NTP state machine interfaces */
+nsec_t ntp_scale(nsec_t value);
+int ntp_advance(nsec_t value);
+int ntp_adjtimex(struct timex*);
+int ntp_leapsecond(struct timespec now);
+void ntp_clear(void);
+int get_ntp_status(void);
+
+#endif
include/linux/time.h (mode:100644) +4 -0
Index: include/linux/time.h
===================================================================
@@ -27,6 +27,10 @@
 
 #ifdef __KERNEL__
 
+/* timeofday base types */
+typedef u64 nsec_t;
+typedef u64 cycle_t;
+
 /* Parameters used to convert the timespec values */
 #ifndef USEC_PER_SEC
 #define USEC_PER_SEC (1000000L)
include/linux/timeofday.h (mode:100644) renamed from dev/null (tree:eed337ef5e9ae7d62caa84b7974a11fddc7f06e0) +73 -0

73 lines not on this page · raw message

include/linux/timesource.h (mode:100644) renamed from dev/null (tree:eed337ef5e9ae7d62caa84b7974a11fddc7f06e0) +157 -0

157 lines not on this page · raw message

include/linux/timex.h (mode:100644) +2 -0
Index: include/linux/timex.h
===================================================================
@@ -228,6 +228,7 @@
 extern unsigned long tick_nsec;		/* ACTHZ          period (nsec) */
 extern int tickadj;			/* amount of adjustment per tick */
 
+#ifndef CONFIG_NEWTOD
 /*
  * phase-lock loop variables
  */
@@ -314,6 +315,7 @@
 }
 
 #endif /* !CONFIG_TIME_INTERPOLATION */
+#endif /* !CONFIG_NEWTOD */
 
 #endif /* KERNEL */
 
init/main.c (mode:100644) +2 -0
Index: init/main.c
===================================================================
@@ -47,6 +47,7 @@
 #include <linux/rmap.h>
 #include <linux/mempolicy.h>
 #include <linux/key.h>
+#include <linux/timeofday.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -467,6 +468,7 @@
 	pidhash_init();
 	init_timers();
 	softirq_init();
+	timeofday_init();
 	time_init();
 
 	/*
kernel/Makefile (mode:100644) +1 -0
Index: kernel/Makefile
===================================================================
@@ -9,6 +9,7 @@
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o
 
+obj-$(CONFIG_NEWTOD) += timeofday.o timesource.o ntp.o
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o spinlock.o
kernel/ntp.c (mode:100644) renamed from dev/null (tree:eed337ef5e9ae7d62caa84b7974a11fddc7f06e0) +520 -0

520 lines not on this page · raw message

kernel/time.c (mode:100644) +18 -0
Index: kernel/time.c
===================================================================
@@ -38,6 +38,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <linux/timeofday.h>
 
 /* 
  * The timezone where the local system is located.  Used as a default by some
@@ -128,6 +129,7 @@
  * as real UNIX machines always do it. This avoids all headaches about
  * daylight saving times and warping kernel clocks.
  */
+#ifndef CONFIG_NEWTOD
 inline static void warp_clock(void)
 {
 	write_seqlock_irq(&xtime_lock);
@@ -137,6 +139,18 @@
 	write_sequnlock_irq(&xtime_lock);
 	clock_was_set();
 }
+#else /* !CONFIG_NEWTOD */
+/* XXX - this is somewhat cracked out and should
+         be checked  [email protected]
+*/
+inline static void warp_clock(void)
+{
+	struct timespec ts;
+	getnstimeofday(&ts);
+	ts.tv_sec += sys_tz.tz_minuteswest * 60;
+	do_settimeofday(&ts);
+}
+#endif /* !CONFIG_NEWTOD */
 
 /*
  * In case for some reason the CMOS clock has not already been running
@@ -227,6 +241,7 @@
 /* adjtimex mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
+#ifndef CONFIG_NEWTOD
 int do_adjtimex(struct timex *txc)
 {
         long ltemp, mtemp, save_adjust;
@@ -410,6 +425,7 @@
 	notify_arch_cmos_timer();
 	return(result);
 }
+#endif /* !CONFIG_NEWTOD */
 
 asmlinkage long sys_adjtimex(struct timex __user *txc_p)
 {
@@ -558,6 +574,7 @@
 
 
 #else
+#ifndef CONFIG_NEWTOD
 /*
  * Simulate gettimeofday using do_gettimeofday which only allows a timeval
  * and therefore only yields usec accuracy
@@ -570,6 +587,7 @@
 	tv->tv_sec = x.tv_sec;
 	tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
 }
+#endif /* !CONFIG_NEWTOD */
 #endif
 
 #if (BITS_PER_LONG < 64)
kernel/timeofday.c (mode:100644) renamed from dev/null (tree:eed337ef5e9ae7d62caa84b7974a11fddc7f06e0) +603 -0

603 lines not on this page · raw message

kernel/timer.c (mode:100644) +4 -0
Index: kernel/timer.c
===================================================================
@@ -577,6 +577,7 @@
 int tickadj = 500/HZ ? : 1;		/* microsecs */
 
 
+#ifndef CONFIG_NEWTOD
 /*
  * phase-lock loop variables
  */
@@ -807,6 +808,9 @@
 		}
 	} while (ticks);
 }
+#else /* !CONFIG_NEWTOD */
+#define update_wall_time(x)
+#endif /* !CONFIG_NEWTOD */
 
 /*
  * Called from the timer interrupt handler to charge one tick to the current 
kernel/timesource.c (mode:100644) renamed from dev/null (tree:eed337ef5e9ae7d62caa84b7974a11fddc7f06e0) +237 -0

237 lines not on this page · raw message

#1 lore raw

RFC PATCH 1/1 new timeofday i386 arch specific changes (v A5)

All,
This patch converts the i386 arch to use the new timeofday
infrastructure. It applies ontop of my linux-2.6.12-rc4_timeofday- core_A5 patch. This is a full conversion, so most of this patch is subtractions removing the existing arch specific time keeping code. This patch does not provide any i386 timesources, so using this patch alone ontop of the timeofday-core patch will only give you the jiffies timesource. To get full replacements for the code being removed here, the following timeofday-timesources-i386 patch will need to be applied.

I intend to send this patch along with the timeofday-core patch to Andrew at the end of this month for testing in his tree. So please, if you have any complaints, suggestions, or blocking issues, let me know.

New in this version:
o This patch was broken out of the multi-arch timeofday-arch_A4 patch
o Removed #ifdefs and fully converted i386 to use the new timeofday code.

Todo Items:
o Further cleanups and re-arainging in arch/i386/kernel/time.c of the reminants of the arch specific time keeping code

thanks
-john

linux-2.6.12-rc4_timeofday-arch-i386_A5.patch
=============================================

arch/i386/Kconfig (mode:100644) +5 -0
Index: arch/i386/Kconfig
===================================================================
@@ -14,6 +14,11 @@
 	  486, 586, Pentiums, and various instruction-set-compatible chips by
 	  AMD, Cyrix, and others.
 
+config NEWTOD
+	bool
+	default y
+
+
 config MMU
 	bool
 	default y
arch/i386/kernel/Makefile (mode:100644) +1 -2
Index: arch/i386/kernel/Makefile
===================================================================
@@ -7,10 +7,9 @@
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
 		pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
-		doublefault.o quirks.o
+		doublefault.o quirks.o tsc.o
 
 obj-y				+= cpu/
-obj-y				+= timers/
 obj-$(CONFIG_ACPI_BOOT)		+= acpi/
 obj-$(CONFIG_X86_BIOS_REBOOT)	+= reboot.o
 obj-$(CONFIG_MCA)		+= mca.o
arch/i386/kernel/i8259.c (mode:100644) +42 -0

48 lines not on this page · raw message

arch/i386/kernel/setup.c (mode:100644) +1 -0
Index: arch/i386/kernel/setup.c
===================================================================
@@ -1523,6 +1523,7 @@
 	conswitchp = &dummy_con;
 #endif
 #endif
+	tsc_init();
 }
 
 #include "setup_arch_post.h"
arch/i386/kernel/time.c (mode:100644) +35 -180

308 lines not on this page · raw message

dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/Makefile (mode:100644) +0 -9
Index: arch/i386/kernel/timers/Makefile
===================================================================
@@ -1,9 +0,0 @@
-#
-# Makefile for x86 timers
-#
-
-obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o common.o
-
-obj-$(CONFIG_X86_CYCLONE_TIMER)	+= timer_cyclone.o
-obj-$(CONFIG_HPET_TIMER)	+= timer_hpet.o
-obj-$(CONFIG_X86_PM_TIMER)	+= timer_pm.o
dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/common.c (mode:100644) +0 -160

160 lines not on this page · raw message

dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/timer.c (mode:100644) +0 -66

66 lines not on this page · raw message

dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/timer_cyclone.c (mode:100644) +0 -259

259 lines not on this page · raw message

dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/timer_hpet.c (mode:100644) +0 -194

194 lines not on this page · raw message

dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/timer_none.c (mode:100644) +0 -39
Index: arch/i386/kernel/timers/timer_none.c
===================================================================
@@ -1,39 +0,0 @@
-#include <linux/init.h>
-#include <asm/timer.h>
-
-static void mark_offset_none(void)
-{
-	/* nothing needed */
-}
-
-static unsigned long get_offset_none(void)
-{
-	return 0;
-}
-
-static unsigned long long monotonic_clock_none(void)
-{
-	return 0;
-}
-
-static void delay_none(unsigned long loops)
-{
-	int d0;
-	__asm__ __volatile__(
-		"\tjmp 1f\n"
-		".align 16\n"
-		"1:\tjmp 2f\n"
-		".align 16\n"
-		"2:\tdecl %0\n\tjns 2b"
-		:"=&a" (d0)
-		:"0" (loops));
-}
-
-/* none timer_opts struct */
-struct timer_opts timer_none = {
-	.name = 	"none",
-	.mark_offset =	mark_offset_none, 
-	.get_offset =	get_offset_none,
-	.monotonic_clock =	monotonic_clock_none,
-	.delay = delay_none,
-};
dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/timer_pit.c (mode:100644) +0 -206

206 lines not on this page · raw message

dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/timer_pm.c (mode:100644) +0 -258

258 lines not on this page · raw message

dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) renamed from arch/i386/kernel/timers/timer_tsc.c (mode:100644) +0 -560

560 lines not on this page · raw message

arch/i386/kernel/tsc.c (mode:100644) renamed from dev/null (tree:d68b09f31fa98801ead715e9281a2e4676b770a5) +163 -0

163 lines not on this page · raw message

arch/i386/lib/delay.c (mode:100644) +13 -3
Index: arch/i386/lib/delay.c
===================================================================
@@ -13,6 +13,7 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
+#include <linux/timeofday.h>
 #include <asm/processor.h>
 #include <asm/delay.h>
 #include <asm/timer.h>
@@ -21,11 +22,20 @@
 #include <asm/smp.h>
 #endif
 
-extern struct timer_opts* timer;
-
+/* XXX - For now just use a simple loop delay
+ *  This has cpufreq issues, but so did the old method.
+ */
 void __delay(unsigned long loops)
 {
-	cur_timer->delay(loops);
+	int d0;
+	__asm__ __volatile__(
+		"\tjmp 1f\n"
+		".align 16\n"
+		"1:\tjmp 2f\n"
+		".align 16\n"
+		"2:\tdecl %0\n\tjns 2b"
+		:"=&a" (d0)
+		:"0" (loops));
 }
 
 inline void __const_udelay(unsigned long xloops)
include/asm-i386/mach-default/mach_timer.h (mode:100644) +5 -1
Index: include/asm-i386/mach-default/mach_timer.h
===================================================================
@@ -14,8 +14,12 @@
  */
 #ifndef _MACH_TIMER_H
 #define _MACH_TIMER_H
+#include <linux/jiffies.h>
+#include <asm/io.h>
 
-#define CALIBRATE_LATCH	(5 * LATCH)
+#define CALIBRATE_ITERATION 50
+#define CALIBRATE_LATCH	(CALIBRATE_ITERATION * LATCH)
+#define CALIBRATE_TIME	(CALIBRATE_ITERATION * 1000020/HZ)
 
 static inline void mach_prepare_counter(void)
 {
include/asm-i386/timer.h (mode:100644) +0 -53

63 lines not on this page · raw message

include/asm-i386/timex.h (mode:100644) +3 -0
Index: include/asm-i386/timex.h
===================================================================
@@ -16,6 +16,8 @@
 #endif
 
 
+/* XXX - All of this should likely move elsewhere [email protected]*/
+
 /*
  * Standard way to access the cycle counter on i586+ CPUs.
  * Currently only used on SMP.
@@ -48,5 +50,6 @@
 }
 
 extern unsigned long cpu_khz;
+extern void tsc_init(void);
 
 #endif
#2 lore raw

RFC PATCH 1/1 new timeofday x86-64 specific changes (v A5)

All,
This patch converts the x86-64 arch to use the new timeofday
infrastructure. It applies on top of my linux-2.6.12-rc4_timeofday- core_A5 patch. This is a full conversion, so most of this patch is subtractions removing the existing arch specific time keeping code. This patch does not provide any x86-64 timesources, so using this patch alone ontop of the timeofday-core patch will only give you the jiffies timesource. To get full replacements for the code being removed here, the following timeofday-timesources-i386 patch (x86-64 shares the same timesources as i386) will need to be applied.

I would like to send this patch along with the timeofday-core patch to Andrew at the end of this month for testing in his tree. So please, if you have any complaints, suggestions, or blocking issues, let me know.

New in this version:
o This patch was broken out of the multi-arch timeofday-arch_A4 patch
o Removed #ifdefs and fully converted x86-64 to use the new timeofday code.
o Integrated the proof of concept vsyscall implementation

Todo Items:
o Further cleanups and re-arranging in arch/x86-64/kernel/time.c of the remnants of the arch specific time keeping code
o Further removal of the old vsyscall code.

thanks
-john

linux-2.6.12-rc4_timeofday-arch-x86-64_A5.patch
===============================================

arch/i386/kernel/acpi/boot.c (mode:100644) +3 -9
Index: arch/i386/kernel/acpi/boot.c
===================================================================
@@ -547,7 +547,7 @@
 
 
 #ifdef CONFIG_HPET_TIMER
-
+#include <asm/hpet.h>
 static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
 {
 	struct acpi_table_hpet *hpet_tbl;
@@ -570,18 +570,12 @@
 #ifdef	CONFIG_X86_64
         vxtime.hpet_address = hpet_tbl->addr.addrl |
                 ((long) hpet_tbl->addr.addrh << 32);
-
-        printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
-               hpet_tbl->id, vxtime.hpet_address);
+	hpet_address = vxtime.hpet_address;
 #else	/* X86 */
-	{
-		extern unsigned long hpet_address;
-
 		hpet_address = hpet_tbl->addr.addrl;
+#endif	/* X86 */
 		printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
 			hpet_tbl->id, hpet_address);
-	}
-#endif	/* X86 */
 
 	return 0;
 }
arch/x86_64/Kconfig (mode:100644) +8 -0
Index: arch/x86_64/Kconfig
===================================================================
@@ -24,6 +24,14 @@
 	bool
 	default y
 
+config NEWTOD
+	bool
+	default y
+
+config NEWTOD_VSYSCALL
+	bool
+	default y
+
 config MMU
 	bool
 	default y
arch/x86_64/kernel/time.c (mode:100644) +26 -266

360 lines not on this page · raw message

arch/x86_64/kernel/vmlinux.lds.S (mode:100644) +7 -0
Index: arch/x86_64/kernel/vmlinux.lds.S
===================================================================
@@ -71,6 +71,13 @@
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   .jiffies : AT CACHE_ALIGN(AFTER(.xtime)) { *(.jiffies) }
   jiffies = LOADADDR(.jiffies);
+
+  .vsyscall_gtod_data : AT AFTER(.jiffies) { *(.vsyscall_gtod_data) }
+  vsyscall_gtod_data = LOADADDR(.vsyscall_gtod_data);
+  .vsyscall_gtod_lock : AT AFTER(.vsyscall_gtod_data) { *(.vsyscall_gtod_lock) }
+  vsyscall_gtod_lock = LOADADDR(.vsyscall_gtod_lock);
+
+
   .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) }
   . = LOADADDR(.vsyscall_0) + 4096;
 
arch/x86_64/kernel/vsyscall.c (mode:100644) +103 -30

176 lines not on this page · raw message

include/asm-generic/div64.h (mode:100644) +9 -0
Index: include/asm-generic/div64.h
===================================================================
@@ -55,4 +55,13 @@
 
 #endif /* BITS_PER_LONG */
 
+#ifndef div_long_long_rem
+#define div_long_long_rem(dividend,divisor,remainder) \
+({							\
+	u64 result = dividend;				\
+	*remainder = do_div(result,divisor);		\
+	result;						\
+})
+#endif
+
 #endif /* _ASM_GENERIC_DIV64_H */
include/asm-x86_64/hpet.h (mode:100644) +2 -1
Index: include/asm-x86_64/hpet.h
===================================================================
@@ -1,6 +1,6 @@
 #ifndef _ASM_X8664_HPET_H
 #define _ASM_X8664_HPET_H 1
-
+#include <asm/fixmap.h>
 /*
  * Documentation on HPET can be found at:
  *      http://www.intel.com/ial/home/sp/pcmmspec.htm
@@ -44,6 +44,7 @@
 #define HPET_TN_SETVAL		0x040
 #define HPET_TN_32BIT		0x100
 
+extern unsigned long hpet_address;	/* hpet memory map physical address */
 extern int is_hpet_enabled(void);
 extern int hpet_rtc_timer_init(void);
 extern int oem_force_hpet_timer(void);
include/asm-x86_64/vsyscall.h (mode:100644) +2 -0
Index: include/asm-x86_64/vsyscall.h
===================================================================
@@ -22,6 +22,8 @@
 #define __section_sysctl_vsyscall __attribute__ ((unused, __section__ (".sysctl_vsyscall"), aligned(16)))
 #define __section_xtime __attribute__ ((unused, __section__ (".xtime"), aligned(16)))
 #define __section_xtime_lock __attribute__ ((unused, __section__ (".xtime_lock"), aligned(16)))
+#define __section_vsyscall_gtod_data __attribute__ ((unused, __section__ (".vsyscall_gtod_data"),aligned(16)))
+#define __section_vsyscall_gtod_lock __attribute__ ((unused, __section__ (".vsyscall_gtod_lock"),aligned(16)))
 
 #define VXTIME_TSC	1
 #define VXTIME_HPET	2
#3 lore raw

RFC PATCH 1/1 new timeofday i386 and x86-64 timesources (v A5)

All,
This patch implements the time sources shared between i386 and x86-64
(acpi_pm, cyclone, hpet, pit, tsc and tsc-interp). The patch should apply ontop of either linux-2.6.12-rc4_timeofday-arch-x86-64_A5.patch or linux-2.6.12-rc4_timeofday-arch-i386_A5.patch.

The patch should be fairly straight forward, only adding the new
timesources.

I intend to send this patch along with the timeofday-core and
timeofday-arch-i386 patches to Andrew at the end of this month for testing in his tree. So please, if you have any complaints, suggestions, or blocking issues, let me know.

New in this release:
o i386_pit timesource has been fixed and properly works now
o New code to handle TSC stalls on cpus that halt the TSC in C3 mode
o A new TSC/Jiffies interpolation example.

This new tsc-interp timesource provides the same interpolated timekeeping method as was used previously in the i386 arch specific time code. This should also quiet fears about the TSC timesource not being stable enough for embedded systems.

Items still on the TODO list:
o make acpi-pm and pit x86-64 compatible
o make cyclone ia64 generic

I look forward to your comments and feedback.

thanks
-john

linux-2.6.12-rc4_timeofday-timesources-i386_A5.patch
====================================================

drivers/acpi/processor_idle.c (mode:100644) +5 -0
Index: drivers/acpi/processor_idle.c
===================================================================
@@ -162,6 +162,7 @@
 	return;
 }
 
+extern void tsc_c3_compensate(unsigned long usecs);
 
 static void acpi_processor_idle (void)
 {
@@ -309,6 +310,10 @@
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
 		/* Enable bus master arbitration */
 		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK);
+
+		/* compensate for TSC pause */
+		tsc_c3_compensate(((t2-t1)*286)>>10);
+
 		/* Re-enable interrupts */
 		local_irq_enable();
 		/* Compute time (ticks) that we were actually asleep */
drivers/timesource/Makefile (mode:100644) +6 -0
Index: drivers/timesource/Makefile
===================================================================
@@ -1 +1,7 @@
 obj-y += jiffies.o
+obj-$(CONFIG_X86) += tsc.o
+obj-$(CONFIG_X86) += i386_pit.o
+obj-$(CONFIG_X86) += tsc-interp.o
+obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
+obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
+obj-$(CONFIG_HPET_TIMER) += hpet.o
drivers/timesource/acpi_pm.c (mode:100644) renamed from dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) +135 -0

135 lines not on this page · raw message

drivers/timesource/cyclone.c (mode:100644) renamed from dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) +135 -0

135 lines not on this page · raw message

drivers/timesource/hpet.c (mode:100644) renamed from dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) +59 -0

59 lines not on this page · raw message

drivers/timesource/i386_pit.c (mode:100644) renamed from dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) +64 -0

64 lines not on this page · raw message

drivers/timesource/tsc-interp.c (mode:100644) renamed from dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) +108 -0

108 lines not on this page · raw message

drivers/timesource/tsc.c (mode:100644) renamed from dev/null (tree:0feb50d39a18b8a58ac2894eeac9b2f24a3b4435) +95 -0

95 lines not on this page · raw message

#4 lore raw

RFC PATCH 1/1 new timeofday ia64,ppc32,ppc64 and s390 arch specific hooks (v A5)

All,
This patch implements the minimal architecture specific hooks to enable
the new time of day subsystem code for ia64, ppc32, ppc64 and s390. It applies on top of my linux-2.6.12-rc4_timeofday-core_A5 patch and with this patch applied, you can test the new time of day subsystem on these arches.

Basically it configs in the NEWTOD code and cuts alot of code out of
the build via #ifdefs. I know, I know, #ifdefs' are ugly and bad, and the final patch for each arch will just remove the old code. Don't worry, I'm not going to push this to Andrew anytime soon. For now this allows us to be flexible and easily switch between the two implementations with a single define.

This code is largely untested, but I tried to make sure ia64, ppc32 and ppc64 compiled without warnings.

I'd like to thank the following folks for their work in providing these arch implementations:
o Max Asbock for the ia64 work
o Darrick Wong for the ppc32 work
o Martin Schwidefsky! for the s390 work

Items still on the TODO list:
o More testing
o arch specific vsyscall/fsyscall interface
o other arch ports

I look forward to your comments and feedback.

thanks
-john

linux-2.6.12-rc4_timeofday-arch-other_A5.patch
==============================================

arch/ia64/Kconfig (mode:100644) +5 -1
Index: arch/ia64/Kconfig
===================================================================
@@ -18,6 +18,10 @@
 	  page at <http://www.linuxia64.org/> and a mailing list at
 	  <[email protected]>.
 
+config NEWTOD
+        bool
+        default y
+
 config 64BIT
 	bool
 	default y
@@ -36,7 +40,7 @@
 
 config TIME_INTERPOLATION
 	bool
-	default y
+	default n
 
 config EFI
 	bool
arch/ia64/kernel/asm-offsets.c (mode:100644) +2 -0
Index: arch/ia64/kernel/asm-offsets.c
===================================================================
@@ -222,6 +222,7 @@
 	DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET,
 	       offsetof (struct ia64_mca_cpu, init_stack));
 	BLANK();
+#ifndef CONFIG_NEWTOD
 	/* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
 	DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr));
 	DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source));
@@ -235,5 +236,6 @@
 	DEFINE(IA64_TIME_SOURCE_CPU, TIME_SOURCE_CPU);
 	DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64);
 	DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32);
+#endif /* CONFIG_NEWTOD */
 	DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 }
arch/ia64/kernel/cyclone.c (mode:100644) +2 -1
Index: arch/ia64/kernel/cyclone.c
===================================================================
@@ -17,7 +17,7 @@
 	use_cyclone = 1;
 }
 
-
+#ifndef CONFIG_NEWTOD
 struct time_interpolator cyclone_interpolator = {
 	.source =	TIME_SOURCE_MMIO64,
 	.shift =	16,
@@ -107,3 +107,4 @@
 }
 
 __initcall(init_cyclone_clock);
+#endif /* !CONFIG_NEWTOD */
arch/ia64/kernel/fsys.S (mode:100644) +12 -0
Index: arch/ia64/kernel/fsys.S
===================================================================
@@ -145,6 +145,7 @@
 	FSYS_RETURN
 END(fsys_set_tid_address)
 
+#ifndef CONFIG_NEWTOD
 /*
  * Ensure that the time interpolator structure is compatible with the asm code
  */
@@ -326,6 +327,7 @@
 EX(.fail_efault, st8 [r31] = r9)
 EX(.fail_efault, st8 [r23] = r21)
 	FSYS_RETURN
+#endif /* !CONFIG_NEWTOD */
 .fail_einval:
 	mov r8 = EINVAL
 	mov r10 = -1
@@ -334,6 +336,7 @@
 	mov r8 = EFAULT
 	mov r10 = -1
 	FSYS_RETURN
+#ifndef CONFIG_NEWTOD
 END(fsys_gettimeofday)
 
 ENTRY(fsys_clock_gettime)
@@ -347,6 +350,7 @@
 	shl r30 = r32,15
 	br.many .gettime
 END(fsys_clock_gettime)
+#endif /* !CONFIG_NEWTOD */
 
 /*
  * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize).
@@ -689,7 +693,11 @@
 	data8 0				// setrlimit
 	data8 0				// getrlimit		// 1085
 	data8 0				// getrusage
+#ifdef CONFIG_NEWTOD
+	data8 0				// gettimeofday
+#else
 	data8 fsys_gettimeofday		// gettimeofday
+#endif
 	data8 0				// settimeofday
 	data8 0				// select
 	data8 0				// poll			// 1090
@@ -856,7 +864,11 @@
 	data8 0				// timer_getoverrun
 	data8 0				// timer_delete
 	data8 0				// clock_settime
+#ifdef CONFIG_NEWTOD
+	data8 0				// clock_gettime
+#else
 	data8 fsys_clock_gettime	// clock_gettime
+#endif
 	data8 0				// clock_getres		// 1255
 	data8 0				// clock_nanosleep
 	data8 0				// fstatfs64
arch/ia64/kernel/time.c (mode:100644) +19 -0
Index: arch/ia64/kernel/time.c
===================================================================
@@ -21,6 +21,7 @@
 #include <linux/efi.h>
 #include <linux/profile.h>
 #include <linux/timex.h>
+#include <linux/timeofday.h>
 
 #include <asm/machvec.h>
 #include <asm/delay.h>
@@ -45,11 +46,13 @@
 
 #endif
 
+#ifndef CONFIG_NEWTOD
 static struct time_interpolator itc_interpolator = {
 	.shift = 16,
 	.mask = 0xffffffffffffffffLL,
 	.source = TIME_SOURCE_CPU
 };
+#endif /* CONFIG_NEWTOD */
 
 static irqreturn_t
 timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
@@ -211,6 +214,7 @@
 	local_cpu_data->nsec_per_cyc = ((NSEC_PER_SEC<<IA64_NSEC_PER_CYC_SHIFT)
 					+ itc_freq/2)/itc_freq;
 
+#ifndef CONFIG_NEWTOD
 	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
 		itc_interpolator.frequency = local_cpu_data->itc_freq;
 		itc_interpolator.drift = itc_drift;
@@ -229,6 +233,7 @@
 #endif
 		register_time_interpolator(&itc_interpolator);
 	}
+#endif /* CONFIG_NEWTOD */
 
 	/* Setup the CPU local timer tick */
 	ia64_cpu_local_tick();
@@ -253,3 +258,17 @@
 	 */
 	set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
 }
+
+/* arch specific timeofday hooks */
+nsec_t read_persistent_clock(void)
+{
+        struct timespec ts;
+        efi_gettimeofday(&ts);
+        return (nsec_t)(ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec);
+}
+
+void sync_persistent_clock(struct timespec ts)
+{
+	/* XXX - Something should go here, no? */
+}
+
arch/ia64/sn/kernel/sn2/timer.c (mode:100644) +6 -0
Index: arch/ia64/sn/kernel/sn2/timer.c
===================================================================
@@ -19,6 +19,7 @@
 #include <asm/sn/shub_mmr.h>
 #include <asm/sn/clksupport.h>
 
+#ifndef CONFIG_NEWTOD
 extern unsigned long sn_rtc_cycles_per_second;
 
 static struct time_interpolator sn2_interpolator = {
@@ -34,3 +35,8 @@
 	sn2_interpolator.addr = RTC_COUNTER_ADDR;
 	register_time_interpolator(&sn2_interpolator);
 }
+#else
+void __init sn_timer_init(void)
+{
+}
+#endif
arch/ppc/Kconfig (mode:100644) +4 -0
Index: arch/ppc/Kconfig
===================================================================
@@ -8,6 +8,10 @@
 	bool
 	default y
 
+config NEWTOD
+	bool
+	default y
+
 config UID16
 	bool
 
arch/ppc/kernel/time.c (mode:100644) +47 -0

89 lines not on this page · raw message

arch/ppc64/Kconfig (mode:100644) +4 -0
Index: arch/ppc64/Kconfig
===================================================================
@@ -10,6 +10,10 @@
 	bool
 	default y
 
+config NEWTOD
+	bool
+	default y
+
 config UID16
 	bool
 
arch/ppc64/kernel/sys_ppc32.c (mode:100644) +2 -0
Index: arch/ppc64/kernel/sys_ppc32.c
===================================================================
@@ -322,8 +322,10 @@
 
 	ret = do_adjtimex(&txc);
 
+#ifndef CONFIG_NEWTOD
 	/* adjust the conversion of TB to time of day to track adjtimex */
 	ppc_adjtimex();
+#endif
 
 	if(put_user(txc.modes, &utp->modes) ||
 	   __put_user(txc.offset, &utp->offset) ||
arch/ppc64/kernel/time.c (mode:100644) +60 -0

132 lines not on this page · raw message

arch/s390/Kconfig (mode:100644) +4 -0
Index: arch/s390/Kconfig
===================================================================
@@ -127,6 +127,10 @@
 	  This allows you to run 32-bit Linux/ELF binaries on your zSeries
 	  in 64 bit mode. Everybody wants this; say Y.
 
+config NEWTOD
+	bool
+	default y
+
 comment "Code generation options"
 
 choice
arch/s390/kernel/time.c (mode:100644) +22 -0
Index: arch/s390/kernel/time.c
===================================================================
@@ -29,6 +29,7 @@
 #include <linux/profile.h>
 #include <linux/timex.h>
 #include <linux/notifier.h>
+#include <linux/timeofday.h>
 
 #include <asm/uaccess.h>
 #include <asm/delay.h>
@@ -89,6 +90,7 @@
 	return (unsigned long) now;
 }
 
+#ifndef CONFIG_NEWTOD
 /*
  * This version of gettimeofday has microsecond resolution.
  */
@@ -149,7 +151,27 @@
 }
 
 EXPORT_SYMBOL(do_settimeofday);
+#endif
+
+nsec_t read_persistent_clock(void)
+{
+	unsigned long long nsecs;
+	/*
+	 * The TOD clock counts from 1900-01-01. Bit 2^12 of the
+	 * 64 bit register is micro-seconds.
+	 */
+	nsecs = get_clock() - 0x7d91048bca000000LL;
+	/*
+	 * Calc nsecs * 1000 / 4096 without overflow and
+	 * without loosing too many bits.
+	 */
+	nsecs = (((((nsecs >> 3) * 5) >> 3) * 5) >> 3) * 5;
+	return (nsec_t) nsecs;
+}
 
+void sync_persistent_clock(struct timespec ts)
+{
+}
 
 #ifdef CONFIG_PROFILING
 #define s390_do_profile(regs)	profile_tick(CPU_PROFILING, regs)
include/asm-ppc64/time.h (mode:100644) +1 -0
Index: include/asm-ppc64/time.h
===================================================================
@@ -21,6 +21,7 @@
 #include <asm/processor.h>
 #include <asm/paca.h>
 #include <asm/iSeries/HvCall.h>
+#include <asm/percpu.h>
 
 /* time.c */
 extern unsigned long tb_ticks_per_jiffy;
#5 lore raw

RFC PATCH 1/1 new timeofday ia64,ppc32,ppc64 and s390 timesources (v A5)

All,
This patch implements the time sources for ppc32, ppc64, s390 and
initial untested sketches of timesources for ia64. The patch should apply ontop of linux-2.6.12-rc4_timeofday-arch-other_A5. The patch should be fairly straight forward, only adding the new timesources.

I'd like to thank the following folks for their work in providing these arch implementations:
o Darrick Wong for the ppc32 work
o Martin Schwidefsky! for the s390 work

New in this release:
o minor fixes for compile warnings

Items still on the TODO list:
o real ia64 timesources
o all other arch timesources
o lots of cleanups
o lots of testing

I look forward to your comments and feedback.

thanks
-john

linux-2.6.12-rc4_timeofday-timesources-other_A5.patch
======================================================

drivers/timesource/Makefile (mode:100644) +8 -0
Index: drivers/timesource/Makefile
===================================================================
@@ -1 +1,9 @@
 obj-y += jiffies.o
+
+obj-$(CONFIG_PPC64) += ppc64_timebase.o
+obj-$(CONFIG_PPC) += ppc_timebase.o
+obj-$(CONFIG_ARCH_S390) += s390_tod.o
+
+# XXX - Untested/Uncompiled
+#obj-$(CONFIG_IA64) += itc.c
+#obj-$(CONFIG_IA64_SGI_SN2) += sn2_rtc.c
drivers/timesource/itc.c (mode:100644) renamed from dev/null (tree:f86144e80c5de25e7bea135a07a5635205be4cf3) +35 -0
Index: drivers/timesource/itc.c
===================================================================
@@ -0,0 +1,35 @@
+/* XXX - this is totally untested and uncompiled
+ * TODO:
+ *		o cpufreq issues
+ *		o unsynched ITCs ?
+ */
+#include <linux/timesource.h>
+
+/* XXX - Other includes needed for:
+ *		sal_platform_features, IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT,
+ *		local_cpu_data->itc_freq
+ * See arch/ia64/kernel/time.c for ideas
+ */
+
+static struct timesource_t timesource_itc = {
+	.name = "itc",
+	.priority = 25,
+	.type = TIMESOURCE_CYCLES,
+	.mask = (cycle_t)-1,
+	.mult = 0, /* to be set */
+	.shift = 22,
+};
+
+static int __init init_itc_timesource(void)
+{
+	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
+		/* XXX - I'm not really sure if itc_freq is in cyc/sec */
+		timesource_itc.mult = timesource_hz2mult(local_cpu_data->itc_freq,
+									timesource_itc.shift);
+		register_timesource(&timesource_itc);
+	}
+	return 0;
+}
+
+module_init(init_itc_timesource);
+
drivers/timesource/ppc64_timebase.c (mode:100644) renamed from dev/null (tree:f86144e80c5de25e7bea135a07a5635205be4cf3) +33 -0
Index: drivers/timesource/ppc64_timebase.c
===================================================================
@@ -0,0 +1,33 @@
+#include <linux/timesource.h>
+#include <asm/time.h>
+
+static cycle_t timebase_read(void)
+{
+	return (cycle_t)get_tb();
+}
+
+struct timesource_t timesource_timebase = {
+	.name = "timebase",
+	.priority = 200,
+	.type = TIMESOURCE_FUNCTION,
+	.read_fnct = timebase_read,
+	.mask = (cycle_t)-1,
+	.mult = 0,
+	.shift = 22,
+};
+
+
+/* XXX - this should be calculated or properly externed! */
+extern unsigned long tb_to_ns_scale;
+extern unsigned long tb_to_ns_shift;
+extern unsigned long tb_ticks_per_sec;
+
+static int __init init_timebase_timesource(void)
+{
+	timesource_timebase.mult = timesource_hz2mult(tb_ticks_per_sec,
+										timesource_timebase.shift);
+	register_timesource(&timesource_timebase);
+	return 0;
+}
+
+module_init(init_timebase_timesource);
drivers/timesource/ppc_timebase.c (mode:100644) renamed from dev/null (tree:f86144e80c5de25e7bea135a07a5635205be4cf3) +56 -0

56 lines not on this page · raw message

drivers/timesource/s390_tod.c (mode:100644) renamed from dev/null (tree:f86144e80c5de25e7bea135a07a5635205be4cf3) +37 -0
Index: drivers/timesource/s390_tod.c
===================================================================
@@ -0,0 +1,37 @@
+/*
+ * linux/drivers/timesource/s390_tod.c
+ *
+ * (C) Copyright IBM Corp. 2004
+ *
+ * Author(s): Martin Schwidefsky ([email protected]),
+ *
+ * s390 TOD clock time source.
+ */
+
+#include <linux/timesource.h>
+#include <linux/timex.h>
+#include <linux/init.h>
+
+static cycle_t s390_tod_read(void)
+{
+	return get_clock();
+}
+
+struct timesource_t timesource_s390_tod = {
+	.name = "TOD",
+	.priority = 100,
+	.type = TIMESOURCE_FUNCTION,
+	.read_fnct = s390_tod_read,
+	.mask = -1ULL,
+	.mult = 1000,
+	.shift = 12
+};
+
+
+static int __init init_s390_timesource(void)
+{
+	register_timesource(&timesource_s390_tod);
+	return 0;
+}
+
+module_init(init_s390_timesource);
drivers/timesource/sn2_rtc.c (mode:100644) renamed from dev/null (tree:f86144e80c5de25e7bea135a07a5635205be4cf3) +29 -0
Index: drivers/timesource/sn2_rtc.c
===================================================================
@@ -0,0 +1,29 @@
+#include <linux/timesource.h>
+/* XXX this will need some includes
+ * to find: sn_rtc_cycles_per_second and RTC_COUNTER_ADDR
+ * See arch/ia64/sn/kernel/sn2/timer.c for likely suspects
+ */
+
+#define SN2_RTC_MASK ((1LL << 55) - 1)
+#define SN2_SHIFT 10
+
+struct timesource_t timesource_sn2_rtc = {
+	.name = "sn2_rtc",
+	.priority = 300, /* XXX - not sure what this should be */
+	.type = TIMESOURCE_MMIO_64,
+	.mmio_ptr = NULL,
+	.mask = (cycle_t)SN2_RTC_MASK,
+	.mult = 0, /* set below */
+	.shift = SN2_SHIFT,
+};
+
+static void __init init_sn2_timesource(void)
+{
+	timesource_sn2_rtc.mult = timesource_hz2mult(sn_rtc_cycles_per_second,
+												SN2_SHIFT);
+	timesource_sn2_rtc.mmio_ptr = RTC_COUNTER_ADDR;
+
+	register_time_interpolator(&timesource_sn2_rtc);
+	return 0;
+}
+module_init(init_sn2_timesource);
#6 lore raw

RFC PATCH 1/1 new timeofday i386 vsyscall proof of concept (v A5)

All,

This patch implements vsyscall-gettimeofday() functions for i386
using the new timeofday core code. This is just a hackish proof of concept that shows how it could be done and what interfaces are needed to have a clean separation of the arch independent time keeping and the very arch specific vsyscall code. It should apply on top of my linux-2.6.12-rc4_timeofday-timesources-i386_A5 patch.

I look forward to your comments and feedback.

thanks
-john

linux-2.6.12-rc4_timeofday-vsyscall-i386_A5.patch
=================================================

arch/i386/Kconfig (mode:100644) +3 -0
Index: arch/i386/Kconfig
===================================================================
@@ -18,6 +18,9 @@
 	bool
 	default y
 
+config NEWTOD_VSYSCALL
+	depends on EXPERIMENTAL
+	bool "VSYSCALL gettimeofday() interface"
 
 config MMU
 	bool
arch/i386/kernel/Makefile (mode:100644) +1 -0
Index: arch/i386/kernel/Makefile
===================================================================
@@ -10,6 +10,7 @@
 		doublefault.o quirks.o tsc.o
 
 obj-y				+= cpu/
+obj-$(CONFIG_NEWTOD_VSYSCALL)	+= vsyscall-gtod.o
 obj-$(CONFIG_ACPI_BOOT)		+= acpi/
 obj-$(CONFIG_X86_BIOS_REBOOT)	+= reboot.o
 obj-$(CONFIG_MCA)		+= mca.o
arch/i386/kernel/setup.c (mode:100644) +2 -0
Index: arch/i386/kernel/setup.c
===================================================================
@@ -50,6 +50,7 @@
 #include <asm/io_apic.h>
 #include <asm/ist.h>
 #include <asm/io.h>
+#include <asm/vsyscall-gtod.h>
 #include "setup_arch_pre.h"
 #include <bios_ebda.h>
 
@@ -1524,6 +1525,7 @@
 #endif
 #endif
 	tsc_init();
+	vsyscall_init();
 }
 
 #include "setup_arch_post.h"
arch/i386/kernel/vmlinux.lds.S (mode:100644) +27 -0
Index: arch/i386/kernel/vmlinux.lds.S
===================================================================
@@ -5,6 +5,8 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
+#include <linux/config.h>
+#include <asm/vsyscall-gtod.h>
 
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
@@ -52,6 +54,31 @@
 
   _edata = .;			/* End of data section */
 
+/* VSYSCALL_GTOD data */
+#ifdef CONFIG_NEWTOD_VSYSCALL
+
+  /* vsyscall entry */
+   . = ALIGN(64);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  .vsyscall_0 VSYSCALL_GTOD_START: AT ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095)) { *(.vsyscall_0) }
+  __vsyscall_0 = LOADADDR(.vsyscall_0);
+
+
+	/* generic gtod variables */
+  . = ALIGN(64);
+  .vsyscall_gtod_data : AT ((LOADADDR(.vsyscall_0) + SIZEOF(.vsyscall_0) + 63) & ~(63)) { *(.vsyscall_gtod_data) }
+  vsyscall_gtod_data = LOADADDR(.vsyscall_gtod_data);
+
+    . = ALIGN(16);
+  .vsyscall_gtod_lock : AT ((LOADADDR(.vsyscall_gtod_data) + SIZEOF(.vsyscall_gtod_data) + 15) & ~(15)) { *(.vsyscall_gtod_lock) }
+  vsyscall_gtod_lock = LOADADDR(.vsyscall_gtod_lock);
+
+  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) }
+  . = LOADADDR(.vsyscall_0) + 4096;
+#endif
+/* END of VSYSCALL_GTOD data*/
+
   . = ALIGN(THREAD_SIZE);	/* init_task */
   .data.init_task : { *(.data.init_task) }
 
arch/i386/kernel/vsyscall-gtod.c (mode:100644) renamed from dev/null (tree:3b4165efeade40b65ea2e8188184e4f8d3d8d636) +193 -0

193 lines not on this page · raw message

include/asm-i386/fixmap.h (mode:100644) +6 -0
Index: include/asm-i386/fixmap.h
===================================================================
@@ -27,6 +27,7 @@
 #include <asm/acpi.h>
 #include <asm/apicdef.h>
 #include <asm/page.h>
+#include <asm/vsyscall-gtod.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
@@ -53,6 +54,11 @@
 enum fixed_addresses {
 	FIX_HOLE,
 	FIX_VSYSCALL,
+#ifdef CONFIG_NEWTOD_VSYSCALL
+	FIX_VSYSCALL_GTOD_LAST_PAGE,
+	FIX_VSYSCALL_GTOD_FIRST_PAGE = FIX_VSYSCALL_GTOD_LAST_PAGE
+					+ VSYSCALL_GTOD_NUMPAGES - 1,
+#endif
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
include/asm-i386/pgtable.h (mode:100644) +4 -0
Index: include/asm-i386/pgtable.h
===================================================================
@@ -159,6 +159,8 @@
 #define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD)
 #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+#define __PAGE_KERNEL_VSYSCALL \
+	(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 
 #define PAGE_KERNEL		__pgprot(__PAGE_KERNEL)
 #define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO)
@@ -166,6 +168,8 @@
 #define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE)
 #define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE)
 #define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC)
+#define PAGE_KERNEL_VSYSCALL __pgprot(__PAGE_KERNEL_VSYSCALL)
+#define PAGE_KERNEL_VSYSCALL_NOCACHE __pgprot(__PAGE_KERNEL_VSYSCALL|(__PAGE_KERNEL_RO | _PAGE_PCD))
 
 /*
  * The i386 can't do page protection for execute, and considers that
include/asm-i386/vsyscall-gtod.h (mode:100644) renamed from dev/null (tree:3b4165efeade40b65ea2e8188184e4f8d3d8d636) +41 -0

41 lines not on this page · raw message

#7 lore raw

Re: [RFC][PATCH (7/7)] new timeofday i386 vsyscall proof of concept (v A5)

All,
Yikes, here is another small fix a last minute function name
change caused, this time in the vsyscall-i386 patch. This small fix applies on top of my timeofday-vsyscall-i386_A5 patch to resolve the issue.

Also it was noted that the vsyscall-i386 patch puts the vsyscall config option in a bad place. I'll fix that in my next release.

Sorry about that.

thanks
-john

arch/i386/kernel/vsyscall-gtod.c: needs update
Index: arch/i386/kernel/vsyscall-gtod.c
===================================================================

arch/i386/kernel/vsyscall-gtod.c (mode:100644) +1 -1
@@ -113,7 +113,7 @@
 	}
 
 	/* save off wall time as timeval */
-	vsyscall_gtod_data.wall_time_tv = ns2timeval(wall_time);
+	vsyscall_gtod_data.wall_time_tv = ns_to_timeval(wall_time);
 
 	/* save offset_base */
 	vsyscall_gtod_data.offset_base = offset_base;
#8 lore raw

IA64 implementation of timesource for new time of day subsystem

In reply to john stultz
Quoted 1 line · john stultz

I look forward to your comments and feedback.

Here is the implementation of the IA64 timesources for the new time of day subsystem.

This is quite straighforward. Thanks John. However, the ITC interpolator can no longer use MMIO in SMP situations since there is no provision for jitter compensation in the new time of day subsystem. I have implemented that via a function now which will slow down clock access for non SGI IA64 hardware significantly since it will not be able to use the fastcall anymore.

I am working on the fastcall but I would need a couple of changes to the core code to make the following symbols non-static since they will need to be accessed from the fast syscall handler:

timesource
system_time
wall_time_offset
offset_base

The asm code is going to be simplified because there will be no need to support jitter compensation and most values are now single 64 bit values instead of two 64 bit values with separate seconds and nanoseconds.

However, the asm code is also is going to be a bit more complicated since the split from 64 bit nanoseconds into seconds and nanoseconds/microseconds for gettimeofday and clock_gettime has to be done in asm as well.

I would recommend to add jitter compensation to the time sources. Otherwise each ITC/TSC like timesource will have to implement that on its own.

Index: linux-2.6.12-rc4/drivers/timesource/Makefile
=================================--- linux-2.6.12-rc4.orig/drivers/timesource/Makefile 2005-05-14 11:21:46.000000000 -0700
+++ linux-2.6.12-rc4/drivers/timesource/Makefile 2005-05-14 12:15:08.000000000 -0700
@@ -4,9 +4,8 @@ obj-$(CONFIG_PPC64) += ppc64_timebase.o
obj-$(CONFIG_PPC) += ppc_timebase.o obj-$(CONFIG_ARCH_S390) += s390_tod.o

-# XXX - Untested/Uncompiled
-#obj-$(CONFIG_IA64) += itc.c -#obj-$(CONFIG_IA64_SGI_SN2) += sn2_rtc.c +obj-$(CONFIG_IA64) += itc.o +obj-$(CONFIG_IA64_SGI_SN2) += sn2_rtc.o
obj-$(CONFIG_X86) += tsc.o
obj-$(CONFIG_X86) += i386_pit.o
obj-$(CONFIG_X86) += tsc-interp.o
Index: linux-2.6.12-rc4/drivers/timesource/itc.c
=================================--- linux-2.6.12-rc4.orig/drivers/timesource/itc.c 2005-05-14 11:21:46.000000000 -0700
+++ linux-2.6.12-rc4/drivers/timesource/itc.c 2005-05-14 12:20:00.000000000 -0700
@@ -1,31 +1,83 @@
-/* XXX - this is totally untested and uncompiled
- * TODO:
- * o cpufreq issues
- * o unsynched ITCs ?
+/*
+ * drivers/timesource/itc.c
+ *
+ * Use of the ITC register on Itanium processors as a time source
+ *
+ * Copyright (C) 2005 Silicon Graphics, Inc.
+ * Christoph Lameter, <[email protected]>
*/
+#include <linux/config.h>
#include <linux/timesource.h>
+#include <linux/jiffies.h>

-/* XXX - Other includes needed for:
- * sal_platform_features, IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT,
- * local_cpu_data->itc_freq
- * See arch/ia64/kernel/time.c for ideas
- */
+#include <asm/machvec.h>
+#include <asm/sal.h>
+#include <asm/system.h>

static struct timesource_t timesource_itc = {
.name = "itc",
.priority = 25,
.type = TIMESOURCE_CYCLES,
.mask = (cycle_t)-1,
- .mult = 0, /* to be set */
.shift = 22,
};

+#ifdef CONFIG_SMP
+static int nojitter;
+
+static __init int nojitter_setup(char *str)
+{
+ nojitter = 1;
+ printk(KERN_INFO "ITC timesource: Jitter checking bypassed.\n");
+ return 1;
+}
+
+__setup("itc_nojitter", nojitter_setup);
+
+cycle_t last_itc;
+
+/*
+ * Insure that ITC is monotonically increasing by comparing
+ * to the last value encountered. Do this in an atomic fashion
+ * by using cmpxchg for synchronization between processors
+ * and at the same time for the updating of the last_itc value;
+ */
+static cycle_t itc_filtered(void) {
+ cycle_t now, last;
+
+ do {
+ last = last_itc;
+ smb_rmb();
+ now = get_cycles();
+ if (time_before(now, last))
+ return last_itc;
+ } while (cmpxchg(&last_itc, last, now) != last);
+ return now;
+}
+#endif
+
static int __init init_itc_timesource(void)
{
if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
- /* XXX - I'm not really sure if itc_freq is in cyc/sec */
timesource_itc.mult = timesource_hz2mult(local_cpu_data->itc_freq,
timesource_itc.shift);
+#ifdef CONFIG_SMP
+ /* ITCs are never accurately synchronized in an SMP configuration
+ * even if the ITC_DRIFT bit is not set.
+ * Jitter compensation requires a cmpxchg which may limit
+ * the scalability of the syscalls for retrieving time.
+ * ITC synchronization is usually successful to within a few
+ * ITC ticks but this is not a sure thing. If you need to improve
+ * timer performance in SMP situations then boot the kernel with the
+ * "itc_nojitter" option. However, doing so may result in time fluctuating
+ * (maybe even appearing to go backward!) if the ITC offsets between the
+ * individual CPUs are too large.
+ */
+ if (!nojitter) {
+ timesource_itc.type = TIMESOURCE_FUNCTION;
+ timesource_itc.read_fnct = itc_filtered;
+ }
+#endif
register_timesource(&timesource_itc);
}
return 0;
Index: linux-2.6.12-rc4/arch/ia64/kernel/time.c
=================================--- linux-2.6.12-rc4.orig/arch/ia64/kernel/time.c 2005-05-14 11:21:46.000000000 -0700
+++ linux-2.6.12-rc4/arch/ia64/kernel/time.c 2005-05-14 12:15:08.000000000 -0700
@@ -139,6 +139,7 @@ ia64_cpu_local_tick (void)
ia64_set_itm(local_cpu_data->itm_next);
}

+#ifndef CONFIG_NEWTOD
static int nojitter;

static int __init nojitter_setup(char *str)
@@ -150,6 +151,7 @@ static int __init nojitter_setup(char *s

__setup("nojitter", nojitter_setup);

+#endif

void __devinit
ia64_init_itm (void)
Index: linux-2.6.12-rc4/drivers/timesource/sn2_rtc.c
=================================--- linux-2.6.12-rc4.orig/drivers/timesource/sn2_rtc.c 2005-05-14 11:21:46.000000000 -0700
+++ linux-2.6.12-rc4/drivers/timesource/sn2_rtc.c 2005-05-14 12:15:08.000000000 -0700
@@ -1,29 +1,38 @@
-#include <linux/timesource.h>
-/* XXX this will need some includes
- * to find: sn_rtc_cycles_per_second and RTC_COUNTER_ADDR
- * See arch/ia64/sn/kernel/sn2/timer.c for likely suspects +/*
+ * linux/drivers/timesource/sn2_rtc.c
+ *
+ * Use the RTC on the SN2 on an Altix system as the time source
+ *
+ * (C) 2005 Silicon Graphics, Inc.
+ * Christoph Lameter <[email protected]>
*/

+
+#include <linux/timesource.h>
+#include <asm/system.h>
+#include <asm/sn/leds.h>
+#include <asm/sn/shub_mmr.h>
+#include <asm/sn/clksupport.h>
+
+extern unsigned long sn_rtc_cycles_per_second;
+
#define SN2_RTC_MASK ((1LL << 55) - 1)
#define SN2_SHIFT 10

struct timesource_t timesource_sn2_rtc = {
.name = "sn2_rtc",
- .priority = 300, /* XXX - not sure what this should be */
+ .priority = 999,
.type = TIMESOURCE_MMIO_64,
- .mmio_ptr = NULL,
.mask = (cycle_t)SN2_RTC_MASK,
.mult = 0, /* set below */
.shift = SN2_SHIFT,
};

-static void __init init_sn2_timesource(void) +static __init int init_sn2_timesource(void)
{
- timesource_sn2_rtc.mult = timesource_hz2mult(sn_rtc_cycles_per_second,
- SN2_SHIFT);
+ timesource_sn2_rtc.mult = timesource_hz2mult(sn_rtc_cycles_per_second, SN2_SHIFT);
timesource_sn2_rtc.mmio_ptr = RTC_COUNTER_ADDR;
-
- register_time_interpolator(&timesource_sn2_rtc);
+ register_timesource(&timesource_sn2_rtc);
return 0;
}
module_init(init_sn2_timesource);

#9 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 16 lines · Christoph Lameter
Quoted 1 line · john stultz

I look forward to your comments and feedback.

Here is the implementation of the IA64 timesources for the new time of day subsystem.

This is quite straighforward. Thanks John. However, the ITC interpolator can no longer use MMIO in SMP situations since there is no provision for jitter compensation in the new time of day subsystem. I have implemented that via a function now which will slow down clock access for non SGI IA64 hardware significantly since it will not be able to use the fastcall anymore.

Quoted 9 lines

I am working on the fastcall but I would need a couple of changes to the core code to make the following symbols non-static since they will need to be accessed from the fast syscall handler:

timesource
system_time
wall_time_offset
offset_base

Will this mean that Linux will have a monotonic time source? For media players we need a timesource that does not change under any circumstances. e.g. User changes the clock time, the monotonic time source should not change. The monotonic time source should just start at 0 at power on, and continually increase accurately over time. I.e. A very accurate "uptime" measurement.

James

#10 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 1 line

Will this mean that Linux will have a monotonic time source?

2.6 has had one for a long time (posix_gettime(CLOCK_MONOTONIC))

-Andi

#11 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 3 lines · Andi Kleen
Quoted 1 line

Will this mean that Linux will have a monotonic time source?

2.6 has had one for a long time (posix_gettime(CLOCK_MONOTONIC))

I think that's clock_gettime(), no?

Chris

#12 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

In reply to Christoph Lameter
Quoted 6 lines · Christoph Lameter
Quoted 1 line · john stultz

I look forward to your comments and feedback.

Here is the implementation of the IA64 timesources for the new time of day subsystem.

Great!

Quoted 7 lines

This is quite straighforward. Thanks John. However, the ITC interpolator can no longer use MMIO in SMP situations since there is no provision for jitter compensation in the new time of day subsystem. I have implemented that via a function now which will slow down clock access for non SGI IA64 hardware significantly since it will not be able to use the fastcall anymore.

Quoted 8 lines

I am working on the fastcall but I would need a couple of changes to the core code to make the following symbols non-static since they will need to be accessed from the fast syscall handler:

timesource
system_time
wall_time_offset
offset_base

Actually that shouldn't be necessary. Look at my arch-x86-64 patch or vsyscall-i386 patch for how the arch_vsyscall_gtod_update() function is used. It provides an arch specific hook called by the timeofday core to provide the information you desire.

Please let me know if it is not sufficient for some reason.

[snip]

Quoted 2 lines

I would recommend to add jitter compensation to the time sources. Otherwise each ITC/TSC like timesource will have to implement that on its own.

Just to clarify for others, this is the same unsynced cpu cycle counter problem that affects the TSC on i386 and x86-64. ia64 gets around the problem by checking on every call to gettimeofday() if the ITC value is less then the ITC value used on the previous call to gettimeofday(). If the value is less (ie: would result in time going backwards) it just uses the last value to calculate time. It then uses cmpxchg to atomically update the last ITC value.

The problem I have with this is it that if the ITCs are not synced, they really are not good timesources. If one cpu's ITC is behind another, the net result of the above algorithm is cpu 2 will always just use cpu 1's last calculated time. This could cause jumps in time when a process moves from cpu2 to cpu1.

Since it only affects the TSC and ITC, I think keeping the decision to use cmpxchg in the timesource code, as you've implemented with the ITC is the best way to go. If you really want to you can special case the arch specific fsyscall code by switching on the time source .name, and that would allow you to use a similar cmpxchg algorithm there as well.

thanks
-john

#13 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 6 lines · john stultz

Actually that shouldn't be necessary. Look at my arch-x86-64 patch or vsyscall-i386 patch for how the arch_vsyscall_gtod_update() function is used. It provides an arch specific hook called by the timeofday core to provide the information you desire.

Please let me know if it is not sufficient for some reason.

Obviously this wont work since you cannot execute C code nor functions in an ia64 fastcall. I need the variables exported.

Quoted 10 lines
Quoted 2 lines

I would recommend to add jitter compensation to the time sources. Otherwise each ITC/TSC like timesource will have to implement that on its own.

Just to clarify for others, this is the same unsynced cpu cycle counter problem that affects the TSC on i386 and x86-64. ia64 gets around the problem by checking on every call to gettimeofday() if the ITC value is less then the ITC value used on the previous call to gettimeofday(). If the value is less (ie: would result in time going backwards) it just uses the last value to calculate time. It then uses cmpxchg to atomically update the last ITC value.

Nope. You are way off here. Unsynched cpu cycle counters lead to the ITC timesource not being registered.

Quoted 5 lines

The problem I have with this is it that if the ITCs are not synced, they really are not good timesources. If one cpu's ITC is behind another, the net result of the above algorithm is cpu 2 will always just use cpu 1's last calculated time. This could cause jumps in time when a process moves from cpu2 to cpu1.

Note again that the use of cmpxchg is NOT covering the case of ITCs not being synced. If the ITCs are not synced then no timesource will be established for ITC!

This is the case of ITC's running synchronous but at a tiny offset. The startup on IA64 syncs the ITCs but cannot guarantee a complete sync. There may be a small offset of a few clock ticks. The cmpxchg is needed to compensate for that small offset. I imagine that other architectures have similar issues.

Quoted 5 lines

Since it only affects the TSC and ITC, I think keeping the decision to use cmpxchg in the timesource code, as you've implemented with the ITC is the best way to go. If you really want to you can special case the arch specific fsyscall code by switching on the time source .name, and that would allow you to use a similar cmpxchg algorithm there as well.

Again this will not work on IA64 since it does the fast system calls in a different way.

Clock jitter can affect multiple clock sources that may fluctuate in a minor way due to a variety of influences. Jitter compensation may help in these situations.

#14 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 11 lines · Christoph Lameter
Quoted 6 lines · john stultz

Actually that shouldn't be necessary. Look at my arch-x86-64 patch or vsyscall-i386 patch for how the arch_vsyscall_gtod_update() function is used. It provides an arch specific hook called by the timeofday core to provide the information you desire.

Please let me know if it is not sufficient for some reason.

Obviously this wont work since you cannot execute C code nor functions in an ia64 fastcall. I need the variables exported.

No. Look at the x86-64 code. The generic timeofday core calls arch_update_vsyscall_gtod() (sorry for the function name confusion above) any time the timekeeping variables change.

All you need is to do is define implement an ia64 version of arch_update_vsyscall_gtod() which can then export the values passed to it in whatever form you desire so it can be used by the fastcall.

Quoted 24 lines
Quoted 10 lines
Quoted 2 lines

I would recommend to add jitter compensation to the time sources. Otherwise each ITC/TSC like timesource will have to implement that on its own.

Just to clarify for others, this is the same unsynced cpu cycle counter problem that affects the TSC on i386 and x86-64. ia64 gets around the problem by checking on every call to gettimeofday() if the ITC value is less then the ITC value used on the previous call to gettimeofday(). If the value is less (ie: would result in time going backwards) it just uses the last value to calculate time. It then uses cmpxchg to atomically update the last ITC value.

Nope. You are way off here. Unsynched cpu cycle counters lead to the ITC timesource not being registered.

Quoted 5 lines

The problem I have with this is it that if the ITCs are not synced, they really are not good timesources. If one cpu's ITC is behind another, the net result of the above algorithm is cpu 2 will always just use cpu 1's last calculated time. This could cause jumps in time when a process moves from cpu2 to cpu1.

Note again that the use of cmpxchg is NOT covering the case of ITCs not being synced. If the ITCs are not synced then no timesource will be established for ITC!

Quoted 5 lines

This is the case of ITC's running synchronous but at a tiny offset. The startup on IA64 syncs the ITCs but cannot guarantee a complete sync. There may be a small offset of a few clock ticks. The cmpxchg is needed to compensate for that small offset. I imagine that other architectures have similar issues.

Just per-cpu cycle counters like the TSC and ITC to my knowledge. The PPC timebase increments off of a global bus-signal, so it is not affected. I'd be interested in other examples, though.

Quoted 8 lines
Quoted 5 lines

Since it only affects the TSC and ITC, I think keeping the decision to use cmpxchg in the timesource code, as you've implemented with the ITC is the best way to go. If you really want to you can special case the arch specific fsyscall code by switching on the time source .name, and that would allow you to use a similar cmpxchg algorithm there as well.

Again this will not work on IA64 since it does the fast system calls in a different way.

I think you'll find otherwise. The arch_update_vsyscall_gtod() interface gives each arch quite a bit of flexibility in how to implement their own accelerated timeofday.

In pseudo code, all you would need to do is something like:

arch_update_vsyscall_gtod(wall_time, offset_base, timesource, ntp_adj):

fastcall_data.wall = wall_time
fastcall_data.base = offset_base
fastcall_data.ts = timesource
fastcall_data.ntpadj = ntp_adj

fastcall_gtod(): [I understand this would be done in asm]

switch(fastcall_data.ts.type):
case TIMESOURCE_MMIO:
now = <mmio read code>
case TIMESOURCE_CYCLE:
bow = <cycle read code>
case TIMESOURCE_FUNCTION:
# special case for itc
if (fastcall_data.ts.name = "itc")
now = <cycle jitter read>
else
return gettimeofday()

offset = (now - fastcall_data.base)
offset *= fastcall_data.ts.mult
offset += fastcall_data.ntpadj
offset >>= fastcall_data.ts.shift

return fastcall_data.wall + offset

Quoted 3 lines

Clock jitter can affect multiple clock sources that may fluctuate in a minor way due to a variety of influences. Jitter compensation may help in these situations.

Forgive me as I'm just not aware of these, and am thus hesitant to change the core code for two known cases that can be cleanly dealt with in the timesource driver code.

thanks
-john

#15 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 3 lines · john stultz

All you need is to do is define implement an ia64 version of arch_update_vsyscall_gtod() which can then export the values passed to it in whatever form you desire so it can be used by the fastcall.

Sorry, that first sentence wasn't complete, I went to go look up the reference and got distracted with something else.

It should be "All you need to do is define NEWTOD_VSYSCALL and implement.."

time for more coffee :)
-john

#16 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

In reply to john stultz
Quoted 8 lines · john stultz

In pseudo code, all you would need to do is something like:

arch_update_vsyscall_gtod(wall_time, offset_base, timesource, ntp_adj):

fastcall_data.wall = wall_time
fastcall_data.base = offset_base
fastcall_data.ts = timesource
fastcall_data.ntpadj = ntp_adj

Ahh. Thanks.

Quoted 7 lines
Quoted 3 lines

Clock jitter can affect multiple clock sources that may fluctuate in a minor way due to a variety of influences. Jitter compensation may help in these situations.

Forgive me as I'm just not aware of these, and am thus hesitant to change the core code for two known cases that can be cleanly dealt with in the timesource driver code.

I am happy to leave the situation as is since it does not affect SGI. We have a memory mapped timer that does not need this jitter compensation.

Other IA64 vendors will see that their timer performance drops significantly after the new timer subsystem is in. IBM no longer has IA64 systems that rely on ITC?

#17 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Christoph Lameter

Christoph> Other IA64 vendors will see that their timer performance Christoph> drops significantly after the new timer subsystem is Christoph> in. IBM no longer has IA64 systems that rely on ITC?

Would that somehow make it ok to break existing and working code?

	--david
#18 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 7 lines · David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Christoph Lameter

Christoph> Other IA64 vendors will see that their timer performance Christoph> drops significantly after the new timer subsystem is Christoph> in. IBM no longer has IA64 systems that rely on ITC?

Would that somehow make it ok to break existing and working code?

No. I intend to preserve the existing functionality (and performance) of the current code. The current timeofday core should allow for this (as I described in my last mail), so really its just a matter of either me or someone else getting around to properly converting that arch with the help of the arch maintainer. Until the arch is really ready to use the new timeofday core, no changes are necessary.

Christoph's patch is just a step in the right direction. That is, a much appreciated step, I haven't yet had the time to implement or test the ia64 timesources. Any notable regressions introduced will need to be resolved before the arch specific patch is finally submitted.

What I'm trying to shake out, with Christoph's help, is any major limitations in the core timeofday code that would keep an arch from being able to use it. I feel Christoph's concerns have been addressed, but please let me know if you disagree.

thanks
-john

#19 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 7 lines · john stultz

No. I intend to preserve the existing functionality (and performance) of the current code. The current timeofday core should allow for this (as I described in my last mail), so really its just a matter of either me or someone else getting around to properly converting that arch with the help of the arch maintainer. Until the arch is really ready to use the new timeofday core, no changes are necessary.

Its not an arch specific issue. The time sources need to have a field that specifies that jitter protection is needed and there needs to be some logic to implement it. Otherwise we have to develop special functions for each timesource that deal with jitter protection. Function will make a fastcall for the clocks that use jitter protection not possible and thus timer access will slow down.

Quoted 4 lines

What I'm trying to shake out, with Christoph's help, is any major limitations in the core timeofday code that would keep an arch from being able to use it. I feel Christoph's concerns have been addressed, but please let me know if you disagree.

Please add jitter protection to the arch independent code.

#20 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 10 lines · Christoph Lameter
Quoted 7 lines · john stultz

No. I intend to preserve the existing functionality (and performance) of the current code. The current timeofday core should allow for this (as I described in my last mail), so really its just a matter of either me or someone else getting around to properly converting that arch with the help of the arch maintainer. Until the arch is really ready to use the new timeofday core, no changes are necessary.

Quoted 4 lines

Its not an arch specific issue. The time sources need to have a field that specifies that jitter protection is needed and there needs to be some logic to implement it. Otherwise we have to develop special functions for each timesource that deal with jitter protection.

You've only pointed out two timesources that could want this (ITC and TSC), so I think its reasonable to do your jitter handling in the timesource driver. If there are other arches that have non hardware synced per-cpu counters, then it would be something to consider.

Quoted 3 lines

Function will make a
fastcall for the clocks that use jitter protection not possible and thus timer access will slow down.

I disagree. I already explained how this can be done via the arch_update_vsyscall_gtod() interface by special casing for this specific well known time source.

Quoted 6 lines
Quoted 4 lines

What I'm trying to shake out, with Christoph's help, is any major limitations in the core timeofday code that would keep an arch from being able to use it. I feel Christoph's concerns have been addressed, but please let me know if you disagree.

Please add jitter protection to the arch independent code.

If more timesources need that functionality, then I'll be happy to. Until then it should stay in the ia64 specific itc driver and fastcall code.

thanks
-john

#21 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · john stultz

John> You've only pointed out two timesources that could want this John> (ITC and TSC), so I think its reasonable to do your jitter John> handling in the timesource driver. If there are other arches John> that have non hardware synced per-cpu counters, then it would John> be something to consider.

I think Christopher's point is that _all_ time-sources which require software syncing will need this since it is not possible to sync perfectly, even if there is no drift.

	--david
#22 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 10 lines · David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · john stultz

John> You've only pointed out two timesources that could want this John> (ITC and TSC), so I think its reasonable to do your jitter John> handling in the timesource driver. If there are other arches John> that have non hardware synced per-cpu counters, then it would John> be something to consider.

I think Christopher's point is that _all_ time-sources which require software syncing will need this since it is not possible to sync perfectly, even if there is no drift.

Yes, but to my knowledge it is only the ITC that does software syncing. The TSC could use it as well, but doesn't. Other then that I haven't heard of any other timesource that would use such functionality.

Since its possible to do jitter compensation within the itc timesource driver (and within the fastcall code to preserve the existing performance), would it be reasonable to deffer making the jitter compensation code generic until another timesource needs it? It should be a fairly simple change.

Or is this just something I'm being hard-headed about?

thanks
-john

#23 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

Quoted 5 lines · john stultz

Since its possible to do jitter compensation within the itc timesource driver (and within the fastcall code to preserve the existing performance), would it be reasonable to deffer making the jitter compensation code generic until another timesource needs it? It should be a fairly simple change.

Well looks that we will start out with the new time subsystem by putting some hacks in. I need to check in the funky routine (for setting up the fastcall configuration) if the function pointer passed = jitter-compensated-itc and depending on that set a special flag that makes the asm code do jitter compensation.

Quoted 1 line

Or is this just something I'm being hard-headed about?

Looks like it. Its not that difficult. Add a jitter compensation flag to timesource. Check on retrieving from a timesource if its less than last if flag is set. Pass the field to the funky function to setup the vsyscalls.

Maybe add a general flags field? There may be other things that need to be added in the future.

#24 lore raw

Re: IA64 implementation of timesource for new time of day subsystem

In reply to David Mosberger
Quoted 7 lines · David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Christoph Lameter

Christoph> Other IA64 vendors will see that their timer performance Christoph> drops significantly after the new timer subsystem is Christoph> in. IBM no longer has IA64 systems that rely on ITC?

Would that somehow make it ok to break existing and working code?

AFAIR the design goal was not to make a new time implementation, but to make a more precise one ;-)

Regards,
Ulrich

#25 lore raw

Re: [RFC][PATCH (3/7)] new timeofday x86-64 specific changes (v A5)

In reply to john stultz

All,
I just realized a last minute function name change didn't get updated
on the x86-64 patch. This small fix applies on top of my timeofday- arch-x86-64_A5 patch to resolve the issue.

thanks
-john

arch/x86_64/kernel/vsyscall.c: needs update
Index: arch/x86_64/kernel/vsyscall.c
===================================================================

arch/x86_64/kernel/vsyscall.c (mode:100644) +1 -1
@@ -194,7 +194,7 @@
 	}
 
 	/* save off wall time as timeval */
-	vsyscall_gtod_data.wall_time_tv = ns2timeval(wall_time);
+	vsyscall_gtod_data.wall_time_tv = ns_to_timeval(wall_time);
 
 	/* save offset_base */
 	vsyscall_gtod_data.offset_base = offset_base;
#26 lore raw

cover new timeofday-based soft-timer subsystem

In reply to john stultz
Quoted 9 lines · john stultz

All,
This patch implements the architecture independent portion of the new
time of day subsystem. For a brief description on the rework, see here:
http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that easy to understand writeup!)

I intend this to be the last RFC release and to submit this patch to
Andrew for for testing near the end of this month. So please, if you have any complaints, suggestions, or blocking issues, let me know.

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patches attempts to begin this process. I would greatly appreciate any comments.

Some design points:

1) The patch is small but does a lot.
a) Renames timer_jiffies to last_timer_time (now that we are not jiffies-based).
b) Converts the soft-timer time-vector's/bucket's entries to timerinterval (a new unit) width, instead of jiffy width.
c) Defines timerintervals to be the current time as reported by the new timeofday-subsystem shifted down by TIMERINTERVAL_BITS bits. Thus, various pseudo-'human time' units can be emulated.
d) Uses do_monotonic_clock() (converted to timerintervals) as the basis for addition and expiration of timers instead of jiffies.
e) Adds some new helper functions for dealing with nanosecond values.

2) The patch depends on John's timeofday core rework. For arches that will not have the new timeofday (or for which the rework is still in progress), I can emulate the existing system with a separate patch (Such a possible patch will follow). The goal of this patch, though, is just to show how easy the new system can be implemented and the benefits. It has been tested on x86 and x86_64 archs; there may be some issues with ppc and ppc64 which I am working on resolving.

3) The reason for the re-work? Many people complain about all of the adding of 1 jiffy here or there to fix bugs. This new systems is fundamentally human-time oriented and deals with those issues correctly and, more importantly, sanely :)

The code is reasonably well commented, but does expect readers to understand the current soft-timer subsystem.

This is still an early working of this patch, so I expect criticism, and am happy to make changes.

I will try to get some current benchmark differentials posted tomorrow. The previous patch I released showed little difference between mainline, John's timeofday rework and my soft-timer rework in kernbench.

Overview:

1/4: A small interdiff between John's current stack and what is necessary for my patch to work. Moves timeofday.h architecture-specific code to asm/timeofday.h. This is necessary for my patch.

2/4: Converts the soft-timer subsystem to use timerinterval as the units of addition and expiration.

3/4: Converts, as an example, sys_nanosleep() to use the new interfaces provided by patch 2. For instance, you (albeit somewhat rarely -- maybe once out of every 100,000 requests) may get only 10 usecs of actual sleep (instead of 2+ msecs no matter what).

4/4: Enables non-NEWTOD archs to use the same interfaces, with some performance penalty (am working on a better alternative, this is just a POC).

Thanks,
Nish

#27 lore raw

RFC PATCH 1/4 move arch-specific timeofday core to asm

Quoted 7 lines · Nishanth Aravamudan
Quoted 6 lines · john stultz

All,
This patch implements the architecture independent portion of the new
time of day subsystem. For a brief description on the rework, see here:
http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that easy to understand writeup!)

Quoted 7 lines
Quoted 3 lines

I intend this to be the last RFC release and to submit this patch to
Andrew for for testing near the end of this month. So please, if you have any complaints, suggestions, or blocking issues, let me know.

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patches attempts to begin this process. I would greatly appreciate any comments.

Description: Updates the timeofday-rework to move arch-specific code into asm headers files.

arch/i386/kernel/time.c +1 -2
diff -urpN 2.6.12-rc4-tod-lkml/arch/i386/kernel/time.c 2.6.12-rc4-tod/arch/i386/kernel/time.c
@@ -56,6 +56,7 @@
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <asm/timer.h>
+#include <asm/timeofday.h>
 
 #include "mach_time.h"
 
@@ -68,8 +69,6 @@
 
 #include "io_ports.h"
 
-#include <linux/timeofday.h>
-
 extern spinlock_t i8259A_lock;
 int pit_latch_buggy;              /* extern */
 
include/asm-generic/timeofday.h +26 -0
diff -urpN 2.6.12-rc4-tod-lkml/include/asm-generic/timeofday.h 2.6.12-rc4-tod/include/asm-generic/timeofday.h
@@ -0,0 +1,26 @@
+/*  linux/include/asm-generic/timeofday.h
+ *
+ *  This file contains the asm-generic interface
+ *  to the arch specific calls used by the time of day subsystem
+ */
+#ifndef _ASM_GENERIC_TIMEOFDAY_H
+#define _ASM_GENERIC_TIMEOFDAY_H
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <asm/div64.h>
+#ifdef CONFIG_NEWTOD
+
+/* Required externs */
+extern nsec_t read_persistent_clock(void);
+extern void sync_persistent_clock(struct timespec ts);
+
+#ifdef CONFIG_NEWTOD_VSYSCALL
+extern void arch_update_vsyscall_gtod(nsec_t wall_time, cycle_t offset_base,
+				struct timesource_t* timesource, int ntp_adj);
+#else
+#define arch_update_vsyscall_gtod(x,y,z,w) {}
+#endif /* CONFIG_NEWTOD_VSYSCALL */
+
+#endif /* CONFIG_NEWTOD */
+#endif
include/asm-i386/timeofday.h +4 -0
diff -urpN 2.6.12-rc4-tod-lkml/include/asm-i386/timeofday.h 2.6.12-rc4-tod/include/asm-i386/timeofday.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_I386_TIMEOFDAY_H
+#define _ASM_I386_TIMEOFDAY_H
+#include <asm-generic/timeofday.h>
+#endif
include/asm-ia64/timeofday.h +4 -0
diff -urpN 2.6.12-rc4-tod-lkml/include/asm-ia64/timeofday.h 2.6.12-rc4-tod/include/asm-ia64/timeofday.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_IA64_TIMEOFDAY_H
+#define _ASM_IA64_TIMEOFDAY_H
+#include <asm-generic/timeofday.h>
+#endif
include/asm-ppc/timeofday.h +4 -0
diff -urpN 2.6.12-rc4-tod-lkml/include/asm-ppc/timeofday.h 2.6.12-rc4-tod/include/asm-ppc/timeofday.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_PPC_TIMEOFDAY_H
+#define _ASM_PPC_TIMEOFDAY_H
+#include <asm-generic/timeofday.h>
+#endif
include/asm-ppc64/timeofday.h +4 -0
diff -urpN 2.6.12-rc4-tod-lkml/include/asm-ppc64/timeofday.h 2.6.12-rc4-tod/include/asm-ppc64/timeofday.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_PPC64_TIMEOFDAY_H
+#define _ASM_PPC64_TIMEOFDAY_H
+#include <asm-generic/timeofday.h>
+#endif
include/asm-s390/timeofday.h +4 -0
diff -urpN 2.6.12-rc4-tod-lkml/include/asm-s390/timeofday.h 2.6.12-rc4-tod/include/asm-s390/timeofday.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_S390_TIMEOFDAY_H
+#define _ASM_S390_TIMEOFDAY_H
+#include <asm-generic/timeofday.h>
+#endif
include/asm-x86_64/timeofday.h +4 -0
diff -urpN 2.6.12-rc4-tod-lkml/include/asm-x86_64/timeofday.h 2.6.12-rc4-tod/include/asm-x86_64/timeofday.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_X86_64_TIMEOFDAY_H
+#define _ASM_X86_64_TIMEOFDAY_H
+#include <asm-generic/timeofday.h>
+#endif
include/linux/timeofday.h +0 -14
diff -urpN 2.6.12-rc4-tod-lkml/include/linux/timeofday.h 2.6.12-rc4-tod/include/linux/timeofday.h
@@ -7,7 +7,6 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/timex.h>
-#include <linux/timesource.h>
 #include <asm/div64.h>
 
 #ifdef CONFIG_NEWTOD
@@ -23,19 +22,6 @@ extern int do_adjtimex(struct timex *tx)
 
 extern void timeofday_init(void);
 
-
-/* Required externs */
-/* XXX - should this go elsewhere? */
-extern nsec_t read_persistent_clock(void);
-extern void sync_persistent_clock(struct timespec ts);
-#ifdef CONFIG_NEWTOD_VSYSCALL
-extern void arch_update_vsyscall_gtod(nsec_t wall_time, cycle_t offset_base,
-				struct timesource_t* timesource, int ntp_adj);
-#else
-#define arch_update_vsyscall_gtod(x,y,z,w) {}
-#endif
-
-
 /* Inline helper functions */
 static inline struct timeval ns_to_timeval(nsec_t ns)
 {
kernel/timeofday.c +1 -0
diff -urpN 2.6.12-rc4-tod-lkml/kernel/timeofday.c 2.6.12-rc4-tod/kernel/timeofday.c
@@ -58,6 +58,7 @@
 #include <linux/sched.h> /* Needed for capable() */
 #include <linux/sysdev.h>
 #include <linux/jiffies.h>
+#include <asm/timeofday.h>
 
 /* XXX - remove later */
 #define TIME_DBG 0
#28 lore raw

RFC PATCH 2/4 convert soft-timer subsystem to timerintervals

In reply to Nishanth Aravamudan
Quoted 7 lines · Nishanth Aravamudan
Quoted 6 lines · john stultz

All,
This patch implements the architecture independent portion of the new
time of day subsystem. For a brief description on the rework, see here:
http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that easy to understand writeup!)

Quoted 7 lines
Quoted 3 lines

I intend this to be the last RFC release and to submit this patch to
Andrew for for testing near the end of this month. So please, if you have any complaints, suggestions, or blocking issues, let me know.

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patches attempts to begin this process. I would greatly appreciate any comments.

Description: Rework the soft-timer subsytem to use timerintervals (a new unit) instead of jiffies for expiration and addition. timerintervals are nothing more than the nanosecond time returned by the new timeofday-subsystem shifted down a certain number of bits (thus determining the precisino of the soft-timer subsystem at compile-time).

include/linux/jiffies.h +31 -2
diff -urpN 2.6.12-rc4-tod/include/linux/jiffies.h 2.6.12-rc4-tod-timer/include/linux/jiffies.h
@@ -263,7 +263,7 @@ static inline unsigned int jiffies_to_ms
 #endif
 }
 
-static inline unsigned int jiffies_to_usecs(const unsigned long j)
+static inline unsigned long jiffies_to_usecs(const unsigned long j)
 {
 #if HZ <= 1000000 && !(1000000 % HZ)
 	return (1000000 / HZ) * j;
@@ -274,6 +274,17 @@ static inline unsigned int jiffies_to_us
 #endif
 }
 
+static inline nsec_t jiffies_to_nsecs(const unsigned long j)
+{
+#if HZ <= NSEC_PER_SEC && !(NSEC_PER_SEC % HZ)
+	return (NSEC_PER_SEC / HZ) * (nsec_t)j;
+#elif HZ > NSEC_PER_SEC && !(HZ % NSEC_PER_SEC)
+	return ((nsec_t)j + (HZ / NSEC_PER_SEC) - 1)/(HZ / NSEC_PER_SEC);
+#else
+	return ((nsec_t)j * NSEC_PER_SEC) / HZ;
+#endif
+}
+
 static inline unsigned long msecs_to_jiffies(const unsigned int m)
 {
 	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
@@ -287,7 +298,7 @@ static inline unsigned long msecs_to_jif
 #endif
 }
 
-static inline unsigned long usecs_to_jiffies(const unsigned int u)
+static inline unsigned long usecs_to_jiffies(const unsigned long u)
 {
 	if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
 		return MAX_JIFFY_OFFSET;
@@ -300,6 +311,24 @@ static inline unsigned long usecs_to_jif
 #endif
 }
 
+static inline unsigned long nsecs_to_jiffies(const nsec_t n)
+{
+	nsec_t temp;
+	if (n > jiffies_to_nsecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
+#if HZ <= NSEC_PER_SEC && !(NSEC_PER_SEC % HZ)
+	temp = n + (NSEC_PER_SEC / HZ) - 1;
+	do_div(temp, (NSEC_PER_SEC / HZ));
+	return (unsigned long)temp;
+#elif HZ > NSEC_PER_SEC && !(HZ % NSEC_PER_SEC)
+	return n * (HZ / NSEC_PER_SEC);
+#else
+	temp = n * HZ + NSEC_PER_SEC - 1;
+	do_div(temp, NSEC_PER_SEC);
+	return (unsigned long)temp;
+#endif
+}
+
 /*
  * The TICK_NSEC - 1 rounds up the value to the next resolution.  Note
  * that a remainder subtract here would not do the right thing as the
include/linux/sched.h +6 -0
diff -urpN 2.6.12-rc4-tod/include/linux/sched.h 2.6.12-rc4-tod-timer/include/linux/sched.h
@@ -182,7 +182,13 @@ extern void scheduler_tick(void);
 extern int in_sched_functions(unsigned long addr);
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
+#define	MAX_SCHEDULE_TIMEOUT_NSECS	((nsec_t)(-1))
+#define	MAX_SCHEDULE_TIMEOUT_USECS	ULONG_MAX
+#define	MAX_SCHEDULE_TIMEOUT_MSECS	UINT_MAX
 extern signed long FASTCALL(schedule_timeout(signed long timeout));
+extern nsec_t FASTCALL(schedule_timeout_nsecs(nsec_t timeout_nsecs));
+extern unsigned long FASTCALL(schedule_timeout_usecs(unsigned long timeout_usecs));
+extern unsigned int FASTCALL(schedule_timeout_msecs(unsigned int timeout_msesc));
 asmlinkage void schedule(void);
 
 struct namespace;
include/linux/time.h +4 -0
diff -urpN 2.6.12-rc4-tod/include/linux/time.h 2.6.12-rc4-tod-timer/include/linux/time.h
@@ -40,6 +40,10 @@ typedef u64 cycle_t;
 #define NSEC_PER_SEC (1000000000L)
 #endif
 
+#ifndef NSEC_PER_MSEC
+#define NSEC_PER_MSEC (1000000L)
+#endif
+
 #ifndef NSEC_PER_USEC
 #define NSEC_PER_USEC (1000L)
 #endif
include/linux/timer.h +5 -18
diff -urpN 2.6.12-rc4-tod/include/linux/timer.h 2.6.12-rc4-tod-timer/include/linux/timer.h
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
+#include <linux/timeofday.h>
 
 struct tvec_t_base_s;
 
@@ -65,27 +66,13 @@ extern void add_timer_on(struct timer_li
 extern int del_timer(struct timer_list * timer);
 extern int __mod_timer(struct timer_list *timer, unsigned long expires);
 extern int mod_timer(struct timer_list *timer, unsigned long expires);
+extern void add_timer(struct timer_list *timer);
+extern int set_timer_nsecs(struct timer_list *timer, nsec_t expires_nsecs);
+extern void set_timer_on_nsecs(struct timer_list *timer, nsec_t expires_nsecs,
+								int cpu);
 
 extern unsigned long next_timer_interrupt(void);
 
-/***
- * add_timer - start a timer
- * @timer: the timer to be added
- *
- * The kernel will do a ->function(->data) callback from the
- * timer interrupt at the ->expired point in the future. The
- * current time is 'jiffies'.
- *
- * The timer's ->expired, ->function (and if the handler uses it, ->data)
- * fields must be set prior calling this function.
- *
- * Timers with an ->expired field in the past will be executed in the next
- * timer tick.
- */
-static inline void add_timer(struct timer_list * timer)
-{
-	__mod_timer(timer, timer->expires);
-}
 
 #ifdef CONFIG_SMP
   extern int del_timer_sync(struct timer_list *timer);
kernel/timer.c +339 -16

499 lines not on this page · raw message

#29 lore raw

RFC PATCH 2/4 convert soft-timer subsystem to timerintervals

Quoted 16 lines · Nishanth Aravamudan
Quoted 7 lines · Nishanth Aravamudan
Quoted 6 lines · john stultz

All,
This patch implements the architecture independent portion of the new
time of day subsystem. For a brief description on the rework, see here:
http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that easy to understand writeup!)

Quoted 7 lines
Quoted 3 lines

I intend this to be the last RFC release and to submit this patch to
Andrew for for testing near the end of this month. So please, if you have any complaints, suggestions, or blocking issues, let me know.

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patches attempts to begin this process. I would greatly appreciate any comments.

Quoted 5 lines

Description: Rework the soft-timer subsytem to use timerintervals (a new unit) instead of jiffies for expiration and addition. timerintervals are nothing more than the nanosecond time returned by the new timeofday-subsystem shifted down a certain number of bits (thus determining the precisino of the soft-timer subsystem at compile-time).

Sorry, this patch introduced a bug in the nsecs->timerinterval conversion functions which prevented the kernel from booting. Please use the following patch instead.

Thanks,
Nish

Description: Rework the soft-timer subsytem to use timerintervals (a new unit) instead of jiffies for expiration and addition. timerintervals are nothing more than the nanosecond time returned by the new timeofday-subsystem shifted down a certain number of bits (thus determining the precisino of the soft-timer subsystem at compile-time).

include/linux/jiffies.h +31 -2
diff -urpN 2.6.12-rc4-tod/include/linux/jiffies.h 2.6.12-rc4-tod-timer/include/linux/jiffies.h
@@ -263,7 +263,7 @@ static inline unsigned int jiffies_to_ms
 #endif
 }
 
-static inline unsigned int jiffies_to_usecs(const unsigned long j)
+static inline unsigned long jiffies_to_usecs(const unsigned long j)
 {
 #if HZ <= 1000000 && !(1000000 % HZ)
 	return (1000000 / HZ) * j;
@@ -274,6 +274,17 @@ static inline unsigned int jiffies_to_us
 #endif
 }
 
+static inline nsec_t jiffies_to_nsecs(const unsigned long j)
+{
+#if HZ <= NSEC_PER_SEC && !(NSEC_PER_SEC % HZ)
+	return (NSEC_PER_SEC / HZ) * (nsec_t)j;
+#elif HZ > NSEC_PER_SEC && !(HZ % NSEC_PER_SEC)
+	return ((nsec_t)j + (HZ / NSEC_PER_SEC) - 1)/(HZ / NSEC_PER_SEC);
+#else
+	return ((nsec_t)j * NSEC_PER_SEC) / HZ;
+#endif
+}
+
 static inline unsigned long msecs_to_jiffies(const unsigned int m)
 {
 	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
@@ -287,7 +298,7 @@ static inline unsigned long msecs_to_jif
 #endif
 }
 
-static inline unsigned long usecs_to_jiffies(const unsigned int u)
+static inline unsigned long usecs_to_jiffies(const unsigned long u)
 {
 	if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
 		return MAX_JIFFY_OFFSET;
@@ -300,6 +311,24 @@ static inline unsigned long usecs_to_jif
 #endif
 }
 
+static inline unsigned long nsecs_to_jiffies(const nsec_t n)
+{
+	nsec_t temp;
+	if (n > jiffies_to_nsecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
+#if HZ <= NSEC_PER_SEC && !(NSEC_PER_SEC % HZ)
+	temp = n + (NSEC_PER_SEC / HZ) - 1;
+	do_div(temp, (NSEC_PER_SEC / HZ));
+	return (unsigned long)temp;
+#elif HZ > NSEC_PER_SEC && !(HZ % NSEC_PER_SEC)
+	return n * (HZ / NSEC_PER_SEC);
+#else
+	temp = n * HZ + NSEC_PER_SEC - 1;
+	do_div(temp, NSEC_PER_SEC);
+	return (unsigned long)temp;
+#endif
+}
+
 /*
  * The TICK_NSEC - 1 rounds up the value to the next resolution.  Note
  * that a remainder subtract here would not do the right thing as the
include/linux/sched.h +6 -0
diff -urpN 2.6.12-rc4-tod/include/linux/sched.h 2.6.12-rc4-tod-timer/include/linux/sched.h
@@ -182,7 +182,13 @@ extern void scheduler_tick(void);
 extern int in_sched_functions(unsigned long addr);
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
+#define	MAX_SCHEDULE_TIMEOUT_NSECS	((nsec_t)(-1))
+#define	MAX_SCHEDULE_TIMEOUT_USECS	ULONG_MAX
+#define	MAX_SCHEDULE_TIMEOUT_MSECS	UINT_MAX
 extern signed long FASTCALL(schedule_timeout(signed long timeout));
+extern nsec_t FASTCALL(schedule_timeout_nsecs(nsec_t timeout_nsecs));
+extern unsigned long FASTCALL(schedule_timeout_usecs(unsigned long timeout_usecs));
+extern unsigned int FASTCALL(schedule_timeout_msecs(unsigned int timeout_msesc));
 asmlinkage void schedule(void);
 
 struct namespace;
include/linux/time.h +4 -0
diff -urpN 2.6.12-rc4-tod/include/linux/time.h 2.6.12-rc4-tod-timer/include/linux/time.h
@@ -40,6 +40,10 @@ typedef u64 cycle_t;
 #define NSEC_PER_SEC (1000000000L)
 #endif
 
+#ifndef NSEC_PER_MSEC
+#define NSEC_PER_MSEC (1000000L)
+#endif
+
 #ifndef NSEC_PER_USEC
 #define NSEC_PER_USEC (1000L)
 #endif
include/linux/timer.h +5 -18
diff -urpN 2.6.12-rc4-tod/include/linux/timer.h 2.6.12-rc4-tod-timer/include/linux/timer.h
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
+#include <linux/timeofday.h>
 
 struct tvec_t_base_s;
 
@@ -65,27 +66,13 @@ extern void add_timer_on(struct timer_li
 extern int del_timer(struct timer_list * timer);
 extern int __mod_timer(struct timer_list *timer, unsigned long expires);
 extern int mod_timer(struct timer_list *timer, unsigned long expires);
+extern void add_timer(struct timer_list *timer);
+extern int set_timer_nsecs(struct timer_list *timer, nsec_t expires_nsecs);
+extern void set_timer_on_nsecs(struct timer_list *timer, nsec_t expires_nsecs,
+								int cpu);
 
 extern unsigned long next_timer_interrupt(void);
 
-/***
- * add_timer - start a timer
- * @timer: the timer to be added
- *
- * The kernel will do a ->function(->data) callback from the
- * timer interrupt at the ->expired point in the future. The
- * current time is 'jiffies'.
- *
- * The timer's ->expired, ->function (and if the handler uses it, ->data)
- * fields must be set prior calling this function.
- *
- * Timers with an ->expired field in the past will be executed in the next
- * timer tick.
- */
-static inline void add_timer(struct timer_list * timer)
-{
-	__mod_timer(timer, timer->expires);
-}
 
 #ifdef CONFIG_SMP
   extern int del_timer_sync(struct timer_list *timer);
kernel/timer.c +346 -16

506 lines not on this page · raw message

#30 lore raw

Re: [RFC][UPDATE PATCH 2/4] convert soft-timer subsystem to timerintervals

Hi, Nishanth,

To my uneducated eye, this patch looks like a useful cleaning-up of the timer API. I do have one question, though...

kernel/timer.c void add_timer_on(struct timer_list *tim · line 330

Quoted 5 lines
kernel/timer.c +1 -0
@@ -238,15 +327,41 @@ void add_timer_on(struct timer_list *tim
 	check_timer(timer);
 
 	spin_lock_irqsave(&base->lock, flags);
+	timer->expires = jiffies_to_timerintervals(timer->expires);

It would appear that, depending on where you are, ->expires can be expressed in two different units. Users of add_timer() and mod_timer() are expecting jiffies, but the internal code uses timer intervals. What happens when somebody does something like this?

	mod_timer(&my_timer, my_timer.expires + additional_delay);

Might it be better to store the timerintervals value in a different field, and leave ->expires as part of the legacy interface only?

jon

Jonathan Corbet
Executive editor, LWN.net
[email protected]

#31 lore raw

Re: [RFC][UPDATE PATCH 2/4] convert soft-timer subsystem to timerintervals

Quoted 4 lines · Jonathan Corbet

Hi, Nishanth,

To my uneducated eye, this patch looks like a useful cleaning-up of the timer API. I do have one question, though...

Thanks! I think one of the best side-effects (beyond a more accurate execution of sleep requests) of my patch is that the new interfaces are a heck of a lot saner :)

Quoted 11 lines

kernel/timer.c void add_timer_on(struct timer_list *tim · line 330

Quoted 5 lines
kernel/timer.c +1 -0
@@ -238,15 +327,41 @@ void add_timer_on(struct timer_list *tim
 	check_timer(timer);
 
 	spin_lock_irqsave(&base->lock, flags);
+	timer->expires = jiffies_to_timerintervals(timer->expires);

It would appear that, depending on where you are, ->expires can be expressed in two different units. Users of add_timer() and mod_timer() are expecting jiffies, but the internal code uses timer intervals. What happens when somebody does something like this?

Quoted 4 lines
	mod_timer(&my_timer, my_timer.expires + additional_delay);

Might it be better to store the timerintervals value in a different field, and leave ->expires as part of the legacy interface only?

This is definitely an option. Currently, it is somewhat vague as to whether, once a timer has been submitted, whether the expires field is still valid to the caller. In the new system, it will clearly explicitly not be (I meant to modify the comment to add_timer(), mod_timer() and set_timer_nsecs() appropriately, but have not yet.

The problem with the mod_timer() approach you suggest is that there is no guarantee that my_timer.expires represents anything close to the current time. And, as far as my experience with reviewing the current callers is concerned, there is no such usage.

It definitely is feasible and reasonable, though, to make that change. I will look into it and see what I can do.

Thanks for the feedback!

-Nish

#32 lore raw

RFC PATCH 3/4 convert sys_nanosleep() to use new soft-timer subsystem

In reply to Nishanth Aravamudan
Quoted 7 lines · Nishanth Aravamudan
Quoted 6 lines · john stultz

All,
This patch implements the architecture independent portion of the new
time of day subsystem. For a brief description on the rework, see here:
http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that easy to understand writeup!)

Quoted 7 lines
Quoted 3 lines

I intend this to be the last RFC release and to submit this patch to
Andrew for for testing near the end of this month. So please, if you have any complaints, suggestions, or blocking issues, let me know.

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patches attempts to begin this process. I would greatly appreciate any comments.

Description: Convert sys_nanosleep() to use the new timerinterval-based soft-timer interfaces.

kernel/timer.c +11 -11
diff -urpN 2.6.12-rc4-tod-timer-a/kernel/timer.c 2.6.12-rc4-tod-timer-b/kernel/timer.c
@@ -1460,21 +1460,21 @@ asmlinkage long sys_gettid(void)
 
 static long __sched nanosleep_restart(struct restart_block *restart)
 {
-	unsigned long expire = restart->arg0, now = jiffies;
+	nsec_t expire = restart->arg0, now = do_monotonic_clock();
 	struct timespec __user *rmtp = (struct timespec __user *) restart->arg1;
 	long ret;
 
 	/* Did it expire while we handled signals? */
-	if (!time_after(expire, now))
+	if (now > expire)
 		return 0;
 
-	current->state = TASK_INTERRUPTIBLE;
-	expire = schedule_timeout(expire - now);
+	set_current_state(TASK_INTERRUPTIBLE);
+	expire = schedule_timeout_nsecs(expire - now);
 
 	ret = 0;
 	if (expire) {
 		struct timespec t;
-		jiffies_to_timespec(expire, &t);
+		t = ns_to_timespec(expire);
 
 		ret = -ERESTART_RESTARTBLOCK;
 		if (rmtp && copy_to_user(rmtp, &t, sizeof(t)))
@@ -1487,7 +1487,7 @@ static long __sched nanosleep_restart(st
 asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
 {
 	struct timespec t;
-	unsigned long expire;
+	nsec_t expire;
 	long ret;
 
 	if (copy_from_user(&t, rqtp, sizeof(t)))
@@ -1496,20 +1496,20 @@ asmlinkage long sys_nanosleep(struct tim
 	if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0))
 		return -EINVAL;
 
-	expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
-	current->state = TASK_INTERRUPTIBLE;
-	expire = schedule_timeout(expire);
+	expire = timespec_to_ns(&t);
+	set_current_state(TASK_INTERRUPTIBLE);
+	expire = schedule_timeout_nsecs(expire);
 
 	ret = 0;
 	if (expire) {
 		struct restart_block *restart;
-		jiffies_to_timespec(expire, &t);
+		t = ns_to_timespec(expire);
 		if (rmtp && copy_to_user(rmtp, &t, sizeof(t)))
 			return -EFAULT;
 
 		restart = &current_thread_info()->restart_block;
 		restart->fn = nanosleep_restart;
-		restart->arg0 = jiffies + expire;
+		restart->arg0 = do_monotonic_clock() + expire;
 		restart->arg1 = (unsigned long) rmtp;
 		ret = -ERESTART_RESTARTBLOCK;
 	}
#33 lore raw

RFC PATCH 4/4 support new soft-timer subsystem on non-NEWTOD archs

In reply to Nishanth Aravamudan
Quoted 7 lines · Nishanth Aravamudan
Quoted 6 lines · john stultz

All,
This patch implements the architecture independent portion of the new
time of day subsystem. For a brief description on the rework, see here:
http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that easy to understand writeup!)

Quoted 7 lines
Quoted 3 lines

I intend this to be the last RFC release and to submit this patch to
Andrew for for testing near the end of this month. So please, if you have any complaints, suggestions, or blocking issues, let me know.

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patches attempts to begin this process. I would greatly appreciate any comments.

Description: Support the new soft-timer interfaces on non-NEWTOD archs by emulating nanoseconds via jiffies.

include/linux/timeofday.h +9 -0
@@ -55,5 +55,14 @@ static inline nsec_t timeval_to_ns(struc
 }
 #else /* CONFIG_NEWTOD */
 #define timeofday_init()
+/*
+ * do_monotonic_clock():
+ *    Emulate the monotonically increasing number of nanoseconds
+ *    of NEWTOD archs via jiffies.
+ */
+nsec_t do_monotonic_clock(void)
+{
+	return jiffies_to_nsecs(jiffies);
+}
 #endif /* CONFIG_NEWTOD */
 #endif /* _LINUX_TIMEOFDAY_H */
#34 lore raw

Re: [RFC][PATCH 0/4] new timeofday-based soft-timer subsystem

In reply to Nishanth Aravamudan
Quoted 14 lines · Nishanth Aravamudan
Quoted 9 lines · john stultz

All,
This patch implements the architecture independent portion of the new
time of day subsystem. For a brief description on the rework, see here:
http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that easy to understand writeup!)

I intend this to be the last RFC release and to submit this patch to
Andrew for for testing near the end of this month. So please, if you have any complaints, suggestions, or blocking issues, let me know.

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patches attempts to begin this process. I would greatly appreciate any comments.

<snip>

Quoted 3 lines

I will try to get some current benchmark differentials posted tomorrow. The previous patch I released showed little difference between mainline, John's timeofday rework and my soft-timer rework in kernbench.

<snip>

Hrm, "tomorrow" became "two days from now," but here they are, kernbench comparisons (in percent relative to mainline) for x86 and x86_64, 10 iterations each.

The x86_64 machine is a 2-way 2.0 GHz with 3.5 GB of RAM. The x86 machine is 16-way (32 with HT) 1.4 GHz Xeon with 15 GB of RAM.

				x86

					Elapsed	User	System	CPU

2.6.12-rc4: 100% 100% 100% 100%

2.6.12-rc4 + John's patch: 100.3% 100% 99.8% 99.6%

2.6.12-rc4 + John's patch + my patch: 102.1% 101% 100% 98%

				x86_64

					Elapsed	User	System	CPU

2.6.12-rc4: 100% 100% 100% 100%

2.6.12-rc4 + John's patch: 99.5% 99.5% 99.1% 99.9%

2.6.12-rc4 + John's patch + my patch: 99.7% 99.7% 99.5% 100%

----

All in all, pretty consistent across the board.

Thanks,
Nish