[NEW PATCH] timers, sysctl, signal (only to get POSIX timers and clocks)

Robert H. de Vries (rhdv@rhdv.cistron.nl)
Thu, 5 Aug 1999 20:58:36 +0200


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

Next try,

This patch adds only the posix timers to the kernel, not the clocks. IMHO the
standard POSIX timer for CLOCK_REALTIME belongs in the kernel, just as the
itimer does. The patch from Jakub for SPARC is integrated.

The clocks are now in user space. However I need some kernel support to know
something about the kernel setting/hardware. So there I need some extra items
from sysctl. One to know the value of HZ and one to know the processor
frequency for my second clock, the TSC. This clock uses the time stamp counter
on a pentium and should use similar clocks on other processors. The sample
implementation is not that fast (2 microsecs on my Pentium 166 MHz), but could
probably be improved by someone smarter than me.

In order to support sysconf(3) I added some more parameters to
sysctl. This should help Ulrich in his C library implementation.

Last but not least my infamous signal handling patch for nrt signals. Initially
implemented as a fixed buffer in struct task_struct, now it is implemented by
adding the siginfo in the siginfo list. Only one non realtime signal can be in
the signal queue at a time. The patch looks rather large but that is caused by
the fact that the difference between realtime and non realtime signals has
largely vanished, which reduced one level of if-statements.

In a follow up mail I have enclosed a sample C library implementation for the
POSIX clocks and timers and sysconf. Plus some test code for the clocks and
signals and a sysconf program dumping all parameters.

The patch is also available from http://www.rhdv.cistron.nl/posix.html in case
it doesn't get through vger in one piece. The test code is also there.

Robert

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

--Boundary-=_nWlrBbmQBhCDarzOwKkYHIDdqSCD
Content-Type: text/x-c;
name="timer-sysctl-signal.2.3.13-pre5.patch"
Content-Transfer-Encoding: 8bit
Content-Description: timer, sysctl and signal patch for 2.3.13-pre5
Content-Disposition: attachment; filename="timer-sysctl-signal.2.3.13-pre5.patch"

diff -ruN linux-2.3.13-pre5-vanilla/arch/alpha/kernel/entry.S linux-2.3.13-pre5-devt/arch/alpha/kernel/entry.S
--- linux-2.3.13-pre5-vanilla/arch/alpha/kernel/entry.S Thu Aug 5 19:02:51 1999
+++ linux-2.3.13-pre5-devt/arch/alpha/kernel/entry.S Thu Aug 5 19:05:39 1999
@@ -1147,3 +1147,8 @@
.quad sys_capget
.quad sys_capset
.quad sys_sendfile /* 370 */
+ .quad sys_timer_create
+ .quad sys_timer_settime
+ .quad sys_timer_gettime
+ .quad sys_timer_getoverrun
+ .quad sys_timer_delete /* 375 */
diff -ruN linux-2.3.13-pre5-vanilla/arch/arm/kernel/calls.S linux-2.3.13-pre5-devt/arch/arm/kernel/calls.S
--- linux-2.3.13-pre5-vanilla/arch/arm/kernel/calls.S Sat Jul 24 16:26:05 1999
+++ linux-2.3.13-pre5-devt/arch/arm/kernel/calls.S Thu Aug 5 19:05:39 1999
@@ -200,8 +200,13 @@
.long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_ni_syscall)
/* 190 */ .long SYMBOL_NAME(sys_vfork_wrapper)
+ .long SYMBOL_NAME(sys_timer_create)
+ .long SYMBOL_NAME(sys_timer_settime)
+ .long SYMBOL_NAME(sys_timer_gettime)
+ .long SYMBOL_NAME(sys_timer_getoverrun)
+/* 195 */ .long SYMBOL_NAME(sys_timer_delete)

- .rept NR_syscalls-186
+ .rept NR_syscalls-195
.long SYMBOL_NAME(sys_ni_syscall)
.endr
#endif
diff -ruN linux-2.3.13-pre5-vanilla/arch/i386/kernel/entry.S linux-2.3.13-pre5-devt/arch/i386/kernel/entry.S
--- linux-2.3.13-pre5-vanilla/arch/i386/kernel/entry.S Thu Aug 5 19:02:52 1999
+++ linux-2.3.13-pre5-devt/arch/i386/kernel/entry.S Thu Aug 5 19:05:39 1999
@@ -560,6 +560,11 @@
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
+ .long SYMBOL_NAME(sys_timer_create)
+ .long SYMBOL_NAME(sys_timer_settime)
+ .long SYMBOL_NAME(sys_timer_gettime)
+ .long SYMBOL_NAME(sys_timer_getoverrun)
+ .long SYMBOL_NAME(sys_timer_delete) /* 195 */

/*
* NOTE!! This doesn't have to be exact - we just have
@@ -567,6 +572,6 @@
* entries. Don't panic if you notice that this hasn't
* been shrunk every time we add a new system call.
*/
- .rept NR_syscalls-190
+ .rept NR_syscalls-195
.long SYMBOL_NAME(sys_ni_syscall)
.endr
diff -ruN linux-2.3.13-pre5-vanilla/arch/m68k/kernel/entry.S linux-2.3.13-pre5-devt/arch/m68k/kernel/entry.S
--- linux-2.3.13-pre5-vanilla/arch/m68k/kernel/entry.S Sun Jun 20 11:40:26 1999
+++ linux-2.3.13-pre5-devt/arch/m68k/kernel/entry.S Thu Aug 5 19:05:39 1999
@@ -609,6 +609,11 @@
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
+ .long SYMBOL_NAME(sys_timer_create)
+ .long SYMBOL_NAME(sys_timer_settime)
+ .long SYMBOL_NAME(sys_timer_gettime)
+ .long SYMBOL_NAME(sys_timer_getoverrun)
+ .long SYMBOL_NAME(sys_timer_delete) /* 195 */

.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
.long SYMBOL_NAME(sys_ni_syscall)
diff -ruN linux-2.3.13-pre5-vanilla/arch/mips/kernel/irix5sys.h linux-2.3.13-pre5-devt/arch/mips/kernel/irix5sys.h
--- linux-2.3.13-pre5-vanilla/arch/mips/kernel/irix5sys.h Thu Jul 1 20:36:17 1999
+++ linux-2.3.13-pre5-devt/arch/mips/kernel/irix5sys.h Thu Aug 5 19:05:40 1999
@@ -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*/
diff -ruN linux-2.3.13-pre5-vanilla/arch/mips/kernel/syscalls.h linux-2.3.13-pre5-devt/arch/mips/kernel/syscalls.h
--- linux-2.3.13-pre5-vanilla/arch/mips/kernel/syscalls.h Thu Jul 1 20:36:18 1999
+++ linux-2.3.13-pre5-devt/arch/mips/kernel/syscalls.h Thu Aug 5 19:05:40 1999
@@ -225,3 +225,8 @@
SYS(sys_sendfile, 3)
SYS(sys_ni_syscall, 0)
SYS(sys_ni_syscall, 0)
+SYS(sys_timer_create, 3) /* 4210 */
+SYS(sys_timer_settime, 4)
+SYS(sys_timer_gettime, 2)
+SYS(sys_timer_getoverrun, 1)
+SYS(sys_timer_delete, 1)
diff -ruN linux-2.3.13-pre5-vanilla/arch/ppc/kernel/misc.S linux-2.3.13-pre5-devt/arch/ppc/kernel/misc.S
--- linux-2.3.13-pre5-vanilla/arch/ppc/kernel/misc.S Thu Jul 1 20:36:20 1999
+++ linux-2.3.13-pre5-devt/arch/ppc/kernel/misc.S Thu Aug 5 19:05:40 1999
@@ -894,4 +894,9 @@
.long sys_ni_syscall /* streams1 */
.long sys_ni_syscall /* streams2 */
.long sys_vfork
- .space (NR_syscalls-183)*4
+ .long sys_timer_create /* 190 */
+ .long sys_timer_settime
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete /* 194 */
+ .space (NR_syscalls-194)*4
diff -ruN linux-2.3.13-pre5-vanilla/arch/ppc/kernel/smp.c linux-2.3.13-pre5-devt/arch/ppc/kernel/smp.c
--- linux-2.3.13-pre5-vanilla/arch/ppc/kernel/smp.c Thu Aug 5 19:02:52 1999
+++ linux-2.3.13-pre5-devt/arch/ppc/kernel/smp.c Thu Aug 5 19:05:40 1999
@@ -39,6 +39,7 @@
int first_cpu_booted = 0;
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
+int cpu_nr = 1;
int smp_num_cpus = 1;
struct cpuinfo_PPC cpu_data[NR_CPUS];
struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
@@ -244,7 +245,7 @@
extern struct task_struct *current_set[NR_CPUS];
extern void __secondary_start_psurge(void);
extern void __secondary_start_chrp(void);
- int i, cpu_nr;
+ int i;
struct task_struct *p;
unsigned long a;

diff -ruN linux-2.3.13-pre5-vanilla/arch/sparc/kernel/systbls.S linux-2.3.13-pre5-devt/arch/sparc/kernel/systbls.S
--- linux-2.3.13-pre5-vanilla/arch/sparc/kernel/systbls.S Sun Jun 20 11:39:49 1999
+++ linux-2.3.13-pre5-devt/arch/sparc/kernel/systbls.S Thu Aug 5 19:05:40 1999
@@ -37,8 +37,8 @@
/*90*/ .long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
/*95*/ .long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
/*100*/ .long sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending
-/*105*/ .long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
-/*110*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*105*/ .long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_timer_create, sys_timer_settime
+/*110*/ .long sys_timer_gettime, sys_timer_getoverrun, sys_timer_delete, sys_nis_syscall, sys_nis_syscall
/*115*/ .long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd
/*120*/ .long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
/*125*/ .long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate
diff -ruN linux-2.3.13-pre5-vanilla/arch/sparc64/kernel/sys_sparc32.c linux-2.3.13-pre5-devt/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.3.13-pre5-vanilla/arch/sparc64/kernel/sys_sparc32.c Thu Aug 5 19:02:52 1999
+++ linux-2.3.13-pre5-devt/arch/sparc64/kernel/sys_sparc32.c Thu Aug 5 19:05:40 1999
@@ -3849,3 +3849,113 @@

return ret;
}
+
+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;
+}
diff -ruN linux-2.3.13-pre5-vanilla/arch/sparc64/kernel/systbls.S linux-2.3.13-pre5-devt/arch/sparc64/kernel/systbls.S
--- linux-2.3.13-pre5-vanilla/arch/sparc64/kernel/systbls.S Thu Aug 5 19:02:52 1999
+++ linux-2.3.13-pre5-devt/arch/sparc64/kernel/systbls.S Thu Aug 5 19:05:40 1999
@@ -38,8 +38,8 @@
/*90*/ .word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall
.word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
/*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
- .word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
-/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+ .word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys32_timer_create, sys32_timer_settime
+/*110*/ .word sys32_timer_gettime, sys_timer_getoverrun, sys_timer_delete, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
.word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate
@@ -68,7 +68,7 @@
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep
/*250*/ .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
- .word sys_aplib
+/*255*/ .word sys_aplib

/* Now the 64-bit native Linux syscall table. */

@@ -97,8 +97,8 @@
/*90*/ .word sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
.word sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept
/*100*/ .word sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending
- .word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
-/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg
+ .word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_timer_create, sys_timer_settime
+/*110*/ .word sys_timer_gettime, sys_timer_getoverrun, sys_timer_delete, sys_recvmsg, sys_sendmsg
.word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd
/*120*/ .word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
.word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
@@ -127,7 +127,7 @@
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
/*250*/ .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
- .word sys_aplib
+/*255*/ .word sys_aplib

/* Now the 32-bit SunOS syscall table. */

diff -ruN linux-2.3.13-pre5-vanilla/include/asm-alpha/siginfo.h linux-2.3.13-pre5-devt/include/asm-alpha/siginfo.h
--- linux-2.3.13-pre5-vanilla/include/asm-alpha/siginfo.h Sun Jun 20 11:39:59 1999
+++ linux-2.3.13-pre5-devt/include/asm-alpha/siginfo.h Thu Aug 5 19:05:48 1999
@@ -67,6 +67,8 @@
*/
#define si_pid _sifields._kill._pid
#define si_uid _sifields._kill._uid
+#define si_timer1 _sifields._timer._timer1
+#define si_timer2 _sifields._timer._timer2
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-alpha/unistd.h linux-2.3.13-pre5-devt/include/asm-alpha/unistd.h
--- linux-2.3.13-pre5-vanilla/include/asm-alpha/unistd.h Thu Aug 5 19:02:55 1999
+++ linux-2.3.13-pre5-devt/include/asm-alpha/unistd.h Thu Aug 5 19:05:49 1999
@@ -308,6 +308,11 @@
#define __NR_capget 368
#define __NR_capset 369
#define __NR_sendfile 370
+#define __NR_timer_create 371
+#define __NR_timer_settime 372
+#define __NR_timer_gettime 373
+#define __NR_timer_getoverrun 374
+#define __NR_timer_delete 375

#if defined(__LIBRARY__) && defined(__GNUC__)

diff -ruN linux-2.3.13-pre5-vanilla/include/asm-arm/siginfo.h linux-2.3.13-pre5-devt/include/asm-arm/siginfo.h
--- linux-2.3.13-pre5-vanilla/include/asm-arm/siginfo.h Sun Jun 20 11:39:59 1999
+++ linux-2.3.13-pre5-devt/include/asm-arm/siginfo.h Thu Aug 5 19:05:49 1999
@@ -67,6 +67,8 @@
*/
#define si_pid _sifields._kill._pid
#define si_uid _sifields._kill._uid
+#define si_timer1 _sifields._timer._timer1
+#define si_timer2 _sifields._timer._timer2
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-arm/unistd.h linux-2.3.13-pre5-devt/include/asm-arm/unistd.h
--- linux-2.3.13-pre5-vanilla/include/asm-arm/unistd.h Mon Jun 21 22:33:31 1999
+++ linux-2.3.13-pre5-devt/include/asm-arm/unistd.h Thu Aug 5 19:05:49 1999
@@ -198,6 +198,11 @@
/* 188 reserved */
/* 189 reserved */
#define __NR_vfork (__NR_SYSCALL_BASE+190)
+#define __NR_timer_create (__NR_SYSCALL_BASE+191)
+#define __NR_timer_settime (__NR_SYSCALL_BASE+192)
+#define __NR_timer_gettime (__NR_SYSCALL_BASE+193)
+#define __NR_timer_getoverrun (__NR_SYSCALL_BASE+194)
+#define __NR_timer_delete (__NR_SYSCALL_BASE+195)

#define __sys2(x) #x
#define __sys1(x) __sys2(x)
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-i386/siginfo.h linux-2.3.13-pre5-devt/include/asm-i386/siginfo.h
--- linux-2.3.13-pre5-vanilla/include/asm-i386/siginfo.h Sun Jun 20 11:39:59 1999
+++ linux-2.3.13-pre5-devt/include/asm-i386/siginfo.h Thu Aug 5 19:05:49 1999
@@ -31,13 +31,14 @@
struct {
unsigned int _timer1;
unsigned int _timer2;
+ sigval_t _sigval2; /* FIXME: must map to _sigval below because it is the same */
} _timer;

/* POSIX.1b signals */
struct {
pid_t _pid; /* sender's pid */
uid_t _uid; /* sender's uid */
- sigval_t _sigval;
+ sigval_t _sigval; /* FIXME: move out of union together with _sigval2 */
} _rt;

/* SIGCHLD */
@@ -67,6 +68,8 @@
*/
#define si_pid _sifields._kill._pid
#define si_uid _sifields._kill._uid
+#define si_timer1 _sifields._timer._timer1
+#define si_timer2 _sifields._timer._timer2
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-i386/unistd.h linux-2.3.13-pre5-devt/include/asm-i386/unistd.h
--- linux-2.3.13-pre5-vanilla/include/asm-i386/unistd.h Thu Aug 5 19:02:55 1999
+++ linux-2.3.13-pre5-devt/include/asm-i386/unistd.h Thu Aug 5 19:05:49 1999
@@ -195,6 +195,11 @@
#define __NR_getpmsg 188 /* some people actually want streams */
#define __NR_putpmsg 189 /* some people actually want streams */
#define __NR_vfork 190
+#define __NR_timer_create 191
+#define __NR_timer_settime 192
+#define __NR_timer_gettime 193
+#define __NR_timer_getoverrun 194
+#define __NR_timer_delete 195

/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */

diff -ruN linux-2.3.13-pre5-vanilla/include/asm-m68k/siginfo.h linux-2.3.13-pre5-devt/include/asm-m68k/siginfo.h
--- linux-2.3.13-pre5-vanilla/include/asm-m68k/siginfo.h Wed Aug 19 22:24:44 1998
+++ linux-2.3.13-pre5-devt/include/asm-m68k/siginfo.h Thu Aug 5 19:05:49 1999
@@ -67,6 +67,8 @@
*/
#define si_pid _sifields._kill._pid
#define si_uid _sifields._kill._uid
+#define si_timer1 _sifields._timer._timer1
+#define si_timer2 _sifields._timer._timer2
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-m68k/unistd.h linux-2.3.13-pre5-devt/include/asm-m68k/unistd.h
--- linux-2.3.13-pre5-vanilla/include/asm-m68k/unistd.h Tue Jan 19 19:58:34 1999
+++ linux-2.3.13-pre5-devt/include/asm-m68k/unistd.h Thu Aug 5 19:05:49 1999
@@ -194,6 +194,11 @@
#define __NR_getpmsg 188 /* some people actually want streams */
#define __NR_putpmsg 189 /* some people actually want streams */
#define __NR_vfork 190
+#define __NR_timer_create 191
+#define __NR_timer_settime 192
+#define __NR_timer_gettime 193
+#define __NR_timer_getoverrun 194
+#define __NR_timer_delete 195

/* user-visible error numbers are in the range -1 - -122: see
<asm-m68k/errno.h> */
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-mips/siginfo.h linux-2.3.13-pre5-devt/include/asm-mips/siginfo.h
--- linux-2.3.13-pre5-vanilla/include/asm-mips/siginfo.h Sun Jun 20 11:39:59 1999
+++ linux-2.3.13-pre5-devt/include/asm-mips/siginfo.h Thu Aug 5 19:05:49 1999
@@ -75,6 +75,8 @@
*/
#define si_pid _sifields._kill._pid
#define si_uid _sifields._kill._uid
+#define si_timer1 _sifields._timer._timer1
+#define si_timer2 _sifields._timer._timer2
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-mips/unistd.h linux-2.3.13-pre5-devt/include/asm-mips/unistd.h
--- linux-2.3.13-pre5-vanilla/include/asm-mips/unistd.h Thu Jul 1 20:36:33 1999
+++ linux-2.3.13-pre5-devt/include/asm-mips/unistd.h Thu Aug 5 19:05:49 1999
@@ -1196,6 +1196,11 @@
#define __NR_sendfile (__NR_Linux + 207)
#define __NR_getpmsg (__NR_Linux + 208)
#define __NR_putpmsg (__NR_Linux + 209)
+#define __NR_timer_create (__NR_Linux + 210)
+#define __NR_timer_settime (__NR_Linux + 211)
+#define __NR_timer_gettime (__NR_Linux + 212)
+#define __NR_timer_getoverrun (__NR_Linux + 213)
+#define __NR_timer_delete (__NR_Linux + 214)

/*
* Offset of the last Linux flavoured syscall
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-ppc/siginfo.h linux-2.3.13-pre5-devt/include/asm-ppc/siginfo.h
--- linux-2.3.13-pre5-vanilla/include/asm-ppc/siginfo.h Sun Jun 20 11:39:59 1999
+++ linux-2.3.13-pre5-devt/include/asm-ppc/siginfo.h Thu Aug 5 19:05:49 1999
@@ -67,6 +67,8 @@
*/
#define si_pid _sifields._kill._pid
#define si_uid _sifields._kill._uid
+#define si_timer1 _sifields._timer._timer1
+#define si_timer2 _sifields._timer._timer2
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
@@ -122,7 +124,7 @@
* SIGSEGV si_codes
*/
#define SEGV_MAPERR 1 /* address not mapped to object */
-#define SRGV_ACCERR 2 /* invalid permissions for mapped object */
+#define SEGV_ACCERR 2 /* invalid permissions for mapped object */
#define NSIGSEGV 2

/*
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-ppc/unistd.h linux-2.3.13-pre5-devt/include/asm-ppc/unistd.h
--- linux-2.3.13-pre5-vanilla/include/asm-ppc/unistd.h Thu Jul 1 20:36:34 1999
+++ linux-2.3.13-pre5-devt/include/asm-ppc/unistd.h Thu Aug 5 19:05:49 1999
@@ -194,6 +194,11 @@
#define __NR_getpmsg 187 /* some people actually want streams */
#define __NR_putpmsg 188 /* some people actually want streams */
#define __NR_vfork 189
+#define __NR_timer_create 190
+#define __NR_timer_settime 191
+#define __NR_timer_gettime 192
+#define __NR_timer_getoverrun 193
+#define __NR_timer_delete 194

#define __NR(n) #n

diff -ruN linux-2.3.13-pre5-vanilla/include/asm-sparc/siginfo.h linux-2.3.13-pre5-devt/include/asm-sparc/siginfo.h
--- linux-2.3.13-pre5-vanilla/include/asm-sparc/siginfo.h Thu Aug 5 19:02:55 1999
+++ linux-2.3.13-pre5-devt/include/asm-sparc/siginfo.h Thu Aug 5 19:05:49 1999
@@ -70,6 +70,8 @@
*/
#define si_pid _sifields._kill._pid
#define si_uid _sifields._kill._uid
+#define si_timer1 _sifields._timer._timer1
+#define si_timer2 _sifields._timer._timer2
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
@@ -127,7 +129,7 @@
* SIGSEGV si_codes
*/
#define SEGV_MAPERR 1 /* address not mapped to object */
-#define SRGV_ACCERR 2 /* invalid permissions for mapped object */
+#define SEGV_ACCERR 2 /* invalid permissions for mapped object */
#define NSIGSEGV 2

/*
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-sparc/unistd.h linux-2.3.13-pre5-devt/include/asm-sparc/unistd.h
--- linux-2.3.13-pre5-vanilla/include/asm-sparc/unistd.h Sun Jun 20 11:40:00 1999
+++ linux-2.3.13-pre5-devt/include/asm-sparc/unistd.h Thu Aug 5 19:05:49 1999
@@ -123,11 +123,11 @@
#define __NR_rt_sigtimedwait 105 /* Linux Specific */
#define __NR_rt_sigqueueinfo 106 /* Linux Specific */
#define __NR_rt_sigsuspend 107 /* Linux Specific */
-/* #define __NR_sigvec 108 SunOS Specific */
-/* #define __NR_sigblock 109 SunOS Specific */
-/* #define __NR_sigsetmask 110 SunOS Specific */
-/* #define __NR_sigpause 111 SunOS Specific */
-/* #define __NR_sigstack 112 SunOS Specific */
+#define __NR_timer_create 108 /* Linux Specific */
+#define __NR_timer_settime 109 /* Linux Specific */
+#define __NR_timer_gettime 110 /* Linux Specific */
+#define __NR_timer_getoverrun 111 /* Linux Specific */
+#define __NR_timer_delete 112 /* Linux Specific */
#define __NR_recvmsg 113 /* Common */
#define __NR_sendmsg 114 /* Common */
/* #define __NR_vtrace 115 SunOS Specific */
@@ -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) \
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-sparc64/siginfo.h linux-2.3.13-pre5-devt/include/asm-sparc64/siginfo.h
--- linux-2.3.13-pre5-vanilla/include/asm-sparc64/siginfo.h Thu Aug 5 19:02:55 1999
+++ linux-2.3.13-pre5-devt/include/asm-sparc64/siginfo.h Thu Aug 5 19:05:49 1999
@@ -130,6 +130,8 @@
*/
#define si_pid _sifields._kill._pid
#define si_uid _sifields._kill._uid
+#define si_timer1 _sifields._timer._timer1
+#define si_timer2 _sifields._timer._timer2
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
@@ -187,7 +189,7 @@
* SIGSEGV si_codes
*/
#define SEGV_MAPERR 1 /* address not mapped to object */
-#define SRGV_ACCERR 2 /* invalid permissions for mapped object */
+#define SEGV_ACCERR 2 /* invalid permissions for mapped object */
#define NSIGSEGV 2

/*
@@ -266,7 +268,7 @@
#ifdef __KERNEL__

typedef struct sigevent32 {
- sigval_t sigev_value;
+ sigval_t32 sigev_value;
int sigev_signo;
int sigev_notify;
union {
diff -ruN linux-2.3.13-pre5-vanilla/include/asm-sparc64/unistd.h linux-2.3.13-pre5-devt/include/asm-sparc64/unistd.h
--- linux-2.3.13-pre5-vanilla/include/asm-sparc64/unistd.h Thu Aug 5 19:02:55 1999
+++ linux-2.3.13-pre5-devt/include/asm-sparc64/unistd.h Thu Aug 5 19:05:49 1999
@@ -123,11 +123,11 @@
#define __NR_rt_sigtimedwait 105 /* Linux Specific */
#define __NR_rt_sigqueueinfo 106 /* Linux Specific */
#define __NR_rt_sigsuspend 107 /* Linux Specific */
-/* #define __NR_sigvec 108 SunOS Specific */
-/* #define __NR_sigblock 109 SunOS Specific */
-/* #define __NR_sigsetmask 110 SunOS Specific */
-/* #define __NR_sigpause 111 SunOS Specific */
-/* #define __NR_sigstack 112 SunOS Specific */
+#define __NR_timer_create 108 /* Linux Specific */
+#define __NR_timer_settime 109 /* Linux Specific */
+#define __NR_timer_gettime 110 /* Linux Specific */
+#define __NR_timer_getoverrun 111 /* Linux Specific */
+#define __NR_timer_delete 112 /* Linux Specific */
#define __NR_recvmsg 113 /* Common */
#define __NR_sendmsg 114 /* Common */
/* #define __NR_vtrace 115 SunOS Specific */
@@ -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) \
diff -ruN linux-2.3.13-pre5-vanilla/include/linux/limits.h linux-2.3.13-pre5-devt/include/linux/limits.h
--- linux-2.3.13-pre5-vanilla/include/linux/limits.h Thu Jul 29 03:21:45 1999
+++ linux-2.3.13-pre5-devt/include/linux/limits.h Thu Aug 5 19:05:52 1999
@@ -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
diff -ruN linux-2.3.13-pre5-vanilla/include/linux/sched.h linux-2.3.13-pre5-devt/include/linux/sched.h
--- linux-2.3.13-pre5-vanilla/include/linux/sched.h Thu Aug 5 19:02:55 1999
+++ linux-2.3.13-pre5-devt/include/linux/sched.h Thu Aug 5 19:15:26 1999
@@ -36,6 +36,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
@@ -240,6 +241,26 @@
*/
struct user_struct;

+/* POSIX.1b interval timer structure. */
+struct k_itimer {
+ spinlock_t it_lock;
+ clockid_t it_clock; /* which timer type */
+ timer_t it_id; /* timer id */
+ int it_overrun; /* number of signals overrun */
+ struct sigevent it_signal; /* signal to be delivered */
+ struct timespec it_interval; /* interval (rounded to jiffies) */
+ int it_incr; /* interval specified in jiffies */
+ struct task_struct *it_process; /* process to send signal to */
+ struct timer_list it_timer;
+};
+
+/* Structure to maintain the dynamically created POSIX.1b interval timers. */
+struct itimer_struct {
+ atomic_t count;
+ spinlock_t its_lock;
+ struct k_itimer *itimer[TIMER_MAX];
+};
+
struct task_struct {
/* these are hardcoded - don't touch */
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
@@ -295,6 +316,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];
@@ -381,6 +403,7 @@
/* chld wait */ __WAIT_QUEUE_HEAD_INITIALIZER(name.wait_chldexit), NULL, \
/* timeout */ SCHED_OTHER,0,0,0,0,0,0,0, \
/* timer */ { NULL, NULL, 0, 0, it_real_fn }, \
+/* POSIX.1b timer */ NULL, \
/* utime */ {0,0,0,0},0, \
/* per CPU times */ {0, }, {0, }, \
/* flt */ 0,0,0,0,0,0, \
@@ -676,6 +699,7 @@
extern void exit_fs(struct task_struct *);
extern void exit_files(struct task_struct *);
extern void exit_sighand(struct task_struct *);
+extern void exit_itimers(struct task_struct *);

extern int do_execve(char *, char **, char **, struct pt_regs *);
extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
diff -ruN linux-2.3.13-pre5-vanilla/include/linux/sysctl.h linux-2.3.13-pre5-devt/include/linux/sysctl.h
--- linux-2.3.13-pre5-vanilla/include/linux/sysctl.h Sat Jul 24 16:26:13 1999
+++ linux-2.3.13-pre5-devt/include/linux/sysctl.h Thu Aug 5 19:05:52 1999
@@ -93,15 +93,63 @@
KERN_SG_BIG_BUFF=29,
KERN_ACCT=30, /* BSD process accounting parameters */
KERN_PPC_L2CR=31, /* l2cr register on PPC */
-
- KERN_RTSIGNR=32, /* Number of rt sigs queued */
- KERN_RTSIGMAX=33, /* Max queuable */

KERN_SHMMAX=34, /* int: Maximum shared memory segment */
KERN_MSGMAX=35, /* int: Maximum size of a messege */
KERN_MSGMNB=36, /* int: Maximum message queue size */
KERN_MSGPOOL=37, /* int: Maximum system message pool size */
- KERN_MAX_THREADS=38 /* int: Maximum nr of threads in the system */
+ KERN_MAX_THREADS=38, /* int: Maximum nr of threads in the system */
+ KERN_ARG_MAX=39, /* int: Max size of argv[] plus envp[] */
+ KERN_CHILD_MAX=40, /* int: Max processes allowed to a UID */
+ KERN_CLK_TCK=41, /* int: Ticks per second (clock_t) */
+ KERN_NGROUPS_MAX=42, /* int: Max simultaneous groups to which one
+ may belong */
+ KERN_OPEN_MAX=43, /* int: Max open files per process */
+ KERN_JOB_CONTROL=44, /* int: Job control supported? */
+ KERN_SAVED_IDS=45, /* int: Saved IDs (seteuid()) supported? */
+ KERN_PAGE_SIZE=46, /* int: system memory page size */
+ KERN_NPROCESSORS_CONF=47, /* int: Number of processors configured */
+ KERN_NPROCESSORS_ONLN=48, /* int: Number of processors online */
+ KERN_ASYNCHRONOUS_IO=49, /* int: Supports asynchronous I/O */
+ KERN_FSYNC=50, /* int: Supports file synchronization */
+ KERN_MAPPED_FILES=51, /* int: Supports memory mapped files */
+ KERN_MEMLOCK=52, /* int: Supports process memory locking */
+ KERN_MEMLOCK_RANGE=53, /* int: Supports memory range locking */
+ KERN_MEMORY_PROTECTION=54, /* int: Supports memory protection */
+ KERN_MESSAGE_PASSING=55, /* int: Supports message passing */
+ KERN_PRIORITIZED_IO=56, /* int: Supports prioritized I/O */
+ KERN_PRIORITY_SCHEDULING=57, /* int: Supports priority scheduling */
+ KERN_REALTIME_SIGNALS=58, /* int: Supports realtime signals */
+ KERN_SEMAPHORES=59, /* int: Supports semaphores */
+ KERN_SHARED_MEMORY_OBJECTS=60, /* int: Supports shared memory objects */
+ KERN_SYNCHRONIZED_IO=61, /* int: Supports syncrhonized I/O */
+ KERN_TIMERS=62, /* int: Supports POSIX timers */
+ KERN_DELAYTIMER_MAX=63, /* int: Max value of timer overrun */
+ KERN_TIMER_MAX=64, /* int: Max number of timers per process */
+ KERN_IOV_MAX=65, /* int: Max number of iovec structures per
+ readv or writev call */
+ KERN_STREAM_MAX=66, /* int: Max number of streams one process
+ can have open */
+ KERN_AIO_LISTIO_MAX=67, /* int: Max number of I/O operations in a
+ single list I/O call */
+ KERN_AIO_MAX=68, /* int: Max number of outstanding asynchronous
+ I/O operations */
+ KERN_AIO_PRIO_DELTA_MAX=69, /* int: Max amount by which a process can
+ decrease its asynchronous I/O
+ priority level from its own
+ scheduling priority */
+ KERN_MQ_OPEN_MAX=70, /* int: Max number of open message queues
+ per process */
+ KERN_MQ_PRIO_MAX=71, /* int: Max number of message priorities
+ supported by implementation */
+ KERN_SEM_NSEMS_MAX=72, /* int: Max number of semaphores per process */
+ KERN_SEM_VALUE_MAX=73, /* int: Max value a semaphore may have */
+ KERN_SIGQUEUE_MAX=74, /* int: Max number of queued signals that a process may
+ send and have pending at receiver(s) at a time */
+ KERN_SIGQUEUE_NR=75, /* int: number of queued signals in the system */
+ KERN_RTSIG_MAX=76, /* int: Max number of realtime signals reserved for
+ application use */
+ KERN_LINUX_COUNTER_HZ=77 /* int: Frequency of free running counter */
};


diff -ruN linux-2.3.13-pre5-vanilla/include/linux/time.h linux-2.3.13-pre5-devt/include/linux/time.h
--- linux-2.3.13-pre5-vanilla/include/linux/time.h Mon Dec 28 07:18:28 1998
+++ linux-2.3.13-pre5-devt/include/linux/time.h Thu Aug 5 19:05:52 1999
@@ -26,6 +26,19 @@
*/
#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)

+/* Parameters used to convert the timespec values */
+#ifndef USEC_PER_SEC
+#define USEC_PER_SEC (1000000L)
+#endif
+
+#ifndef NSEC_PER_SEC
+#define NSEC_PER_SEC (1000000000L)
+#endif
+
+#ifndef NSEC_PER_USEC
+#define NSEC_PER_USEC (1000L)
+#endif
+
static __inline__ unsigned long
timespec_to_jiffies(struct timespec *value)
{
@@ -34,15 +47,15 @@

if (sec >= (MAX_JIFFY_OFFSET / HZ))
return MAX_JIFFY_OFFSET;
- nsec += 1000000000L / HZ - 1;
- nsec /= 1000000000L / HZ;
+ nsec += NSEC_PER_SEC / HZ - 1;
+ nsec /= NSEC_PER_SEC / HZ;
return HZ * sec + nsec;
}

static __inline__ void
jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
{
- value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
+ value->tv_nsec = (jiffies % HZ) * (NSEC_PER_SEC / HZ);
value->tv_sec = jiffies / HZ;
}

@@ -88,5 +101,24 @@
struct timeval it_interval; /* timer interval */
struct timeval it_value; /* current value */
};
+
+
+/*
+ * Data types for POSIX.1b interval timers.
+ */
+typedef int clockid_t;
+typedef int timer_t;
+
+/*
+ * The IDs of the various system clocks (for POSIX.1b interval timers).
+ */
+#define CLOCK_REALTIME 0
+
+/*
+ * The various flags for setting POSIX.1b interval timers.
+ */
+
+#define TIMER_ABSTIME 0x01
+

#endif
diff -ruN linux-2.3.13-pre5-vanilla/kernel/exit.c linux-2.3.13-pre5-devt/kernel/exit.c
--- linux-2.3.13-pre5-vanilla/kernel/exit.c Thu Aug 5 19:02:58 1999
+++ linux-2.3.13-pre5-devt/kernel/exit.c Thu Aug 5 19:05:52 1999
@@ -260,6 +260,34 @@
mmdrop(active_mm);
}

+static inline void __exit_itimers(struct task_struct *tsk)
+{
+ struct itimer_struct *timers = tsk->posix_timers;
+ struct k_itimer *timr;
+ int i;
+
+ if (timers == NULL) return;
+
+ if (atomic_dec_and_test(&timers->count)) {
+ tsk->posix_timers = NULL;
+ for (i = 0; i < TIMER_MAX; i++) {
+ timr = timers->itimer[i];
+ if (timr) {
+ start_bh_atomic();
+ del_timer(&timr->it_timer);
+ end_bh_atomic();
+ kfree(timr);
+ }
+ }
+ kfree(timers);
+ }
+}
+
+void exit_itimers(struct task_struct *tsk)
+{
+ __exit_itimers(tsk);
+}
+
/*
* Turn us into a lazy TLB process if we
* aren't already..
@@ -384,6 +412,7 @@
__exit_files(tsk);
__exit_fs(tsk);
__exit_sighand(tsk);
+ __exit_itimers(tsk);
exit_thread();
tsk->state = TASK_ZOMBIE;
tsk->exit_code = code;
diff -ruN linux-2.3.13-pre5-vanilla/kernel/fork.c linux-2.3.13-pre5-devt/kernel/fork.c
--- linux-2.3.13-pre5-vanilla/kernel/fork.c Thu Aug 5 19:02:58 1999
+++ linux-2.3.13-pre5-devt/kernel/fork.c Thu Aug 5 19:05:52 1999
@@ -581,6 +581,23 @@
p->flags = new_flags;
}

+
+static inline int copy_itimers(unsigned long clone_flags, struct task_struct * tsk)
+{
+ if (clone_flags & CLONE_ITIMERS) {
+ atomic_inc(&tsk->posix_timers->count);
+ return 0;
+ }
+
+ tsk->posix_timers = kmalloc(sizeof(*tsk->posix_timers), GFP_KERNEL);
+ if (tsk->posix_timers == NULL) return -1;
+ spin_lock_init(&tsk->posix_timers->its_lock);
+ atomic_set(&tsk->posix_timers->count, 1);
+ memset(tsk->posix_timers->itimer, 0, sizeof(tsk->posix_timers->itimer));
+ return 0;
+}
+
+
/*
* Ok, this is the main fork-routine. It copies the system process
* information (task[nr]) and sets up the necessary registers. It
@@ -680,6 +697,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);
@@ -724,6 +743,8 @@
down(&sem);
return retval;

+bad_fork_cleanup_itimers:
+ exit_itimers(p);
bad_fork_cleanup_sighand:
exit_sighand(p);
bad_fork_cleanup_fs:
diff -ruN linux-2.3.13-pre5-vanilla/kernel/itimer.c linux-2.3.13-pre5-devt/kernel/itimer.c
--- linux-2.3.13-pre5-vanilla/kernel/itimer.c Tue Nov 24 22:51:44 1998
+++ linux-2.3.13-pre5-devt/kernel/itimer.c Thu Aug 5 19:05:52 1999
@@ -9,14 +9,16 @@
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
+#include <linux/malloc.h>
+#include <linux/time.h>

#include <asm/uaccess.h>

/*
- * change timeval to jiffies, trying to avoid the
+ * change timeval to jiffies, trying to avoid the
* most obvious overflows..
*
- * The tv_*sec values are signed, but nothing seems to
+ * The tv_*sec values are signed, but nothing seems to
* indicate whether we really should use them as signed values
* when doing itimers. POSIX doesn't mention this (but if
* alarm() uses itimers without checking, we have to use unsigned
@@ -168,6 +170,389 @@
return error;

if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
- return -EFAULT;
+ return -EFAULT;
+ return 0;
+}
+
+/* PRECONDITION:
+ * timr->it_lock must be locked
+ */
+static void timer_notify_task(struct k_itimer *timr)
+{
+ struct siginfo info;
+ int ret;
+
+ if (timr->it_signal.sigev_notify == SIGEV_SIGNAL) {
+
+ /* Send signal to the process that owns this timer. */
+ info.si_signo = timr->it_signal.sigev_signo;
+ info.si_errno = 0;
+ info.si_code = SI_TIMER;
+ /* TODO: if someone has better ideas what to put in
+ * the next two fields...
+ * si_timer1 is currently used in signal.c to check
+ * whether a signal from this timer is already in the signal
+ * queue.
+ */
+ info.si_timer1 = timr->it_id;
+ info.si_timer2 = 0;
+ info.si_value = timr->it_signal.sigev_value;
+ ret = send_sig_info(info.si_signo, &info, timr->it_process);
+ switch (ret) {
+ case 0: /* all's well */
+ timr->it_overrun = 0;
+ break;
+ case 1: /* signal from this timer was already in the queue */
+ timr->it_overrun++;
+ break;
+ default:
+ printk(KERN_WARNING "sending signal failed: %d\n", ret);
+ break;
+ }
+ }
+}
+
+/* This function gets called when a POSIX.1b interval timer expires. */
+static void posix_timer_fn(unsigned long __data)
+{
+ struct k_itimer *timr = (struct k_itimer *)__data;
+ unsigned long interval;
+
+ spin_lock(&timr->it_lock);
+
+ timer_notify_task(timr);
+
+ /* Set up the timer for the next interval (if there is one) */
+ if ((interval = timr->it_incr) == 0) goto out;
+
+ if (interval > (unsigned long) LONG_MAX)
+ interval = LONG_MAX;
+ timr->it_timer.expires = jiffies + interval;
+ add_timer(&timr->it_timer);
+out:
+ spin_unlock(&timr->it_lock);
+}
+
+/* Find the first available slot for the new timer. */
+static int timer_find_slot(struct itimer_struct *timers)
+{
+ int i;
+
+ for (i = 0; i < 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;
+}
+
+/* Create a POSIX.1b interval timer. */
+
+asmlinkage int sys_timer_create(clockid_t which_clock,
+ struct sigevent *timer_event_spec,
+ timer_t *created_timer_id)
+{
+ int error = 0;
+ struct k_itimer *new_timer = NULL;
+ struct itimer_struct *timers = current->posix_timers;
+ int new_timer_id;
+
+ /* Right now, we only support CLOCK_REALTIME for timers. */
+ if (which_clock != CLOCK_REALTIME) return -EINVAL;
+
+ new_timer = (struct k_itimer *)kmalloc(sizeof(*new_timer), GFP_KERNEL);
+ if (new_timer == NULL) return -EAGAIN;
+
+ spin_lock_init(&new_timer->it_lock);
+ new_timer->it_clock = which_clock;
+ new_timer->it_incr = 0;
+ new_timer->it_overrun = 0;
+
+ if (timer_event_spec) {
+ if (copy_from_user(&new_timer->it_signal, timer_event_spec,
+ sizeof(new_timer->it_signal))) {
+ error = -EFAULT;
+ goto out;
+ }
+ if (!good_sigevent(&new_timer->it_signal)) {
+ error = -EINVAL;
+ goto out;
+ }
+ }
+ else {
+ new_timer->it_signal.sigev_notify = SIGEV_SIGNAL;
+ new_timer->it_signal.sigev_signo = SIGALRM;
+ }
+
+ new_timer->it_interval.tv_sec = 0;
+ new_timer->it_interval.tv_nsec = 0;
+ new_timer->it_process = current;
+ new_timer->it_timer.next = NULL;
+ new_timer->it_timer.prev = NULL;
+ new_timer->it_timer.expires = 0;
+ new_timer->it_timer.data = (unsigned long)new_timer;
+ new_timer->it_timer.function = posix_timer_fn;
+
+ spin_lock(&timers->its_lock);
+
+ new_timer_id = timer_find_slot(timers);
+ if (new_timer_id == -1) {
+ error = -EAGAIN;
+ goto out;
+ }
+ new_timer->it_id = new_timer_id;
+ timers->itimer[new_timer_id] = new_timer;
+ if (timer_event_spec == NULL) {
+ new_timer->it_signal.sigev_value.sival_int = new_timer_id;
+ }
+
+ if (copy_to_user(created_timer_id, &new_timer_id, sizeof(new_timer_id))) {
+ error = -EFAULT;
+ timers->itimer[new_timer_id] = NULL;
+ }
+
+ spin_unlock(&timers->its_lock);
+out:
+ if (error) {
+ kfree(new_timer);
+ }
+ return error;
+}
+
+
+/* good_timespec
+ *
+ * This function checks the elements of a timespec structure.
+ *
+ * Arguments:
+ * ts : Pointer to the timespec structure to check
+ *
+ * Return value:
+ * If a NULL pointer was passed in, or the tv_nsec field was less than 0 or
+ * greater than NSEC_PER_SEC, or the tv_sec field was less than 0, this
+ * function returns 0. Otherwise it returns 1.
+ */
+
+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;
+ 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. */
+void do_timer_settime(struct k_itimer *timr, int flags,
+ struct itimerspec *new_setting,
+ struct itimerspec *old_setting)
+{
+ /* disable the timer */
+ start_bh_atomic();
+ del_timer(&timr->it_timer);
+ end_bh_atomic();
+
+ if (old_setting) {
+ do_timer_gettime(timr, old_setting);
+ }
+
+ /* switch off the timer when it_value is zero */
+ if ((new_setting->it_value.tv_sec == 0) &&
+ (new_setting->it_value.tv_nsec == 0)) {
+ timr->it_incr = 0;
+ timr->it_timer.expires = 0;
+ timr->it_interval.tv_sec = 0;
+ timr->it_interval.tv_nsec = 0;
+ return;
+ }
+
+ timr->it_incr = timespec_to_jiffies(&new_setting->it_interval);
+ /* save the interval rounded to jiffies */
+ jiffies_to_timespec(timr->it_incr, &timr->it_interval);
+
+ if (flags & TIMER_ABSTIME) {
+ timer_value_abs_to_rel(&new_setting->it_value);
+ }
+
+ timr->it_timer.expires = timespec_to_jiffies(&new_setting->it_value) + jiffies;
+
+ /*
+ * For some reason the timer does not fire immediately if expires is
+ * equal to jiffies, so the timer callback function is called directly.
+ */
+ if (timr->it_timer.expires == jiffies) {
+ posix_timer_fn((unsigned long)timr);
+ }
+ else {
+ add_timer(&timr->it_timer);
+ }
+}
+
+
+/* Set a POSIX.1b interval timer */
+asmlinkage int sys_timer_settime(timer_t timer_id, int flags,
+ const struct itimerspec *new_setting,
+ struct itimerspec *old_setting)
+{
+ struct k_itimer *timr;
+ struct itimerspec new_spec, old_spec;
+ int error = 0;
+
+ timr = lock_timer(current, timer_id);
+ if (!timr) return -EINVAL;
+
+ if (new_setting == NULL) {
+ error = -EINVAL;
+ goto out;
+ }
+
+ if (copy_from_user(&new_spec, new_setting, sizeof(new_spec))) {
+ error = -EFAULT;
+ goto out;
+ }
+
+ if ((!good_timespec(&new_spec.it_interval)) ||
+ (!good_timespec(&new_spec.it_value))) {
+ error = -EINVAL;
+ goto out;
+ }
+
+ do_timer_settime(timr, flags, &new_spec,
+ old_setting ? &old_spec : NULL);
+
+ if (old_setting) {
+ if (copy_to_user(old_setting, &old_spec, sizeof(old_spec))) {
+ error = -EFAULT;
+ }
+ }
+
+out:
+ unlock_timer(timr);
+ return error;
+}
+
+
+/* Delete a POSIX.1b interval timer. */
+asmlinkage int sys_timer_delete(timer_t timer_id)
+{
+ struct k_itimer *timr;
+
+ timr = lock_timer(current, timer_id);
+ if (!timr) return -EINVAL;
+
+ start_bh_atomic();
+ del_timer(&timr->it_timer);
+ end_bh_atomic();
+
+ spin_lock(&current->posix_timers->its_lock);
+
+ kfree(timr);
+ current->posix_timers->itimer[timer_id] = NULL;
+
+ spin_unlock(&current->posix_timers->its_lock);
+
return 0;
}
diff -ruN linux-2.3.13-pre5-vanilla/kernel/signal.c linux-2.3.13-pre5-devt/kernel/signal.c
--- linux-2.3.13-pre5-vanilla/kernel/signal.c Sat Jul 10 16:30:50 1999
+++ linux-2.3.13-pre5-devt/kernel/signal.c Thu Aug 5 19:05:52 1999
@@ -129,64 +129,48 @@

if (sig) {
int reset = 1;
+ struct signal_queue *q, **pp;

/* Collect the siginfo appropriate to this signal. */
- if (sig < SIGRTMIN) {
- /* XXX: As an extension, support queueing exactly
- one non-rt signal if SA_SIGINFO is set, so that
- we can get more detailed information about the
- cause of the signal. */
- /* Deciding not to init these couple of fields is
- more expensive that just initializing them. */
+ pp = &current->sigqueue;
+ q = current->sigqueue;
+
+ /* Find the one we're interested in ... */
+ for ( ; q ; pp = &q->next, q = q->next)
+ if (q->info.si_signo == sig)
+ break;
+ if (q) {
+ if ((*pp = q->next) == NULL)
+ current->sigqueue_tail = pp;
+ *info = q->info;
+ kmem_cache_free(signal_queue_cachep,q);
+ atomic_dec(&nr_queued_signals);
+
+ /* then see if this signal is still pending. */
+ q = *pp;
+ while (q) {
+ if (q->info.si_signo == sig) {
+ reset = 0;
+ break;
+ }
+ q = q->next;
+ }
+ } else {
+ /* Ok, it wasn't in the queue. It must have
+ been sent either by a non-rt mechanism and
+ we ran out of queue space. So zero out the
+ info. */
info->si_signo = sig;
info->si_errno = 0;
info->si_code = 0;
info->si_pid = 0;
info->si_uid = 0;
- } else {
- struct signal_queue *q, **pp;
- pp = &current->sigqueue;
- q = current->sigqueue;
-
- /* Find the one we're interested in ... */
- for ( ; q ; pp = &q->next, q = q->next)
- if (q->info.si_signo == sig)
- break;
- if (q) {
- if ((*pp = q->next) == NULL)
- current->sigqueue_tail = pp;
- *info = q->info;
- kmem_cache_free(signal_queue_cachep,q);
- atomic_dec(&nr_queued_signals);
-
- /* then see if this signal is still pending. */
- q = *pp;
- while (q) {
- if (q->info.si_signo == sig) {
- reset = 0;
- break;
- }
- q = q->next;
- }
- } else {
- /* Ok, it wasn't in the queue. It must have
- been sent either by a non-rt mechanism and
- we ran out of queue space. So zero out the
- info. */
- info->si_signo = sig;
- info->si_errno = 0;
- info->si_code = 0;
- info->si_pid = 0;
- info->si_uid = 0;
- }
}

if (reset)
sigdelset(&current->signal, sig);
recalc_sigpending(current);

- /* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER,
- we need to xchg out the timer overrun values. */
} else {
/* XXX: Once CLONE_PID is in to join those "threads" that are
part of the same "process", look for signals sent to the
@@ -247,11 +231,31 @@
return 1;
}

+static void set_siginfo(siginfo_t *info, int sig, int kernel_signal)
+{
+ if (kernel_signal) {
+ info->si_signo = sig;
+ info->si_errno = 0;
+ info->si_code = SI_KERNEL;
+ info->si_pid = 0;
+ info->si_uid = 0;
+ }
+ else {
+ info->si_signo = sig;
+ info->si_errno = 0;
+ info->si_code = SI_USER;
+ info->si_pid = current->pid;
+ info->si_uid = current->uid;
+ }
+}
+
int
send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
{
unsigned long flags;
int ret;
+ struct signal_queue *q;
+ siginfo_t info_compat;

#if DEBUG_SIG
printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
@@ -260,9 +264,16 @@
ret = -EINVAL;
if (sig < 0 || sig > _NSIG)
goto out_nolock;
+
+ /* backward compatibility, convert magic info value to real info */
+ if ((info == NULL) || ((unsigned long)info == 1)) {
+ set_siginfo(&info_compat, sig, info != NULL);
+ info = &info_compat;
+ }
+
/* The somewhat baroque permissions check... */
ret = -EPERM;
- if ((!info || ((unsigned long)info != 1 && SI_FROMUSER(info)))
+ if (SI_FROMUSER(info)
&& ((sig != SIGCONT) || (current->session != t->session))
&& (current->euid ^ t->suid) && (current->euid ^ t->uid)
&& (current->uid ^ t->suid) && (current->uid ^ t->uid)
@@ -304,63 +315,61 @@
if (ignored_signal(sig, t))
goto out;

- if (sig < SIGRTMIN) {
- /* Non-real-time signals are not queued. */
- /* XXX: As an extension, support queueing exactly one
- non-rt signal if SA_SIGINFO is set, so that we can
- get more detailed information about the cause of
- the signal. */
+ /* 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 (info->si_code == SI_TIMER) {
+ for (q = t->sigqueue; q; q = q->next) {
+ if ((q->info.si_code == SI_TIMER) &&
+ (q->info.si_timer1 == info->si_timer1)) {
+ /* this special value (1) is recognized
+ only by posix_timer_fn() in itimer.c */
+ ret = 1;
+ goto out;
+ }
+ }
+ }
+ /* If it is not a timer signal, and it is a NON RT signal,
+ only one signal gets queued, the later ones are discarded.
+ However, signals coming from posix timers are allowed in order
+ to be able to maintain the overrun count (see above if stmt.) */
+
+ else if (sig < SIGRTMIN) {
+ /* Non-real-time signals are not queued. */
if (sigismember(&t->signal, sig))
goto out;
+ }
+
+ /* Real-time signals must be queued if sent by sigqueue, or
+ some other real-time mechanism. It is implementation
+ defined whether kill() does so. We attempt to do so, on
+ the principle of least surprise, but since kill is not
+ allowed to fail with EAGAIN when low on memory we just
+ make sure at least one signal gets delivered and don't
+ pass on the info struct. */
+
+ q = 0;
+ if (atomic_read(&nr_queued_signals) < max_queued_signals) {
+ q = (struct signal_queue *)
+ kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
+ }
+
+ if (q) {
+ atomic_inc(&nr_queued_signals);
+ q->next = NULL;
+ *t->sigqueue_tail = q;
+ t->sigqueue_tail = &q->next;
+ q->info = *info;
} else {
- /* Real-time signals must be queued if sent by sigqueue, or
- some other real-time mechanism. It is implementation
- defined whether kill() does so. We attempt to do so, on
- the principle of least surprise, but since kill is not
- allowed to fail with EAGAIN when low on memory we just
- make sure at least one signal gets delivered and don't
- pass on the info struct. */
-
- struct signal_queue *q = 0;
-
- if (atomic_read(&nr_queued_signals) < max_queued_signals) {
- q = (struct signal_queue *)
- kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
- }
-
- if (q) {
- atomic_inc(&nr_queued_signals);
- q->next = NULL;
- *t->sigqueue_tail = q;
- t->sigqueue_tail = &q->next;
- switch ((unsigned long) info) {
- case 0:
- q->info.si_signo = sig;
- q->info.si_errno = 0;
- q->info.si_code = SI_USER;
- q->info.si_pid = current->pid;
- q->info.si_uid = current->uid;
- break;
- case 1:
- q->info.si_signo = sig;
- q->info.si_errno = 0;
- q->info.si_code = SI_KERNEL;
- q->info.si_pid = 0;
- q->info.si_uid = 0;
- break;
- default:
- q->info = *info;
- break;
- }
- } else {
- /* If this was sent by a rt mechanism, try again. */
- if (info->si_code < 0) {
- ret = -EAGAIN;
- goto out;
- }
- /* Otherwise, mention that the signal is pending,
- but don't queue the info. */
+ /* If this was sent by a rt mechanism, try again. */
+ if (info->si_code < 0) {
+ ret = -EAGAIN;
+ goto out;
}
+ /* Otherwise, mention that the signal is pending,
+ but don't queue the info. */
}

sigaddset(&t->signal, sig);
diff -ruN linux-2.3.13-pre5-vanilla/kernel/sysctl.c linux-2.3.13-pre5-devt/kernel/sysctl.c
--- linux-2.3.13-pre5-vanilla/kernel/sysctl.c Sat Jul 24 16:26:14 1999
+++ linux-2.3.13-pre5-devt/kernel/sysctl.c Thu Aug 5 19:05:52 1999
@@ -20,6 +20,13 @@
#include <linux/utsname.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/limits.h>
+#include <linux/uio.h>
+#include <linux/swap.h>
+#include <linux/mm.h>
+#include <asm/param.h>
+#include <asm/page.h>
+#include <asm/smp.h>

#include <asm/uaccess.h>

@@ -37,6 +44,22 @@
extern int max_threads;
extern int nr_queued_signals, max_queued_signals;

+#ifdef __SMP__
+#if defined __i386__
+extern unsigned int num_processors; /* arch/i386/kernel/smp.c */
+#elif defined __alpha__
+extern int smp_num_probed; /* arch/alpha/kernel/smp.c */
+#elif defined __powerpc__
+extern int cpu_nr; /* arch/ppc/kernel/smp.c */
+#endif
+
+extern int smp_num_cpus; /* arch/<all>/kernel/smp.c */
+#endif /* __SMP__ */
+
+#ifdef __i386__
+extern unsigned long cpu_hz; /* arch/i386/kernel/time.c */
+#endif
+
#ifdef CONFIG_KMOD
extern char modprobe_path[];
#endif
@@ -153,6 +176,21 @@
{0}
};

+/* static values */
+static int arg_max = ARG_MAX;
+static int child_max = CHILD_MAX; /* from limits.h, but is there really a limit? */
+static int clk_tck = HZ;
+static int ngroups_max = NGROUPS;
+static int open_max = NR_OPEN;
+static int supp = 1;
+static int not_supp = 0;
+static int one = 1;
+static int page_size = PAGE_SIZE;
+static int delaytimer_max = DELAYTIMER_MAX;
+static int timer_max = TIMER_MAX;
+static int iov_max = UIO_MAXIOV;
+static int rtsig_max = SIGRTMAX - SIGRTMIN + 1;
+
static ctl_table kern_table[] = {
{KERN_OSTYPE, "ostype", system_utsname.sysname, 64,
0444, NULL, &proc_doutsstring, &sysctl_string},
@@ -200,16 +238,96 @@
{KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
0644, NULL, &proc_dointvec},
#endif
- {KERN_RTSIGNR, "rtsig-nr", &nr_queued_signals, sizeof(int),
- 0444, NULL, &proc_dointvec},
- {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int),
+ {KERN_SIGQUEUE_MAX, "sigqueue-max", &max_queued_signals, sizeof(int),
0644, NULL, &proc_dointvec},
+ {KERN_SIGQUEUE_NR, "sigqueue-nr", &nr_queued_signals, sizeof(int),
+ 0444, NULL, &proc_dointvec},
#ifdef CONFIG_SYSVIPC
{KERN_SHMMAX, "shmmax", &shmmax, sizeof (int),
0644, NULL, &proc_dointvec},
#endif
{KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int),
0644, NULL, &proc_dointvec},
+ {KERN_ARG_MAX, "arg-max", &arg_max, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_CHILD_MAX, "child-max", &child_max, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_CLK_TCK, "clk-tck", &clk_tck, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_NGROUPS_MAX, "ngroups-max", &ngroups_max, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_OPEN_MAX, "open-max", &open_max, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_JOB_CONTROL, "job-control", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_SAVED_IDS, "saved-ids", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_PAGE_SIZE, "page-size", &page_size, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_NPROCESSORS_CONF, "nprocessors-conf",
+#ifdef __SMP__
+#if defined __i386__
+ &num_processors,
+#elif defined __sparc__
+ &linux_num_cpus,
+#elif defined __alpha__
+ &smp_num_probed,
+#elif defined __powerpc__
+ &cpu_nr,
+#elif
+#error "smp not supported for this platform"
+#endif /* various platforms */
+#else /* !__SMP__ */
+ &one,
+#endif /* !__SMP__ */
+ sizeof(int), 0444, NULL, &proc_dointvec},
+ {KERN_NPROCESSORS_ONLN, "nprocessors-onln",
+#ifdef __SMP__
+ &smp_num_cpus,
+#else
+ &one,
+#endif
+ sizeof(int), 0444, NULL, &proc_dointvec},
+ {KERN_ASYNCHRONOUS_IO, "asynchronous-io", &not_supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_FSYNC, "fsync", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_MAPPED_FILES, "mapped-files", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_MEMLOCK, "memlock", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_MEMLOCK_RANGE, "memlock-range", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_MEMORY_PROTECTION, "memory-protection", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_MESSAGE_PASSING, "message-passing", &not_supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_PRIORITIZED_IO, "prioritized-io", &not_supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_PRIORITY_SCHEDULING, "priority-scheduling", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_REALTIME_SIGNALS, "realtime-signals", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_SEMAPHORES, "semaphores", &not_supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_SHARED_MEMORY_OBJECTS, "shared-memory-objects", &not_supp,
+ sizeof(int), 0444, NULL, &proc_dointvec},
+ {KERN_SYNCHRONIZED_IO, "synchronized-io", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_TIMERS, "timers", &supp, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_DELAYTIMER_MAX, "delaytimer-max", &delaytimer_max, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_TIMER_MAX, "timer-max", &timer_max, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_IOV_MAX, "iov-max", &iov_max, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+ {KERN_RTSIG_MAX, "rtsig-max", &rtsig_max, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+#ifdef __i386__
+ {KERN_LINUX_COUNTER_HZ, "linux-counter-hz", &cpu_hz, sizeof(int),
+ 0444, NULL, &proc_dointvec},
+#endif
{0}
};

--Boundary-=_nWlrBbmQBhCDarzOwKkYHIDdqSCD--

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