--------------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 */ 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 */ 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 */ 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 +#include #include #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 #include #include +#include +#include #include /* - * 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 str