POSIX clocks & timers take 4 (NOT HIGH RES)
Subsystems (7)
PATCH 1/1 POSIX clocks & timers take 4 (NOT HIGH RES)
This, patch implements the POSIX clocks and timers functions. The two standard clocks are defined(CLOCK_REALTIME & CLOCK_MONOTONIC).
With this version, nano_sleep() is rolled into clock_nanosleep(). Also a bug fix in clock_nanosleep().
kernel/timer.c is modified to remove the timer_t typedef which conflicts with the POSIX standard definition for this type.
The patch introduces a new kernel source (posix-timers.c) which contains most of the code.
This implementation NOW removes all limits on the number of timers in the system or per process or task, thanks to Jim Houston.
Kernel version 2.5.44
To follow are the core and i386 high res patches and a patch to convert this code to use high-res.
Test programs, man pages and readme files as well as this patch are available on the sourceforge high-res-timers site:
http://sourceforge.net/projects/high-res-timers/
Signature · 5 lines
George Anzinger [email protected] High-res-timers: http://sourceforge.net/projects/high-res-timers/ Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml
arch/i386/kernel/entry.S +16 -7
@@ -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)
@@ -314,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
@@ -761,7 +762,17 @@ .long sys_free_hugepages .long sys_exit_group .long sys_lookup_dcookie - - .rept NR_syscalls-(.-sys_call_table)/4 - .long sys_ni_syscall - .endr + .long sys_timer_create + .long sys_timer_settime /* 255 */ + .long sys_timer_gettime + .long sys_timer_getoverrun + .long sys_timer_delete + .long sys_clock_settime + .long sys_clock_gettime /* 260 */ + .long sys_clock_getres + .long sys_clock_nanosleep + +nr_syscalls=(.-sys_call_table)/4 +# .rept NR_syscalls-(.-sys_call_table)/4 +# .long sys_ni_syscall +# .endr
arch/i386/kernel/time.c +1 -0
@@ -131,6 +131,7 @@ time_maxerror =NTP_PHASE_LIMIT ; time_esterror =NTP_PHASE_LIMIT ;write_unlock_irq (&xtime_lock); +clock_was_set (); }/*
arch/i386/kernel/timers/timer_tsc.c +1 -1
@@ -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 ) {
drivers/pnp/Config.in +1 -1
@@ -4,7 +4,7 @@ mainmenu_option next_comment comment 'Plug and Play configuration' -dep_bool 'Plug and Play support' CONFIG_PNP +bool 'Plug and Play support' CONFIG_PNP dep_bool ' Plug and Play device name database' CONFIG_PNP_NAMES $CONFIG_PNP dep_bool ' PnP Debug Messages' CONFIG_PNP_DEBUG $CONFIG_PNP
fs/exec.c +1 -0
@@ -756,6 +756,7 @@flush_signal_handlers (current);flush_old_files (current->files); +exit_itimers (current);return 0 ;
include/asm-generic/siginfo.h +8 -4
@@ -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__
include/asm-i386/posix_types.h +2 -0
@@ -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 ;
include/asm-i386/signal.h +74 -0
83 lines not on this page · raw message
include/asm-i386/unistd.h +9 -0
@@ -258,6 +258,15 @@#define __NR_free_hugepages 251#define __NR_exit_group 252#define __NR_lookup_dcookie 253 +#define __NR_timer_create 254 +#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> */
include/linux/id_reuse.h +119 -0
119 lines not on this page · raw message
include/linux/init_task.h +1 -0
@@ -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, \
include/linux/posix-timers.h +18 -0
@@ -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
include/linux/sched.h +21 -0
@@ -268,6 +268,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;
@@ -333,6 +352,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 ];
@@ -639,6 +659,7 @@extern void exit_files (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 void reparent_to_init (void );extern void daemonize (void );
include/linux/signal.h +30 -0
@@ -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__ */
include/linux/sys.h +1 -1
@@ -4,7 +4,7 @@/* * system call entry points ... but not all are defined */ -#define NR_syscalls 256 +//#define NR_syscalls 275 /* * These are system calls that will be removed at some time
include/linux/time.h +35 -0
@@ -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
include/linux/types.h +2 -0
@@ -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 ;
kernel/Makefile +1 -1
@@ -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
kernel/exit.c +2 -0
@@ -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)
kernel/fork.c +1 -0
@@ -783,6 +783,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))
kernel/id_reuse.c +198 -0
198 lines not on this page · raw message
kernel/posix-timers.c +1151 -0
1,151 lines not on this page · raw message
kernel/signal.c +35 -12
77 lines not on this page · raw message
kernel/timer.c +39 -15
139 lines not on this page · raw message