lkml.org 
[lkml]   [2000]   [Aug]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectPOSIX timers for 2.4.0-test7
Date
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
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
\
 
 \ /
  Last update: 2005-03-22 12:38    [W:0.096 / U:0.256 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site