Use on_each_cpu.
[linux-2.6/linux-mips.git] / kernel / itimer.c
bloba544d4090d36c9061e56e959218c20f5ebd5bef1
1 /*
2 * linux/kernel/itimer.c
4 * Copyright (C) 1992 Darren Senn
5 */
7 /* These are all the functions necessary to implement itimers */
9 #include <linux/mm.h>
10 #include <linux/smp_lock.h>
11 #include <linux/interrupt.h>
13 #include <asm/uaccess.h>
15 int do_getitimer(int which, struct itimerval *value)
17 register unsigned long val, interval;
19 switch (which) {
20 case ITIMER_REAL:
21 interval = current->it_real_incr;
22 val = 0;
23 /*
24 * FIXME! This needs to be atomic, in case the kernel timer happens!
26 if (timer_pending(&current->real_timer)) {
27 val = current->real_timer.expires - jiffies;
29 /* look out for negative/zero itimer.. */
30 if ((long) val <= 0)
31 val = 1;
33 break;
34 case ITIMER_VIRTUAL:
35 val = current->it_virt_value;
36 interval = current->it_virt_incr;
37 break;
38 case ITIMER_PROF:
39 val = current->it_prof_value;
40 interval = current->it_prof_incr;
41 break;
42 default:
43 return(-EINVAL);
45 jiffies_to_timeval(val, &value->it_value);
46 jiffies_to_timeval(interval, &value->it_interval);
47 return 0;
50 /* SMP: Only we modify our itimer values. */
51 asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
53 int error = -EFAULT;
54 struct itimerval get_buffer;
56 if (value) {
57 error = do_getitimer(which, &get_buffer);
58 if (!error &&
59 copy_to_user(value, &get_buffer, sizeof(get_buffer)))
60 error = -EFAULT;
62 return error;
65 void it_real_fn(unsigned long __data)
67 struct task_struct * p = (struct task_struct *) __data;
68 unsigned long interval;
70 send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
71 interval = p->it_real_incr;
72 if (interval) {
73 if (interval > (unsigned long) LONG_MAX)
74 interval = LONG_MAX;
75 p->real_timer.expires = jiffies + interval;
76 add_timer(&p->real_timer);
80 int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
82 register unsigned long i, j;
83 int k;
85 i = timeval_to_jiffies(&value->it_interval);
86 j = timeval_to_jiffies(&value->it_value);
87 if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
88 return k;
89 switch (which) {
90 case ITIMER_REAL:
91 del_timer_sync(&current->real_timer);
92 current->it_real_value = j;
93 current->it_real_incr = i;
94 if (!j)
95 break;
96 if (j > (unsigned long) LONG_MAX)
97 j = LONG_MAX;
98 i = j + jiffies;
99 current->real_timer.expires = i;
100 add_timer(&current->real_timer);
101 break;
102 case ITIMER_VIRTUAL:
103 if (j)
104 j++;
105 current->it_virt_value = j;
106 current->it_virt_incr = i;
107 break;
108 case ITIMER_PROF:
109 if (j)
110 j++;
111 current->it_prof_value = j;
112 current->it_prof_incr = i;
113 break;
114 default:
115 return -EINVAL;
117 return 0;
120 /* SMP: Again, only we play with our itimers, and signals are SMP safe
121 * now so that is not an issue at all anymore.
123 asmlinkage long sys_setitimer(int which,
124 struct itimerval __user *value,
125 struct itimerval __user *ovalue)
127 struct itimerval set_buffer, get_buffer;
128 int error;
130 if (value) {
131 if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
132 return -EFAULT;
133 } else
134 memset((char *) &set_buffer, 0, sizeof(set_buffer));
136 error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
137 if (error || !ovalue)
138 return error;
140 if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
141 return -EFAULT;
142 return 0;