diff --git a/include/minix/com.h b/include/minix/com.h index 04fc74d95..270e6406f 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -676,6 +676,7 @@ #define SCHEDCTL_ENDPOINT m9_l2 /* endpt of process to be scheduled */ #define SCHEDCTL_QUANTUM m9_l3 /* current scheduling quantum */ #define SCHEDCTL_PRIORITY m9_s4 /* current scheduling priority */ +#define SCHEDCTL_CPU m9_l5 /* where to place this process */ /*===========================================================================* * Messages for the Reincarnation Server * @@ -1141,6 +1142,7 @@ # define SCHEDULING_ENDPOINT m9_l1 # define SCHEDULING_QUANTUM m9_l2 # define SCHEDULING_PRIORITY m9_s1 +# define SCHEDULING_CPU m9_l4 /* SCHEDULING_START uses _ENDPOINT, _PRIORITY and _QUANTUM from * SCHEDULING_NO_QUANTUM */ diff --git a/include/minix/rs.h b/include/minix/rs.h index 5d64ff756..f0493dcad 100644 --- a/include/minix/rs.h +++ b/include/minix/rs.h @@ -33,6 +33,10 @@ Interface to the reincarnation server #define RS_NR_PCI_CLASS 4 #define RS_MAX_LABEL_LEN 16 +/* CPU special values */ +#define RS_CPU_DEFAULT -1 /* use the default cpu or do not change the current one */ +#define RS_CPU_BSP -2 /* use the bootstrap cpu */ + /* Labels are copied over separately. */ struct rss_label { diff --git a/include/minix/sched.h b/include/minix/sched.h index 6134f8a0c..8a32e30a0 100644 --- a/include/minix/sched.h +++ b/include/minix/sched.h @@ -5,7 +5,7 @@ _PROTOTYPE(int sched_stop, (endpoint_t scheduler_e, endpoint_t schedulee_e)); _PROTOTYPE(int sched_start, (endpoint_t scheduler_e, endpoint_t schedulee_e, - endpoint_t parent_e, unsigned maxprio, unsigned quantum, + endpoint_t parent_e, int maxprio, int quantum, int cpu, endpoint_t *newscheduler_e)); _PROTOTYPE(int sched_inherit, (endpoint_t scheduler_e, endpoint_t schedulee_e, endpoint_t parent_e, unsigned maxprio, diff --git a/include/minix/syslib.h b/include/minix/syslib.h index 36f4a33df..b1a3db189 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -44,9 +44,10 @@ _PROTOTYPE( int sys_clear, (endpoint_t proc_ep)); _PROTOTYPE( int sys_exit, (void)); _PROTOTYPE( int sys_trace, (int req, endpoint_t proc_ep, long addr, long *data_p)); -_PROTOTYPE( int sys_schedule, (endpoint_t proc_ep, unsigned priority, unsigned quantum)); +_PROTOTYPE( int sys_schedule, (endpoint_t proc_ep, int priority, + int quantum, int cpu)); _PROTOTYPE( int sys_schedctl, (unsigned flags, endpoint_t proc_ep, - unsigned priority, unsigned quantum)); + int priority, int quantum, int cpu)); /* Shorthands for sys_runctl() system call. */ #define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, 0) diff --git a/kernel/proto.h b/kernel/proto.h index 0ac33a28c..aa2d4413d 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -84,7 +84,7 @@ _PROTOTYPE( void clear_ipc_refs, (struct proc *rc, int caller_ret) ); _PROTOTYPE( phys_bytes umap_bios, (vir_bytes vir_addr, vir_bytes bytes)); _PROTOTYPE( void kernel_call_resume, (struct proc *p)); _PROTOTYPE( int sched_proc, (struct proc *rp, - unsigned priority, unsigned quantum)); + int priority, int quantum, int cpu)); /* system/do_newmap.c */ _PROTOTYPE( int newmap, (struct proc * caller, struct proc *rp, diff --git a/kernel/system.c b/kernel/system.c index 3f18a3187..6e02000da 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -638,29 +638,51 @@ PUBLIC void kernel_call_resume(struct proc *caller) /*===========================================================================* * sched_proc * *===========================================================================*/ -PUBLIC int sched_proc(struct proc *rp, unsigned priority, unsigned quantum) +PUBLIC int sched_proc(struct proc *p, + int priority, + int quantum, + int cpu) { - /* Make sure the priority number given is within the allowed range.*/ - if (priority < TASK_Q || priority > NR_SCHED_QUEUES) - return EINVAL; + /* Make sure the values given are within the allowed range.*/ + if ((priority < TASK_Q && priority != -1) || priority > NR_SCHED_QUEUES) + return(EINVAL); - /* Make sure the quantum given is within the allowed range.*/ - if(quantum <= 0) - return EINVAL; + if (quantum < 1 && quantum != -1) + return(EINVAL); + + if ((cpu < 0 && cpu != -1) || (cpu > 0 && (unsigned) cpu >= ncpus)) + return(EINVAL); /* In some cases, we might be rescheduling a runnable process. In such * a case (i.e. if we are updating the priority) we set the NO_QUANTUM * flag before the generic unset to dequeue/enqueue the process */ - if (proc_is_runnable(rp)) - RTS_SET(rp, RTS_NO_QUANTUM); + + /* FIXME this preempts the process, do we really want to do that ?*/ + + /* FIXME this is a problem for SMP if the processes currently runs on a + * different CPU */ + if (proc_is_runnable(p) && p->p_cpu != cpuid && + (cpu != -1 || cpu != p->p_cpu)) { + printf("WARNING : changing cpu of a runnable process %d " + "on a different cpu!\n", p->p_endpoint); + return(EINVAL); + } + + if (proc_is_runnable(p)) + RTS_SET(p, RTS_NO_QUANTUM); + + if (priority != -1) + p->p_priority = priority; + if (quantum != -1) { + p->p_quantum_size_ms = quantum; + p->p_cpu_time_left = ms_2_cpu_time(quantum); + } + if (cpu != -1) + p->p_cpu = cpu; /* Clear the scheduling bit and enqueue the process */ - rp->p_priority = priority; - rp->p_quantum_size_ms = quantum; - rp->p_cpu_time_left = ms_2_cpu_time(quantum); - - RTS_UNSET(rp, RTS_NO_QUANTUM); + RTS_UNSET(p, RTS_NO_QUANTUM); return OK; } diff --git a/kernel/system/do_schedctl.c b/kernel/system/do_schedctl.c index 8a40e1e09..b2e4563a3 100644 --- a/kernel/system/do_schedctl.c +++ b/kernel/system/do_schedctl.c @@ -8,7 +8,7 @@ PUBLIC int do_schedctl(struct proc * caller, message * m_ptr) { struct proc *p; unsigned flags; - unsigned priority, quantum; + int priority, quantum, cpu; int proc_nr; int r; @@ -29,11 +29,12 @@ PUBLIC int do_schedctl(struct proc * caller, message * m_ptr) /* the kernel becomes the scheduler and starts * scheduling the process. */ - priority = (unsigned) m_ptr->SCHEDCTL_PRIORITY; - quantum = (unsigned) m_ptr->SCHEDCTL_QUANTUM; + priority = (int) m_ptr->SCHEDCTL_PRIORITY; + quantum = (int) m_ptr->SCHEDCTL_QUANTUM; + cpu = (int) m_ptr->SCHEDCTL_CPU; /* Try to schedule the process. */ - if((r = sched_proc(p, priority, quantum) != OK)) + if((r = sched_proc(p, priority, quantum, cpu) != OK)) return r; p->p_scheduler = NULL; } else { diff --git a/kernel/system/do_schedule.c b/kernel/system/do_schedule.c index d4935c755..436f8147d 100644 --- a/kernel/system/do_schedule.c +++ b/kernel/system/do_schedule.c @@ -9,7 +9,7 @@ PUBLIC int do_schedule(struct proc * caller, message * m_ptr) { struct proc *p; int proc_nr; - unsigned priority, quantum; + int priority, quantum, cpu; if (!isokendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr)) return EINVAL; @@ -21,7 +21,9 @@ PUBLIC int do_schedule(struct proc * caller, message * m_ptr) return(EPERM); /* Try to schedule the process. */ - priority = (unsigned) m_ptr->SCHEDULING_PRIORITY; - quantum = (unsigned) m_ptr->SCHEDULING_QUANTUM; - return sched_proc(p, priority, quantum); + priority = (int) m_ptr->SCHEDULING_PRIORITY; + quantum = (int) m_ptr->SCHEDULING_QUANTUM; + cpu = (int) m_ptr->SCHEDULING_CPU; + + return sched_proc(p, priority, quantum, cpu); } diff --git a/lib/libsys/sched_start.c b/lib/libsys/sched_start.c index 4a41b013a..0f8f2402d 100644 --- a/lib/libsys/sched_start.c +++ b/lib/libsys/sched_start.c @@ -46,9 +46,13 @@ PUBLIC int sched_inherit(endpoint_t scheduler_e, /*===========================================================================* * sched_start * *===========================================================================*/ -PUBLIC int sched_start(endpoint_t scheduler_e, endpoint_t schedulee_e, - endpoint_t parent_e, unsigned maxprio, unsigned quantum, - endpoint_t *newscheduler_e) +PUBLIC int sched_start(endpoint_t scheduler_e, + endpoint_t schedulee_e, + endpoint_t parent_e, + int maxprio, + int quantum, + int cpu, + endpoint_t *newscheduler_e) { int rv; message m; @@ -68,7 +72,7 @@ PUBLIC int sched_start(endpoint_t scheduler_e, endpoint_t schedulee_e, /* The KERNEL must schedule this process. */ if(scheduler_e == KERNEL) { if ((rv = sys_schedctl(SCHEDCTL_FLAG_KERNEL, - schedulee_e, maxprio, quantum)) != OK) { + schedulee_e, maxprio, quantum, cpu)) != OK) { return rv; } *newscheduler_e = scheduler_e; diff --git a/lib/libsys/sys_schedctl.c b/lib/libsys/sys_schedctl.c index 46ef5f1bb..b7b975e4c 100644 --- a/lib/libsys/sys_schedctl.c +++ b/lib/libsys/sys_schedctl.c @@ -1,7 +1,10 @@ #include "syslib.h" -PUBLIC int sys_schedctl(unsigned flags, endpoint_t proc_ep, unsigned priority, - unsigned quantum) +PUBLIC int sys_schedctl(unsigned flags, + endpoint_t proc_ep, + int priority, + int quantum, + int cpu) { message m; @@ -9,5 +12,6 @@ PUBLIC int sys_schedctl(unsigned flags, endpoint_t proc_ep, unsigned priority, m.SCHEDCTL_ENDPOINT = proc_ep; m.SCHEDCTL_PRIORITY = priority; m.SCHEDCTL_QUANTUM = quantum; + m.SCHEDCTL_CPU = cpu; return(_kernel_call(SYS_SCHEDCTL, &m)); } diff --git a/lib/libsys/sys_schedule.c b/lib/libsys/sys_schedule.c index 94354ed96..f7664c47c 100644 --- a/lib/libsys/sys_schedule.c +++ b/lib/libsys/sys_schedule.c @@ -1,11 +1,15 @@ #include "syslib.h" -PUBLIC int sys_schedule(endpoint_t proc_ep, unsigned priority, unsigned quantum) +PUBLIC int sys_schedule(endpoint_t proc_ep, + int priority, + int quantum, + int cpu) { message m; m.SCHEDULING_ENDPOINT = proc_ep; m.SCHEDULING_PRIORITY = priority; m.SCHEDULING_QUANTUM = quantum; + m.SCHEDULING_CPU = cpu; return(_kernel_call(SYS_SCHEDULE, &m)); } diff --git a/servers/pm/schedule.c b/servers/pm/schedule.c index aa0d0bdf8..e94c20eb2 100644 --- a/servers/pm/schedule.c +++ b/servers/pm/schedule.c @@ -39,6 +39,7 @@ PUBLIC void sched_init(void) parent_e, /* parent_e */ USER_Q, /* maxprio */ USER_QUANTUM, /* quantum */ + -1, /* don't change cpu */ &trmp->mp_scheduler); /* *newsched_e */ if (s != OK) { printf("PM: SCHED denied taking over scheduling of %s: %d\n", diff --git a/servers/rs/glo.h b/servers/rs/glo.h index d4db45227..4c883ad21 100644 --- a/servers/rs/glo.h +++ b/servers/rs/glo.h @@ -50,5 +50,7 @@ EXTERN int shutting_down; EXTERN unsigned system_hz; +EXTERN struct machine machine; /* machine info */ + #endif /* RS_GLO_H */ diff --git a/servers/rs/main.c b/servers/rs/main.c index a5293e3fa..21bdedf83 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -33,6 +33,7 @@ FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) ); FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) ); FORWARD _PROTOTYPE( int sef_cb_signal_manager, (endpoint_t target, int signo) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -46,9 +47,13 @@ PUBLIC int main(void) int ipc_status; /* status code */ int call_nr, who_e,who_p; /* call number and caller */ int result; /* result to return */ + int s; /* SEF local startup. */ sef_local_startup(); + + if (OK != (s=sys_getmachine(&machine))) + panic("couldn't get machine info: %d", s); /* Main loop - get work and do it, forever. */ while (TRUE) { diff --git a/servers/rs/manager.c b/servers/rs/manager.c index 3e778c0ec..4897e8d1a 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -1361,6 +1361,7 @@ endpoint_t source; rp->r_scheduler = rs_start->rss_scheduler; rp->r_priority = rs_start->rss_priority; rp->r_quantum = rs_start->rss_quantum; + rp->r_cpu = rs_start->rss_cpu; } /* Update command and arguments. */ diff --git a/servers/rs/request.c b/servers/rs/request.c index 0282a3510..eccf60ed5 100755 --- a/servers/rs/request.c +++ b/servers/rs/request.c @@ -958,6 +958,18 @@ PRIVATE int check_request(struct rs_start *rs_start) return EINVAL; } + if (rs_start->rss_cpu == RS_CPU_BSP) + rs_start->rss_cpu = machine.bsp_id; + else if (rs_start->rss_cpu == RS_CPU_DEFAULT) { + /* keep the default value */ + } else if (rs_start->rss_cpu < 0) + return EINVAL; + else if (rs_start->rss_cpu > machine.processors_count) { + printf("RS: cpu number %d out of range 0-%d, using BSP\n", + rs_start->rss_cpu, machine.processors_count); + rs_start->rss_cpu = machine.bsp_id; + } + /* Verify signal manager. */ if (rs_start->rss_sigmgr != SELF && (rs_start->rss_sigmgr < 0 || diff --git a/servers/rs/type.h b/servers/rs/type.h index b9eee86d0..8deb541e1 100644 --- a/servers/rs/type.h +++ b/servers/rs/type.h @@ -62,8 +62,9 @@ struct rproc { */ uid_t r_uid; endpoint_t r_scheduler; /* scheduler */ - unsigned r_priority; - unsigned r_quantum; + int r_priority; /* negative values are reserved for special meanings */ + int r_quantum; + int r_cpu; char r_ipc_list[MAX_IPC_LIST]; int r_nr_control; diff --git a/servers/rs/utility.c b/servers/rs/utility.c index dbbedc214..c32ecbd22 100644 --- a/servers/rs/utility.c +++ b/servers/rs/utility.c @@ -205,7 +205,7 @@ PUBLIC int sched_init_proc(struct rproc *rp) /* Start scheduling for the given process. */ if ((s = sched_start(rp->r_scheduler, rp->r_pub->endpoint, - RS_PROC_NR, rp->r_priority, rp->r_quantum, + RS_PROC_NR, rp->r_priority, rp->r_quantum, rp->r_cpu, &rp->r_scheduler)) != OK) { return s; } diff --git a/servers/sched/schedule.c b/servers/sched/schedule.c index 142cfad32..97e9674f9 100644 --- a/servers/sched/schedule.c +++ b/servers/sched/schedule.c @@ -189,7 +189,7 @@ PUBLIC int do_start_scheduling(message *m_ptr) /* Take over scheduling the process. The kernel reply message populates * the processes current priority and its time slice */ - if ((rv = sys_schedctl(0, rmp->endpoint, 0, 0)) != OK) { + if ((rv = sys_schedctl(0, rmp->endpoint, 0, 0, 0)) != OK) { printf("Sched: Error taking over scheduling for %d, kernel said %d\n", rmp->endpoint, rv); return rv; @@ -268,7 +268,7 @@ PRIVATE int schedule_process(struct schedproc * rmp) pick_cpu(rmp); if ((rv = sys_schedule(rmp->endpoint, rmp->priority, - rmp->time_slice)) != OK) { + rmp->time_slice, rmp->cpu)) != OK) { printf("SCHED: An error occurred when trying to schedule %d: %d\n", rmp->endpoint, rv); }