amt_wanted_min added to resource requests
[akaros.git] / user / roslib / src / syscall.c
1 // System call stubs.
2
3 #include <ros/common.h>
4 #include <arch/arch.h>
5 #include <ros/syscall.h>
6 #include <lib.h>
7
8 intreg_t syscall(uint16_t num, intreg_t a1,
9                 intreg_t a2, intreg_t a3,
10                 intreg_t a4, intreg_t a5);
11
12 static error_t async_syscall(syscall_req_t *COUNT(1) req, syscall_desc_t* desc)
13 {
14         // Note that this assumes one global frontring (TODO)
15         // abort if there is no room for our request.  ring size is currently 64.
16         // we could spin til it's free, but that could deadlock if this same thread
17         // is supposed to consume the requests it is waiting on later.
18         if (RING_FULL(&syscallfrontring))
19                 return -EBUSY;
20         // req_prod_pvt comes in as the previously produced item.  need to
21         // increment to the next available spot, which is the one we'll work on.
22         // at some point, we need to listen for the responses.
23         desc->idx = ++(syscallfrontring.req_prod_pvt);
24         desc->sysfr = &syscallfrontring;
25         syscall_req_t* r = RING_GET_REQUEST(&syscallfrontring, desc->idx);
26         memcpy(r, req, sizeof(syscall_req_t));
27         // push our updates to syscallfrontring.req_prod_pvt
28         RING_PUSH_REQUESTS(&syscallfrontring);
29         //cprintf("DEBUG: sring->req_prod: %d, sring->rsp_prod: %d\n", 
30         //   syscallfrontring.sring->req_prod, syscallfrontring.sring->rsp_prod);
31         return 0;
32 }
33
34 // consider a timeout too
35 error_t waiton_syscall(syscall_desc_t* desc, syscall_rsp_t* rsp)
36 {
37         // Make sure we were given a desc with a non-NULL frontring.  This could
38         // happen if someone forgot to check the error code on the paired syscall.
39         if (!desc->sysfr)
40                 return -EFAIL;
41         // this forces us to call wait in the order in which the syscalls are made.
42         if (desc->idx != desc->sysfr->rsp_cons + 1)
43                 return -EDEADLOCK;
44         while (!(RING_HAS_UNCONSUMED_RESPONSES(desc->sysfr)))
45                 cpu_relax();
46         memcpy(rsp, RING_GET_RESPONSE(desc->sysfr, desc->idx), sizeof(*rsp));
47         desc->sysfr->rsp_cons++;
48     // run a cleanup function for this desc, if available
49     if (desc->cleanup)
50         desc->cleanup(desc->data);
51         return 0;
52 }
53
54 void sys_null()
55 {
56         syscall(SYS_null,0,0,0,0,0);
57 }
58
59 error_t sys_null_async(syscall_desc_t* desc)
60 {
61         syscall_req_t syscall = {SYS_null, 0, {[0 ... (NUM_SYSCALL_ARGS-1)] 0}};
62         desc->cleanup = NULL;
63         desc->data = NULL;
64         return async_syscall(&syscall, desc);
65 }
66
67 void sys_cache_buster(uint32_t num_writes, uint32_t num_pages, uint32_t flags)
68 {
69         syscall(SYS_cache_buster, num_writes, num_pages, flags, 0, 0);
70 }
71
72 error_t sys_cache_buster_async(syscall_desc_t* desc, uint32_t num_writes,
73                                                uint32_t num_pages, uint32_t flags)
74 {
75         syscall_req_t syscall = {SYS_cache_buster, 0, {num_writes, num_pages, flags,
76                                                        [3 ... (NUM_SYSCALL_ARGS-1)] 0}};
77         // just to be safe, 0 these out.  they should have been 0'd right after
78         // the desc was POOL_GET'd
79         desc->cleanup = NULL;
80         desc->data = NULL;
81         return async_syscall(&syscall, desc);
82 }
83
84 void sys_cache_invalidate()
85 {
86         syscall(SYS_cache_invalidate, 0, 0, 0, 0, 0);
87 }
88
89 ssize_t sys_cputs(const char *s, size_t len)
90 {
91         return syscall(SYS_cputs, (uintreg_t)s,  len, 0, 0, 0);
92 }
93
94 error_t sys_cputs_async(const char *s, size_t len, syscall_desc_t* desc,
95                         void (*cleanup_handler)(void*), void* cleanup_data)
96 {
97         // could just hardcode 4 0's, will eventually wrap this marshaller anyway
98         syscall_req_t syscall = {SYS_cputs, 0, {(uint32_t)s, len, [2 ... (NUM_SYSCALL_ARGS-1)] 0} };
99         desc->cleanup = cleanup_handler;
100         desc->data = cleanup_data;
101         return async_syscall(&syscall, desc);
102 }
103
104 uint16_t sys_cgetc(void)
105 {
106         return syscall(SYS_cgetc, 0, 0, 0, 0, 0);
107 }
108
109 size_t sys_getcpuid(void)
110 {
111         return syscall(SYS_getcpuid, 0, 0, 0, 0, 0);
112 }
113
114 int sys_getpid(void)
115 {
116         return syscall(SYS_getpid, 0, 0, 0, 0, 0);
117 }
118
119 error_t sys_proc_destroy(int pid)
120 {
121         return syscall(SYS_proc_destroy, pid, 0, 0, 0, 0);
122 }
123
124 void sys_yield(void)
125 {
126         syscall(SYS_yield, 0, 0, 0, 0, 0);
127         return;
128 }
129
130 int sys_proc_create(char* path)
131 {
132         return syscall(SYS_proc_create, (uintreg_t)path, 0, 0, 0, 0);
133 }
134
135 error_t sys_proc_run(int pid)
136 {
137         return syscall(SYS_proc_run, pid, 0, 0, 0, 0);
138 }
139
140 /* We need to do some hackery to pass 6 arguments.  Arg4 pts to the real arg4,
141  * arg5, and arg6.  Keep this in sync with kern/src/syscall.c.
142  * TODO: consider a syscall_multi that can take more args, and keep it in sync
143  * with the kernel.  Maybe wait til we fix sysenter to have 5 or 6 args. */
144 void *CT(length)
145 sys_mmap(void *SNT addr, size_t length, int prot, int flags, int fd,
146          size_t offset)
147 {
148         struct args {
149                 int _flags;
150                 int _fd;
151                 size_t _offset;
152         } extra_args;
153         extra_args._flags = flags;
154         extra_args._fd = fd;
155         extra_args._offset = offset;
156         // TODO: deputy bitches about this
157         return (void*CT(length))TC(syscall(SYS_mmap, (uint32_t)addr, length, prot,
158                               (int32_t)&extra_args, 0));
159 }
160
161 /* Request resources from the kernel.  Flags in ros/resource.h. */
162 ssize_t sys_resource_req(int type, size_t amt_wanted, size_t amt_wanted_min,
163                          uint32_t flags)
164 {
165         return syscall(SYS_resource_req, type, amt_wanted, amt_wanted_min, flags, 0);
166 }