]> Zhao Yanbai Git Server - minix.git/commitdiff
SMP - Scheduler can assign process to a cpu
authorTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:10:33 +0000 (14:10 +0000)
committerTomas Hruby <tom@minix3.org>
Wed, 15 Sep 2010 14:10:33 +0000 (14:10 +0000)
- 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
kernel/main.c
servers/pm/glo.h
servers/sched/main.c
servers/sched/sched.h
servers/sched/schedproc.h
servers/sched/schedule.c

index 5dc039f747b5b4610986e58e5fb30341a758f42c..7e8c9ff16b40d234eadce852a66839ef2f98113d 100644 (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? */
index d4dde5180a52c59a95b8bc350746caeedb56bfc8..e24e0748afb1720267897b8731585f22071a9918 100644 (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();
index 4485e9710e7b72474ead5a9f1503849609d8615e..46e4b449b67c49ee978de1ed16568278c627be20 100644 (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];
index 1b6a12113eb1566a10743994f93df2783bcaa72e..d2f24b86c5601e9b6a7f17660000fb583c7ebac4 100644 (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();
 
index 3388a2fa5a73236de96cb758cfa0148b189ed0be..edd85aeed6ba2fc8e035c8f6b628f633ec1b1e28 100644 (file)
@@ -18,3 +18,5 @@
 #include <errno.h>
 
 #include "proto.h"
+
+extern struct machine machine;         /* machine info */
index 508a7515d09738182e5ff8b7932b9cff8270e3ed..77e31b638e5f1943942958703717282cff075f34 100644 (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 */
index 9def6ae117e9ab07cf493b6740b0821df39061be..142cfad32da8230ce69e7a9f41b2d279bcbe42f9 100644 (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",