diff --git a/include/kernel/sched.h b/include/kernel/sched.h index 3533b9a..5f81516 100644 --- a/include/kernel/sched.h +++ b/include/kernel/sched.h @@ -11,13 +11,21 @@ struct thread_info; #define SCHED_CLASS_RR 0 #define SCHED_CLASS_BITMAP 1 +typedef int sched_class_t; #define SCHED_OPT_NONE 0 #define SCHED_OPT_RESTORE_ONLY 1 #define SCHED_OPT_RESET 2 #define SCHED_OPT_TICK 3 +/* scheduler implementation hooks */ +#define HOOK_SCHED_CLASS(name, sched_struct) \ + static struct sched *sched_class_##name \ + __attribute__((section(".sched.class"), aligned(sizeof(long)), \ + used)) = sched_struct; + struct sched { + sched_class_t class_type; int (*init)(void); int (*enqueue)(struct thread_info *thread); int (*dequeue)(struct thread_info *thread); @@ -25,7 +33,7 @@ struct sched { }; int sched_init(); -int sched_select(int sched_type); +int sched_select(sched_class_t sched_type); int sched_enqueue(struct thread_info *thread); int sched_dequeue(struct thread_info *thread); int sched_elect(int flags); diff --git a/kernel/sched.c b/kernel/sched.c index 3b9c0a2..e54b5fe 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1,35 +1,48 @@ #include #include -extern const struct sched sched_rr; -extern const struct sched sched_bitmap; +extern unsigned long __sched_classes_start__; +extern unsigned long __sched_classes_end__; -static const struct sched *sched; +/* static vars to repesent sched classes list */ +static struct sched **sched_classes = + (struct sched **) &__sched_classes_start__; +static struct sched **sched_classes_end = + (struct sched **) &__sched_classes_end__; + +static struct sched *sched; int sched_init() { - int ret; + int ret = 0; - ret = sched_rr.init(); - ret = sched_bitmap.init(); + /* Initialize each scheduler class by traversing hooks */ + for (struct sched **c = sched_classes; + c < sched_classes_end; c++) { + struct sched *class = *c; + ret |= class->init(); + } return ret; } -int sched_select(int sched_type) +int sched_select(sched_class_t sched_type) { - switch (sched_type) { - case SCHED_CLASS_RR: - sched = &sched_rr; - break; - case SCHED_CLASS_BITMAP: - sched = &sched_bitmap; - break; - default: - return -1; + int ret = -1; + struct sched *class = NULL; + + /* Examine specified sched class in hooks or not */ + for (struct sched **c = sched_classes; + c < sched_classes_end; c++) + if (sched_type == (*c)->class_type) + class = *c; + + if (class) { + sched = class; + ret = 0; } - return 0; + return ret; } int sched_enqueue(struct thread_info *thread) diff --git a/kernel/sched/bitmap.c b/kernel/sched/bitmap.c index 314e079..27b3da2 100644 --- a/kernel/sched/bitmap.c +++ b/kernel/sched/bitmap.c @@ -112,10 +112,13 @@ static int sched_bitmap_elect(int flags) } // clang-format off -const struct sched sched_bitmap = { +static struct sched sched_bitmap = { + .class_type = SCHED_CLASS_BITMAP, .init = sched_bitmap_init, .enqueue = sched_bitmap_enqueue, .dequeue = sched_bitmap_dequeue, .elect = sched_bitmap_elect, }; // clang-format on + +HOOK_SCHED_CLASS(bitmap, &sched_bitmap) diff --git a/kernel/sched/rr.c b/kernel/sched/rr.c index fa0ddbf..aab294b 100644 --- a/kernel/sched/rr.c +++ b/kernel/sched/rr.c @@ -87,10 +87,13 @@ int sched_rr_elect(int switch_type) } // clang-format off -const struct sched sched_rr = { +static struct sched sched_rr = { + .class_type = SCHED_CLASS_RR, .init = sched_rr_init, .enqueue = sched_rr_enqueue, .dequeue = sched_rr_dequeue, .elect = sched_rr_elect, }; // clang-format on + +HOOK_SCHED_CLASS(RR, &sched_rr) diff --git a/piko.lds.S b/piko.lds.S index 7ec695f..87ff843 100644 --- a/piko.lds.S +++ b/piko.lds.S @@ -24,6 +24,9 @@ SECTIONS PROVIDE(__shell_cmd_start__ = .); KEEP(*(.shell_cmd*)) PROVIDE(__shell_cmd_end__ = .); + PROVIDE(__sched_classes_start__ = .); + KEEP(*(.sched.class*)) + PROVIDE(__sched_classes_end__ = .); PROVIDE(__rodata_start__ = .); *(.rodata*) PROVIDE(__rodata_end__ = .);