[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-kernel
Subject:    POSIX 1003.1b timer/clock patch for 2.3.11
From:       "Robert H. de Vries" <rhdv () rhdv ! cistron ! nl>
Date:       1999-07-25 14:48:55
[Download RAW message or body]

Hi,

Attached you will find a patch to add POSIX 1003.1b (aka POSIX.4) clocks and
timers.
The code is derived from a patch from the university of Kansas. However it has
been so much modified that hardly any of their code (except some of the
structure) is left.
The patch includes modifications for all architectures for the system call
numbers and some other stuff. The core facilities are architecture independent.

I have also made some minor modifications to the signal handling code for the
non RT signals. These signals now also carry the extra information from the RT
signals only it is not in the queue.

Test code is attached in the gzipped/tarred thing. Included there are also the
system call stubs for user land.

Any comments?

Robert

-- 
Robert de Vries
rhdv@rhdv.cistron.nl

["posix_timer.2.3.11.patch" (text/x-c)]

diff -ruN linux-2.3.11-vanilla/arch/alpha/kernel/entry.S linux-2.3.11/arch/alpha/kernel/entry.S
--- linux-2.3.11-vanilla/arch/alpha/kernel/entry.S	Sun Jun 20 11:40:24 1999
+++ linux-2.3.11/arch/alpha/kernel/entry.S	Sat Jul 24 16:31:27 1999
@@ -1143,3 +1143,11 @@
 	.quad sys_capget
 	.quad sys_capset
 	.quad sys_sendfile			/* 370 */
+	.quad sys_timer_create
+	.quad sys_timer_settime
+	.quad sys_timer_gettime
+	.quad sys_timer_setoverrun
+	.quad sys_timer_delete			/* 375 */
+	.quad sys_clock_gettime
+	.quad sys_clock_settime
+	.quad sys_clock_getres			/* 378 */
diff -ruN linux-2.3.11-vanilla/arch/arm/kernel/calls.S linux-2.3.11/arch/arm/kernel/calls.S
--- linux-2.3.11-vanilla/arch/arm/kernel/calls.S	Sat Jul 24 16:26:05 1999
+++ linux-2.3.11/arch/arm/kernel/calls.S	Sat Jul 24 16:31:27 1999
@@ -200,8 +200,16 @@
 		.long	SYMBOL_NAME(sys_ni_syscall)
 		.long	SYMBOL_NAME(sys_ni_syscall)
 /* 190 */	.long	SYMBOL_NAME(sys_vfork_wrapper)
+		.long	SYMBOL_NAME(sys_timer_create)
+		.long	SYMBOL_NAME(sys_timer_settime)
+		.long	SYMBOL_NAME(sys_timer_gettime)
+		.long	SYMBOL_NAME(sys_timer_getoverrun)
+/* 195 */	.long	SYMBOL_NAME(sys_timer_delete)
+		.long	SYMBOL_NAME(sys_clock_gettime)
+		.long	SYMBOL_NAME(sys_clock_settime)
+		.long	SYMBOL_NAME(sys_clock_getres)
 
-		.rept	NR_syscalls-186
+		.rept	NR_syscalls-198
 			.long	SYMBOL_NAME(sys_ni_syscall)
 		.endr
 #endif
diff -ruN linux-2.3.11-vanilla/arch/i386/kernel/entry.S linux-2.3.11/arch/i386/kernel/entry.S
--- linux-2.3.11-vanilla/arch/i386/kernel/entry.S	Sat Jul 24 16:26:05 1999
+++ linux-2.3.11/arch/i386/kernel/entry.S	Sat Jul 24 16:31:27 1999
@@ -560,6 +560,14 @@
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
 	.long SYMBOL_NAME(sys_vfork)            /* 190 */
+	.long SYMBOL_NAME(sys_timer_create)
+	.long SYMBOL_NAME(sys_timer_settime)
+	.long SYMBOL_NAME(sys_timer_gettime)
+	.long SYMBOL_NAME(sys_timer_getoverrun)
+	.long SYMBOL_NAME(sys_timer_delete)	/* 195 */
+	.long SYMBOL_NAME(sys_clock_gettime)
+	.long SYMBOL_NAME(sys_clock_settime)
+	.long SYMBOL_NAME(sys_clock_getres)	/* 198 */
 
 	/*
 	 * NOTE!! This doesn't have to be exact - we just have
@@ -567,6 +575,6 @@
 	 * entries. Don't panic if you notice that this hasn't
 	 * been shrunk every time we add a new system call.
 	 */
-	.rept NR_syscalls-190
+	.rept NR_syscalls-198
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -ruN linux-2.3.11-vanilla/arch/m68k/kernel/entry.S linux-2.3.11/arch/m68k/kernel/entry.S
--- linux-2.3.11-vanilla/arch/m68k/kernel/entry.S	Sun Jun 20 11:40:26 1999
+++ linux-2.3.11/arch/m68k/kernel/entry.S	Sat Jul 24 16:31:27 1999
@@ -609,6 +609,14 @@
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
 	.long SYMBOL_NAME(sys_vfork)            /* 190 */
+	.long SYMBOL_NAME(sys_timer_create)
+	.long SYMBOL_NAME(sys_timer_settime)
+	.long SYMBOL_NAME(sys_timer_gettime)
+	.long SYMBOL_NAME(sys_timer_getoverrun)
+	.long SYMBOL_NAME(sys_timer_delete)	/* 195 */
+	.long SYMBOL_NAME(sys_clock_gettime)
+	.long SYMBOL_NAME(sys_clock_settime)
+	.long SYMBOL_NAME(sys_clock_getres)	/* 198 */
 
 	.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
 		.long SYMBOL_NAME(sys_ni_syscall)
diff -ruN linux-2.3.11-vanilla/arch/mips/kernel/syscalls.h linux-2.3.11/arch/mips/kernel/syscalls.h
--- linux-2.3.11-vanilla/arch/mips/kernel/syscalls.h	Thu Jul  1 20:36:18 1999
+++ linux-2.3.11/arch/mips/kernel/syscalls.h	Sat Jul 24 16:31:27 1999
@@ -225,3 +225,11 @@
 SYS(sys_sendfile, 3)
 SYS(sys_ni_syscall, 0)
 SYS(sys_ni_syscall, 0)
+SYS(sys_timer_create, 3)			/* 4210 */
+SYS(sys_timer_settime, 4)
+SYS(sys_timer_gettime, 2)
+SYS(sys_timer_getoverrun, 1)
+SYS(sys_timer_delete, 1)
+SYS(sys_clock_gettime, 2)			/* 4215 */
+SYS(sys_clock_settime, 2)
+SYS(sys_clock_getres, 2)
diff -ruN linux-2.3.11-vanilla/arch/ppc/kernel/misc.S linux-2.3.11/arch/ppc/kernel/misc.S
--- linux-2.3.11-vanilla/arch/ppc/kernel/misc.S	Thu Jul  1 20:36:20 1999
+++ linux-2.3.11/arch/ppc/kernel/misc.S	Sat Jul 24 16:31:27 1999
@@ -894,4 +894,12 @@
 	.long sys_ni_syscall		/* streams1 */
 	.long sys_ni_syscall		/* streams2 */
 	.long sys_vfork
-	.space (NR_syscalls-183)*4
+	.long sys_timer_create	/* 190 */
+	.long sys_timer_settime
+	.long sys_timer_gettime
+	.long sys_timer_getoverrun
+	.long sys_timer_delete
+	.long sys_clock_gettime	/* 195 */
+	.long sys_clock_settime
+	.long sys_clock_getres	/* 197 */
+	.space (NR_syscalls-197)*4
diff -ruN linux-2.3.11-vanilla/arch/sparc/kernel/systbls.S linux-2.3.11/arch/sparc/kernel/systbls.S
--- linux-2.3.11-vanilla/arch/sparc/kernel/systbls.S	Sun Jun 20 11:39:49 1999
+++ linux-2.3.11/arch/sparc/kernel/systbls.S	Sat Jul 24 16:31:27 1999
@@ -68,7 +68,8 @@
 /*240*/	.long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, \
sys_sched_getscheduler  /*245*/	.long sys_sched_yield, sys_sched_get_priority_max, \
sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep  /*250*/	.long sys_mremap, \
                sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-/*255*/	.long sys_aplib, sys_nis_syscall
+/*255*/	.long sys_aplib, sys_timer_create, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+/*260*/ .long sys_timer_delete, sys_clock_gettime, sys_clock_settime, sys_clock_getres
 
 	/* Now the SunOS syscall table. */
 
diff -ruN linux-2.3.11-vanilla/arch/sparc64/kernel/systbls.S linux-2.3.11/arch/sparc64/kernel/systbls.S
--- linux-2.3.11-vanilla/arch/sparc64/kernel/systbls.S	Sun Jun 20 11:43:00 1999
+++ linux-2.3.11/arch/sparc64/kernel/systbls.S	Sat Jul 24 16:31:27 1999
@@ -68,7 +68,8 @@
 /*240*/	.word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, \
                sys_sched_getscheduler
 	.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, \
sys32_sched_rr_get_interval, sys32_nanosleep  /*250*/	.word sys_mremap, sys_sysctl, sys_getsid, \
                sys_fdatasync, sys32_nfsservctl
-	.word sys_aplib
+/*255*/	.word sys_aplib, sys_timer_create, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+/*260*/ .word sys_timer_delete, sys_clock_gettime, sys_clock_settime, sys_clock_getres
 
 	/* Now the 64-bit native Linux syscall table. */
 
@@ -127,7 +128,8 @@
 /*240*/	.word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, \
                sys_sched_getscheduler
 	.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, \
sys_sched_rr_get_interval, sys_nanosleep  /*250*/	.word sys_mremap, sys_sysctl, sys_getsid, \
                sys_fdatasync, sys_nfsservctl
-	.word sys_aplib
+/*255*/	.word sys_aplib, sys_timer_create, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+/*260*/ .word sys_timer_delete, sys_clock_gettime, sys_clock_settime, sys_clock_getres
 
 	/* Now the 32-bit SunOS syscall table. */
 
diff -ruN linux-2.3.11-vanilla/include/asm-alpha/siginfo.h linux-2.3.11/include/asm-alpha/siginfo.h
--- linux-2.3.11-vanilla/include/asm-alpha/siginfo.h	Sun Jun 20 11:39:59 1999
+++ linux-2.3.11/include/asm-alpha/siginfo.h	Sat Jul 24 16:31:27 1999
@@ -67,6 +67,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_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
diff -ruN linux-2.3.11-vanilla/include/asm-alpha/unistd.h linux-2.3.11/include/asm-alpha/unistd.h
--- linux-2.3.11-vanilla/include/asm-alpha/unistd.h	Thu Jan 21 20:26:30 1999
+++ linux-2.3.11/include/asm-alpha/unistd.h	Sat Jul 24 16:31:27 1999
@@ -308,6 +308,14 @@
 #define __NR_capget			368
 #define __NR_capset			369
 #define __NR_sendfile			370
+#define __NR_timer_create		371
+#define __NR_timer_settime		372
+#define __NR_timer_gettime		373
+#define __NR_timer_getoverrun		374
+#define __NR_timer_delete		375
+#define __NR_clock_gettime		376
+#define __NR_clock_settime		377
+#define __NR_clock_getres		378
 
 #if defined(__LIBRARY__) && defined(__GNUC__)
 
diff -ruN linux-2.3.11-vanilla/include/asm-arm/siginfo.h linux-2.3.11/include/asm-arm/siginfo.h
--- linux-2.3.11-vanilla/include/asm-arm/siginfo.h	Sun Jun 20 11:39:59 1999
+++ linux-2.3.11/include/asm-arm/siginfo.h	Sat Jul 24 16:31:27 1999
@@ -67,6 +67,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_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
diff -ruN linux-2.3.11-vanilla/include/asm-arm/unistd.h linux-2.3.11/include/asm-arm/unistd.h
--- linux-2.3.11-vanilla/include/asm-arm/unistd.h	Mon Jun 21 22:33:31 1999
+++ linux-2.3.11/include/asm-arm/unistd.h	Sat Jul 24 16:31:27 1999
@@ -198,6 +198,14 @@
 					/* 188 reserved */
 					/* 189 reserved */
 #define __NR_vfork			(__NR_SYSCALL_BASE+190)
+#define __NR_timer_create		(__NR_SYSCALL_BASE+191)
+#define __NR_timer_settime		(__NR_SYSCALL_BASE+192)
+#define __NR_timer_gettime		(__NR_SYSCALL_BASE+193)
+#define __NR_timer_getoverrun		(__NR_SYSCALL_BASE+194)
+#define __NR_timer_delete		(__NR_SYSCALL_BASE+195)
+#define __NR_clock_gettime		(__NR_SYSCALL_BASE+196)
+#define __NR_clock_settime		(__NR_SYSCALL_BASE+197)
+#define __NR_clock_getres		(__NR_SYSCALL_BASE+198)
 
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
diff -ruN linux-2.3.11-vanilla/include/asm-i386/siginfo.h linux-2.3.11/include/asm-i386/siginfo.h
--- linux-2.3.11-vanilla/include/asm-i386/siginfo.h	Sun Jun 20 11:39:59 1999
+++ linux-2.3.11/include/asm-i386/siginfo.h	Sat Jul 24 16:31:27 1999
@@ -31,13 +31,14 @@
 		struct {
 			unsigned int _timer1;
 			unsigned int _timer2;
+			sigval_t _sigval2;	/* FIXME: must map to _sigval below because it is the same */
 		} _timer;
 
 		/* POSIX.1b signals */
 		struct {
 			pid_t _pid;		/* sender's pid */
 			uid_t _uid;		/* sender's uid */
-			sigval_t _sigval;
+			sigval_t _sigval;	/* FIXME: move out of union together with _sigval2 */
 		} _rt;
 
 		/* SIGCHLD */
@@ -67,6 +68,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_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
diff -ruN linux-2.3.11-vanilla/include/asm-i386/unistd.h linux-2.3.11/include/asm-i386/unistd.h
--- linux-2.3.11-vanilla/include/asm-i386/unistd.h	Wed Jan 20 20:06:24 1999
+++ linux-2.3.11/include/asm-i386/unistd.h	Sat Jul 24 16:31:27 1999
@@ -195,6 +195,14 @@
 #define __NR_getpmsg		188	/* some people actually want streams */
 #define __NR_putpmsg		189	/* some people actually want streams */
 #define __NR_vfork		190
+#define __NR_timer_create	191
+#define __NR_timer_settime	192
+#define __NR_timer_gettime	193
+#define __NR_timer_getoverrun	194
+#define __NR_timer_delete	195
+#define __NR_clock_gettime	196
+#define __NR_clock_settime	197
+#define __NR_clock_getres	198
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
diff -ruN linux-2.3.11-vanilla/include/asm-m68k/siginfo.h linux-2.3.11/include/asm-m68k/siginfo.h
--- linux-2.3.11-vanilla/include/asm-m68k/siginfo.h	Wed Aug 19 22:24:44 1998
+++ linux-2.3.11/include/asm-m68k/siginfo.h	Sat Jul 24 16:31:27 1999
@@ -67,6 +67,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_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
diff -ruN linux-2.3.11-vanilla/include/asm-m68k/unistd.h linux-2.3.11/include/asm-m68k/unistd.h
--- linux-2.3.11-vanilla/include/asm-m68k/unistd.h	Tue Jan 19 19:58:34 1999
+++ linux-2.3.11/include/asm-m68k/unistd.h	Sat Jul 24 16:31:27 1999
@@ -194,6 +194,14 @@
 #define __NR_getpmsg		188	/* some people actually want streams */
 #define __NR_putpmsg		189	/* some people actually want streams */
 #define __NR_vfork		190
+#define __NR_timer_create	191
+#define __NR_timer_settime	192
+#define __NR_timer_gettime	193
+#define __NR_timer_getoverrun	194
+#define __NR_timer_delete	195
+#define __NR_clock_gettime	196
+#define __NR_clock_settime	197
+#define __NR_clock_getres	198
 
 /* user-visible error numbers are in the range -1 - -122: see
    <asm-m68k/errno.h> */
diff -ruN linux-2.3.11-vanilla/include/asm-mips/siginfo.h linux-2.3.11/include/asm-mips/siginfo.h
--- linux-2.3.11-vanilla/include/asm-mips/siginfo.h	Sun Jun 20 11:39:59 1999
+++ linux-2.3.11/include/asm-mips/siginfo.h	Sat Jul 24 16:31:27 1999
@@ -75,6 +75,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_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
diff -ruN linux-2.3.11-vanilla/include/asm-mips/unistd.h linux-2.3.11/include/asm-mips/unistd.h
--- linux-2.3.11-vanilla/include/asm-mips/unistd.h	Thu Jul  1 20:36:33 1999
+++ linux-2.3.11/include/asm-mips/unistd.h	Sat Jul 24 16:31:27 1999
@@ -1196,6 +1196,14 @@
 #define __NR_sendfile			(__NR_Linux + 207)
 #define __NR_getpmsg			(__NR_Linux + 208)
 #define __NR_putpmsg			(__NR_Linux + 209)
+#define __NR_timer_create		(__NR_Linux + 210)
+#define __NR_timer_settime		(__NR_Linux + 211)
+#define __NR_timer_gettime		(__NR_Linux + 212)
+#define __NR_timer_getoverrun		(__NR_Linux + 213)
+#define __NR_timer_delete		(__NR_Linux + 214)
+#define __NR_clock_gettime		(__NR_Linux + 215)
+#define __NR_clock_settime		(__NR_Linux + 216)
+#define __NR_clock_getres		(__NR_Linux + 217)
 
 /*
  * Offset of the last Linux flavoured syscall
diff -ruN linux-2.3.11-vanilla/include/asm-ppc/siginfo.h linux-2.3.11/include/asm-ppc/siginfo.h
--- linux-2.3.11-vanilla/include/asm-ppc/siginfo.h	Sun Jun 20 11:39:59 1999
+++ linux-2.3.11/include/asm-ppc/siginfo.h	Sat Jul 24 16:31:27 1999
@@ -67,6 +67,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_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -122,7 +124,7 @@
  * SIGSEGV si_codes
  */
 #define SEGV_MAPERR	1	/* address not mapped to object */
-#define SRGV_ACCERR	2	/* invalid permissions for mapped object */
+#define SEGV_ACCERR	2	/* invalid permissions for mapped object */
 #define NSIGSEGV	2
 
 /*
diff -ruN linux-2.3.11-vanilla/include/asm-ppc/unistd.h linux-2.3.11/include/asm-ppc/unistd.h
--- linux-2.3.11-vanilla/include/asm-ppc/unistd.h	Thu Jul  1 20:36:34 1999
+++ linux-2.3.11/include/asm-ppc/unistd.h	Sat Jul 24 16:31:27 1999
@@ -194,6 +194,14 @@
 #define __NR_getpmsg		187	/* some people actually want streams */
 #define __NR_putpmsg		188	/* some people actually want streams */
 #define __NR_vfork		189
+#define __NR_timer_create	190
+#define __NR_timer_settime	191
+#define __NR_timer_gettime	192
+#define __NR_timer_getoverrun	193
+#define __NR_timer_delete	194
+#define __NR_clock_gettime	195
+#define __NR_clock_settime	196
+#define __NR_clock_getres	197
 
 #define __NR(n)	#n
 
diff -ruN linux-2.3.11-vanilla/include/asm-sparc/siginfo.h linux-2.3.11/include/asm-sparc/siginfo.h
--- linux-2.3.11-vanilla/include/asm-sparc/siginfo.h	Sun Jun 20 11:40:43 1999
+++ linux-2.3.11/include/asm-sparc/siginfo.h	Sat Jul 24 16:31:28 1999
@@ -70,6 +70,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_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -126,7 +128,7 @@
  * SIGSEGV si_codes
  */
 #define SEGV_MAPERR	1	/* address not mapped to object */
-#define SRGV_ACCERR	2	/* invalid permissions for mapped object */
+#define SEGV_ACCERR	2	/* invalid permissions for mapped object */
 #define NSIGSEGV	2
 
 /*
diff -ruN linux-2.3.11-vanilla/include/asm-sparc/unistd.h linux-2.3.11/include/asm-sparc/unistd.h
--- linux-2.3.11-vanilla/include/asm-sparc/unistd.h	Sun Jun 20 11:40:00 1999
+++ linux-2.3.11/include/asm-sparc/unistd.h	Sat Jul 24 16:31:28 1999
@@ -271,6 +271,14 @@
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
 #define __NR_aplib              255
+#define __NR_timer_create	256
+#define __NR_timer_settime	257
+#define __NR_timer_gettime	258
+#define __NR_timer_getoverrun	259
+#define __NR_timer_delete	260
+#define __NR_clock_gettime	261
+#define __NR_clock_settime	262
+#define __NR_clock_getres	263
 
 #define _syscall0(type,name) \
 type name(void) \
diff -ruN linux-2.3.11-vanilla/include/asm-sparc64/siginfo.h linux-2.3.11/include/asm-sparc64/siginfo.h
--- linux-2.3.11-vanilla/include/asm-sparc64/siginfo.h	Sun Jun 20 11:40:00 1999
+++ linux-2.3.11/include/asm-sparc64/siginfo.h	Sat Jul 24 16:31:28 1999
@@ -129,6 +129,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_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -185,7 +187,7 @@
  * SIGSEGV si_codes
  */
 #define SEGV_MAPERR	1	/* address not mapped to object */
-#define SRGV_ACCERR	2	/* invalid permissions for mapped object */
+#define SEGV_ACCERR	2	/* invalid permissions for mapped object */
 #define NSIGSEGV	2
 
 /*
diff -ruN linux-2.3.11-vanilla/include/asm-sparc64/unistd.h linux-2.3.11/include/asm-sparc64/unistd.h
--- linux-2.3.11-vanilla/include/asm-sparc64/unistd.h	Sun Jun 20 11:40:00 1999
+++ linux-2.3.11/include/asm-sparc64/unistd.h	Sat Jul 24 16:31:28 1999
@@ -271,6 +271,14 @@
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
 #define __NR_aplib              255
+#define __NR_timer_create	256
+#define __NR_timer_settime	257
+#define __NR_timer_gettime	258
+#define __NR_timer_getoverrun	259
+#define __NR_timer_delete	260
+#define __NR_clock_gettime	261
+#define __NR_clock_settime	262
+#define __NR_clock_getres	263
 
 #define _syscall0(type,name) \
 type name(void) \
diff -ruN linux-2.3.11-vanilla/include/linux/limits.h linux-2.3.11/include/linux/limits.h
--- linux-2.3.11-vanilla/include/linux/limits.h	Tue Dec  2 22:44:40 1997
+++ linux-2.3.11/include/linux/limits.h	Sat Jul 24 16:31:28 1999
@@ -14,6 +14,8 @@
 #define PATH_MAX        4095	/* # chars in a path name */
 #define PIPE_BUF        4096	/* # bytes in atomic write to a pipe */
 
+#define MAX_ITIMERS       32    /* # POSIX.1b itimers per process */
+
 #define RTSIG_MAX	  32
 
 #endif
diff -ruN linux-2.3.11-vanilla/include/linux/sched.h linux-2.3.11/include/linux/sched.h
--- linux-2.3.11-vanilla/include/linux/sched.h	Sat Jul 24 16:26:13 1999
+++ linux-2.3.11/include/linux/sched.h	Sat Jul 24 16:46:56 1999
@@ -35,6 +35,7 @@
 #define CLONE_PID	0x00001000	/* set if pid shared */
 #define CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
 #define CLONE_VFORK	0x00004000	/* set if the parent wants the child to wake it up on mm_release */
+#define CLONE_ITIMERS   0x00008000      /* set if POSIX.1b itimers are shared */
 
 /*
  * These are the constant used to fake the fixed-point load-average
@@ -223,6 +224,26 @@
  */
 struct user_struct;
 
+/* POSIX.1b interval timer structure. */
+struct k_itimer {
+	spinlock_t it_lock;
+	clockid_t it_clock;		/* which timer type */
+	timer_t it_id;			/* timer id */
+	int it_overrun;			/* number of signals overrun */
+	struct sigevent it_signal;	/* signal to be delivered */
+	struct timespec it_interval;	/* interval (rounded to jiffies) */
+	int it_incr;			/* interval specified in jiffies */
+	struct task_struct *it_process;	/* process to send signal to */
+	struct timer_list it_timer;
+};
+
+/* Structure to maintain the dynamically created POSIX.1b interval timers. */
+struct itimer_struct {
+	atomic_t count;
+	spinlock_t its_lock;
+	struct k_itimer *itimer[MAX_ITIMERS];	
+};
+
 struct task_struct {
 /* these are hardcoded - don't touch */
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
@@ -278,6 +299,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 itimer_struct *posix_timers; /* POSIX.1b Interval Timers */
 	struct tms times;
 	unsigned long start_time;
 	long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
@@ -315,6 +337,7 @@
 	spinlock_t sigmask_lock;	/* Protects signal and blocked */
 	struct signal_struct *sig;
 	sigset_t signal, blocked;
+	siginfo_t nrt_info[SIGRTMIN];	/* siginfo for non RT signals */
 	struct signal_queue *sigqueue, **sigqueue_tail;
 	unsigned long sas_ss_sp;
 	size_t sas_ss_size;
@@ -364,6 +387,7 @@
 /* chld wait */	__WAIT_QUEUE_HEAD_INITIALIZER(name.wait_chldexit), NULL, \
 /* timeout */	SCHED_OTHER,0,0,0,0,0,0,0, \
 /* timer */	{ NULL, NULL, 0, 0, it_real_fn }, \
+/* POSIX.1b timer */ NULL, \
 /* utime */	{0,0,0,0},0, \
 /* per CPU times */ {0, }, {0, }, \
 /* flt */	0,0,0,0,0,0, \
@@ -382,7 +406,7 @@
 /* fs */	&init_fs, \
 /* files */	&init_files, \
 /* mm */	NULL, &init_mm, \
-/* signals */	SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
+/* signals */	SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, {{0,},}, NULL, &init_task.sigqueue, 0, 0, \
\  }
 
 #ifndef INIT_TASK_SIZE
@@ -614,6 +638,7 @@
 extern void exit_fs(struct task_struct *);
 extern void exit_files(struct task_struct *);
 extern void exit_sighand(struct task_struct *);
+extern void exit_itimers(struct task_struct *);
 
 extern int do_execve(char *, char **, char **, struct pt_regs *);
 extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
diff -ruN linux-2.3.11-vanilla/include/linux/time.h linux-2.3.11/include/linux/time.h
--- linux-2.3.11-vanilla/include/linux/time.h	Mon Dec 28 07:18:28 1998
+++ linux-2.3.11/include/linux/time.h	Sat Jul 24 16:31:28 1999
@@ -26,6 +26,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)
 {
@@ -34,15 +47,15 @@
 
 	if (sec >= (MAX_JIFFY_OFFSET / HZ))
 		return MAX_JIFFY_OFFSET;
-	nsec += 1000000000L / HZ - 1;
-	nsec /= 1000000000L / HZ;
+	nsec += NSEC_PER_SEC / HZ - 1;
+	nsec /= NSEC_PER_SEC / HZ;
 	return HZ * sec + nsec;
 }
 
 static __inline__ void
 jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
 {
-	value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
+	value->tv_nsec = (jiffies % HZ) * (NSEC_PER_SEC / HZ);
 	value->tv_sec = jiffies / HZ;
 }
  
@@ -88,5 +101,24 @@
 	struct	timeval it_interval;	/* timer interval */
 	struct	timeval it_value;	/* current value */
 };
+
+
+/* 
+ * Data types for POSIX.1b interval timers.
+ */
+typedef int clockid_t;
+typedef int timer_t;
+
+/*
+ * The IDs of the various system clocks (for POSIX.1b interval timers).
+ */
+#define CLOCK_REALTIME 0
+
+/*
+ * The various flags for setting POSIX.1b interval timers.
+ */
+
+#define TIMER_ABSTIME 0x01
+
 
 #endif
diff -ruN linux-2.3.11-vanilla/kernel/exit.c linux-2.3.11/kernel/exit.c
--- linux-2.3.11-vanilla/kernel/exit.c	Sat Jul 24 16:26:13 1999
+++ linux-2.3.11/kernel/exit.c	Sat Jul 24 16:37:05 1999
@@ -229,6 +229,34 @@
 	__exit_sighand(tsk);
 }
 
+static inline void __exit_itimers(struct task_struct *tsk)
+{
+	struct itimer_struct *timers = tsk->posix_timers;
+	struct k_itimer *timr;
+	int i;
+
+	if (timers == NULL) return;
+	
+	if (atomic_dec_and_test(&timers->count)) {
+		tsk->posix_timers = NULL;
+		for (i = 0; i < MAX_ITIMERS; i++) {
+			timr = timers->itimer[i];
+			if (timr) {
+				start_bh_atomic();
+				del_timer(&timr->it_timer);
+				end_bh_atomic();
+				kfree(timr);
+			}
+		}
+		kfree(timers);
+	}
+}
+
+void exit_itimers(struct task_struct *tsk)
+{
+	__exit_itimers(tsk);
+}
+
 /*
  * Turn us into a lazy TLB process if we
  * aren't already..
@@ -352,6 +380,7 @@
 	__exit_files(tsk);
 	__exit_fs(tsk);
 	__exit_sighand(tsk);
+	__exit_itimers(tsk);
 	exit_thread();
 	tsk->state = TASK_ZOMBIE;
 	tsk->exit_code = code;
diff -ruN linux-2.3.11-vanilla/kernel/fork.c linux-2.3.11/kernel/fork.c
--- linux-2.3.11-vanilla/kernel/fork.c	Sat Jul 24 16:26:14 1999
+++ linux-2.3.11/kernel/fork.c	Sat Jul 24 16:34:27 1999
@@ -551,6 +551,24 @@
 	p->flags = new_flags;
 }
 
+
+static inline int copy_itimers(unsigned long clone_flags, struct task_struct * tsk)
+{
+	if (clone_flags & CLONE_ITIMERS) {
+		atomic_inc(&tsk->posix_timers->count);
+		return 0;
+	}
+
+	tsk->posix_timers = kmalloc(sizeof(*tsk->posix_timers), GFP_KERNEL);
+	if (tsk->posix_timers == NULL) return -1;
+	spin_lock_init(&tsk->posix_timers->its_lock);
+	atomic_set(&tsk->posix_timers->count, 1);
+	memset(tsk->posix_timers->itimer, 0, sizeof(tsk->posix_timers->itimer));
+
+	return 0;
+}
+
+
 /*
  *  Ok, this is the main fork-routine. It copies the system process
  * information (task[nr]) and sets up the necessary registers. It
@@ -649,6 +667,8 @@
 		goto bad_fork_cleanup_files;
 	if (copy_sighand(clone_flags, p))
 		goto bad_fork_cleanup_fs;
+	if (copy_itimers(clone_flags, p))
+		goto bad_fork_cleanup_itimers;
 	if (copy_mm(clone_flags, p))
 		goto bad_fork_cleanup_sighand;
 	retval = copy_thread(0, clone_flags, usp, p, regs);
@@ -693,6 +713,8 @@
 		down(&sem);
 	return retval;
 
+bad_fork_cleanup_itimers:
+	exit_itimers(p);
 bad_fork_cleanup_sighand:
 	exit_sighand(p);
 bad_fork_cleanup_fs:
diff -ruN linux-2.3.11-vanilla/kernel/itimer.c linux-2.3.11/kernel/itimer.c
--- linux-2.3.11-vanilla/kernel/itimer.c	Tue Nov 24 22:51:44 1998
+++ linux-2.3.11/kernel/itimer.c	Sat Jul 24 16:31:28 1999
@@ -9,14 +9,16 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/malloc.h>
+#include <linux/time.h>
 
 #include <asm/uaccess.h>
 
 /*
- * change timeval to jiffies, trying to avoid the 
+ * change timeval to jiffies, trying to avoid the
  * most obvious overflows..
  *
- * The tv_*sec values are signed, but nothing seems to 
+ * The tv_*sec values are signed, but nothing seems to
  * indicate whether we really should use them as signed values
  * when doing itimers. POSIX doesn't mention this (but if
  * alarm() uses itimers without checking, we have to use unsigned
@@ -168,6 +170,389 @@
 		return error;
 
 	if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
-		return -EFAULT; 
+		return -EFAULT;
+	return 0;
+}
+
+/* PRECONDITION:
+ * timr->it_lock must be locked
+ */
+static void timer_notify_task(struct k_itimer *timr)
+{
+	struct siginfo info;
+	int ret;
+
+	if (timr->it_signal.sigev_notify == SIGEV_SIGNAL) {
+
+		/* Send signal to the process that owns this timer. */
+		info.si_signo = timr->it_signal.sigev_signo;
+		info.si_errno = 0;
+		info.si_code = SI_TIMER;
+		/* TODO: if someone has better ideas what to put in 
+		 * the next two fields...
+		 * si_timer1 is currently used in signal.c to check
+		 * whether a signal from this timer is already in the signal
+		 * queue.
+		 */
+		info.si_timer1 = timr->it_id;
+		info.si_timer2 = 0;
+		info.si_value = timr->it_signal.sigev_value;
+		ret = send_sig_info(info.si_signo, &info, timr->it_process);
+		switch (ret) {
+		case 0:		/* all's well */
+			timr->it_overrun = 0;
+			break;
+		case 1:	/* signal from this timer was already in the queue */
+			timr->it_overrun++;
+			break;
+		default:
+			printk(KERN_WARNING "sending signal failed: %d\n", ret);
+			break;
+		}
+	}
+}
+
+/* This function gets called when a POSIX.1b interval timer expires. */
+static void posix_timer_fn(unsigned long __data)
+{  
+	struct k_itimer *timr = (struct k_itimer *)__data;
+	unsigned long interval;
+
+	spin_lock(&timr->it_lock);
+	
+	timer_notify_task(timr);
+
+	/* Set up the timer for the next interval (if there is one) */
+	if ((interval = timr->it_incr) == 0) goto out;
+		
+	if (interval > (unsigned long) LONG_MAX)
+		interval = LONG_MAX;
+	timr->it_timer.expires = jiffies + interval;
+	add_timer(&timr->it_timer);
+out:
+	spin_unlock(&timr->it_lock);
+}
+
+/* Find the first available slot for the new timer. */
+static int timer_find_slot(struct itimer_struct *timers)
+{
+	int i;
+
+	for (i = 0; i < MAX_ITIMERS; i++) {
+		if (timers->itimer[i] == NULL) return i;
+	}
+	return -1;
+}
+
+static int good_sigevent(const struct sigevent *sigev)
+{
+	switch (sigev->sigev_notify) {
+	case SIGEV_NONE:
+		break;
+	case SIGEV_SIGNAL:
+		if ((sigev->sigev_signo <= 0) ||
+		    (sigev->sigev_signo > SIGRTMAX))
+			return 0;
+		break;
+	default:
+		return 0;
+	}
+	return 1;
+}
+
+/* Create a POSIX.1b interval timer. */
+
+asmlinkage int sys_timer_create(clockid_t which_clock,
+				struct sigevent *timer_event_spec,
+				timer_t *created_timer_id)
+{
+	int error = 0;
+	struct k_itimer *new_timer = NULL;
+	struct itimer_struct *timers = current->posix_timers;
+	int new_timer_id;
+ 
+	/* Right now, we only support CLOCK_REALTIME for timers. */
+	if (which_clock != CLOCK_REALTIME) return -EINVAL;
+
+	new_timer = (struct k_itimer *)kmalloc(sizeof(*new_timer), GFP_KERNEL);
+	if (new_timer == NULL) return -EAGAIN;
+
+	spin_lock_init(&new_timer->it_lock);
+	new_timer->it_clock = which_clock;
+	new_timer->it_incr = 0;
+	new_timer->it_overrun = 0;
+
+	if (timer_event_spec) {
+		if (copy_from_user(&new_timer->it_signal, timer_event_spec,
+				   sizeof(new_timer->it_signal))) {
+			error = -EFAULT;
+			goto out;
+		}
+		if (!good_sigevent(&new_timer->it_signal)) {
+			error = -EINVAL;
+			goto out;
+		}
+	}
+	else {
+		new_timer->it_signal.sigev_notify = SIGEV_SIGNAL;
+		new_timer->it_signal.sigev_signo = SIGALRM;
+	}
+
+	new_timer->it_interval.tv_sec = 0;
+	new_timer->it_interval.tv_nsec = 0;
+	new_timer->it_process = current;
+	new_timer->it_timer.next = NULL;
+	new_timer->it_timer.prev = NULL;
+	new_timer->it_timer.expires = 0;
+	new_timer->it_timer.data = (unsigned long)new_timer;
+	new_timer->it_timer.function = posix_timer_fn;
+
+	spin_lock(&timers->its_lock);
+
+	new_timer_id = timer_find_slot(timers);
+	if (new_timer_id == -1) {
+		error = -EAGAIN;
+		goto out;
+	}
+	new_timer->it_id = new_timer_id;
+	timers->itimer[new_timer_id] = new_timer;
+	if (timer_event_spec == NULL) {
+		new_timer->it_signal.sigev_value.sival_int = new_timer_id;
+	}
+
+	if (copy_to_user(created_timer_id, &new_timer_id, sizeof(new_timer_id))) {
+		error = -EFAULT;
+		timers->itimer[new_timer_id] = NULL;
+	}
+
+	spin_unlock(&timers->its_lock);
+out:
+	if (error) {
+		kfree(new_timer);
+	}
+	return error;
+}
+
+
+/* good_timespec
+ *
+ * This function checks the elements of a timespec structure.
+ *
+ * Arguments:
+ * ts       : Pointer to the timespec structure to check
+ *
+ * Return value:
+ * If a NULL pointer was passed in, or the tv_nsec field was less than 0 or
+ * greater than NSEC_PER_SEC, or the tv_sec field was less than 0, this
+ * function returns 0. Otherwise it returns 1.
+ */
+
+static int good_timespec(const struct timespec *ts)
+{
+	if (ts == NULL) return 0;
+	if (ts->tv_sec < 0) return 0;
+	if ((ts->tv_nsec < 0) || (ts->tv_nsec >= NSEC_PER_SEC)) return 0;
+	return 1;
+}
+
+static inline struct k_itimer* lock_timer(struct task_struct *tsk, timer_t timer_id)
+{
+	struct k_itimer *timr;
+
+	if ((timer_id < 0) || (timer_id >= MAX_ITIMERS)) return NULL;
+	spin_lock(&tsk->posix_timers->its_lock);
+	timr = tsk->posix_timers->itimer[timer_id];
+	if (timr) spin_lock(&timr->it_lock);
+	spin_unlock(&tsk->posix_timers->its_lock);
+	return timr;
+}
+
+static inline void unlock_timer(struct k_itimer *timr)
+{
+	spin_unlock(&timr->it_lock);
+}
+
+/* Get the time remaining on a POSIX.1b interval timer. */
+static void do_timer_gettime(struct k_itimer *timr,
+			     struct itimerspec *cur_setting)
+{
+	unsigned long expires = timr->it_timer.expires;
+
+	if (expires) expires -= jiffies;
+	
+	jiffies_to_timespec(expires, &cur_setting->it_value);
+	cur_setting->it_interval = timr->it_interval;
+}
+
+/* Get the time remaining on a POSIX.1b interval timer. */
+asmlinkage int sys_timer_gettime(timer_t timer_id, struct itimerspec *setting)
+{
+	struct k_itimer *timr;
+	struct itimerspec cur_setting;
+
+	timr = lock_timer(current, timer_id);
+	if (!timr) return -EINVAL;
+
+	do_timer_gettime(timr, &cur_setting);
+
+	unlock_timer(timr);
+	
+	copy_to_user_ret(setting, &cur_setting, sizeof(cur_setting), -EFAULT);
+
+	return 0;
+}
+
+/* Get the number of overruns of a POSIX.1b interval timer */
+asmlinkage int sys_timer_getoverrun(timer_t timer_id)
+{
+	struct k_itimer *timr;
+	int overrun;
+
+	timr = lock_timer(current, timer_id);
+	if (!timr) return -EINVAL;
+
+	overrun = timr->it_overrun;
+	
+	unlock_timer(timr);
+
+	return overrun;
+}
+
+static void timer_value_abs_to_rel(struct timespec *val)
+{
+	struct timeval tv;
+	struct timespec ts;
+
+	do_gettimeofday(&tv);
+	ts.tv_sec = tv.tv_sec;
+	ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC;
+
+	/* check whether the time lies in the past */
+	if ((val->tv_sec < ts.tv_sec) || 
+	    ((val->tv_sec == ts.tv_sec) &&
+	     (val->tv_nsec <= ts.tv_nsec))) {
+		/* expire immediately */
+		val->tv_sec = 0;
+		val->tv_nsec = 0;
+	}
+	else {
+		val->tv_sec -= ts.tv_sec;
+		val->tv_nsec -= ts.tv_nsec;
+		if (val->tv_nsec < 0) {
+			val->tv_nsec += NSEC_PER_SEC;
+			val->tv_sec--;
+		}
+	}
+}
+
+/* Set a POSIX.1b interval timer. */
+static void do_timer_settime(struct k_itimer *timr, int flags,
+			     struct itimerspec *new_setting,
+			     struct itimerspec *old_setting)
+{
+	/* disable the timer */
+	start_bh_atomic();
+	del_timer(&timr->it_timer);
+	end_bh_atomic();
+
+	if (old_setting) {
+		do_timer_gettime(timr, old_setting);
+	}
+
+	/* switch off the timer when it_value is zero */
+	if ((new_setting->it_value.tv_sec == 0) &&
+	    (new_setting->it_value.tv_nsec == 0)) {
+		timr->it_incr = 0;
+		timr->it_timer.expires = 0;
+		timr->it_interval.tv_sec = 0;
+		timr->it_interval.tv_nsec = 0;
+		return;
+	}
+
+	timr->it_incr = timespec_to_jiffies(&new_setting->it_interval);
+	/* save the interval rounded to jiffies */
+	jiffies_to_timespec(timr->it_incr, &timr->it_interval);
+
+	if (flags & TIMER_ABSTIME) {
+		timer_value_abs_to_rel(&new_setting->it_value);
+	}
+
+	timr->it_timer.expires = timespec_to_jiffies(&new_setting->it_value) + jiffies;
+
+	/*
+	 * For some reason the timer does not fire immediately if expires is
+	 * equal to jiffies, so the timer callback function is called directly.
+	 */
+	if (timr->it_timer.expires == jiffies) {
+		posix_timer_fn((unsigned long)timr);
+	}
+	else {
+		add_timer(&timr->it_timer);
+	}
+}
+
+
+/* Set a POSIX.1b interval timer */
+asmlinkage int sys_timer_settime(timer_t timer_id, int flags,
+				 const struct itimerspec *new_setting,
+				 struct itimerspec *old_setting)
+{
+	struct k_itimer *timr;
+	struct itimerspec new_spec, old_spec;
+	int error = 0;
+
+	timr = lock_timer(current, timer_id);
+	if (!timr) return -EINVAL;
+
+	if (new_setting == NULL) {
+		error = -EINVAL;
+		goto out;
+	}
+
+	if (copy_from_user(&new_spec, new_setting, sizeof(new_spec))) {
+		error = -EFAULT;
+		goto out;
+	}
+
+	if ((!good_timespec(&new_spec.it_interval)) ||
+	    (!good_timespec(&new_spec.it_value))) {
+		error = -EINVAL;
+		goto out;
+	}
+
+	do_timer_settime(timr, flags, &new_spec,
+			 old_setting ? &old_spec : NULL);
+
+	if (old_setting) {
+		if (copy_to_user(old_setting, &old_spec, sizeof(old_spec))) {
+			error = -EFAULT;
+		}
+	}
+
+out:
+	unlock_timer(timr);
+	return error;
+}
+
+
+/* Delete a POSIX.1b interval timer. */
+asmlinkage int sys_timer_delete(timer_t timer_id)
+{
+	struct k_itimer *timr;
+
+	timr = lock_timer(current, timer_id);
+	if (!timr) return -EINVAL;
+
+	start_bh_atomic();
+	del_timer(&timr->it_timer);
+	end_bh_atomic();
+
+	spin_lock(&current->posix_timers->its_lock);
+
+	kfree(timr);
+	current->posix_timers->itimer[timer_id] = NULL;
+
+	spin_unlock(&current->posix_timers->its_lock);
+
 	return 0;
 }
diff -ruN linux-2.3.11-vanilla/kernel/signal.c linux-2.3.11/kernel/signal.c
--- linux-2.3.11-vanilla/kernel/signal.c	Sat Jul 10 16:30:50 1999
+++ linux-2.3.11/kernel/signal.c	Sat Jul 24 16:31:28 1999
@@ -132,17 +132,7 @@
 
 		/* Collect the siginfo appropriate to this signal.  */
 		if (sig < SIGRTMIN) {
-			/* XXX: As an extension, support queueing exactly
-			   one non-rt signal if SA_SIGINFO is set, so that
-			   we can get more detailed information about the
-			   cause of the signal.  */
-			/* Deciding not to init these couple of fields is
-			   more expensive that just initializing them.  */
-			info->si_signo = sig;
-			info->si_errno = 0;
-			info->si_code = 0;
-			info->si_pid = 0;
-			info->si_uid = 0;
+			*info = current->nrt_info[sig];
 		} else {
 			struct signal_queue *q, **pp;
 			pp = &current->sigqueue;
@@ -185,8 +175,6 @@
 			sigdelset(&current->signal, sig);
 		recalc_sigpending(current);
 
-		/* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER,
-		   we need to xchg out the timer overrun values.  */
 	} else {
 		/* XXX: Once CLONE_PID is in to join those "threads" that are
 		   part of the same "process", look for signals sent to the
@@ -247,6 +235,29 @@
 	return 1;
 }
 
+static void set_siginfo(siginfo_t *dst, const siginfo_t *src, int sig)
+{
+	switch ((unsigned long)src) {
+	case 0:
+		dst->si_signo = sig;
+		dst->si_errno = 0;
+		dst->si_code = SI_USER;
+		dst->si_pid = current->pid;
+		dst->si_uid = current->uid;
+		break;
+	case 1:
+		dst->si_signo = sig;
+		dst->si_errno = 0;
+		dst->si_code = SI_KERNEL;
+		dst->si_pid = 0;
+		dst->si_uid = 0;
+		break;
+	default:
+		*dst = *src;
+		break;
+	}
+}
+
 int
 send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
 {
@@ -306,12 +317,10 @@
 
 	if (sig < SIGRTMIN) {
 		/* Non-real-time signals are not queued.  */
-		/* XXX: As an extension, support queueing exactly one
-		   non-rt signal if SA_SIGINFO is set, so that we can
-		   get more detailed information about the cause of
-		   the signal.  */
 		if (sigismember(&t->signal, sig))
 			goto out;
+		set_siginfo(&t->nrt_info[sig], info, sig);
+
 	} else {
 		/* Real-time signals must be queued if sent by sigqueue, or
 		   some other real-time mechanism.  It is implementation
@@ -323,6 +332,21 @@
 
 		struct signal_queue *q = 0;
 
+		/* In case of a POSIX timer generated signal you must check 
+		   if a signal from this timer is already in the queue */
+		if (info && (info->si_code == SI_TIMER)) {
+			for (q = t->sigqueue; q; q = q->next) {
+				if ((q->info.si_code == SI_TIMER) &&
+				    (q->info.si_timer1 == info->si_timer1)) {
+					/* this special value (1) is recognized
+					   only by posix_timer_fn() in
+					   itimer.c */
+					ret = 1;
+					goto out;
+				}
+			}
+		}
+
 		if (atomic_read(&nr_queued_signals) < max_queued_signals) {
 			q = (struct signal_queue *)
 			    kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
@@ -333,25 +357,7 @@
 			q->next = NULL;
 			*t->sigqueue_tail = q;
 			t->sigqueue_tail = &q->next;
-			switch ((unsigned long) info) {
-			case 0:
-				q->info.si_signo = sig;
-				q->info.si_errno = 0;
-				q->info.si_code = SI_USER;
-				q->info.si_pid = current->pid;
-				q->info.si_uid = current->uid;
-				break;
-			case 1:
-				q->info.si_signo = sig;
-				q->info.si_errno = 0;
-				q->info.si_code = SI_KERNEL;
-				q->info.si_pid = 0;
-				q->info.si_uid = 0;
-				break;
-			default:
-				q->info = *info;
-				break;
-			}
+			set_siginfo(&q->info, info, sig);
 		} else {
 			/* If this was sent by a rt mechanism, try again.  */
 			if (info->si_code < 0) {
diff -ruN linux-2.3.11-vanilla/kernel/time.c linux-2.3.11/kernel/time.c
--- linux-2.3.11-vanilla/kernel/time.c	Sun Jun 20 11:42:37 1999
+++ linux-2.3.11/kernel/time.c	Sat Jul 24 16:31:28 1999
@@ -414,3 +414,57 @@
 	ret = do_adjtimex(&txc);
 	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
 }
+
+
+/* POSIX.1b clock functions */
+
+asmlinkage int sys_clock_gettime(clockid_t clock_id, struct timespec *ts)
+{
+	struct timespec kts;
+	struct timeval ktv;
+
+	if (clock_id != CLOCK_REALTIME)	return -EINVAL;
+	
+	if (ts == NULL) return 0;
+		
+	do_gettimeofday(&ktv);
+	kts.tv_sec = ktv.tv_sec;
+	kts.tv_nsec = ktv.tv_usec * NSEC_PER_USEC;
+	if (copy_to_user(ts, &kts, sizeof(kts))) return -EFAULT;
+
+	return 0;
+}
+
+
+asmlinkage int sys_clock_settime(clockid_t clock_id,
+				 const struct timespec *ts)
+{
+	struct timespec new_ts;
+	struct timeval tv;
+
+	if (clock_id != CLOCK_REALTIME)	return -EINVAL;
+
+	if (ts == NULL) return 0;
+
+	if (copy_from_user(&new_ts, ts, sizeof(*ts))) return -EFAULT;
+	tv.tv_sec = new_ts.tv_sec;
+	tv.tv_usec = new_ts.tv_nsec / NSEC_PER_USEC;
+	return do_sys_settimeofday(&tv, NULL);
+}
+
+
+asmlinkage int sys_clock_getres(clockid_t clock_id,
+				struct timespec *res)
+{
+	struct timespec kres;
+
+	if (clock_id != CLOCK_REALTIME) return -EINVAL;
+
+	if (res == NULL) return 0;
+
+	kres.tv_sec = 0;
+	kres.tv_nsec = NSEC_PER_SEC / HZ;
+	if (copy_to_user(res, &kres, sizeof(kres))) return -EFAULT;
+
+	return 0;
+}


["posix_timer_test.tar.gz" (application/x-gzip)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic