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 ***/