Statistics
| Branch: | Revision:

root / prex-0.9.0 / sys / kern / sysent.c @ 03e9c04a

History | View | Annotate | Download (6.5 KB)

1
/*-
2
 * Copyright (c) 2005-2009 Kohsuke Ohtani
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the author nor the names of any co-contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29

    
30
/*
31
 * sysent.c - system call switch table.
32
 */
33

    
34
#include <kernel.h>
35
#include <thread.h>
36
#include <timer.h>
37
#include <vm.h>
38
#include <task.h>
39
#include <exception.h>
40
#include <ipc.h>
41
#include <device.h>
42
#include <sync.h>
43
#include <system.h>
44

    
45
typedef register_t (*sysfn_t)(register_t, register_t, register_t, register_t);
46

    
47
#ifdef DEBUG
48
static void strace_entry(register_t, register_t, register_t, register_t,
49
                         register_t);
50
static void strace_return(register_t, register_t);
51
#endif
52

    
53
struct sysent {
54
#ifdef DEBUG
55
        int        sy_narg;        /* number of arguments */
56
        char        *sy_name;        /* name string */
57
#endif
58
        sysfn_t        sy_call;        /* handler */
59
};
60

    
61
/*
62
 * Sysent initialization macros.
63
 *
64
 * Initialization macro for system calls which take their args
65
 * in the C style. In order to reduce the memory space, we
66
 * store the syscall name and its argument count only when
67
 * DEBUG is defined.
68
 *
69
 */
70
#ifdef DEBUG
71
#define SYSENT(n, fn)        {n, __STRING(fn), (sysfn_t)(fn)}
72
#else
73
#define SYSENT(n, fn)        {(sysfn_t)(fn)}
74
#endif
75

    
76
/*
77
 * This table is the switch used to transfer to the
78
 * appropriate routine for processing a system call.
79
 * The first element must be exception_return because
80
 * it requires special handling in HAL code.
81
 */
82
static const struct sysent sysent[] = {
83
        /*  0 */ SYSENT(0, exception_return),
84
        /*  1 */ SYSENT(1, exception_setup),
85
        /*  2 */ SYSENT(2, exception_raise),
86
        /*  3 */ SYSENT(1, exception_wait),
87
        /*  4 */ SYSENT(3, task_create),
88
        /*  5 */ SYSENT(1, task_terminate),
89
        /*  6 */ SYSENT(0, task_self),
90
        /*  7 */ SYSENT(1, task_suspend),
91
        /*  8 */ SYSENT(1, task_resume),
92
        /*  9 */ SYSENT(2, task_setname),
93
        /* 10 */ SYSENT(2, task_setcap),
94
        /* 11 */ SYSENT(2, task_chkcap),
95
        /* 12 */ SYSENT(2, thread_create),
96
        /* 13 */ SYSENT(1, thread_terminate),
97
        /* 14 */ SYSENT(3, thread_load),
98
        /* 15 */ SYSENT(0, thread_self),
99
        /* 16 */ SYSENT(0, thread_yield),
100
        /* 17 */ SYSENT(1, thread_suspend),
101
        /* 18 */ SYSENT(1, thread_resume),
102
        /* 19 */ SYSENT(3, thread_schedparam),
103
        /* 20 */ SYSENT(4, vm_allocate),
104
        /* 21 */ SYSENT(2, vm_free),
105
        /* 22 */ SYSENT(3, vm_attribute),
106
        /* 23 */ SYSENT(4, vm_map),
107
        /* 24 */ SYSENT(2, object_create),
108
        /* 25 */ SYSENT(1, object_destroy),
109
        /* 26 */ SYSENT(2, object_lookup),
110
        /* 27 */ SYSENT(3, msg_send),
111
        /* 28 */ SYSENT(3, msg_receive),
112
        /* 29 */ SYSENT(3, msg_reply),
113
        /* 30 */ SYSENT(2, timer_sleep),
114
        /* 31 */ SYSENT(2, timer_alarm),
115
        /* 32 */ SYSENT(3, timer_periodic),
116
        /* 33 */ SYSENT(0, timer_waitperiod),
117
        /* 34 */ SYSENT(3, device_open),
118
        /* 35 */ SYSENT(1, device_close),
119
        /* 36 */ SYSENT(4, device_read),
120
        /* 37 */ SYSENT(4, device_write),
121
        /* 38 */ SYSENT(3, device_ioctl),
122
        /* 39 */ SYSENT(1, mutex_init),
123
        /* 40 */ SYSENT(1, mutex_destroy),
124
        /* 41 */ SYSENT(1, mutex_lock),
125
        /* 42 */ SYSENT(1, mutex_trylock),
126
        /* 43 */ SYSENT(1, mutex_unlock),
127
        /* 44 */ SYSENT(1, cond_init),
128
        /* 45 */ SYSENT(1, cond_destroy),
129
        /* 46 */ SYSENT(2, cond_wait),
130
        /* 47 */ SYSENT(1, cond_signal),
131
        /* 48 */ SYSENT(1, cond_broadcast),
132
        /* 49 */ SYSENT(2, sem_init),
133
        /* 50 */ SYSENT(1, sem_destroy),
134
        /* 51 */ SYSENT(2, sem_wait),
135
        /* 52 */ SYSENT(1, sem_trywait),
136
        /* 53 */ SYSENT(1, sem_post),
137
        /* 54 */ SYSENT(2, sem_getvalue),
138
        /* 55 */ SYSENT(1, sys_log),
139
        /* 56 */ SYSENT(1, sys_panic),
140
        /* 57 */ SYSENT(2, sys_info),
141
        /* 58 */ SYSENT(1, sys_time),
142
        /* 59 */ SYSENT(2, sys_debug),
143
};
144

    
145
#define NSYSCALL        (int)(sizeof(sysent) / sizeof(sysent[0]))
146

    
147

    
148
/*
149
 * System call dispatcher.
150
 */
151
register_t
152
syscall_handler(register_t a1, register_t a2, register_t a3, register_t a4,
153
                register_t id)
154
{
155
        register_t retval = EINVAL;
156
        const struct sysent *callp;
157

    
158
#ifdef DEBUG
159
        strace_entry(a1, a2, a3, a4, id);
160
#endif
161

    
162
        if (id < NSYSCALL) {
163
                callp = &sysent[id];
164
                retval = (*callp->sy_call)(a1, a2, a3, a4);
165
        }
166

    
167
#ifdef DEBUG
168
        strace_return(retval, id);
169
#endif
170
        return retval;
171
}
172

    
173
#ifdef DEBUG
174
/*
175
 * Show syscall info if the task is being traced.
176
 */
177
static void
178
strace_entry(register_t a1, register_t a2, register_t a3, register_t a4,
179
             register_t id)
180
{
181
        const struct sysent *callp;
182

    
183
        if (curtask->flags & TF_TRACE) {
184
                if (id >= NSYSCALL) {
185
                        printf("%s: OUT OF RANGE (%d)\n",
186
                               curtask->name, id);
187
                        return;
188
                }
189

    
190
                callp = &sysent[id];
191

    
192
                printf("%s: %s(", curtask->name, callp->sy_name);
193
                switch (callp->sy_narg) {
194
                case 0:
195
                        printf(")\n");
196
                        break;
197
                case 1:
198
                        printf("0x%08x)\n", a1);
199
                        break;
200
                case 2:
201
                        printf("0x%08x, 0x%08x)\n", a1, a2);
202
                        break;
203
                case 3:
204
                        printf("0x%08x, 0x%08x, 0x%08x)\n",
205
                               a1, a2, a3);
206
                        break;
207
                case 4:
208
                        printf("0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
209
                               a1, a2, a3, a4);
210
                        break;
211
                }
212
        }
213
}
214

    
215
/*
216
 * Show status if syscall is failed.
217
 *
218
 * We ignore the return code for the function which does
219
 * not have any arguments, although timer_waitperiod()
220
 * has valid return code...
221
 */
222
static void
223
strace_return(register_t retval, register_t id)
224
{
225
        const struct sysent *callp;
226

    
227
        if (curtask->flags & TF_TRACE) {
228
                if (id >= NSYSCALL)
229
                        return;
230
                callp = &sysent[id];
231
                if (callp->sy_narg != 0 && retval != 0)
232
                        printf("%s: !!! %s() = 0x%08x\n",
233
                                curtask->name, callp->sy_name, retval);
234
        }
235
}
236
#endif /* !DEBUG */