Skip to contentSkip to conversation

POSIX clocks & timers

PATCH New george anzinger 1 participant 1 message Oct 16, 2002

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

PATCH 1/1 POSIX clocks & timers

Oops! Wrong patch. Attached is the correct one.

This, patch implements the POSIX clocks and timers functions. The two standard clocks are defined(CLOCK_REALTIME & CLOCK_MONOTONIC).

With this version, nano_sleep() is rolled into clock_nanosleep(). Also a bug fix in clock_nanosleep().

kernel/timer.c is modified to remove the timer_t typedef which conflicts with the POSIX standard definition for this type.

The patch introduces a new kernel source (posix-timers.c) which contains most of the code.

This implementation defines a timer as a system wide resource with system wide limits on the number of allocated timers. This number can be set at configure time and is defaulted to 3000. There
are NO other limits on how many timers a process can have.

Kernel version 2.5.42-bk2

Test programs, man pages and readme files are available on the sourceforge high-res-timers site:

http://sourceforge.net/projects/high-res-timers/

Signature · 5 lines
George Anzinger   [email protected]
High-res-timers: 
http://sourceforge.net/projects/high-res-timers/
Preemption patch:
http://www.kernel.org/pub/linux/kernel/people/rml
arch/i386/kernel/entry.S +9 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
@@ -760,6 +760,15 @@
 	.long sys_alloc_hugepages /* 250 */
 	.long sys_free_hugepages
 	.long sys_exit_group
+	.long sys_timer_create
+	.long sys_timer_settime
+	.long sys_timer_gettime	  /* 255 */
+	.long sys_timer_getoverrun
+	.long sys_timer_delete
+	.long sys_clock_settime
+	.long sys_clock_gettime
+	.long sys_clock_getres	  /* 260 */
+	.long sys_clock_nanosleep
 
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
arch/i386/kernel/time.c +1 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
@@ -136,6 +136,7 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 	write_unlock_irq(&xtime_lock);
+	clock_was_set();
 }
 
 /*

Binary files linux-2.5.42-bk2-kb/core and linux/core differ

fs/exec.c +1 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/fs/exec.c linux/fs/exec.c
@@ -756,6 +756,7 @@
 			
 	flush_signal_handlers(current);
 	flush_old_files(current->files);
+	exit_itimers(current);
 
 	return 0;
 
include/asm-generic/siginfo.h +8 -4
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/asm-generic/siginfo.h linux/include/asm-generic/siginfo.h
@@ -31,8 +31,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -71,8 +72,8 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
-#define si_timer1	_sifields._timer._timer1
-#define si_timer2	_sifields._timer._timer2
+#define si_tid		_sifields._timer._tid
+#define si_overrun	_sifields._timer._overrun
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -203,6 +204,7 @@
 #define SIGEV_SIGNAL	0	/* notify via signal */
 #define SIGEV_NONE	1	/* other notification: meaningless */
 #define SIGEV_THREAD	2	/* deliver via thread creation */
+#define SIGEV_THREAD_ID 4	/* deliver to thread */
 
 #define SIGEV_MAX_SIZE	64
 #ifndef SIGEV_PAD_SIZE
@@ -217,6 +219,7 @@
 	int sigev_notify;
 	union {
 		int _pad[SIGEV_PAD_SIZE];
+		 int _tid;
 
 		struct {
 			void (*_function)(sigval_t);
@@ -229,6 +232,7 @@
 
 #define sigev_notify_function	_sigev_un._sigev_thread._function
 #define sigev_notify_attributes	_sigev_un._sigev_thread._attribute
+#define sigev_notify_thread_id	 _sigev_un._tid
 
 #ifdef __KERNEL__
 
include/asm-i386/posix_types.h +2 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/asm-i386/posix_types.h linux/include/asm-i386/posix_types.h
@@ -22,6 +22,8 @@
 typedef long		__kernel_time_t;
 typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
 typedef unsigned short	__kernel_uid16_t;
include/asm-i386/signal.h +67 -0

73 lines not on this page · raw message

include/asm-i386/unistd.h +9 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
@@ -257,6 +257,15 @@
 #define __NR_alloc_hugepages	250
 #define __NR_free_hugepages	251
 #define __NR_exit_group		252
+#define __NR_timer_create	253
+#define __NR_timer_settime	(__NR_timer_create+1)
+#define __NR_timer_gettime	(__NR_timer_create+2)
+#define __NR_timer_getoverrun	(__NR_timer_create+3)
+#define __NR_timer_delete	(__NR_timer_create+4)
+#define __NR_clock_settime	 (__NR_timer_create+5)
+#define __NR_clock_gettime	 (__NR_timer_create+6)
+#define __NR_clock_getres	 (__NR_timer_create+7)
+#define __NR_clock_nanosleep	 (__NR_timer_create+8)
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
include/linux/init_task.h +1 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/linux/init_task.h linux/include/linux/init_task.h
@@ -93,6 +93,7 @@
 	.sig		= &init_signals,				\
 	.pending	= { NULL, &tsk.pending.head, {{0}}},		\
 	.blocked	= {{0}},					\
+	 .posix_timers	 = LIST_HEAD_INIT(tsk.posix_timers),		   \
 	.alloc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.switch_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
include/linux/posix-timers.h +18 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/linux/posix-timers.h linux/include/linux/posix-timers.h
@@ -0,0 +1,18 @@
+#ifndef _linux_POSIX_TIMERS_H
+#define _linux_POSIX_TIMERS_H
+
+struct k_clock {
+	 int  res;		    /* in nano seconds */
+	 int ( *clock_set)(struct timespec *tp);
+	 int ( *clock_get)(struct timespec *tp);
+	 int ( *nsleep)(   int flags, 
+			   struct timespec*new_setting,
+			   struct itimerspec *old_setting);
+	 int ( *timer_set)(struct k_itimer *timr, int flags,
+			   struct itimerspec *new_setting,
+			   struct itimerspec *old_setting);
+	 int  ( *timer_del)(struct k_itimer *timr);
+	 void ( *timer_get)(struct k_itimer *timr,
+			   struct itimerspec *cur_setting);
+};
+#endif
include/linux/sched.h +26 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/linux/sched.h linux/include/linux/sched.h
@@ -278,6 +278,30 @@
 typedef struct prio_array prio_array_t;
 struct backing_dev_info;
 
+/* POSIX.1b interval timer structure. */
+struct k_itimer {
+	struct list_head list;		 /* free/ allocate list */
+	spinlock_t it_lock;
+	clockid_t it_clock;		/* which timer type */
+	timer_t it_id;			/* timer id */
+	int it_overrun;			/* overrun on pending signal  */
+	int it_overrun_last;		 /* overrun on last delivered signal */
+	int it_overrun_deferred;	 /* overrun on pending timer interrupt */
+	int it_sigev_notify;		 /* notify word of sigevent struct */
+	int it_sigev_signo;		 /* signo word of sigevent struct */
+	sigval_t it_sigev_value;	 /* value word of sigevent struct */
+	unsigned long it_incr;		/* interval specified in jiffies */
+#ifdef CONFIG_HIGH_RES_TIMERS
+	 int it_sub_incr;		 /* sub jiffie part of interval */
+#endif
+	struct task_struct *it_process;	/* process to send signal to */
+	struct timer_list it_timer;
+};
+
+
+//extern struct itimer_struct *itimer_struct_new(void);
+extern void itimer_delete(struct k_itimer *timers);
+
 struct task_struct {
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
 	struct thread_info *thread_info;
@@ -343,6 +367,7 @@
 	unsigned long it_real_value, it_prof_value, it_virt_value;
 	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
 	struct timer_list real_timer;
+	struct list_head posix_timers; /* POSIX.1b Interval Timers */
 	unsigned long utime, stime, cutime, cstime;
 	unsigned long start_time;
 	long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
@@ -651,6 +676,7 @@
 
 extern void exit_mm(struct task_struct *);
 extern void exit_files(struct task_struct *);
+extern void exit_itimers(struct task_struct *);
 extern void exit_sighand(struct task_struct *);
 extern void __exit_sighand(struct task_struct *);
 
include/linux/signal.h +30 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/linux/signal.h linux/include/linux/signal.h
@@ -224,6 +224,36 @@
 struct pt_regs;
 extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs);
 #endif
+/*
+ * We would like the asm/signal.h code to define these so that the using
+ * function can call do_signal().  In loo of that, we define a genaric
+ * version that pretends that do_signal() was called and delivered a signal.
+ * To see how this is used, see nano_sleep() in timer.c and the i386 version
+ * in asm_i386/signal.h.
+ */
+#ifndef PT_REGS_ENTRY
+#define PT_REGS_ENTRY(type,name,p1_type,p1, p2_type,p2) \
+type name(p1_type p1,p2_type p2)\
+{
+#endif
+#ifndef _do_signal
+#define _do_signal() 1
+#endif
+#ifndef NANOSLEEP_ENTRY
+#define NANOSLEEP_ENTRY(a) asmlinkage long sys_nanosleep( struct timespec* rqtp, \
+							  struct timespec * rmtp) \
+{ a
+#endif
+#ifndef CLOCK_NANOSLEEP_ENTRY
+#define CLOCK_NANOSLEEP_ENTRY(a) asmlinkage long sys_clock_nanosleep( \
+			       clockid_t which_clock,	   \
+			       int flags,		   \
+			       const struct timespec *rqtp, \
+			       struct timespec *rmtp)	    \
+{ a
+ 
+#endif
+
 
 #endif /* __KERNEL__ */
 
include/linux/sys.h +1 -1
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/linux/sys.h linux/include/linux/sys.h
@@ -4,7 +4,7 @@
 /*
  * system call entry points ... but not all are defined
  */
-#define NR_syscalls 256
+#define NR_syscalls 275
 
 /*
  * These are system calls that will be removed at some time
include/linux/time.h +35 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/linux/time.h linux/include/linux/time.h
@@ -38,6 +38,19 @@
  */
 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
 
+/* Parameters used to convert the timespec values */
+#ifndef USEC_PER_SEC
+#define USEC_PER_SEC (1000000L)
+#endif
+
+#ifndef NSEC_PER_SEC
+#define NSEC_PER_SEC (1000000000L)
+#endif
+
+#ifndef NSEC_PER_USEC
+#define NSEC_PER_USEC (1000L)
+#endif
+
 static __inline__ unsigned long
 timespec_to_jiffies(struct timespec *value)
 {
@@ -124,6 +137,8 @@
 #ifdef __KERNEL__
 extern void do_gettimeofday(struct timeval *tv);
 extern void do_settimeofday(struct timeval *tv);
+extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+extern void clock_was_set(void); // call when ever the clock is set
 #endif
 
 #define FD_SETSIZE		__FD_SETSIZE
@@ -149,5 +164,25 @@
 	struct	timeval it_interval;	/* timer interval */
 	struct	timeval it_value;	/* current value */
 };
+
+
+/*
+ * The IDs of the various system clocks (for POSIX.1b interval timers).
+ */
+#define CLOCK_REALTIME		  0
+#define CLOCK_MONOTONIC	  1
+#define CLOCK_PROCESS_CPUTIME_ID 2
+#define CLOCK_THREAD_CPUTIME_ID	 3
+#define CLOCK_REALTIME_HR	 4
+#define CLOCK_MONOTONIC_HR	  5
+
+#define MAX_CLOCKS 6
+
+/*
+ * The various flags for setting POSIX.1b interval timers.
+ */
+
+#define TIMER_ABSTIME 0x01
+
 
 #endif
include/linux/types.h +2 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/include/linux/types.h linux/include/linux/types.h
@@ -23,6 +23,8 @@
 typedef __kernel_daddr_t	daddr_t;
 typedef __kernel_key_t		key_t;
 typedef __kernel_suseconds_t	suseconds_t;
+typedef __kernel_timer_t	timer_t;
+typedef __kernel_clockid_t	clockid_t;
 
 #ifdef __KERNEL__
 typedef __kernel_uid32_t	uid_t;
init/Config.help +8 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/init/Config.help linux/init/Config.help
@@ -115,3 +115,11 @@
   replacement for kerneld.) Say Y here and read about configuring it
   in <file:Documentation/kmod.txt>.
 
+Maximum number of POSIX timers
+CONFIG_MAX_POSIX_TIMERS
+  This option allows you to configure the system wide maximum number of
+  POSIX timers.  Timers are allocated as needed so the only memory
+  overhead this adds is about 4 bytes for every 50 or so timers to keep
+  track of each block of timers.  The system quietly rounds this number
+  up to fill out a timer allocation block.  It is ok to have several
+  thousand timers as needed by your applications.
init/Config.in +1 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/init/Config.in linux/init/Config.in
@@ -9,6 +9,7 @@
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
+int 'System wide maximum number of POSIX timers' CONFIG_MAX_POSIX_TIMERS 3000
 endmenu
 
 mainmenu_option next_comment
kernel/Makefile +2 -1
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/kernel/Makefile linux/kernel/Makefile
@@ -8,7 +8,8 @@
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
 	    module.o exit.o itimer.o time.o softirq.o resource.o \
 	    sysctl.o capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o
+	    signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o \
+	    posix-timers.o
 
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o
kernel/exit.c +16 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/kernel/exit.c linux/kernel/exit.c
@@ -408,6 +408,21 @@
 	mmdrop(active_mm);
 }
 
+static inline void __exit_itimers(struct task_struct *tsk)
+{
+	struct	k_itimer *tmr;
+
+	while (tsk->posix_timers.next != &tsk->posix_timers){
+		 tmr = list_entry(tsk->posix_timers.next,struct k_itimer,list);
+		itimer_delete(tmr);
+	}
+}
+
+void exit_itimers(struct task_struct *tsk)
+{
+	__exit_itimers(tsk);
+}
+
 /*
  * Turn us into a lazy TLB process if we
  * aren't already..
@@ -643,6 +658,7 @@
 	__exit_files(tsk);
 	__exit_fs(tsk);
 	exit_namespace(tsk);
+	__exit_itimers(tsk);
 	exit_thread();
 
 	if (current->leader)
kernel/fork.c +1 -0
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.42-bk2-kb/kernel/fork.c linux/kernel/fork.c
@@ -783,6 +783,7 @@
 		goto bad_fork_cleanup_files;
 	if (copy_sighand(clone_flags, p))
 		goto bad_fork_cleanup_fs;
+	INIT_LIST_HEAD(&p->posix_timers);
 	if (copy_mm(clone_flags, p))
 		goto bad_fork_cleanup_sighand;
 	if (copy_namespace(clone_flags, p))
kernel/posix-timers.c +1288 -0

1,288 lines not on this page · raw message

kernel/signal.c +35 -12

77 lines not on this page · raw message

kernel/timer.c +39 -15

139 lines not on this page · raw message

Binary files linux-2.5.42-bk2-kb/scripts/fixdep and linux/scripts/fixdep differ