sys_arch.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001, Swedish Institute of Computer Science.
00003  * All rights reserved. 
00004  *
00005  * Redistribution and use in source and binary forms, with or without 
00006  * modification, are permitted provided that the following conditions 
00007  * are met: 
00008  * 1. Redistributions of source code must retain the above copyright 
00009  *    notice, this list of conditions and the following disclaimer. 
00010  * 2. Redistributions in binary form must reproduce the above copyright 
00011  *    notice, this list of conditions and the following disclaimer in the 
00012  *    documentation and/or other materials provided with the distribution. 
00013  * 3. Neither the name of the Institute nor the names of its contributors 
00014  *    may be used to endorse or promote products derived from this software 
00015  *    without specific prior written permission. 
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
00027  * SUCH DAMAGE. 
00028  *
00029  * This file is part of the lwIP TCP/IP stack.
00030  * 
00031  * Author:     Adam Dunkels      <adam@sics.se>
00032  * Sub Author: Christopher Olsen <colsen@domaintlantic.com>
00033  *
00034  * Notes:
00035  *  Modified to work with the ubix operating system
00036  *
00037  * $Log: sys__arch_8c-source.html,v $
00037  * Revision 1.5  2006/12/12 14:09:08  reddawg
00037  * Changes
00037  *
00038  * Revision 1.1.1.1  2006/06/01 12:46:16  reddawg
00039  * ubix2
00040  *
00041  * Revision 1.2  2005/10/12 00:13:37  reddawg
00042  * Removed
00043  *
00044  * Revision 1.1.1.1  2005/09/26 17:24:31  reddawg
00045  * no message
00046  *
00047  * Revision 1.6  2004/09/11 21:30:37  apwillia
00048  * Fix race conditions in net thread and scheduler
00049  *
00050  * Revision 1.5  2004/09/07 20:58:35  reddawg
00051  * time to roll back i can't think straight by friday
00052  *
00053  * Revision 1.4  2004/05/25 22:49:29  reddawg
00054  * Stupid Old CODE!!!
00055  *
00056  * Revision 1.3  2004/05/19 04:07:43  reddawg
00057  * kmalloc(size,pid) no more it is no kmalloc(size); the way it should of been
00058  *
00059  * Revision 1.2  2004/05/19 03:35:02  reddawg
00060  * Fixed A Few Ordering Issues In The Service Startup Routine
00061  *
00062  * Revision 1.1.1.1  2004/04/15 12:07:14  reddawg
00063  * UbixOS v1.0
00064  *
00065  * Revision 1.13  2004/04/13 21:29:53  reddawg
00066  * We now have sockets working. Lots of functionality to be added to continually
00067  * improve on the existing layers now its clean up time to get things in a better
00068  * working order.
00069  *
00070  * Revision 1.12  2004/04/13 16:08:07  reddawg
00071  * Removed all of the old debug code the problem seems to be in ubthreads with
00072  * ubthread_mutex_init
00073  *
00074  * Revision 1.11  2004/04/13 16:05:40  reddawg
00075  * Function Renaming
00076  *
00077  *
00078  *
00079  * $Id: sys__arch_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
00080  */
00081 
00082 #include <ubixos/types.h>
00083 #include <ubixos/sched.h>
00084 #include <ubixos/ubthread.h>
00085 #include <ubixos/kpanic.h>
00086 #include <lib/kprintf.h>
00087 #include <lib/kmalloc.h>
00088 
00089 #include "net/debug.h"
00090 #include "net/sys.h"
00091 #include "net/opt.h"
00092 #include "net/stats.h"
00093 
00094 #include <ubixos/spinlock.h>
00095 
00096 #define UMAX(a, b)      ((a) > (b) ? (a) : (b))
00097 
00098 static struct sys_thread *threads = 0x0;
00099 static spinLock_t netThreadSpinlock = SPIN_LOCK_INITIALIZER;
00100 
00101 struct sys_mbox_msg {
00102   struct sys_mbox_msg *next;
00103   void *msg;
00104 };
00105 
00106 #define SYS_MBOX_SIZE 100
00107 
00108 struct sys_mbox {
00109   uInt16 first, last;
00110   void *msgs[SYS_MBOX_SIZE];
00111   struct sys_sem *mail;
00112   struct sys_sem *mutex;
00113 };
00114 
00115 struct sys_sem {
00116   unsigned int c;
00117   ubthread_cond_t cond;
00118   ubthread_mutex_t mutex;
00119 };
00120 
00121 struct sys_thread {
00122   struct sys_thread *next;
00123   struct sys_timeouts timeouts;
00124   kTask_t *ubthread;
00125 };
00126 
00127 
00128 static struct timeval starttime;
00129 
00130 static struct sys_sem *sys_sem_new_(uInt8 count);
00131 static void sys_sem_free_(struct sys_sem *sem);
00132 
00133 static uInt16 cond_wait(ubthread_cond_t *cond, ubthread_mutex_t *mutex, uInt16 timeout);
00134 
00135 static struct sys_thread *current_thread(void) {
00136   struct sys_thread *st;
00137   kTask_t *pt;
00138   pt = ubthread_self();
00139   spinLock(&netThreadSpinlock);
00140   for(st = threads; st != NULL; st = st->next) {
00141     if(st->ubthread == pt) {
00142       spinUnlock(&netThreadSpinlock);
00143       return st;
00144     }
00145   }
00146   spinUnlock(&netThreadSpinlock);
00147   kprintf("sys: current_thread: could not find current thread!\n");
00148   kprintf("This is due to a race condition in the LinuxThreads\n");
00149   kprintf("ubthreads implementation. Start the program again.\n");
00150   
00151   kpanic("ABORT");
00152   return(0x0);
00153   }
00154 
00155 
00156 struct thread_start_param {
00157   struct sys_thread *thread;
00158   void (* function)(void *);
00159   void *arg;
00160   };
00161 
00162 /*
00163 static void *thread_start(void *arg) {
00164   struct thread_start_param *tp = arg;
00165   tp->thread->ubthread = ubthread_self();
00166   tp->function(tp->arg);
00167   kfree(tp);
00168   return(NULL);
00169   }
00170 */
00171 
00172 void sys_thread_new(void (* function)(void), void *arg) {
00173   struct sys_thread *thread = 0x0;
00174   //struct thread_start_param *thread_param;
00175   kprintf("sys_thread: [0x%X]\n",sizeof(struct sys_thread));
00176   
00177   thread = kmalloc(sizeof(struct sys_thread));
00178   kprintf("THREAD: [0x%X]\n",thread);
00179   spinLock(&netThreadSpinlock);
00180   thread->next = threads;
00181   thread->timeouts.next = NULL;
00182   thread->ubthread = 0x0;
00183   threads = thread;
00184   spinUnlock(&netThreadSpinlock);
00185   
00186 
00187   /*
00188   thread_param = kmalloc(sizeof(struct thread_start_param));
00189   
00190   thread_param->function = function;
00191   thread_param->arg = arg;
00192   thread_param->thread = thread;
00193   */
00194   //execThread((void *)function,0x0,0x0);
00195  
00196   kprintf("thread->ubthread: [0x%X]\n",thread->ubthread);
00197   if(ubthread_create(&thread->ubthread, 0x0,(void *)(function), arg) != 0x0) {
00198     kpanic("sys_thread_new: ubthread_create");
00199     }
00200   kprintf("thread->ubthread: [0x%X]\n",thread->ubthread); 
00201   
00202   }
00203 
00204 struct sys_mbox *sys_mbox_new() {
00205   struct sys_mbox *mbox;
00206 
00207   mbox = kmalloc(sizeof(struct sys_mbox));
00208   mbox->first = mbox->last = 0;
00209   mbox->mail = sys_sem_new_(0);
00210   mbox->mutex = sys_sem_new_(1);
00211   
00212   return(mbox);
00213   }
00214 
00215 void sys_mbox_free(struct sys_mbox *mbox) {
00216   if (mbox != SYS_MBOX_NULL) {
00217     sys_sem_wait(mbox->mutex);
00218     
00219     sys_sem_free_(mbox->mail);
00220     sys_sem_free_(mbox->mutex);
00221     mbox->mail = mbox->mutex = NULL;
00222     //kprintf("sys_mbox_free: mbox 0x%lx\n", mbox);
00223     kfree(mbox);
00224     }
00225   }
00226 
00227 void sys_mbox_post(struct sys_mbox *mbox, void *msg) {
00228   uInt8 first;
00229   
00230   sys_sem_wait(mbox->mutex);
00231   
00232   //kprintf("sys_mbox_post: mbox %p msg %p\n", mbox, msg);
00233 
00234   mbox->msgs[mbox->last] = msg;
00235 
00236   if (mbox->last == mbox->first) {
00237     first = 1;
00238     }
00239   else {
00240     first = 0;
00241     }
00242   
00243   mbox->last++;
00244   if(mbox->last == SYS_MBOX_SIZE) {
00245     mbox->last = 0;
00246     }
00247 
00248   if(first) {
00249     sys_sem_signal(mbox->mail);
00250     }
00251   sys_sem_signal(mbox->mutex);
00252   }
00253 
00254 uInt16 sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, uInt16 timeout) {
00255   uInt16 time = 1;
00256   
00257   /* The mutex lock is quick so we don't bother with the timeout
00258      stuff here. */
00259   sys_arch_sem_wait(mbox->mutex, 0);
00260   
00261   while(mbox->first == mbox->last) {
00262     sys_sem_signal(mbox->mutex);
00263     
00264     /* We block while waiting for a mail to arrive in the mailbox. We
00265        must be prepared to timeout. */
00266     if(timeout != 0) {
00267       time = sys_arch_sem_wait(mbox->mail, timeout);
00268       
00269       /* If time == 0, the sem_wait timed out, and we return 0. */
00270       if(time == 0) {
00271         return 0;
00272       }
00273     } else {
00274       sys_arch_sem_wait(mbox->mail, 0);
00275     }
00276     
00277     sys_arch_sem_wait(mbox->mutex, 0);
00278   }
00279   
00280   if(msg != NULL) {
00281     //kprintf("sys_mbox_fetch: mbox %p msg %p\n", mbox, *msg);
00282     *msg = mbox->msgs[mbox->first];
00283   }
00284   
00285   mbox->first++;
00286   if(mbox->first == SYS_MBOX_SIZE) {
00287     mbox->first = 0;
00288   }    
00289   
00290   sys_sem_signal(mbox->mutex);
00291   
00292   return(time);
00293   }
00294 
00295 struct sys_sem *sys_sem_new(uInt8 count) {
00296   return sys_sem_new_(count);
00297   }
00298 
00299 static struct sys_sem *sys_sem_new_(uInt8 count) {
00300   struct sys_sem *sem;
00301   
00302   sem = kmalloc(sizeof(struct sys_sem));
00303   sem->c = count;
00304   
00305   ubthread_cond_init(&(sem->cond), NULL);
00306   ubthread_mutex_init(&(sem->mutex), NULL);
00307   
00308   return sem;
00309   }
00310 
00311 static uInt16 cond_wait(ubthread_cond_t *cond, ubthread_mutex_t *mutex, uInt16 timeout) {
00312   unsigned int tdiff;
00313   unsigned long sec, usec;
00314   struct timeval rtime1, rtime2;
00315   struct timespec ts;
00316   struct timezone tz;
00317   int retval;
00318 
00319   if (timeout > 0) {
00320     /* Get a timestamp and add the timeout value. */
00321     gettimeofday(&rtime1, &tz);
00322     sec = rtime1.tv_sec;
00323     usec = rtime1.tv_usec;
00324     usec += timeout % 1000 * 1000;  
00325     sec += (int)(timeout / 1000) + (int)(usec / 1000000);
00326     usec = usec % 1000000;
00327     ts.tv_nsec = usec * 1000;
00328     ts.tv_sec = sec;
00329     
00330     retval = ubthread_cond_timedwait(cond, mutex, &ts);
00331     if (retval == ETIMEDOUT) {
00332       return 0;
00333       }
00334     else {
00335       /* Calculate for how long we waited for the cond. */
00336       gettimeofday(&rtime2, &tz);
00337       tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +  
00338         (rtime2.tv_usec - rtime1.tv_usec) / 1000;
00339       if (tdiff == 0) {
00340         return 1;
00341         }
00342       return tdiff;
00343       }
00344     }
00345   else {
00346     ubthread_cond_wait(cond, mutex);
00347     return 0;
00348     }
00349   }
00350 
00351 uInt16 sys_arch_sem_wait(struct sys_sem *sem, uInt16 timeout) {
00352   uInt16 time = 1;
00353   ubthread_mutex_lock(&(sem->mutex));
00354   while(sem->c <= 0) {
00355     if(timeout > 0) {
00356       time = cond_wait(&(sem->cond), &(sem->mutex), timeout);
00357       if(time == 0) {
00358         ubthread_mutex_unlock(&(sem->mutex));
00359         return 0;
00360       }
00361     } else {
00362       cond_wait(&(sem->cond), &(sem->mutex), 0);
00363     }
00364   }
00365   sem->c--;
00366   ubthread_mutex_unlock(&(sem->mutex));
00367   return(time);
00368   }
00369 
00370 void sys_sem_signal(struct sys_sem *sem) {
00371   ubthread_mutex_lock(&(sem->mutex));
00372   sem->c++;
00373   if(sem->c > 1)
00374     sem->c = 1;
00375   ubthread_cond_signal(&(sem->cond));
00376   ubthread_mutex_unlock(&(sem->mutex));
00377   }
00378 
00379 void sys_sem_free(struct sys_sem *sem) {
00380   if(sem != SYS_SEM_NULL) {
00381     sys_sem_free_(sem);
00382     } 
00383   }
00384 
00385 static void sys_sem_free_(struct sys_sem *sem) {
00386   ubthread_cond_destroy(&(sem->cond));
00387   ubthread_mutex_destroy(&(sem->mutex));
00388   kfree(sem);
00389   }
00390 
00391 unsigned long sys_unix_now() {
00392   struct timeval tv;
00393   struct timezone tz;
00394   long sec, usec;
00395   unsigned long msec;
00396   gettimeofday(&tv, &tz);
00397 
00398   sec = tv.tv_sec - starttime.tv_sec;
00399   usec = tv.tv_usec - starttime.tv_usec;
00400   msec = sec * 1000 + usec / 1000;
00401   return msec;
00402   }
00403 
00404 void sys_init() {
00405   struct timezone tz;
00406   gettimeofday(&starttime, &tz);
00407   }
00408 
00409 struct sys_timeouts *sys_arch_timeouts(void) {
00410   struct sys_thread *thread;
00411   thread = current_thread();
00412   return(&thread->timeouts);
00413   }
00414 
00415 /***
00416  END
00417  ***/

Generated on Tue Dec 12 08:52:07 2006 for UbixOS V2 by  doxygen 1.4.7