Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

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  */
00030 
00031 /*********************************************************************************/
00032 /* This file has been written by Sergio Perez Alcañiz <serpeal@disca.upv.es>     */
00033 /*            Departamento de Informática de Sistemas y Computadores             */
00034 /*            Universidad Politécnica de Valencia                                */
00035 /*            Valencia (Spain)                                                   */
00036 /*                                                                               */
00037 /* The RTL-lwIP project has been supported by the Spanish Government Research    */
00038 /* Office (CICYT) under grant TIC2002-04123-C03-03                               */
00039 /*                                                                               */
00040 /* Copyright (c) March, 2003 SISTEMAS DE TIEMPO REAL EMPOTRADOS, FIABLES Y       */
00041 /* DISTRIBUIDOS BASADOS EN COMPONENTES                                           */
00042 /*                                                                               */
00043 /*  This program is free software; you can redistribute it and/or modify         */
00044 /*  it under the terms of the GNU General Public License as published by         */
00045 /*  the Free Software Foundation; either version 2 of the License, or            */
00046 /*  (at your option) any later version.                                          */
00047 /*                                                                               */
00048 /*  This program is distributed in the hope that it will be useful,              */
00049 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of               */
00050 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
00051 /*  GNU General Public License for more details.                                 */
00052 /*                                                                               */
00053 /*  You should have received a copy of the GNU General Public License            */
00054 /*  along with this program; if not, write to the Free Software                  */
00055 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    */
00056 /*                                                                               */
00057 /*  Linking RTL-lwIP statically or dynamically with other modules is making a    */
00058 /*  combined work based on RTL-lwIP.  Thus, the terms and conditions of the GNU  */
00059 /*  General Public License cover the whole combination.                          */
00060 /*                                                                               */
00061 /*  As a special exception, the copyright holders of RTL-lwIP give you           */
00062 /*  permission to link RTL-lwIP with independent modules that communicate with   */
00063 /*  RTL-lwIP solely through the interfaces, regardless of the license terms of   */
00064 /*  these independent modules, and to copy and distribute the resulting combined */
00065 /*  work under terms of your choice, provided that every copy of the combined    */
00066 /*  work is accompanied by a complete copy of the source code of RTL-lwIP (the   */
00067 /*  version of RTL-lwIP used to produce the combined work), being distributed    */
00068 /*  under the terms of the GNU General Public License plus this exception.  An   */
00069 /*  independent module is a module which is not derived from or based on         */
00070 /*  RTL-lwIP.                                                                    */
00071 /*                                                                               */
00072 /*  Note that people who make modified versions of RTL-lwIP are not obligated to */
00073 /*  grant this special exception for their modified versions; it is their choice */
00074 /*  whether to do so.  The GNU General Public License gives permission to        */
00075 /*  release a modified version without this exception; this exception also makes */
00076 /*  it possible to release a modified version which carries forward this         */
00077 /*  exception.                                                                   */
00078 /*********************************************************************************/
00079 
00080 #include <rtl_debug.h>
00081 #include <pthread.h>
00082 #include "lwip/sys.h"
00083 #include "lwip/opt.h"
00084 #include "rtl_malloc.h"
00085 #include "gettimeofday.h"
00086 #include "bcopy.h"
00087 #include <rtl_sched.h>
00088 #include <rtl_sync.h>
00089 #include <rtl_sema.h>
00090 #include <rtl.h>
00091 #include <time.h>
00092 #include <signal.h>
00093 
00094 //#define THREAD_DEBUG
00095 
00096 #define AND(a, b) (a & b)
00097 #define SET(a, b) ((b) <= (0xFF) ? (a=(a | b)) : (a=0x00))
00098 
00099 #define MAX_TIMERS 20
00100 
00101 static struct sys_thread *threads = NULL;
00102 
00103 #define MAX_VECTOR_MALLOCS 50
00104 
00105 static void *mallocs[MAX_VECTOR_MALLOCS];
00106 static int malloc_index = 0;
00107 static int n_mallocs=0, n_frees = 0;
00108 
00109 struct sys_timeouts {
00110   timer_t timer;
00111   struct sigevent timer_event_spec;
00112   struct itimerspec ospec;
00113   struct itimerspec old_setting;
00114   struct sigaction sa;
00115   int signal;
00116 };
00117 
00118 static struct sys_timeouts vector_of_timers[MAX_TIMERS];
00119 static int timer_index = 0;
00120 static int signal = 0;
00121 
00122 struct sys_mbox_msg {
00123   struct sys_mbox_msg *next;
00124   void *msg;
00125 };
00126 
00127 #define SYS_MBOX_SIZE 100
00128 
00129 struct sys_sem {
00130   sem_t sem;
00131   unsigned int c;
00132 };
00133 
00134 struct sys_mbox {
00135   u16_t first, last;
00136   void *msgs[SYS_MBOX_SIZE];
00137   struct sys_sem *mail;
00138   struct sys_sem *mutex;
00139 };
00140 
00141 struct sys_thread {
00142   struct sys_thread *next;
00143   pthread_t pthread;
00144   char *stack;
00145   struct sys_timeouts *timeouts;
00146 #ifdef THREAD_DEBUG
00147   char *name;
00148 #endif /* THREAD_DEBUG */
00149   char flags;
00150 };
00151 
00152 static struct sys_sem *sys_sem_new_(u8_t count);
00153 
00154 /*-----------------------------------------------------------------------------------*/
00155 int sys_sem_post(sem_t *sem)
00156 {
00157   sem_post(sem);
00158   return 0;
00159 }
00160 
00161 /*-----------------------------------------------------------------------------------*/
00162 int sys_sem_signal_pre(struct sys_sem *sem)
00163 {
00164   rtl_irqstate_t flags;
00165 
00166   sem->c++;
00167   if(sem->c > 1){
00168     sem->c = 1;
00169   }
00170   sem->sem.value = sem->c;
00171 
00172   // I need this implementation because it doesn't call to rtl_schedule
00173   rtl_spin_lock_irqsave (&sem->sem.lock, flags);
00174 
00175   ++(sem->sem.value);
00176   rtl_wait_wakeup (&sem->sem.wait);
00177   
00178   rtl_spin_unlock_irqrestore(&sem->sem.lock, flags);
00179 
00180   return 0;
00181 }
00182 
00183 /*-----------------------------------------------------------------------------------*/
00184 void sys_stop_interrupts(unsigned int *state){
00185   rtl_no_interrupts((rtl_irqstate_t) *state);
00186 }
00187 
00188 /*-----------------------------------------------------------------------------------*/
00189 void sys_allow_interrupts(unsigned int *state){
00190     rtl_restore_interrupts((rtl_irqstate_t) *state);
00191 }
00192 
00193 /*-----------------------------------------------------------------------------------*/
00194 int obtain_index_to_free(void *mem){
00195   int i;
00196 
00197   for(i=0; i< MAX_VECTOR_MALLOCS; i++)
00198     if(mallocs[i] == mem)
00199       return i;
00200   return -1;
00201 }
00202 
00203 /*-----------------------------------------------------------------------------------*/
00204 void free_all_resources(void){
00205   int i;
00206 
00207   for(i=0; i<MAX_VECTOR_MALLOCS; i++)
00208     if(mallocs[i] != NULL){
00209       rtl_free(mallocs[i]);
00210       n_frees++;
00211     }
00212 }
00213 
00214 /*-----------------------------------------------------------------------------------*/
00215 void *sys_malloc(size_t size){
00216   void *tmp;
00217   int entry = malloc_index % MAX_VECTOR_MALLOCS;
00218   unsigned int state;
00219 
00220   sys_stop_interrupts(&state);
00221 
00222   while(mallocs[entry] != NULL)
00223     entry = ++malloc_index % MAX_VECTOR_MALLOCS;
00224 
00225   tmp = mallocs[entry] = rtl_malloc(size);
00226 
00227   if(tmp != NULL){
00228     n_mallocs++;
00229     malloc_index++;
00230   }else
00231     rtl_printf("\n\n\n\nERROR: Not enough memory!\n\n\n\n");
00232 
00233   sys_allow_interrupts(&state);
00234 
00235   return tmp;
00236 }
00237 
00238 /*-----------------------------------------------------------------------------------*/
00239 void sys_free(void *ptr){
00240   int index;
00241   unsigned int state;
00242 
00243   sys_stop_interrupts(&state);
00244 
00245   if(ptr != NULL){
00246     index = obtain_index_to_free(ptr);
00247     if(index != -1){
00248       mallocs[index] = NULL;
00249       rtl_free(ptr);
00250       n_frees++;
00251     }else{
00252       rtl_printf("sys_free: no memory reserved for this pointer\n");
00253     }
00254   }
00255 
00256   sys_allow_interrupts(&state);
00257 }
00258 
00259 /*-----------------------------------------------------------------------------------*/
00260 static struct sys_thread *
00261 sys_current_thread(void)
00262 {
00263   struct sys_thread *st;
00264   pthread_t pt;
00265 
00266   pt = pthread_self();
00267 
00268   for(st = threads; st != NULL; st = st->next) {
00269 
00270     /* If the thread represented by st has exited and it's memory hasn't been deallocated ... */
00271     if(AND(st->flags,0x81)== 0x80){
00272       sys_free(st->stack);
00273       SET(st->flags, 0x81);
00274       continue;
00275     }
00276 
00277     if(pthread_equal(st->pthread, pt)) 
00278       return st;
00279   }
00280 
00281   return NULL;
00282 }
00283 
00284 /*-----------------------------------------------------------------------------------*/
00285 static struct sys_thread *
00286 sys_search_thread(void *pthread)
00287 {
00288   struct sys_thread *st;
00289   pthread_t pt = (pthread_t) pthread;
00290 
00291   for(st = threads; st != NULL; st = st->next) {
00292 
00293     /* If the thread represented by st has exited and it's memory hasn't been deallocated ... */
00294     if(AND(st->flags,0x81)== 0x80){
00295       sys_free(st->stack);
00296       SET(st->flags, 0x81);
00297       continue;
00298     }
00299 
00300     if(pthread_equal(st->pthread, pt)) 
00301       return st;
00302   }
00303 
00304   return NULL;
00305 }
00306 
00307 /*-----------------------------------------------------------------------------------*/
00308 #ifdef THREAD_DEBUG
00309 char *thread_name(void)
00310 {
00311   struct sys_thread *sys_thread;
00312 
00313   sys_thread = sys_current_thread();
00314 
00315   return (char *) sys_thread->name;
00316 }
00317 #endif
00318 
00319 /*-----------------------------------------------------------------------------------*/
00320 struct thread_start_param {
00321   struct sys_thread *thread;
00322   void (* function)(void *);
00323   void *arg;
00324 };
00325 
00326 /*-----------------------------------------------------------------------------------*/
00327 static void *
00328 thread_start(void *arg)
00329 {
00330   struct thread_start_param *tp = arg;
00331 
00332   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00333   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
00334 
00335   tp->thread->pthread = pthread_self();
00336   tp->function(tp->arg);
00337 
00338   sys_free(tp);
00339 
00340   return NULL;
00341 }
00342 
00343 /*-----------------------------------------------------------------------------------*/
00344 void *sys_thread_exit(void)
00345 {
00346   struct sys_thread *thread;
00347   void *status = NULL;
00348   
00349   thread = sys_current_thread();
00350 
00351   if(thread->stack != NULL) //i.e. It is a standalone thread
00352     SET(thread->flags, 0x80);
00353   else SET(thread->flags, 0x81);
00354 
00355   pthread_exit(status);
00356   return NULL;
00357 }
00358 
00359 /*-----------------------------------------------------------------------------------*/
00360 int sys_thread_delete(void *pthread)
00361 {
00362   struct sys_thread *thread;
00363   
00364   thread = sys_search_thread(pthread);
00365 
00366   if(thread != NULL){
00367     if(thread->stack != NULL) //i.e. It is a standalone thread
00368       SET(thread->flags, 0x80);
00369     else SET(thread->flags, 0x81);
00370     pthread_cancel(pthread);
00371     pthread_join(pthread,NULL);
00372     return 0;
00373   }
00374 
00375 
00376   return -1;
00377 }
00378 
00379 /*-----------------------------------------------------------------------------------*/
00380 void sys_thread_register(void *pthread)
00381 {
00382   struct sys_thread *thread;
00383 
00384   thread = sys_malloc(sizeof(struct sys_thread));
00385 
00386 
00387   thread->next = threads;
00388   thread->pthread = (pthread_t) pthread;
00389   thread->stack = NULL;
00390   thread->timeouts = NULL;
00391 
00392   SET(thread->flags, 0x01);
00393   threads = thread;
00394 
00395   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00396   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
00397 
00398 }
00399 
00400 
00401 /*-----------------------------------------------------------------------------------*/
00402 void *
00403 #ifdef THREAD_DEBUG
00404 sys_thread_new(void (* function)(void *arg), void *arg, unsigned long period, char *name, int name_len)
00405 #else
00406      sys_thread_new(void (* function)(void *arg), void *arg, unsigned long period)
00407 #endif
00408 {
00409   struct sys_thread *thread;
00410   struct thread_start_param *thread_param;
00411   pthread_attr_t attr;
00412 
00413   thread = sys_malloc(sizeof(struct sys_thread));
00414 
00415   if(thread != NULL){
00416 
00417     thread->next = threads;
00418 
00419     SET(thread->flags, 0x00);
00420 
00421     thread->stack = (char *) sys_malloc(sizeof(char)*THREAD_STACK_SIZE);
00422 
00423     thread->timeouts = NULL;
00424 
00425 #ifdef THREAD_DEBUG
00426     thread->name = (char *) sys_malloc(20);
00427     bcopy(name, thread->name, name_len);
00428 #endif
00429 
00430     if(thread->stack == NULL){
00431       sys_free(thread);
00432       rtl_printf("ERROR: Not enough memory to create new thread's stack\n");
00433       return NULL;
00434     }
00435 
00436     threads = thread;
00437 
00438     pthread_attr_init(&attr);
00439 
00440 
00441     /* Because it's a thread which is trying to create another thread, RTLinux
00442        only allows that by passing to the new thread it's stack */    
00443     pthread_attr_setstackaddr(&attr, thread->stack);
00444     pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
00445     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00446     
00447     thread_param = sys_malloc(sizeof(struct thread_start_param));
00448     
00449     if(thread_param == NULL){
00450       sys_free(thread->stack);
00451       sys_free(thread);
00452       rtl_printf("ERROR: Not enough memory to create thread start param\n");
00453       return NULL;
00454     }
00455     
00456     thread_param->function = function;
00457     thread_param->arg = arg;
00458     thread_param->thread = thread;
00459     
00460     if(pthread_create(&(thread->pthread),&attr, thread_start, thread_param)) {
00461       rtl_printf("\nsys_thread_new: pthread_create  0x%x 0x%x\n", pthread_self(),thread->pthread);
00462       rtl_printf("Kernel Panic\n");
00463       return NULL;
00464     }
00465 
00466     if(period != 0)
00467       pthread_make_periodic_np(thread->pthread, gethrtime(), period);
00468 
00469     return (void *) thread->pthread;
00470   }
00471   
00472   rtl_printf("ERROR: Not enough memory to create thread\n"); 
00473   return NULL;
00474 }
00475 
00476 /*-----------------------------------------------------------------------------------*/
00477 struct sys_mbox *
00478 sys_mbox_new()
00479 {
00480   struct sys_mbox *mbox;
00481 
00482   mbox = sys_malloc(sizeof(struct sys_mbox));
00483 
00484   if(mbox != NULL){
00485     
00486     mbox->first = mbox->last = 0;
00487     mbox->mail = sys_sem_new_(0);
00488     mbox->mutex = sys_sem_new_(1);
00489 
00490     return mbox;
00491   }else{
00492     rtl_printf("ERROR: Not enough memory to create mbox\n");
00493     return NULL;
00494   }
00495 }
00496 
00497 /*-----------------------------------------------------------------------------------*/
00498 void
00499 sys_mbox_free(struct sys_mbox *mbox)
00500 {
00501 
00502   if(mbox != SYS_MBOX_NULL) {
00503 
00504     sys_sem_wait(mbox->mutex);
00505     
00506     sys_sem_free(mbox->mail);
00507     sys_sem_free(mbox->mutex);
00508     mbox->mail = mbox->mutex = NULL;
00509 
00510     sys_free(mbox);
00511   }
00512 }
00513 /*-----------------------------------------------------------------------------------*/
00514 void
00515 sys_mbox_post(struct sys_mbox *mbox, void *msg)
00516 {
00517   u8_t first;
00518   unsigned int state;
00519 
00520   sys_sem_wait(mbox->mutex);
00521   
00522   mbox->msgs[mbox->last] = msg;
00523 
00524   if(mbox->last == mbox->first) {
00525     first = 1;
00526   } else {
00527     first = 0;
00528   }
00529   
00530   mbox->last++;
00531   if(mbox->last == SYS_MBOX_SIZE) {
00532     mbox->last = 0;
00533   }
00534 
00535   sys_stop_interrupts(&state);
00536   
00537   if(first)
00538     sys_sem_signal_pre(mbox->mail);
00539 
00540   sys_sem_signal(mbox->mutex);
00541   
00542   sys_allow_interrupts(&state);
00543 
00544 }
00545 /*-----------------------------------------------------------------------------------*/
00546 u16_t
00547 sys_arch_mbox_fetch(struct sys_mbox *mbox, void **msg, u16_t timeout)
00548 {
00549   u16_t time = 1;
00550   
00551   /* The mutex lock is quick so we don't bother with the timeout
00552      stuff here. */
00553   sys_arch_sem_wait(mbox->mutex, 0);
00554   while(mbox->first == mbox->last) {
00555     sys_sem_signal(mbox->mutex);
00556     /* We block while waiting for a mail to arrive in the mailbox. We
00557        must be prepared to timeout. */
00558     if(timeout != 0) {
00559 
00560       time = sys_arch_sem_wait(mbox->mail, timeout);
00561       
00562       /* If time == 0, the sem_wait timed out, and we return 0. */
00563       if(time == 0) {
00564         return 0;
00565       }
00566     } else
00567       sys_arch_sem_wait(mbox->mail, 0);
00568 
00569     sys_arch_sem_wait(mbox->mutex, 0);
00570   }
00571   
00572   if(msg != NULL) {
00573     *msg = mbox->msgs[mbox->first];
00574   }
00575   
00576   mbox->first++;
00577   if(mbox->first == SYS_MBOX_SIZE) {
00578     mbox->first = 0;
00579   }    
00580   
00581   sys_sem_signal(mbox->mutex);
00582   
00583   return time;
00584 }
00585 
00586 /*-----------------------------------------------------------------------------------*/
00587 struct sys_sem *
00588 sys_sem_new(u8_t count)
00589 {
00590   return sys_sem_new_(count);
00591 }
00592 
00593 /*-----------------------------------------------------------------------------------*/
00594 static struct sys_sem *
00595 sys_sem_new_(u8_t count)
00596 {
00597   struct sys_sem *sem;
00598 
00599   sem = sys_malloc(sizeof(struct sys_sem));
00600 
00601   if(sem != NULL){
00602     sem->c = count;
00603     sem_init(&(sem->sem),0,count);
00604     return sem;
00605   }else{
00606     rtl_printf("ERROR: Not enough memory to create semaphore\n");
00607     return NULL;
00608   }
00609 }
00610 
00611 /*-----------------------------------------------------------------------------------*/
00612 static u16_t wait_for_semaphore(struct sys_sem *sem, u16_t timeout){
00613   unsigned int tdiff;
00614   unsigned long sec, usec;
00615   struct timeval rtime1, rtime2;
00616   struct timespec ts;
00617   struct timezone tz;
00618   int retval;
00619 
00620   if(timeout > 0) {
00621     /* Get a timestamp and add the timeout value. */
00622     gettimeofday(&rtime1, &tz);
00623 
00624     sec = rtime1.tv_sec;
00625     usec = rtime1.tv_usec;
00626     usec += timeout % 1000 * 1000;  
00627     sec += (int)(timeout / 1000) + (int)(usec / 1000000);
00628     usec = usec % 1000000;
00629     ts.tv_nsec = usec * 1000;
00630     ts.tv_sec = sec;
00631  
00632     retval = sem_timedwait(&(sem->sem),&ts);   
00633 
00634     if(retval == -1) {
00635       return 0;
00636     } else {
00637       /* Calculate for how long we waited for the cond. */
00638       gettimeofday(&rtime2, &tz);
00639       tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 +  
00640         (rtime2.tv_usec - rtime1.tv_usec) / 1000;
00641       if(tdiff == 0) {
00642         return 1;
00643       }
00644       return tdiff;
00645     }
00646   } else {
00647     sem_wait(&(sem->sem));
00648     return 0;
00649   }
00650 }
00651 
00652 /*-----------------------------------------------------------------------------------*/
00653 u16_t
00654 sys_arch_sem_wait(struct sys_sem *sem, u16_t timeout)
00655 {
00656   u16_t time = 1;
00657 
00658   sem->sem.value = sem->c;
00659 
00660   while(sem->c <= 0) {
00661     
00662     if(timeout > 0) {
00663 
00664       time = wait_for_semaphore(sem, timeout);
00665       if(time == 0) 
00666         return 0;
00667     } else {
00668       wait_for_semaphore(sem,0);
00669     }
00670   }
00671 
00672   sem->c--;
00673   sem->sem.value = sem->c;
00674 
00675   return time;
00676 }
00677 
00678 /*-----------------------------------------------------------------------------------*/
00679 int
00680 sys_sem_signal(struct sys_sem *sem)
00681 {
00682 
00683   sem->c++;
00684   if(sem->c > 1)
00685     sem->c = 1;
00686 
00687   sem->sem.value = sem->c;
00688 
00689   return sys_sem_post(&(sem->sem));
00690 }
00691 
00692 /*-----------------------------------------------------------------------------------*/
00693 void
00694 sys_sem_free(struct sys_sem *sem)
00695 {
00696   if(sem != NULL)
00697     sem_destroy(&(sem->sem));
00698 
00699   sys_free(sem);
00700 }
00701 
00702 /*-----------------------------------------------------------------------------------*/
00703 void sys_arch_close(void)
00704 {
00705   struct sys_thread *st;
00706 
00707   for(st = threads; st != NULL; st = st->next) {
00708     if(AND(st->flags,0x81)== 0x80){ //i.e. It is a standalone thread finished
00709       sys_free(st->stack);
00710     }else if(AND(st->flags,0xff)==0x00){ //i.e A thread still working
00711       pthread_delete_np(st->pthread);
00712       //This line is necessary because the thread could be standalone.
00713       //If it is not, nothing happens
00714       sys_free(st->stack);               
00715     }else if(AND(st->flags,0xff)==0x01){ //i.e A registered thread still working
00716       pthread_cancel(st->pthread);
00717       pthread_join(st->pthread,NULL);
00718     }
00719   }
00720 
00721   free_all_resources();
00722 
00723   return;
00724 }
00725 
00726 /*-----------------------------------------------------------------------------------*/
00727 void
00728 sys_init(void)
00729 {
00730   int i,retval;
00731 
00732   for(i=0; i<=500; i++)
00733     mallocs[i] = NULL;
00734 
00735   for(i=0; i<MAX_TIMERS; i++){
00736     vector_of_timers[i].signal = RTL_SIGRTMIN + signal++;
00737     vector_of_timers[i].timer_event_spec.sigev_notify = SIGEV_SIGNAL;
00738     vector_of_timers[i].timer_event_spec.sigev_signo = vector_of_timers[i].signal;
00739     vector_of_timers[i].timer_event_spec.sigev_value.sival_int = 13;
00740     
00741     retval = timer_create(CLOCK_REALTIME, &(vector_of_timers[i].timer_event_spec), &(vector_of_timers[i].timer));
00742     
00743     if (retval) {
00744       rtl_printf("timer_create(CLOCK_REALTIME) failed:\n");
00745     }
00746   }
00747 }
00748 
00749 /*-----------------------------------------------------------------------------------*/
00750 void
00751 sys_sem_wait(sys_sem_t sem)
00752 {
00753   sys_arch_sem_wait(sem, 0);
00754 }
00755 
00756 /*-----------------------------------------------------------------------------------*/
00757 int sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
00758 {
00759   return sys_arch_sem_wait(sem, timeout);
00760 }
00761 
00762 /*-----------------------------------------------------------------------------------*/
00763 void
00764 sys_mbox_fetch(sys_mbox_t mbox, void **msg)
00765 {
00766   sys_arch_mbox_fetch(mbox, msg, 0);
00767 }
00768 
00769 /*-----------------------------------------------------------------------------------*/
00770 void sys_timeout(u16_t msecs, sys_timeout_handler h, void *arg)
00771 {
00772   struct sys_thread *thread;
00773   int err, sec = 0, nsec = 0;
00774 
00775   thread = sys_current_thread();
00776 
00777   if(thread->timeouts == NULL){
00778     thread->timeouts = &vector_of_timers[timer_index++];
00779   }
00780 
00781   thread->timeouts->sa.sa_handler = h;
00782   thread->timeouts->sa.sa_mask=0;
00783   thread->timeouts->sa.sa_flags=0;
00784   thread->timeouts->sa.sa_focus=0;
00785 
00786   rtl_sigemptyset(&(thread->timeouts->sa.sa_mask));
00787 
00788   if (sigaction(thread->timeouts->signal, &(thread->timeouts->sa), NULL)) {
00789     rtl_printf("sigaction failed");
00790   }  
00791 
00792   if(msecs >= 100){
00793     sec = msecs / 1000;
00794     nsec = (msecs % 1000) * 1000000 ;
00795   }else{
00796     nsec = msecs * 1000000;
00797   }
00798 
00799   thread->timeouts->ospec.it_value.tv_sec = sec;
00800   thread->timeouts->ospec.it_value.tv_nsec = nsec;
00801   thread->timeouts->ospec.it_interval.tv_sec = 0;
00802   thread->timeouts->ospec.it_interval.tv_nsec = 0;
00803 
00804   err = timer_settime(thread->timeouts->timer, 0, &(thread->timeouts->ospec), &(thread->timeouts->old_setting));
00805 
00806   return;  
00807 }
00808 
00809 /*-----------------------------------------------------------------------------------*/
00810 void sys_untimeout(sys_timeout_handler h, void *arg){
00811   struct sys_thread *thread;
00812 
00813   thread = sys_current_thread();
00814 
00815   if(thread->timeouts != NULL)
00816     timer_delete(thread->timeouts->timer);
00817 }

Generated on Wed Jan 14 12:58:57 2004 for RTL-lwIP-0.4 by doxygen 1.3.4