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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [kernel/] [itimer.c] - Blame information for rev 1766

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

Line No. Rev Author Line
1 1275 phoenix
/*
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/smp_lock.h>
11
#include <linux/interrupt.h>
12
 
13
#include <asm/uaccess.h>
14
 
15
/*
16
 * change timeval to jiffies, trying to avoid the
17
 * most obvious overflows..
18
 *
19
 * The tv_*sec values are signed, but nothing seems to
20
 * indicate whether we really should use them as signed values
21
 * when doing itimers. POSIX doesn't mention this (but if
22
 * alarm() uses itimers without checking, we have to use unsigned
23
 * arithmetic).
24
 */
25
static unsigned long tvtojiffies(struct timeval *value)
26
{
27
        unsigned long sec = (unsigned) value->tv_sec;
28
        unsigned long usec = (unsigned) value->tv_usec;
29
 
30
        if (sec > (ULONG_MAX / HZ))
31
                return ULONG_MAX;
32
        usec += 1000000 / HZ - 1;
33
        usec /= 1000000 / HZ;
34
        return HZ*sec+usec;
35
}
36
 
37
static void jiffiestotv(unsigned long jiffies, struct timeval *value)
38
{
39
        value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
40
        value->tv_sec = jiffies / HZ;
41
}
42
 
43
int do_getitimer(int which, struct itimerval *value)
44
{
45
        register unsigned long val, interval;
46
 
47
        switch (which) {
48
        case ITIMER_REAL:
49
                interval = current->it_real_incr;
50
                val = 0;
51
                /*
52
                 * FIXME! This needs to be atomic, in case the kernel timer happens!
53
                 */
54
                if (timer_pending(&current->real_timer)) {
55
                        val = current->real_timer.expires - jiffies;
56
 
57
                        /* look out for negative/zero itimer.. */
58
                        if ((long) val <= 0)
59
                                val = 1;
60
                }
61
                break;
62
        case ITIMER_VIRTUAL:
63
                val = current->it_virt_value;
64
                interval = current->it_virt_incr;
65
                break;
66
        case ITIMER_PROF:
67
                val = current->it_prof_value;
68
                interval = current->it_prof_incr;
69
                break;
70
        default:
71
                return(-EINVAL);
72
        }
73
        jiffiestotv(val, &value->it_value);
74
        jiffiestotv(interval, &value->it_interval);
75
        return 0;
76
}
77
 
78
/* SMP: Only we modify our itimer values. */
79
asmlinkage long sys_getitimer(int which, struct itimerval *value)
80
{
81
        int error = -EFAULT;
82
        struct itimerval get_buffer;
83
 
84
        if (value) {
85
                error = do_getitimer(which, &get_buffer);
86
                if (!error &&
87
                    copy_to_user(value, &get_buffer, sizeof(get_buffer)))
88
                        error = -EFAULT;
89
        }
90
        return error;
91
}
92
 
93
void it_real_fn(unsigned long __data)
94
{
95
        struct task_struct * p = (struct task_struct *) __data;
96
        unsigned long interval;
97
 
98
        send_sig(SIGALRM, p, 1);
99
        interval = p->it_real_incr;
100
        if (interval) {
101
                if (interval > (unsigned long) LONG_MAX)
102
                        interval = LONG_MAX;
103
                p->real_timer.expires = jiffies + interval;
104
                add_timer(&p->real_timer);
105
        }
106
}
107
 
108
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
109
{
110
        register unsigned long i, j;
111
        int k;
112
 
113
        i = tvtojiffies(&value->it_interval);
114
        j = tvtojiffies(&value->it_value);
115
        if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
116
                return k;
117
        switch (which) {
118
                case ITIMER_REAL:
119
                        del_timer_sync(&current->real_timer);
120
                        current->it_real_value = j;
121
                        current->it_real_incr = i;
122
                        if (!j)
123
                                break;
124
                        if (j > (unsigned long) LONG_MAX)
125
                                j = LONG_MAX;
126
                        i = j + jiffies;
127
                        current->real_timer.expires = i;
128
                        add_timer(&current->real_timer);
129
                        break;
130
                case ITIMER_VIRTUAL:
131
                        if (j)
132
                                j++;
133
                        current->it_virt_value = j;
134
                        current->it_virt_incr = i;
135
                        break;
136
                case ITIMER_PROF:
137
                        if (j)
138
                                j++;
139
                        current->it_prof_value = j;
140
                        current->it_prof_incr = i;
141
                        break;
142
                default:
143
                        return -EINVAL;
144
        }
145
        return 0;
146
}
147
 
148
/* SMP: Again, only we play with our itimers, and signals are SMP safe
149
 *      now so that is not an issue at all anymore.
150
 */
151
asmlinkage long sys_setitimer(int which, struct itimerval *value,
152
                              struct itimerval *ovalue)
153
{
154
        struct itimerval set_buffer, get_buffer;
155
        int error;
156
 
157
        if (value) {
158
                if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
159
                        return -EFAULT;
160
        } else
161
                memset((char *) &set_buffer, 0, sizeof(set_buffer));
162
 
163
        error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
164
        if (error || !ovalue)
165
                return error;
166
 
167
        if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
168
                return -EFAULT;
169
        return 0;
170
}

powered by: WebSVN 2.1.0

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