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
47 #include "lwip/debug.h"
51 #include <sys/types.h>
58 #include "lwip/stats.h"
60 #define UMAX(a, b) ((a) > (b) ? (a) : (b))
62 static struct sys_thread *threads = NULL;
63 static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER;
66 struct sys_mbox_msg *next;
70 #define SYS_MBOX_SIZE 128
74 void *msgs[SYS_MBOX_SIZE];
76 struct sys_sem *mutex;
83 pthread_mutex_t mutex;
87 struct sys_thread *next;
88 struct sys_timeouts timeouts;
93 static struct timeval starttime;
95 static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER;
96 static pthread_t lwprot_thread = (pthread_t) 0xDEAD;
97 static int lwprot_count = 0;
99 static struct sys_sem *sys_sem_new_(u8_t count);
100 static void sys_sem_free_(struct sys_sem *sem);
102 static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex,
105 /*-----------------------------------------------------------------------------------*/
106 static struct sys_thread *
107 introduce_thread(pthread_t id)
109 struct sys_thread *thread;
111 thread = malloc(sizeof(struct sys_thread));
113 if (thread != NULL) {
114 pthread_mutex_lock(&threads_mutex);
115 thread->next = threads;
116 thread->timeouts.next = NULL;
117 thread->pthread = id;
119 pthread_mutex_unlock(&threads_mutex);
124 /*-----------------------------------------------------------------------------------*/
125 static struct sys_thread *
128 struct sys_thread *st;
131 pthread_mutex_lock(&threads_mutex);
133 for(st = threads; st != NULL; st = st->next) {
134 if (pthread_equal(st->pthread, pt)) {
135 pthread_mutex_unlock(&threads_mutex);
141 pthread_mutex_unlock(&threads_mutex);
143 st = introduce_thread(pt);
146 printf("current_thread???\n");
152 /*-----------------------------------------------------------------------------------*/
154 sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
158 struct sys_thread *st = NULL;
160 code = pthread_create(&tmp,
167 st = introduce_thread(tmp);
171 LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%x",
177 /*-----------------------------------------------------------------------------------*/
179 sys_mbox_new(int size)
181 struct sys_mbox *mbox;
183 mbox = malloc(sizeof(struct sys_mbox));
185 mbox->first = mbox->last = 0;
186 mbox->mail = sys_sem_new_(0);
187 mbox->mutex = sys_sem_new_(1);
191 lwip_stats.sys.mbox.used++;
192 if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max) {
193 lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
195 #endif /* SYS_STATS */
199 /*-----------------------------------------------------------------------------------*/
201 sys_mbox_free(struct sys_mbox *mbox)
203 if (mbox != SYS_MBOX_NULL) {
205 lwip_stats.sys.mbox.used--;
206 #endif /* SYS_STATS */
207 sys_sem_wait(mbox->mutex);
209 sys_sem_free_(mbox->mail);
210 sys_sem_free_(mbox->mutex);
211 mbox->mail = mbox->mutex = NULL;
212 /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
216 /*-----------------------------------------------------------------------------------*/
218 sys_mbox_trypost(struct sys_mbox *mbox, void *msg)
222 sys_sem_wait(mbox->mutex);
224 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
225 (void *)mbox, (void *)msg));
227 if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE))
230 mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
232 if (mbox->last == mbox->first) {
241 sys_sem_signal(mbox->mail);
244 sys_sem_signal(mbox->mutex);
248 /*-----------------------------------------------------------------------------------*/
250 sys_mbox_post(struct sys_mbox *mbox, void *msg)
254 sys_sem_wait(mbox->mutex);
256 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
258 while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
260 sys_sem_signal(mbox->mutex);
261 sys_arch_sem_wait(mbox->mail, 0);
262 sys_arch_sem_wait(mbox->mutex, 0);
266 mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
268 if (mbox->last == mbox->first) {
277 sys_sem_signal(mbox->mail);
280 sys_sem_signal(mbox->mutex);
282 /*-----------------------------------------------------------------------------------*/
284 sys_arch_mbox_tryfetch(struct sys_mbox *mbox, void **msg)
286 sys_arch_sem_wait(mbox->mutex, 0);
288 if (mbox->first == mbox->last) {
289 sys_sem_signal(mbox->mutex);
290 return SYS_MBOX_EMPTY;
294 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
295 *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
298 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
303 if (mbox->wait_send) {
304 sys_sem_signal(mbox->mail);
307 sys_sem_signal(mbox->mutex);
311 /*-----------------------------------------------------------------------------------*/
313 sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u32_t timeout)
317 /* The mutex lock is quick so we don't bother with the timeout
319 sys_arch_sem_wait(mbox->mutex, 0);
321 while (mbox->first == mbox->last) {
322 sys_sem_signal(mbox->mutex);
324 /* We block while waiting for a mail to arrive in the mailbox. We
325 must be prepared to timeout. */
327 time = sys_arch_sem_wait(mbox->mail, timeout);
329 if (time == SYS_ARCH_TIMEOUT) {
330 return SYS_ARCH_TIMEOUT;
333 sys_arch_sem_wait(mbox->mail, 0);
336 sys_arch_sem_wait(mbox->mutex, 0);
340 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
341 *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
344 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
349 if (mbox->wait_send) {
350 sys_sem_signal(mbox->mail);
353 sys_sem_signal(mbox->mutex);
357 /*-----------------------------------------------------------------------------------*/
359 sys_sem_new(u8_t count)
362 lwip_stats.sys.sem.used++;
363 if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) {
364 lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
366 #endif /* SYS_STATS */
367 return sys_sem_new_(count);
370 /*-----------------------------------------------------------------------------------*/
371 static struct sys_sem *
372 sys_sem_new_(u8_t count)
376 sem = malloc(sizeof(struct sys_sem));
379 pthread_cond_init(&(sem->cond), NULL);
380 pthread_mutex_init(&(sem->mutex), NULL);
385 /*-----------------------------------------------------------------------------------*/
387 cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout)
390 unsigned long sec, usec;
391 struct timeval rtime1, rtime2;
397 /* Get a timestamp and add the timeout value. */
398 gettimeofday(&rtime1, &tz);
400 usec = rtime1.tv_usec;
401 usec += timeout % 1000 * 1000;
402 sec += (int)(timeout / 1000) + (int)(usec / 1000000);
403 usec = usec % 1000000;
404 ts.tv_nsec = usec * 1000;
407 retval = pthread_cond_timedwait(cond, mutex, &ts);
409 if (retval == ETIMEDOUT) {
410 return SYS_ARCH_TIMEOUT;
412 /* Calculate for how long we waited for the cond. */
413 gettimeofday(&rtime2, &tz);
414 tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +
415 (rtime2.tv_usec - rtime1.tv_usec) / 1000;
424 pthread_cond_wait(cond, mutex);
425 return SYS_ARCH_TIMEOUT;
428 /*-----------------------------------------------------------------------------------*/
430 sys_arch_sem_wait(struct sys_sem *sem, u32_t timeout)
434 pthread_mutex_lock(&(sem->mutex));
435 while (sem->c <= 0) {
437 time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
439 if (time == SYS_ARCH_TIMEOUT) {
440 pthread_mutex_unlock(&(sem->mutex));
441 return SYS_ARCH_TIMEOUT;
443 /* pthread_mutex_unlock(&(sem->mutex));
446 cond_wait(&(sem->cond), &(sem->mutex), 0);
450 pthread_mutex_unlock(&(sem->mutex));
453 /*-----------------------------------------------------------------------------------*/
455 sys_sem_signal(struct sys_sem *sem)
457 pthread_mutex_lock(&(sem->mutex));
464 pthread_cond_broadcast(&(sem->cond));
465 pthread_mutex_unlock(&(sem->mutex));
467 /*-----------------------------------------------------------------------------------*/
469 sys_sem_free(struct sys_sem *sem)
471 if (sem != SYS_SEM_NULL) {
473 lwip_stats.sys.sem.used--;
474 #endif /* SYS_STATS */
479 /*-----------------------------------------------------------------------------------*/
481 sys_sem_free_(struct sys_sem *sem)
483 pthread_cond_destroy(&(sem->cond));
484 pthread_mutex_destroy(&(sem->mutex));
487 /*-----------------------------------------------------------------------------------*/
495 gettimeofday(&tv, &tz);
497 sec = tv.tv_sec - starttime.tv_sec;
498 usec = tv.tv_usec - starttime.tv_usec;
499 msec = sec * 1000 + usec / 1000;
503 /*-----------------------------------------------------------------------------------*/
508 gettimeofday(&starttime, &tz);
510 /*-----------------------------------------------------------------------------------*/
511 struct sys_timeouts *
512 sys_arch_timeouts(void)
514 struct sys_thread *thread;
516 thread = current_thread();
517 return &thread->timeouts;
519 /*-----------------------------------------------------------------------------------*/
520 /** sys_prot_t sys_arch_protect(void)
522 This optional function does a "fast" critical region protection and returns
523 the previous protection level. This function is only called during very short
524 critical regions. An embedded system which supports ISR-based drivers might
525 want to implement this function by disabling interrupts. Task-based systems
526 might want to implement this by using a mutex or disabling tasking. This
527 function should support recursive calls from the same task or interrupt. In
528 other words, sys_arch_protect() could be called while already protected. In
529 that case the return value indicates that it is already protected.
531 sys_arch_protect() is only required if your port is supporting an operating
535 sys_arch_protect(void)
537 /* Note that for the UNIX port, we are using a lightweight mutex, and our
538 * own counter (which is locked by the mutex). The return code is not actually
540 if (lwprot_thread != pthread_self())
542 /* We are locking the mutex where it has not been locked before *
543 * or is being locked by another thread */
544 pthread_mutex_lock(&lwprot_mutex);
545 lwprot_thread = pthread_self();
549 /* It is already locked by THIS thread */
553 /*-----------------------------------------------------------------------------------*/
554 /** void sys_arch_unprotect(sys_prot_t pval)
556 This optional function does a "fast" set of critical region protection to the
557 value specified by pval. See the documentation for sys_arch_protect() for
558 more information. This function is only required if your port is supporting
562 sys_arch_unprotect(sys_prot_t pval)
564 if (lwprot_thread == pthread_self())
566 if (--lwprot_count == 0)
568 lwprot_thread = (pthread_t) 0xDEAD;
569 pthread_mutex_unlock(&lwprot_mutex);
574 /*-----------------------------------------------------------------------------------*/
576 #ifndef MAX_JIFFY_OFFSET
577 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
588 unsigned long sec = tv.tv_sec;
589 long usec = tv.tv_usec;
591 gettimeofday(&tv,NULL);
593 if (sec >= (MAX_JIFFY_OFFSET / HZ))
594 return MAX_JIFFY_OFFSET;
595 usec += 1000000L / HZ - 1;
596 usec /= 1000000L / HZ;
597 return HZ * sec + usec;
604 void ppp_trace(int level, const char *format, ...)
609 va_start(args, format);
610 vprintf(format, args);