rtai_schedcore.h

00001 /*
00002  * Copyright (C) 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #ifndef _RTAI_SCHEDCORE_H
00020 #define _RTAI_SCHEDCORE_H
00021 
00022 #include <rtai_version.h>
00023 #include <rtai_lxrt.h>
00024 #include <rtai_sched.h>
00025 #include <rtai_malloc.h>
00026 #include <rtai_trace.h>
00027 #include <rtai_leds.h>
00028 #include <rtai_sem.h>
00029 #include <rtai_rwl.h>
00030 #include <rtai_spl.h>
00031 #include <rtai_scb.h>
00032 #include <rtai_mbx.h>
00033 #include <rtai_msg.h>
00034 #include <rtai_tbx.h>
00035 #include <rtai_mq.h>
00036 #include <rtai_bits.h>
00037 #include <rtai_wd.h>
00038 #include <rtai_tasklets.h>
00039 #include <rtai_fifos.h>
00040 #include <rtai_netrpc.h>
00041 #include <rtai_shm.h>
00042 #include <rtai_usi.h>
00043 
00044 #ifdef __KERNEL__
00045 
00046 #include <linux/module.h>
00047 #include <linux/init.h>
00048 #include <linux/kernel.h>
00049 #include <linux/version.h>
00050 #include <linux/errno.h>
00051 #include <linux/slab.h>
00052 #include <linux/timex.h>
00053 #include <linux/sched.h>
00054 #include <asm/param.h>
00055 #include <asm/system.h>
00056 #include <asm/io.h>
00057 
00058 extern RT_TASK rt_smp_linux_task[];
00059 
00060 extern RT_TASK *rt_smp_current[];
00061 
00062 extern RTIME rt_smp_time_h[];
00063 
00064 extern int rt_smp_oneshot_timer[];
00065 
00066 #ifdef CONFIG_RTAI_MALLOC
00067 #define sched_malloc(size)              rt_malloc((size))
00068 #define sched_free(adr)                 rt_free((adr))
00069 #ifndef CONFIG_RTAI_MALLOC_BUILTIN
00070 #define sched_mem_init()
00071 #define sched_mem_end()
00072 #else  /* CONFIG_RTAI_MALLOC_BUILTIN */
00073 #define sched_mem_init() \
00074         { if(__rtai_heap_init() != 0) { \
00075                 return(-ENOMEM); \
00076         } }
00077 #define sched_mem_end()         __rtai_heap_exit()
00078 #endif /* !CONFIG_RTAI_MALLOC_BUILTIN */
00079 #define call_exit_handlers(task)                __call_exit_handlers(task)
00080 #define set_exit_handler(task, fun, arg1, arg2) __set_exit_handler(task, fun, arg1, arg2)
00081 #else  /* !CONFIG_RTAI_MALLOC */
00082 #define sched_malloc(size)      kmalloc((size), GFP_KERNEL)
00083 #define sched_free(adr)         kfree((adr))
00084 #define sched_mem_init()
00085 #define sched_mem_end()
00086 #define call_exit_handlers(task)
00087 #define set_exit_handler(task, fun, arg1, arg2)
00088 #endif /* CONFIG_RTAI_MALLOC */
00089 
00090 #define RT_SEM_MAGIC 0xaabcdeff
00091 
00092 #define SEM_ERR (0xFfff)
00093 
00094 #define MSG_ERR ((RT_TASK *)0xFfff)
00095 
00096 #define NOTHING ((void *)0)
00097 
00098 #define SOMETHING ((void *)1)
00099 
00100 #define SEMHLF 0x0000FFFF
00101 #define RPCHLF 0xFFFF0000
00102 #define RPCINC 0x00010000
00103 
00104 #define DECLARE_RT_CURRENT int cpuid; RT_TASK *rt_current
00105 #define ASSIGN_RT_CURRENT rt_current = rt_smp_current[cpuid = rtai_cpuid()]
00106 #define RT_CURRENT rt_smp_current[rtai_cpuid()]
00107 
00108 #define MAX_LINUX_RTPRIO  99
00109 #define MIN_LINUX_RTPRIO   1
00110 
00111 #ifdef CONFIG_RTAI_SCHED_ISR_LOCK
00112 void rtai_handle_isched_lock(int nesting);
00113 #endif /* CONFIG_RTAI_SCHED_ISR_LOCK */
00114 
00115 #ifdef CONFIG_SMP
00116 #define rt_time_h (rt_smp_time_h[cpuid])
00117 #define oneshot_timer (rt_smp_oneshot_timer[cpuid])
00118 #define rt_linux_task (rt_smp_linux_task[cpuid])
00119 #else
00120 #define rt_time_h (rt_smp_time_h[0])
00121 #define oneshot_timer (rt_smp_oneshot_timer[0])
00122 #define rt_linux_task (rt_smp_linux_task[0])
00123 #endif
00124 
00125 #ifdef CONFIG_SMP
00126 
00127 static inline void send_sched_ipi(unsigned long dest)
00128 {
00129         _send_sched_ipi(dest);
00130 }
00131 
00132 #define RT_SCHEDULE_MAP(schedmap) \
00133         do { if (schedmap) send_sched_ipi(schedmap); } while (0)
00134 
00135 #define RT_SCHEDULE_MAP_BOTH(schedmap) \
00136         do { if (schedmap) send_sched_ipi(schedmap); rt_schedule(); } while (0)
00137 
00138 #define RT_SCHEDULE(task, cpuid) \
00139         do { \
00140                 if ((task)->runnable_on_cpus != (cpuid)) { \
00141                         send_sched_ipi(1 << (task)->runnable_on_cpus); \
00142                 } else { \
00143                         rt_schedule(); \
00144                 } \
00145         } while (0)
00146 
00147 #define RT_SCHEDULE_BOTH(task, cpuid) \
00148         { \
00149                 if ((task)->runnable_on_cpus != (cpuid)) { \
00150                         send_sched_ipi(1 << (task)->runnable_on_cpus); \
00151                 } \
00152                 rt_schedule(); \
00153         }
00154 
00155 #else /* !CONFIG_SMP */
00156 
00157 #define send_sched_ipi(dest)
00158 
00159 #define RT_SCHEDULE_MAP_BOTH(schedmap)  rt_schedule()
00160 
00161 #define RT_SCHEDULE_MAP(schedmap)       rt_schedule()
00162 
00163 #define RT_SCHEDULE(task, cpuid)        rt_schedule()
00164 
00165 #define RT_SCHEDULE_BOTH(task, cpuid)   rt_schedule()
00166 
00167 #endif /* CONFIG_SMP */
00168 
00169 #define BASE_SOFT_PRIORITY 1000000000
00170 
00171 #define TASK_HARDREALTIME  TASK_UNINTERRUPTIBLE
00172 
00173 static inline void enq_ready_edf_task(RT_TASK *ready_task)
00174 {
00175         RT_TASK *task;
00176 #ifdef CONFIG_SMP
00177         task = rt_smp_linux_task[ready_task->runnable_on_cpus].rnext;
00178 #else
00179         task = rt_smp_linux_task[0].rnext;
00180 #endif
00181         while (task->policy < 0 && ready_task->period >= task->period) {
00182                 task = task->rnext;
00183         }
00184         task->rprev = (ready_task->rprev = task->rprev)->rnext = ready_task;
00185         ready_task->rnext = task;
00186 }
00187 
00188 #define MAX_WAKEUP_SRQ (2 << 6)
00189 
00190 struct klist_t { volatile int srq, in, out; void *task[MAX_WAKEUP_SRQ]; };
00191 extern struct klist_t wake_up_srq;
00192 
00193 static inline void enq_ready_task(RT_TASK *ready_task)
00194 {
00195         RT_TASK *task;
00196         if (ready_task->is_hard) {
00197 #ifdef CONFIG_SMP
00198                 task = rt_smp_linux_task[ready_task->runnable_on_cpus].rnext;
00199 #else
00200                 task = rt_smp_linux_task[0].rnext;
00201 #endif
00202                 while (ready_task->priority >= task->priority) {
00203                         if ((task = task->rnext)->priority < 0) break;
00204                 }
00205                 task->rprev = (ready_task->rprev = task->rprev)->rnext = ready_task;
00206                 ready_task->rnext = task;
00207         } else {
00208                 ready_task->state |= RT_SCHED_SFTRDY;
00209                 wake_up_srq.task[wake_up_srq.in] = ready_task->lnxtsk;
00210                 wake_up_srq.in = (wake_up_srq.in + 1) & (MAX_WAKEUP_SRQ - 1);
00211                 rt_pend_linux_srq(wake_up_srq.srq);
00212         }
00213 }
00214 
00215 static inline int renq_ready_task(RT_TASK *ready_task, int priority)
00216 {
00217         int retval;
00218         if ((retval = ready_task->priority != priority)) {
00219                 ready_task->priority = priority;
00220                 if (ready_task->state == RT_SCHED_READY) {
00221                         (ready_task->rprev)->rnext = ready_task->rnext;
00222                         (ready_task->rnext)->rprev = ready_task->rprev;
00223                         enq_ready_task(ready_task);
00224                 }
00225         }
00226         return retval;
00227 }
00228 
00229 static inline int renq_current(RT_TASK *rt_current, int priority)
00230 {
00231         int retval;
00232         if ((retval = rt_current->priority != priority)) {
00233                 rt_current->priority = priority;
00234                 (rt_current->rprev)->rnext = rt_current->rnext;
00235                 (rt_current->rnext)->rprev = rt_current->rprev;
00236                 enq_ready_task(rt_current);
00237         }
00238         return retval;
00239 }
00240 
00241 static inline void rem_ready_task(RT_TASK *task)
00242 {
00243         if (task->state == RT_SCHED_READY) {
00244                 if (!task->is_hard) {
00245                         (task->lnxtsk)->state = TASK_HARDREALTIME;
00246                 }
00247                 (task->rprev)->rnext = task->rnext;
00248                 (task->rnext)->rprev = task->rprev;
00249         }
00250 }
00251 
00252 static inline void rem_ready_current(RT_TASK *rt_current)
00253 {
00254         if (!rt_current->is_hard) {
00255                 (rt_current->lnxtsk)->state = TASK_HARDREALTIME;
00256         }
00257         (rt_current->rprev)->rnext = rt_current->rnext;
00258         (rt_current->rnext)->rprev = rt_current->rprev;
00259 }
00260 
00261 static inline void enq_timed_task(RT_TASK *timed_task)
00262 {
00263         RT_TASK *task;
00264 #ifdef CONFIG_SMP
00265         task = rt_smp_linux_task[timed_task->runnable_on_cpus].tnext;
00266 #else
00267         task = rt_smp_linux_task[0].tnext;
00268 #endif
00269         while (timed_task->resume_time > task->resume_time) {
00270                 task = task->tnext;
00271         }
00272         task->tprev = (timed_task->tprev = task->tprev)->tnext = timed_task;
00273         timed_task->tnext = task;
00274 }
00275 
00276 static inline void wake_up_timed_tasks(int cpuid)
00277 {
00278         RT_TASK *task;
00279 #ifdef CONFIG_SMP
00280         task = rt_smp_linux_task[cpuid].tnext;
00281 #else
00282         task = rt_smp_linux_task[0].tnext;
00283 #endif
00284         while (task->resume_time <= rt_time_h) {
00285                 if ((task->state &= ~(RT_SCHED_DELAYED | RT_SCHED_SEMAPHORE | RT_SCHED_RECEIVE | RT_SCHED_SEND | RT_SCHED_RPC | RT_SCHED_RETURN | RT_SCHED_MBXSUSP)) == RT_SCHED_READY) {
00286                         if (task->policy < 0) {
00287                                 enq_ready_edf_task(task);
00288                         } else {
00289                                 enq_ready_task(task);
00290                         }
00291                 }
00292                 task = task->tnext;
00293         }
00294 #ifdef CONFIG_SMP
00295         rt_smp_linux_task[cpuid].tnext = task;
00296         task->tprev = &rt_smp_linux_task[cpuid];
00297 #else
00298         rt_smp_linux_task[0].tnext = task;
00299         task->tprev = &rt_smp_linux_task[0];
00300 #endif
00301 }
00302 
00303 static inline void rem_timed_task(RT_TASK *task)
00304 {
00305         if ((task->state & RT_SCHED_DELAYED)) {
00306                 (task->tprev)->tnext = task->tnext;
00307                 (task->tnext)->tprev = task->tprev;
00308         }
00309 }
00310 
00311 #define get_time() rt_get_time()
00312 #if 0
00313 static inline RTIME get_time(void)
00314 {
00315 #ifdef CONFIG_SMP
00316         int cpuid;
00317         return rt_smp_oneshot_timer[cpuid = rtai_cpuid()] ? rdtsc() : rt_smp_times[cpuid].tick_time;
00318 #else
00319         return rt_smp_oneshot_timer[0] ? rdtsc() : rt_smp_times[0].tick_time;
00320 #endif
00321 }
00322 #endif
00323 
00324 static inline void enqueue_blocked(RT_TASK *task, QUEUE *queue, int qtype)
00325 {
00326         QUEUE *q;
00327         task->blocked_on = (q = queue);
00328         if (!qtype) {
00329                 while ((q = q->next) != queue && (q->task)->priority <= task->priority);
00330         }
00331         q->prev = (task->queue.prev = q->prev)->next  = &(task->queue);
00332         task->queue.next = q;
00333 }
00334 
00335 
00336 static inline void dequeue_blocked(RT_TASK *task)
00337 {
00338         task->prio_passed_to     = NOTHING;
00339         (task->queue.prev)->next = task->queue.next;
00340         (task->queue.next)->prev = task->queue.prev;
00341         task->blocked_on         = NOTHING;
00342 }
00343 
00344 static __volatile__ inline unsigned long pass_prio(RT_TASK *to, RT_TASK *from)
00345 {
00346         QUEUE *q;
00347 #ifdef CONFIG_SMP
00348         unsigned long schedmap;
00349         schedmap = 0;
00350 #endif
00351         from->prio_passed_to = to;
00352         while (to && to->priority > from->priority) {
00353                 to->priority = from->priority;
00354                 if (to->state == RT_SCHED_READY) {
00355                         (to->rprev)->rnext = to->rnext;
00356                         (to->rnext)->rprev = to->rprev;
00357                         enq_ready_task(to);
00358 #ifdef CONFIG_SMP
00359                         set_bit(to->runnable_on_cpus & 0x1F, &schedmap);
00360 #endif
00361                 } else if ((q = to->blocked_on) && !((to->state & RT_SCHED_SEMAPHORE) &&
00362  ((SEM *)q)->qtype)) {
00363                         (to->queue.prev)->next = to->queue.next;
00364                         (to->queue.next)->prev = to->queue.prev;
00365                         while ((q = q->next) != to->blocked_on && (q->task)->priority <= to->priority);
00366                         q->prev = (to->queue.prev = q->prev)->next  = &(to->queue);
00367                         to->queue.next = q;
00368                 }
00369                 to = to->prio_passed_to;
00370         }
00371 #ifdef CONFIG_SMP
00372         return schedmap;
00373 #else
00374         return 0;
00375 #endif
00376 }
00377 
00378 static inline RT_TASK *_rt_whoami(void)
00379 {
00380 #ifdef CONFIG_SMP
00381         RT_TASK *rt_current;
00382         unsigned long flags;
00383         flags = rt_global_save_flags_and_cli();
00384         rt_current = RT_CURRENT;
00385         rt_global_restore_flags(flags);
00386         return rt_current;
00387 #else
00388         return rt_smp_current[0];
00389 #endif
00390 }
00391 
00392 static inline void __call_exit_handlers(RT_TASK *task)
00393 {
00394         XHDL *pt, *tmp;
00395 
00396         pt = task->ExitHook; // Initialise ExitHook in rt_task_init()
00397         while ( pt ) {
00398                 (*pt->fun) (pt->arg1, pt->arg2);
00399                 tmp = pt;
00400                 pt  = pt->nxt;
00401                 rt_free(tmp);
00402         }
00403         task->ExitHook = 0;
00404 }
00405 
00406 static inline XHDL *__set_exit_handler(RT_TASK *task, void (*fun) (void *, int), void *arg1, int arg2)
00407 {
00408         XHDL *p;
00409 
00410         // exit handler functions are automatically executed at terminattion time by rt_task_delete()
00411         // in the reverse order they were created (like C++ destructors behave).
00412         if (task->magic != RT_TASK_MAGIC) return 0;
00413         if (!(p = (XHDL *) rt_malloc (sizeof(XHDL)))) return 0;
00414         p->fun  = fun;
00415         p->arg1 = arg1;
00416         p->arg2 = arg2;
00417         p->nxt  = task->ExitHook;
00418         return (task->ExitHook = p);
00419 }
00420 
00421 static inline int rtai_init_features (void)
00422 
00423 {
00424 #ifdef CONFIG_RTAI_LEDS_BUILTIN
00425     __rtai_leds_init();
00426 #endif /* CONFIG_RTAI_LEDS_BUILTIN */
00427 #ifdef CONFIG_RTAI_SEM_BUILTIN
00428     __rtai_sem_init();
00429 #endif /* CONFIG_RTAI_SEM_BUILTIN */
00430 #ifdef CONFIG_RTAI_MSG_BUILTIN
00431     __rtai_msg_init();
00432 #endif /* CONFIG_RTAI_MSG_BUILTIN */
00433 #ifdef CONFIG_RTAI_MBX_BUILTIN
00434     __rtai_mbx_init();
00435 #endif /* CONFIG_RTAI_MBX_BUILTIN */
00436 #ifdef CONFIG_RTAI_TBX_BUILTIN
00437     __rtai_tbx_init();
00438 #endif /* CONFIG_RTAI_TBX_BUILTIN */
00439 #ifdef CONFIG_RTAI_MQ_BUILTIN
00440     __rtai_mq_init();
00441 #endif /* CONFIG_RTAI_MQ_BUILTIN */
00442 #ifdef CONFIG_RTAI_BITS_BUILTIN
00443     __rtai_bits_init();
00444 #endif /* CONFIG_RTAI_BITS_BUILTIN */
00445 #ifdef CONFIG_RTAI_TASKLETS_BUILTIN
00446     __rtai_tasklets_init();
00447 #endif /* CONFIG_RTAI_TASKLETS_BUILTIN */
00448 #ifdef CONFIG_RTAI_FIFOS_BUILTIN
00449     __rtai_fifos_init();
00450 #endif /* CONFIG_RTAI_FIFOS_BUILTIN */
00451 #ifdef CONFIG_RTAI_NETRPC_BUILTIN
00452     __rtai_netrpc_init();
00453 #endif /* CONFIG_RTAI_NETRPC_BUILTIN */
00454 #ifdef CONFIG_RTAI_SHM_BUILTIN
00455     __rtai_shm_init();
00456 #endif /* CONFIG_RTAI_SHM_BUILTIN */
00457 #ifdef CONFIG_RTAI_USI_BUILTIN
00458     __rtai_usi_init();
00459 #endif /* CONFIG_RTAI_USI_BUILTIN */
00460 #ifdef CONFIG_RTAI_MATH_BUILTIN
00461     __rtai_math_init();
00462 #endif /* CONFIG_RTAI_MATH_BUILTIN */
00463 
00464         return 0;
00465 }
00466 
00467 static inline void rtai_cleanup_features (void) {
00468 
00469 #ifdef CONFIG_RTAI_MATH_BUILTIN
00470     __rtai_math_exit();
00471 #endif /* CONFIG_RTAI_MATH_BUILTIN */
00472 #ifdef CONFIG_RTAI_USI_BUILTIN
00473     __rtai_usi_exit();
00474 #endif /* CONFIG_RTAI_USI_BUILTIN */
00475 #ifdef CONFIG_RTAI_SHM_BUILTIN
00476     __rtai_shm_exit();
00477 #endif /* CONFIG_RTAI_SHM_BUILTIN */
00478 #ifdef CONFIG_RTAI_NETRPC_BUILTIN
00479     __rtai_netrpc_exit();
00480 #endif /* CONFIG_RTAI_NETRPC_BUILTIN */
00481 #ifdef CONFIG_RTAI_FIFOS_BUILTIN
00482     __rtai_fifos_exit();
00483 #endif /* CONFIG_RTAI_FIFOS_BUILTIN */
00484 #ifdef CONFIG_RTAI_TASKLETS_BUILTIN
00485     __rtai_tasklets_exit();
00486 #endif /* CONFIG_RTAI_TASKLETS_BUILTIN */
00487 #ifdef CONFIG_RTAI_BITS_BUILTIN
00488     __rtai_bits_exit();
00489 #endif /* CONFIG_RTAI_BITS_BUILTIN */
00490 #ifdef CONFIG_RTAI_MQ_BUILTIN
00491     __rtai_mq_exit();
00492 #endif /* CONFIG_RTAI_MQ_BUILTIN */
00493 #ifdef CONFIG_RTAI_TBX_BUILTIN
00494     __rtai_tbx_exit();
00495 #endif /* CONFIG_RTAI_TBX_BUILTIN */
00496 #ifdef CONFIG_RTAI_MBX_BUILTIN
00497     __rtai_mbx_exit();
00498 #endif /* CONFIG_RTAI_MBX_BUILTIN */
00499 #ifdef CONFIG_RTAI_MSG_BUILTIN
00500     __rtai_msg_exit();
00501 #endif /* CONFIG_RTAI_MSG_BUILTIN */
00502 #ifdef CONFIG_RTAI_SEM_BUILTIN
00503     __rtai_sem_exit();
00504 #endif /* CONFIG_RTAI_SEM_BUILTIN */
00505 #ifdef CONFIG_RTAI_LEDS_BUILTIN
00506     __rtai_leds_exit();
00507 #endif /* CONFIG_RTAI_LEDS_BUILTIN */
00508 }
00509 
00510 int rt_check_current_stack(void);
00511 
00512 int rt_kthread_init(RT_TASK *task,
00513                     void (*rt_thread)(int),
00514                     int data,
00515                     int stack_size,
00516                     int priority,
00517                     int uses_fpu,
00518                     void(*signal)(void));
00519 
00520 int rt_kthread_init_cpuid(RT_TASK *task,
00521                           void (*rt_thread)(int),
00522                           int data,
00523                           int stack_size,
00524                           int priority,
00525                           int uses_fpu,
00526                           void(*signal)(void),
00527                           unsigned int cpuid);
00528 
00529 #endif /* __KERNEL__ */
00530 
00531 #endif /* !_RTAI_SCHEDCORE_H */

Generated on Tue Jan 18 22:53:52 2005 for RTAI API by  doxygen 1.3.9.1