POSIX clocks & timers
Subsystems (6)
PATCH 1/1 POSIX clocks & timers
Oops! Wrong patch. Attached is the correct one.
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 defines a timer as a system wide resource with system wide limits on the number of allocated timers. This number can be set at configure time and is defaulted to 3000. There
are NO other limits on how many timers a process can have.
Kernel version 2.5.42-bk2
Test programs, man pages and readme files 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 +9 -0
@@ -760,6 +760,15 @@ .long sys_alloc_hugepages /* 250 */ .long sys_free_hugepages .long sys_exit_group + .long sys_timer_create + .long sys_timer_settime + .long sys_timer_gettime /* 255 */ + .long sys_timer_getoverrun + .long sys_timer_delete + .long sys_clock_settime + .long sys_clock_gettime + .long sys_clock_getres /* 260 */ + .long sys_clock_nanosleep .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall
arch/i386/kernel/time.c +1 -0
@@ -136,6 +136,7 @@ time_maxerror =NTP_PHASE_LIMIT ; time_esterror =NTP_PHASE_LIMIT ;write_unlock_irq (&xtime_lock); +clock_was_set (); }/*
Binary files linux-2.5.42-bk2-kb/core and linux/core differ
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
@@ -31,8 +31,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 */
@@ -71,8 +72,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
@@ -203,6 +204,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
@@ -217,6 +219,7 @@int sigev_notify;union {int _pad[SIGEV_PAD_SIZE ]; +int _tid;struct {void (*_function)(sigval_t );
@@ -229,6 +232,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 +67 -0
73 lines not on this page · raw message
include/asm-i386/unistd.h +9 -0
@@ -257,6 +257,15 @@#define __NR_alloc_hugepages 250#define __NR_free_hugepages 251#define __NR_exit_group 252 +#define __NR_timer_create 253 +#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/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 +26 -0
@@ -278,6 +278,30 @@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 */ +#ifdef CONFIG_HIGH_RES_TIMERS +int it_sub_incr;/* sub jiffie part of interval */ +#endif +struct task_struct *it_process;/* process to send signal to */ +struct timer_list it_timer; +}; + + +//extern struct itimer_struct *itimer_struct_new(void); +extern void itimer_delete (struct k_itimer *timers); +struct task_struct {volatile long state;/* -1 unrunnable, 0 runnable, >0 stopped */ struct thread_info *thread_info;
@@ -343,6 +367,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 ];
@@ -651,6 +676,7 @@extern void exit_mm (struct task_struct *);extern void exit_files (struct task_struct *); +extern void exit_itimers (struct task_struct *);extern void exit_sighand (struct task_struct *);extern void __exit_sighand (struct task_struct *);
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 ;
init/Config.help +8 -0
@@ -115,3 +115,11 @@ replacement for kerneld.) Say Y here and read about configuring it in <file:Documentation/kmod.txt>. +Maximum number of POSIX timers +CONFIG_MAX_POSIX_TIMERS + This option allows you to configure the system wide maximum number of + POSIX timers. Timers are allocated as needed so the only memory + overhead this adds is about 4 bytes for every 50 or so timers to keep + track of each block of timers. The system quietly rounds this number + up to fill out a timer allocation block. It is ok to have several + thousand timers as needed by your applications.
init/Config.in +1 -0
@@ -9,6 +9,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL +int 'System wide maximum number of POSIX timers' CONFIG_MAX_POSIX_TIMERS 3000 endmenu mainmenu_option next_comment
kernel/Makefile +2 -1
@@ -8,7 +8,8 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ 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 + signal.o sys.o kmod.o workqueue.o futex.o platform.o pid.o \ + posix-timers.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += cpu.o
kernel/exit.c +16 -0
@@ -408,6 +408,21 @@mmdrop (active_mm); } +static inline void __exit_itimers (struct task_struct *tsk) +{ +struct k_itimer *tmr; + +while (tsk->posix_timers.next != &tsk->posix_timers){ + tmr = list_entry(tsk->posix_timers.next,struct k_itimer,list); +itimer_delete (tmr); + } +} + +void exit_itimers (struct task_struct *tsk) +{ +__exit_itimers (tsk); +} +/* * Turn us into a lazy TLB process if we * aren't already..
@@ -643,6 +658,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/posix-timers.c +1288 -0
1,288 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
Binary files linux-2.5.42-bk2-kb/scripts/fixdep and linux/scripts/fixdep differ