From 1e273f640e6e36dfae25b92e878c5b2bbf9dd0b9 Mon Sep 17 00:00:00 2001 From: Tomas Hruby Date: Wed, 15 Sep 2010 14:10:33 +0000 Subject: [PATCH] SMP - Scheduler can assign process to a cpu - machine information contains the number of cpus and the bsp id - a dummy SMP scheduler which keeps all system processes on BSP and all other process on APs. The scheduler remembers how many processes are assigned to each CPU and always picks the one with the least processes for a new process. --- include/minix/type.h | 4 ++- kernel/main.c | 5 ++++ servers/pm/glo.h | 3 +++ servers/sched/main.c | 5 ++++ servers/sched/sched.h | 2 ++ servers/sched/schedproc.h | 6 +++++ servers/sched/schedule.c | 57 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 81 insertions(+), 1 deletion(-) diff --git a/include/minix/type.h b/include/minix/type.h index 5dc039f74..7e8c9ff16 100644 --- a/include/minix/type.h +++ b/include/minix/type.h @@ -124,7 +124,9 @@ struct machine { int pc_at; int ps_mca; int processor; - int padding; /* used to be protected */ + unsigned processors_count; /* how many cpus are available */ + unsigned bsp_id; /* id of the bootstrap cpu */ + int padding; /* used to be protected */ int vdu_ega; int vdu_vga; int apic_enabled; /* does the kernel use APIC or not? */ diff --git a/kernel/main.c b/kernel/main.c index d4dde5180..e24e0748a 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -89,6 +89,11 @@ PUBLIC void bsp_finish_booting(void) #ifdef CONFIG_SMP cpu_set_flag(bsp_cpu_id, CPU_IS_READY); + machine.processors_count = ncpus; + machine.bsp_id = bsp_cpu_id; +#else + machine.processors_count = 1; + machine.bsp_id = 0; #endif switch_to_user(); diff --git a/servers/pm/glo.h b/servers/pm/glo.h index 4485e9710..46e4b449b 100644 --- a/servers/pm/glo.h +++ b/servers/pm/glo.h @@ -26,3 +26,6 @@ EXTERN sigset_t noign_sset; /* which signals cannot be ignored */ EXTERN u32_t system_hz; /* System clock frequency. */ EXTERN int abort_flag; EXTERN char monitor_code[256]; + +EXTERN struct machine machine; /* machine info */ +EXTERN unsigned cpu_proc[CONFIG_MAX_CPUS]; diff --git a/servers/sched/main.c b/servers/sched/main.c index 1b6a12113..d2f24b86c 100644 --- a/servers/sched/main.c +++ b/servers/sched/main.c @@ -13,6 +13,8 @@ FORWARD _PROTOTYPE( void reply, (endpoint_t whom, message *m_ptr) ); FORWARD _PROTOTYPE( void sef_local_startup, (void) ); +PUBLIC struct machine machine; /* machine info */ + /*===========================================================================* * main * *===========================================================================*/ @@ -24,10 +26,13 @@ PUBLIC int main(void) int who_e; /* caller's endpoint */ int result; /* result to system call */ int rv; + int s; /* SEF local startup. */ sef_local_startup(); + if (OK != (s=sys_getmachine(&machine))) + panic("couldn't get machine info: %d", s); /* Initialize scheduling timers, used for running balance_queues */ init_scheduling(); diff --git a/servers/sched/sched.h b/servers/sched/sched.h index 3388a2fa5..edd85aeed 100644 --- a/servers/sched/sched.h +++ b/servers/sched/sched.h @@ -18,3 +18,5 @@ #include #include "proto.h" + +extern struct machine machine; /* machine info */ diff --git a/servers/sched/schedproc.h b/servers/sched/schedproc.h index 508a7515d..77e31b638 100644 --- a/servers/sched/schedproc.h +++ b/servers/sched/schedproc.h @@ -3,6 +3,8 @@ */ #include +#include + /* EXTERN should be extern except in main.c, where we want to keep the struct */ #ifdef _MAIN #undef EXTERN @@ -23,6 +25,10 @@ EXTERN struct schedproc { unsigned max_priority; /* this process' highest allowed priority */ unsigned priority; /* the process' current priority */ unsigned time_slice; /* this process's time slice */ + unsigned cpu; /* what CPU is the process running on */ + bitchunk_t cpu_mask[BITMAP_CHUNKS(CONFIG_MAX_CPUS)]; /* what CPUs is hte + process allowed + to run on */ } schedproc[NR_PROCS]; /* Flag values */ diff --git a/servers/sched/schedule.c b/servers/sched/schedule.c index 9def6ae11..142cfad32 100644 --- a/servers/sched/schedule.c +++ b/servers/sched/schedule.c @@ -24,6 +24,41 @@ FORWARD _PROTOTYPE( void balance_queues, (struct timer *tp) ); #define DEFAULT_USER_TIME_SLICE 200 +/* processes created by RS are sysytem processes */ +#define is_system_proc(p) ((p)->parent == RS_PROC_NR) + +PRIVATE unsigned cpu_proc[CONFIG_MAX_CPUS]; + +PRIVATE void pick_cpu(struct schedproc * proc) +{ +#ifdef CONFIG_SMP + unsigned cpu, c; + unsigned cpu_load = (unsigned) -1; + + if (machine.processors_count == 1) { + proc->cpu = machine.bsp_id; + return; + } + + /* schedule sysytem processes only on the boot cpu */ + if (is_system_proc(proc)) { + proc->cpu = machine.bsp_id; + return; + } + + for (c = 0; c < machine.processors_count; c++) { + if (c != machine.bsp_id && cpu_load > cpu_proc[c]) { + cpu_load = cpu_proc[c]; + cpu = c; + } + } + proc->cpu = cpu; + cpu_proc[cpu]++; +#else + proc->cpu = 0; +#endif +} + /*===========================================================================* * do_noquantum * *===========================================================================*/ @@ -69,6 +104,7 @@ PUBLIC int do_stop_scheduling(message *m_ptr) } rmp = &schedproc[proc_nr_n]; + cpu_proc[rmp->cpu]--; rmp->flags = 0; /*&= ~IN_USE;*/ return OK; @@ -104,6 +140,25 @@ PUBLIC int do_start_scheduling(message *m_ptr) if (rmp->max_priority >= NR_SCHED_QUEUES) { return EINVAL; } + + /* Inherit current priority and time slice from parent. Since there + * is currently only one scheduler scheduling the whole system, this + * value is local and we assert that the parent endpoint is valid */ + if (rmp->endpoint == rmp->parent) { + /* We have a special case here for init, which is the first + process scheduled, and the parent of itself. */ + rmp->priority = USER_Q; + rmp->time_slice = DEFAULT_USER_TIME_SLICE; + + /* + * Since kernel never changes the cpu of a process, all are + * started on the BSP and the userspace scheduling hasn't + * changed that yet either, we can be sure that BSP is the + * processor where the processes run now. + */ + rmp->cpu = machine.bsp_id; + /* FIXME set the cpu mask */ + } switch (m_ptr->m_type) { @@ -210,6 +265,8 @@ PRIVATE int schedule_process(struct schedproc * rmp) { int rv; + pick_cpu(rmp); + if ((rv = sys_schedule(rmp->endpoint, rmp->priority, rmp->time_slice)) != OK) { printf("SCHED: An error occurred when trying to schedule %d: %d\n",