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.


Release 1.0
[palacios.git] / geekos / 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 /*
48  * Modified by Lei Xia (lxia@northwestern.edu) to fit to Palacios, 9/29/2008
49  */
50 #include "lwip/debug.h"
51
52 #include <string.h>
53
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>
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 /*-----------------------------------------------------------------------------------*/
192 sys_thread_t
193 sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
194 {
195   //int code;
196   //pthread_t tmp;
197   struct Kernel_Thread *tmp;
198   struct sys_thread *st = NULL;
199   
200   //tmp = (struct Kernel_Thread *)Malloc(sizeof(struct Kernel_Thread));
201   
202   /* code = pthread_create(&tmp,
203                         NULL, 
204                         (void *(*)(void *)) 
205                         function, 
206                         arg); */
207                        
208   tmp = Start_Kernel_Thread(function, arg, PRIORITY_NORMAL , false);  //did not consider the priority here
209   
210   if (tmp != NULL) {
211     st = introduce_thread(tmp);
212   }
213   
214   if (NULL == st) {
215     LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create: 0x%x, st = 0x%x",
216                        (int)tmp, (int)st));
217     abort();
218   }
219   return st;
220 }
221
222
223 /*-----------------------------------------------------------------------------------*/
224 struct sys_mbox *
225 sys_mbox_new(int size)
226 {
227   struct sys_mbox *mbox;
228   
229   mbox = (struct sys_mbox *)Malloc(sizeof(struct sys_mbox));
230   if (mbox != NULL) {
231     mbox->first = mbox->last = 0;
232     mbox->mail = sys_sem_new_(0);
233     mbox->mutex = sys_sem_new_(1);
234     mbox->wait_send = 0;
235   
236 #if SYS_STATS
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;
240     }
241 #endif /* SYS_STATS */
242   }
243   return mbox;
244 }
245 /*-----------------------------------------------------------------------------------*/
246 void
247 sys_mbox_free(struct sys_mbox *mbox)
248 {
249   if (mbox != SYS_MBOX_NULL) {
250 #if SYS_STATS
251     lwip_stats.sys.mbox.used--;
252 #endif /* SYS_STATS */
253     sys_sem_wait(mbox->mutex);
254     
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); */
259
260     Free(mbox); 
261   }
262 }
263 /*-----------------------------------------------------------------------------------*/
264 err_t
265 sys_mbox_trypost(struct sys_mbox *mbox, void *msg)
266 {
267   u8_t first;
268   
269   sys_sem_wait(mbox->mutex);
270   
271   LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
272                           (void *)mbox, (void *)msg));
273   
274   if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE))
275     return ERR_MEM;
276
277   mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
278   
279   if (mbox->last == mbox->first) {
280     first = 1;
281   } else {
282     first = 0;
283   }
284   
285   mbox->last++;
286   
287   if (first) {
288     sys_sem_signal(mbox->mail);
289   }
290
291   sys_sem_signal(mbox->mutex);
292
293   return ERR_OK;
294 }
295 /*-----------------------------------------------------------------------------------*/
296 void
297 sys_mbox_post(struct sys_mbox *mbox, void *msg)
298 {
299   u8_t first;
300   
301   sys_sem_wait(mbox->mutex);
302   
303   LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
304   
305   while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
306     mbox->wait_send++;
307     sys_sem_signal(mbox->mutex);
308     sys_arch_sem_wait(mbox->mail, 0);
309     sys_arch_sem_wait(mbox->mutex, 0);
310     mbox->wait_send--;
311   }
312   
313   mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
314   
315   if (mbox->last == mbox->first) {
316     first = 1;
317   } else {
318     first = 0;
319   }
320   
321   mbox->last++;
322   
323   if (first) {
324     sys_sem_signal(mbox->mail);
325   }
326
327   sys_sem_signal(mbox->mutex);
328 }
329 /*-----------------------------------------------------------------------------------*/
330 u32_t
331 sys_arch_mbox_tryfetch(struct sys_mbox *mbox, void **msg)
332 {
333   sys_arch_sem_wait(mbox->mutex, 0);
334
335   if (mbox->first == mbox->last) {
336     sys_sem_signal(mbox->mutex);
337     return SYS_MBOX_EMPTY;
338   }
339
340   if (msg != NULL) {
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];
343   }
344   else{
345     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
346   }
347
348   mbox->first++;
349   
350   if (mbox->wait_send) {
351     sys_sem_signal(mbox->mail);
352   }
353
354   sys_sem_signal(mbox->mutex);
355
356   return 0;
357 }
358 /*-----------------------------------------------------------------------------------*/
359 u32_t
360 sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u32_t timeout)
361 {
362   u32_t time = 0;
363   
364   /* The mutex lock is quick so we don't bother with the timeout
365      stuff here. */
366   sys_arch_sem_wait(mbox->mutex, 0);
367
368   while (mbox->first == mbox->last) {
369     sys_sem_signal(mbox->mutex);
370     
371     /* We block while waiting for a mail to arrive in the mailbox. We
372        must be prepared to timeout. */
373     if (timeout != 0) {
374       time = sys_arch_sem_wait(mbox->mail, timeout);
375       
376       if (time == SYS_ARCH_TIMEOUT) {
377         return SYS_ARCH_TIMEOUT;
378       }
379     } else {
380       sys_arch_sem_wait(mbox->mail, 0);
381     }
382     
383     sys_arch_sem_wait(mbox->mutex, 0);
384   }
385
386   if (msg != NULL) {
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];
389   }
390   else{
391     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
392   }
393
394   mbox->first++;
395   
396   if (mbox->wait_send) {
397     sys_sem_signal(mbox->mail);
398   }
399
400   sys_sem_signal(mbox->mutex);
401
402   return time;
403 }
404 /*-----------------------------------------------------------------------------------*/
405 struct sys_sem *
406 sys_sem_new(u8_t count)
407 {
408 #if SYS_STATS
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;
412   }
413 #endif /* SYS_STATS */
414   return sys_sem_new_(count);
415 }
416
417 /*-----------------------------------------------------------------------------------*/
418 static struct sys_sem *
419 sys_sem_new_(u8_t count)
420 {
421   struct sys_sem *sem;
422   
423   sem = (struct sys_sem *)Malloc(sizeof(struct sys_sem));
424   if (sem != NULL) {
425     sem->c = count;
426
427     //pthread_cond_init(&(sem->cond), NULL);
428     Cond_Init(&(sem->cond));
429     
430     //pthread_mutex_init(&(sem->mutex), NULL);
431     Mutex_Init(&(sem->mutex));
432   }
433   return sem;
434 }
435
436
437 /*-----------------------------------------------------------------------------------*/
438 static u32_t
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 */)
440 {
441   ulong_t tdiff, msec;
442
443   /*
444   struct timeval rtime1, rtime2;
445   struct timespec ts;
446   struct timezone tz;
447   */
448   int retval;
449
450   if (timeout > 0) {
451
452     /* Get a timestamp and add the timeout value. */
453     /*gettimeofday(&rtime1, &tz);
454     sec = rtime1.tv_sec;
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;
460     ts.tv_sec = sec;
461     */
462     msec = clock_time();
463   
464     if (Cond_Wait_Timeout(cond, mutex, timeout) == 1) //return due to timeout
465                 retval = ETIMEDOUT;
466         
467     //retval = pthread_cond_timedwait(cond, mutex, &ts);
468     
469     if (retval == ETIMEDOUT) {
470       return SYS_ARCH_TIMEOUT;
471     } else {
472       /* Calculate for how long we waited for the cond. */
473
474       /*
475       gettimeofday(&rtime2, &tz);
476       tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +
477         (rtime2.tv_usec - rtime1.tv_usec) / 1000;
478       */
479       tdiff = clock_time();
480
481       tdiff -= msec;
482       
483       if (tdiff <= 0) {
484         return 0;
485       }
486       
487       return tdiff;
488     }
489   } else {
490     //pthread_cond_wait(cond, mutex);
491     Cond_Wait(cond, mutex);
492         
493     return SYS_ARCH_TIMEOUT;
494   }
495 }
496 /*-----------------------------------------------------------------------------------*/
497 u32_t
498 sys_arch_sem_wait(struct sys_sem *sem, u32_t timeout)
499 {
500   u32_t time = 0;
501   
502   //pthread_mutex_lock(&(sem->mutex));
503   Mutex_Lock(&(sem->mutex));
504   
505   while (sem->c <= 0) {
506     if (timeout > 0) {
507       time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
508       
509       if (time == SYS_ARCH_TIMEOUT) {
510         //pthread_mutex_unlock(&(sem->mutex));
511         Mutex_Unlock(&(sem->mutex));
512         
513         return SYS_ARCH_TIMEOUT;
514       }
515       /*      pthread_mutex_unlock(&(sem->mutex));
516               return time; */
517     } else {  // if timeout = 0
518       cond_wait(&(sem->cond), &(sem->mutex), 0);
519     }
520   }
521   sem->c--;
522   //pthread_mutex_unlock(&(sem->mutex));
523   Mutex_Unlock(&(sem->mutex));
524   
525   return time;
526 }
527 /*-----------------------------------------------------------------------------------*/
528 void
529 sys_sem_signal(struct sys_sem *sem)
530 {
531   //pthread_mutex_lock(&(sem->mutex));
532   Mutex_Lock(&(sem->mutex));
533   
534   sem->c++;
535
536   if (sem->c > 1) {
537     sem->c = 1;
538   }
539
540   //pthread_cond_broadcast(&(sem->cond));
541   Cond_Broadcast(&(sem->cond));
542   
543   //pthread_mutex_unlock(&(sem->mutex));
544   Mutex_Unlock(&(sem->mutex));
545   
546 }
547 /*-----------------------------------------------------------------------------------*/
548 void
549 sys_sem_free(struct sys_sem *sem)
550 {
551   if (sem != SYS_SEM_NULL) {
552 #if SYS_STATS
553     lwip_stats.sys.sem.used--;
554 #endif /* SYS_STATS */
555     sys_sem_free_(sem);
556   }
557 }
558
559 /*-----------------------------------------------------------------------------------*/
560 static void
561 sys_sem_free_(struct sys_sem *sem)
562 {
563   //pthread_cond_destroy(&(sem->cond));
564   Cond_Destroy(&(sem->cond));
565   
566   //pthread_mutex_destroy(&(sem->mutex));
567   Mutex_Destroy(&(sem->mutex));
568   
569   Free(sem);
570 }
571
572 #if 0
573 //return time, we do not need this
574 /*-----------------------------------------------------------------------------------*/
575 unsigned long
576 sys_unix_now()
577 {
578   struct timeval tv;
579   struct timezone tz;
580   long sec, usec;
581   unsigned long msec;
582   gettimeofday(&tv, &tz);
583   
584   sec = tv.tv_sec - starttime.tv_sec;
585   usec = tv.tv_usec - starttime.tv_usec;
586   msec = sec * 1000 + usec / 1000;
587     
588   return msec;
589 }
590 #endif
591
592 /*-----------------------------------------------------------------------------------*/
593 void
594 sys_init()
595 {
596   //struct timezone tz;
597   //gettimeofday(&starttime, &tz);
598
599   Mutex_Init(&threads_mutex);
600   Mutex_Init(&lwprot_mutex);
601   
602 }
603 /*-----------------------------------------------------------------------------------*/
604 struct sys_timeouts *
605 sys_arch_timeouts(void)
606 {
607   struct sys_thread *thread;
608
609   thread = current_thread();
610   return &thread->timeouts;
611 }
612
613
614 /*-----------------------------------------------------------------------------------*/
615 /** sys_prot_t sys_arch_protect(void)
616
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.
625
626 sys_arch_protect() is only required if your port is supporting an operating
627 system.
628 */
629
630 #if 0
631 sys_prot_t
632 sys_arch_protect(void)
633 {
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
636      * used. */
637     if (lwprot_thread != current_thread() /*lwprot_thread != pthread_self()*/)
638     {
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();
643         lwprot_count = 1;
644     }
645     else
646         /* It is already locked by THIS thread */
647         lwprot_count++;
648     return 0;
649 }
650 /*-----------------------------------------------------------------------------------*/
651 /** void sys_arch_unprotect(sys_prot_t pval)
652
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
656 an operating system.
657 */
658 void
659 sys_arch_unprotect(sys_prot_t pval)
660 {
661     if (lwprot_thread == current_thread())
662     {
663         if (--lwprot_count == 0)
664         {
665             lwprot_thread = (struc Kernel_Thread) 0xDEAD;
666             Mutex_Unlock(&lwprot_mutex);
667         }
668     }
669 }
670 #endif
671
672 /*-----------------------------------------------------------------------------------*/
673
674 #ifndef MAX_JIFFY_OFFSET
675 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
676 #endif
677
678 #ifndef HZ
679 #define HZ 100
680 #endif
681
682 #if 0
683 unsigned long
684 sys_jiffies(void)
685 {
686     struct timeval tv;
687     unsigned long sec = tv.tv_sec;
688     long usec = tv.tv_usec;
689
690     gettimeofday(&tv,NULL);
691
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;
697 }
698 #endif
699
700 #if PPP_DEBUG
701
702 #include <geekos/serial.h>
703
704 void ppp_trace(int level, const char *format, ...)
705 {
706     va_list args;
707
708     (void)level;
709     va_start(args, format);
710         
711     //vprintf(format, args);
712     PrintDebug(format, args);
713         
714     va_end(args);
715 }
716 #endif