00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
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
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
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
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
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
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)
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)
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
00442
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
00552
00553 sys_arch_sem_wait(mbox->mutex, 0);
00554 while(mbox->first == mbox->last) {
00555 sys_sem_signal(mbox->mutex);
00556
00557
00558 if(timeout != 0) {
00559
00560 time = sys_arch_sem_wait(mbox->mail, timeout);
00561
00562
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
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
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){
00709 sys_free(st->stack);
00710 }else if(AND(st->flags,0xff)==0x00){
00711 pthread_delete_np(st->pthread);
00712
00713
00714 sys_free(st->stack);
00715 }else if(AND(st->flags,0xff)==0x01){
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 }