727c254230fe82fc774c9a933b636d631c729d63
[akaros.git] / user / lwip / core / sys_arch.c
1 /*
2  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3  * All rights reserved. 
4  * 
5  * Redistribution and use in source and binary forms, with or without modification, 
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission. 
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  * 
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32
33 #include "lwip/debug.h"
34
35 #include "lwip/sys.h"
36 #include "lwip/opt.h"
37 #include "lwip/stats.h"
38
39 #include <pthread.h>
40 #include <arch/arch.h>
41
42 #define sys_debug(...) //printf(__VA_ARGS__)
43
44 pthread_mutex_t sys_lock;
45
46 uint8_t protection_status;
47
48 __thread struct sys_timeouts local_timeouts;
49
50 typedef struct sys_hart_startup {
51
52         void (*hart_startup)(void* arg);
53         void *arg;
54
55 } sys_hart_startup_t;
56
57 // HACK
58 void sys_init(void) {
59         sys_debug("In sys_init\n");
60
61         pthread_mutex_init(&sys_lock, NULL);
62         
63         protection_status = 0;
64
65         printf("Register callback\n");
66 }
67
68 // HACK
69 u32_t sys_now(void) {
70
71         sys_debug("In sys_now\n");
72
73         uint64_t now = read_tsc();
74
75         now = now / procinfo.tsc_freq;
76
77         now = now * 1000;
78
79         return (uint32_t)now;
80 }
81
82 // OK
83 sys_sem_t sys_sem_new(u8_t count) {
84
85         sys_debug("In sys_sem_new\n");
86
87         sys_sem_t sem = (sys_sem_t)malloc(sizeof(struct sys_sem));
88
89         if (sem == NULL)
90                 return SYS_SEM_NULL;
91
92         pthread_mutex_init(&(sem->lock), NULL);
93
94         sem->count = count;
95
96         return sem;
97 }
98
99 // OK
100 void sys_sem_free(sys_sem_t sem) {
101
102         sys_debug("In sys_sem_free\n");
103
104         pthread_mutex_destroy(&(sem->lock));    
105
106         free(sem);
107
108         return;
109 }
110
111 // OK
112 void sys_sem_signal(sys_sem_t sem) {
113
114         sys_debug("In sys_sem_signal\n");
115
116         pthread_mutex_lock(&(sem->lock));
117
118         sem->count = sem->count + 1;
119
120         pthread_mutex_unlock(&(sem->lock));
121         
122         return;
123 }
124
125 // OK
126 u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) {
127
128         sys_debug("In sys_arch_sem_wait\n");
129
130         uint32_t start = sys_now();
131         uint32_t current = 0;
132
133         pthread_mutex_lock(&(sem->lock));
134
135         while (sem->count == 0) {
136
137                 pthread_mutex_unlock(&(sem->lock));
138
139                 current = sys_now();
140                 
141                 if (((current - start) > timeout) && (timeout != 0)) {
142                         return SYS_ARCH_TIMEOUT;
143                 }
144
145                 hart_relax();
146                 
147                 pthread_mutex_lock(&(sem->lock));
148         }
149
150         sem->count = sem->count - 1;
151
152         pthread_mutex_unlock(&(sem->lock));
153
154         return sys_now() - start;
155 }
156
157
158 //HACK
159 sys_mbox_t sys_mbox_new(int size) {
160
161         sys_debug("In sys_mbox_new\n");
162
163
164         // HACK:
165         if (size == 0)
166                 size = 20;
167
168         sys_mbox_t new_box = (sys_mbox_t)malloc(sizeof(struct sys_mbox) + size * sizeof(char*));
169
170         if (new_box == NULL)
171                 return SYS_MBOX_NULL;
172         memset(new_box, 0x00, sizeof(struct sys_mbox) + size * sizeof(char*));
173
174         pthread_mutex_init(&(new_box->lock), NULL);
175
176         new_box->size = size;
177         new_box->count = 0;
178         new_box->first = 0;
179         
180         return new_box;
181 }
182
183 // HACK
184 void sys_mbox_free(sys_mbox_t mbox) {
185
186         sys_debug("In sys_mbox_new\n");
187
188         
189         // Should we aquire the lock here?
190         if (mbox->count != 0) {
191                 printf("LWIP Stack errror. Bad.\n");
192                 return;
193         }
194
195         pthread_mutex_destroy(&(mbox->lock));
196
197         free(mbox);
198
199         return;
200 }
201
202
203 // HACK
204 void sys_mbox_post(sys_mbox_t mbox, void *msg) {
205
206         sys_debug("In sys_mbox_post\n");
207
208         pthread_mutex_lock(&(mbox->lock));
209
210         while(mbox->count >= mbox->size) {
211                 
212                 pthread_mutex_unlock(&(mbox->lock));
213                 
214                 hart_relax();
215                 
216                 pthread_mutex_lock(&(mbox->lock));
217         }
218
219         mbox->buf[(mbox->first + mbox->count) % mbox->size] = msg;
220         mbox->count = mbox->count + 1;
221         
222         pthread_mutex_unlock(&(mbox->lock));
223
224         return;
225 }
226
227 // HACK
228 err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg) {
229
230         sys_debug("In sys_mbox_trypost\n");
231
232         pthread_mutex_lock(&(mbox->lock));
233
234         if (mbox->count >= mbox->size) {
235                 
236                 pthread_mutex_unlock(&(mbox->lock));
237
238                 return ERR_MEM;
239         }
240
241
242         mbox->buf[(mbox->first + mbox->count) % mbox->size] = msg;
243         mbox->count = mbox->count + 1;
244
245         pthread_mutex_unlock(&(mbox->lock));
246
247         return ERR_OK;
248 }
249
250 // HACK
251 u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) {
252
253         sys_debug("In sys_arch_mbox_fetch\n");
254
255         uint32_t start = sys_now();
256         uint32_t current = 0;
257
258         pthread_mutex_lock(&(mbox->lock));
259
260         while (mbox->count == 0) {
261
262                 pthread_mutex_unlock(&(mbox->lock));
263
264                 current = sys_now();
265
266                 if (((current - start) > timeout) && (timeout != 0)) {
267                         return SYS_ARCH_TIMEOUT;
268                 }
269
270                 hart_relax();
271
272                 pthread_mutex_lock(&(mbox->lock));
273         }
274
275         *msg = mbox->buf[mbox->first];
276
277         mbox->first = (mbox->first + 1) % (mbox->size);
278
279         mbox->count = mbox->count - 1;
280
281         pthread_mutex_unlock(&(mbox->lock));
282
283         return sys_now() - start;
284 }
285
286 // HACK
287 u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) {
288
289         sys_debug("In sys_arch_mbox_tryfetch\n");
290
291         pthread_mutex_lock(&(mbox->lock));
292
293         if (mbox->count == 0) {
294
295                 pthread_mutex_unlock(&(mbox->lock));
296
297                 return SYS_MBOX_EMPTY;
298         }
299
300         *msg = mbox->buf[mbox->first];
301
302         mbox->first = (mbox->first + 1) % (mbox->size);
303
304         mbox->count = mbox->count - 1;
305
306         pthread_mutex_unlock(&(mbox->lock));
307
308         return 0;
309 }
310
311 // HACK
312 struct sys_timeouts *sys_arch_timeouts(void) {
313
314         sys_debug("In sys_timeouts\n");
315
316         return &local_timeouts;
317 }
318
319 void sys_thread_wrapper(void *arg) {
320
321         sys_hart_startup_t* ptr = arg;
322
323         local_timeouts.next = NULL;
324
325         ptr->hart_startup(ptr->arg);
326
327         free(ptr);
328 }
329
330 // HACK
331 sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) {
332
333         sys_debug("In sys_thread_new");
334
335         extern void (*hart_startup)();
336         extern void *hart_startup_arg;
337
338         sys_hart_startup_t* wrapper_arg = malloc(sizeof(sys_hart_startup_t));
339
340         if (wrapper_arg == NULL)
341                 return NULL;
342
343         wrapper_arg->hart_startup = thread;
344         wrapper_arg->arg = arg;
345
346         hart_startup = sys_thread_wrapper;
347         hart_startup_arg = wrapper_arg;
348
349         hart_request(1);
350
351         return 0;
352 }
353
354 // HACK
355 sys_prot_t sys_arch_protect(void) {
356
357         sys_debug("In sys_arch_protect\n");
358
359         pthread_mutex_lock(&sys_lock);
360
361         sys_prot_t old = protection_status;
362
363         protection_status = 1;
364
365         pthread_mutex_unlock(&sys_lock);
366
367         return old;
368 }
369
370 // HACK
371 void sys_arch_unprotect(sys_prot_t pval) {
372
373         sys_debug("In sys_arch_unprotect\n");
374
375         pthread_mutex_lock(&sys_lock);
376
377         protection_status = pval;
378
379         pthread_mutex_unlock(&sys_lock);
380
381 }
382