OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [kernel/] [itimer.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * linux/kernel/itimer.c
3
 *
4
 * Copyright (C) 1992 Darren Senn
5
 */
6
 
7
/* These are all the functions necessary to implement itimers */
8
 
9
#include <linux/mm.h>
10
#include <linux/interrupt.h>
11
#include <linux/syscalls.h>
12
#include <linux/time.h>
13
#include <linux/posix-timers.h>
14
#include <linux/hrtimer.h>
15
 
16
#include <asm/uaccess.h>
17
 
18
/**
19
 * itimer_get_remtime - get remaining time for the timer
20
 *
21
 * @timer: the timer to read
22
 *
23
 * Returns the delta between the expiry time and now, which can be
24
 * less than zero or 1usec for an pending expired timer
25
 */
26
static struct timeval itimer_get_remtime(struct hrtimer *timer)
27
{
28
        ktime_t rem = hrtimer_get_remaining(timer);
29
 
30
        /*
31
         * Racy but safe: if the itimer expires after the above
32
         * hrtimer_get_remtime() call but before this condition
33
         * then we return 0 - which is correct.
34
         */
35
        if (hrtimer_active(timer)) {
36
                if (rem.tv64 <= 0)
37
                        rem.tv64 = NSEC_PER_USEC;
38
        } else
39
                rem.tv64 = 0;
40
 
41
        return ktime_to_timeval(rem);
42
}
43
 
44
int do_getitimer(int which, struct itimerval *value)
45
{
46
        struct task_struct *tsk = current;
47
        cputime_t cinterval, cval;
48
 
49
        switch (which) {
50
        case ITIMER_REAL:
51
                spin_lock_irq(&tsk->sighand->siglock);
52
                value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
53
                value->it_interval =
54
                        ktime_to_timeval(tsk->signal->it_real_incr);
55
                spin_unlock_irq(&tsk->sighand->siglock);
56
                break;
57
        case ITIMER_VIRTUAL:
58
                read_lock(&tasklist_lock);
59
                spin_lock_irq(&tsk->sighand->siglock);
60
                cval = tsk->signal->it_virt_expires;
61
                cinterval = tsk->signal->it_virt_incr;
62
                if (!cputime_eq(cval, cputime_zero)) {
63
                        struct task_struct *t = tsk;
64
                        cputime_t utime = tsk->signal->utime;
65
                        do {
66
                                utime = cputime_add(utime, t->utime);
67
                                t = next_thread(t);
68
                        } while (t != tsk);
69
                        if (cputime_le(cval, utime)) { /* about to fire */
70
                                cval = jiffies_to_cputime(1);
71
                        } else {
72
                                cval = cputime_sub(cval, utime);
73
                        }
74
                }
75
                spin_unlock_irq(&tsk->sighand->siglock);
76
                read_unlock(&tasklist_lock);
77
                cputime_to_timeval(cval, &value->it_value);
78
                cputime_to_timeval(cinterval, &value->it_interval);
79
                break;
80
        case ITIMER_PROF:
81
                read_lock(&tasklist_lock);
82
                spin_lock_irq(&tsk->sighand->siglock);
83
                cval = tsk->signal->it_prof_expires;
84
                cinterval = tsk->signal->it_prof_incr;
85
                if (!cputime_eq(cval, cputime_zero)) {
86
                        struct task_struct *t = tsk;
87
                        cputime_t ptime = cputime_add(tsk->signal->utime,
88
                                                      tsk->signal->stime);
89
                        do {
90
                                ptime = cputime_add(ptime,
91
                                                    cputime_add(t->utime,
92
                                                                t->stime));
93
                                t = next_thread(t);
94
                        } while (t != tsk);
95
                        if (cputime_le(cval, ptime)) { /* about to fire */
96
                                cval = jiffies_to_cputime(1);
97
                        } else {
98
                                cval = cputime_sub(cval, ptime);
99
                        }
100
                }
101
                spin_unlock_irq(&tsk->sighand->siglock);
102
                read_unlock(&tasklist_lock);
103
                cputime_to_timeval(cval, &value->it_value);
104
                cputime_to_timeval(cinterval, &value->it_interval);
105
                break;
106
        default:
107
                return(-EINVAL);
108
        }
109
        return 0;
110
}
111
 
112
asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
113
{
114
        int error = -EFAULT;
115
        struct itimerval get_buffer;
116
 
117
        if (value) {
118
                error = do_getitimer(which, &get_buffer);
119
                if (!error &&
120
                    copy_to_user(value, &get_buffer, sizeof(get_buffer)))
121
                        error = -EFAULT;
122
        }
123
        return error;
124
}
125
 
126
 
127
/*
128
 * The timer is automagically restarted, when interval != 0
129
 */
130
enum hrtimer_restart it_real_fn(struct hrtimer *timer)
131
{
132
        struct signal_struct *sig =
133
                container_of(timer, struct signal_struct, real_timer);
134
 
135
        send_group_sig_info(SIGALRM, SEND_SIG_PRIV, sig->tsk);
136
 
137
        return HRTIMER_NORESTART;
138
}
139
 
140
/*
141
 * Returns true if the timeval is in canonical form
142
 */
143
#define timeval_valid(t) \
144
        (((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC))
145
 
146
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
147
{
148
        struct task_struct *tsk = current;
149
        struct hrtimer *timer;
150
        ktime_t expires;
151
        cputime_t cval, cinterval, nval, ninterval;
152
 
153
        /*
154
         * Validate the timevals in value.
155
         */
156
        if (!timeval_valid(&value->it_value) ||
157
            !timeval_valid(&value->it_interval))
158
                return -EINVAL;
159
 
160
        switch (which) {
161
        case ITIMER_REAL:
162
again:
163
                spin_lock_irq(&tsk->sighand->siglock);
164
                timer = &tsk->signal->real_timer;
165
                if (ovalue) {
166
                        ovalue->it_value = itimer_get_remtime(timer);
167
                        ovalue->it_interval
168
                                = ktime_to_timeval(tsk->signal->it_real_incr);
169
                }
170
                /* We are sharing ->siglock with it_real_fn() */
171
                if (hrtimer_try_to_cancel(timer) < 0) {
172
                        spin_unlock_irq(&tsk->sighand->siglock);
173
                        goto again;
174
                }
175
                expires = timeval_to_ktime(value->it_value);
176
                if (expires.tv64 != 0) {
177
                        tsk->signal->it_real_incr =
178
                                timeval_to_ktime(value->it_interval);
179
                        hrtimer_start(timer, expires, HRTIMER_MODE_REL);
180
                } else
181
                        tsk->signal->it_real_incr.tv64 = 0;
182
 
183
                spin_unlock_irq(&tsk->sighand->siglock);
184
                break;
185
        case ITIMER_VIRTUAL:
186
                nval = timeval_to_cputime(&value->it_value);
187
                ninterval = timeval_to_cputime(&value->it_interval);
188
                read_lock(&tasklist_lock);
189
                spin_lock_irq(&tsk->sighand->siglock);
190
                cval = tsk->signal->it_virt_expires;
191
                cinterval = tsk->signal->it_virt_incr;
192
                if (!cputime_eq(cval, cputime_zero) ||
193
                    !cputime_eq(nval, cputime_zero)) {
194
                        if (cputime_gt(nval, cputime_zero))
195
                                nval = cputime_add(nval,
196
                                                   jiffies_to_cputime(1));
197
                        set_process_cpu_timer(tsk, CPUCLOCK_VIRT,
198
                                              &nval, &cval);
199
                }
200
                tsk->signal->it_virt_expires = nval;
201
                tsk->signal->it_virt_incr = ninterval;
202
                spin_unlock_irq(&tsk->sighand->siglock);
203
                read_unlock(&tasklist_lock);
204
                if (ovalue) {
205
                        cputime_to_timeval(cval, &ovalue->it_value);
206
                        cputime_to_timeval(cinterval, &ovalue->it_interval);
207
                }
208
                break;
209
        case ITIMER_PROF:
210
                nval = timeval_to_cputime(&value->it_value);
211
                ninterval = timeval_to_cputime(&value->it_interval);
212
                read_lock(&tasklist_lock);
213
                spin_lock_irq(&tsk->sighand->siglock);
214
                cval = tsk->signal->it_prof_expires;
215
                cinterval = tsk->signal->it_prof_incr;
216
                if (!cputime_eq(cval, cputime_zero) ||
217
                    !cputime_eq(nval, cputime_zero)) {
218
                        if (cputime_gt(nval, cputime_zero))
219
                                nval = cputime_add(nval,
220
                                                   jiffies_to_cputime(1));
221
                        set_process_cpu_timer(tsk, CPUCLOCK_PROF,
222
                                              &nval, &cval);
223
                }
224
                tsk->signal->it_prof_expires = nval;
225
                tsk->signal->it_prof_incr = ninterval;
226
                spin_unlock_irq(&tsk->sighand->siglock);
227
                read_unlock(&tasklist_lock);
228
                if (ovalue) {
229
                        cputime_to_timeval(cval, &ovalue->it_value);
230
                        cputime_to_timeval(cinterval, &ovalue->it_interval);
231
                }
232
                break;
233
        default:
234
                return -EINVAL;
235
        }
236
        return 0;
237
}
238
 
239
/**
240
 * alarm_setitimer - set alarm in seconds
241
 *
242
 * @seconds:    number of seconds until alarm
243
 *              0 disables the alarm
244
 *
245
 * Returns the remaining time in seconds of a pending timer or 0 when
246
 * the timer is not active.
247
 *
248
 * On 32 bit machines the seconds value is limited to (INT_MAX/2) to avoid
249
 * negative timeval settings which would cause immediate expiry.
250
 */
251
unsigned int alarm_setitimer(unsigned int seconds)
252
{
253
        struct itimerval it_new, it_old;
254
 
255
#if BITS_PER_LONG < 64
256
        if (seconds > INT_MAX)
257
                seconds = INT_MAX;
258
#endif
259
        it_new.it_value.tv_sec = seconds;
260
        it_new.it_value.tv_usec = 0;
261
        it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
262
 
263
        do_setitimer(ITIMER_REAL, &it_new, &it_old);
264
 
265
        /*
266
         * We can't return 0 if we have an alarm pending ...  And we'd
267
         * better return too much than too little anyway
268
         */
269
        if ((!it_old.it_value.tv_sec && it_old.it_value.tv_usec) ||
270
              it_old.it_value.tv_usec >= 500000)
271
                it_old.it_value.tv_sec++;
272
 
273
        return it_old.it_value.tv_sec;
274
}
275
 
276
asmlinkage long sys_setitimer(int which,
277
                              struct itimerval __user *value,
278
                              struct itimerval __user *ovalue)
279
{
280
        struct itimerval set_buffer, get_buffer;
281
        int error;
282
 
283
        if (value) {
284
                if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
285
                        return -EFAULT;
286
        } else
287
                memset((char *) &set_buffer, 0, sizeof(set_buffer));
288
 
289
        error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL);
290
        if (error || !ovalue)
291
                return error;
292
 
293
        if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
294
                return -EFAULT;
295
        return 0;
296
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.