1/* 2 * Copyright (c) 2007, 2008, 2009, 2011, 2012, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <lwip/sys.h> 11#include <barrelfish/barrelfish.h> 12#include <barrelfish/deferred.h> 13#include <barrelfish/systime.h> 14 15/* 16 * TODO: 17 * - implement timeout versions of semaphores and mailboxes correctly 18 * - implement mboxes of size > 1 19 * - implement sys_msleep 20 * - implement sys_jiffies 21 */ 22 23unsigned char debug_flags; 24 25u32_t sys_now(void) 26{ 27 uint64_t ns = systime_to_ns(systime_now()); 28 return ns / 1000000; 29} 30 31#if 0 32 33// from example in http://lwip.wikia.com/wiki/Porting_for_an_OS 34struct thread_wrapper { 35 struct thread_wrapper *next; 36 struct thread *thread; // barrelfish thread 37 struct sys_timeouts timeouts; 38}; 39 40 41// track threads and timeouts. 42struct sys_timeouts lwip_system_timeouts = { .next = NULL }; // Default timeouts list for lwIP 43struct thread_wrapper *lwip_system_threads = NULL; // a list of all threads created by lwIP 44 45 46// wrapper for a condition variable with timeout 47static u32_t thread_cond_wait_timeout(struct thread_cond *cond, 48 struct thread_mutex *mutex, 49 u32_t timeout) 50{ 51 // TODO: implement timeout properly 52 thread_cond_wait(cond, mutex); 53 return timeout; 54} 55 56 57static void *last_locker = NULL, *last_user = NULL; 58struct thread_mutex *lwip_mutex; 59 60void lwip_mutex_lock(void) 61{ 62 if (lwip_mutex != NULL) { 63 last_locker = __builtin_return_address(0); 64 thread_mutex_lock(lwip_mutex); 65 } 66} 67 68void lwip_mutex_unlock(void) 69{ 70 if (lwip_mutex != NULL) { 71 if(lwip_mutex->locked == 0) { 72 printf("mutex NOT locked, called %p, last %p, locked by %p\n", __builtin_return_address(0), last_user, last_locker); 73 } else { 74 last_user = __builtin_return_address(0); 75 } 76 thread_mutex_unlock(lwip_mutex); 77 } 78} 79 80 81#if SYS_LIGHTWEIGHT_PROT 82static struct thread_mutex lock = THREAD_MUTEX_INITIALIZER; 83 84sys_prot_t sys_arch_protect(void) 85{ 86 thread_mutex_lock(&lock); 87 return 0; 88} 89 90void sys_arch_unprotect(sys_prot_t pval) 91{ 92 // this is always true (sys_prot_t is uint8_t!) -AB 93 //if(pval >= 0) { 94 thread_mutex_unlock(&lock); 95 //} 96} 97 98#endif // SYS_LIGHTWEIGHT_PROT 99 100/* sys_init() must be called before anthing else. */ 101void sys_init(void) 102{ 103 // Nothing to do 104} 105 106 107 108// from example in http://lwip.wikia.com/wiki/Porting_for_an_OS 109struct sys_timeouts *sys_arch_timeouts(void) { 110 struct thread_wrapper *thread = lwip_system_threads; 111 struct thread *self = thread_self(); // current thread 112 113 // Search the threads list for the thread that is currently running 114 for ( ; thread != NULL; thread = thread->next) { 115 if (thread->thread == self) { 116 return &thread->timeouts; 117 } 118 } 119 120 // No match, so just return the system-wide default version 121 return &lwip_system_timeouts; 122} 123 124 125 126/* Semaphore functions. */ 127sys_sem_t sys_sem_new(u8_t count) 128{ 129 /* debug_printf("sys_sem_new(%d)\n", count); */ 130 struct thread_sem *newsem = malloc(sizeof(struct thread_sem)); 131 thread_sem_init(newsem, count); 132 return newsem; 133} 134 135void sys_sem_signal(sys_sem_t sem) 136{ 137 /* printf("sys_sem_signal\n"); */ 138 thread_sem_post(sem); 139} 140 141u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) 142{ 143 // TODO: implement timeout correctly 144 145 /* printf("sys_arch_sem_wait\n"); */ 146 147 systime_t start, end; 148 start = get_system_time(); 149 150 thread_sem_wait(sem); 151 152 end = get_system_time(); 153 154 return end - start; 155} 156 157void sys_sem_free(sys_sem_t sem) 158{ 159 free(sem); 160} 161 162 163 164 165 166u32_t sys_jiffies(void) 167{ 168 /* since power up. */ 169 assert(!"NYI"); 170 return 0; 171} 172 173/* Mailbox functions. */ 174sys_mbox_t sys_mbox_new(int size) 175{ 176 // TODO: support mailboxes of size > 1. we only support size 1 right now 177 178 // debug_printf("sys_mbox_new(%d)\n", size); 179 180 sys_mbox_t mbox; 181 mbox = (sys_mbox_t)malloc(sizeof(struct bf_sys_mbox)); 182 183 if (mbox == NULL) { 184 return SYS_MBOX_NULL; 185 } 186 mbox->msg = NULL; 187 mbox->empty = true; 188 189 thread_mutex_init(&mbox->mutex); 190 thread_cond_init(&mbox->changed_cond); 191 192// debug_printf("sys_mbox_new(%p): created of size %d\n", mbox, size); 193 return mbox; 194} 195 196void sys_mbox_post(sys_mbox_t mbox, void *msg) 197{ 198// debug_printf("sys_mbox_post(%p)\n", mbox); 199 200 // keep trying until we succeed 201 while (1) { 202 thread_mutex_lock(&mbox->mutex); 203 if (mbox->empty) { 204 mbox->msg = msg; 205 mbox->empty = false; 206 thread_mutex_unlock(&mbox->mutex); 207 thread_cond_signal(&mbox->changed_cond); 208 break; 209 } else { 210 // wait until something changes 211 thread_cond_wait(&mbox->changed_cond, &mbox->mutex); 212 thread_mutex_unlock(&mbox->mutex); 213 } 214 } 215 216// debug_printf("sys_mbox_post(%p) done\n", mbox); 217} 218 219err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg) 220{ 221// debug_printf("sys_mboxtry_post(%p)\n", mbox); 222 223 err_t err; 224 thread_mutex_lock(&mbox->mutex); 225 if (mbox->empty) { 226 mbox->msg = msg; 227 mbox->empty = false; 228 thread_cond_signal(&mbox->changed_cond); 229 err = ERR_OK; 230 } else { 231 err = ERR_MEM; 232 } 233 thread_mutex_unlock(&mbox->mutex); 234 235 return err; 236} 237 238u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) 239{ 240// debug_printf("sys_arch_mbox_fetch(%p) timeout %u\n",mbox, timeout); 241 242 u32_t time_left = timeout; 243 u32_t res; 244 245 systime_t start, end; 246 start = get_system_time(); 247 248 // keep trying until we succeed 249 while (1) { 250 if (time_left <= 0 && timeout != 0) { 251 return SYS_ARCH_TIMEOUT; 252 } 253 thread_mutex_lock(&mbox->mutex); 254 if (!mbox->empty) { 255 if (msg != NULL) { 256 *msg = mbox->msg; 257 } 258 mbox->empty = true; 259 thread_mutex_unlock(&mbox->mutex); 260 thread_cond_signal(&mbox->changed_cond); 261 break; 262 } else { 263 // wait until something changes 264 if (timeout != 0) { 265 time_left -= thread_cond_wait_timeout(&mbox->changed_cond, 266 &mbox->mutex, 267 time_left); 268 } else { 269 thread_cond_wait(&mbox->changed_cond, &mbox->mutex); 270 } 271 thread_mutex_unlock(&mbox->mutex); 272 } 273 } 274 275 end = get_system_time(); 276 277 if (timeout == 0) { 278 res = end - start; 279 } else { 280 res = timeout - time_left; 281 } 282 283// debug_printf("sys_arch_mbox_fetch(%p) done!\n", mbox); 284 return res; 285} 286 287u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) 288{ 289 // assert(!"NYI"); 290 u32_t res; 291 thread_mutex_lock(&mbox->mutex); 292 if (!mbox->empty) { 293 *msg = mbox->msg; 294 mbox->empty = true; 295 thread_cond_signal(&mbox->changed_cond); 296 res = 0; // success 297 } else { 298 res = SYS_MBOX_EMPTY; 299 } 300 thread_mutex_unlock(&mbox->mutex); 301 302 return res; 303} 304 305void sys_mbox_free(sys_mbox_t mbox) 306{ 307 assert(mbox != NULL); 308 assert(mbox->empty); 309 free(mbox); 310} 311 312// from example in http://lwip.wikia.com/wiki/Porting_for_an_OS 313sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), 314 void *arg, int stacksize, int prio) 315{ 316 sys_thread_t newthread; 317 SYS_ARCH_DECL_PROTECT(old_val); 318 319// debug_printf("sys_thread_new(%s, %p, %p)\n", name, thread, arg); 320 321 // TODO: this has to get free'd when the thread terminates 322 newthread = (sys_thread_t)malloc(sizeof(struct thread_wrapper)); 323 if (newthread == NULL) { 324 return NULL; 325 } 326 327 // Need to protect this -- preemption here could be a problem! 328 SYS_ARCH_PROTECT(old_val); 329 newthread->next = lwip_system_threads; 330 lwip_system_threads = newthread; 331 SYS_ARCH_UNPROTECT(old_val); 332 333 newthread->timeouts.next = NULL; // initialize the linked list to NULL 334 335 // TODO: do something with the rest of the arguments (name, stacksize, prio) 336 newthread->thread = thread_create((thread_func_t)thread, arg); 337 if (newthread->thread == NULL) { 338 SYS_ARCH_PROTECT(old_val); 339 lwip_system_threads = newthread->next; 340 SYS_ARCH_UNPROTECT(old_val); 341 free(newthread); 342 newthread = NULL; 343 } 344 345 return newthread; 346} 347#endif 348