[LWN Logo]
[Timeline]
From:	"Robert H. de Vries" <rhdv@rhdv.cistron.nl>
To:	linux-kernel@vger.kernel.org
Subject: POSIX timers for 2.4.0-test7
Date:	Sat, 26 Aug 2000 13:29:12 +0200


--------------Boundary-00=_O8DWS8NIGHEI649WR4VT
Content-Type: text/plain
Content-Transfer-Encoding: 8bit

Hi Linus,

I have updated the POSIX timer patches to work with 2.4.0-test7.
Please consider this patch.
See also http://www.rhdv.cistron.nl/posix.html for more information and
http://www.rhdv.cistron.nl/2.4.0-test7.timer.patch or the attachment for the
patch.

	Robert

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

--------------Boundary-00=_O8DWS8NIGHEI649WR4VT
Content-Type: text/x-c;
  name="2.4.0-test7.timer.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="2.4.0-test7.timer.patch"

Index: linux/arch/alpha/kernel/entry.S
diff -u linux/arch/alpha/kernel/entry.S:1.1.1.10 linux/arch/alpha/kernel/entry.S:1.1.2.8
--- linux/arch/alpha/kernel/entry.S:1.1.1.10	Thu Aug 24 20:39:44 2000
+++ linux/arch/alpha/kernel/entry.S	Thu Aug 24 21:12:29 2000
@@ -1161,3 +1161,8 @@
 	.quad sys_mincore			/* 375 */
 	.quad sys_pciconfig_iobase
 	.quad sys_getdents64
+	.quad sys_timer_create
+	.quad sys_timer_settime
+	.quad sys_timer_gettime			/* 380 */
+	.quad sys_timer_getoverrun
+	.quad sys_timer_delete
Index: linux/arch/alpha/kernel/signal.c
diff -u linux/arch/alpha/kernel/signal.c:1.1.1.3 linux/arch/alpha/kernel/signal.c:1.1.2.3
--- linux/arch/alpha/kernel/signal.c:1.1.1.3	Tue Jun 27 19:29:20 2000
+++ linux/arch/alpha/kernel/signal.c	Fri Jul 21 20:38:50 2000
@@ -53,6 +53,10 @@
 		err = __put_user(*(long *)&from->si_signo, (long *)&to->si_signo);
 		err |= __put_user((short)from->si_code, &to->si_code);
 		switch (from->si_code >> 16) {
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/arm/kernel/calls.S
diff -u linux/arch/arm/kernel/calls.S:1.1.1.5 linux/arch/arm/kernel/calls.S:1.1.2.5
--- linux/arch/arm/kernel/calls.S:1.1.1.5	Thu Aug 24 20:39:47 2000
+++ linux/arch/arm/kernel/calls.S	Thu Aug 24 21:12:31 2000
@@ -227,8 +227,13 @@
 /* 215 */	.long	SYMBOL_NAME(sys_setfsuid)
 		.long	SYMBOL_NAME(sys_setfsgid)
 		.long	SYMBOL_NAME(sys_getdents64)
+		.long	SYMBOL_NAME(sys_timer_create)
+		.long	SYMBOL_NAME(sys_timer_settime)
+/* 220 */	.long	SYMBOL_NAME(sys_timer_gettime)
+		.long	SYMBOL_NAME(sys_timer_getoverrun)
+		.long	SYMBOL_NAME(sys_timer_delete)
 
-		.rept	NR_syscalls-217
+		.rept	NR_syscalls-222
 			.long	SYMBOL_NAME(sys_ni_syscall)
 		.endr
 #endif
Index: linux/arch/arm/kernel/signal.c
diff -u linux/arch/arm/kernel/signal.c:1.1.1.7 linux/arch/arm/kernel/signal.c:1.1.2.5
--- linux/arch/arm/kernel/signal.c:1.1.1.7	Thu Aug 24 20:39:47 2000
+++ linux/arch/arm/kernel/signal.c	Thu Aug 24 21:12:31 2000
@@ -56,6 +56,10 @@
 	switch (from->si_code >> 16) {
 	case __SI_FAULT >> 16:
 		break;
+	case __SI_TIMER >> 16:
+		err |= __put_user(from->si_tid, &to->si_tid);
+		err |= __put_user(from->si_ptr, &to->si_ptr);
+		break;
 	case __SI_CHLD >> 16:
 		err |= __put_user(from->si_utime, &to->si_utime);
 		err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/i386/kernel/entry.S
diff -u linux/arch/i386/kernel/entry.S:1.1.1.11 linux/arch/i386/kernel/entry.S:1.1.2.10
--- linux/arch/i386/kernel/entry.S:1.1.1.11	Thu Aug 24 20:39:50 2000
+++ linux/arch/i386/kernel/entry.S	Thu Aug 24 21:12:33 2000
@@ -643,6 +643,11 @@
 	.long SYMBOL_NAME(sys_madvise)
 	.long SYMBOL_NAME(sys_getdents64)	/* 220 */
 	.long SYMBOL_NAME(sys_fcntl64)
+	.long SYMBOL_NAME(sys_timer_create)
+	.long SYMBOL_NAME(sys_timer_settime)
+	.long SYMBOL_NAME(sys_timer_gettime)
+	.long SYMBOL_NAME(sys_timer_getoverrun)	/* 225 */
+	.long SYMBOL_NAME(sys_timer_delete)
 
 	/*
 	 * NOTE!! This doesn't have to be exact - we just have
@@ -650,6 +655,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-221
+	.rept NR_syscalls-226
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
Index: linux/arch/i386/kernel/signal.c
diff -u linux/arch/i386/kernel/signal.c:1.1.1.7 linux/arch/i386/kernel/signal.c:1.1.2.6
--- linux/arch/i386/kernel/signal.c:1.1.1.7	Wed Jul 12 21:47:35 2000
+++ linux/arch/i386/kernel/signal.c	Fri Jul 21 20:39:00 2000
@@ -52,6 +52,10 @@
 		switch (from->si_code >> 16) {
 		case __SI_FAULT >> 16:
 			break;
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/ia64/kernel/entry.S
diff -u linux/arch/ia64/kernel/entry.S:1.1.1.8 linux/arch/ia64/kernel/entry.S:1.1.4.8
--- linux/arch/ia64/kernel/entry.S:1.1.1.8	Thu Aug 24 20:40:22 2000
+++ linux/arch/ia64/kernel/entry.S	Thu Aug 24 21:12:35 2000
@@ -1198,11 +1198,11 @@
 	data8 sys_newfstat
 	data8 sys_clone2
 	data8 sys_getdents64
-	data8 ia64_ni_syscall			// 1215
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
+	data8 sys_timer_create			// 1215
+	data8 sys_timer_settime
+	data8 sys_timer_gettime
+	data8 sys_timer_getoverrun
+	data8 sys_timer_delete
 	data8 ia64_ni_syscall			// 1220
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall
Index: linux/arch/ia64/kernel/signal.c
diff -u linux/arch/ia64/kernel/signal.c:1.1.1.4 linux/arch/ia64/kernel/signal.c:1.1.4.5
--- linux/arch/ia64/kernel/signal.c:1.1.1.4	Fri Jul 28 20:45:57 2000
+++ linux/arch/ia64/kernel/signal.c	Fri Jul 28 21:31:00 2000
@@ -179,6 +179,10 @@
 		err |= __put_user(from->si_errno, &to->si_errno);
 		err |= __put_user((short)from->si_code, &to->si_code);
 		switch (from->si_code >> 16) {
+		      case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		      case __SI_FAULT >> 16:
 			err |= __put_user(from->si_isr, &to->si_isr);
 		      case __SI_POLL >> 16:
Index: linux/arch/m68k/kernel/entry.S
diff -u linux/arch/m68k/kernel/entry.S:1.1.1.5 linux/arch/m68k/kernel/entry.S:1.1.2.5
--- linux/arch/m68k/kernel/entry.S:1.1.1.5	Thu Aug 24 20:39:57 2000
+++ linux/arch/m68k/kernel/entry.S	Thu Aug 24 21:12:36 2000
@@ -633,6 +633,11 @@
 	.long SYMBOL_NAME(sys_ni_syscall)
 	.long SYMBOL_NAME(sys_ni_syscall)
 	.long SYMBOL_NAME(sys_getdents64)	/* 220 */
+	.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)	/* 225 */
 
 	.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
 		.long SYMBOL_NAME(sys_ni_syscall)
Index: linux/arch/m68k/kernel/signal.c
diff -u linux/arch/m68k/kernel/signal.c:1.1.1.4 linux/arch/m68k/kernel/signal.c:1.1.2.4
--- linux/arch/m68k/kernel/signal.c:1.1.1.4	Tue Jun 27 19:29:30 2000
+++ linux/arch/m68k/kernel/signal.c	Fri Jul 21 20:39:01 2000
@@ -211,6 +211,10 @@
 		switch (from->si_code >> 16) {
 		case __SI_FAULT >> 16:
 			break;
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/mips/kernel/irix5sys.h
diff -u linux/arch/mips/kernel/irix5sys.h:1.1.1.2 linux/arch/mips/kernel/irix5sys.h:1.1.2.2
--- linux/arch/mips/kernel/irix5sys.h:1.1.1.2	Wed May 24 18:58:03 2000
+++ linux/arch/mips/kernel/irix5sys.h	Wed May 24 23:33:53 2000
@@ -235,7 +235,7 @@
 SYS(irix_unimp, 0)			/* 1213  XXX timer_delete()	*/
 SYS(irix_unimp, 0)			/* 1214  XXX timer_settime()	*/
 SYS(irix_unimp, 0)			/* 1215  XXX timer_gettime()	*/
-SYS(irix_unimp, 0)			/* 1216  XXX timer_setoverrun()	*/
+SYS(irix_unimp, 0)			/* 1216  XXX timer_getoverrun()	*/
 SYS(sys_sched_rr_get_interval, 2)	/* 1217  sched_rr_get_interval()V*/
 SYS(sys_sched_yield, 0)			/* 1218  sched_yield()	       V*/
 SYS(sys_sched_getscheduler, 1)		/* 1219  sched_getscheduler()  V*/
Index: linux/arch/mips/kernel/signal.c
diff -u linux/arch/mips/kernel/signal.c:1.1.1.5 linux/arch/mips/kernel/signal.c:1.1.2.4
--- linux/arch/mips/kernel/signal.c:1.1.1.5	Wed Jul 12 21:47:42 2000
+++ linux/arch/mips/kernel/signal.c	Fri Jul 21 20:39:02 2000
@@ -60,6 +60,10 @@
 		switch (from->si_code >> 16) {
 		case __SI_FAULT >> 16:
 			break;
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/mips/kernel/syscalls.h
diff -u linux/arch/mips/kernel/syscalls.h:1.1.1.4 linux/arch/mips/kernel/syscalls.h:1.1.2.4
--- linux/arch/mips/kernel/syscalls.h:1.1.1.4	Thu Aug 24 20:40:03 2000
+++ linux/arch/mips/kernel/syscalls.h	Thu Aug 24 21:12:36 2000
@@ -235,3 +235,8 @@
 SYS(sys_mincore, 3)
 SYS(sys_madvise, 3)
 SYS(sys_getdents64, 3)
+SYS(sys_timer_create, 3)			/* 4220 */
+SYS(sys_timer_settime, 4)
+SYS(sys_timer_gettime, 2)
+SYS(sys_timer_getoverrun, 1)
+SYS(sys_timer_delete, 1)
Index: linux/arch/mips64/kernel/signal.c
diff -u linux/arch/mips64/kernel/signal.c:1.1.1.4 linux/arch/mips64/kernel/signal.c:1.1.2.4
--- linux/arch/mips64/kernel/signal.c:1.1.1.4	Wed Jul 12 21:48:01 2000
+++ linux/arch/mips64/kernel/signal.c	Fri Jul 21 20:39:02 2000
@@ -60,6 +60,10 @@
 		case __SI_FAULT >> 16:
 			err |= __put_user((long)from->si_addr, &to->si_addr);
 			break;
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/ppc/kernel/misc.S
diff -u linux/arch/ppc/kernel/misc.S:1.1.1.11 linux/arch/ppc/kernel/misc.S:1.1.2.9
--- linux/arch/ppc/kernel/misc.S:1.1.1.11	Thu Aug 24 20:40:08 2000
+++ linux/arch/ppc/kernel/misc.S	Thu Aug 24 21:12:39 2000
@@ -1217,6 +1217,11 @@
 	.long sys_pciconfig_iobase 	/* 200 */
 	.long sys_ni_syscall		/* 201 - reserved - MacOnLinux - new */
 	.long sys_getdents64		/* 202 */
-	.rept NR_syscalls-201
+	.long sys_timer_create		/* 203 */
+	.long sys_timer_settime		/* 204 */
+	.long sys_timer_gettime		/* 205 */
+	.long sys_timer_getoverrun	/* 206 */
+	.long sys_timer_delete		/* 207 */
+	.rept NR_syscalls-207
 		.long sys_ni_syscall
 	.endr
Index: linux/arch/ppc/kernel/signal.c
diff -u linux/arch/ppc/kernel/signal.c:1.1.1.3 linux/arch/ppc/kernel/signal.c:1.1.2.3
--- linux/arch/ppc/kernel/signal.c:1.1.1.3	Sat Jul 15 11:39:28 2000
+++ linux/arch/ppc/kernel/signal.c	Fri Jul 21 20:39:03 2000
@@ -78,6 +78,10 @@
 		switch (from->si_code >> 16) {
 		case __SI_FAULT >> 16:
 			break;
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/s390/kernel/entry.S
diff -u linux/arch/s390/kernel/entry.S:1.1.1.3 linux/arch/s390/kernel/entry.S:1.1.2.4
--- linux/arch/s390/kernel/entry.S:1.1.1.3	Thu Aug 24 20:40:27 2000
+++ linux/arch/s390/kernel/entry.S	Thu Aug 24 21:12:39 2000
@@ -604,7 +604,12 @@
         .long  sys_mincore
         .long  sys_madvise
 	.long  sys_getdents64		 /* 220 */
-	.rept  255-220
+	.long  sys_timer_create
+	.long  sys_timer_settime
+	.long  sys_timer_gettime
+	.long  sys_timer_getoverrun
+	.long  sys_timer_delete		 /* 225 */
+	.rept  255-225
 	.long  sys_ni_syscall
 	.endr
 
Index: linux/arch/sh/kernel/signal.c
diff -u linux/arch/sh/kernel/signal.c:1.1.1.8 linux/arch/sh/kernel/signal.c:1.1.2.8
--- linux/arch/sh/kernel/signal.c:1.1.1.8	Sun Aug 20 15:27:26 2000
+++ linux/arch/sh/kernel/signal.c	Sun Aug 20 16:01:29 2000
@@ -55,6 +55,10 @@
 		switch (from->si_code >> 16) {
 		case __SI_FAULT >> 16:
 			break;
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/sparc/kernel/signal.c
diff -u linux/arch/sparc/kernel/signal.c:1.1.1.8 linux/arch/sparc/kernel/signal.c:1.1.2.7
--- linux/arch/sparc/kernel/signal.c:1.1.1.8	Wed Jul 12 21:47:52 2000
+++ linux/arch/sparc/kernel/signal.c	Fri Jul 21 20:39:04 2000
@@ -113,6 +113,10 @@
 		err |= __put_user(from->si_errno, &to->si_errno);
 		err |= __put_user((short)from->si_code, &to->si_code);
 		switch (from->si_code >> 16) {
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/sparc/kernel/systbls.S
diff -u linux/arch/sparc/kernel/systbls.S:1.1.1.10 linux/arch/sparc/kernel/systbls.S:1.1.2.9
--- linux/arch/sparc/kernel/systbls.S:1.1.1.10	Thu Aug 24 20:40:15 2000
+++ linux/arch/sparc/kernel/systbls.S	Thu Aug 24 21:12:40 2000
@@ -51,8 +51,8 @@
 /*150*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
 /*155*/	.long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/	.long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
-/*165*/	.long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
-/*170*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
+/*165*/	.long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_timer_create
+/*170*/	.long sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun, sys_timer_delete, sys_getdents
 /*175*/	.long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*180*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
 /*185*/	.long sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
Index: linux/arch/sparc64/kernel/signal.c
diff -u linux/arch/sparc64/kernel/signal.c:1.1.1.6 linux/arch/sparc64/kernel/signal.c:1.1.2.5
--- linux/arch/sparc64/kernel/signal.c:1.1.1.6	Sun Aug 20 15:27:31 2000
+++ linux/arch/sparc64/kernel/signal.c	Sun Aug 20 16:01:32 2000
@@ -59,6 +59,10 @@
 		err = __put_user(*(long *)&from->si_signo, (long *)&to->si_signo);
 		err |= __put_user((short)from->si_code, &to->si_code);
 		switch (from->si_code >> 16) {
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_ptr, &to->si_ptr);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
Index: linux/arch/sparc64/kernel/sys_sparc32.c
diff -u linux/arch/sparc64/kernel/sys_sparc32.c:1.1.1.21 linux/arch/sparc64/kernel/sys_sparc32.c:1.1.2.18
--- linux/arch/sparc64/kernel/sys_sparc32.c:1.1.1.21	Thu Aug 24 20:40:18 2000
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Thu Aug 24 21:12:41 2000
@@ -4210,3 +4210,113 @@
 	}
 	return error;
 }
+
+struct itimerspec32 {
+	struct  timespec32 it_interval;
+        struct  timespec32 it_value;
+};
+
+int good_timespec(const struct timespec *ts);
+extern struct k_itimer* lock_timer(struct task_struct *tsk, timer_t timer_id);
+static inline void unlock_timer(struct k_itimer *timr)
+{
+	spin_unlock(&timr->it_lock);
+}
+extern void do_timer_gettime(struct k_itimer *timr, struct itimerspec *cur_setting);
+extern void do_timer_settime(struct k_itimer *timr, int flags, struct itimerspec *new_setting, struct itimerspec *old_setting);
+extern int sys_timer_create(clockid_t which_clock, sigevent_t *timer_event_spec, timer_t *created_timer_id);
+
+asmlinkage int sys32_timer_create(clockid_t which_clock, sigevent_t32 *timer_event_spec, timer_t *created_timer_id);
+{
+	mm_segment_t old_fs;
+	sigevent_t tes;
+	int ret, new_timer_id;
+	
+	if (timer_event_spec) {
+		memset (&tes, 0, sizeof(tes));
+		if (get_user (tes.sigev_value.sival_int, &timer_event_spec->sigev_value.sival_int) ||
+		    __get_user (tes.sigev_signo, &timer_event_spec->sigev_signo) ||
+		    __get_user (tes.sigev_notify, &timer_event_spec->sigev_notify) ||
+		    __get_user (tes._sigev_un._sigev_thread._attribute, &timer_event_spec->_sigev_un._sigev_thread._attribute))
+			return -EFAULT;
+		/* As sigev_value is a union of 32bit int and 64bit void *, put the int twice into the ptr, so that when
+		   actually sending the signal both sival_int and sival_ptr will result in correct operation. */
+		tes.sigev_value.sival_ptr = (void *)((long)tes.sigev_value.sival_int<<32 | tes.sigev_value.sival_int);
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		ret = sys_timer_create (which_clock, &tes, &new_timer_id);
+		set_fs (old_fs);
+		if (!ret) {
+			if (put_user (new_timer_id, created_timer_id))
+				return -EFAULT;
+		}
+		return ret;
+	} else
+		return sys_timer_create (which_clock, NULL, created_timer_id);
+}
+
+asmlinkage int sys32_timer_gettime(timer_t timer_id, struct itimerspec32 *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);
+	
+	if (put_user (cur_setting.it_interval.tv_sec, &setting->it_interval.tv_sec) ||
+	    __put_user (cur_setting.it_interval.tv_nsec, &setting->it_interval.tv_nsec) ||
+	    __put_user (cur_setting.it_value.tv_sec, &setting->it_value.tv_sec) ||
+	    __put_user (cur_setting.it_value.tv_nsec, &setting->it_value.tv_nsec))
+		return -EFAULT;		    
+
+	return 0;
+}
+
+asmlinkage int sys32_timer_settime(timer_t timer_id, int flags, struct itimerspec32 *new_setting,
+				   struct itimerspec32 *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 (get_user (new_spec.it_interval.tv_sec, &new_setting->it_interval.tv_sec) ||
+	    __get_user (new_spec.it_interval.tv_nsec, &new_setting->it_interval.tv_nsec) ||
+	    __get_user (new_spec.it_value.tv_sec, &new_setting->it_value.tv_sec) ||
+	    __get_user (new_spec.it_value.tv_nsec, &new_setting->it_value.tv_nsec)) {
+		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 (put_user (old_spec.it_interval.tv_sec, &old_setting->it_interval.tv_sec) ||
+		    __put_user (old_spec.it_interval.tv_nsec, &old_setting->it_interval.tv_nsec) ||
+		    __put_user (old_spec.it_value.tv_sec, &old_setting->it_value.tv_sec) ||
+		    __put_user (old_spec.it_value.tv_nsec, &old_setting->it_value.tv_nsec))
+			error = -EFAULT;
+	}
+
+out:
+	unlock_timer(timr);
+	return error;
+}
Index: linux/arch/sparc64/kernel/systbls.S
diff -u linux/arch/sparc64/kernel/systbls.S:1.1.1.12 linux/arch/sparc64/kernel/systbls.S:1.1.2.11
--- linux/arch/sparc64/kernel/systbls.S:1.1.1.12	Thu Aug 24 20:40:19 2000
+++ linux/arch/sparc64/kernel/systbls.S	Thu Aug 24 21:12:42 2000
@@ -52,8 +52,8 @@
 /*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
 	.word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
 /*160*/	.word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
-	.word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
-/*170*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
+	.word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys32_timer_create
+/*170*/	.word sys32_timer_settime, sys32_timer_gettime, sys32_timer_getoverrun, sys32_timer_delete, sys32_getdents
 	.word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*180*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
 	.word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
@@ -111,8 +111,8 @@
 /*150*/	.word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
 	.word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/	.word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
-	.word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
-/*170*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
+	.word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_timer_create
+/*170*/	.word sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun, sys_timer_delete, sys_getdents
 	.word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*180*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
 	.word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
Index: linux/fs/exec.c
diff -u linux/fs/exec.c:1.1.1.16 linux/fs/exec.c:1.1.2.14
--- linux/fs/exec.c:1.1.1.16	Thu Aug 24 20:42:07 2000
+++ linux/fs/exec.c	Thu Aug 24 21:13:19 2000
@@ -545,6 +545,7 @@
 			
 	flush_signal_handlers(current);
 	flush_old_files(current->files);
+	exit_itimers(current);
 
 	return 0;
 
Index: linux/include/asm-alpha/posix_types.h
diff -u linux/include/asm-alpha/posix_types.h:1.1.1.2 linux/include/asm-alpha/posix_types.h:1.1.2.2
--- linux/include/asm-alpha/posix_types.h:1.1.1.2	Sun Jan 30 22:22:53 2000
+++ linux/include/asm-alpha/posix_types.h	Mon Jan 31 00:26:12 2000
@@ -23,6 +23,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 long	__kernel_sigset_t;	/* at least 32 bits */
Index: linux/include/asm-alpha/siginfo.h
diff -u linux/include/asm-alpha/siginfo.h:1.1.1.3 linux/include/asm-alpha/siginfo.h:1.1.2.4
--- linux/include/asm-alpha/siginfo.h:1.1.1.3	Tue Jun 27 19:31:42 2000
+++ linux/include/asm-alpha/siginfo.h	Fri Jul 21 20:39:07 2000
@@ -29,8 +29,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -67,6 +68,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -85,7 +87,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-alpha/unistd.h
diff -u linux/include/asm-alpha/unistd.h:1.1.1.5 linux/include/asm-alpha/unistd.h:1.1.2.4
--- linux/include/asm-alpha/unistd.h:1.1.1.5	Thu Aug 24 20:42:25 2000
+++ linux/include/asm-alpha/unistd.h	Thu Aug 24 21:13:26 2000
@@ -315,6 +315,11 @@
 #define __NR_mincore			375
 #define __NR_pciconfig_iobase		376
 #define __NR_getdents64			377
+#define __NR_timer_create		378
+#define __NR_timer_settime		379
+#define __NR_timer_gettime		380
+#define __NR_timer_getoverrun		381
+#define __NR_timer_delete		382
 
 #if defined(__GNUC__)
 
Index: linux/include/asm-arm/posix_types.h
diff -u linux/include/asm-arm/posix_types.h:1.1.1.2 linux/include/asm-arm/posix_types.h:1.1.2.2
--- linux/include/asm-arm/posix_types.h:1.1.1.2	Sun Jan 30 22:22:59 2000
+++ linux/include/asm-arm/posix_types.h	Mon Jan 31 00:26:12 2000
@@ -30,6 +30,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;
Index: linux/include/asm-arm/siginfo.h
diff -u linux/include/asm-arm/siginfo.h:1.1.1.3 linux/include/asm-arm/siginfo.h:1.1.2.4
--- linux/include/asm-arm/siginfo.h:1.1.1.3	Tue Jun 27 19:31:43 2000
+++ linux/include/asm-arm/siginfo.h	Fri Jul 21 20:39:07 2000
@@ -29,8 +29,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -67,6 +68,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -85,7 +87,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-arm/unistd.h
diff -u linux/include/asm-arm/unistd.h:1.1.1.5 linux/include/asm-arm/unistd.h:1.1.2.5
--- linux/include/asm-arm/unistd.h:1.1.1.5	Thu Aug 24 20:42:27 2000
+++ linux/include/asm-arm/unistd.h	Thu Aug 24 21:13:28 2000
@@ -224,6 +224,11 @@
 #define __NR_setfsuid32			(__NR_SYSCALL_BASE+215)
 #define __NR_setfsgid32			(__NR_SYSCALL_BASE+216)
 #define __NR_getdents64			(__NR_SYSCALL_BASE+217)
+#define __NR_timer_create		(__NR_SYSCALL_BASE+218)
+#define __NR_timer_settime		(__NR_SYSCALL_BASE+219)
+#define __NR_timer_gettime		(__NR_SYSCALL_BASE+220)
+#define __NR_timer_getoverrun		(__NR_SYSCALL_BASE+221)
+#define __NR_timer_delete		(__NR_SYSCALL_BASE+222)
 
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
Index: linux/include/asm-i386/posix_types.h
diff -u linux/include/asm-i386/posix_types.h:1.1.1.2 linux/include/asm-i386/posix_types.h:1.1.2.2
--- linux/include/asm-i386/posix_types.h:1.1.1.2	Sun Jan 30 22:22:52 2000
+++ linux/include/asm-i386/posix_types.h	Mon Jan 31 00:26:15 2000
@@ -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;
Index: linux/include/asm-i386/siginfo.h
diff -u linux/include/asm-i386/siginfo.h:1.1.1.3 linux/include/asm-i386/siginfo.h:1.1.2.4
--- linux/include/asm-i386/siginfo.h:1.1.1.3	Tue Jun 27 19:31:47 2000
+++ linux/include/asm-i386/siginfo.h	Fri Jul 21 20:39:08 2000
@@ -29,8 +29,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -67,6 +68,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -85,7 +87,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-i386/unistd.h
diff -u linux/include/asm-i386/unistd.h:1.1.1.4 linux/include/asm-i386/unistd.h:1.1.2.4
--- linux/include/asm-i386/unistd.h:1.1.1.4	Thu Aug 24 20:42:32 2000
+++ linux/include/asm-i386/unistd.h	Thu Aug 24 21:13:30 2000
@@ -227,6 +227,11 @@
 #define __NR_madvise1		219	/* delete when C lib stub is removed */
 #define __NR_getdents64		220
 #define __NR_fcntl64		221
+#define __NR_timer_create	222
+#define __NR_timer_settime	223
+#define __NR_timer_gettime	224
+#define __NR_timer_getoverrun	225
+#define __NR_timer_delete	226
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
Index: linux/include/asm-ia64/posix_types.h
diff -u linux/include/asm-ia64/posix_types.h:1.1.1.1 linux/include/asm-ia64/posix_types.h:1.1.4.2
--- linux/include/asm-ia64/posix_types.h:1.1.1.1	Sat Feb 12 10:18:57 2000
+++ linux/include/asm-ia64/posix_types.h	Sun Mar 26 22:21:10 2000
@@ -26,6 +26,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 long	__kernel_sigset_t;	/* at least 32 bits */
Index: linux/include/asm-ia64/siginfo.h
diff -u linux/include/asm-ia64/siginfo.h:1.1.1.5 linux/include/asm-ia64/siginfo.h:1.1.4.6
--- linux/include/asm-ia64/siginfo.h:1.1.1.5	Thu Aug 24 20:43:00 2000
+++ linux/include/asm-ia64/siginfo.h	Thu Aug 24 21:13:30 2000
@@ -33,8 +33,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -74,6 +75,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -98,7 +100,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-ia64/unistd.h
diff -u linux/include/asm-ia64/unistd.h:1.1.1.5 linux/include/asm-ia64/unistd.h:1.1.4.6
--- linux/include/asm-ia64/unistd.h:1.1.1.5	Thu Aug 24 20:43:00 2000
+++ linux/include/asm-ia64/unistd.h	Thu Aug 24 21:13:31 2000
@@ -204,6 +204,11 @@
 #define __NR_fstat			1212
 #define __NR_clone2			1213
 #define __NR_getdents64			1214
+#define __NR_timer_create		1215
+#define __NR_timer_settime		1216
+#define __NR_timer_gettime		1217
+#define __NR_timer_getoverrun		1218
+#define __NR_timer_delete		1219
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
Index: linux/include/asm-m68k/posix_types.h
diff -u linux/include/asm-m68k/posix_types.h:1.1.1.2 linux/include/asm-m68k/posix_types.h:1.1.2.2
--- linux/include/asm-m68k/posix_types.h:1.1.1.2	Sun Jan 30 22:22:54 2000
+++ linux/include/asm-m68k/posix_types.h	Mon Jan 31 00:26:16 2000
@@ -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;
Index: linux/include/asm-m68k/siginfo.h
diff -u linux/include/asm-m68k/siginfo.h:1.1.1.3 linux/include/asm-m68k/siginfo.h:1.1.2.4
--- linux/include/asm-m68k/siginfo.h:1.1.1.3	Tue Jun 27 19:31:49 2000
+++ linux/include/asm-m68k/siginfo.h	Fri Jul 21 20:39:08 2000
@@ -29,8 +29,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -67,6 +68,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -85,7 +87,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-m68k/unistd.h
diff -u linux/include/asm-m68k/unistd.h:1.1.1.2 linux/include/asm-m68k/unistd.h:1.1.2.2
--- linux/include/asm-m68k/unistd.h:1.1.1.2	Thu Aug 24 20:42:34 2000
+++ linux/include/asm-m68k/unistd.h	Thu Aug 24 21:13:31 2000
@@ -221,6 +221,11 @@
 #define __NR_setfsuid32		215
 #define __NR_setfsgid32		216
 #define __NR_getdents64		220
+#define __NR_timer_create	221
+#define __NR_timer_settime	222
+#define __NR_timer_gettime	223
+#define __NR_timer_getoverrun	224
+#define __NR_timer_delete	225
 
 /* user-visible error numbers are in the range -1 - -122: see
    <asm-m68k/errno.h> */
Index: linux/include/asm-mips/posix_types.h
diff -u linux/include/asm-mips/posix_types.h:1.1.1.4 linux/include/asm-mips/posix_types.h:1.1.2.4
--- linux/include/asm-mips/posix_types.h:1.1.1.4	Wed Jul 12 21:49:57 2000
+++ linux/include/asm-mips/posix_types.h	Wed Jul 12 22:15:35 2000
@@ -32,6 +32,8 @@
 typedef long		__kernel_clock_t;
 typedef long		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
 
 typedef unsigned short	__kernel_uid16_t;
 typedef unsigned short	__kernel_gid16_t;
Index: linux/include/asm-mips/siginfo.h
diff -u linux/include/asm-mips/siginfo.h:1.1.1.5 linux/include/asm-mips/siginfo.h:1.1.2.6
--- linux/include/asm-mips/siginfo.h:1.1.1.5	Tue Jun 27 19:31:51 2000
+++ linux/include/asm-mips/siginfo.h	Fri Jul 21 20:39:09 2000
@@ -68,8 +68,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -87,6 +88,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -105,7 +107,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-mips/unistd.h
diff -u linux/include/asm-mips/unistd.h:1.1.1.4 linux/include/asm-mips/unistd.h:1.1.2.4
--- linux/include/asm-mips/unistd.h:1.1.1.4	Thu Aug 24 20:42:35 2000
+++ linux/include/asm-mips/unistd.h	Thu Aug 24 21:13:32 2000
@@ -1206,11 +1206,16 @@
 #define __NR_mincore			(__NR_Linux + 217)
 #define __NR_madvise			(__NR_Linux + 218)
 #define __NR_getdents64			(__NR_Linux + 219)
+#define __NR_timer_create		(__NR_Linux + 220)
+#define __NR_timer_settime		(__NR_Linux + 221)
+#define __NR_timer_gettime		(__NR_Linux + 222)
+#define __NR_timer_getoverrun		(__NR_Linux + 223)
+#define __NR_timer_delete		(__NR_Linux + 224)
 
 /*
  * Offset of the last Linux flavoured syscall
  */
-#define __NR_Linux_syscalls		219
+#define __NR_Linux_syscalls		224
 
 #ifndef _LANGUAGE_ASSEMBLY
 
Index: linux/include/asm-mips64/siginfo.h
diff -u linux/include/asm-mips64/siginfo.h:1.1.1.3 linux/include/asm-mips64/siginfo.h:1.1.2.4
--- linux/include/asm-mips64/siginfo.h:1.1.1.3	Tue Jun 27 19:32:13 2000
+++ linux/include/asm-mips64/siginfo.h	Fri Jul 21 20:39:09 2000
@@ -68,8 +68,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -87,6 +88,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -105,7 +107,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-ppc/posix_types.h
diff -u linux/include/asm-ppc/posix_types.h:1.1.1.5 linux/include/asm-ppc/posix_types.h:1.1.2.5
--- linux/include/asm-ppc/posix_types.h:1.1.1.5	Tue Jun 27 19:31:53 2000
+++ linux/include/asm-ppc/posix_types.h	Wed Jul 12 22:15:38 2000
@@ -21,6 +21,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 short             __kernel_ipc_pid_t;
Index: linux/include/asm-ppc/siginfo.h
diff -u linux/include/asm-ppc/siginfo.h:1.1.1.4 linux/include/asm-ppc/siginfo.h:1.1.2.4
--- linux/include/asm-ppc/siginfo.h:1.1.1.4	Tue Jun 27 19:31:53 2000
+++ linux/include/asm-ppc/siginfo.h	Fri Jul 21 20:39:10 2000
@@ -29,8 +29,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -67,6 +68,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -85,7 +87,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-ppc/unistd.h
diff -u linux/include/asm-ppc/unistd.h:1.1.1.4 linux/include/asm-ppc/unistd.h:1.1.2.4
--- linux/include/asm-ppc/unistd.h:1.1.1.4	Thu Aug 24 20:42:38 2000
+++ linux/include/asm-ppc/unistd.h	Thu Aug 24 21:13:33 2000
@@ -206,6 +206,11 @@
 #define __NR_sys_pciconfig_iobase	200
 #define __NR_multiplexer		201
 #define __NR_getdents64		202
+#define __NR_timer_create	203
+#define __NR_timer_settime	204
+#define __NR_timer_gettime	205
+#define __NR_timer_getoverrun	206
+#define __NR_timer_delete	207
 
 #define __NR(n)	#n
 
Index: linux/include/asm-s390/siginfo.h
diff -u linux/include/asm-s390/siginfo.h:1.1.1.1 linux/include/asm-s390/siginfo.h:1.1.2.2
--- linux/include/asm-s390/siginfo.h:1.1.1.1	Sat May 13 01:04:16 2000
+++ linux/include/asm-s390/siginfo.h	Fri Jul 21 20:37:01 2000
@@ -37,8 +37,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -75,6 +76,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
Index: linux/include/asm-s390/unistd.h
diff -u linux/include/asm-s390/unistd.h:1.1.1.2 linux/include/asm-s390/unistd.h:1.1.2.3
--- linux/include/asm-s390/unistd.h:1.1.1.2	Thu Aug 24 20:43:04 2000
+++ linux/include/asm-s390/unistd.h	Thu Aug 24 21:13:35 2000
@@ -209,7 +209,11 @@
 #define __NR_mincore            218
 #define __NR_madvise            219
 #define __NR_getdents64		220
-
+#define __NR_timer_create	221
+#define __NR_timer_settime	222
+#define __NR_timer_gettime	223
+#define __NR_timer_getoverrun	224
+#define __NR_timer_delete	225
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
 
Index: linux/include/asm-sh/posix_types.h
diff -u linux/include/asm-sh/posix_types.h:1.1.1.2 linux/include/asm-sh/posix_types.h:1.1.2.2
--- linux/include/asm-sh/posix_types.h:1.1.1.2	Sat Mar 11 11:12:59 2000
+++ linux/include/asm-sh/posix_types.h	Sun Mar 12 13:17:28 2000
@@ -24,6 +24,8 @@
 typedef long		__kernel_clock_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
 typedef unsigned short	__kernel_uid16_t;
 typedef unsigned short	__kernel_gid16_t;
 typedef unsigned int	__kernel_uid32_t;
Index: linux/include/asm-sh/siginfo.h
diff -u linux/include/asm-sh/siginfo.h:1.1.1.3 linux/include/asm-sh/siginfo.h:1.1.2.4
--- linux/include/asm-sh/siginfo.h:1.1.1.3	Tue Jun 27 19:31:54 2000
+++ linux/include/asm-sh/siginfo.h	Fri Jul 21 20:39:12 2000
@@ -29,8 +29,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -67,6 +68,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -85,7 +87,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-sparc/posix_types.h
diff -u linux/include/asm-sparc/posix_types.h:1.1.1.2 linux/include/asm-sparc/posix_types.h:1.1.2.2
--- linux/include/asm-sparc/posix_types.h:1.1.1.2	Sun Jan 30 22:22:55 2000
+++ linux/include/asm-sparc/posix_types.h	Mon Jan 31 00:26:19 2000
@@ -13,6 +13,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_pid_t;
 typedef unsigned short         __kernel_ipc_pid_t;
 typedef unsigned short         __kernel_uid_t;
Index: linux/include/asm-sparc/siginfo.h
diff -u linux/include/asm-sparc/siginfo.h:1.1.1.4 linux/include/asm-sparc/siginfo.h:1.1.2.5
--- linux/include/asm-sparc/siginfo.h:1.1.1.4	Tue Jun 27 19:31:56 2000
+++ linux/include/asm-sparc/siginfo.h	Fri Jul 21 20:39:12 2000
@@ -31,8 +31,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -70,6 +71,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -89,7 +91,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-sparc/unistd.h
diff -u linux/include/asm-sparc/unistd.h:1.1.1.5 linux/include/asm-sparc/unistd.h:1.1.2.4
--- linux/include/asm-sparc/unistd.h:1.1.1.5	Thu Aug 24 20:42:42 2000
+++ linux/include/asm-sparc/unistd.h	Thu Aug 24 21:13:36 2000
@@ -184,11 +184,11 @@
 /* #define __NR_exportfs        166    SunOS Specific                              */
 #define __NR_mount              167 /* Common                                      */
 #define __NR_ustat              168 /* Common                                      */
-/* #define __NR_semsys          169    SunOS Specific                              */
-/* #define __NR_msgsys          170    SunOS Specific                              */
-/* #define __NR_shmsys          171    SunOS Specific                              */
-/* #define __NR_auditsys        172    SunOS Specific                              */
-/* #define __NR_rfssys          173    SunOS Specific                              */
+#define __NR_timer_create       169 /* Linux Specific, semsys under SunOS          */
+#define __NR_timer_settime      170 /* Linux Specific, msgsys under SunOS          */
+#define __NR_timer_gettime      171 /* Linux Specific, shmsys under SunOS          */
+#define __NR_timer_getoverrun   172 /* Linux Specific, auditsys under SunOS        */
+#define __NR_timer_delete       173 /* Linux Specific, rfssys under SunOS          */
 #define __NR_getdents           174 /* Common                                      */
 #define __NR_setsid             175 /* Common                                      */
 #define __NR_fchdir             176 /* Common                                      */
@@ -201,9 +201,9 @@
 #define __NR_sigpending         183 /* Common                                      */
 #define __NR_query_module	184 /* Linux Specific				   */
 #define __NR_setpgid            185 /* Common                                      */
-/* #define __NR_pathconf        186    SunOS Specific                              */
-/* #define __NR_fpathconf       187    SunOS Specific                              */
-/* #define __NR_sysconf         188    SunOS Specific                              */
+/* #define __NR_clock_gettime	186    Linux Specific				   */
+/* #define __NR_clock_settime	187    Linux Specific				   */
+/* #define __NR_clock_getres	188    Linux Specific				   */
 #define __NR_uname              189 /* Linux Specific                              */
 #define __NR_init_module        190 /* Linux Specific                              */
 #define __NR_personality        191 /* Linux Specific                              */
@@ -271,6 +271,8 @@
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
 #define __NR_aplib              255
+/* Please don't add syscalls above 255.
+   Contact jj@ultra.linux.cz or davem@redhat.com for number assignment.  */
 
 #define _syscall0(type,name) \
 type name(void) \
Index: linux/include/asm-sparc64/posix_types.h
diff -u linux/include/asm-sparc64/posix_types.h:1.1.1.3 linux/include/asm-sparc64/posix_types.h:1.1.2.3
--- linux/include/asm-sparc64/posix_types.h:1.1.1.3	Sat Feb 12 10:18:49 2000
+++ linux/include/asm-sparc64/posix_types.h	Sun Feb 20 18:46:30 2000
@@ -18,6 +18,8 @@
 typedef long                   __kernel_ptrdiff_t;
 typedef long                   __kernel_time_t;
 typedef long                   __kernel_clock_t;
+typedef int		       __kernel_timer_t;
+typedef int		       __kernel_clockid_t;
 typedef int                    __kernel_pid_t;
 typedef int                    __kernel_ipc_pid_t;
 typedef unsigned int           __kernel_uid_t;
@@ -73,6 +75,8 @@
 typedef unsigned int           __kernel_caddr_t32;
 typedef long		       __kernel_loff_t32;
 typedef __kernel_fsid_t        __kernel_fsid_t32;
+typedef int		       __kernel_timer_t32;
+typedef int		       __kernel_clockid_t32;
 
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
Index: linux/include/asm-sparc64/siginfo.h
diff -u linux/include/asm-sparc64/siginfo.h:1.1.1.4 linux/include/asm-sparc64/siginfo.h:1.1.2.5
--- linux/include/asm-sparc64/siginfo.h:1.1.1.4	Tue Jun 27 19:31:58 2000
+++ linux/include/asm-sparc64/siginfo.h	Fri Jul 21 20:39:13 2000
@@ -37,8 +37,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _pad;		/* padding */
+			sigval_t _sigval;	/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -89,8 +90,9 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t32 _tid;			/* timer id */
+			int _pad			/* padding */
+			sigval_t32 _sigval;		/* same as below */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -130,6 +132,7 @@
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_tid		_sifields._timer._tid
 #define si_status	_sifields._sigchld._status
 #define si_utime	_sifields._sigchld._utime
 #define si_stime	_sifields._sigchld._stime
@@ -149,7 +152,7 @@
 #define __SI_FAULT	(3 << 16)
 #define __SI_CHLD	(4 << 16)
 #define __SI_RT		(5 << 16)
-#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
 #else
 #define __SI_KILL	0
 #define __SI_TIMER	0
Index: linux/include/asm-sparc64/unistd.h
diff -u linux/include/asm-sparc64/unistd.h:1.1.1.6 linux/include/asm-sparc64/unistd.h:1.1.2.5
--- linux/include/asm-sparc64/unistd.h:1.1.1.6	Thu Aug 24 20:42:45 2000
+++ linux/include/asm-sparc64/unistd.h	Thu Aug 24 21:13:36 2000
@@ -184,11 +184,11 @@
 /* #define __NR_exportfs        166    SunOS Specific                              */
 #define __NR_mount              167 /* Common                                      */
 #define __NR_ustat              168 /* Common                                      */
-/* #define __NR_semsys          169    SunOS Specific                              */
-/* #define __NR_msgsys          170    SunOS Specific                              */
-/* #define __NR_shmsys          171    SunOS Specific                              */
-/* #define __NR_auditsys        172    SunOS Specific                              */
-/* #define __NR_rfssys          173    SunOS Specific                              */
+#define __NR_timer_create       169 /* Linux Specific, semsys under SunOS          */
+#define __NR_timer_settime      170 /* Linux Specific, msgsys under SunOS          */
+#define __NR_timer_gettime      171 /* Linux Specific, shmsys under SunOS          */
+#define __NR_timer_getoverrun   172 /* Linux Specific, auditsys under SunOS        */
+#define __NR_timer_delete       173 /* Linux Specific, rfssys under SunOS          */
 #define __NR_getdents           174 /* Common                                      */
 #define __NR_setsid             175 /* Common                                      */
 #define __NR_fchdir             176 /* Common                                      */
@@ -201,9 +201,9 @@
 #define __NR_sigpending         183 /* Common                                      */
 #define __NR_query_module	184 /* Linux Specific				   */
 #define __NR_setpgid            185 /* Common                                      */
-/* #define __NR_pathconf        186    SunOS Specific                              */
-/* #define __NR_fpathconf       187    SunOS Specific                              */
-/* #define __NR_sysconf         188    SunOS Specific                              */
+/* #define __NR_clock_gettime	186    Linux Specific				   */
+/* #define __NR_clock_settime	187    Linux Specific				   */
+/* #define __NR_clock_getres	188    Linux Specific				   */
 #define __NR_uname              189 /* Linux Specific                              */
 #define __NR_init_module        190 /* Linux Specific                              */
 #define __NR_personality        191 /* Linux Specific                              */
@@ -273,6 +273,8 @@
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
 #define __NR_aplib              255
+/* Please don't add syscalls above 255.
+   Contact jj@ultra.linux.cz or davem@redhat.com for number assignment.  */
 
 #define _syscall0(type,name) \
 type name(void) \
Index: linux/include/linux/limits.h
diff -u linux/include/linux/limits.h:1.1.1.1 linux/include/linux/limits.h:1.1.2.1
--- linux/include/linux/limits.h:1.1.1.1	Sun Jan 30 22:21:03 2000
+++ linux/include/linux/limits.h	Sun Jan 30 22:56:36 2000
@@ -14,6 +14,9 @@
 #define PATH_MAX        4095	/* # chars in a path name */
 #define PIPE_BUF        4096	/* # bytes in atomic write to a pipe */
 
+#define TIMER_MAX         32    /* # POSIX.1b timers a process may have */
+#define DELAYTIMER_MAX INT_MAX	/* # timer expiration overruns a POSIX.1b timer may have */
+
 #define RTSIG_MAX	  32
 
 #endif
Index: linux/include/linux/sched.h
diff -u linux/include/linux/sched.h:1.1.1.13 linux/include/linux/sched.h:1.1.2.13
--- linux/include/linux/sched.h:1.1.1.13	Thu Aug 24 20:42:51 2000
+++ linux/include/linux/sched.h	Thu Aug 24 21:13:39 2000
@@ -38,6 +38,7 @@
 #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_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
+#define CLONE_ITIMERS   0x00010000      /* set if POSIX.1b itimers are shared */
 
 /*
  * These are the constant used to fake the fixed-point load-average
@@ -262,6 +263,29 @@
 extern struct user_struct root_user;
 #define INIT_USER (&root_user)
 
+/* 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[TIMER_MAX];	
+};
+
+extern struct itimer_struct *itimer_struct_new(void);
+extern void itimer_struct_delete(struct itimer_struct *timers);
+
 struct task_struct {
 	/*
 	 * offsets of these are hardcoded elsewhere - touch with care
@@ -330,6 +354,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];
@@ -439,6 +464,7 @@
     real_timer:		{						\
 	function:		it_real_fn				\
     },									\
+    posix_timers:	NULL,						\
     cap_effective:	CAP_INIT_EFF_SET,				\
     cap_inheritable:	CAP_INIT_INH_SET,				\
     cap_permitted:	CAP_FULL_SET,					\
@@ -711,6 +737,7 @@
 extern void exit_mm(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 void daemonize(void);
 
Index: linux/include/linux/time.h
diff -u linux/include/linux/time.h:1.1.1.1 linux/include/linux/time.h:1.1.2.1
--- linux/include/linux/time.h:1.1.1.1	Sun Jan 30 22:21:03 2000
+++ linux/include/linux/time.h	Sun Jan 30 22:56:36 2000
@@ -1,7 +1,7 @@
 #ifndef _LINUX_TIME_H
 #define _LINUX_TIME_H
 
-#include <asm/param.h>
+#include <linux/param.h>
 #include <linux/types.h>
 
 #ifndef _STRUCT_TIMESPEC
@@ -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,18 @@
 	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
+
+/*
+ * The various flags for setting POSIX.1b interval timers.
+ */
+
+#define TIMER_ABSTIME 0x01
+
 
 #endif
Index: linux/include/linux/types.h
diff -u linux/include/linux/types.h:1.1.1.3 linux/include/linux/types.h:1.1.2.3
--- linux/include/linux/types.h:1.1.1.3	Sat Jul 15 11:41:56 2000
+++ linux/include/linux/types.h	Sat Jul 15 11:53:20 2000
@@ -20,6 +20,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;
Index: linux/kernel/exit.c
diff -u linux/kernel/exit.c:1.1.1.15 linux/kernel/exit.c:1.1.2.14
--- linux/kernel/exit.c:1.1.1.15	Thu Aug 24 20:43:06 2000
+++ linux/kernel/exit.c	Thu Aug 24 21:13:42 2000
@@ -301,6 +301,21 @@
 	mmdrop(active_mm);
 }
 
+static inline void __exit_itimers(struct task_struct *tsk)
+{
+	struct itimer_struct *timers = tsk->posix_timers;
+
+	if (timers) {
+		itimer_struct_delete(timers);
+		tsk->posix_timers = NULL;
+	}
+}
+
+void exit_itimers(struct task_struct *tsk)
+{
+	__exit_itimers(tsk);
+}
+
 /*
  * Turn us into a lazy TLB process if we
  * aren't already..
@@ -450,6 +465,7 @@
 	__exit_files(tsk);
 	__exit_fs(tsk);
 	__exit_sighand(tsk);
+	__exit_itimers(tsk);
 	exit_thread();
 	tsk->state = TASK_ZOMBIE;
 	tsk->exit_code = code;
Index: linux/kernel/fork.c
diff -u linux/kernel/fork.c:1.1.1.14 linux/kernel/fork.c:1.1.2.13
--- linux/kernel/fork.c:1.1.1.14	Thu Aug 24 20:43:06 2000
+++ linux/kernel/fork.c	Thu Aug 24 21:13:42 2000
@@ -526,6 +526,23 @@
 	p->flags = new_flags;
 }
 
+
+static inline int copy_itimers(unsigned long clone_flags, struct task_struct * tsk)
+{
+	if (clone_flags & CLONE_ITIMERS) {
+		if (tsk->posix_timers == NULL) {
+			tsk->posix_timers = itimer_struct_new();
+			if (tsk->posix_timers == NULL) return -1;
+		}
+		atomic_inc(&tsk->posix_timers->count);
+		return 0;
+	}
+	tsk->posix_timers = NULL;
+
+	return 0;
+}
+
+
 /*
  *  Ok, this is the main fork-routine. It copies the system process
  * information (task[nr]) and sets up the necessary registers. It
@@ -626,6 +643,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);
@@ -678,6 +697,8 @@
 		down(&sem);
 	return retval;
 
+bad_fork_cleanup_itimers:
+	exit_itimers(p);
 bad_fork_cleanup_sighand:
 	exit_sighand(p);
 bad_fork_cleanup_fs:
Index: linux/kernel/itimer.c
diff -u linux/kernel/itimer.c:1.1.1.3 linux/kernel/itimer.c:1.1.2.7
--- linux/kernel/itimer.c:1.1.1.3	Wed Jul 12 21:50:24 2000
+++ linux/kernel/itimer.c	Sun Aug 20 16:02:28 2000
@@ -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
@@ -165,6 +167,430 @@
 		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) {
+
+		memset(&info, 0, sizeof(info));
+
+		/* 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;
+		info.si_tid = timr->it_id;
+		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;
+		}
+	}
+}
+
+/* 
+ * Notify the task and set up the timer for the next expiration (if applicable).
+ * This function requires that the k_itimer structure it_lock is taken.
+ */
+static void posix_timer_fire(struct k_itimer *timr)
+{
+	unsigned long interval;
+
+	timer_notify_task(timr);
+
+	/* Set up the timer for the next interval (if there is one) */
+	if ((interval = timr->it_incr) == 0) return;
+		
+	if (interval > (unsigned long) LONG_MAX)
+		interval = LONG_MAX;
+	timr->it_timer.expires += interval;
+	add_timer(&timr->it_timer);
+}
+
+/*
+ * This function gets called when a POSIX.1b interval timer expires.
+ * It is used as a callback from the kernel internal timer.
+ */
+static void posix_timer_fn(unsigned long __data)
+{
+	struct k_itimer *timr = (struct k_itimer *)__data;
+
+	spin_lock(&timr->it_lock);
+	posix_timer_fire(timr);
+	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 < TIMER_MAX; 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;
+}
+
+struct itimer_struct *itimer_struct_new(void)
+{
+	struct itimer_struct *posix_timers;
+
+	posix_timers = kmalloc(sizeof(struct itimer_struct), GFP_KERNEL);
+	if (posix_timers == NULL) return NULL;
+	spin_lock_init(&posix_timers->its_lock);
+	atomic_set(&posix_timers->count, 1);
+	memset(posix_timers->itimer, 0, sizeof(posix_timers->itimer));
+	return posix_timers;
+}
+
+void itimer_struct_delete(struct itimer_struct *timers)
+{
+	int i;
+	struct k_itimer *timr;
+
+	if (atomic_dec_and_test(&timers->count)) {
+		for (i = 0; i < TIMER_MAX; i++) {
+			timr = timers->itimer[i];
+			if (timr) {
+				del_timer_sync(&timr->it_timer);
+				kfree(timr);
+			}
+		}
+		kfree(timers);
+	}
+}
+
+
+
+/* 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;
+
+	if (timers == NULL) {
+		timers = current->posix_timers = itimer_struct_new();
+		if (timers == NULL) return -EAGAIN;
+	}
+
+	/* 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.list.next = NULL;
+	new_timer->it_timer.list.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_locked;
+	}
+	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;
+	}
+
+out_locked:
+	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;
+}
+
+inline struct k_itimer* lock_timer(struct task_struct *tsk, timer_t timer_id)
+{
+	struct k_itimer *timr;
+
+	if ((timer_id < 0) || (timer_id >= TIMER_MAX)) return NULL;
+	if (tsk->posix_timers == NULL) 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. */
+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. */
+/* timr->it_lock is taken. */
+static void do_timer_settime(struct k_itimer *timr, int flags,
+		      struct itimerspec *new_setting,
+		      struct itimerspec *old_setting)
+{
+	/* disable the timer */
+	del_timer_sync(&timr->it_timer);
+
+	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_fire(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;
+
+	del_timer_sync(&timr->it_timer);
+
+	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;
 }
Index: linux/kernel/signal.c
diff -u linux/kernel/signal.c:1.1.1.8 linux/kernel/signal.c:1.1.2.8
--- linux/kernel/signal.c:1.1.1.8	Thu Aug 24 20:43:06 2000
+++ linux/kernel/signal.c	Thu Aug 24 21:13:42 2000
@@ -228,8 +228,6 @@
 			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
@@ -389,6 +387,23 @@
 	   the signal. */
 	if (sig < SIGRTMIN && sigismember(&t->signal, sig))
 		goto out;
+
+	/* In case of a POSIX timer generated signal you must check 
+	   if a signal from this timer is already in the queue.
+	   If that is is true, the overrun count will be increased in
+	   itimer.c:posix_timer_fn(). */
+
+	if (((unsigned long)info > 1) && (info->si_code == SI_TIMER)) {
+		for (q = t->sigqueue; q; q = q->next) {
+			if ((q->info.si_code == SI_TIMER) &&
+			    (q->info.si_tid == info->si_tid)) {
+				/* this special value (1) is recognized
+				   only by posix_timer_fn() in itimer.c */
+				ret = 1;
+				goto out;
+			}
+		}
+	}
 
 	/* Real-time signals must be queued if sent by sigqueue, or
 	   some other real-time mechanism.  It is implementation

--------------Boundary-00=_O8DWS8NIGHEI649WR4VT--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/