2 * linux/kernel/itimer.c
4 * Copyright (C) 1992 Darren Senn
7 /* These are all the functions necessary to implement itimers */
10 #include <linux/smp_lock.h>
11 #include <linux/interrupt.h>
13 #include <asm/uaccess.h>
16 * change timeval to jiffies, trying to avoid the
17 * most obvious overflows..
19 * The tv_*sec values are signed, but nothing seems to
20 * indicate whether we really should use them as signed values
21 * when doing itimers. POSIX doesn't mention this (but if
22 * alarm() uses itimers without checking, we have to use unsigned
25 static unsigned long tvtojiffies(struct timeval
*value
)
27 unsigned long sec
= (unsigned) value
->tv_sec
;
28 unsigned long usec
= (unsigned) value
->tv_usec
;
30 if (sec
> (ULONG_MAX
/ HZ
))
32 usec
+= 1000000 / HZ
- 1;
37 static void jiffiestotv(unsigned long jiffies
, struct timeval
*value
)
39 value
->tv_usec
= (jiffies
% HZ
) * (1000000 / HZ
);
40 value
->tv_sec
= jiffies
/ HZ
;
43 int do_getitimer(int which
, struct itimerval
*value
)
45 register unsigned long val
, interval
;
49 interval
= current
->it_real_incr
;
52 if (timer_pending(¤t
->real_timer
)) {
53 val
= current
->real_timer
.expires
- jiffies
;
55 /* look out for negative/zero itimer.. */
62 val
= current
->it_virt_value
;
63 interval
= current
->it_virt_incr
;
66 val
= current
->it_prof_value
;
67 interval
= current
->it_prof_incr
;
72 jiffiestotv(val
, &value
->it_value
);
73 jiffiestotv(interval
, &value
->it_interval
);
77 /* SMP: Only we modify our itimer values. */
78 asmlinkage
int sys_getitimer(int which
, struct itimerval
*value
)
81 struct itimerval get_buffer
;
84 error
= do_getitimer(which
, &get_buffer
);
86 copy_to_user(value
, &get_buffer
, sizeof(get_buffer
)))
92 void it_real_fn(unsigned long __data
)
94 struct task_struct
* p
= (struct task_struct
*) __data
;
95 unsigned long interval
;
97 send_sig(SIGALRM
, p
, 1);
98 interval
= p
->it_real_incr
;
100 if (interval
> (unsigned long) LONG_MAX
)
102 p
->real_timer
.expires
= jiffies
+ interval
;
103 add_timer(&p
->real_timer
);
107 int do_setitimer(int which
, struct itimerval
*value
, struct itimerval
*ovalue
)
109 register unsigned long i
, j
;
112 i
= tvtojiffies(&value
->it_interval
);
113 j
= tvtojiffies(&value
->it_value
);
114 if (ovalue
&& (k
= do_getitimer(which
, ovalue
)) < 0)
119 del_timer(¤t
->real_timer
);
121 current
->it_real_value
= j
;
122 current
->it_real_incr
= i
;
125 if (j
> (unsigned long) LONG_MAX
)
128 current
->real_timer
.expires
= i
;
129 add_timer(¤t
->real_timer
);
134 current
->it_virt_value
= j
;
135 current
->it_virt_incr
= i
;
140 current
->it_prof_value
= j
;
141 current
->it_prof_incr
= i
;
149 /* SMP: Again, only we play with our itimers, and signals are SMP safe
150 * now so that is not an issue at all anymore.
152 asmlinkage
int sys_setitimer(int which
, struct itimerval
*value
,
153 struct itimerval
*ovalue
)
155 struct itimerval set_buffer
, get_buffer
;
159 if(verify_area(VERIFY_READ
, value
, sizeof(*value
)))
161 if(copy_from_user(&set_buffer
, value
, sizeof(set_buffer
)))
164 memset((char *) &set_buffer
, 0, sizeof(set_buffer
));
166 error
= do_setitimer(which
, &set_buffer
, ovalue
? &get_buffer
: 0);
167 if (error
|| !ovalue
)
170 if (copy_to_user(ovalue
, &get_buffer
, sizeof(get_buffer
)))