int *queue; /* return: queue to use */
int *front; /* return: front or back */
{
-/* This function determines the scheduling policy. It is called whenever a
+/* This function determines the scheduling policy. It is called whenever a
* process must be added to one of the scheduling queues to decide where to
- * insert it.
+ * insert it. As a side-effect the process' priority may be updated.
*/
- int time_left;
- int penalty;
-
- /* Check whether the process has time left. Otherwise give a new quantum.
+ static struct proc *prev_ptr = NIL_PROC; /* previous without time */
+ int time_left = (rp->p_ticks_left > 0); /* quantum fully consumed */
+ int penalty = 0; /* change in priority */
+
+ /* Check whether the process has time left. Otherwise give a new quantum
+ * and possibly raise the priority. Processes using multiple quantums
+ * in a row get a lower priority to catch infinite loops in high priority
+ * processes (system servers and drivers).
*/
- time_left = (rp->p_ticks_left > 0); /* check ticks left */
if ( ! time_left) { /* quantum consumed ? */
rp->p_ticks_left = rp->p_quantum_size; /* give new quantum */
+ if (prev_ptr == rp) penalty ++; /* catch infinite loops */
+ else penalty --; /* give slow way back */
+ prev_ptr = rp; /* store ptr for next */
}
- /* Determine the new priority of this process. User and system processes
- * are treated different. They can be distinguished because only user
- * processes (and IDLE) are billable.
- */
- penalty = 0;
+#if 0
if (priv(rp)->s_flags & BILLABLE) { /* user process */
}
else { /* system process */
}
- rp->p_priority = MIN((rp->p_max_priority + penalty), (IDLE_Q - 1));
+#endif
+
+ /* Determine the new priority of this process. The bounds are determined
+ * by IDLE's queue and the maximum priority of this process. Kernel task
+ * and the idle process are never changed in priority.
+ */
+ if (! iskernelp(rp) && penalty != 0) {
+ rp->p_priority += penalty; /* update with penalty */
+ if (rp->p_priority < rp->p_max_priority) /* check upper bound */
+ rp->p_priority=rp->p_max_priority;
+ else if (rp->p_priority > IDLE_Q-1) /* check lower bound */
+ rp->p_priority = IDLE_Q-1;
+ }
/* If there is time left, the process is added to the front of its queue,
* so that it can immediately run. The queue to use simply is always the
{ HARDWARE, 0, TSK_F, 64, TASK_Q, HRD_S, 0, 0, 0, "KERNEL"},
{ PM_PROC_NR, 0, SRV_F, 32, 3, 0, SRV_T, SRV_M, PM_C, "pm" },
{ FS_PROC_NR, 0, SRV_F, 32, 4, 0, SRV_T, SRV_M, FS_C, "fs" },
- { SM_PROC_NR, 0, SRV_F, 32, 3, 0, SRV_T, SYS_M, SM_C, "sm" },
- { TTY_PROC_NR, 0, SRV_F, 16, 1, 0, SRV_T, SYS_M, DRV_C, "tty" },
- { MEM_PROC_NR, 0, SRV_F, 16, 2, 0, SRV_T, DRV_M, MEM_C, "memory"},
- { LOG_PROC_NR, 0, SRV_F, 16, 2, 0, SRV_T, SYS_M, DRV_C, "log" },
- { DRVR_PROC_NR, 0, SRV_F, 16, 2, 0, SRV_T, SYS_M, DRV_C, "driver"},
+ { SM_PROC_NR, 0, SRV_F, 4, 3, 0, SRV_T, SYS_M, SM_C, "sm" },
+ { TTY_PROC_NR, 0, SRV_F, 4, 1, 0, SRV_T, SYS_M, DRV_C, "tty" },
+ { MEM_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, DRV_M, MEM_C, "memory"},
+ { LOG_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "log" },
+ { DRVR_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "driver"},
{ INIT_PROC_NR, 0, USR_F, 8, USER_Q, 0, USR_T, USR_M, 0, "init" },
};