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 #include <linux/module.h>
00078 #include <linux/version.h>
00079 #include <linux/proc_fs.h>
00080 #include <linux/sched.h>
00081 #include <linux/slab.h>
00082 #include <linux/interrupt.h>
00083 #include <asm/uaccess.h>
00084 #include <asm/system.h>
00085 #include <asm/rtai_sched.h>
00086 #include <rtai_tasklets.h>
00087 #include <rtai_lxrt.h>
00088 #include <rtai_malloc.h>
00089 #include <rtai_schedcore.h>
00090
00091 MODULE_LICENSE("GPL");
00092
00093 extern struct epoch_struct boot_epoch;
00094
00095 DEFINE_LINUX_CR0
00096
00097 #ifdef CONFIG_SMP
00098 #define NUM_CPUS RTAI_NR_CPUS
00099 #define TIMED_TIMER_CPUID (timed_timer->cpuid)
00100 #define TIMER_CPUID (timer->cpuid)
00101 #define LIST_CPUID (cpuid)
00102 #else
00103 #define NUM_CPUS 1
00104 #define TIMED_TIMER_CPUID (0)
00105 #define TIMER_CPUID (0)
00106 #define LIST_CPUID (0)
00107 #endif
00108
00109
00110 static struct rt_tasklet_struct timers_list[NUM_CPUS] =
00111 { { &timers_list[0], &timers_list[0], RT_SCHED_LOWEST_PRIORITY, 0, 0, RT_TIME_END, 0LL, NULL, 0UL, 0UL, 0, NULL, NULL, 0,
00112 #ifdef CONFIG_RTAI_LONG_TIMED_LIST
00113 { NULL }
00114 #endif
00115 }, };
00116
00117 static struct rt_tasklet_struct tasklets_list =
00118 { &tasklets_list, &tasklets_list, };
00119
00120 static spinlock_t timers_lock[NUM_CPUS] = { SPIN_LOCK_UNLOCKED, };
00121 static spinlock_t tasklets_lock = SPIN_LOCK_UNLOCKED;
00122
00123 static struct rt_fun_entry rt_tasklet_fun[] __attribute__ ((__unused__));
00124
00125 static struct rt_fun_entry rt_tasklet_fun[] = {
00126 { 0, rt_init_tasklet },
00127 { 0, rt_delete_tasklet },
00128 { 0, rt_insert_tasklet },
00129 { 0, rt_remove_tasklet },
00130 { 0, rt_tasklet_use_fpu },
00131 { 0, rt_insert_timer },
00132 { 0, rt_remove_timer },
00133 { 0, rt_set_timer_priority },
00134 { 0, rt_set_timer_firing_time },
00135 { 0, rt_set_timer_period },
00136 { 0, rt_set_tasklet_handler },
00137 { 0, rt_set_tasklet_data },
00138 { 0, rt_exec_tasklet },
00139 { 0, rt_wait_tasklet_is_hard },
00140 { 0, rt_set_tasklet_priority },
00141 { 0, rt_register_task },
00142 { 0, rt_get_timer_times },
00143 { 0, rt_get_timer_overrun },
00144
00145
00146
00147 { 0, rt_ptimer_create },
00148 { 0, rt_ptimer_settime },
00149 { 0, rt_ptimer_overrun },
00150 { 0, rt_ptimer_gettime },
00151 { 0, rt_ptimer_delete }
00152
00153
00154
00155 };
00156
00157 #ifdef CONFIG_RTAI_LONG_TIMED_LIST
00158
00159
00160 static inline void enq_timer(struct rt_tasklet_struct *timed_timer)
00161 {
00162 struct rt_tasklet_struct *timerh, *tmrnxt, *timer;
00163 rb_node_t **rbtn, *rbtpn = NULL;
00164 timer = timerh = &timers_list[TIMED_TIMER_CPUID];
00165 rbtn = &timerh->rbr.rb_node;
00166
00167 while (*rbtn) {
00168 rbtpn = *rbtn;
00169 tmrnxt = rb_entry(rbtpn, struct rt_tasklet_struct, rbn);
00170 if (timer->firing_time > tmrnxt->firing_time) {
00171 rbtn = &(rbtpn)->rb_right;
00172 } else {
00173 rbtn = &(rbtpn)->rb_left;
00174 timer = tmrnxt;
00175 }
00176 }
00177 rb_link_node(&timed_timer->rbn, rbtpn, rbtn);
00178 rb_insert_color(&timed_timer->rbn, &timerh->rbr);
00179 timer->prev = (timed_timer->prev = timer->prev)->next = timed_timer;
00180 timed_timer->next = timer;
00181 }
00182
00183 #define rb_erase_timer(timer) \
00184 rb_erase(&(timer)->rbn, &timers_list[NUM_CPUS > 1 ? (timer)->cpuid : 0].rbr)
00185
00186 #else
00187
00188
00189 static inline void enq_timer(struct rt_tasklet_struct *timed_timer)
00190 {
00191 struct rt_tasklet_struct *timer;
00192 timer = &timers_list[TIMED_TIMER_CPUID];
00193 while (timed_timer->firing_time > (timer = timer->next)->firing_time);
00194 timer->prev = (timed_timer->prev = timer->prev)->next = timed_timer;
00195 timed_timer->next = timer;
00196 }
00197
00198 #define rb_erase_timer(timer)
00199
00200 #endif
00201
00202 static inline void rem_timer(struct rt_tasklet_struct *timer)
00203 {
00204 (timer->next)->prev = timer->prev;
00205 (timer->prev)->next = timer->next;
00206 timer->next = timer->prev = timer;
00207 rb_erase_timer(timer);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 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)
00242 {
00243 unsigned long flags;
00244
00245
00246 if (!handler || !id) {
00247 return -EINVAL;
00248 }
00249 tasklet->uses_fpu = 0;
00250 tasklet->priority = priority;
00251 tasklet->handler = handler;
00252 tasklet->data = data;
00253 tasklet->id = id;
00254 if (!pid) {
00255 tasklet->task = 0;
00256 } else {
00257 (tasklet->task)->priority = priority;
00258 rt_copy_to_user(tasklet->usptasklet, tasklet, sizeof(struct rt_usp_tasklet_struct));
00259 }
00260
00261 flags = rt_spin_lock_irqsave(&tasklets_lock);
00262 tasklet->next = &tasklets_list;
00263 tasklet->prev = tasklets_list.prev;
00264 (tasklets_list.prev)->next = tasklet;
00265 tasklets_list.prev = tasklet;
00266 rt_spin_unlock_irqrestore(flags, &tasklets_lock);
00267 return 0;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 RTAI_SYSCALL_MODE void rt_remove_tasklet(struct rt_tasklet_struct *tasklet)
00281 {
00282 if (tasklet->next && tasklet->prev && tasklet->next != tasklet && tasklet->prev != tasklet) {
00283 unsigned long flags;
00284 flags = rt_spin_lock_irqsave(&tasklets_lock);
00285 (tasklet->next)->prev = tasklet->prev;
00286 (tasklet->prev)->next = tasklet->next;
00287 tasklet->next = tasklet->prev = tasklet;
00288 rt_spin_unlock_irqrestore(flags, &tasklets_lock);
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 struct rt_tasklet_struct *rt_find_tasklet_by_id(unsigned long id)
00307 {
00308 struct rt_tasklet_struct *tasklet;
00309
00310 tasklet = &tasklets_list;
00311 while ((tasklet = tasklet->next) != &tasklets_list) {
00312 if (id == tasklet->id) {
00313 return tasklet;
00314 }
00315 }
00316 return 0;
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 RTAI_SYSCALL_MODE int rt_exec_tasklet(struct rt_tasklet_struct *tasklet)
00340 {
00341 if (tasklet && tasklet->next != tasklet && tasklet->prev != tasklet) {
00342 if (!tasklet->task) {
00343 tasklet->handler(tasklet->data);
00344 } else {
00345 rt_task_resume(tasklet->task);
00346 }
00347 return 0;
00348 }
00349 return -EINVAL;
00350 }
00351
00352 RTAI_SYSCALL_MODE void rt_set_tasklet_priority(struct rt_tasklet_struct *tasklet, int priority)
00353 {
00354 tasklet->priority = priority;
00355 if (tasklet->task) {
00356 (tasklet->task)->priority = priority;
00357 }
00358 }
00359
00360 RTAI_SYSCALL_MODE int rt_set_tasklet_handler(struct rt_tasklet_struct *tasklet, void (*handler)(unsigned long))
00361 {
00362 if (!handler) {
00363 return -EINVAL;
00364 }
00365 tasklet->handler = handler;
00366 if (tasklet->task) {
00367 rt_copy_to_user(tasklet->usptasklet, tasklet, sizeof(struct rt_usp_tasklet_struct));
00368 }
00369 return 0;
00370 }
00371
00372 RTAI_SYSCALL_MODE void rt_set_tasklet_data(struct rt_tasklet_struct *tasklet, unsigned long data)
00373 {
00374 tasklet->data = data;
00375 if (tasklet->task) {
00376 rt_copy_to_user(tasklet->usptasklet, tasklet, sizeof(struct rt_usp_tasklet_struct));
00377 }
00378 }
00379
00380 RTAI_SYSCALL_MODE RT_TASK *rt_tasklet_use_fpu(struct rt_tasklet_struct *tasklet, int use_fpu)
00381 {
00382 tasklet->uses_fpu = use_fpu ? 1 : 0;
00383 return tasklet->task;
00384 }
00385
00386 static RT_TASK timers_manager[NUM_CPUS];
00387
00388 static inline void asgn_min_prio(int cpuid)
00389 {
00390
00391 RT_TASK *timer_manager;
00392 struct rt_tasklet_struct *timer, *timerl;
00393 spinlock_t *lock;
00394 unsigned long flags;
00395 int priority;
00396
00397 priority = (timer = (timerl = &timers_list[LIST_CPUID])->next)->priority;
00398 flags = rt_spin_lock_irqsave(lock = &timers_lock[LIST_CPUID]);
00399 while ((timer = timer->next) != timerl) {
00400 if (timer->priority < priority) {
00401 priority = timer->priority;
00402 }
00403 rt_spin_unlock_irqrestore(flags, lock);
00404 flags = rt_spin_lock_irqsave(lock);
00405 }
00406 rt_spin_unlock_irqrestore(flags, lock);
00407 flags = rt_global_save_flags_and_cli();
00408 if ((timer_manager = &timers_manager[LIST_CPUID])->priority > priority) {
00409 timer_manager->priority = priority;
00410 if (timer_manager->state == RT_SCHED_READY) {
00411 rem_ready_task(timer_manager);
00412 enq_ready_task(timer_manager);
00413 }
00414 }
00415 rt_global_restore_flags(flags);
00416 }
00417
00418 static inline void set_timer_firing_time(struct rt_tasklet_struct *timer, RTIME firing_time)
00419 {
00420 if (timer->next != timer && timer->prev != timer) {
00421 spinlock_t *lock;
00422 unsigned long flags;
00423
00424 timer->firing_time = firing_time;
00425 flags = rt_spin_lock_irqsave(lock = &timers_lock[TIMER_CPUID]);
00426 rem_timer(timer);
00427 enq_timer(timer);
00428 rt_spin_unlock_irqrestore(flags, lock);
00429 }
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 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)
00470 {
00471 spinlock_t *lock;
00472 unsigned long flags, cpuid;
00473 RT_TASK *timer_manager;
00474
00475
00476 timer->uses_fpu = 0;
00477
00478 if (pid >= 0) {
00479 if (!handler) {
00480 return -EINVAL;
00481 }
00482 timer->handler = handler;
00483 timer->data = data;
00484 } else {
00485 if (timer->handler != NULL || timer->handler == (void *)1) {
00486 timer->handler = (void *)1;
00487 timer->data = data;
00488 }
00489 }
00490
00491 timer->priority = priority;
00492 REALTIME2COUNT(firing_time)
00493 timer->firing_time = firing_time;
00494 timer->period = period;
00495
00496 if (!pid) {
00497 timer->task = 0;
00498 timer->cpuid = cpuid = NUM_CPUS > 1 ? rtai_cpuid() : 0;
00499 } else {
00500 timer->cpuid = cpuid = NUM_CPUS > 1 ? (timer->task)->runnable_on_cpus : 0;
00501 (timer->task)->priority = priority;
00502 rt_copy_to_user(timer->usptasklet, timer, sizeof(struct rt_usp_tasklet_struct));
00503 }
00504
00505 flags = rt_spin_lock_irqsave(lock = &timers_lock[LIST_CPUID]);
00506 enq_timer(timer);
00507 rt_spin_unlock_irqrestore(flags, lock);
00508
00509 if (timer->priority < (timer_manager = &timers_manager[LIST_CPUID])->priority) {
00510 timer_manager->priority = timer->priority;
00511 }
00512
00513 flags = rt_global_save_flags_and_cli();
00514 if (timers_list[LIST_CPUID].next == timer && (timer_manager->state & RT_SCHED_DELAYED) && firing_time < timer_manager->resume_time) {
00515 timer_manager->resume_time = firing_time;
00516 rem_timed_task(timer_manager);
00517 enq_timed_task(timer_manager);
00518 rt_schedule();
00519 }
00520 rt_global_restore_flags(flags);
00521 return 0;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 RTAI_SYSCALL_MODE void rt_remove_timer(struct rt_tasklet_struct *timer)
00535 {
00536 if (timer->next && timer->prev && timer->next != timer && timer->prev != timer) {
00537 spinlock_t *lock;
00538 unsigned long flags;
00539 flags = rt_spin_lock_irqsave(lock = &timers_lock[TIMER_CPUID]);
00540 rem_timer(timer);
00541 rt_spin_unlock_irqrestore(flags, lock);
00542 asgn_min_prio(TIMER_CPUID);
00543 }
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 RTAI_SYSCALL_MODE void rt_set_timer_priority(struct rt_tasklet_struct *timer, int priority)
00563 {
00564 timer->priority = priority;
00565 if (timer->task) {
00566 (timer->task)->priority = priority;
00567 }
00568 asgn_min_prio(TIMER_CPUID);
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 RTAI_SYSCALL_MODE void rt_set_timer_firing_time(struct rt_tasklet_struct *timer, RTIME firing_time)
00592 {
00593 unsigned long flags;
00594 RT_TASK *timer_manager;
00595
00596 set_timer_firing_time(timer, firing_time);
00597 flags = rt_global_save_flags_and_cli();
00598 if (timers_list[TIMER_CPUID].next == timer && ((timer_manager = &timers_manager[TIMER_CPUID])->state & RT_SCHED_DELAYED) && firing_time < timer_manager->resume_time) {
00599 timer_manager->resume_time = firing_time;
00600 rem_timed_task(timer_manager);
00601 enq_timed_task(timer_manager);
00602 rt_schedule();
00603 }
00604 rt_global_restore_flags(flags);
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 RTAI_SYSCALL_MODE void rt_set_timer_period(struct rt_tasklet_struct *timer, RTIME period)
00632 {
00633 spinlock_t *lock;
00634 unsigned long flags;
00635 flags = rt_spin_lock_irqsave(lock = &timers_lock[TIMER_CPUID]);
00636 timer->period = period;
00637 rt_spin_unlock_irqrestore(flags, lock);
00638 }
00639
00640 RTAI_SYSCALL_MODE void rt_get_timer_times(struct rt_tasklet_struct *timer, RTIME timer_times[])
00641 {
00642 RTIME firing;
00643
00644 firing = -rt_get_time();
00645 firing += timer->firing_time;
00646
00647 timer_times[0] = firing > 0 ? firing : -1;
00648 timer_times[1] = timer->period;
00649 }
00650
00651 RTAI_SYSCALL_MODE RTIME rt_get_timer_overrun(struct rt_tasklet_struct *timer)
00652 {
00653 return timer->overrun;
00654 }
00655
00656 static int TimersManagerPrio = 0;
00657 RTAI_MODULE_PARM(TimersManagerPrio, int);
00658
00659
00660
00661 static void rt_timers_manager(long cpuid)
00662 {
00663 RTIME now;
00664 RT_TASK *timer_manager;
00665 struct rt_tasklet_struct *tmr, *timer, *timerl;
00666 spinlock_t *lock;
00667 unsigned long flags, timer_tol;
00668 int priority, used_fpu;
00669
00670 timer_manager = &timers_manager[LIST_CPUID];
00671 timerl = &timers_list[LIST_CPUID];
00672 lock = &timers_lock[LIST_CPUID];
00673 timer_tol = tuned.timers_tol[LIST_CPUID];
00674
00675 while (1) {
00676 int retval;
00677 retval = rt_sleep_until((timerl->next)->firing_time);
00678
00679 now = rt_get_time() + timer_tol;
00680
00681 while (1) {
00682 used_fpu = 0;
00683 tmr = timer = timerl;
00684 priority = RT_SCHED_LOWEST_PRIORITY;
00685 flags = rt_spin_lock_irqsave(lock);
00686 while ((tmr = tmr->next)->firing_time <= now) {
00687 if (tmr->priority < priority) {
00688 priority = (timer = tmr)->priority;
00689 }
00690 }
00691 rt_spin_unlock_irqrestore(flags, lock);
00692 if (timer == timerl) {
00693 if (timer_manager->priority > TimersManagerPrio) {
00694 timer_manager->priority = TimersManagerPrio;
00695 }
00696 break;
00697 }
00698 timer_manager->priority = priority;
00699 #if 1
00700 flags = rt_spin_lock_irqsave(lock);
00701 rem_timer(timer);
00702 if (timer->period) {
00703 timer->firing_time += timer->period;
00704 enq_timer(timer);
00705 }
00706 rt_spin_unlock_irqrestore(flags, lock);
00707 #else
00708 if (!timer->period) {
00709 flags = rt_spin_lock_irqsave(lock);
00710 rem_timer(timer);
00711 rt_spin_unlock_irqrestore(flags, lock);
00712 } else {
00713 set_timer_firing_time(timer, timer->firing_time + timer->period);
00714 }
00715 #endif
00716
00717 tmr->overrun = 0;
00718 if (!timer->task) {
00719 if (!used_fpu && timer->uses_fpu) {
00720 used_fpu = 1;
00721 save_fpcr_and_enable_fpu(linux_cr0);
00722 save_fpenv(timer_manager->fpu_reg);
00723 }
00724 timer->handler(timer->data);
00725 } else {
00726 rt_task_resume(timer->task);
00727 }
00728
00729
00730
00731 }
00732 if (used_fpu) {
00733 restore_fpenv(timer_manager->fpu_reg);
00734 restore_fpcr(linux_cr0);
00735 }
00736
00737 asgn_min_prio(LIST_CPUID);
00738
00739 }
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 struct rt_tasklet_struct *rt_init_tasklet(void)
00756 {
00757 struct rt_tasklet_struct *tasklet;
00758 if ((tasklet = rt_malloc(sizeof(struct rt_tasklet_struct)))) {
00759 memset(tasklet, 0, sizeof(struct rt_tasklet_struct));
00760 }
00761 return tasklet;
00762 }
00763
00764 RTAI_SYSCALL_MODE void rt_register_task(struct rt_tasklet_struct *tasklet, struct rt_tasklet_struct *usptasklet, RT_TASK *task)
00765 {
00766 tasklet->task = task;
00767 tasklet->usptasklet = usptasklet;
00768 rt_copy_to_user(usptasklet, tasklet, sizeof(struct rt_usp_tasklet_struct));
00769 }
00770
00771 RTAI_SYSCALL_MODE int rt_wait_tasklet_is_hard(struct rt_tasklet_struct *tasklet, long thread)
00772 {
00773 #define POLLS_PER_SEC 100
00774 int i;
00775 tasklet->thread = thread;
00776 for (i = 0; i < POLLS_PER_SEC/5; i++) {
00777 if (!tasklet->task || !((tasklet->task)->state & RT_SCHED_SUSPENDED)) {
00778 current->state = TASK_INTERRUPTIBLE;
00779 schedule_timeout(HZ/POLLS_PER_SEC);
00780 } else {
00781 return 0;
00782 }
00783 }
00784 return 1;
00785 #undef POLLS_PER_SEC
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 RTAI_SYSCALL_MODE int rt_delete_tasklet(struct rt_tasklet_struct *tasklet)
00804 {
00805 int thread;
00806
00807 rt_remove_tasklet(tasklet);
00808 tasklet->handler = 0;
00809 rt_copy_to_user(tasklet->usptasklet, tasklet, sizeof(struct rt_usp_tasklet_struct));
00810 rt_task_resume(tasklet->task);
00811 thread = tasklet->thread;
00812 rt_free(tasklet);
00813 return thread;
00814 }
00815
00816
00817
00818
00819
00820
00821 static int PosixTimers = POSIX_TIMERS;
00822 RTAI_MODULE_PARM(PosixTimers, int);
00823
00824 static spinlock_t ptimer_lock = SPIN_LOCK_UNLOCKED;
00825 static volatile int ptimer_index;
00826 struct ptimer_list { int t_indx, p_idx; struct ptimer_list *p_ptr; struct rt_tasklet_struct *timer;} *posix_timer;
00827
00828 static int init_ptimers(void)
00829 {
00830 int i;
00831
00832 if (!(posix_timer = (struct ptimer_list *)kmalloc((PosixTimers)*sizeof(struct ptimer_list), GFP_KERNEL))) {
00833 printk("Init MODULE no memory for Posix Timer's list.\n");
00834 return -ENOMEM;
00835 }
00836 for (i = 0; i < PosixTimers; i++) {
00837 posix_timer[i].t_indx = posix_timer[i].p_idx = i;
00838 posix_timer[i].p_ptr = posix_timer + i;
00839 }
00840 return 0;
00841
00842 }
00843
00844 static void cleanup_ptimers(void)
00845 {
00846 kfree(posix_timer);
00847 }
00848
00849 static inline int get_ptimer_indx(struct rt_tasklet_struct *timer)
00850 {
00851 unsigned long flags;
00852
00853 flags = rt_spin_lock_irqsave(&ptimer_lock);
00854 if (ptimer_index < PosixTimers) {
00855 struct ptimer_list *p;
00856 p = posix_timer[ptimer_index++].p_ptr;
00857 p->timer = timer;
00858 rt_spin_unlock_irqrestore(flags, &ptimer_lock);
00859 return p->t_indx;
00860 }
00861 rt_spin_unlock_irqrestore(flags, &ptimer_lock);
00862 return 0;
00863 }
00864
00865 static inline int gvb_ptimer_indx(int itimer)
00866 {
00867 unsigned long flags;
00868
00869 flags = rt_spin_lock_irqsave(&ptimer_lock);
00870 if (itimer < PosixTimers) {
00871 struct ptimer_list *tmp_p;
00872 int tmp_place;
00873 tmp_p = posix_timer[--ptimer_index].p_ptr;
00874 tmp_place = posix_timer[itimer].p_idx;
00875 posix_timer[itimer].p_idx = ptimer_index;
00876 posix_timer[ptimer_index].p_ptr = &posix_timer[itimer];
00877 tmp_p->p_idx = tmp_place;
00878 posix_timer[tmp_place].p_ptr = tmp_p;
00879 rt_spin_unlock_irqrestore(flags, &ptimer_lock);
00880 return 0;
00881 }
00882 rt_spin_unlock_irqrestore(flags, &ptimer_lock);
00883 return -EINVAL;
00884 }
00885
00886 RTAI_SYSCALL_MODE timer_t rt_ptimer_create(struct rt_tasklet_struct *timer, void (*handler)(unsigned long), unsigned long data, long pid, long thread)
00887 {
00888 if (thread) {
00889 rt_wait_tasklet_is_hard(timer, thread);
00890 }
00891 timer->next = timer;
00892 timer->prev = timer;
00893 timer->data = data;
00894 timer->handler = handler;
00895 return get_ptimer_indx(timer);
00896 }
00897 EXPORT_SYMBOL(rt_ptimer_create);
00898
00899 RTAI_SYSCALL_MODE void rt_ptimer_settime(timer_t timer, const struct itimerspec *value, unsigned long data, long flags)
00900 {
00901 struct rt_tasklet_struct *tasklet;
00902 RTIME now;
00903
00904 tasklet = posix_timer[timer].timer;
00905 rt_remove_timer(tasklet);
00906 now = rt_get_time();
00907 if (flags == TIMER_ABSTIME) {
00908 if (timespec2count(&(value->it_value)) < now) {
00909 now -= timespec2count (&(value->it_value));
00910 }else {
00911 now = 0;
00912 }
00913 }
00914 if (timespec2count ( &(value->it_value)) > 0) {
00915 if (data) {
00916 rt_insert_timer(tasklet, 0, now + timespec2count ( &(value->it_value) ), timespec2count ( &(value->it_interval) ), NULL, data, -1);
00917 } else {
00918 rt_insert_timer(tasklet, 0, now + timespec2count ( &(value->it_value) ), timespec2count ( &(value->it_interval) ), tasklet->handler, tasklet->data, 0);
00919 }
00920 }
00921 }
00922 EXPORT_SYMBOL(rt_ptimer_settime);
00923
00924 RTAI_SYSCALL_MODE int rt_ptimer_overrun(timer_t timer)
00925 {
00926 return rt_get_timer_overrun(posix_timer[timer].timer);
00927 }
00928 EXPORT_SYMBOL(rt_ptimer_overrun);
00929
00930 RTAI_SYSCALL_MODE void rt_ptimer_gettime(timer_t timer, RTIME timer_times[])
00931 {
00932 rt_get_timer_times(posix_timer[timer].timer, timer_times);
00933 }
00934 EXPORT_SYMBOL(rt_ptimer_gettime);
00935
00936 RTAI_SYSCALL_MODE int rt_ptimer_delete(timer_t timer, long space)
00937 {
00938 struct rt_tasklet_struct *tasklet;
00939 int rtn = 0;
00940
00941 tasklet = posix_timer[timer].timer;
00942 gvb_ptimer_indx(timer);
00943 rt_remove_tasklet(tasklet);
00944 if (space) {
00945 tasklet->handler = 0;
00946 rt_copy_to_user(tasklet->usptasklet, tasklet, sizeof(struct rt_usp_tasklet_struct));
00947 rt_task_resume(tasklet->task);
00948 rtn = tasklet->thread;
00949 }
00950 rt_free(tasklet);
00951 return rtn;
00952 }
00953 EXPORT_SYMBOL(rt_ptimer_delete);
00954
00955
00956
00957
00958
00959 static int TaskletsStacksize = TASKLET_STACK_SIZE;
00960 RTAI_MODULE_PARM(TaskletsStacksize, int);
00961
00962 int __rtai_tasklets_init(void)
00963 {
00964 int cpuid;
00965
00966 if(set_rt_fun_ext_index(rt_tasklet_fun, TASKLETS_IDX)) {
00967 printk("Recompile your module with a different index\n");
00968 return -EACCES;
00969 }
00970 if (init_ptimers()) {
00971 return -ENOMEM;
00972 }
00973 for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {
00974 timers_lock[cpuid] = timers_lock[0];
00975 timers_list[cpuid] = timers_list[0];
00976 timers_list[cpuid].cpuid = cpuid;
00977 timers_list[cpuid].next = timers_list[cpuid].prev = &timers_list[cpuid];
00978 rt_task_init_cpuid(&timers_manager[cpuid], rt_timers_manager, cpuid, TaskletsStacksize, TimersManagerPrio, 0, 0, cpuid);
00979 rt_task_resume(&timers_manager[cpuid]);
00980 }
00981 printk(KERN_INFO "RTAI[tasklets]: loaded.\n");
00982 return 0;
00983 }
00984
00985 void __rtai_tasklets_exit(void)
00986 {
00987 int cpuid;
00988 reset_rt_fun_ext_index(rt_tasklet_fun, TASKLETS_IDX);
00989 cleanup_ptimers();
00990 for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {
00991 rt_task_delete(&timers_manager[cpuid]);
00992 }
00993 printk(KERN_INFO "RTAI[tasklets]: unloaded.\n");
00994 }
00995
00996
00997
00998 #ifndef CONFIG_RTAI_TASKLETS_BUILTIN
00999 module_init(__rtai_tasklets_init);
01000 module_exit(__rtai_tasklets_exit);
01001 #endif
01002
01003 #ifdef CONFIG_KBUILD
01004 EXPORT_SYMBOL(rt_insert_tasklet);
01005 EXPORT_SYMBOL(rt_remove_tasklet);
01006 EXPORT_SYMBOL(rt_find_tasklet_by_id);
01007 EXPORT_SYMBOL(rt_exec_tasklet);
01008 EXPORT_SYMBOL(rt_set_tasklet_priority);
01009 EXPORT_SYMBOL(rt_set_tasklet_handler);
01010 EXPORT_SYMBOL(rt_set_tasklet_data);
01011 EXPORT_SYMBOL(rt_tasklet_use_fpu);
01012 EXPORT_SYMBOL(rt_insert_timer);
01013 EXPORT_SYMBOL(rt_remove_timer);
01014 EXPORT_SYMBOL(rt_set_timer_priority);
01015 EXPORT_SYMBOL(rt_set_timer_firing_time);
01016 EXPORT_SYMBOL(rt_set_timer_period);
01017 EXPORT_SYMBOL(rt_init_tasklet);
01018 EXPORT_SYMBOL(rt_register_task);
01019 EXPORT_SYMBOL(rt_wait_tasklet_is_hard);
01020 EXPORT_SYMBOL(rt_delete_tasklet);
01021 EXPORT_SYMBOL(rt_get_timer_times);
01022 EXPORT_SYMBOL(rt_get_timer_overrun);
01023 #endif