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 timeval starttime;
66 static struct sys_thread *threads = NULL;
67 static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER;
70 struct sys_mbox_msg *next;
74 #define SYS_MBOX_SIZE 128
78 void *msgs[SYS_MBOX_SIZE];
79 struct sys_sem *not_empty;
80 struct sys_sem *not_full;
81 struct sys_sem *mutex;
88 pthread_mutex_t mutex;
92 struct sys_thread *next;
96 #if SYS_LIGHTWEIGHT_PROT
97 static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER;
98 static pthread_t lwprot_thread = (pthread_t)0xDEAD;
99 static int lwprot_count = 0;
100 #endif /* SYS_LIGHTWEIGHT_PROT */
102 static struct sys_sem *sys_sem_new_internal(u8_t count);
103 static void sys_sem_free_internal(struct sys_sem *sem);
105 static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex,
108 /*-----------------------------------------------------------------------------------*/
109 static struct sys_thread *
110 introduce_thread(pthread_t id)
112 struct sys_thread *thread;
114 thread = (struct sys_thread *)malloc(sizeof(struct sys_thread));
116 if (thread != NULL) {
117 pthread_mutex_lock(&threads_mutex);
118 thread->next = threads;
119 thread->pthread = id;
121 pthread_mutex_unlock(&threads_mutex);
126 /*-----------------------------------------------------------------------------------*/
128 sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
132 struct sys_thread *st = NULL;
133 LWIP_UNUSED_ARG(name);
134 LWIP_UNUSED_ARG(stacksize);
135 LWIP_UNUSED_ARG(prio);
137 code = pthread_create(&tmp,
144 st = introduce_thread(tmp);
148 LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%lx",
149 code, (unsigned long)st));
154 /*-----------------------------------------------------------------------------------*/
156 sys_mbox_new(struct sys_mbox **mb, int size)
158 struct sys_mbox *mbox;
159 LWIP_UNUSED_ARG(size);
161 mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox));
165 mbox->first = mbox->last = 0;
166 mbox->not_empty = sys_sem_new_internal(0);
167 mbox->not_full = sys_sem_new_internal(0);
168 mbox->mutex = sys_sem_new_internal(1);
171 SYS_STATS_INC_USED(mbox);
175 /*-----------------------------------------------------------------------------------*/
177 sys_mbox_free(struct sys_mbox **mb)
179 if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) {
180 struct sys_mbox *mbox = *mb;
181 SYS_STATS_DEC(mbox.used);
182 sys_arch_sem_wait(&mbox->mutex, 0);
184 sys_sem_free_internal(mbox->not_empty);
185 sys_sem_free_internal(mbox->not_full);
186 sys_sem_free_internal(mbox->mutex);
187 mbox->not_empty = mbox->not_full = mbox->mutex = NULL;
188 /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
192 /*-----------------------------------------------------------------------------------*/
194 sys_mbox_trypost(struct sys_mbox **mb, void *msg)
197 struct sys_mbox *mbox;
198 LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
201 sys_arch_sem_wait(&mbox->mutex, 0);
203 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
204 (void *)mbox, (void *)msg));
206 if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
207 sys_sem_signal(&mbox->mutex);
211 mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
213 if (mbox->last == mbox->first) {
222 sys_sem_signal(&mbox->not_empty);
225 sys_sem_signal(&mbox->mutex);
229 /*-----------------------------------------------------------------------------------*/
231 sys_mbox_post(struct sys_mbox **mb, void *msg)
234 struct sys_mbox *mbox;
235 LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
238 sys_arch_sem_wait(&mbox->mutex, 0);
240 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
242 while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
244 sys_sem_signal(&mbox->mutex);
245 sys_arch_sem_wait(&mbox->not_full, 0);
246 sys_arch_sem_wait(&mbox->mutex, 0);
250 mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
252 if (mbox->last == mbox->first) {
261 sys_sem_signal(&mbox->not_empty);
264 sys_sem_signal(&mbox->mutex);
266 /*-----------------------------------------------------------------------------------*/
268 sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg)
270 struct sys_mbox *mbox;
271 LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
274 sys_arch_sem_wait(&mbox->mutex, 0);
276 if (mbox->first == mbox->last) {
277 sys_sem_signal(&mbox->mutex);
278 return SYS_MBOX_EMPTY;
282 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
283 *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
286 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
291 if (mbox->wait_send) {
292 sys_sem_signal(&mbox->not_full);
295 sys_sem_signal(&mbox->mutex);
299 /*-----------------------------------------------------------------------------------*/
301 sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, u32_t timeout)
303 u32_t time_needed = 0;
304 struct sys_mbox *mbox;
305 LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
308 /* The mutex lock is quick so we don't bother with the timeout
310 sys_arch_sem_wait(&mbox->mutex, 0);
312 while (mbox->first == mbox->last) {
313 sys_sem_signal(&mbox->mutex);
315 /* We block while waiting for a mail to arrive in the mailbox. We
316 must be prepared to timeout. */
318 time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout);
320 if (time_needed == SYS_ARCH_TIMEOUT) {
321 return SYS_ARCH_TIMEOUT;
324 sys_arch_sem_wait(&mbox->not_empty, 0);
327 sys_arch_sem_wait(&mbox->mutex, 0);
331 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
332 *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
335 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
340 if (mbox->wait_send) {
341 sys_sem_signal(&mbox->not_full);
344 sys_sem_signal(&mbox->mutex);
348 /*-----------------------------------------------------------------------------------*/
349 static struct sys_sem *
350 sys_sem_new_internal(u8_t count)
354 sem = (struct sys_sem *)malloc(sizeof(struct sys_sem));
357 pthread_cond_init(&(sem->cond), NULL);
358 pthread_mutex_init(&(sem->mutex), NULL);
362 /*-----------------------------------------------------------------------------------*/
364 sys_sem_new(struct sys_sem **sem, u8_t count)
366 SYS_STATS_INC_USED(sem);
367 *sem = sys_sem_new_internal(count);
373 /*-----------------------------------------------------------------------------------*/
375 cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout)
378 unsigned long sec, usec;
379 struct timeval rtime1, rtime2;
384 /* Get a timestamp and add the timeout value. */
385 gettimeofday(&rtime1, NULL);
387 usec = rtime1.tv_usec;
388 usec += timeout % 1000 * 1000;
389 sec += (int)(timeout / 1000) + (int)(usec / 1000000);
390 usec = usec % 1000000;
391 ts.tv_nsec = usec * 1000;
394 retval = pthread_cond_timedwait(cond, mutex, &ts);
396 if (retval == ETIMEDOUT) {
397 return SYS_ARCH_TIMEOUT;
399 /* Calculate for how long we waited for the cond. */
400 gettimeofday(&rtime2, NULL);
401 tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +
402 (rtime2.tv_usec - rtime1.tv_usec) / 1000;
411 pthread_cond_wait(cond, mutex);
412 return SYS_ARCH_TIMEOUT;
415 /*-----------------------------------------------------------------------------------*/
417 sys_arch_sem_wait(struct sys_sem **s, u32_t timeout)
419 u32_t time_needed = 0;
421 LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL));
424 pthread_mutex_lock(&(sem->mutex));
425 while (sem->c <= 0) {
427 time_needed = cond_wait(&(sem->cond), &(sem->mutex), timeout);
429 if (time_needed == SYS_ARCH_TIMEOUT) {
430 pthread_mutex_unlock(&(sem->mutex));
431 return SYS_ARCH_TIMEOUT;
433 /* pthread_mutex_unlock(&(sem->mutex));
434 return time_needed; */
436 cond_wait(&(sem->cond), &(sem->mutex), 0);
440 pthread_mutex_unlock(&(sem->mutex));
443 /*-----------------------------------------------------------------------------------*/
445 sys_sem_signal(struct sys_sem **s)
448 LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL));
451 pthread_mutex_lock(&(sem->mutex));
458 pthread_cond_broadcast(&(sem->cond));
459 pthread_mutex_unlock(&(sem->mutex));
461 /*-----------------------------------------------------------------------------------*/
463 sys_sem_free_internal(struct sys_sem *sem)
465 pthread_cond_destroy(&(sem->cond));
466 pthread_mutex_destroy(&(sem->mutex));
469 /*-----------------------------------------------------------------------------------*/
471 sys_sem_free(struct sys_sem **sem)
473 if ((sem != NULL) && (*sem != SYS_SEM_NULL)) {
474 SYS_STATS_DEC(sem.used);
475 sys_sem_free_internal(*sem);
479 /*-----------------------------------------------------------------------------------*/
484 u32_t sec, usec, msec;
485 gettimeofday(&tv, NULL);
487 sec = (u32_t)(tv.tv_sec - starttime.tv_sec);
488 usec = (u32_t)(tv.tv_usec - starttime.tv_usec);
489 msec = sec * 1000 + usec / 1000;
493 /*-----------------------------------------------------------------------------------*/
497 gettimeofday(&starttime, NULL);
499 /*-----------------------------------------------------------------------------------*/
500 #if SYS_LIGHTWEIGHT_PROT
501 /** sys_prot_t sys_arch_protect(void)
503 This optional function does a "fast" critical region protection and returns
504 the previous protection level. This function is only called during very short
505 critical regions. An embedded system which supports ISR-based drivers might
506 want to implement this function by disabling interrupts. Task-based systems
507 might want to implement this by using a mutex or disabling tasking. This
508 function should support recursive calls from the same task or interrupt. In
509 other words, sys_arch_protect() could be called while already protected. In
510 that case the return value indicates that it is already protected.
512 sys_arch_protect() is only required if your port is supporting an operating
516 sys_arch_protect(void)
518 /* Note that for the UNIX port, we are using a lightweight mutex, and our
519 * own counter (which is locked by the mutex). The return code is not actually
521 if (lwprot_thread != pthread_self())
523 /* We are locking the mutex where it has not been locked before *
524 * or is being locked by another thread */
525 pthread_mutex_lock(&lwprot_mutex);
526 lwprot_thread = pthread_self();
530 /* It is already locked by THIS thread */
534 /*-----------------------------------------------------------------------------------*/
535 /** void sys_arch_unprotect(sys_prot_t pval)
537 This optional function does a "fast" set of critical region protection to the
538 value specified by pval. See the documentation for sys_arch_protect() for
539 more information. This function is only required if your port is supporting
543 sys_arch_unprotect(sys_prot_t pval)
545 LWIP_UNUSED_ARG(pval);
546 if (lwprot_thread == pthread_self())
548 if (--lwprot_count == 0)
550 lwprot_thread = (pthread_t) 0xDEAD;
551 pthread_mutex_unlock(&lwprot_mutex);
555 #endif /* SYS_LIGHTWEIGHT_PROT */
557 /*-----------------------------------------------------------------------------------*/
559 #ifndef MAX_JIFFY_OFFSET
560 #define MAX_JIFFY_OFFSET ((~0U >> 1)-1)
574 gettimeofday(&tv,NULL);
575 sec = tv.tv_sec - starttime.tv_sec;
578 if (sec >= (MAX_JIFFY_OFFSET / HZ))
579 return MAX_JIFFY_OFFSET;
580 usec += 1000000L / HZ - 1;
581 usec /= 1000000L / HZ;
582 return HZ * sec + usec;
589 void ppp_trace(int level, const char *format, ...)
594 va_start(args, format);
595 vprintf(format, args);