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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [kernel/] [itimer.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1634 jcastillo
/*
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/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
 
18
/*
19
 * change timeval to jiffies, trying to avoid the
20
 * most obvious overflows..
21
 *
22
 * The tv_*sec values are signed, but nothing seems to
23
 * indicate whether we really should use them as signed values
24
 * when doing itimers. POSIX doesn't mention this (but if
25
 * alarm() uses itimers without checking, we have to use unsigned
26
 * arithmetic).
27
 */
28
static unsigned long tvtojiffies(struct timeval *value)
29
{
30
        unsigned long sec = (unsigned) value->tv_sec;
31
        unsigned long usec = (unsigned) value->tv_usec;
32
 
33
        if (sec > (ULONG_MAX / HZ))
34
                return ULONG_MAX;
35
        usec += 1000000 / HZ - 1;
36
        usec /= 1000000 / HZ;
37
        return HZ*sec+usec;
38
}
39
 
40
static void jiffiestotv(unsigned long jiffies, struct timeval *value)
41
{
42
        value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
43
        value->tv_sec = jiffies / HZ;
44
        return;
45
}
46
 
47
static int _getitimer(int which, struct itimerval *value)
48
{
49
        register unsigned long val, interval;
50
 
51
        switch (which) {
52
        case ITIMER_REAL:
53
                interval = current->it_real_incr;
54
                val = 0;
55
                if (del_timer(&current->real_timer)) {
56
                        unsigned long now = jiffies;
57
                        val = current->real_timer.expires;
58
                        add_timer(&current->real_timer);
59
                        /* look out for negative/zero itimer.. */
60
                        if (val <= now)
61
                                val = now+1;
62
                        val -= now;
63
                }
64
                break;
65
        case ITIMER_VIRTUAL:
66
                val = current->it_virt_value;
67
                interval = current->it_virt_incr;
68
                break;
69
        case ITIMER_PROF:
70
                val = current->it_prof_value;
71
                interval = current->it_prof_incr;
72
                break;
73
        default:
74
                return(-EINVAL);
75
        }
76
        jiffiestotv(val, &value->it_value);
77
        jiffiestotv(interval, &value->it_interval);
78
        return 0;
79
}
80
 
81
asmlinkage int sys_getitimer(int which, struct itimerval *value)
82
{
83
        int error;
84
        struct itimerval get_buffer;
85
 
86
        if (!value)
87
                return -EFAULT;
88
        error = _getitimer(which, &get_buffer);
89
        if (error)
90
                return error;
91
        error = verify_area(VERIFY_WRITE, value, sizeof(struct itimerval));
92
        if (error)
93
                return error;
94
        memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
95
        return 0;
96
}
97
 
98
void it_real_fn(unsigned long __data)
99
{
100
        struct task_struct * p = (struct task_struct *) __data;
101
        unsigned long interval;
102
 
103
        send_sig(SIGALRM, p, 1);
104
        interval = p->it_real_incr;
105
        if (interval) {
106
                unsigned long timeout = jiffies + interval;
107
                /* check for overflow */
108
                if (timeout < interval)
109
                        timeout = ULONG_MAX;
110
                p->real_timer.expires = timeout;
111
                add_timer(&p->real_timer);
112
        }
113
}
114
 
115
int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
116
{
117
        register unsigned long i, j;
118
        int k;
119
 
120
        i = tvtojiffies(&value->it_interval);
121
        j = tvtojiffies(&value->it_value);
122
        if (ovalue && (k = _getitimer(which, ovalue)) < 0)
123
                return k;
124
        switch (which) {
125
                case ITIMER_REAL:
126
                        del_timer(&current->real_timer);
127
                        current->it_real_value = j;
128
                        current->it_real_incr = i;
129
                        if (!j)
130
                                break;
131
                        i = j + jiffies;
132
                        /* check for overflow.. */
133
                        if (i < j)
134
                                i = ULONG_MAX;
135
                        current->real_timer.expires = i;
136
                        add_timer(&current->real_timer);
137
                        break;
138
                case ITIMER_VIRTUAL:
139
                        if (j)
140
                                j++;
141
                        current->it_virt_value = j;
142
                        current->it_virt_incr = i;
143
                        break;
144
                case ITIMER_PROF:
145
                        if (j)
146
                                j++;
147
                        current->it_prof_value = j;
148
                        current->it_prof_incr = i;
149
                        break;
150
                default:
151
                        return -EINVAL;
152
        }
153
        return 0;
154
}
155
 
156
asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
157
{
158
        int error;
159
        struct itimerval set_buffer, get_buffer;
160
 
161
        if (value) {
162
                error = verify_area(VERIFY_READ, value, sizeof(*value));
163
                if (error)
164
                        return error;
165
                memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
166
        } else
167
                memset((char *) &set_buffer, 0, sizeof(set_buffer));
168
 
169
        if (ovalue) {
170
                error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
171
                if (error)
172
                        return error;
173
        }
174
 
175
        error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
176
        if (error || !ovalue)
177
                return error;
178
 
179
        memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
180
        return error;
181
}

powered by: WebSVN 2.1.0

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