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