base/include/rtai_tasklets.h

Go to the documentation of this file.
00001 /** 00002 * @ingroup tasklets 00003 * @file 00004 * 00005 * Interface of the @ref tasklets "mini LXRT RTAI tasklets module". 00006 * 00007 * @author Paolo Mantegazza 00008 * 00009 * @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it> 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License as 00013 * published by the Free Software Foundation; either version 2 of the 00014 * License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00024 */ 00025 00026 #ifndef _RTAI_TASKLETS_H 00027 #define _RTAI_TASKLETS_H 00028 00029 /** 00030 * @addtogroup tasklets 00031 *@{*/ 00032 00033 #include <rtai_types.h> 00034 #include <rtai_sched.h> 00035 00036 #define TSKIDX 1 00037 00038 #define INIT 0 00039 #define DELETE 1 00040 #define TASK_INSERT 2 00041 #define TASK_REMOVE 3 00042 #define USE_FPU 4 00043 #define TIMER_INSERT 5 00044 #define TIMER_REMOVE 6 00045 #define SET_TASKLETS_PRI 7 00046 #define SET_FIR_TIM 8 00047 #define SET_PER 9 00048 #define SET_HDL 10 00049 #define SET_DAT 11 00050 #define EXEC_TASKLET 12 00051 #define WAIT_IS_HARD 13 00052 #define SET_TSK_PRI 14 00053 #define REG_TASK 15 00054 00055 struct rt_task_struct; 00056 00057 #define TASKLET_STACK_SIZE 8196 00058 00059 #ifdef __KERNEL__ 00060 00061 struct rt_tasklet_struct { 00062 struct rt_tasklet_struct *next, *prev; 00063 int priority, uses_fpu; 00064 RTIME firing_time, period; 00065 void (*handler)(unsigned long); 00066 unsigned long data, id; 00067 int thread; 00068 struct rt_task_struct *task; 00069 struct rt_tasklet_struct *usptasklet; 00070 #ifdef CONFIG_RTAI_LONG_TIMED_LIST 00071 rb_root_t rbr; 00072 rb_node_t rbn; 00073 #endif 00074 }; 00075 00076 #ifdef __cplusplus 00077 extern "C" { 00078 #endif /* !__cplusplus */ 00079 00080 int __rtai_tasklets_init(void); 00081 00082 void __rtai_tasklets_exit(void); 00083 00084 struct rt_tasklet_struct *rt_init_tasklet(void); 00085 00086 int rt_delete_tasklet(struct rt_tasklet_struct *tasklet); 00087 00088 int rt_insert_tasklet(struct rt_tasklet_struct *tasklet, 00089 int priority, 00090 void (*handler)(unsigned long), 00091 unsigned long data, 00092 unsigned long id, 00093 int pid); 00094 00095 void rt_remove_tasklet(struct rt_tasklet_struct *tasklet); 00096 00097 struct rt_tasklet_struct *rt_find_tasklet_by_id(unsigned long id); 00098 00099 int rt_exec_tasklet(struct rt_tasklet_struct *tasklet); 00100 00101 void rt_set_tasklet_priority(struct rt_tasklet_struct *tasklet, 00102 int priority); 00103 00104 int rt_set_tasklet_handler(struct rt_tasklet_struct *tasklet, 00105 void (*handler)(unsigned long)); 00106 00107 #define rt_fast_set_tasklet_handler(t, h) do { (t)->handler = (h); } while (0) 00108 00109 void rt_set_tasklet_data(struct rt_tasklet_struct *tasklet, 00110 unsigned long data); 00111 00112 #define rt_fast_set_tasklet_data(t, d) \ 00113 do { \ 00114 (t)->data = (d); \ 00115 } while (0) 00116 00117 /** 00118 * Notify the use of floating point operations within any tasklet/timer. 00119 * 00120 * rt_tasklets_use_fpu notifies that there is at least one tasklet/timer using 00121 * floating point calculations within its handler function. 00122 * 00123 * @param use_fpu set/resets the use of floating point calculations: 00124 * - a value different from 0 sets the use of floating point calculations ; 00125 * - a 0 value resets the no floating calculations state. 00126 * 00127 * Note that the use of floating calculations is assigned once for all and is 00128 * valid for all tasklets/timers. If just one handler needs it all of them 00129 * will have floating point support. An optimized floating point support, 00130 * i.e. on a per tasklet/timer base will add an unnoticeable performance 00131 * improvement on most CPUs. However such an optimization is not rule out a 00132 * priori, if anybody can prove it is really important. 00133 * 00134 * This function and macro can be used within the timer handler. 00135 * 00136 * 00137 * @note To be used only with RTAI24.x.xx. 00138 */ 00139 struct rt_task_struct *rt_tasklet_use_fpu(struct rt_tasklet_struct *tasklet, 00140 int use_fpu); 00141 00142 /** 00143 * Init, in kernel space, a timed tasklet, simply called timer, structure 00144 * to be used in user space. 00145 * 00146 * rt_timer_init allocate a timer tasklet structure (struct rt_tasklet_struct) 00147 * in kernel space to be used for the management of a user space timer. 00148 * 00149 * This function is to be used only for user space timers. In kernel space 00150 * it is just an empty macro, as the user can, and must allocate the related 00151 * structure directly, either statically or dynamically. 00152 * 00153 * @return the pointer to the timer structure the user space application must 00154 * use to access all its related services. 00155 * 00156 * @note To be used only with RTAI24.x.xx. 00157 */ 00158 #define rt_init_timer rt_init_tasklet 00159 00160 /** 00161 * Delete, in kernel space, a timed tasklet, simply called timer, structure 00162 * to be used in user space. 00163 * 00164 * rt_timer_delete free a timer tasklet structure (struct rt_tasklet_struct) in 00165 * kernel space that was allocated by rt_timer_init. 00166 * 00167 * @param timer is a pointer to a timer tasklet structure (struct 00168 * rt_tasklet_struct). 00169 * 00170 * This function is to be used only for user space timers. In kernel space 00171 * it is just an empty macro, as the user can, and must allocate the related 00172 * structure directly, either statically or dynamically. 00173 * 00174 * @note To be used only with RTAI24.x.xx. 00175 */ 00176 #define rt_delete_timer rt_delete_tasklet 00177 00178 int rt_insert_timer(struct rt_tasklet_struct *timer, 00179 int priority, 00180 RTIME firing_time, 00181 RTIME period, 00182 void (*handler)(unsigned long), 00183 unsigned long data, 00184 int pid); 00185 00186 void rt_remove_timer(struct rt_tasklet_struct *timer); 00187 00188 void rt_set_timer_priority(struct rt_tasklet_struct *timer, 00189 int priority); 00190 00191 void rt_set_timer_firing_time(struct rt_tasklet_struct *timer, 00192 RTIME firing_time); 00193 00194 void rt_set_timer_period(struct rt_tasklet_struct *timer, 00195 RTIME period); 00196 00197 #define rt_fast_set_timer_period(t, p) \ 00198 do { \ 00199 (t)->period = (p); \ 00200 } while (0) 00201 00202 /** 00203 * Change the timer handler. 00204 * 00205 * rt_set_timer_handler changes the timer handler function overloading any 00206 * existing value, so that at the next timer firing the new handler will be 00207 * used. Note that if a oneshot timer has its handler changed after it has 00208 * already expired this function has no effect. You should reinsert it in the 00209 * timer list with the new handler. 00210 * 00211 * @param timer is the pointer to the timer structure to be used to manage the 00212 * timer at hand. 00213 * 00214 * @param handler is the new handler. 00215 * 00216 * The macro rt_fast_set_timer_handler can safely be used to substitute the 00217 * corresponding function in kernel space. 00218 * 00219 * This function and macro can be used within the timer handler. 00220 * 00221 * @retval 0 on success. 00222 * 00223 * @note To be used only with RTAI24.x.xx. 00224 */ 00225 #define rt_set_timer_handler rt_set_tasklet_handler 00226 00227 #define rt_fast_set_timer_handler(t, h) do { (t)->handler = (h); } while (0) 00228 00229 /** 00230 * Change the data passed to a timer. 00231 * 00232 * rt_set_timer_data changes the timer data, overloading any existing value, so 00233 * that at the next timer firing the new data will be used. Note that if a 00234 * oneshot timer has its data changed after it is already expired this function 00235 * has no effect. You should reinsert it in the timer list with the new data. 00236 * 00237 * @param timer is the pointer to the timer structure to be used to manage the 00238 * timer at hand. 00239 * 00240 * @param data is the new data. 00241 * 00242 * The macro rt_fast_set_timer_data can safely be used substitute the 00243 * corresponding function in kernel space. 00244 * 00245 * This function and macro can be used within the timer handler. 00246 * 00247 * @retval 0 on success. 00248 * 00249 * @note To be used only with RTAI24.x.xx. 00250 */ 00251 #define rt_set_timer_data rt_set_tasklet_data 00252 00253 #define rt_fast_set_timer_data(t, d) do { (t)->data = (d); } while (0) 00254 00255 #define rt_timer_use_fpu rt_tasklet_use_fpu 00256 00257 void rt_wait_tasklet_is_hard(struct rt_tasklet_struct *tasklet, 00258 int thread); 00259 00260 void rt_register_task(struct rt_tasklet_struct *tasklet, 00261 struct rt_tasklet_struct *usptasklet, 00262 struct rt_task_struct *task); 00263 00264 #ifdef __cplusplus 00265 } 00266 #endif /* __cplusplus */ 00267 00268 #else /* !__KERNEL__ */ 00269 00270 #include <sys/types.h> 00271 #include <sys/wait.h> 00272 #include <sys/mman.h> 00273 #include <stdarg.h> 00274 00275 #include <rtai_usi.h> 00276 #include <rtai_lxrt.h> 00277 00278 struct rt_tasklet_struct { 00279 struct rt_tasklet_struct *next, *prev; 00280 int priority, uses_fpu; 00281 RTIME firing_time, period; 00282 void (*handler)(unsigned long); 00283 unsigned long data, id; 00284 int thread; 00285 struct rt_task_struct *task; 00286 struct rt_tasklet_struct *usptasklet; 00287 #ifdef CONFIG_RTAI_LONG_TIMED_LIST 00288 struct { void *rb_parent; int rb_color; void *rb_right, *rb_left; } rbn; 00289 struct { void *rb_node; } rbr; 00290 #endif 00291 }; 00292 00293 #ifndef __SUPPORT_TASKLET__ 00294 #define __SUPPORT_TASKLET__ 00295 00296 static int support_tasklet(void *tasklet) 00297 { 00298 RT_TASK *task; 00299 struct rt_tasklet_struct usptasklet; 00300 struct { struct rt_tasklet_struct *tasklet; void *handler; } arg = { (struct rt_tasklet_struct *)tasklet, }; 00301 00302 if (!(task = rt_thread_init((unsigned long)arg.tasklet, 98, 0, SCHED_FIFO, 0xF))) { 00303 printf("CANNOT INIT SUPPORT TASKLET\n"); 00304 return -1; 00305 } else { 00306 struct { struct rt_tasklet_struct *tasklet, *usptasklet; RT_TASK *task; } reg = { arg.tasklet, &usptasklet, task }; 00307 rtai_lxrt(TSKIDX, sizeof(reg), REG_TASK, &reg); 00308 } 00309 00310 mlockall(MCL_CURRENT | MCL_FUTURE); 00311 rt_make_hard_real_time(); 00312 while (1) { 00313 rt_task_suspend(task); 00314 if ((arg.handler = (void*)usptasklet.handler)) { 00315 rtai_lxrt(TSKIDX, SIZARG, SET_HDL, &arg); 00316 usptasklet.handler(usptasklet.data); 00317 } else { 00318 break; 00319 } 00320 } 00321 rtai_sti(); 00322 rt_make_soft_real_time(); 00323 rt_task_delete(task); 00324 00325 return 0; 00326 } 00327 #endif /* __SUPPORT_TASKLET__ */ 00328 00329 #ifdef __cplusplus 00330 extern "C" { 00331 #endif /* __cplusplus */ 00332 00333 RTAI_PROTO(struct rt_tasklet_struct *, rt_init_tasklet,(void)) 00334 { 00335 struct { struct rt_tasklet_struct *tasklet; long thread; } arg; 00336 00337 arg.tasklet = (struct rt_tasklet_struct*)rtai_lxrt(TSKIDX, SIZARG, INIT, &arg).v[LOW]; 00338 arg.thread = rt_thread_create((void *)support_tasklet, arg.tasklet, TASKLET_STACK_SIZE); 00339 // arg.thread = clone(support_tasklet, sp + TASKLET_STACK_SIZE - 1, CLONE_VM | CLONE_FS | CLONE_FILES, arg.tasklet); 00340 rtai_lxrt(TSKIDX, SIZARG, WAIT_IS_HARD, &arg); 00341 00342 return arg.tasklet; 00343 } 00344 00345 #define rt_init_timer rt_init_tasklet 00346 00347 RTAI_PROTO(void, rt_delete_tasklet,(struct rt_tasklet_struct *tasklet)) 00348 { 00349 int thread; 00350 struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet }; 00351 if ((thread = rtai_lxrt(TSKIDX, SIZARG, DELETE, &arg).i[LOW])) { 00352 rt_thread_join(thread); 00353 } 00354 } 00355 00356 #define rt_delete_timer rt_delete_tasklet 00357 00358 RTAI_PROTO(int, rt_insert_timer,(struct rt_tasklet_struct *timer, 00359 int priority, 00360 RTIME firing_time, 00361 RTIME period, 00362 void (*handler)(unsigned long), 00363 unsigned long data, 00364 int pid)) 00365 { 00366 struct { struct rt_tasklet_struct *timer; long priority; RTIME firing_time; RTIME period; void (*handler)(unsigned long); unsigned long data; long pid; } arg = { timer, priority, firing_time, period, handler, data, pid }; 00367 return rtai_lxrt(TSKIDX, SIZARG, TIMER_INSERT, &arg).i[LOW]; 00368 } 00369 00370 RTAI_PROTO(void, rt_remove_timer,(struct rt_tasklet_struct *timer)) 00371 { 00372 struct { struct rt_tasklet_struct *timer; } arg = { timer }; 00373 rtai_lxrt(TSKIDX, SIZARG, TIMER_REMOVE, &arg); 00374 } 00375 00376 RTAI_PROTO(void, rt_set_timer_priority,(struct rt_tasklet_struct *timer, int priority)) 00377 { 00378 struct { struct rt_tasklet_struct *timer; long priority; } arg = { timer, priority }; 00379 rtai_lxrt(TSKIDX, SIZARG, SET_TASKLETS_PRI, &arg); 00380 } 00381 00382 RTAI_PROTO(void, rt_set_timer_firing_time,(struct rt_tasklet_struct *timer, RTIME firing_time)) 00383 { 00384 struct { struct rt_tasklet_struct *timer; RTIME firing_time; } arg = { timer, firing_time }; 00385 rtai_lxrt(TSKIDX, SIZARG, SET_FIR_TIM, &arg); 00386 } 00387 00388 RTAI_PROTO(void, rt_set_timer_period,(struct rt_tasklet_struct *timer, RTIME period)) 00389 { 00390 struct { struct rt_tasklet_struct *timer; RTIME period; } arg = { timer, period }; 00391 rtai_lxrt(TSKIDX, SIZARG, SET_PER, &arg); 00392 } 00393 00394 RTAI_PROTO(int, rt_set_tasklet_handler,(struct rt_tasklet_struct *tasklet, void (*handler)(unsigned long))) 00395 { 00396 struct { struct rt_tasklet_struct *tasklet; void (*handler)(unsigned long); } arg = { tasklet, handler }; 00397 return rtai_lxrt(TSKIDX, SIZARG, SET_HDL, &arg).i[LOW]; 00398 } 00399 00400 #define rt_set_timer_handler rt_set_tasklet_handler 00401 00402 RTAI_PROTO(void, rt_set_tasklet_data,(struct rt_tasklet_struct *tasklet, unsigned long data)) 00403 { 00404 struct { struct rt_tasklet_struct *tasklet; unsigned long data; } arg = { tasklet, data }; 00405 rtai_lxrt(TSKIDX, SIZARG, SET_DAT, &arg); 00406 } 00407 00408 #define rt_set_timer_data rt_set_tasklet_data 00409 00410 RTAI_PROTO(RT_TASK *, rt_tasklet_use_fpu,(struct rt_tasklet_struct *tasklet, int use_fpu)) 00411 { 00412 RT_TASK *task; 00413 struct { struct rt_tasklet_struct *tasklet; long use_fpu; } arg = { tasklet, use_fpu }; 00414 if ((task = (RT_TASK*)rtai_lxrt(TSKIDX, SIZARG, USE_FPU, &arg).v[LOW])) { 00415 rt_task_use_fpu(task, use_fpu); 00416 } 00417 return task; 00418 } 00419 00420 #define rt_timer_use_fpu rt_tasklet_use_fpu 00421 00422 RTAI_PROTO(int, rt_insert_tasklet,(struct rt_tasklet_struct *tasklet, 00423 int priority, 00424 void (*handler)(unsigned long), 00425 unsigned long data, 00426 unsigned long id, 00427 int pid)) 00428 { 00429 struct { struct rt_tasklet_struct *tasklet; long priority; void (*handler)(unsigned long); unsigned long data; unsigned long id; long pid; } arg = { tasklet, priority, handler, data, id, pid }; 00430 return rtai_lxrt(TSKIDX, SIZARG, TASK_INSERT, &arg).i[LOW]; 00431 } 00432 00433 RTAI_PROTO(void, rt_set_tasklet_priority,(struct rt_tasklet_struct *tasklet, int priority)) 00434 { 00435 struct { struct rt_tasklet_struct *tasklet; long priority; } arg = { tasklet, priority }; 00436 rtai_lxrt(TSKIDX, SIZARG, SET_TSK_PRI, &arg); 00437 } 00438 00439 RTAI_PROTO(void, rt_remove_tasklet,(struct rt_tasklet_struct *tasklet)) 00440 { 00441 struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet }; 00442 rtai_lxrt(TSKIDX, SIZARG, TASK_REMOVE, &arg); 00443 } 00444 00445 RTAI_PROTO(int, rt_exec_tasklet,(struct rt_tasklet_struct *tasklet)) 00446 { 00447 struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet }; 00448 return rtai_lxrt(TSKIDX, SIZARG, EXEC_TASKLET, &arg).i[LOW]; 00449 } 00450 00451 #ifdef __cplusplus 00452 } 00453 #endif /* __cplusplus */ 00454 00455 #endif /* __KERNEL__ */ 00456 00457 /*@}*/ 00458 00459 #endif /* !_RTAI_TASKLETS_H */

Generated on Thu Nov 20 11:49:50 2008 for RTAI API by doxygen 1.3.8