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.


Add archtecture dependent stuffs for lwIP, mainly on lwip/arch/sys_arch.c
[palacios-OLD.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 <palacios/vmm.h>
59 #include <geekos/debug.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 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;
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(pthread_cond_t * cond, pthread_mutex_t * mutex,
120                        u32_t timeout);
121
122
123 /*-----------------------------------------------------------------------------------*/
124 static struct sys_thread * 
125 introduce_thread(Kernel_Thread *id /*pthread_t id*/)
126 {
127   struct sys_thread *thread;
128   
129   thread = v3ee_alloc(sizeof(struct sys_thread));  //!!!!!! malloc
130     
131   if (thread != NULL) {
132     //pthread_mutex_lock(&threads_mutex);
133     Mutex_Lock(&threads_mutex);
134         
135     thread->next = threads;
136     thread->timeouts.next = NULL;
137     thread->pthread = id;
138     threads = thread;
139
140     //pthread_mutex_unlock(&threads_mutex);
141     Mutex_Unlock(&threads_mutex);
142   }
143     
144   return thread;
145 }
146
147 static int thread_equal(struct Kernel_Thread *kth1, struct Kernel_Thread *kth2){  //added
148
149         return (kth1->pid == kth2->pid);
150
151 }
152
153 /*-----------------------------------------------------------------------------------*/
154 static struct sys_thread *
155 current_thread(void)
156 {
157   struct sys_thread *st;
158   
159   //pthread_t pt;
160   struct Kernel_Thread *pt;
161   
162   //pt = pthread_self();
163   //!!!!!!!!!!!Do these have the same means? Not sure
164   pt = Get_Current(void);
165   
166   //pthread_mutex_lock(&threads_mutex);
167   Mutex_Lock(&threads_mutex);
168
169   for(st = threads; st != NULL; st = st->next) {    
170     if (thread_equal(&(st->pthread), pt)) {
171       //pthread_mutex_unlock(&threads_mutex);
172       Mutex_Unlock(&threads_mutex);
173
174       return st;
175     }
176   }
177
178   //pthread_mutex_unlock(&threads_mutex);
179   Mutex_Unlock(&threads_mutex);
180
181   st = introduce_thread(pt);
182
183   if (!st) {
184     PrintBoth("lwIP error: In current_thread: current_thread???\n");
185     abort();
186   }
187
188   return st;
189 }
190
191
192 //!!!!!!!!!!!!backto this function later
193 /*-----------------------------------------------------------------------------------*/
194 sys_thread_t
195 sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
196 {
197   int code;
198   //pthread_t tmp;
199   struct Kernel_Thread tmp;
200   struct sys_thread *st = NULL;
201   
202   
203   
204   code = pthread_create(&tmp,
205                         NULL, 
206                         (void *(*)(void *)) 
207                         function, 
208                         arg);
209   
210   if (0 == code) {
211     st = introduce_thread(tmp);
212   }
213   
214   if (NULL == st) {
215     LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%x",
216                        code, (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 = 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);  //!!!! need change
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 = V3_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 /* pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout */)
440 {
441   int tdiff;
442   unsigned long sec, usec;
443   struct timeval rtime1, rtime2;
444   struct timespec ts;
445   struct timezone tz;
446   int retval;
447
448
449   //!!!!!!!!!!!!! OK, we need a timerly-condition wait here
450   if (timeout > 0) {
451     /* Get a timestamp and add the timeout value. */
452     gettimeofday(&rtime1, &tz);
453     sec = rtime1.tv_sec;
454     usec = rtime1.tv_usec;
455     usec += timeout % 1000 * 1000;
456     sec += (int)(timeout / 1000) + (int)(usec / 1000000);
457     usec = usec % 1000000;
458     ts.tv_nsec = usec * 1000;
459     ts.tv_sec = sec;
460     
461     retval = pthread_cond_timedwait(cond, mutex, &ts);
462     
463     if (retval == ETIMEDOUT) {
464       return SYS_ARCH_TIMEOUT;
465     } else {
466       /* Calculate for how long we waited for the cond. */
467       gettimeofday(&rtime2, &tz);
468       tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +
469         (rtime2.tv_usec - rtime1.tv_usec) / 1000;
470       
471       if (tdiff <= 0) {
472         return 0;
473       }
474       
475       return tdiff;
476     }
477   } else {
478     //pthread_cond_wait(cond, mutex);
479     Cond_Wait(cond, mutex);
480         
481     return SYS_ARCH_TIMEOUT;
482   }
483 }
484 /*-----------------------------------------------------------------------------------*/
485 u32_t
486 sys_arch_sem_wait(struct sys_sem *sem, u32_t timeout)
487 {
488   u32_t time = 0;
489   
490   //pthread_mutex_lock(&(sem->mutex));
491   Mutex_Lock(&(sem->mutex));
492   
493   while (sem->c <= 0) {
494     if (timeout > 0) {
495       time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
496       
497       if (time == SYS_ARCH_TIMEOUT) {
498         //pthread_mutex_unlock(&(sem->mutex));
499         Mutex_Unlock(&(sem->mutex));
500         
501         return SYS_ARCH_TIMEOUT;
502       }
503       /*      pthread_mutex_unlock(&(sem->mutex));
504               return time; */
505     } else { //!!!!!!! this else should be paired with  if (time == SYS_ARCH_TIMEOUT) ?????
506       cond_wait(&(sem->cond), &(sem->mutex), 0);
507     }
508   }
509   sem->c--;
510   //pthread_mutex_unlock(&(sem->mutex));
511   Mutex_Unlock(&(sem->mutex));
512   
513   return time;
514 }
515 /*-----------------------------------------------------------------------------------*/
516 void
517 sys_sem_signal(struct sys_sem *sem)
518 {
519   //pthread_mutex_lock(&(sem->mutex));
520   Mutex_Lock(&(sem->mutex));
521   
522   sem->c++;
523
524   if (sem->c > 1) {
525     sem->c = 1;
526   }
527
528   //pthread_cond_broadcast(&(sem->cond));
529   Cond_Broadcast(&(sem->cond));
530   
531   //pthread_mutex_unlock(&(sem->mutex));
532   Mutex_Unlock(&(sem->mutex));
533   
534 }
535 /*-----------------------------------------------------------------------------------*/
536 void
537 sys_sem_free(struct sys_sem *sem)
538 {
539   if (sem != SYS_SEM_NULL) {
540 #if SYS_STATS
541     lwip_stats.sys.sem.used--;
542 #endif /* SYS_STATS */
543     sys_sem_free_(sem);
544   }
545 }
546
547 /*-----------------------------------------------------------------------------------*/
548 static void
549 sys_sem_free_(struct sys_sem *sem)
550 {
551   //pthread_cond_destroy(&(sem->cond));
552   Cond_Destroy(&(sem->cond));
553   
554   //pthread_mutex_destroy(&(sem->mutex));
555   Mutex_Destroy(&(sem->mutex));
556   
557   V3_Free(sem);
558 }
559
560 //return time, back to this later
561 /*-----------------------------------------------------------------------------------*/
562 unsigned long
563 sys_unix_now()
564 {
565   struct timeval tv;
566   struct timezone tz;
567   long sec, usec;
568   unsigned long msec;
569   gettimeofday(&tv, &tz);
570   
571   sec = tv.tv_sec - starttime.tv_sec;
572   usec = tv.tv_usec - starttime.tv_usec;
573   msec = sec * 1000 + usec / 1000;
574     
575   return msec;
576 }
577 /*-----------------------------------------------------------------------------------*/
578 void
579 sys_init()
580 {
581   struct timezone tz;
582   gettimeofday(&starttime, &tz);
583 }
584 /*-----------------------------------------------------------------------------------*/
585 struct sys_timeouts *
586 sys_arch_timeouts(void)
587 {
588   struct sys_thread *thread;
589
590   thread = current_thread();
591   return &thread->timeouts;
592 }
593 /*-----------------------------------------------------------------------------------*/
594 /** sys_prot_t sys_arch_protect(void)
595
596 This optional function does a "fast" critical region protection and returns
597 the previous protection level. This function is only called during very short
598 critical regions. An embedded system which supports ISR-based drivers might
599 want to implement this function by disabling interrupts. Task-based systems
600 might want to implement this by using a mutex or disabling tasking. This
601 function should support recursive calls from the same task or interrupt. In
602 other words, sys_arch_protect() could be called while already protected. In
603 that case the return value indicates that it is already protected.
604
605 sys_arch_protect() is only required if your port is supporting an operating
606 system.
607 */
608 sys_prot_t
609 sys_arch_protect(void)
610 {
611     /* Note that for the UNIX port, we are using a lightweight mutex, and our
612      * own counter (which is locked by the mutex). The return code is not actually
613      * used. */
614     if (lwprot_thread != pthread_self())
615     {
616         /* We are locking the mutex where it has not been locked before *
617         * or is being locked by another thread */
618         pthread_mutex_lock(&lwprot_mutex);
619         lwprot_thread = pthread_self();
620         lwprot_count = 1;
621     }
622     else
623         /* It is already locked by THIS thread */
624         lwprot_count++;
625     return 0;
626 }
627 /*-----------------------------------------------------------------------------------*/
628 /** void sys_arch_unprotect(sys_prot_t pval)
629
630 This optional function does a "fast" set of critical region protection to the
631 value specified by pval. See the documentation for sys_arch_protect() for
632 more information. This function is only required if your port is supporting
633 an operating system.
634 */
635 void
636 sys_arch_unprotect(sys_prot_t pval)
637 {
638     if (lwprot_thread == pthread_self())
639     {
640         if (--lwprot_count == 0)
641         {
642             lwprot_thread = (pthread_t) 0xDEAD;
643             pthread_mutex_unlock(&lwprot_mutex);
644         }
645     }
646 }
647
648 /*-----------------------------------------------------------------------------------*/
649
650 #ifndef MAX_JIFFY_OFFSET
651 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
652 #endif
653
654 #ifndef HZ
655 #define HZ 100
656 #endif
657
658 unsigned long
659 sys_jiffies(void)
660 {
661     struct timeval tv;
662     unsigned long sec = tv.tv_sec;
663     long usec = tv.tv_usec;
664
665     gettimeofday(&tv,NULL);
666
667     if (sec >= (MAX_JIFFY_OFFSET / HZ))
668         return MAX_JIFFY_OFFSET;
669     usec += 1000000L / HZ - 1;
670     usec /= 1000000L / HZ;
671     return HZ * sec + usec;
672 }
673
674 #if PPP_DEBUG
675
676 #include <geekos/serial.h>
677
678 void ppp_trace(int level, const char *format, ...)
679 {
680     va_list args;
681
682     (void)level;
683     va_start(args, format);
684         
685     //vprintf(format, args);
686     SerialPrintList(format, args);
687         
688     va_end(args);
689 }
690 #endif