1
2
3
4
5
6
7
8
9#include <linux/mm.h>
10#include <linux/smp_lock.h>
11#include <linux/interrupt.h>
12
13#include <asm/uaccess.h>
14
15int do_getitimer(int which, struct itimerval *value)
16{
17 register unsigned long val, interval;
18
19 switch (which) {
20 case ITIMER_REAL:
21 interval = current->it_real_incr;
22 val = 0;
23
24
25
26 if (timer_pending(¤t->real_timer)) {
27 val = current->real_timer.expires - jiffies;
28
29
30 if ((long) val <= 0)
31 val = 1;
32 }
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);
44 }
45 jiffies_to_timeval(val, &value->it_value);
46 jiffies_to_timeval(interval, &value->it_interval);
47 return 0;
48}
49
50
51asmlinkage long sys_getitimer(int which, struct itimerval *value)
52{
53 int error = -EFAULT;
54 struct itimerval get_buffer;
55
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;
61 }
62 return error;
63}
64
65void it_real_fn(unsigned long __data)
66{
67 struct task_struct * p = (struct task_struct *) __data;
68 unsigned long interval;
69
70 send_sig(SIGALRM, p, 1);
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);
77 }
78}
79
80int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
81{
82 register unsigned long i, j;
83 int k;
84
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(¤t->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(¤t->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;
116 }
117 return 0;
118}
119
120
121
122
123asmlinkage long sys_setitimer(int which, struct itimerval *value,
124 struct itimerval *ovalue)
125{
126 struct itimerval set_buffer, get_buffer;
127 int error;
128
129 if (value) {
130 if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
131 return -EFAULT;
132 } else
133 memset((char *) &set_buffer, 0, sizeof(set_buffer));
134
135 error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
136 if (error || !ovalue)
137 return error;
138
139 if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
140 return -EFAULT;
141 return 0;
142}
143