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.
This commit is contained in:
Tomas Hruby 2010-09-15 14:10:33 +00:00
parent 9e12630d75
commit 1e273f640e
7 changed files with 81 additions and 1 deletions

View file

@ -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? */

View file

@ -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();

View file

@ -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];

View file

@ -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();

View file

@ -18,3 +18,5 @@
#include <errno.h>
#include "proto.h"
extern struct machine machine; /* machine info */

View file

@ -3,6 +3,8 @@
*/
#include <limits.h>
#include <minix/bitmap.h>
/* 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 */

View file

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