Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added new copyright and license
[palacios.git] / palacios / src / lwip / arch / 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 /*
34  * Wed Apr 17 16:05:29 EDT 2002 (James Roth)
35  *
36  *  - Fixed an unlikely sys_thread_new() race condition.
37  *
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().
41  *
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
45  *    leaking messages.
46  */
47 #include "lwip/debug.h"
48
49 #include <string.h>
50 #include <sys/time.h>
51 #include <sys/types.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <pthread.h>
55
56 #include <geekos/synch.h>
57 #include <geekos/kthread.h>
58 #include <geekos/debug.h>
59 #include <geekos/malloc.h>
60
61 #include "lwip/sys.h"
62 #include "lwip/opt.h"
63 #include "lwip/stats.h"
64
65 #define UMAX(a, b)      ((a) > (b) ? (a) : (b))
66
67 static struct sys_thread *threads = NULL;
68
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);
71
72 struct sys_mbox_msg {
73   struct sys_mbox_msg *next;
74   void *msg;
75 };
76
77 #define SYS_MBOX_SIZE 128
78
79 struct sys_mbox {
80   int first, last;
81   void *msgs[SYS_MBOX_SIZE];
82   struct sys_sem *mail;
83   struct sys_sem *mutex;
84   int wait_send;
85 };
86
87 struct sys_sem {
88   unsigned int c;
89   
90   //pthread_cond_t cond;
91   struct Condition cond;
92   
93   //pthread_mutex_t mutex;
94   struct Mutex mutex;
95 };
96
97 struct sys_thread {
98   struct sys_thread *next;
99   struct sys_timeouts timeouts;
100   
101  // pthread_t pthread;
102   struct Kernel_Thread *pthread;
103 };
104
105
106 static struct timeval starttime;
107
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);
110
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?
113
114 static int lwprot_count = 0;
115
116 static struct sys_sem *sys_sem_new_(u8_t count);
117 static void sys_sem_free_(struct sys_sem *sem);
118
119 static u32_t cond_wait(struct Condition *cond, struct Mutex *mutex, u32_t timeout);
120
121
122 /*-----------------------------------------------------------------------------------*/
123 static struct sys_thread * 
124 introduce_thread(struct Kernel_Thread *id /*pthread_t id*/)
125 {
126   struct sys_thread *thread;
127   
128   thread = (struct sys_thread *)Malloc(sizeof(struct sys_thread)); 
129     
130   if (thread != NULL) {
131     //pthread_mutex_lock(&threads_mutex);
132     Mutex_Lock(&threads_mutex);
133         
134     thread->next = threads;
135     thread->timeouts.next = NULL;
136     thread->pthread = id;
137     threads = thread;
138
139     //pthread_mutex_unlock(&threads_mutex);
140     Mutex_Unlock(&threads_mutex);
141   }
142     
143   return thread;
144 }
145
146 static int thread_equal(struct Kernel_Thread *kth1, struct Kernel_Thread *kth2){  //added
147
148         return (kth1->pid == kth2->pid);
149
150 }
151
152 /*-----------------------------------------------------------------------------------*/
153 static struct sys_thread *
154 current_thread(void)
155 {
156   struct sys_thread *st;
157   
158   //pthread_t pt;
159   struct Kernel_Thread *pt;
160   
161   //pt = pthread_self();
162   //!!!!!!!!!!!Do these have the same means? Not sure
163   pt = Get_Current();
164   
165   //pthread_mutex_lock(&threads_mutex);
166   Mutex_Lock(&threads_mutex);
167
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);
172
173       return st;
174     }
175   }
176
177   //pthread_mutex_unlock(&threads_mutex);
178   Mutex_Unlock(&threads_mutex);
179
180   st = introduce_thread(pt);
181
182   if (!st) {
183     PrintBoth("lwIP error: In current_thread: Can not get current_thread\n");
184     abort();
185   }
186
187   return st;
188 }
189
190
191 //!!!!!!!!!!!!backto this function later
192 /*-----------------------------------------------------------------------------------*/
193 sys_thread_t
194 sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
195 {
196   int code;
197   //pthread_t tmp;
198   struct Kernel_Thread *tmp;
199   struct sys_thread *st = NULL;
200   
201   //tmp = (struct Kernel_Thread *)Malloc(sizeof(struct Kernel_Thread));
202   
203   /* code = pthread_create(&tmp,
204                         NULL, 
205                         (void *(*)(void *)) 
206                         function, 
207                         arg); */
208                        
209   tmp = Start_Kernel_Thread(function, arg, PRIORITY_NORMAL , false);  //did not consider the priority here
210   
211   if (tmp != NULL) {
212     st = introduce_thread(tmp);
213   }
214   
215   if (NULL == st) {
216     LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create: 0x%x, st = 0x%x",
217                        (int)tmp, (int)st));
218     abort();
219   }
220   return st;
221 }
222
223
224 /*-----------------------------------------------------------------------------------*/
225 struct sys_mbox *
226 sys_mbox_new(int size)
227 {
228   struct sys_mbox *mbox;
229   
230   mbox = (struct sys_mbox *)Malloc(sizeof(struct sys_mbox));
231   if (mbox != NULL) {
232     mbox->first = mbox->last = 0;
233     mbox->mail = sys_sem_new_(0);
234     mbox->mutex = sys_sem_new_(1);
235     mbox->wait_send = 0;
236   
237 #if SYS_STATS
238     lwip_stats.sys.mbox.used++;
239     if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max) {
240       lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
241     }
242 #endif /* SYS_STATS */
243   }
244   return mbox;
245 }
246 /*-----------------------------------------------------------------------------------*/
247 void
248 sys_mbox_free(struct sys_mbox *mbox)
249 {
250   if (mbox != SYS_MBOX_NULL) {
251 #if SYS_STATS
252     lwip_stats.sys.mbox.used--;
253 #endif /* SYS_STATS */
254     sys_sem_wait(mbox->mutex);
255     
256     sys_sem_free_(mbox->mail);
257     sys_sem_free_(mbox->mutex);
258     mbox->mail = mbox->mutex = NULL;
259     /*  LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
260
261     Free(mbox); 
262   }
263 }
264 /*-----------------------------------------------------------------------------------*/
265 err_t
266 sys_mbox_trypost(struct sys_mbox *mbox, void *msg)
267 {
268   u8_t first;
269   
270   sys_sem_wait(mbox->mutex);
271   
272   LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
273                           (void *)mbox, (void *)msg));
274   
275   if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE))
276     return ERR_MEM;
277
278   mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
279   
280   if (mbox->last == mbox->first) {
281     first = 1;
282   } else {
283     first = 0;
284   }
285   
286   mbox->last++;
287   
288   if (first) {
289     sys_sem_signal(mbox->mail);
290   }
291
292   sys_sem_signal(mbox->mutex);
293
294   return ERR_OK;
295 }
296 /*-----------------------------------------------------------------------------------*/
297 void
298 sys_mbox_post(struct sys_mbox *mbox, void *msg)
299 {
300   u8_t first;
301   
302   sys_sem_wait(mbox->mutex);
303   
304   LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
305   
306   while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
307     mbox->wait_send++;
308     sys_sem_signal(mbox->mutex);
309     sys_arch_sem_wait(mbox->mail, 0);
310     sys_arch_sem_wait(mbox->mutex, 0);
311     mbox->wait_send--;
312   }
313   
314   mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
315   
316   if (mbox->last == mbox->first) {
317     first = 1;
318   } else {
319     first = 0;
320   }
321   
322   mbox->last++;
323   
324   if (first) {
325     sys_sem_signal(mbox->mail);
326   }
327
328   sys_sem_signal(mbox->mutex);
329 }
330 /*-----------------------------------------------------------------------------------*/
331 u32_t
332 sys_arch_mbox_tryfetch(struct sys_mbox *mbox, void **msg)
333 {
334   sys_arch_sem_wait(mbox->mutex, 0);
335
336   if (mbox->first == mbox->last) {
337     sys_sem_signal(mbox->mutex);
338     return SYS_MBOX_EMPTY;
339   }
340
341   if (msg != NULL) {
342     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
343     *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
344   }
345   else{
346     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
347   }
348
349   mbox->first++;
350   
351   if (mbox->wait_send) {
352     sys_sem_signal(mbox->mail);
353   }
354
355   sys_sem_signal(mbox->mutex);
356
357   return 0;
358 }
359 /*-----------------------------------------------------------------------------------*/
360 u32_t
361 sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u32_t timeout)
362 {
363   u32_t time = 0;
364   
365   /* The mutex lock is quick so we don't bother with the timeout
366      stuff here. */
367   sys_arch_sem_wait(mbox->mutex, 0);
368
369   while (mbox->first == mbox->last) {
370     sys_sem_signal(mbox->mutex);
371     
372     /* We block while waiting for a mail to arrive in the mailbox. We
373        must be prepared to timeout. */
374     if (timeout != 0) {
375       time = sys_arch_sem_wait(mbox->mail, timeout);
376       
377       if (time == SYS_ARCH_TIMEOUT) {
378         return SYS_ARCH_TIMEOUT;
379       }
380     } else {
381       sys_arch_sem_wait(mbox->mail, 0);
382     }
383     
384     sys_arch_sem_wait(mbox->mutex, 0);
385   }
386
387   if (msg != NULL) {
388     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
389     *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
390   }
391   else{
392     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
393   }
394
395   mbox->first++;
396   
397   if (mbox->wait_send) {
398     sys_sem_signal(mbox->mail);
399   }
400
401   sys_sem_signal(mbox->mutex);
402
403   return time;
404 }
405 /*-----------------------------------------------------------------------------------*/
406 struct sys_sem *
407 sys_sem_new(u8_t count)
408 {
409 #if SYS_STATS
410   lwip_stats.sys.sem.used++;
411   if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) {
412     lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
413   }
414 #endif /* SYS_STATS */
415   return sys_sem_new_(count);
416 }
417
418 /*-----------------------------------------------------------------------------------*/
419 static struct sys_sem *
420 sys_sem_new_(u8_t count)
421 {
422   struct sys_sem *sem;
423   
424   sem = (struct sys_sem *)Malloc(sizeof(struct sys_sem));
425   if (sem != NULL) {
426     sem->c = count;
427
428     //pthread_cond_init(&(sem->cond), NULL);
429     Cond_Init(&(sem->cond));
430     
431     //pthread_mutex_init(&(sem->mutex), NULL);
432     Mutex_Init(&(sem->mutex));
433   }
434   return sem;
435 }
436
437
438 /*-----------------------------------------------------------------------------------*/
439 static u32_t
440 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 */)
441 {
442   ulong_t tdiff, msec;
443
444   /*
445   struct timeval rtime1, rtime2;
446   struct timespec ts;
447   struct timezone tz;
448   */
449   int retval;
450
451   if (timeout > 0) {
452
453     /* Get a timestamp and add the timeout value. */
454     /*gettimeofday(&rtime1, &tz);
455     sec = rtime1.tv_sec;
456     usec = rtime1.tv_usec;
457     usec += timeout % 1000 * 1000;
458     sec += (int)(timeout / 1000) + (int)(usec / 1000000);
459     usec = usec % 1000000;
460     ts.tv_nsec = usec * 1000;
461     ts.tv_sec = sec;
462     */
463     msec = clock_time();
464   
465     if (Cond_Wait_Timeout(cond, mutex, timeout) == 1) //return due to timeout
466                 retval = ETIMEDOUT;
467         
468     //retval = pthread_cond_timedwait(cond, mutex, &ts);
469     
470     if (retval == ETIMEDOUT) {
471       return SYS_ARCH_TIMEOUT;
472     } else {
473       /* Calculate for how long we waited for the cond. */
474
475       /*
476       gettimeofday(&rtime2, &tz);
477       tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +
478         (rtime2.tv_usec - rtime1.tv_usec) / 1000;
479       */
480       tdiff = clock_time();
481
482       tdiff -= msec;
483       
484       if (tdiff <= 0) {
485         return 0;
486       }
487       
488       return tdiff;
489     }
490   } else {
491     //pthread_cond_wait(cond, mutex);
492     Cond_Wait(cond, mutex);
493         
494     return SYS_ARCH_TIMEOUT;
495   }
496 }
497 /*-----------------------------------------------------------------------------------*/
498 u32_t
499 sys_arch_sem_wait(struct sys_sem *sem, u32_t timeout)
500 {
501   u32_t time = 0;
502   
503   //pthread_mutex_lock(&(sem->mutex));
504   Mutex_Lock(&(sem->mutex));
505   
506   while (sem->c <= 0) {
507     if (timeout > 0) {
508       time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
509       
510       if (time == SYS_ARCH_TIMEOUT) {
511         //pthread_mutex_unlock(&(sem->mutex));
512         Mutex_Unlock(&(sem->mutex));
513         
514         return SYS_ARCH_TIMEOUT;
515       }
516       /*      pthread_mutex_unlock(&(sem->mutex));
517               return time; */
518     } else {  // if timeout = 0
519       cond_wait(&(sem->cond), &(sem->mutex), 0);
520     }
521   }
522   sem->c--;
523   //pthread_mutex_unlock(&(sem->mutex));
524   Mutex_Unlock(&(sem->mutex));
525   
526   return time;
527 }
528 /*-----------------------------------------------------------------------------------*/
529 void
530 sys_sem_signal(struct sys_sem *sem)
531 {
532   //pthread_mutex_lock(&(sem->mutex));
533   Mutex_Lock(&(sem->mutex));
534   
535   sem->c++;
536
537   if (sem->c > 1) {
538     sem->c = 1;
539   }
540
541   //pthread_cond_broadcast(&(sem->cond));
542   Cond_Broadcast(&(sem->cond));
543   
544   //pthread_mutex_unlock(&(sem->mutex));
545   Mutex_Unlock(&(sem->mutex));
546   
547 }
548 /*-----------------------------------------------------------------------------------*/
549 void
550 sys_sem_free(struct sys_sem *sem)
551 {
552   if (sem != SYS_SEM_NULL) {
553 #if SYS_STATS
554     lwip_stats.sys.sem.used--;
555 #endif /* SYS_STATS */
556     sys_sem_free_(sem);
557   }
558 }
559
560 /*-----------------------------------------------------------------------------------*/
561 static void
562 sys_sem_free_(struct sys_sem *sem)
563 {
564   //pthread_cond_destroy(&(sem->cond));
565   Cond_Destroy(&(sem->cond));
566   
567   //pthread_mutex_destroy(&(sem->mutex));
568   Mutex_Destroy(&(sem->mutex));
569   
570   Free(sem);
571 }
572
573 #if 0
574 //return time, we do not need this
575 /*-----------------------------------------------------------------------------------*/
576 unsigned long
577 sys_unix_now()
578 {
579   struct timeval tv;
580   struct timezone tz;
581   long sec, usec;
582   unsigned long msec;
583   gettimeofday(&tv, &tz);
584   
585   sec = tv.tv_sec - starttime.tv_sec;
586   usec = tv.tv_usec - starttime.tv_usec;
587   msec = sec * 1000 + usec / 1000;
588     
589   return msec;
590 }
591 #endif
592
593 /*-----------------------------------------------------------------------------------*/
594 void
595 sys_init()
596 {
597   //struct timezone tz;
598   //gettimeofday(&starttime, &tz);
599
600   Mutex_Init(&threads_mutex);
601   Mutex_Init(&lwprot_mutex);
602   
603 }
604 /*-----------------------------------------------------------------------------------*/
605 struct sys_timeouts *
606 sys_arch_timeouts(void)
607 {
608   struct sys_thread *thread;
609
610   thread = current_thread();
611   return &thread->timeouts;
612 }
613 /*-----------------------------------------------------------------------------------*/
614 /** sys_prot_t sys_arch_protect(void)
615
616 This optional function does a "fast" critical region protection and returns
617 the previous protection level. This function is only called during very short
618 critical regions. An embedded system which supports ISR-based drivers might
619 want to implement this function by disabling interrupts. Task-based systems
620 might want to implement this by using a mutex or disabling tasking. This
621 function should support recursive calls from the same task or interrupt. In
622 other words, sys_arch_protect() could be called while already protected. In
623 that case the return value indicates that it is already protected.
624
625 sys_arch_protect() is only required if your port is supporting an operating
626 system.
627 */
628 sys_prot_t
629 sys_arch_protect(void)
630 {
631     /* Note that for the UNIX port, we are using a lightweight mutex, and our
632      * own counter (which is locked by the mutex). The return code is not actually
633      * used. */
634     if (lwprot_thread != current_thread() /*lwprot_thread != pthread_self()*/)
635     {
636         /* We are locking the mutex where it has not been locked before *
637         * or is being locked by another thread */
638         Mutex_Lock(&lwprot_mutex);
639         lwprot_thread = current_thread();
640         lwprot_count = 1;
641     }
642     else
643         /* It is already locked by THIS thread */
644         lwprot_count++;
645     return 0;
646 }
647 /*-----------------------------------------------------------------------------------*/
648 /** void sys_arch_unprotect(sys_prot_t pval)
649
650 This optional function does a "fast" set of critical region protection to the
651 value specified by pval. See the documentation for sys_arch_protect() for
652 more information. This function is only required if your port is supporting
653 an operating system.
654 */
655 void
656 sys_arch_unprotect(sys_prot_t pval)
657 {
658     if (lwprot_thread == current_thread())
659     {
660         if (--lwprot_count == 0)
661         {
662             lwprot_thread = (Kernel_Thread) 0xDEAD;
663             Mutex_Unlock(&lwprot_mutex);
664         }
665     }
666 }
667
668 /*-----------------------------------------------------------------------------------*/
669
670 #ifndef MAX_JIFFY_OFFSET
671 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
672 #endif
673
674 #ifndef HZ
675 #define HZ 100
676 #endif
677
678 unsigned long
679 sys_jiffies(void)
680 {
681     struct timeval tv;
682     unsigned long sec = tv.tv_sec;
683     long usec = tv.tv_usec;
684
685     gettimeofday(&tv,NULL);
686
687     if (sec >= (MAX_JIFFY_OFFSET / HZ))
688         return MAX_JIFFY_OFFSET;
689     usec += 1000000L / HZ - 1;
690     usec /= 1000000L / HZ;
691     return HZ * sec + usec;
692 }
693
694 #if PPP_DEBUG
695
696 #include <geekos/serial.h>
697
698 void ppp_trace(int level, const char *format, ...)
699 {
700     va_list args;
701
702     (void)level;
703     va_start(args, format);
704         
705     //vprintf(format, args);
706     SerialPrintList(format, args);
707         
708     va_end(args);
709 }
710 #endif