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.


modify sys_arch.c file
[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 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 *)V3_Malloc(sizeof(struct sys_thread));  //!!!!!! malloc
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: 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 *)V3_Malloc(sizeof(struct Kernel_Thread));
202   
203   code = pthread_create(&tmp,
204                         NULL, 
205                         (void *(*)(void *)) 
206                         function, 
207                         arg);
208   
209   if (0 == code) {
210     st = introduce_thread(tmp);
211   }
212   
213   if (NULL == st) {
214     LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%x",
215                        code, (int)st));
216     abort();
217   }
218   return st;
219 }
220
221
222 /*-----------------------------------------------------------------------------------*/
223 struct sys_mbox *
224 sys_mbox_new(int size)
225 {
226   struct sys_mbox *mbox;
227   
228   mbox = (struct sys_mbox *)V3_Malloc(sizeof(struct sys_mbox));
229   if (mbox != NULL) {
230     mbox->first = mbox->last = 0;
231     mbox->mail = sys_sem_new_(0);
232     mbox->mutex = sys_sem_new_(1);
233     mbox->wait_send = 0;
234   
235 #if SYS_STATS
236     lwip_stats.sys.mbox.used++;
237     if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max) {
238       lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
239     }
240 #endif /* SYS_STATS */
241   }
242   return mbox;
243 }
244 /*-----------------------------------------------------------------------------------*/
245 void
246 sys_mbox_free(struct sys_mbox *mbox)
247 {
248   if (mbox != SYS_MBOX_NULL) {
249 #if SYS_STATS
250     lwip_stats.sys.mbox.used--;
251 #endif /* SYS_STATS */
252     sys_sem_wait(mbox->mutex);
253     
254     sys_sem_free_(mbox->mail);
255     sys_sem_free_(mbox->mutex);
256     mbox->mail = mbox->mutex = NULL;
257     /*  LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
258
259     V3_Free(mbox); 
260   }
261 }
262 /*-----------------------------------------------------------------------------------*/
263 err_t
264 sys_mbox_trypost(struct sys_mbox *mbox, void *msg)
265 {
266   u8_t first;
267   
268   sys_sem_wait(mbox->mutex);
269   
270   LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
271                           (void *)mbox, (void *)msg));
272   
273   if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE))
274     return ERR_MEM;
275
276   mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
277   
278   if (mbox->last == mbox->first) {
279     first = 1;
280   } else {
281     first = 0;
282   }
283   
284   mbox->last++;
285   
286   if (first) {
287     sys_sem_signal(mbox->mail);
288   }
289
290   sys_sem_signal(mbox->mutex);
291
292   return ERR_OK;
293 }
294 /*-----------------------------------------------------------------------------------*/
295 void
296 sys_mbox_post(struct sys_mbox *mbox, void *msg)
297 {
298   u8_t first;
299   
300   sys_sem_wait(mbox->mutex);
301   
302   LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
303   
304   while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
305     mbox->wait_send++;
306     sys_sem_signal(mbox->mutex);
307     sys_arch_sem_wait(mbox->mail, 0);
308     sys_arch_sem_wait(mbox->mutex, 0);
309     mbox->wait_send--;
310   }
311   
312   mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
313   
314   if (mbox->last == mbox->first) {
315     first = 1;
316   } else {
317     first = 0;
318   }
319   
320   mbox->last++;
321   
322   if (first) {
323     sys_sem_signal(mbox->mail);
324   }
325
326   sys_sem_signal(mbox->mutex);
327 }
328 /*-----------------------------------------------------------------------------------*/
329 u32_t
330 sys_arch_mbox_tryfetch(struct sys_mbox *mbox, void **msg)
331 {
332   sys_arch_sem_wait(mbox->mutex, 0);
333
334   if (mbox->first == mbox->last) {
335     sys_sem_signal(mbox->mutex);
336     return SYS_MBOX_EMPTY;
337   }
338
339   if (msg != NULL) {
340     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
341     *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
342   }
343   else{
344     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
345   }
346
347   mbox->first++;
348   
349   if (mbox->wait_send) {
350     sys_sem_signal(mbox->mail);
351   }
352
353   sys_sem_signal(mbox->mutex);
354
355   return 0;
356 }
357 /*-----------------------------------------------------------------------------------*/
358 u32_t
359 sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u32_t timeout)
360 {
361   u32_t time = 0;
362   
363   /* The mutex lock is quick so we don't bother with the timeout
364      stuff here. */
365   sys_arch_sem_wait(mbox->mutex, 0);
366
367   while (mbox->first == mbox->last) {
368     sys_sem_signal(mbox->mutex);
369     
370     /* We block while waiting for a mail to arrive in the mailbox. We
371        must be prepared to timeout. */
372     if (timeout != 0) {
373       time = sys_arch_sem_wait(mbox->mail, timeout);
374       
375       if (time == SYS_ARCH_TIMEOUT) {
376         return SYS_ARCH_TIMEOUT;
377       }
378     } else {
379       sys_arch_sem_wait(mbox->mail, 0);
380     }
381     
382     sys_arch_sem_wait(mbox->mutex, 0);
383   }
384
385   if (msg != NULL) {
386     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
387     *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
388   }
389   else{
390     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
391   }
392
393   mbox->first++;
394   
395   if (mbox->wait_send) {
396     sys_sem_signal(mbox->mail);
397   }
398
399   sys_sem_signal(mbox->mutex);
400
401   return time;
402 }
403 /*-----------------------------------------------------------------------------------*/
404 struct sys_sem *
405 sys_sem_new(u8_t count)
406 {
407 #if SYS_STATS
408   lwip_stats.sys.sem.used++;
409   if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) {
410     lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
411   }
412 #endif /* SYS_STATS */
413   return sys_sem_new_(count);
414 }
415
416 /*-----------------------------------------------------------------------------------*/
417 static struct sys_sem *
418 sys_sem_new_(u8_t count)
419 {
420   struct sys_sem *sem;
421   
422   sem = (struct sys_sem *)V3_Malloc(sizeof(struct sys_sem));
423   if (sem != NULL) {
424     sem->c = count;
425
426     //pthread_cond_init(&(sem->cond), NULL);
427     Cond_Init(&(sem->cond));
428     
429     //pthread_mutex_init(&(sem->mutex), NULL);
430     Mutex_Init(&(sem->mutex));
431   }
432   return sem;
433 }
434
435
436 /*-----------------------------------------------------------------------------------*/
437 static u32_t
438 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 */)
439 {
440   int tdiff;
441   unsigned long sec, usec;
442   struct timeval rtime1, rtime2;
443   struct timespec ts;
444   struct timezone tz;
445   int retval;
446
447
448   //!!!!!!!!!!!!! OK, we need a timerly-condition wait here
449   if (timeout > 0) {
450     /* Get a timestamp and add the timeout value. */
451     gettimeofday(&rtime1, &tz);
452     sec = rtime1.tv_sec;
453     usec = rtime1.tv_usec;
454     usec += timeout % 1000 * 1000;
455     sec += (int)(timeout / 1000) + (int)(usec / 1000000);
456     usec = usec % 1000000;
457     ts.tv_nsec = usec * 1000;
458     ts.tv_sec = sec;
459     
460     retval = pthread_cond_timedwait(cond, mutex, &ts);
461     
462     if (retval == ETIMEDOUT) {
463       return SYS_ARCH_TIMEOUT;
464     } else {
465       /* Calculate for how long we waited for the cond. */
466       gettimeofday(&rtime2, &tz);
467       tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +
468         (rtime2.tv_usec - rtime1.tv_usec) / 1000;
469       
470       if (tdiff <= 0) {
471         return 0;
472       }
473       
474       return tdiff;
475     }
476   } else {
477     //pthread_cond_wait(cond, mutex);
478     Cond_Wait(cond, mutex);
479         
480     return SYS_ARCH_TIMEOUT;
481   }
482 }
483 /*-----------------------------------------------------------------------------------*/
484 u32_t
485 sys_arch_sem_wait(struct sys_sem *sem, u32_t timeout)
486 {
487   u32_t time = 0;
488   
489   //pthread_mutex_lock(&(sem->mutex));
490   Mutex_Lock(&(sem->mutex));
491   
492   while (sem->c <= 0) {
493     if (timeout > 0) {
494       time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
495       
496       if (time == SYS_ARCH_TIMEOUT) {
497         //pthread_mutex_unlock(&(sem->mutex));
498         Mutex_Unlock(&(sem->mutex));
499         
500         return SYS_ARCH_TIMEOUT;
501       }
502       /*      pthread_mutex_unlock(&(sem->mutex));
503               return time; */
504     } else { //!!!!!!! this else should be paired with  if (time == SYS_ARCH_TIMEOUT) ?????
505       cond_wait(&(sem->cond), &(sem->mutex), 0);
506     }
507   }
508   sem->c--;
509   //pthread_mutex_unlock(&(sem->mutex));
510   Mutex_Unlock(&(sem->mutex));
511   
512   return time;
513 }
514 /*-----------------------------------------------------------------------------------*/
515 void
516 sys_sem_signal(struct sys_sem *sem)
517 {
518   //pthread_mutex_lock(&(sem->mutex));
519   Mutex_Lock(&(sem->mutex));
520   
521   sem->c++;
522
523   if (sem->c > 1) {
524     sem->c = 1;
525   }
526
527   //pthread_cond_broadcast(&(sem->cond));
528   Cond_Broadcast(&(sem->cond));
529   
530   //pthread_mutex_unlock(&(sem->mutex));
531   Mutex_Unlock(&(sem->mutex));
532   
533 }
534 /*-----------------------------------------------------------------------------------*/
535 void
536 sys_sem_free(struct sys_sem *sem)
537 {
538   if (sem != SYS_SEM_NULL) {
539 #if SYS_STATS
540     lwip_stats.sys.sem.used--;
541 #endif /* SYS_STATS */
542     sys_sem_free_(sem);
543   }
544 }
545
546 /*-----------------------------------------------------------------------------------*/
547 static void
548 sys_sem_free_(struct sys_sem *sem)
549 {
550   //pthread_cond_destroy(&(sem->cond));
551   Cond_Destroy(&(sem->cond));
552   
553   //pthread_mutex_destroy(&(sem->mutex));
554   Mutex_Destroy(&(sem->mutex));
555   
556   V3_Free(sem);
557 }
558
559 //return time, back to this later
560 /*-----------------------------------------------------------------------------------*/
561 unsigned long
562 sys_unix_now()
563 {
564   struct timeval tv;
565   struct timezone tz;
566   long sec, usec;
567   unsigned long msec;
568   gettimeofday(&tv, &tz);
569   
570   sec = tv.tv_sec - starttime.tv_sec;
571   usec = tv.tv_usec - starttime.tv_usec;
572   msec = sec * 1000 + usec / 1000;
573     
574   return msec;
575 }
576 /*-----------------------------------------------------------------------------------*/
577 void
578 sys_init()
579 {
580   struct timezone tz;
581   gettimeofday(&starttime, &tz);
582 }
583 /*-----------------------------------------------------------------------------------*/
584 struct sys_timeouts *
585 sys_arch_timeouts(void)
586 {
587   struct sys_thread *thread;
588
589   thread = current_thread();
590   return &thread->timeouts;
591 }
592 /*-----------------------------------------------------------------------------------*/
593 /** sys_prot_t sys_arch_protect(void)
594
595 This optional function does a "fast" critical region protection and returns
596 the previous protection level. This function is only called during very short
597 critical regions. An embedded system which supports ISR-based drivers might
598 want to implement this function by disabling interrupts. Task-based systems
599 might want to implement this by using a mutex or disabling tasking. This
600 function should support recursive calls from the same task or interrupt. In
601 other words, sys_arch_protect() could be called while already protected. In
602 that case the return value indicates that it is already protected.
603
604 sys_arch_protect() is only required if your port is supporting an operating
605 system.
606 */
607 sys_prot_t
608 sys_arch_protect(void)
609 {
610     /* Note that for the UNIX port, we are using a lightweight mutex, and our
611      * own counter (which is locked by the mutex). The return code is not actually
612      * used. */
613     if (lwprot_thread != pthread_self())
614     {
615         /* We are locking the mutex where it has not been locked before *
616         * or is being locked by another thread */
617         pthread_mutex_lock(&lwprot_mutex);
618         lwprot_thread = pthread_self();
619         lwprot_count = 1;
620     }
621     else
622         /* It is already locked by THIS thread */
623         lwprot_count++;
624     return 0;
625 }
626 /*-----------------------------------------------------------------------------------*/
627 /** void sys_arch_unprotect(sys_prot_t pval)
628
629 This optional function does a "fast" set of critical region protection to the
630 value specified by pval. See the documentation for sys_arch_protect() for
631 more information. This function is only required if your port is supporting
632 an operating system.
633 */
634 void
635 sys_arch_unprotect(sys_prot_t pval)
636 {
637     if (lwprot_thread == pthread_self())
638     {
639         if (--lwprot_count == 0)
640         {
641             lwprot_thread = (pthread_t) 0xDEAD;
642             pthread_mutex_unlock(&lwprot_mutex);
643         }
644     }
645 }
646
647 /*-----------------------------------------------------------------------------------*/
648
649 #ifndef MAX_JIFFY_OFFSET
650 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
651 #endif
652
653 #ifndef HZ
654 #define HZ 100
655 #endif
656
657 unsigned long
658 sys_jiffies(void)
659 {
660     struct timeval tv;
661     unsigned long sec = tv.tv_sec;
662     long usec = tv.tv_usec;
663
664     gettimeofday(&tv,NULL);
665
666     if (sec >= (MAX_JIFFY_OFFSET / HZ))
667         return MAX_JIFFY_OFFSET;
668     usec += 1000000L / HZ - 1;
669     usec /= 1000000L / HZ;
670     return HZ * sec + usec;
671 }
672
673 #if PPP_DEBUG
674
675 #include <geekos/serial.h>
676
677 void ppp_trace(int level, const char *format, ...)
678 {
679     va_list args;
680
681     (void)level;
682     va_start(args, format);
683         
684     //vprintf(format, args);
685     SerialPrintList(format, args);
686         
687     va_end(args);
688 }
689 #endif