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 TASKLETS_IDX  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 #define GET_TMR_TIM 16
00055 #define GET_TMR_OVRN    17
00056 
00057 /* Posix timers support */
00058 
00059 #define PTIMER_CREATE   18
00060 #define PTIMER_SETTIME  19
00061 #define PTIMER_OVERRUN  20
00062 #define PTIMER_GETTIME  21
00063 #define PTIMER_DELETE   22
00064 
00065 #define POSIX_TIMERS    128
00066 
00067 /* End Posix timers support */
00068 
00069 struct rt_task_struct;
00070 
00071 #define TASKLET_STACK_SIZE  8196
00072 
00073 struct rt_usp_tasklet_struct {
00074     struct rt_tasklet_struct *next, *prev;
00075     int priority, uses_fpu, cpuid;
00076     RTIME firing_time, period;
00077     void (*handler)(unsigned long);
00078     unsigned long data, id;
00079     long thread;
00080     struct rt_task_struct *task;
00081     struct rt_tasklet_struct *usptasklet;
00082     int overrun;
00083 };
00084 
00085 #ifdef __KERNEL__
00086 
00087 struct rt_tasklet_struct {
00088     struct rt_tasklet_struct *next, *prev;
00089     int priority, uses_fpu, cpuid;
00090     RTIME firing_time, period;
00091     void (*handler)(unsigned long);
00092     unsigned long data, id;
00093     long thread;
00094     struct rt_task_struct *task;
00095     struct rt_tasklet_struct *usptasklet;
00096     int overrun;
00097 #ifdef  CONFIG_RTAI_LONG_TIMED_LIST
00098     rb_root_t rbr;
00099     rb_node_t rbn;
00100 #endif
00101 };
00102 
00103 #ifdef __cplusplus
00104 extern "C" {
00105 #endif /* !__cplusplus */
00106 
00107 int __rtai_tasklets_init(void);
00108 
00109 void __rtai_tasklets_exit(void);
00110 
00111 struct rt_tasklet_struct *rt_init_tasklet(void);
00112 
00113 RTAI_SYSCALL_MODE int rt_delete_tasklet(struct rt_tasklet_struct *tasklet);
00114 
00115 RTAI_SYSCALL_MODE int rt_insert_tasklet(struct rt_tasklet_struct *tasklet, int priority, void (*handler)(unsigned long), unsigned long data, unsigned long id, int pid);
00116 
00117 RTAI_SYSCALL_MODE void rt_remove_tasklet(struct rt_tasklet_struct *tasklet);
00118 
00119 struct rt_tasklet_struct *rt_find_tasklet_by_id(unsigned long id);
00120 
00121 RTAI_SYSCALL_MODE int rt_exec_tasklet(struct rt_tasklet_struct *tasklet);
00122 
00123 RTAI_SYSCALL_MODE void rt_set_tasklet_priority(struct rt_tasklet_struct *tasklet, int priority);
00124 
00125 RTAI_SYSCALL_MODE int rt_set_tasklet_handler(struct rt_tasklet_struct *tasklet, void (*handler)(unsigned long));
00126 
00127 #define rt_fast_set_tasklet_handler(t, h) do { (t)->handler = (h); } while (0)
00128 
00129 RTAI_SYSCALL_MODE void rt_set_tasklet_data(struct rt_tasklet_struct *tasklet, unsigned long data);
00130 
00131 #define rt_fast_set_tasklet_data(t, d) \
00132 do { \
00133    (t)->data = (d); \
00134 } while (0)
00135 
00136 /**
00137  * Notify the use of floating point operations within any tasklet/timer.
00138  *
00139  * rt_tasklets_use_fpu notifies that there is at least one tasklet/timer using
00140  * floating point calculations within its handler function.
00141  *
00142  * @param use_fpu set/resets the use of floating point calculations:
00143  * - a value different from 0 sets the use of floating point calculations ;
00144  * - a 0 value resets the no floating calculations state.
00145  *
00146  * Note that the use of floating calculations is assigned once for all and is
00147  * valid for all tasklets/timers. If just one handler needs it all of them
00148  * will have floating point support. An optimized floating point support,
00149  * i.e. on a per tasklet/timer base will add an unnoticeable performance
00150  * improvement on most CPUs. However such an optimization is not rule out a
00151  * priori, if anybody can prove it is really important.
00152  *
00153  * This function and macro can be used within the timer handler.
00154  *
00155  */
00156 RTAI_SYSCALL_MODE struct rt_task_struct *rt_tasklet_use_fpu(struct rt_tasklet_struct *tasklet, int use_fpu);
00157 
00158 /**
00159  * Init, in kernel space, a timed tasklet, simply called timer, structure
00160  * to be used in user space.
00161  *
00162  * rt_timer_init allocate a timer tasklet structure (struct rt_tasklet_struct)
00163  * in kernel space to be used for the management of a user space timer.
00164  *
00165  * This function is to be used only for user space timers. In kernel space
00166  * it is just an empty macro, as the user can, and must allocate the related
00167  * structure directly, either statically or dynamically.
00168  *
00169  * @return the pointer to the timer structure the user space application must
00170  * use to access all its related services.
00171  *
00172  */
00173 #define rt_init_timer rt_init_tasklet 
00174 
00175 /**
00176  * Delete, in kernel space, a timed tasklet, simply called timer, structure
00177  * to be used in user space.
00178  *
00179  * rt_timer_delete free a timer tasklet structure (struct rt_tasklet_struct) in
00180  * kernel space that was allocated by rt_timer_init.
00181  *
00182  * @param timer is a pointer to a timer tasklet structure (struct
00183  * rt_tasklet_struct).
00184  *
00185  * This function is to be used only for user space timers. In kernel space
00186  * it is just an empty macro, as the user can, and must allocate the related
00187  * structure directly, either statically or dynamically.
00188  *
00189  */
00190 #define rt_delete_timer rt_delete_tasklet
00191 
00192 RTAI_SYSCALL_MODE int rt_insert_timer(struct rt_tasklet_struct *timer, int priority, RTIME firing_time, RTIME period, void (*handler)(unsigned long), unsigned long data, int pid);
00193 
00194 RTAI_SYSCALL_MODE void rt_remove_timer(struct rt_tasklet_struct *timer);
00195 
00196 RTAI_SYSCALL_MODE void rt_set_timer_priority(struct rt_tasklet_struct *timer, int priority);
00197 
00198 RTAI_SYSCALL_MODE void rt_set_timer_firing_time(struct rt_tasklet_struct *timer, RTIME firing_time);
00199 
00200 RTAI_SYSCALL_MODE void rt_set_timer_period(struct rt_tasklet_struct *timer, RTIME period);
00201 
00202 RTAI_SYSCALL_MODE void rt_get_timer_times(struct rt_tasklet_struct *timer, RTIME timer_times[]);
00203 
00204 RTAI_SYSCALL_MODE RTIME rt_get_timer_overrun(struct rt_tasklet_struct *timer);
00205 
00206 /* Posix timers support */
00207 
00208 RTAI_SYSCALL_MODE timer_t rt_ptimer_create(struct rt_tasklet_struct *timer, void (*handler)(unsigned long), unsigned long data, long pid, long thread);
00209 
00210 RTAI_SYSCALL_MODE void rt_ptimer_settime(timer_t timer, const struct itimerspec *value, unsigned long data, long flags);
00211 
00212 RTAI_SYSCALL_MODE int rt_ptimer_overrun(timer_t timer);
00213 
00214 RTAI_SYSCALL_MODE void rt_ptimer_gettime(timer_t timer, RTIME timer_times[]);
00215 
00216 RTAI_SYSCALL_MODE int rt_ptimer_delete(timer_t timer, long space);
00217 
00218 /* End Posix timers support */
00219 
00220 #define rt_fast_set_timer_period(t, p) \
00221 do { \
00222    (t)->period = (p); \
00223 } while (0)
00224 
00225 /**
00226  * Change the timer handler.
00227  *
00228  * rt_set_timer_handler changes the timer handler function overloading any
00229  * existing value, so that at the next timer firing the new handler will be
00230  * used.   Note that if a oneshot timer has its handler changed after it has
00231  * already expired this function has no effect. You should reinsert it in the
00232  * timer list with the new handler.
00233  *
00234  * @param timer is the pointer to the timer structure to be used to manage the
00235  * timer at hand.
00236  *
00237  * @param handler is the new handler.
00238  *
00239  * The macro rt_fast_set_timer_handler can safely be used to substitute the
00240  * corresponding function in kernel space.
00241  *
00242  * This function and macro can be used within the timer handler.
00243  *
00244  * @retval 0 on success.
00245  *
00246  */
00247 #define rt_set_timer_handler rt_set_tasklet_handler
00248 
00249 #define rt_fast_set_timer_handler(t, h) do { (t)->handler = (h); } while (0)
00250 
00251 /**
00252  * Change the data passed to a timer.
00253  *
00254  * rt_set_timer_data changes the timer data, overloading any existing value, so
00255  * that at the next timer firing the new data will be used.   Note that if a
00256  * oneshot timer has its data changed after it is already expired this function
00257  * has no effect.   You should reinsert it in the timer list with the new data.
00258  *
00259  * @param timer is the pointer to the timer structure to be used to manage the
00260  * timer at hand.
00261  *
00262  * @param data is the new data.
00263  *
00264  * The macro rt_fast_set_timer_data can safely be used substitute the
00265  * corresponding function in kernel space.
00266  *
00267  *  This function and macro can be used within the timer handler.
00268  *
00269  * @retval 0 on success.
00270  *
00271  */
00272 #define rt_set_timer_data rt_set_tasklet_data
00273 
00274 #define rt_fast_set_timer_data(t, d) do { (t)->data = (d); } while (0)
00275 
00276 #define rt_timer_use_fpu rt_tasklet_use_fpu
00277 
00278 RTAI_SYSCALL_MODE int rt_wait_tasklet_is_hard(struct rt_tasklet_struct *tasklet, long thread);
00279 
00280 RTAI_SYSCALL_MODE void rt_register_task(struct rt_tasklet_struct *tasklet, struct rt_tasklet_struct *usptasklet, struct rt_task_struct *task);
00281  
00282 #ifdef __cplusplus
00283 }
00284 #endif /* __cplusplus */
00285 
00286 #else /* !__KERNEL__ */
00287 
00288 #include <sys/types.h>
00289 #include <sys/wait.h>
00290 #include <sys/mman.h>
00291 #include <stdarg.h>
00292 
00293 #include <rtai_usi.h>
00294 #include <rtai_lxrt.h>
00295 
00296 #define rt_tasklet_struct  rt_usp_tasklet_struct
00297 #if 0
00298 struct rt_tasklet_struct {
00299     struct rt_tasklet_struct *next, *prev;
00300     int priority, uses_fpu, cpuid;
00301     RTIME firing_time, period;
00302     void (*handler)(unsigned long);
00303     unsigned long data, id;
00304     long thread;
00305     struct rt_task_struct *task;
00306     struct rt_tasklet_struct *usptasklet;
00307     int overrun;
00308 #ifdef  CONFIG_RTAI_LONG_TIMED_LIST
00309     struct { void *rb_parent; int rb_color; void *rb_right, *rb_left; } rbn;
00310     struct { void *rb_node; } rbr;
00311 #endif
00312 };
00313 #endif
00314 
00315 #ifndef __SUPPORT_TASKLET__
00316 #define __SUPPORT_TASKLET__
00317 
00318 struct support_tasklet_s { struct rt_tasklet_struct *tasklet; pthread_t thread; volatile int done; };
00319 
00320 static int support_tasklet(struct support_tasklet_s *args)
00321 {
00322     RT_TASK *task;
00323     struct rt_tasklet_struct usptasklet;
00324 
00325     if ((task = rt_thread_init((unsigned long)args->tasklet, 98, 0, SCHED_FIFO, 0xF))) {
00326     {
00327         struct { struct rt_tasklet_struct *tasklet, *usptasklet; RT_TASK *task; } reg = { args->tasklet, &usptasklet, task };
00328         rtai_lxrt(TASKLETS_IDX, sizeof(reg), REG_TASK, &reg);
00329     }
00330         rt_grow_and_lock_stack(TASKLET_STACK_SIZE/2);
00331         mlockall(MCL_CURRENT | MCL_FUTURE);
00332         rt_make_hard_real_time();
00333         args->done = 1;
00334         while (1) {
00335             rt_task_suspend(task);
00336             if (usptasklet.handler) {
00337                 usptasklet.handler(usptasklet.data);
00338             } else {
00339                 break;
00340             }
00341         }
00342         rtai_sti();
00343         rt_make_soft_real_time();
00344         rt_task_delete(task);
00345         return 0;
00346     }
00347     printf("CANNOT INIT SUPPORT TASKLET\n");
00348     return -1;
00349     
00350 }
00351 #endif /* __SUPPORT_TASKLET__ */
00352 
00353 #ifdef __cplusplus
00354 extern "C" {
00355 #endif /* __cplusplus */
00356 
00357 RTAI_PROTO(void, rt_delete_tasklet, (struct rt_tasklet_struct *tasklet));
00358 
00359 RTAI_PROTO(struct rt_tasklet_struct *, rt_init_tasklet, (void))
00360 {
00361     int is_hard;
00362     struct support_tasklet_s arg;
00363 
00364     if ((arg.tasklet = (struct rt_tasklet_struct*)rtai_lxrt(TASKLETS_IDX, SIZARG, INIT, &arg).v[LOW])) {
00365         if ((is_hard = rt_is_hard_real_time(NULL))) {
00366             rt_make_soft_real_time();
00367         }
00368         arg.done = 0;
00369         if ((arg.thread = rt_thread_create((void *)support_tasklet, &arg.tasklet, TASKLET_STACK_SIZE))) {
00370             int i;
00371 #define POLLS_PER_SEC 100
00372                 for (i = 0; i < POLLS_PER_SEC/5 && !arg.done; i++) {
00373                 struct timespec delay = { 0, 1000000000/POLLS_PER_SEC };
00374                 nanosleep(&delay, NULL);
00375                 }
00376 #undef POLLS_PER_SEC
00377             if (!arg.done || rtai_lxrt(TASKLETS_IDX, SIZARG, WAIT_IS_HARD, &arg).i[LOW]) {
00378                 goto notdone;
00379             }
00380         } else {
00381 notdone:
00382             rt_delete_tasklet(arg.tasklet);
00383             arg.tasklet = NULL;
00384         }
00385         if (is_hard) {
00386             rt_make_hard_real_time();
00387         }
00388     }
00389     return arg.tasklet;
00390 }
00391 
00392 #define rt_init_timer rt_init_tasklet
00393 
00394 RTAI_PROTO(void, rt_delete_tasklet, (struct rt_tasklet_struct *tasklet))
00395 {
00396     int thread;
00397     struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet };
00398     if ((thread = rtai_lxrt(TASKLETS_IDX, SIZARG, DELETE, &arg).i[LOW])) {
00399         rt_thread_join(thread);
00400     }
00401 }
00402 
00403 #define rt_delete_timer rt_delete_tasklet
00404 
00405 RTAI_PROTO(int, rt_insert_timer,(struct rt_tasklet_struct *timer,
00406                  int priority,
00407                  RTIME firing_time,
00408                  RTIME period,
00409                  void (*handler)(unsigned long),
00410                  unsigned long data,
00411                  int pid))
00412 {
00413     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 };
00414     return rtai_lxrt(TASKLETS_IDX, SIZARG, TIMER_INSERT, &arg).i[LOW];
00415 }
00416 
00417 RTAI_PROTO(void, rt_remove_timer, (struct rt_tasklet_struct *timer))
00418 {
00419     struct { struct rt_tasklet_struct *timer; } arg = { timer };
00420     rtai_lxrt(TASKLETS_IDX, SIZARG, TIMER_REMOVE, &arg);
00421 }
00422 
00423 RTAI_PROTO(void, rt_set_timer_priority, (struct rt_tasklet_struct *timer, int priority))
00424 {
00425     struct { struct rt_tasklet_struct *timer; long priority; } arg = { timer, priority };
00426     rtai_lxrt(TASKLETS_IDX, SIZARG, SET_TASKLETS_PRI, &arg);
00427 }
00428 
00429 RTAI_PROTO(void, rt_set_timer_firing_time, (struct rt_tasklet_struct *timer, RTIME firing_time))
00430 {
00431     struct { struct rt_tasklet_struct *timer; RTIME firing_time; } arg = { timer, firing_time };
00432     rtai_lxrt(TASKLETS_IDX, SIZARG, SET_FIR_TIM, &arg);
00433 }
00434 
00435 RTAI_PROTO(void, rt_set_timer_period, (struct rt_tasklet_struct *timer, RTIME period))
00436 {
00437     struct { struct rt_tasklet_struct *timer; RTIME period; } arg = { timer, period };
00438     rtai_lxrt(TASKLETS_IDX, SIZARG, SET_PER, &arg);
00439 }
00440 
00441 RTAI_PROTO(void, rt_get_timer_times, (struct rt_tasklet_struct *timer, RTIME timer_times[]))
00442 {
00443     if (timer_times) {
00444           RTIME ltimer_times[2];
00445             struct { struct rt_tasklet_struct *timer; RTIME *timer_times; } arg = { timer, ltimer_times };
00446         rtai_lxrt(TASKLETS_IDX, SIZARG, GET_TMR_TIM, &arg);
00447         memcpy(timer_times, ltimer_times, sizeof(ltimer_times));
00448     }
00449 }
00450 
00451 RTAI_PROTO(RTIME, rt_get_timer_overrun, (struct rt_tasklet_struct *timer ))
00452 {
00453     struct { struct rt_tasklet_struct *timer; } arg = { timer };
00454     return rtai_lxrt(TASKLETS_IDX, SIZARG, GET_TMR_OVRN, &arg).rt;
00455 }
00456 
00457 RTAI_PROTO(int, rt_set_tasklet_handler, (struct rt_tasklet_struct *tasklet, void (*handler)(unsigned long)))
00458 {
00459     struct { struct rt_tasklet_struct *tasklet; void (*handler)(unsigned long); } arg = { tasklet, handler };
00460     return rtai_lxrt(TASKLETS_IDX, SIZARG, SET_HDL, &arg).i[LOW];
00461 }
00462 
00463 #define rt_set_timer_handler rt_set_tasklet_handler
00464 
00465 RTAI_PROTO(void, rt_set_tasklet_data, (struct rt_tasklet_struct *tasklet, unsigned long data))
00466 {
00467     struct { struct rt_tasklet_struct *tasklet; unsigned long data; } arg = { tasklet, data };
00468     rtai_lxrt(TASKLETS_IDX, SIZARG, SET_DAT, &arg);
00469 }
00470 
00471 #define rt_set_timer_data rt_set_tasklet_data
00472 
00473 RTAI_PROTO(RT_TASK *, rt_tasklet_use_fpu, (struct rt_tasklet_struct *tasklet, int use_fpu))
00474 {
00475     RT_TASK *task;
00476     struct { struct rt_tasklet_struct *tasklet; long use_fpu; } arg = { tasklet, use_fpu };
00477     if ((task = (RT_TASK*)rtai_lxrt(TASKLETS_IDX, SIZARG, USE_FPU, &arg).v[LOW])) {
00478         rt_task_use_fpu(task, use_fpu);
00479     }
00480     return task;
00481 }
00482 
00483 #define rt_timer_use_fpu rt_tasklet_use_fpu
00484 
00485 RTAI_PROTO(int, rt_insert_tasklet,(struct rt_tasklet_struct *tasklet,
00486                    int priority,
00487                    void (*handler)(unsigned long),
00488                    unsigned long data,
00489                    unsigned long id,
00490                    int pid))
00491 {
00492     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 };
00493     return rtai_lxrt(TASKLETS_IDX, SIZARG, TASK_INSERT, &arg).i[LOW];
00494 }
00495 
00496 RTAI_PROTO(void, rt_set_tasklet_priority, (struct rt_tasklet_struct *tasklet, int priority))
00497 {
00498     struct { struct rt_tasklet_struct *tasklet; long priority; } arg = { tasklet, priority };
00499     rtai_lxrt(TASKLETS_IDX, SIZARG, SET_TSK_PRI, &arg);
00500 }
00501 
00502 RTAI_PROTO(void, rt_remove_tasklet, (struct rt_tasklet_struct *tasklet))
00503 {
00504     struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet };
00505     rtai_lxrt(TASKLETS_IDX, SIZARG, TASK_REMOVE, &arg);
00506 }
00507 
00508 RTAI_PROTO(int, rt_exec_tasklet, (struct rt_tasklet_struct *tasklet))
00509 {
00510     struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet };
00511     return rtai_lxrt(TASKLETS_IDX, SIZARG, EXEC_TASKLET, &arg).i[LOW];
00512 }
00513 
00514 #include <stdlib.h>
00515 
00516 struct rt_tasklets_struct { volatile int in, out, avb, ntasklets; struct rt_tasklet_struct **tasklets; unsigned long lock; };
00517 
00518 RTAI_PROTO(struct rt_tasklets_struct *, rt_create_tasklets, (int ntasklets))
00519 {
00520     struct rt_tasklets_struct *tasklets;
00521     if ((tasklets = (struct rt_tasklets_struct *)malloc(sizeof(struct rt_tasklets_struct)))) {
00522         if ((tasklets->tasklets = (struct rt_tasklet_struct **)malloc(ntasklets*sizeof(struct rt_tasklet_struct *)))) {
00523             int i;
00524             for (i = 0; i < ntasklets; i++) {
00525                 if (!(tasklets->tasklets[i] = rt_init_tasklet())) {
00526                     int k;
00527                     for (k = 0; k < i; k++) {
00528                         rt_delete_tasklet(tasklets->tasklets[k]);
00529                     }
00530                     free(tasklets->tasklets);
00531                     goto free_tasklets;
00532                 }
00533             }
00534             tasklets->lock = 0;
00535             tasklets->ntasklets = tasklets->avb = tasklets->in = tasklets->out = ntasklets;
00536             return tasklets;
00537         } else {
00538 free_tasklets:
00539             free(tasklets);
00540         }
00541     }
00542     return NULL;
00543 }
00544 
00545 #define rt_create_timers  rt_create_tasklets
00546 
00547 RTAI_PROTO(void, rt_destroy_tasklets, (struct rt_tasklets_struct *tasklets))
00548 {
00549     int i;
00550     for (i = 0; i < tasklets->ntasklets; i++) {
00551         rt_delete_tasklet(tasklets->tasklets[i]);
00552     }
00553     free(tasklets->tasklets);
00554     free(tasklets);
00555 }
00556 
00557 #define rt_destroy_timers  rt_destroy_tasklets
00558 
00559 #include <asm/rtai_atomic.h>
00560 
00561 RTAI_PROTO(struct rt_tasklet_struct *, rt_get_tasklet, (struct rt_tasklets_struct *tasklets))
00562 {
00563     struct rt_tasklet_struct *tasklet;
00564     while (atomic_cmpxchg((void *)&tasklets->lock, 0, 1));
00565     if (tasklets->avb > 0) {
00566         if (tasklets->out >= tasklets->ntasklets) {
00567             tasklets->out = 0;
00568         }
00569         tasklets->avb--;
00570         tasklet = tasklets->tasklets[tasklets->out++];
00571         tasklets->lock = 0;
00572         return tasklet;
00573     }
00574     tasklets->lock = 0;
00575     return NULL;
00576 }
00577 
00578 #define rt_get_timer  rt_get_tasklet
00579 
00580 RTAI_PROTO(int, rt_gvb_tasklet, (struct rt_tasklet_struct *tasklet, struct rt_tasklets_struct *tasklets))
00581 {
00582     while (atomic_cmpxchg((void *)&tasklets->lock, 0, 1));
00583     if (tasklets->avb < tasklets->ntasklets) {
00584         if (tasklets->in >= tasklets->ntasklets) {
00585             tasklets->in = 0;
00586         }
00587         tasklets->avb++;
00588         tasklets->tasklets[tasklets->in++] = tasklet;
00589         tasklets->lock = 0;
00590         return 0;
00591     }
00592     tasklets->lock = 0;
00593     return EINVAL;
00594 }
00595 
00596 #define rt_gvb_timer  rt_gvb_tasklet
00597 
00598 #ifdef __cplusplus
00599 }
00600 #endif /* __cplusplus */
00601 
00602 #endif /* __KERNEL__ */
00603 
00604 /*@}*/
00605 
00606 #endif /* !_RTAI_TASKLETS_H */

Generated on Tue Feb 2 17:46:05 2010 for RTAI API by  doxygen 1.4.7