/ base / include / rtai_tasklets.h
rtai_tasklets.h
  1  /**
  2   * @ingroup tasklets
  3   * @file
  4   *
  5   * Interface of the @ref tasklets "mini LXRT RTAI tasklets module".
  6   *
  7   * @author Paolo Mantegazza
  8   *
  9   * @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
 10   *
 11   * This program is free software; you can redistribute it and/or
 12   * modify it under the terms of the GNU General Public License as
 13   * published by the Free Software Foundation; either version 2 of the
 14   * License, or (at your option) any later version.
 15   *
 16   * This program is distributed in the hope that it will be useful,
 17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 19   * GNU General Public License for more details.
 20   *
 21   * You should have received a copy of the GNU General Public License
 22   * along with this program; if not, write to the Free Software
 23   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 24   */
 25  
 26  #ifndef _RTAI_TASKLETS_H
 27  #define _RTAI_TASKLETS_H
 28  
 29  /**
 30   * @addtogroup tasklets
 31   *@{*/
 32  
 33  #include <rtai_types.h>
 34  #include <rtai_sched.h>
 35  
 36  #define TASKLETS_IDX  1
 37  
 38  #define INIT	 	 0
 39  #define DELETE		 1
 40  #define TASK_INSERT 	 2
 41  #define TASK_REMOVE	 3
 42  #define USE_FPU	 	 4
 43  #define TIMER_INSERT 	 5
 44  #define TIMER_REMOVE	 6
 45  #define SET_TASKLETS_PRI 7
 46  #define SET_FIR_TIM	 8	
 47  #define SET_PER	 	 9
 48  #define SET_HDL		10
 49  #define SET_DAT	 	11
 50  #define EXEC_TASKLET    12
 51  #define WAIT_IS_HARD	13
 52  #define SET_TSK_PRI	14
 53  #define REG_TASK   	15
 54  #define GET_TMR_TIM	16
 55  #define GET_TMR_OVRN	17
 56  
 57  /* Posix timers support */
 58  
 59  #define PTIMER_CREATE   18
 60  #define PTIMER_SETTIME  19
 61  #define PTIMER_OVERRUN  20
 62  #define PTIMER_GETTIME  21
 63  #define PTIMER_DELETE   22
 64  
 65  #define POSIX_TIMERS    128
 66  
 67  /* End Posix timers support */
 68  
 69  struct rt_task_struct;
 70  
 71  #define TASKLET_STACK_SIZE  8196
 72  
 73  struct rt_usp_tasklet_struct {
 74  	struct rt_tasklet_struct *next, *prev;
 75  	int priority, uses_fpu, cpuid;
 76  	RTIME firing_time, period;
 77  	void (*handler)(unsigned long);
 78  	unsigned long data, id;
 79  	long thread;
 80  	struct rt_task_struct *task;
 81  	struct rt_tasklet_struct *usptasklet;
 82  	int overrun;
 83  };
 84  
 85  #ifdef __KERNEL__
 86  
 87  struct rt_tasklet_struct {
 88  	struct rt_tasklet_struct *next, *prev;
 89  	int priority, uses_fpu, cpuid;
 90  	RTIME firing_time, period;
 91  	void (*handler)(unsigned long);
 92  	unsigned long data, id;
 93  	long thread;
 94  	struct rt_task_struct *task;
 95  	struct rt_tasklet_struct *usptasklet;
 96  	int overrun;
 97  #ifdef  CONFIG_RTAI_LONG_TIMED_LIST
 98  	rb_root_t rbr;
 99  	rb_node_t rbn;
100  #endif
101  };
102  
103  #ifdef __cplusplus
104  extern "C" {
105  #endif /* !__cplusplus */
106  
107  int __rtai_tasklets_init(void);
108  
109  void __rtai_tasklets_exit(void);
110  
111  struct rt_tasklet_struct *rt_init_tasklet(void);
112  
113  RTAI_SYSCALL_MODE int rt_delete_tasklet(struct rt_tasklet_struct *tasklet);
114  
115  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);
116  
117  RTAI_SYSCALL_MODE void rt_remove_tasklet(struct rt_tasklet_struct *tasklet);
118  
119  struct rt_tasklet_struct *rt_find_tasklet_by_id(unsigned long id);
120  
121  RTAI_SYSCALL_MODE int rt_exec_tasklet(struct rt_tasklet_struct *tasklet);
122  
123  RTAI_SYSCALL_MODE void rt_set_tasklet_priority(struct rt_tasklet_struct *tasklet, int priority);
124  
125  RTAI_SYSCALL_MODE int rt_set_tasklet_handler(struct rt_tasklet_struct *tasklet, void (*handler)(unsigned long));
126  
127  #define rt_fast_set_tasklet_handler(t, h) do { (t)->handler = (h); } while (0)
128  
129  RTAI_SYSCALL_MODE void rt_set_tasklet_data(struct rt_tasklet_struct *tasklet, unsigned long data);
130  
131  #define rt_fast_set_tasklet_data(t, d) \
132  do { \
133     (t)->data = (d); \
134  } while (0)
135  
136  /**
137   * Notify the use of floating point operations within any tasklet/timer.
138   *
139   * rt_tasklets_use_fpu notifies that there is at least one tasklet/timer using
140   * floating point calculations within its handler function.
141   *
142   * @param use_fpu set/resets the use of floating point calculations:
143   * - a value different from 0 sets the use of floating point calculations ;
144   * - a 0 value resets the no floating calculations state.
145   *
146   * Note that the use of floating calculations is assigned once for all and is
147   * valid for all tasklets/timers. If just one handler needs it all of them
148   * will have floating point support. An optimized floating point support,
149   * i.e. on a per tasklet/timer base will add an unnoticeable performance
150   * improvement on most CPUs. However such an optimization is not rule out a
151   * priori, if anybody can prove it is really important.
152   *
153   * This function and macro can be used within the timer handler.
154   *
155   */
156  RTAI_SYSCALL_MODE struct rt_task_struct *rt_tasklet_use_fpu(struct rt_tasklet_struct *tasklet, int use_fpu);
157  
158  /**
159   * Init, in kernel space, a timed tasklet, simply called timer, structure
160   * to be used in user space.
161   *
162   * rt_timer_init allocate a timer tasklet structure (struct rt_tasklet_struct)
163   * in kernel space to be used for the management of a user space timer.
164   *
165   * This function is to be used only for user space timers. In kernel space
166   * it is just an empty macro, as the user can, and must allocate the related
167   * structure directly, either statically or dynamically.
168   *
169   * @return the pointer to the timer structure the user space application must
170   * use to access all its related services.
171   *
172   */
173  #define rt_init_timer rt_init_tasklet 
174  
175  /**
176   * Delete, in kernel space, a timed tasklet, simply called timer, structure
177   * to be used in user space.
178   *
179   * rt_timer_delete free a timer tasklet structure (struct rt_tasklet_struct) in
180   * kernel space that was allocated by rt_timer_init.
181   *
182   * @param timer is a pointer to a timer tasklet structure (struct
183   * rt_tasklet_struct).
184   *
185   * This function is to be used only for user space timers. In kernel space
186   * it is just an empty macro, as the user can, and must allocate the related
187   * structure directly, either statically or dynamically.
188   *
189   */
190  #define rt_delete_timer rt_delete_tasklet
191  
192  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);
193  
194  RTAI_SYSCALL_MODE void rt_remove_timer(struct rt_tasklet_struct *timer);
195  
196  RTAI_SYSCALL_MODE void rt_set_timer_priority(struct rt_tasklet_struct *timer, int priority);
197  
198  RTAI_SYSCALL_MODE void rt_set_timer_firing_time(struct rt_tasklet_struct *timer, RTIME firing_time);
199  
200  RTAI_SYSCALL_MODE void rt_set_timer_period(struct rt_tasklet_struct *timer, RTIME period);
201  
202  RTAI_SYSCALL_MODE void rt_get_timer_times(struct rt_tasklet_struct *timer, RTIME timer_times[]);
203  
204  RTAI_SYSCALL_MODE RTIME rt_get_timer_overrun(struct rt_tasklet_struct *timer);
205  
206  /* Posix timers support */
207  
208  RTAI_SYSCALL_MODE timer_t rt_ptimer_create(struct rt_tasklet_struct *timer, void (*handler)(unsigned long), unsigned long data, long pid, long thread);
209  
210  RTAI_SYSCALL_MODE void rt_ptimer_settime(timer_t timer, const struct itimerspec *value, unsigned long data, long flags);
211  
212  RTAI_SYSCALL_MODE int rt_ptimer_overrun(timer_t timer);
213  
214  RTAI_SYSCALL_MODE void rt_ptimer_gettime(timer_t timer, RTIME timer_times[]);
215  
216  RTAI_SYSCALL_MODE int rt_ptimer_delete(timer_t timer, long space);
217  
218  /* End Posix timers support */
219  
220  #define rt_fast_set_timer_period(t, p) \
221  do { \
222     (t)->period = (p); \
223  } while (0)
224  
225  /**
226   * Change the timer handler.
227   *
228   * rt_set_timer_handler changes the timer handler function overloading any
229   * existing value, so that at the next timer firing the new handler will be
230   * used.   Note that if a oneshot timer has its handler changed after it has
231   * already expired this function has no effect. You should reinsert it in the
232   * timer list with the new handler.
233   *
234   * @param timer is the pointer to the timer structure to be used to manage the
235   * timer at hand.
236   *
237   * @param handler is the new handler.
238   *
239   * The macro rt_fast_set_timer_handler can safely be used to substitute the
240   * corresponding function in kernel space.
241   *
242   * This function and macro can be used within the timer handler.
243   *
244   * @retval 0 on success.
245   *
246   */
247  #define rt_set_timer_handler rt_set_tasklet_handler
248  
249  #define rt_fast_set_timer_handler(t, h) do { (t)->handler = (h); } while (0)
250  
251  /**
252   * Change the data passed to a timer.
253   *
254   * rt_set_timer_data changes the timer data, overloading any existing value, so
255   * that at the next timer firing the new data will be used.   Note that if a
256   * oneshot timer has its data changed after it is already expired this function
257   * has no effect.   You should reinsert it in the timer list with the new data.
258   *
259   * @param timer is the pointer to the timer structure to be used to manage the
260   * timer at hand.
261   *
262   * @param data is the new data.
263   *
264   * The macro rt_fast_set_timer_data can safely be used substitute the
265   * corresponding function in kernel space.
266   *
267   *  This function and macro can be used within the timer handler.
268   *
269   * @retval 0 on success.
270   *
271   */
272  #define rt_set_timer_data rt_set_tasklet_data
273  
274  #define rt_fast_set_timer_data(t, d) do { (t)->data = (d); } while (0)
275  
276  #define rt_timer_use_fpu rt_tasklet_use_fpu
277  
278  RTAI_SYSCALL_MODE int rt_wait_tasklet_is_hard(struct rt_tasklet_struct *tasklet, long thread);
279  
280  RTAI_SYSCALL_MODE void rt_register_task(struct rt_tasklet_struct *tasklet, struct rt_tasklet_struct *usptasklet, struct rt_task_struct *task);
281   
282  #ifdef __cplusplus
283  }
284  #endif /* __cplusplus */
285  
286  #else /* !__KERNEL__ */
287  
288  #include <sys/types.h>
289  #include <sys/wait.h>
290  #include <sys/mman.h>
291  #include <stdarg.h>
292  
293  #include <rtai_lxrt.h>
294  
295  #define rt_tasklet_struct  rt_usp_tasklet_struct
296  #if 0
297  struct rt_tasklet_struct {
298  	struct rt_tasklet_struct *next, *prev;
299  	int priority, uses_fpu, cpuid;
300  	RTIME firing_time, period;
301  	void (*handler)(unsigned long);
302  	unsigned long data, id;
303  	long thread;
304  	struct rt_task_struct *task;
305  	struct rt_tasklet_struct *usptasklet;
306  	int overrun;
307  #ifdef  CONFIG_RTAI_LONG_TIMED_LIST
308  	struct { void *rb_parent; int rb_color; void *rb_right, *rb_left; } rbn;
309  	struct { void *rb_node; } rbr;
310  #endif
311  };
312  #endif
313  
314  #ifndef __SUPPORT_TASKLET__
315  #define __SUPPORT_TASKLET__
316  
317  struct support_tasklet_s { struct rt_tasklet_struct *tasklet; pthread_t thread; volatile int done; };
318  
319  static int support_tasklet(struct support_tasklet_s *args)
320  {
321  	RT_TASK *task;
322  	struct rt_tasklet_struct usptasklet;
323  
324  	if ((task = rt_thread_init((unsigned long)args->tasklet, 98, 0, SCHED_FIFO, 0xF))) {
325  	{
326  		struct { struct rt_tasklet_struct *tasklet, *usptasklet; RT_TASK *task; } reg = { args->tasklet, &usptasklet, task };
327  		rtai_lxrt(TASKLETS_IDX, sizeof(reg), REG_TASK, &reg);
328  	}
329  		rt_grow_and_lock_stack(TASKLET_STACK_SIZE/2);
330  		mlockall(MCL_CURRENT | MCL_FUTURE);
331  		rt_make_hard_real_time();
332  		args->done = 1;
333  		while (1) {
334  			rt_task_suspend(task);
335  			if (usptasklet.handler) {
336  				usptasklet.handler(usptasklet.data);
337  			} else {
338  				break;
339  			}
340  		}
341  		rt_make_soft_real_time();
342  		rt_task_delete(task);
343  		return 0;
344  	}
345  	printf("CANNOT INIT SUPPORT TASKLET\n");
346  	return -1;
347  	
348  }
349  #endif /* __SUPPORT_TASKLET__ */
350  
351  #ifdef __cplusplus
352  extern "C" {
353  #endif /* __cplusplus */
354  
355  RTAI_PROTO(void, rt_delete_tasklet, (struct rt_tasklet_struct *tasklet));
356  
357  RTAI_PROTO(struct rt_tasklet_struct *, rt_init_tasklet, (void))
358  {
359  	int is_hard;
360  	struct support_tasklet_s arg;
361  
362  	if ((arg.tasklet = (struct rt_tasklet_struct*)rtai_lxrt(TASKLETS_IDX, SIZARG, INIT, &arg).v[LOW])) {
363  		if ((is_hard = rt_is_hard_real_time(NULL))) {
364  			rt_make_soft_real_time();
365  		}
366  		arg.done = 0;
367  		if ((arg.thread = rt_thread_create((void *)support_tasklet, &arg.tasklet, TASKLET_STACK_SIZE))) {
368  			int i;
369  #define POLLS_PER_SEC 100
370  		        for (i = 0; i < POLLS_PER_SEC/5 && !arg.done; i++) {
371  				struct timespec delay = { 0, 1000000000/POLLS_PER_SEC };
372  				nanosleep(&delay, NULL);
373         			}
374  #undef POLLS_PER_SEC
375  			if (!arg.done || rtai_lxrt(TASKLETS_IDX, SIZARG, WAIT_IS_HARD, &arg).i[LOW]) {
376  				goto notdone;
377  			}
378  		} else {
379  notdone:
380  			rt_delete_tasklet(arg.tasklet);
381  			arg.tasklet = NULL;
382  		}
383  		if (is_hard) {
384  			rt_make_hard_real_time();
385  		}
386  	}
387  	return arg.tasklet;
388  }
389  
390  #define rt_init_timer rt_init_tasklet
391  
392  RTAI_PROTO(void, rt_delete_tasklet, (struct rt_tasklet_struct *tasklet))
393  {
394  	int thread;
395  	struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet };
396  	if ((thread = rtai_lxrt(TASKLETS_IDX, SIZARG, DELETE, &arg).i[LOW])) {
397  		rt_thread_join(thread);
398  	}
399  }
400  
401  #define rt_delete_timer rt_delete_tasklet
402  
403  RTAI_PROTO(int, rt_insert_timer,(struct rt_tasklet_struct *timer,
404  				 int priority,
405  				 RTIME firing_time,
406  				 RTIME period,
407  				 void (*handler)(unsigned long),
408  				 unsigned long data,
409  				 int pid))
410  {
411  	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 };
412  	return rtai_lxrt(TASKLETS_IDX, SIZARG, TIMER_INSERT, &arg).i[LOW];
413  }
414  
415  RTAI_PROTO(void, rt_remove_timer, (struct rt_tasklet_struct *timer))
416  {
417  	struct { struct rt_tasklet_struct *timer; } arg = { timer };
418  	rtai_lxrt(TASKLETS_IDX, SIZARG, TIMER_REMOVE, &arg);
419  }
420  
421  RTAI_PROTO(void, rt_set_timer_priority, (struct rt_tasklet_struct *timer, int priority))
422  {
423  	struct { struct rt_tasklet_struct *timer; long priority; } arg = { timer, priority };
424  	rtai_lxrt(TASKLETS_IDX, SIZARG, SET_TASKLETS_PRI, &arg);
425  }
426  
427  RTAI_PROTO(void, rt_set_timer_firing_time, (struct rt_tasklet_struct *timer, RTIME firing_time))
428  {
429  	struct { struct rt_tasklet_struct *timer; RTIME firing_time; } arg = { timer, firing_time };
430  	rtai_lxrt(TASKLETS_IDX, SIZARG, SET_FIR_TIM, &arg);
431  }
432  
433  RTAI_PROTO(void, rt_set_timer_period, (struct rt_tasklet_struct *timer, RTIME period))
434  {
435  	struct { struct rt_tasklet_struct *timer; RTIME period; } arg = { timer, period };
436  	rtai_lxrt(TASKLETS_IDX, SIZARG, SET_PER, &arg);
437  }
438  
439  RTAI_PROTO(void, rt_get_timer_times, (struct rt_tasklet_struct *timer, RTIME timer_times[]))
440  {
441  	if (timer_times) {
442  		  RTIME ltimer_times[2];
443  			struct { struct rt_tasklet_struct *timer; RTIME *timer_times; } arg = { timer, ltimer_times };
444  	    rtai_lxrt(TASKLETS_IDX, SIZARG, GET_TMR_TIM, &arg);
445  	    memcpy(timer_times, ltimer_times, sizeof(ltimer_times));
446  	}
447  }
448  
449  RTAI_PROTO(RTIME, rt_get_timer_overrun, (struct rt_tasklet_struct *timer ))
450  {
451  	struct { struct rt_tasklet_struct *timer; } arg = { timer };
452  	return rtai_lxrt(TASKLETS_IDX, SIZARG, GET_TMR_OVRN, &arg).rt;
453  }
454  
455  RTAI_PROTO(int, rt_set_tasklet_handler, (struct rt_tasklet_struct *tasklet, void (*handler)(unsigned long)))
456  {
457  	struct { struct rt_tasklet_struct *tasklet; void (*handler)(unsigned long); } arg = { tasklet, handler };
458  	return rtai_lxrt(TASKLETS_IDX, SIZARG, SET_HDL, &arg).i[LOW];
459  }
460  
461  #define rt_set_timer_handler rt_set_tasklet_handler
462  
463  RTAI_PROTO(void, rt_set_tasklet_data, (struct rt_tasklet_struct *tasklet, unsigned long data))
464  {
465  	struct { struct rt_tasklet_struct *tasklet; unsigned long data; } arg = { tasklet, data };
466  	rtai_lxrt(TASKLETS_IDX, SIZARG, SET_DAT, &arg);
467  }
468  
469  #define rt_set_timer_data rt_set_tasklet_data
470  
471  RTAI_PROTO(RT_TASK *, rt_tasklet_use_fpu, (struct rt_tasklet_struct *tasklet, int use_fpu))
472  {
473  	RT_TASK *task;
474  	struct { struct rt_tasklet_struct *tasklet; long use_fpu; } arg = { tasklet, use_fpu };
475  	if ((task = (RT_TASK*)rtai_lxrt(TASKLETS_IDX, SIZARG, USE_FPU, &arg).v[LOW])) {
476  		rt_task_use_fpu(task, use_fpu);
477  	}
478  	return task;
479  }
480  
481  #define rt_timer_use_fpu rt_tasklet_use_fpu
482  
483  RTAI_PROTO(int, rt_insert_tasklet,(struct rt_tasklet_struct *tasklet,
484  				   int priority,
485  				   void (*handler)(unsigned long),
486  				   unsigned long data,
487  				   unsigned long id,
488  				   int pid))
489  {
490  	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 };
491  	return rtai_lxrt(TASKLETS_IDX, SIZARG, TASK_INSERT, &arg).i[LOW];
492  }
493  
494  RTAI_PROTO(void, rt_set_tasklet_priority, (struct rt_tasklet_struct *tasklet, int priority))
495  {
496  	struct { struct rt_tasklet_struct *tasklet; long priority; } arg = { tasklet, priority };
497  	rtai_lxrt(TASKLETS_IDX, SIZARG, SET_TSK_PRI, &arg);
498  }
499  
500  RTAI_PROTO(void, rt_remove_tasklet, (struct rt_tasklet_struct *tasklet))
501  {
502  	struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet };
503  	rtai_lxrt(TASKLETS_IDX, SIZARG, TASK_REMOVE, &arg);
504  }
505  
506  RTAI_PROTO(int, rt_exec_tasklet, (struct rt_tasklet_struct *tasklet))
507  {
508  	struct { struct rt_tasklet_struct *tasklet; } arg = { tasklet };
509  	return rtai_lxrt(TASKLETS_IDX, SIZARG, EXEC_TASKLET, &arg).i[LOW];
510  }
511  
512  #include <stdlib.h>
513  
514  struct rt_tasklets_struct { volatile int in, out, avb, ntasklets; struct rt_tasklet_struct **tasklets; unsigned long lock; };
515  
516  RTAI_PROTO(struct rt_tasklets_struct *, rt_create_tasklets, (int ntasklets))
517  {
518  	struct rt_tasklets_struct *tasklets;
519  	if ((tasklets = (struct rt_tasklets_struct *)malloc(sizeof(struct rt_tasklets_struct)))) {
520  		if ((tasklets->tasklets = (struct rt_tasklet_struct **)malloc(ntasklets*sizeof(struct rt_tasklet_struct *)))) {
521  			int i;
522  			for (i = 0; i < ntasklets; i++) {
523  				if (!(tasklets->tasklets[i] = rt_init_tasklet())) {
524  					int k;
525  					for (k = 0; k < i; k++) {
526  						rt_delete_tasklet(tasklets->tasklets[k]);
527  					}
528  					free(tasklets->tasklets);
529  					goto free_tasklets;
530  				}
531  			}
532  			tasklets->lock = 0;
533  			tasklets->ntasklets = tasklets->avb = tasklets->in = tasklets->out = ntasklets;
534  			return tasklets;
535  		} else {
536  free_tasklets:
537  			free(tasklets);
538  		}
539  	}
540  	return NULL;
541  }
542  
543  #define rt_create_timers  rt_create_tasklets
544  
545  RTAI_PROTO(void, rt_destroy_tasklets, (struct rt_tasklets_struct *tasklets))
546  {
547  	int i;
548  	for (i = 0; i < tasklets->ntasklets; i++) {
549  		rt_delete_tasklet(tasklets->tasklets[i]);
550  	}
551  	free(tasklets->tasklets);
552  	free(tasklets);
553  }
554  
555  #define rt_destroy_timers  rt_destroy_tasklets
556  
557  #include <asm/rtai_atomic.h>
558  
559  RTAI_PROTO(struct rt_tasklet_struct *, rt_get_tasklet, (struct rt_tasklets_struct *tasklets))
560  {
561  	struct rt_tasklet_struct *tasklet;
562  	while (atomic_cmpxchg((void *)&tasklets->lock, 0, 1));
563  	if (tasklets->avb > 0) {
564  		if (tasklets->out >= tasklets->ntasklets) {
565  			tasklets->out = 0;
566  		}
567  		tasklets->avb--;
568  		tasklet = tasklets->tasklets[tasklets->out++];
569  		tasklets->lock = 0;
570  		return tasklet;
571  	}
572  	tasklets->lock = 0;
573  	return NULL;
574  }
575  
576  #define rt_get_timer  rt_get_tasklet
577  
578  RTAI_PROTO(int, rt_gvb_tasklet, (struct rt_tasklet_struct *tasklet, struct rt_tasklets_struct *tasklets))
579  {
580  	while (atomic_cmpxchg((void *)&tasklets->lock, 0, 1));
581  	if (tasklets->avb < tasklets->ntasklets) {
582  		if (tasklets->in >= tasklets->ntasklets) {
583  			tasklets->in = 0;
584  		}
585  		tasklets->avb++;
586  		tasklets->tasklets[tasklets->in++] = tasklet;
587  		tasklets->lock = 0;
588  		return 0;
589  	}
590  	tasklets->lock = 0;
591  	return EINVAL;
592  }
593  
594  #define rt_gvb_timer  rt_gvb_tasklet
595  
596  #ifdef __cplusplus
597  }
598  #endif /* __cplusplus */
599  
600  #endif /* __KERNEL__ */
601  
602  /*@}*/
603  
604  #endif /* !_RTAI_TASKLETS_H */