#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 *
# 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 */
#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
{
_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,
_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)
_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,
/*===========================================================================*
* 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);
- /* 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);
+ /* 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);
+ }
- RTS_UNSET(rp, RTS_NO_QUANTUM);
+ 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 */
+ RTS_UNSET(p, RTS_NO_QUANTUM);
return OK;
}
{
struct proc *p;
unsigned flags;
- unsigned priority, quantum;
+ int priority, quantum, cpu;
int proc_nr;
int r;
/* 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 {
{
struct proc *p;
int proc_nr;
- unsigned priority, quantum;
+ int priority, quantum, cpu;
if (!isokendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr))
return EINVAL;
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);
}
/*===========================================================================*
* 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;
/* 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;
#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;
m.SCHEDCTL_ENDPOINT = proc_ep;
m.SCHEDCTL_PRIORITY = priority;
m.SCHEDCTL_QUANTUM = quantum;
+ m.SCHEDCTL_CPU = cpu;
return(_kernel_call(SYS_SCHEDCTL, &m));
}
#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));
}
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",
EXTERN unsigned system_hz;
+EXTERN struct machine machine; /* machine info */
+
#endif /* RS_GLO_H */
FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
FORWARD _PROTOTYPE( int sef_cb_signal_manager, (endpoint_t target, int signo) );
+
/*===========================================================================*
* main *
*===========================================================================*/
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) {
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. */
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 ||
*/
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;
/* 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;
}
/* 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;
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);
}