rtask.c
Go to the documentation of this file.
00001 00040 #include "rtask.h" 00041 #include "cfg/cfg_rtask.h" 00042 #include <cfg/module.h> // MOD_CHECK 00043 00044 #define LOG_LEVEL RTASK_LOG_LEVEL 00045 #define LOG_FORMAT RTASK_LOG_FORMAT 00046 #include <cfg/log.h> 00047 00048 #include <cpu/types.h> 00049 00050 #include <drv/timer.h> 00051 00052 #include <struct/pool.h> 00053 #include <struct/list.h> 00054 00055 #include <kern/proc.h> 00056 #include <kern/signal.h> 00057 #include <kern/sem.h> 00058 00059 #define NEW_TASK SIG_USER0 00060 00061 // TODO: Mixing static and dynamic tests in kernel must be tested with care, 00062 // until then use this workaround 00063 #if CONFIG_KERN_HEAP 00064 #define PROC_NEW() proc_new(rtask_proc, NULL, CONFIG_RTASK_STACK, NULL) 00065 #else 00066 PROC_DEFINE_STACK(rtask_stack, CONFIG_RTASK_STACK); 00067 #define PROC_NEW() proc_new(rtask_proc, NULL, sizeof(rtask_stack), rtask_stack) 00068 #endif 00069 00070 00071 struct RTask 00072 { 00073 Timer t; 00074 rtask_cb_t callback; 00075 void *user_data; 00076 }; 00077 00078 DEFINE_POOL_STATIC(rtask_pool, RTask, CONFIG_RTASK_POOL_SIZE); 00079 static Process *process = NULL; 00080 static List rt_list; 00081 static Semaphore rtask_sem; 00082 #define RTASK_ATOMIC(code) \ 00083 do { \ 00084 sem_obtain(&rtask_sem); \ 00085 code; \ 00086 sem_release(&rtask_sem); \ 00087 } while (0) 00088 00089 00090 //TODO: "Remove synctimer_poll and use a list directly" 00091 static NORETURN void rtask_proc(void) 00092 { 00093 while (1) 00094 { 00095 bool empty; 00096 RTASK_ATOMIC( 00097 empty = LIST_EMPTY(&rt_list); 00098 sig_check(NEW_TASK); 00099 ); 00100 if (empty) 00101 sig_wait(NEW_TASK); 00102 00103 ticks_t delay; 00104 RTASK_ATOMIC(delay = synctimer_nextTimeout(&rt_list)); 00105 timer_delayTicks(delay); 00106 RTASK_ATOMIC(synctimer_poll(&rt_list)); 00107 } 00108 } 00109 00110 static void rtask_trampoline(void *_rtask) 00111 { 00112 // Access the pool and the list freely since this callback is called 00113 // with the semaphore held in rtask_proc. 00114 RTask *rtask = _rtask; 00115 if (rtask->callback(rtask->user_data)) 00116 synctimer_readd(&rtask->t, &rt_list); 00117 else 00118 pool_free(&rtask_pool, rtask); 00119 } 00120 00121 RTask *rtask_add(rtask_cb_t cb, mtime_t delay, void *cb_data) 00122 { 00123 // Beware: this function is called from a different process 00124 // than rtask_proc, so each access to rtask_pool and rt_list 00125 // must be protected with a semaphore. 00126 00127 // The semaphore is not yet initialized, disable preemption 00128 // altogether. 00129 proc_forbid(); 00130 if (UNLIKELY(process == NULL)) 00131 { 00132 MOD_CHECK(proc); 00133 00134 LIST_INIT(&rt_list); 00135 pool_init(rtask_pool, NULL); 00136 sem_init(&rtask_sem); 00137 process = PROC_NEW(); 00138 ASSERT(process); 00139 } 00140 proc_permit(); 00141 00142 RTask *rt = NULL; 00143 RTASK_ATOMIC(rt = (RTask *)pool_alloc(&rtask_pool)); 00144 if (rt) 00145 { 00146 rt->callback = cb; 00147 rt->user_data = cb_data; 00148 timer_setSoftint(&rt->t, rtask_trampoline, rt); 00149 timer_setDelay(&rt->t, ms_to_ticks(delay)); 00150 RTASK_ATOMIC(synctimer_add(&rt->t, &rt_list)); 00151 sig_send(process, NEW_TASK); 00152 } 00153 else 00154 LOG_ERR("Failed to allocate RTask\n"); 00155 return rt; 00156 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)