2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
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.
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
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
34 * Wed Apr 17 16:05:29 EDT 2002 (James Roth)
36 * - Fixed an unlikely sys_thread_new() race condition.
38 * - Made current_thread() work with threads which where
39 * not created with sys_thread_new(). This includes
40 * the main thread and threads made with pthread_create().
42 * - Catch overflows where more than SYS_MBOX_SIZE messages
43 * are waiting to be read. The sys_mbox_post() routine
44 * will block until there is more room instead of just
48 * Modified by Lei Xia (lxia@northwestern.edu) to fit to Palacios, 9/29/2008
50 #include "lwip/debug.h"
54 //#include <palacios/vmm.h>
55 #include <geekos/synch.h>
56 #include <geekos/kthread.h>
57 #include <geekos/debug.h>
58 #include <geekos/timer.h>
59 #include <geekos/malloc.h>
63 #include "lwip/stats.h"
65 #define UMAX(a, b) ((a) > (b) ? (a) : (b))
67 static struct sys_thread *threads = NULL;
69 //static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER;
70 static struct Mutex threads_mutex; // !!!! need to be initiated, void Mutex_Init(struct Mutex* mutex);
73 struct sys_mbox_msg *next;
77 #define SYS_MBOX_SIZE 128
81 void *msgs[SYS_MBOX_SIZE];
83 struct sys_sem *mutex;
90 //pthread_cond_t cond;
91 struct Condition cond;
93 //pthread_mutex_t mutex;
98 struct sys_thread *next;
99 struct sys_timeouts timeouts;
101 // pthread_t pthread;
102 struct Kernel_Thread *pthread;
106 //static struct timeval starttime;
108 //static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER;
109 static struct Mutex lwprot_mutex; // !!!! need to be initiated, void Mutex_Init(struct Mutex* mutex);
111 //static pthread_t lwprot_thread = (pthread_t) 0xDEAD;
112 //static struct Kernel_Thread lwprot_thread = (struct Kernel_Thread) 0xDEAD; //!!!!! how to set it to a NULL thread?
114 //static int lwprot_count = 0;
116 static struct sys_sem *sys_sem_new_(u8_t count);
117 static void sys_sem_free_(struct sys_sem *sem);
119 static u32_t cond_wait(struct Condition *cond, struct Mutex *mutex, u32_t timeout);
122 /*-----------------------------------------------------------------------------------*/
123 static struct sys_thread *
124 introduce_thread(struct Kernel_Thread *id /*pthread_t id*/)
126 struct sys_thread *thread;
128 thread = (struct sys_thread *)Malloc(sizeof(struct sys_thread));
130 if (thread != NULL) {
131 //pthread_mutex_lock(&threads_mutex);
132 Mutex_Lock(&threads_mutex);
134 thread->next = threads;
135 thread->timeouts.next = NULL;
136 thread->pthread = id;
139 //pthread_mutex_unlock(&threads_mutex);
140 Mutex_Unlock(&threads_mutex);
146 static int thread_equal(struct Kernel_Thread *kth1, struct Kernel_Thread *kth2){ //added
148 return (kth1->pid == kth2->pid);
152 /*-----------------------------------------------------------------------------------*/
153 static struct sys_thread *
156 struct sys_thread *st;
159 struct Kernel_Thread *pt;
161 //pt = pthread_self();
162 //!!!!!!!!!!!Do these have the same means? Not sure
165 //pthread_mutex_lock(&threads_mutex);
166 Mutex_Lock(&threads_mutex);
168 for(st = threads; st != NULL; st = st->next) {
169 if (thread_equal(st->pthread, pt)) {
170 //pthread_mutex_unlock(&threads_mutex);
171 Mutex_Unlock(&threads_mutex);
177 //pthread_mutex_unlock(&threads_mutex);
178 Mutex_Unlock(&threads_mutex);
180 st = introduce_thread(pt);
183 PrintBoth("lwIP error: In current_thread: Can not get current_thread\n");
191 /*-----------------------------------------------------------------------------------*/
193 sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
197 struct Kernel_Thread *tmp;
198 struct sys_thread *st = NULL;
200 //tmp = (struct Kernel_Thread *)Malloc(sizeof(struct Kernel_Thread));
202 /* code = pthread_create(&tmp,
208 tmp = Start_Kernel_Thread(function, arg, PRIORITY_NORMAL , false); //did not consider the priority here
211 st = introduce_thread(tmp);
215 LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create: 0x%x, st = 0x%x",
223 /*-----------------------------------------------------------------------------------*/
225 sys_mbox_new(int size)
227 struct sys_mbox *mbox;
229 mbox = (struct sys_mbox *)Malloc(sizeof(struct sys_mbox));
231 mbox->first = mbox->last = 0;
232 mbox->mail = sys_sem_new_(0);
233 mbox->mutex = sys_sem_new_(1);
237 lwip_stats.sys.mbox.used++;
238 if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max) {
239 lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
241 #endif /* SYS_STATS */
245 /*-----------------------------------------------------------------------------------*/
247 sys_mbox_free(struct sys_mbox *mbox)
249 if (mbox != SYS_MBOX_NULL) {
251 lwip_stats.sys.mbox.used--;
252 #endif /* SYS_STATS */
253 sys_sem_wait(mbox->mutex);
255 sys_sem_free_(mbox->mail);
256 sys_sem_free_(mbox->mutex);
257 mbox->mail = mbox->mutex = NULL;
258 /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
263 /*-----------------------------------------------------------------------------------*/
265 sys_mbox_trypost(struct sys_mbox *mbox, void *msg)
269 sys_sem_wait(mbox->mutex);
271 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
272 (void *)mbox, (void *)msg));
274 if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE))
277 mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
279 if (mbox->last == mbox->first) {
288 sys_sem_signal(mbox->mail);
291 sys_sem_signal(mbox->mutex);
295 /*-----------------------------------------------------------------------------------*/
297 sys_mbox_post(struct sys_mbox *mbox, void *msg)
301 sys_sem_wait(mbox->mutex);
303 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
305 while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
307 sys_sem_signal(mbox->mutex);
308 sys_arch_sem_wait(mbox->mail, 0);
309 sys_arch_sem_wait(mbox->mutex, 0);
313 mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
315 if (mbox->last == mbox->first) {
324 sys_sem_signal(mbox->mail);
327 sys_sem_signal(mbox->mutex);
329 /*-----------------------------------------------------------------------------------*/
331 sys_arch_mbox_tryfetch(struct sys_mbox *mbox, void **msg)
333 sys_arch_sem_wait(mbox->mutex, 0);
335 if (mbox->first == mbox->last) {
336 sys_sem_signal(mbox->mutex);
337 return SYS_MBOX_EMPTY;
341 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
342 *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
345 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
350 if (mbox->wait_send) {
351 sys_sem_signal(mbox->mail);
354 sys_sem_signal(mbox->mutex);
358 /*-----------------------------------------------------------------------------------*/
360 sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u32_t timeout)
364 /* The mutex lock is quick so we don't bother with the timeout
366 sys_arch_sem_wait(mbox->mutex, 0);
368 while (mbox->first == mbox->last) {
369 sys_sem_signal(mbox->mutex);
371 /* We block while waiting for a mail to arrive in the mailbox. We
372 must be prepared to timeout. */
374 time = sys_arch_sem_wait(mbox->mail, timeout);
376 if (time == SYS_ARCH_TIMEOUT) {
377 return SYS_ARCH_TIMEOUT;
380 sys_arch_sem_wait(mbox->mail, 0);
383 sys_arch_sem_wait(mbox->mutex, 0);
387 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
388 *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
391 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
396 if (mbox->wait_send) {
397 sys_sem_signal(mbox->mail);
400 sys_sem_signal(mbox->mutex);
404 /*-----------------------------------------------------------------------------------*/
406 sys_sem_new(u8_t count)
409 lwip_stats.sys.sem.used++;
410 if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) {
411 lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
413 #endif /* SYS_STATS */
414 return sys_sem_new_(count);
417 /*-----------------------------------------------------------------------------------*/
418 static struct sys_sem *
419 sys_sem_new_(u8_t count)
423 sem = (struct sys_sem *)Malloc(sizeof(struct sys_sem));
427 //pthread_cond_init(&(sem->cond), NULL);
428 Cond_Init(&(sem->cond));
430 //pthread_mutex_init(&(sem->mutex), NULL);
431 Mutex_Init(&(sem->mutex));
437 /*-----------------------------------------------------------------------------------*/
439 cond_wait(struct Condition *cond, struct Mutex *mutex, u32_t timeout /* timeout is in miliseconds *//* pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout */)
444 struct timeval rtime1, rtime2;
452 /* Get a timestamp and add the timeout value. */
453 /*gettimeofday(&rtime1, &tz);
455 usec = rtime1.tv_usec;
456 usec += timeout % 1000 * 1000;
457 sec += (int)(timeout / 1000) + (int)(usec / 1000000);
458 usec = usec % 1000000;
459 ts.tv_nsec = usec * 1000;
464 if (Cond_Wait_Timeout(cond, mutex, timeout) == 1) //return due to timeout
467 //retval = pthread_cond_timedwait(cond, mutex, &ts);
469 if (retval == ETIMEDOUT) {
470 return SYS_ARCH_TIMEOUT;
472 /* Calculate for how long we waited for the cond. */
475 gettimeofday(&rtime2, &tz);
476 tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +
477 (rtime2.tv_usec - rtime1.tv_usec) / 1000;
479 tdiff = clock_time();
490 //pthread_cond_wait(cond, mutex);
491 Cond_Wait(cond, mutex);
493 return SYS_ARCH_TIMEOUT;
496 /*-----------------------------------------------------------------------------------*/
498 sys_arch_sem_wait(struct sys_sem *sem, u32_t timeout)
502 //pthread_mutex_lock(&(sem->mutex));
503 Mutex_Lock(&(sem->mutex));
505 while (sem->c <= 0) {
507 time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
509 if (time == SYS_ARCH_TIMEOUT) {
510 //pthread_mutex_unlock(&(sem->mutex));
511 Mutex_Unlock(&(sem->mutex));
513 return SYS_ARCH_TIMEOUT;
515 /* pthread_mutex_unlock(&(sem->mutex));
517 } else { // if timeout = 0
518 cond_wait(&(sem->cond), &(sem->mutex), 0);
522 //pthread_mutex_unlock(&(sem->mutex));
523 Mutex_Unlock(&(sem->mutex));
527 /*-----------------------------------------------------------------------------------*/
529 sys_sem_signal(struct sys_sem *sem)
531 //pthread_mutex_lock(&(sem->mutex));
532 Mutex_Lock(&(sem->mutex));
540 //pthread_cond_broadcast(&(sem->cond));
541 Cond_Broadcast(&(sem->cond));
543 //pthread_mutex_unlock(&(sem->mutex));
544 Mutex_Unlock(&(sem->mutex));
547 /*-----------------------------------------------------------------------------------*/
549 sys_sem_free(struct sys_sem *sem)
551 if (sem != SYS_SEM_NULL) {
553 lwip_stats.sys.sem.used--;
554 #endif /* SYS_STATS */
559 /*-----------------------------------------------------------------------------------*/
561 sys_sem_free_(struct sys_sem *sem)
563 //pthread_cond_destroy(&(sem->cond));
564 Cond_Destroy(&(sem->cond));
566 //pthread_mutex_destroy(&(sem->mutex));
567 Mutex_Destroy(&(sem->mutex));
573 //return time, we do not need this
574 /*-----------------------------------------------------------------------------------*/
582 gettimeofday(&tv, &tz);
584 sec = tv.tv_sec - starttime.tv_sec;
585 usec = tv.tv_usec - starttime.tv_usec;
586 msec = sec * 1000 + usec / 1000;
592 /*-----------------------------------------------------------------------------------*/
596 //struct timezone tz;
597 //gettimeofday(&starttime, &tz);
599 Mutex_Init(&threads_mutex);
600 Mutex_Init(&lwprot_mutex);
603 /*-----------------------------------------------------------------------------------*/
604 struct sys_timeouts *
605 sys_arch_timeouts(void)
607 struct sys_thread *thread;
609 thread = current_thread();
610 return &thread->timeouts;
614 /*-----------------------------------------------------------------------------------*/
615 /** sys_prot_t sys_arch_protect(void)
617 This optional function does a "fast" critical region protection and returns
618 the previous protection level. This function is only called during very short
619 critical regions. An embedded system which supports ISR-based drivers might
620 want to implement this function by disabling interrupts. Task-based systems
621 might want to implement this by using a mutex or disabling tasking. This
622 function should support recursive calls from the same task or interrupt. In
623 other words, sys_arch_protect() could be called while already protected. In
624 that case the return value indicates that it is already protected.
626 sys_arch_protect() is only required if your port is supporting an operating
632 sys_arch_protect(void)
634 /* Note that for the UNIX port, we are using a lightweight mutex, and our
635 * own counter (which is locked by the mutex). The return code is not actually
637 if (lwprot_thread != current_thread() /*lwprot_thread != pthread_self()*/)
639 /* We are locking the mutex where it has not been locked before *
640 * or is being locked by another thread */
641 Mutex_Lock(&lwprot_mutex);
642 lwprot_thread = current_thread();
646 /* It is already locked by THIS thread */
650 /*-----------------------------------------------------------------------------------*/
651 /** void sys_arch_unprotect(sys_prot_t pval)
653 This optional function does a "fast" set of critical region protection to the
654 value specified by pval. See the documentation for sys_arch_protect() for
655 more information. This function is only required if your port is supporting
659 sys_arch_unprotect(sys_prot_t pval)
661 if (lwprot_thread == current_thread())
663 if (--lwprot_count == 0)
665 lwprot_thread = (struc Kernel_Thread) 0xDEAD;
666 Mutex_Unlock(&lwprot_mutex);
672 /*-----------------------------------------------------------------------------------*/
674 #ifndef MAX_JIFFY_OFFSET
675 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
687 unsigned long sec = tv.tv_sec;
688 long usec = tv.tv_usec;
690 gettimeofday(&tv,NULL);
692 if (sec >= (MAX_JIFFY_OFFSET / HZ))
693 return MAX_JIFFY_OFFSET;
694 usec += 1000000L / HZ - 1;
695 usec /= 1000000L / HZ;
696 return HZ * sec + usec;
702 #include <geekos/serial.h>
704 void ppp_trace(int level, const char *format, ...)
709 va_start(args, format);
711 //vprintf(format, args);
712 PrintDebug(format, args);