From db8b50ba75f208be80e63366f124f064283f971c Mon Sep 17 00:00:00 2001 From: George Anzinger Date: Mon, 17 Feb 2003 22:41:13 -0800 Subject: [PATCH] POSIX clocks & timers This is version 23 or so of the POSIX timer code. Internal changelog: - Changed the signals code to match the new order of things. Also the new xtime_lock code needed to be picked up. It made some things a lot simpler. - Fixed a spin lock hand off problem in locking timers (thanks to Randy). - Fixed nanosleep to test for out of bound nanoseconds (thanks to Julie). - Fixed a couple of id deallocation bugs that left old ids laying around (hey I get this one). - This version has a new timer id manager. Andrew Morton suggested elimination of recursion (done) and I added code to allow it to release unused nodes. The prior version only released the leaf nodes. (The id manager uses radix tree type nodes.) Also added is a reuse count so ids will not repeat for at least 256 alloc/ free cycles. - The changes for the new sys_call restart now allow one restart function to handle both nanosleep and clock_nanosleep. Saves a bit of code, nice. - All the requested changes and Lindent too :). - I also broke clock_nanosleep() apart much the same way nanosleep() was with the 2.5.50-bk5 changes. TIMER STORMS The POSIX clocks and timers code prevents "timer storms" by not putting repeating timers back in the timer list until the signal is delivered for the prior expiry. Timer events missed by this delay are accounted for in the timer overrun count. The net result is MUCH lower system overhead while presenting the same info to the user as would be the case if an interrupt and timer processing were required for each increment in the overrun count. --- include/linux/idr.h | 63 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/init_task.h | 1 + include/linux/posix-timers.h | 30 +++++++++++++++++++++ include/linux/sched.h | 21 +++++++++++++++ include/linux/signal.h | 2 +- include/linux/sys.h | 3 +-- include/linux/time.h | 35 ++++++++++++++++++++++++ include/linux/types.h | 2 ++ 8 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 include/linux/idr.h create mode 100644 include/linux/posix-timers.h (limited to 'include/linux') diff --git a/include/linux/idr.h b/include/linux/idr.h new file mode 100644 index 000000000000..40861ba1114c --- /dev/null +++ b/include/linux/idr.h @@ -0,0 +1,63 @@ +/* + * 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. + */ +#include +#include + +#define RESERVED_ID_BITS 8 + +#if BITS_PER_LONG == 32 +#define IDR_BITS 5 +#define IDR_FULL 0xffffffff +#elif BITS_PER_LONG == 64 +#define IDR_BITS 6 +#define IDR_FULL 0xffffffffffffffff +#else +#error "BITS_PER_LONG is not 32 or 64" +#endif + +#define IDR_MASK ((1 << IDR_BITS)-1) + +/* Leave the possibility of an incomplete final layer */ +#define MAX_LEVEL (BITS_PER_LONG - RESERVED_ID_BITS + IDR_BITS - 1) / IDR_BITS +#define MAX_ID_SHIFT (BITS_PER_LONG - RESERVED_ID_BITS) +#define MAX_ID_BIT (1 << MAX_ID_SHIFT) +#define MAX_ID_MASK (MAX_ID_BIT - 1) + +/* Number of id_layer structs to leave in free list */ +#define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL + +struct idr_layer { + unsigned long bitmap; // A zero bit means "space here" + int count; // When zero, we can release it + struct idr_layer *ary[1<jiffies = jiffies; +#define posix_time_before(timer, now) \ + time_before((timer)->expires, (now)->jiffies) + +#define posix_bump_timer(timr) do { \ + (timr)->it_timer.expires += (timr)->it_incr; \ + (timr)->it_overrun++; \ + }while (0) +#endif diff --git a/include/linux/sched.h b/include/linux/sched.h index cfa6fd4d86da..ff0fcd301ba1 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -295,6 +295,25 @@ extern struct user_struct root_user; 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_requeue_pending; /* waiting to requeue this timer */ + 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; @@ -358,6 +377,7 @@ struct task_struct { 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; u64 start_time; /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ @@ -597,6 +617,7 @@ extern void exit_signal(struct task_struct *); extern void __exit_signal(struct task_struct *); extern void exit_sighand(struct task_struct *); extern void __exit_sighand(struct task_struct *); +extern void exit_itimers(struct task_struct *); extern NORET_TYPE void do_group_exit(int); diff --git a/include/linux/signal.h b/include/linux/signal.h index 05e1fd671f82..466a7a8ae77a 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -208,7 +208,7 @@ extern int sigprocmask(int, sigset_t *, sigset_t *); struct pt_regs; extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie); #endif - +#define FOLD_NANO_SLEEP_INTO_CLOCK_NANO_SLEEP #endif /* __KERNEL__ */ #endif /* _LINUX_SIGNAL_H */ diff --git a/include/linux/sys.h b/include/linux/sys.h index 95b431dbebff..daa6008bfdc8 100644 --- a/include/linux/sys.h +++ b/include/linux/sys.h @@ -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 --git a/include/linux/time.h b/include/linux/time.h index 7355ae1f78ca..542e00330d22 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -41,6 +41,19 @@ struct timezone { */ #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) { @@ -139,6 +152,8 @@ struct timespec current_kernel_time(void); #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 extern long do_nanosleep(struct timespec *t); extern long do_utimes(char * filename, struct timeval * times); #endif @@ -167,4 +182,24 @@ struct itimerval { 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 --git a/include/linux/types.h b/include/linux/types.h index f1c0ce5eb845..87a71f8f2416 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -27,6 +27,8 @@ typedef __kernel_pid_t pid_t; 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; -- cgit v1.2.3