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>
12 #include <linux/syscalls.h>
13 #include <linux/time.h>
14 #include <linux/posix-timers.h>
16 #include <asm/uaccess.h>
18 static unsigned long it_real_value(struct signal_struct
*sig
)
20 unsigned long val
= 0;
21 if (timer_pending(&sig
->real_timer
)) {
22 val
= sig
->real_timer
.expires
- jiffies
;
24 /* look out for negative/zero itimer.. */
31 int do_getitimer(int which
, struct itimerval
*value
)
33 struct task_struct
*tsk
= current
;
34 unsigned long interval
, val
;
35 cputime_t cinterval
, cval
;
39 spin_lock_irq(&tsk
->sighand
->siglock
);
40 interval
= tsk
->signal
->it_real_incr
;
41 val
= it_real_value(tsk
->signal
);
42 spin_unlock_irq(&tsk
->sighand
->siglock
);
43 jiffies_to_timeval(val
, &value
->it_value
);
44 jiffies_to_timeval(interval
, &value
->it_interval
);
47 read_lock(&tasklist_lock
);
48 spin_lock_irq(&tsk
->sighand
->siglock
);
49 cval
= tsk
->signal
->it_virt_expires
;
50 cinterval
= tsk
->signal
->it_virt_incr
;
51 if (!cputime_eq(cval
, cputime_zero
)) {
52 struct task_struct
*t
= tsk
;
53 cputime_t utime
= tsk
->signal
->utime
;
55 utime
= cputime_add(utime
, t
->utime
);
58 if (cputime_le(cval
, utime
)) { /* about to fire */
59 cval
= jiffies_to_cputime(1);
61 cval
= cputime_sub(cval
, utime
);
64 spin_unlock_irq(&tsk
->sighand
->siglock
);
65 read_unlock(&tasklist_lock
);
66 cputime_to_timeval(cval
, &value
->it_value
);
67 cputime_to_timeval(cinterval
, &value
->it_interval
);
70 read_lock(&tasklist_lock
);
71 spin_lock_irq(&tsk
->sighand
->siglock
);
72 cval
= tsk
->signal
->it_prof_expires
;
73 cinterval
= tsk
->signal
->it_prof_incr
;
74 if (!cputime_eq(cval
, cputime_zero
)) {
75 struct task_struct
*t
= tsk
;
76 cputime_t ptime
= cputime_add(tsk
->signal
->utime
,
79 ptime
= cputime_add(ptime
,
84 if (cputime_le(cval
, ptime
)) { /* about to fire */
85 cval
= jiffies_to_cputime(1);
87 cval
= cputime_sub(cval
, ptime
);
90 spin_unlock_irq(&tsk
->sighand
->siglock
);
91 read_unlock(&tasklist_lock
);
92 cputime_to_timeval(cval
, &value
->it_value
);
93 cputime_to_timeval(cinterval
, &value
->it_interval
);
101 asmlinkage
long sys_getitimer(int which
, struct itimerval __user
*value
)
104 struct itimerval get_buffer
;
107 error
= do_getitimer(which
, &get_buffer
);
109 copy_to_user(value
, &get_buffer
, sizeof(get_buffer
)))
116 void it_real_fn(unsigned long __data
)
118 struct task_struct
* p
= (struct task_struct
*) __data
;
119 unsigned long inc
= p
->signal
->it_real_incr
;
121 send_group_sig_info(SIGALRM
, SEND_SIG_PRIV
, p
);
124 * Now restart the timer if necessary. We don't need any locking
125 * here because do_setitimer makes sure we have finished running
126 * before it touches anything.
127 * Note, we KNOW we are (or should be) at a jiffie edge here so
128 * we don't need the +1 stuff. Also, we want to use the prior
129 * expire value so as to not "slip" a jiffie if we are late.
130 * Deal with requesting a time prior to "now" here rather than
135 while (time_before_eq(p
->signal
->real_timer
.expires
, jiffies
))
136 p
->signal
->real_timer
.expires
+= inc
;
137 add_timer(&p
->signal
->real_timer
);
140 int do_setitimer(int which
, struct itimerval
*value
, struct itimerval
*ovalue
)
142 struct task_struct
*tsk
= current
;
143 unsigned long val
, interval
, expires
;
144 cputime_t cval
, cinterval
, nval
, ninterval
;
149 spin_lock_irq(&tsk
->sighand
->siglock
);
150 interval
= tsk
->signal
->it_real_incr
;
151 val
= it_real_value(tsk
->signal
);
152 /* We are sharing ->siglock with it_real_fn() */
153 if (try_to_del_timer_sync(&tsk
->signal
->real_timer
) < 0) {
154 spin_unlock_irq(&tsk
->sighand
->siglock
);
157 tsk
->signal
->it_real_incr
=
158 timeval_to_jiffies(&value
->it_interval
);
159 expires
= timeval_to_jiffies(&value
->it_value
);
161 mod_timer(&tsk
->signal
->real_timer
,
162 jiffies
+ 1 + expires
);
163 spin_unlock_irq(&tsk
->sighand
->siglock
);
165 jiffies_to_timeval(val
, &ovalue
->it_value
);
166 jiffies_to_timeval(interval
,
167 &ovalue
->it_interval
);
171 nval
= timeval_to_cputime(&value
->it_value
);
172 ninterval
= timeval_to_cputime(&value
->it_interval
);
173 read_lock(&tasklist_lock
);
174 spin_lock_irq(&tsk
->sighand
->siglock
);
175 cval
= tsk
->signal
->it_virt_expires
;
176 cinterval
= tsk
->signal
->it_virt_incr
;
177 if (!cputime_eq(cval
, cputime_zero
) ||
178 !cputime_eq(nval
, cputime_zero
)) {
179 if (cputime_gt(nval
, cputime_zero
))
180 nval
= cputime_add(nval
,
181 jiffies_to_cputime(1));
182 set_process_cpu_timer(tsk
, CPUCLOCK_VIRT
,
185 tsk
->signal
->it_virt_expires
= nval
;
186 tsk
->signal
->it_virt_incr
= ninterval
;
187 spin_unlock_irq(&tsk
->sighand
->siglock
);
188 read_unlock(&tasklist_lock
);
190 cputime_to_timeval(cval
, &ovalue
->it_value
);
191 cputime_to_timeval(cinterval
, &ovalue
->it_interval
);
195 nval
= timeval_to_cputime(&value
->it_value
);
196 ninterval
= timeval_to_cputime(&value
->it_interval
);
197 read_lock(&tasklist_lock
);
198 spin_lock_irq(&tsk
->sighand
->siglock
);
199 cval
= tsk
->signal
->it_prof_expires
;
200 cinterval
= tsk
->signal
->it_prof_incr
;
201 if (!cputime_eq(cval
, cputime_zero
) ||
202 !cputime_eq(nval
, cputime_zero
)) {
203 if (cputime_gt(nval
, cputime_zero
))
204 nval
= cputime_add(nval
,
205 jiffies_to_cputime(1));
206 set_process_cpu_timer(tsk
, CPUCLOCK_PROF
,
209 tsk
->signal
->it_prof_expires
= nval
;
210 tsk
->signal
->it_prof_incr
= ninterval
;
211 spin_unlock_irq(&tsk
->sighand
->siglock
);
212 read_unlock(&tasklist_lock
);
214 cputime_to_timeval(cval
, &ovalue
->it_value
);
215 cputime_to_timeval(cinterval
, &ovalue
->it_interval
);
224 asmlinkage
long sys_setitimer(int which
,
225 struct itimerval __user
*value
,
226 struct itimerval __user
*ovalue
)
228 struct itimerval set_buffer
, get_buffer
;
232 if(copy_from_user(&set_buffer
, value
, sizeof(set_buffer
)))
235 memset((char *) &set_buffer
, 0, sizeof(set_buffer
));
237 error
= do_setitimer(which
, &set_buffer
, ovalue
? &get_buffer
: NULL
);
238 if (error
|| !ovalue
)
241 if (copy_to_user(ovalue
, &get_buffer
, sizeof(get_buffer
)))