5ff45a02d2fe53c27204c2cd6ca22691acaba13d
[akaros.git] / kern / include / ros / syscall.h
1 #ifndef ROS_INC_SYSCALL_H
2 #define ROS_INC_SYSCALL_H
3
4 #include <arch/arch.h>
5 #include <ros/bits/syscall.h>
6 #include <ros/arch/syscall.h>
7 #include <ros/event.h>
8 #include <ros/atomic.h>
9
10 /* Flags for an individual syscall.
11  * Careful, sparc can't handle flags in byte 3. */
12 #define SC_DONE                                 0x0001          /* SC is done */
13 #define SC_PROGRESS                             0x0002          /* SC made progress */
14 #define SC_UEVENT                               0x0004          /* user has an ev_q */
15 #define SC_K_LOCK                               0x0008          /* kernel locked sysc */
16
17 struct syscall {
18         unsigned int                            num;
19         int                                                     err;                    /* errno */
20         long                                            retval;
21         atomic_t                                        flags;
22         struct event_queue                      *ev_q;
23         void                                            *u_data;
24         long                                            arg0;
25         long                                            arg1;
26         long                                            arg2;
27         long                                            arg3;
28         long                                            arg4;
29         long                                            arg5;
30 };
31
32 #ifndef ROS_KERNEL
33
34 #include <arch/atomic.h>
35
36 /* Attempts to block on sysc, returning when it is done or progress has been
37  * made.  (function is in uthread.c) */
38 void ros_syscall_blockon(struct syscall *sysc);
39
40 /* No one should be using this - it's meant to allow glibc to compile, and all
41  * apps will link against parlib to get the real function. */
42 static inline void __ros_syscall_blockon(struct syscall *sysc)
43 {
44         /* My ghetto error message: force a PF */
45         int *x = (int*)0xdeadbeef;
46         *x = 1337;
47 }
48 weak_alias(__ros_syscall_blockon, ros_syscall_blockon);
49
50 /* TODO: make variants of __ros_syscall() based on the number of args (0 - 6) */
51 /* These are simple synchronous system calls, built on top of the kernel's async
52  * interface.  This version makes no assumptions about errno.  You usually don't
53  * want this. */
54 static inline long __ros_syscall(unsigned int _num, long _a0, long _a1, long _a2,
55                                  long _a3, long _a4, long _a5, int *errno_loc)
56 {
57         int num_started;        /* not used yet */
58         struct syscall sysc = {0};
59         sysc.num = _num;
60         sysc.ev_q = 0;
61         sysc.arg0 = _a0;
62         sysc.arg1 = _a1;
63         sysc.arg2 = _a2;
64         sysc.arg3 = _a3;
65         sysc.arg4 = _a4;
66         sysc.arg5 = _a5;
67         num_started = __ros_arch_syscall(&sysc, 1);
68         /* Don't proceed til we are done */
69         while (!(atomic_read(&sysc.flags) & SC_DONE))
70                 ros_syscall_blockon(&sysc);
71         /* Need to wait til it is unlocked.  It's not really done until SC_DONE &
72          * !SC_K_LOCK. */
73         while (atomic_read(&sysc.flags) & SC_K_LOCK)
74                 cpu_relax();
75         if (errno_loc)
76                 *errno_loc = sysc.err;
77         return sysc.retval;
78 }
79
80 #include <errno.h>
81
82 /* This version knows about errno and will handle it. */
83 static inline long __ros_syscall_errno(unsigned int _num, long _a0, long _a1,
84                                        long _a2, long _a3, long _a4, long _a5)
85 {
86         return __ros_syscall(_num, _a0, _a1, _a2, _a3, _a4, _a5, &errno);
87 }
88
89 /* Convenience wrapper for __ros_syscall */
90 #define ros_syscall(which, a0, a1, a2, a3, a4, a5) \
91    __ros_syscall_errno(which, (long)(a0), (long)(a1), (long)(a2), (long)(a3), \
92                        (long)(a4), (long)(a5))
93
94 #endif /* ifndef ROS_KERNEL */
95
96 #endif /* ROS_INC_SYSCALL_H */