[PATCH 3/3] High-res-timers part 3 (posix to hrposix) take 11

george anzinger (george@mvista.com)
Mon, 04 Nov 2002 13:12:55 -0800


This is a multi-part message in MIME format.
--------------FF1EABB613991E0431D8F3D3
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

This patch adds the two POSIX clocks CLOCK_REALTIME_HR and
CLOCK_MONOTONIC_HR to the posix clocks & timers package. A
small change is made in sched.h and the rest of the patch is
against .../kernel/posix_timers.c.

Concerns and on going work:

The kernel interface to the signal delivery code and it's
need for &regs causes the nanosleep and clock_nanosleep code
to be very messy. The supplied interface works for the x86
platform and provides the hooks for other platforms to
connect (see .../include/asm-i386/signal.h for details), but
a much cleaner solution is desired.

This patch guards against overload by limiting the repeat
interval of timers to a fixed value (currently 0.5 ms). A
suggested change, and one I am working on, is to not put the
timer back in the timer list until the user's signal handler
has completed processing the current expiry. This requires
a call back from the signal completion code, again a
platform dependent thing, BUT it has the advantage of
automatically adjusting the interval to match the hardware,
the system overhead and the current load. In all cases, the
standard says we need to account for the overruns, but by
not getting the timer interrupt code involved in useless
spinning, we just bump the overrun, saving a LOT of
overhead.

This patch fixes the high resolution timer resolution at 1
micro second. Should this number be a CONFIG option?

I think it would be a "good thing"=AE to move the NTP stuff to
the jiffies clock. This would allow the wall clock/ jiffies
clock difference to be a "fixed value" so that code that
needed this would not have to read two clocks. Setting the
wall clock would then just be an adjustment to this "fixed
value". It would also eliminate the problem of asking for a
wall clock offset and getting a jiffies clock offset. This
issue is what causes the current 2.5.44 system to fail the
simple:

time sleep 60

test (any value less than 60 seconds violates the standard
in that it implies a timer expired early).

Patch is against 2.5.45-bk1

These patches as well as the POSIX clocks & timers patch are
available on the project site:
http://sourceforge.net/projects/high-res-timers/

The 3 parts to the high res timers are:
core The core kernel (i.e. platform independent)
changes
i386 The high-res changes for the i386 (x86) platform
*posixhr The changes to the POSIX clocks & timers patch to
use high-res timers

Please apply.
-- =

George Anzinger george@mvista.com
High-res-timers: =

http://sourceforge.net/projects/high-res-timers/
Preemption patch:
http://www.kernel.org/pub/linux/kernel/people/rml
--------------FF1EABB613991E0431D8F3D3
Content-Type: text/plain; charset=us-ascii;
name="hrtimers-posix-2.5.45-bk1-1.0.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="hrtimers-posix-2.5.45-bk1-1.0.patch"

diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.5.45-bk1-kb/arch/i386/kernel/entry.S Mon Nov 4 11:04:13 2002
+++ linux/arch/i386/kernel/entry.S Mon Nov 4 11:08:21 2002
@@ -41,7 +41,6 @@
*/

#include <linux/config.h>
-#include <linux/sys.h>
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
@@ -240,7 +239,7 @@
pushl %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebx)
- cmpl $(NR_syscalls), %eax
+ cmpl $(nr_syscalls), %eax
jae syscall_badsys
# system call tracing in operation
testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebx)
@@ -316,7 +315,7 @@
xorl %edx,%edx
call do_syscall_trace
movl ORIG_EAX(%esp), %eax
- cmpl $(NR_syscalls), %eax
+ cmpl $(nr_syscalls), %eax
jnae syscall_call
jmp syscall_exit

@@ -764,11 +763,18 @@
.long sys_exit_group
.long sys_lookup_dcookie
.long sys_epoll_create
- .long sys_epoll_ctl /* 255 */
+ .long sys_epoll_ctl /* 255 */
.long sys_epoll_wait
.long sys_remap_file_pages
+ .long sys_timer_create
+ .long sys_timer_settime
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun /* 260 */
+ .long sys_timer_delete
+ .long sys_clock_settime
+ .long sys_clock_gettime
+ .long sys_clock_getres
+ .long sys_clock_nanosleep /* 265 */
+

-
- .rept NR_syscalls-(.-sys_call_table)/4
- .long sys_ni_syscall
- .endr
+nr_syscalls=(.-sys_call_table)/4
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- linux-2.5.45-bk1-kb/arch/i386/kernel/time.c Wed Oct 16 00:17:47 2002
+++ linux/arch/i386/kernel/time.c Mon Nov 4 11:04:40 2002
@@ -131,6 +131,7 @@
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
write_unlock_irq(&xtime_lock);
+ clock_was_set();
}

/*
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/arch/i386/kernel/timers/timer_tsc.c linux/arch/i386/kernel/timers/timer_tsc.c
--- linux-2.5.45-bk1-kb/arch/i386/kernel/timers/timer_tsc.c Thu Oct 17 17:16:41 2002
+++ linux/arch/i386/kernel/timers/timer_tsc.c Mon Nov 4 11:04:40 2002
@@ -26,7 +26,7 @@
* Equal to 2^32 * (1 / (clocks per usec) ).
* Initialized in time_init.
*/
-static unsigned long fast_gettimeoffset_quotient;
+unsigned long fast_gettimeoffset_quotient;

static unsigned long get_offset_tsc(void)
{
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/fs/exec.c linux/fs/exec.c
--- linux-2.5.45-bk1-kb/fs/exec.c Mon Nov 4 11:03:20 2002
+++ linux/fs/exec.c Mon Nov 4 11:04:40 2002
@@ -756,6 +756,7 @@

flush_signal_handlers(current);
flush_old_files(current->files);
+ exit_itimers(current);

return 0;

diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/asm-generic/siginfo.h linux/include/asm-generic/siginfo.h
--- linux-2.5.45-bk1-kb/include/asm-generic/siginfo.h Wed Oct 30 22:45:08 2002
+++ linux/include/asm-generic/siginfo.h Mon Nov 4 11:04:40 2002
@@ -43,8 +43,9 @@

/* POSIX.1b timers */
struct {
- unsigned int _timer1;
- unsigned int _timer2;
+ timer_t _tid; /* timer id */
+ int _overrun; /* overrun count */
+ sigval_t _sigval; /* same as below */
} _timer;

/* POSIX.1b signals */
@@ -86,8 +87,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_tid _sifields._timer._tid
+#define si_overrun _sifields._timer._overrun
#define si_status _sifields._sigchld._status
#define si_utime _sifields._sigchld._utime
#define si_stime _sifields._sigchld._stime
@@ -221,6 +222,7 @@
#define SIGEV_SIGNAL 0 /* notify via signal */
#define SIGEV_NONE 1 /* other notification: meaningless */
#define SIGEV_THREAD 2 /* deliver via thread creation */
+#define SIGEV_THREAD_ID 4 /* deliver to thread */

#define SIGEV_MAX_SIZE 64
#ifndef SIGEV_PAD_SIZE
@@ -235,6 +237,7 @@
int sigev_notify;
union {
int _pad[SIGEV_PAD_SIZE];
+ int _tid;

struct {
void (*_function)(sigval_t);
@@ -247,6 +250,7 @@

#define sigev_notify_function _sigev_un._sigev_thread._function
#define sigev_notify_attributes _sigev_un._sigev_thread._attribute
+#define sigev_notify_thread_id _sigev_un._tid

#ifdef __KERNEL__

diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/asm-i386/posix_types.h linux/include/asm-i386/posix_types.h
--- linux-2.5.45-bk1-kb/include/asm-i386/posix_types.h Mon Sep 9 10:35:18 2002
+++ linux/include/asm-i386/posix_types.h Mon Nov 4 11:04:40 2002
@@ -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;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/asm-i386/signal.h linux/include/asm-i386/signal.h
--- linux-2.5.45-bk1-kb/include/asm-i386/signal.h Mon Sep 9 10:35:04 2002
+++ linux/include/asm-i386/signal.h Mon Nov 4 11:04:40 2002
@@ -216,9 +216,83 @@
__asm__("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
return word;
}
+#ifndef _STRUCT_TIMESPEC
+#define _STRUCT_TIMESPEC
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+#endif /* _STRUCT_TIMESPEC */

struct pt_regs;
extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
+/*
+ * These macros are used by nanosleep() and clock_nanosleep().
+ * The issue is that these functions need the *regs pointer which is
+ * passed in different ways by the differing archs.
+
+ * Below we do things in two differing ways. In the long run we would
+ * like to see nano_sleep() go away (glibc should call clock_nanosleep
+ * much as we do). When that happens and the nano_sleep() system
+ * call entry is retired, there will no longer be any real need for
+ * sys_nanosleep() so the FOLD_NANO_SLEEP_INTO_CLOCK_NANO_SLEEP macro
+ * could be undefined, resulting in not needing to stack all the
+ * parms over again, i.e. better (faster AND smaller) code.
+
+ * And while were at it, there needs to be a way to set the return code
+ * on the way to do_signal(). It (i.e. do_signal()) saves the regs on
+ * the callers stack to call the user handler and then the return is
+ * done using those registers. This means that the error code MUST be
+ * set in the register PRIOR to calling do_signal(). See our answer
+ * below...thanks to Jim Houston <jim.houston@attbi.com>
+ */
+#define FOLD_NANO_SLEEP_INTO_CLOCK_NANO_SLEEP
+
+
+#ifdef FOLD_NANO_SLEEP_INTO_CLOCK_NANO_SLEEP
+extern long do_clock_nanosleep(struct pt_regs *regs,
+ clockid_t which_clock,
+ int flags,
+ const struct timespec *rqtp,
+ struct timespec *rmtp);
+
+#define NANOSLEEP_ENTRY(a) \
+ asmlinkage long sys_nanosleep( struct timespec* rqtp, \
+ struct timespec * rmtp) \
+{ struct pt_regs *regs = (struct pt_regs *)&rqtp; \
+ return do_clock_nanosleep(regs, CLOCK_REALTIME, 0, rqtp, rmtp); \
+}
+
+#define CLOCK_NANOSLEEP_ENTRY(a) asmlinkage long sys_clock_nanosleep( \
+ clockid_t which_clock, \
+ int flags, \
+ const struct timespec *rqtp, \
+ struct timespec *rmtp) \
+{ struct pt_regs *regs = (struct pt_regs *)&which_clock; \
+ return do_clock_nanosleep(regs, which_clock, flags, rqtp, rmtp); \
+} \
+long do_clock_nanosleep(struct pt_regs *regs, \
+ clockid_t which_clock, \
+ int flags, \
+ const struct timespec *rqtp, \
+ struct timespec *rmtp) \
+{ a
+
+#else
+#define NANOSLEEP_ENTRY(a) \
+ asmlinkage long sys_nanosleep( struct timespec* rqtp, \
+ struct timespec * rmtp) \
+{ struct pt_regs *regs = (struct pt_regs *)&rqtp; \
+ a
+#define CLOCK_NANOSLEEP_ENTRY(a) asmlinkage long sys_clock_nanosleep( \
+ clockid_t which_clock, \
+ int flags, \
+ const struct timespec *rqtp, \
+ struct timespec *rmtp) \
+{ struct pt_regs *regs = (struct pt_regs *)&which_clock; \
+ a
+#endif
+#define _do_signal() (regs->eax = -EINTR, do_signal(regs, NULL))

#endif /* __KERNEL__ */

diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- linux-2.5.45-bk1-kb/include/asm-i386/unistd.h Mon Nov 4 11:03:23 2002
+++ linux/include/asm-i386/unistd.h Mon Nov 4 11:09:48 2002
@@ -262,6 +262,15 @@
#define __NR_sys_epoll_ctl 255
#define __NR_sys_epoll_wait 256
#define __NR_remap_file_pages 257
+#define __NR_timer_create 258
+#define __NR_timer_settime (__NR_timer_create+1)
+#define __NR_timer_gettime (__NR_timer_create+2)
+#define __NR_timer_getoverrun (__NR_timer_create+3)
+#define __NR_timer_delete (__NR_timer_create+4)
+#define __NR_clock_settime (__NR_timer_create+5)
+#define __NR_clock_gettime (__NR_timer_create+6)
+#define __NR_clock_getres (__NR_timer_create+7)
+#define __NR_clock_nanosleep (__NR_timer_create+8)


/* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/linux/id_reuse.h linux/include/linux/id_reuse.h
--- linux-2.5.45-bk1-kb/include/linux/id_reuse.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/id_reuse.h Mon Nov 4 11:04:40 2002
@@ -0,0 +1,119 @@
+/*
+ * include/linux/id.h
+ *
+ * 2002-10-18 written by Jim Houston jim.houston@ccur.com
+ * Copyright (C) 2002 by Concurrent Computer Corporation
+ * Distributed under the GNU GPL license version 2.
+ *
+ * Small id to pointer translation service avoiding fixed sized
+ * tables.
+ */
+
+#define IDR_BITS 5
+#define IDR_MASK ((1 << IDR_BITS)-1)
+#define IDR_FULL ((int)((1ULL << (1 << IDR_BITS))-1))
+
+/* Number of id_layer structs to leave in free list */
+#define IDR_FREE_MAX 6
+
+struct idr_layer {
+ unsigned long bitmap;
+ struct idr_layer *ary[1<<IDR_BITS];
+};
+
+struct idr {
+ int layers;
+ int last;
+ int count;
+ struct idr_layer *top;
+ spinlock_t id_slock;
+};
+
+void *idr_find(struct idr *idp, int id);
+void *idr_find_nolock(struct idr *idp, int id);
+int idr_get_new(struct idr *idp, void *ptr);
+void idr_remove(struct idr *idp, int id);
+void idr_init(struct idr *idp);
+void idr_lock(struct idr *idp);
+void idr_unlock(struct idr *idp);
+
+extern inline void update_bitmap(struct idr_layer *p, int bit)
+{
+ if (p->ary[bit] && p->ary[bit]->bitmap == IDR_FULL)
+ __set_bit(bit, &p->bitmap);
+ else
+ __clear_bit(bit, &p->bitmap);
+}
+
+extern inline void update_bitmap_set(struct idr_layer *p, int bit)
+{
+ if (p->ary[bit] && p->ary[bit]->bitmap == IDR_FULL)
+ __set_bit(bit, &p->bitmap);
+}
+
+extern inline void update_bitmap_clear(struct idr_layer *p, int bit)
+{
+ if (p->ary[bit] && p->ary[bit]->bitmap == IDR_FULL)
+ ;
+ else
+ __clear_bit(bit, &p->bitmap);
+}
+
+extern inline void idr_lock(struct idr *idp)
+{
+ spin_lock(&idp->id_slock);
+}
+
+extern inline void idr_unlock(struct idr *idp)
+{
+ spin_unlock(&idp->id_slock);
+}
+
+extern inline void *idr_find(struct idr *idp, int id)
+{
+ int n;
+ struct idr_layer *p;
+
+ id--;
+ idr_lock(idp);
+ n = idp->layers * IDR_BITS;
+ p = idp->top;
+ if ((unsigned)id >= (1 << n)) { // unsigned catches <=0 input
+ idr_unlock(idp);
+ return(NULL);
+ }
+
+ while (n > 0 && p) {
+ n -= IDR_BITS;
+ p = p->ary[(id >> n) & IDR_MASK];
+ }
+ idr_unlock(idp);
+ return((void *)p);
+}
+/*
+ * caller calls idr_lock/ unlock around this one. Allows
+ * additional code to be protected.
+ */
+extern inline void *idr_find_nolock(struct idr *idp, int id)
+{
+ int n;
+ struct idr_layer *p;
+
+ id--;
+ n = idp->layers * IDR_BITS;
+ p = idp->top;
+ if ((unsigned)id >= (1 << n)) { // unsigned catches <=0 input
+ return(NULL);
+ }
+
+ while (n > 0 && p) {
+ n -= IDR_BITS;
+ p = p->ary[(id >> n) & IDR_MASK];
+ }
+ return((void *)p);
+}
+
+
+
+extern kmem_cache_t *idr_layer_cache;
+
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/linux/init_task.h linux/include/linux/init_task.h
--- linux-2.5.45-bk1-kb/include/linux/init_task.h Thu Oct 3 10:42:11 2002
+++ linux/include/linux/init_task.h Mon Nov 4 11:04:40 2002
@@ -93,6 +93,7 @@
.sig = &init_signals, \
.pending = { NULL, &tsk.pending.head, {{0}}}, \
.blocked = {{0}}, \
+ .posix_timers = LIST_HEAD_INIT(tsk.posix_timers), \
.alloc_lock = SPIN_LOCK_UNLOCKED, \
.switch_lock = SPIN_LOCK_UNLOCKED, \
.journal_info = NULL, \
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/linux/posix-timers.h linux/include/linux/posix-timers.h
--- linux-2.5.45-bk1-kb/include/linux/posix-timers.h Wed Dec 31 16:00:00 1969
+++ linux/include/linux/posix-timers.h Mon Nov 4 11:04:40 2002
@@ -0,0 +1,18 @@
+#ifndef _linux_POSIX_TIMERS_H
+#define _linux_POSIX_TIMERS_H
+
+struct k_clock {
+ int res; /* in nano seconds */
+ int ( *clock_set)(struct timespec *tp);
+ int ( *clock_get)(struct timespec *tp);
+ int ( *nsleep)( int flags,
+ struct timespec*new_setting,
+ struct itimerspec *old_setting);
+ int ( *timer_set)(struct k_itimer *timr, int flags,
+ struct itimerspec *new_setting,
+ struct itimerspec *old_setting);
+ int ( *timer_del)(struct k_itimer *timr);
+ void ( *timer_get)(struct k_itimer *timr,
+ struct itimerspec *cur_setting);
+};
+#endif
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.5.45-bk1-kb/include/linux/sched.h Mon Nov 4 11:03:23 2002
+++ linux/include/linux/sched.h Mon Nov 4 11:04:40 2002
@@ -269,6 +269,25 @@
typedef struct prio_array prio_array_t;
struct backing_dev_info;

+/* POSIX.1b interval timer structure. */
+struct k_itimer {
+ struct list_head list; /* free/ allocate list */
+ spinlock_t it_lock;
+ clockid_t it_clock; /* which timer type */
+ timer_t it_id; /* timer id */
+ int it_overrun; /* overrun on pending signal */
+ int it_overrun_last; /* overrun on last delivered signal */
+ int it_overrun_deferred; /* overrun on pending timer interrupt */
+ int it_sigev_notify; /* notify word of sigevent struct */
+ int it_sigev_signo; /* signo word of sigevent struct */
+ sigval_t it_sigev_value; /* value word of sigevent struct */
+ unsigned long it_incr; /* interval specified in jiffies */
+ struct task_struct *it_process; /* process to send signal to */
+ struct timer_list it_timer;
+};
+
+
+
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
struct thread_info *thread_info;
@@ -331,6 +350,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 list_head posix_timers; /* POSIX.1b Interval Timers */
unsigned long utime, stime, cutime, cstime;
unsigned long start_time;
long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/linux/signal.h linux/include/linux/signal.h
--- linux-2.5.45-bk1-kb/include/linux/signal.h Mon Sep 9 10:35:04 2002
+++ linux/include/linux/signal.h Mon Nov 4 11:04:40 2002
@@ -224,6 +224,36 @@
struct pt_regs;
extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs);
#endif
+/*
+ * We would like the asm/signal.h code to define these so that the using
+ * function can call do_signal(). In loo of that, we define a genaric
+ * version that pretends that do_signal() was called and delivered a signal.
+ * To see how this is used, see nano_sleep() in timer.c and the i386 version
+ * in asm_i386/signal.h.
+ */
+#ifndef PT_REGS_ENTRY
+#define PT_REGS_ENTRY(type,name,p1_type,p1, p2_type,p2) \
+type name(p1_type p1,p2_type p2)\
+{
+#endif
+#ifndef _do_signal
+#define _do_signal() 1
+#endif
+#ifndef NANOSLEEP_ENTRY
+#define NANOSLEEP_ENTRY(a) asmlinkage long sys_nanosleep( struct timespec* rqtp, \
+ struct timespec * rmtp) \
+{ a
+#endif
+#ifndef CLOCK_NANOSLEEP_ENTRY
+#define CLOCK_NANOSLEEP_ENTRY(a) asmlinkage long sys_clock_nanosleep( \
+ clockid_t which_clock, \
+ int flags, \
+ const struct timespec *rqtp, \
+ struct timespec *rmtp) \
+{ a
+
+#endif
+

#endif /* __KERNEL__ */

diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/linux/sys.h linux/include/linux/sys.h
--- linux-2.5.45-bk1-kb/include/linux/sys.h Wed Oct 30 22:46:36 2002
+++ linux/include/linux/sys.h Mon Nov 4 11:04:40 2002
@@ -2,9 +2,8 @@
#define _LINUX_SYS_H

/*
- * system call entry points ... but not all are defined
+ * This file is no longer used or needed
*/
-#define NR_syscalls 260

/*
* These are system calls that will be removed at some time
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/linux/time.h linux/include/linux/time.h
--- linux-2.5.45-bk1-kb/include/linux/time.h Wed Sep 18 17:04:09 2002
+++ linux/include/linux/time.h Mon Nov 4 11:04:40 2002
@@ -38,6 +38,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)
{
@@ -124,6 +137,8 @@
#ifdef __KERNEL__
extern void do_gettimeofday(struct timeval *tv);
extern void do_settimeofday(struct timeval *tv);
+extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+extern void clock_was_set(void); // call when ever the clock is set
#endif

#define FD_SETSIZE __FD_SETSIZE
@@ -149,5 +164,25 @@
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
+#define CLOCK_MONOTONIC 1
+#define CLOCK_PROCESS_CPUTIME_ID 2
+#define CLOCK_THREAD_CPUTIME_ID 3
+#define CLOCK_REALTIME_HR 4
+#define CLOCK_MONOTONIC_HR 5
+
+#define MAX_CLOCKS 6
+
+/*
+ * The various flags for setting POSIX.1b interval timers.
+ */
+
+#define TIMER_ABSTIME 0x01
+

#endif
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/include/linux/types.h linux/include/linux/types.h
--- linux-2.5.45-bk1-kb/include/linux/types.h Tue Oct 15 15:43:06 2002
+++ linux/include/linux/types.h Mon Nov 4 11:04:40 2002
@@ -23,6 +23,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;
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/kernel/Makefile linux/kernel/Makefile
--- linux-2.5.45-bk1-kb/kernel/Makefile Wed Oct 16 00:18:18 2002
+++ linux/kernel/Makefile Mon Nov 4 11:04:40 2002
@@ -10,7 +10,7 @@
module.o exit.o itimer.o time.o softirq.o resource.o \
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o \
- rcupdate.o
+ rcupdate.o posix-timers.o id_reuse.o

obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
obj-$(CONFIG_SMP) += cpu.o
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/kernel/exit.c linux/kernel/exit.c
--- linux-2.5.45-bk1-kb/kernel/exit.c Wed Oct 16 00:18:18 2002
+++ linux/kernel/exit.c Mon Nov 4 11:04:40 2002
@@ -410,6 +410,7 @@
mmdrop(active_mm);
}

+
/*
* Turn us into a lazy TLB process if we
* aren't already..
@@ -647,6 +648,7 @@
__exit_files(tsk);
__exit_fs(tsk);
exit_namespace(tsk);
+ exit_itimers(tsk);
exit_thread();

if (current->leader)
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/kernel/fork.c linux/kernel/fork.c
--- linux-2.5.45-bk1-kb/kernel/fork.c Mon Nov 4 11:03:23 2002
+++ linux/kernel/fork.c Mon Nov 4 11:04:40 2002
@@ -784,6 +784,7 @@
goto bad_fork_cleanup_files;
if (copy_sighand(clone_flags, p))
goto bad_fork_cleanup_fs;
+ INIT_LIST_HEAD(&p->posix_timers);
if (copy_mm(clone_flags, p))
goto bad_fork_cleanup_sighand;
if (copy_namespace(clone_flags, p))
diff -urP -I \$Id:.*Exp \$ -X /usr/src/patch.exclude linux-2.5.45-bk1-kb/kernel/id_reuse.c linux/kernel/id_reuse.c
--- linux-2.5.45-bk1-kb/kernel/id_reuse.c Wed Dec 31 16:00:00 1969
+++ linux/kernel/id_reuse.c Mon Nov 4 11:04:40 2002
@@ -0,0 +1,198 @@
+/*
+ * linux/kernel/id.c
+ *
+ * 2002-10-18 written by Jim Houston jim.houston@ccur.com
+ * Copyright (C) 2002 by Concurrent Computer Corporation
+ * Distributed under the GNU GPL license version 2.
+ *
+ * Small id to pointer translation service.
+ *
+ * It uses a radix tree like structure as a sparse array indexed
+ * by the id to obtain the pointer. The bitmap makes allocating
+ * an new id quick.
+
+ * Modified by George Anzinger to reuse immediately and to use
+ * find bit instructions. Also removed _irq on spinlocks.
+ */
+
+
+#include <linux/slab.h>
+#include <linux/id_reuse.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+static kmem_cache_t *idr_layer_cache;
+
+/*
+ * Since we can't allocate memory with spinlock held and dropping the
+ * lock to allocate gets ugly keep a free list which will satisfy the
+ * worst case allocation.
+
+ * Hm? Looks like the free list is shared with all users... I guess
+ * that is ok, think of it as an extension of alloc.
+ */
+
+static struct idr_layer *id_free;
+static int id_free_cnt;
+
+static inline struct idr_layer *alloc_layer(void)
+{
+ struct idr_layer *p;
+
+ if (!(p = id_free))
+ BUG();
+ id_free = p->ary[0];
+ id_free_cnt--;
+ p->ary[0] = 0;
+ return(p);
+}
+
+static inline void free_layer(struct idr_layer *p)
+{
+ /*
+ * Depends on the return element being zeroed.
+ */
+ p->ary[0] = id_free;
+ id_free = p;
+ id_free_cnt++;
+}
+
+static int sub_alloc(struct idr_layer *p, int shift, void *ptr)
+{
+ int bitmap = p->bitmap;
+ int v, n;
+
+ n = ffz(bitmap);
+ if (shift == 0) {
+ p->ary[n] = (struct idr_layer *)ptr;
+ __set_bit(n, &p->bitmap);
+ return(n);
+ }
+ if (!p->ary[n])
+ p->ary[n] = alloc_layer();
+ v = sub_alloc(p->ary[n], shift-IDR_BITS, ptr);
+ update_bitmap_set(p, n);
+ return(v + (n << shift));
+}
+
+int idr_get_new(struct idr *idp, void *ptr)
+{
+ int n, v;
+
+ idr_lock(idp);
+ n = idp->layers * IDR_BITS;
+ /*
+ * Since we can't allocate memory with spinlock held and dropping the
+ * lock to allocate gets ugly keep a free list which will satisfy the
+ * worst case allocation.
+ */
+ while (id_free_cnt < n+1) {
+ struct idr_layer *new;
+ idr_unlock(idp);
+ new = kmem_cache_alloc(idr_layer_cache, GFP_KERNEL);
+ if(new == NULL)
+ return (0);
+ memset(new, 0, sizeof(struct idr_layer));
+ idr_lock(idp);
+ free_layer(new);
+ }
+ /*
+ * Add a new layer if the array is full
+ */
+ if (idp->top->bitmap == IDR_FULL){
+ struct idr_layer *new = alloc_layer();
+ ++idp->layers;
+ n += IDR_BITS;
+ new->ary[0] = idp->top;
+ idp->top = new;
+ update_bitmap_set(new, 0);
+ }
+ v = sub_alloc(idp->top, n-IDR_BITS, ptr);
+ idp->last = v;
+ idp->count++;
+ idr_unlock(idp);
+ return(v+1);
+}
+/*
+ * At this time we only free leaf nodes. It would take another bitmap
+ * or, better, an in use counter to correctly free higher nodes.
+ */
+
+static int sub_remove(struct idr_layer *p, int shift, int id)
+{
+ int n = (id >> shift) & IDR_MASK;
+
+if (!p) {
+printk("in sub_remove for id=%d called with null pointer.\n", id);
+return(0);
+}
+ if (shift != 0) {
+ if (sub_remove(p->ary[n], shift-IDR_BITS, id)) {
+ free_layer(p->ary[n]);
+ p->ary[n] = NULL;
+ }
+ __clear_bit(n, &p->bitmap);
+ return (0); // for now, prune only at 0
+ } else {
+ p->ary[n] = NULL;
+ __clear_bit(n, &p->bitmap);
+ }
+ return (! p->bitmap);
+}
+
+void