1
2
3
4
5
6
7
8
9#include <linux/signal.h>
10#include <linux/sched.h>
11#include <linux/string.h>
12#include <linux/errno.h>
13#include <linux/time.h>
14#include <linux/mm.h>
15
16#include <asm/segment.h>
17
18static unsigned long tvtojiffies(struct timeval *value)
19{
20 return((unsigned long )value->tv_sec * HZ +
21 (unsigned long )(value->tv_usec + (1000000 / HZ - 1)) /
22 (1000000 / HZ));
23}
24
25static void jiffiestotv(unsigned long jiffies, struct timeval *value)
26{
27 value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
28 value->tv_sec = jiffies / HZ;
29 return;
30}
31
32int _getitimer(int which, struct itimerval *value)
33{
34 register unsigned long val, interval;
35
36 switch (which) {
37 case ITIMER_REAL:
38 val = current->it_real_value;
39 interval = current->it_real_incr;
40 break;
41 case ITIMER_VIRTUAL:
42 val = current->it_virt_value;
43 interval = current->it_virt_incr;
44 break;
45 case ITIMER_PROF:
46 val = current->it_prof_value;
47 interval = current->it_prof_incr;
48 break;
49 default:
50 return(-EINVAL);
51 }
52 jiffiestotv(val, &value->it_value);
53 jiffiestotv(interval, &value->it_interval);
54 return(0);
55}
56
57asmlinkage int sys_getitimer(int which, struct itimerval *value)
58{
59 int error;
60 struct itimerval get_buffer;
61
62 if (!value)
63 return -EFAULT;
64 error = _getitimer(which, &get_buffer);
65 if (error)
66 return error;
67 error = verify_area(VERIFY_WRITE, value, sizeof(struct itimerval));
68 if (error)
69 return error;
70 memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
71 return 0;
72}
73
74int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
75{
76 register unsigned long i, j;
77 int k;
78
79 i = tvtojiffies(&value->it_interval);
80 j = tvtojiffies(&value->it_value);
81 if (ovalue && (k = _getitimer(which, ovalue)) < 0)
82 return k;
83 switch (which) {
84 case ITIMER_REAL:
85 if (j) {
86 j += 1+itimer_ticks;
87 if (j < itimer_next)
88 itimer_next = j;
89 }
90 current->it_real_value = j;
91 current->it_real_incr = i;
92 break;
93 case ITIMER_VIRTUAL:
94 if (j)
95 j++;
96 current->it_virt_value = j;
97 current->it_virt_incr = i;
98 break;
99 case ITIMER_PROF:
100 if (j)
101 j++;
102 current->it_prof_value = j;
103 current->it_prof_incr = i;
104 break;
105 default:
106 return -EINVAL;
107 }
108 return 0;
109}
110
111asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
112{
113 int error;
114 struct itimerval set_buffer, get_buffer;
115
116 if (value) {
117 error = verify_area(VERIFY_READ, value, sizeof(*value));
118 if (error)
119 return error;
120 memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
121 } else
122 memset((char *) &set_buffer, 0, sizeof(set_buffer));
123
124 if (ovalue) {
125 error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
126 if (error)
127 return error;
128 }
129
130 error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
131 if (error || !ovalue)
132 return error;
133
134 memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
135 return error;
136}
137