00001
00025 #ifndef _XENO_NUCLEUS_SCHED_H
00026 #define _XENO_NUCLEUS_SCHED_H
00027
00031 #include <nucleus/thread.h>
00032
00033 #if defined(__KERNEL__) || defined(__XENO_SIM__)
00034
00035 #include <nucleus/schedqueue.h>
00036 #include <nucleus/sched-tp.h>
00037 #include <nucleus/sched-sporadic.h>
00038
00039
00040 #define XNKCOUT 0x80000000
00041 #define XNINTCK 0x40000000
00042 #define XNSWLOCK 0x20000000
00043 #define XNRESCHED 0x10000000
00044
00045
00046 #define XNHTICK 0x00008000
00047 #define XNINIRQ 0x00004000
00048 #define XNHDEFER 0x00002000
00049
00050
00051 #define XNRPICK 0x80000000
00052
00053 struct xnsched_rt {
00054 xnsched_queue_t runnable;
00055 #ifdef CONFIG_XENO_OPT_PRIOCPL
00056 xnsched_queue_t relaxed;
00057 #endif
00058 };
00059
00064 typedef struct xnsched {
00065
00066 xnflags_t status;
00067 xnflags_t lflags;
00068 int cpu;
00069 struct xnthread *curr;
00070 #ifdef CONFIG_SMP
00071 xnarch_cpumask_t resched;
00072 #endif
00073
00074 struct xnsched_rt rt;
00075 #ifdef CONFIG_XENO_OPT_SCHED_TP
00076 struct xnsched_tp tp;
00077 #endif
00078 #ifdef CONFIG_XENO_OPT_SCHED_SPORADIC
00079 struct xnsched_sporadic pss;
00080 #endif
00081
00082 xntimerq_t timerqueue;
00083 volatile unsigned inesting;
00084 struct xntimer htimer;
00085 struct xnthread *zombie;
00086 struct xnthread rootcb;
00088 #ifdef CONFIG_XENO_HW_UNLOCKED_SWITCH
00089 struct xnthread *last;
00090 #endif
00091
00092 #ifdef CONFIG_XENO_HW_FPU
00093 struct xnthread *fpuholder;
00094 #endif
00095
00096 #ifdef CONFIG_XENO_OPT_WATCHDOG
00097 struct xntimer wdtimer;
00098 int wdcount;
00099 #endif
00100
00101 #ifdef CONFIG_XENO_OPT_STATS
00102 xnticks_t last_account_switch;
00103 xnstat_exectime_t *current_account;
00104 #endif
00105
00106 #ifdef CONFIG_XENO_OPT_PRIOCPL
00107 DECLARE_XNLOCK(rpilock);
00108 xnflags_t rpistatus;
00109 #endif
00110
00111 #ifdef CONFIG_XENO_OPT_PERVASIVE
00112 struct task_struct *gatekeeper;
00113 wait_queue_head_t gkwaitq;
00114 struct linux_semaphore gksync;
00115 struct xnthread *gktarget;
00116 #endif
00117
00118 } xnsched_t;
00119
00120 union xnsched_policy_param;
00121
00122 struct xnsched_class {
00123
00124 void (*sched_init)(struct xnsched *sched);
00125 void (*sched_enqueue)(struct xnthread *thread);
00126 void (*sched_dequeue)(struct xnthread *thread);
00127 void (*sched_requeue)(struct xnthread *thread);
00128 struct xnthread *(*sched_pick)(struct xnsched *sched);
00129 void (*sched_tick)(struct xnthread *curr);
00130 void (*sched_rotate)(struct xnsched *sched,
00131 const union xnsched_policy_param *p);
00132 void (*sched_migrate)(struct xnthread *thread,
00133 struct xnsched *sched);
00134 void (*sched_setparam)(struct xnthread *thread,
00135 const union xnsched_policy_param *p);
00136 void (*sched_getparam)(struct xnthread *thread,
00137 union xnsched_policy_param *p);
00138 void (*sched_trackprio)(struct xnthread *thread,
00139 const union xnsched_policy_param *p);
00140 int (*sched_declare)(struct xnthread *thread,
00141 const union xnsched_policy_param *p);
00142 void (*sched_forget)(struct xnthread *thread);
00143 #ifdef CONFIG_XENO_OPT_PRIOCPL
00144 struct xnthread *(*sched_push_rpi)(struct xnsched *sched,
00145 struct xnthread *thread);
00146 void (*sched_pop_rpi)(struct xnthread *thread);
00147 struct xnthread *(*sched_peek_rpi)(struct xnsched *sched);
00148 void (*sched_suspend_rpi)(struct xnthread *thread);
00149 void (*sched_resume_rpi)(struct xnthread *thread);
00150 #endif
00151 #ifdef CONFIG_PROC_FS
00152 void (*sched_init_proc)(struct proc_dir_entry *root);
00153 void (*sched_cleanup_proc)(struct proc_dir_entry *root);
00154 struct proc_dir_entry *proc;
00155 #endif
00156 int nthreads;
00157 struct xnsched_class *next;
00158 int weight;
00159 const char *name;
00160 };
00161
00162 #define XNSCHED_CLASS_MAX_THREADS 32768
00163 #define XNSCHED_CLASS_WEIGHT(n) (n * XNSCHED_CLASS_MAX_THREADS)
00164
00165
00166 #define XNSCHED_RUNPRIO 0x80000000
00167
00168 #ifdef CONFIG_SMP
00169 #define xnsched_cpu(__sched__) ((__sched__)->cpu)
00170 #else
00171 #define xnsched_cpu(__sched__) ({ (void)__sched__; 0; })
00172 #endif
00173
00174
00175 static inline int xnsched_resched_p(struct xnsched *sched)
00176 {
00177 return testbits(sched->status, XNRESCHED);
00178 }
00179
00180
00181 #define xnsched_set_self_resched(__sched__) do { \
00182 XENO_BUGON(NUCLEUS, __sched__ != xnpod_current_sched()); \
00183 __setbits((__sched__)->status, XNRESCHED); \
00184 } while (0)
00185
00186
00187 #ifdef CONFIG_SMP
00188 #define xnsched_set_resched(__sched__) do { \
00189 xnsched_t *current_sched = xnpod_current_sched(); \
00190 if (current_sched == (__sched__)) \
00191 __setbits(current_sched->status, XNRESCHED); \
00192 else if (!xnsched_resched_p(__sched__)) { \
00193 xnarch_cpu_set(xnsched_cpu(__sched__), current_sched->resched); \
00194 __setbits((__sched__)->status, XNRESCHED); \
00195 __setbits(current_sched->status, XNRESCHED); \
00196 } \
00197 } while (0)
00198 #else
00199 #define xnsched_set_resched xnsched_set_self_resched
00200 #endif
00201
00202 void xnsched_zombie_hooks(struct xnthread *thread);
00203
00204 void __xnsched_finalize_zombie(struct xnsched *sched);
00205
00206 static inline void xnsched_finalize_zombie(struct xnsched *sched)
00207 {
00208 if (sched->zombie)
00209 __xnsched_finalize_zombie(sched);
00210 }
00211
00212 #ifdef CONFIG_XENO_HW_UNLOCKED_SWITCH
00213
00214 struct xnsched *xnsched_finish_unlocked_switch(struct xnsched *sched);
00215
00216 #define xnsched_resched_after_unlocked_switch() xnpod_schedule()
00217
00218 static inline
00219 int xnsched_maybe_resched_after_unlocked_switch(struct xnsched *sched)
00220 {
00221 return testbits(sched->status, XNRESCHED);
00222 }
00223
00224 #else
00225
00226 #ifdef CONFIG_SMP
00227 #define xnsched_finish_unlocked_switch(__sched__) \
00228 ({ XENO_BUGON(NUCLEUS, !irqs_disabled_hw()); \
00229 xnpod_current_sched(); })
00230 #else
00231 #define xnsched_finish_unlocked_switch(__sched__) \
00232 ({ XENO_BUGON(NUCLEUS, !irqs_disabled_hw()); \
00233 (__sched__); })
00234 #endif
00235
00236 #define xnsched_resched_after_unlocked_switch() do { } while(0)
00237
00238 #define xnsched_maybe_resched_after_unlocked_switch(sched) \
00239 ({ (void)(sched); 0; })
00240
00241 #endif
00242
00243 #ifdef CONFIG_XENO_OPT_WATCHDOG
00244 static inline void xnsched_reset_watchdog(struct xnsched *sched)
00245 {
00246 sched->wdcount = 0;
00247 }
00248 #else
00249 static inline void xnsched_reset_watchdog(struct xnsched *sched)
00250 {
00251 }
00252 #endif
00253
00254 #include <nucleus/sched-idle.h>
00255 #include <nucleus/sched-rt.h>
00256
00257 void xnsched_init_proc(void);
00258
00259 void xnsched_cleanup_proc(void);
00260
00261 void xnsched_register_classes(void);
00262
00263 void xnsched_init(struct xnsched *sched, int cpu);
00264
00265 void xnsched_destroy(struct xnsched *sched);
00266
00267 struct xnthread *xnsched_pick_next(struct xnsched *sched);
00268
00269 void xnsched_putback(struct xnthread *thread);
00270
00271 int xnsched_set_policy(struct xnthread *thread,
00272 struct xnsched_class *sched_class,
00273 const union xnsched_policy_param *p);
00274
00275 void xnsched_track_policy(struct xnthread *thread,
00276 struct xnthread *target);
00277
00278 void xnsched_migrate(struct xnthread *thread,
00279 struct xnsched *sched);
00280
00281 void xnsched_migrate_passive(struct xnthread *thread,
00282 struct xnsched *sched);
00283
00315 static inline void xnsched_rotate(struct xnsched *sched,
00316 struct xnsched_class *sched_class,
00317 const union xnsched_policy_param *sched_param)
00318 {
00319 sched_class->sched_rotate(sched, sched_param);
00320 }
00321
00322 static inline int xnsched_init_tcb(struct xnthread *thread)
00323 {
00324 int ret = 0;
00325
00326 xnsched_idle_init_tcb(thread);
00327 xnsched_rt_init_tcb(thread);
00328 #ifdef CONFIG_XENO_OPT_SCHED_TP
00329 ret = xnsched_tp_init_tcb(thread);
00330 if (ret)
00331 return ret;
00332 #endif
00333 #ifdef CONFIG_XENO_OPT_SCHED_SPORADIC
00334 ret = xnsched_sporadic_init_tcb(thread);
00335 if (ret)
00336 return ret;
00337 #endif
00338 return ret;
00339 }
00340
00341 static inline int xnsched_root_priority(struct xnsched *sched)
00342 {
00343 return sched->rootcb.cprio;
00344 }
00345
00346 static inline struct xnsched_class *xnsched_root_class(struct xnsched *sched)
00347 {
00348 return sched->rootcb.sched_class;
00349 }
00350
00351 static inline void xnsched_tick(struct xnthread *curr, struct xntbase *tbase)
00352 {
00353 struct xnsched_class *sched_class = curr->sched_class;
00354
00355
00356
00357
00358
00359 if (xnthread_time_base(curr) == tbase &&
00360 sched_class != &xnsched_class_idle &&
00361 sched_class == curr->base_class &&
00362 xnthread_test_state(curr, XNTHREAD_BLOCK_BITS|XNLOCK|XNRRB) == XNRRB)
00363 sched_class->sched_tick(curr);
00364 }
00365
00366 #ifdef CONFIG_XENO_OPT_SCHED_CLASSES
00367
00368 static inline void xnsched_enqueue(struct xnthread *thread)
00369 {
00370 struct xnsched_class *sched_class = thread->sched_class;
00371
00372 if (sched_class != &xnsched_class_idle)
00373 sched_class->sched_enqueue(thread);
00374 }
00375
00376 static inline void xnsched_dequeue(struct xnthread *thread)
00377 {
00378 struct xnsched_class *sched_class = thread->sched_class;
00379
00380 if (sched_class != &xnsched_class_idle)
00381 sched_class->sched_dequeue(thread);
00382 }
00383
00384 static inline void xnsched_requeue(struct xnthread *thread)
00385 {
00386 struct xnsched_class *sched_class = thread->sched_class;
00387
00388 if (sched_class != &xnsched_class_idle)
00389 sched_class->sched_requeue(thread);
00390 }
00391
00392 static inline int xnsched_weighted_bprio(struct xnthread *thread)
00393 {
00394 return thread->bprio + thread->sched_class->weight;
00395 }
00396
00397 static inline int xnsched_weighted_cprio(struct xnthread *thread)
00398 {
00399 return thread->cprio + thread->sched_class->weight;
00400 }
00401
00402 static inline void xnsched_setparam(struct xnthread *thread,
00403 const union xnsched_policy_param *p)
00404 {
00405 thread->sched_class->sched_setparam(thread, p);
00406 }
00407
00408 static inline void xnsched_getparam(struct xnthread *thread,
00409 union xnsched_policy_param *p)
00410 {
00411 thread->sched_class->sched_getparam(thread, p);
00412 }
00413
00414 static inline void xnsched_trackprio(struct xnthread *thread,
00415 const union xnsched_policy_param *p)
00416 {
00417 thread->sched_class->sched_trackprio(thread, p);
00418 }
00419
00420 static inline void xnsched_forget(struct xnthread *thread)
00421 {
00422 struct xnsched_class *sched_class = thread->base_class;
00423
00424 --sched_class->nthreads;
00425
00426 if (sched_class->sched_forget)
00427 sched_class->sched_forget(thread);
00428 }
00429
00430 #ifdef CONFIG_XENO_OPT_PRIOCPL
00431
00432 static inline struct xnthread *xnsched_push_rpi(struct xnsched *sched,
00433 struct xnthread *thread)
00434 {
00435 return thread->sched_class->sched_push_rpi(sched, thread);
00436 }
00437
00438 static inline void xnsched_pop_rpi(struct xnthread *thread)
00439 {
00440 thread->sched_class->sched_pop_rpi(thread);
00441 }
00442
00443 static inline void xnsched_suspend_rpi(struct xnthread *thread)
00444 {
00445 struct xnsched_class *sched_class = thread->sched_class;
00446
00447 if (sched_class->sched_suspend_rpi)
00448 sched_class->sched_suspend_rpi(thread);
00449 }
00450
00451 static inline void xnsched_resume_rpi(struct xnthread *thread)
00452 {
00453 struct xnsched_class *sched_class = thread->sched_class;
00454
00455 if (sched_class->sched_resume_rpi)
00456 sched_class->sched_resume_rpi(thread);
00457 }
00458
00459 #endif
00460
00461 #else
00462
00463
00464
00465
00466
00467
00468 static inline void xnsched_enqueue(struct xnthread *thread)
00469 {
00470 struct xnsched_class *sched_class = thread->sched_class;
00471
00472 if (sched_class != &xnsched_class_idle)
00473 __xnsched_rt_enqueue(thread);
00474 }
00475
00476 static inline void xnsched_dequeue(struct xnthread *thread)
00477 {
00478 struct xnsched_class *sched_class = thread->sched_class;
00479
00480 if (sched_class != &xnsched_class_idle)
00481 __xnsched_rt_dequeue(thread);
00482 }
00483
00484 static inline void xnsched_requeue(struct xnthread *thread)
00485 {
00486 struct xnsched_class *sched_class = thread->sched_class;
00487
00488 if (sched_class != &xnsched_class_idle)
00489 __xnsched_rt_requeue(thread);
00490 }
00491
00492 static inline int xnsched_weighted_bprio(struct xnthread *thread)
00493 {
00494 return thread->bprio;
00495 }
00496
00497 static inline int xnsched_weighted_cprio(struct xnthread *thread)
00498 {
00499 return thread->cprio;
00500 }
00501
00502 static inline void xnsched_setparam(struct xnthread *thread,
00503 const union xnsched_policy_param *p)
00504 {
00505 struct xnsched_class *sched_class = thread->sched_class;
00506
00507 if (sched_class != &xnsched_class_idle)
00508 __xnsched_rt_setparam(thread, p);
00509 else
00510 __xnsched_idle_setparam(thread, p);
00511 }
00512
00513 static inline void xnsched_getparam(struct xnthread *thread,
00514 union xnsched_policy_param *p)
00515 {
00516 struct xnsched_class *sched_class = thread->sched_class;
00517
00518 if (sched_class != &xnsched_class_idle)
00519 __xnsched_rt_getparam(thread, p);
00520 else
00521 __xnsched_idle_getparam(thread, p);
00522 }
00523
00524 static inline void xnsched_trackprio(struct xnthread *thread,
00525 const union xnsched_policy_param *p)
00526 {
00527 struct xnsched_class *sched_class = thread->sched_class;
00528
00529 if (sched_class != &xnsched_class_idle)
00530 __xnsched_rt_trackprio(thread, p);
00531 else
00532 __xnsched_idle_trackprio(thread, p);
00533 }
00534
00535 static inline void xnsched_forget(struct xnthread *thread)
00536 {
00537 --thread->base_class->nthreads;
00538 __xnsched_rt_forget(thread);
00539 }
00540
00541 #ifdef CONFIG_XENO_OPT_PRIOCPL
00542
00543 static inline struct xnthread *xnsched_push_rpi(struct xnsched *sched,
00544 struct xnthread *thread)
00545 {
00546 return __xnsched_rt_push_rpi(sched, thread);
00547 }
00548
00549 static inline void xnsched_pop_rpi(struct xnthread *thread)
00550 {
00551 __xnsched_rt_pop_rpi(thread);
00552 }
00553
00554 static inline void xnsched_suspend_rpi(struct xnthread *thread)
00555 {
00556 __xnsched_rt_suspend_rpi(thread);
00557 }
00558
00559 static inline void xnsched_resume_rpi(struct xnthread *thread)
00560 {
00561 __xnsched_rt_resume_rpi(thread);
00562 }
00563
00564 #endif
00565
00566 #endif
00567
00568 void xnsched_renice_root(struct xnsched *sched,
00569 struct xnthread *target);
00570
00571 struct xnthread *xnsched_peek_rpi(struct xnsched *sched);
00572
00573 #else
00574
00575 #include <nucleus/sched-idle.h>
00576 #include <nucleus/sched-rt.h>
00577
00578 #endif
00579
00582 #endif