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",