]> Zhao Yanbai Git Server - minix.git/commitdiff
Scheduling updates to the kernel. Sched() function now is single point for
authorJorrit Herder <jnherder@minix3.org>
Mon, 22 Aug 2005 15:14:11 +0000 (15:14 +0000)
committerJorrit Herder <jnherder@minix3.org>
Mon, 22 Aug 2005 15:14:11 +0000 (15:14 +0000)
policy. Actual policy not yet implemented.

PM calculates nice values for processes in boot image.

IS debug dumps improved (Shift+F1-F4).

12 files changed:
kernel/clock.c
kernel/glo.h
kernel/main.c
kernel/proc.c
kernel/proc.h
kernel/system/do_fork.c
servers/is/dmp.c
servers/is/dmp_fs.c
servers/is/dmp_kernel.c
servers/is/dmp_pm.c
servers/is/proto.h
servers/pm/main.c

index fbf2d8430df98d618175a35891f8f5bbdfa663b1..e5624d2ec9751878073c8d90ad3f0e43fcb69900 100755 (executable)
@@ -118,7 +118,7 @@ message *m_ptr;                             /* pointer to request message */
    * no more time left, it will get a new quantum and inserted at the right 
    * place in the queues.  As a side-effect a new process will be scheduled.
    */ 
-  if (prev_ptr->p_sched_ticks <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) {
+  if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) {
       lock_dequeue(prev_ptr);          /* take it off the queues */
       lock_enqueue(prev_ptr);          /* and reinsert it again */ 
   }
@@ -182,17 +182,17 @@ irq_hook_t *hook;
    */
   proc_ptr->p_user_time += ticks;
   if (priv(proc_ptr)->s_flags & PREEMPTIBLE) {
-      proc_ptr->p_sched_ticks -= ticks;
+      proc_ptr->p_ticks_left -= ticks;
   }
   if (! (priv(proc_ptr)->s_flags & BILLABLE)) {
       bill_ptr->p_sys_time += ticks;
-      bill_ptr->p_sched_ticks -= ticks;
+      bill_ptr->p_ticks_left -= ticks;
   }
 
   /* Check if do_clocktick() must be called. Done for alarms and scheduling.
    * Some processes, such as the kernel tasks, cannot be preempted. 
    */ 
-  if ((next_timeout <= realtime) || (proc_ptr->p_sched_ticks <= 0)) {
+  if ((next_timeout <= realtime) || (proc_ptr->p_ticks_left <= 0)) {
       prev_ptr = proc_ptr;                     /* store running process */
       lock_notify(HARDWARE, CLOCK);            /* send notification */
   } 
index a80b84dc6b27e40302ec4005a6ab06673a428b21..71fcf0ebb2ed65bd04c5f23287cc5283b665a77e 100755 (executable)
@@ -30,7 +30,6 @@ EXTERN struct proc *proc_ptr; /* pointer to currently running process */
 EXTERN struct proc *next_ptr;  /* next process to run after restart() */
 EXTERN struct proc *bill_ptr;  /* process to bill for clock ticks */
 EXTERN char k_reenter;         /* kernel reentry count (entry count less 1) */
-EXTERN int sched_ticks;                /* keep track of quantum usage */
 EXTERN unsigned lost_ticks;    /* clock ticks counted outside clock task */
 
 
index 8af1329d746bd958f45bfcd6c047c6fa7271cf52..7f8f1d13f86ac737d5eb62ff5588816c43fe6a97 100755 (executable)
@@ -77,8 +77,7 @@ PUBLIC void main()
        rp->p_max_priority = ip->priority;      /* max scheduling priority */
        rp->p_priority = ip->priority;          /* current priority */
        rp->p_quantum_size = ip->quantum;       /* quantum size in ticks */
-       rp->p_sched_ticks = ip->quantum;        /* current credit */
-       rp->p_full_quantums = QUANTUMS(ip->priority);   /* nr quantums left */
+       rp->p_ticks_left = ip->quantum;         /* current credit */
        strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */
        (void) get_priv(rp, (ip->flags & SYS_PROC));    /* assign structure */
        priv(rp)->s_flags = ip->flags;                  /* process flags */
index 618dbb19ab2e598e2aaf2d1e36c72127e01bbcf8..59225177d51f20ca43b39535b0e6e81ac2647bf0 100755 (executable)
@@ -12,8 +12,8 @@
  *   lock_dequeue:    remove a process from the scheduling queues
  *
  * Changes:
- *   Aug 19, 2005     rewrote multilevel scheduling code  (Jorrit N. Herder)
- *   Jul 25, 2005     protection and checks in sys_call()  (Jorrit N. Herder)
+ *   Aug 19, 2005     rewrote scheduling code  (Jorrit N. Herder)
+ *   Jul 25, 2005     rewrote system call handling  (Jorrit N. Herder)
  *   May 26, 2005     rewrote message passing functions  (Jorrit N. Herder)
  *   May 24, 2005     new notification system call  (Jorrit N. Herder)
  *   Oct 28, 2004     nonblocking send and receive calls  (Jorrit N. Herder)
@@ -56,7 +56,6 @@ FORWARD _PROTOTYPE( void enqueue, (struct proc *rp) );
 FORWARD _PROTOTYPE( void dequeue, (struct proc *rp) );
 FORWARD _PROTOTYPE( void sched, (struct proc *rp, int *queue, int *front) );
 FORWARD _PROTOTYPE( void pick_proc, (void) );
-FORWARD _PROTOTYPE( void balance_queues, (struct proc *rp) );
 
 #define BuildMess(m_ptr, src, dst_ptr) \
        (m_ptr)->m_source = (src);                                      \
@@ -401,44 +400,28 @@ int dst;                  /* who is to be notified */
 PRIVATE void enqueue(rp)
 register struct proc *rp;      /* this process is now runnable */
 {
-/* Add 'rp' to one of the queues of runnable processes. We need to decide
- * where to put the process based on its quantum. If there is time left, it
- * is added to the front of its queue, so that it can immediately run. 
- * Otherwise its is given a new quantum and added to the rear of the queue.
+/* Add 'rp' to one of the queues of runnable processes.  This function is 
+ * responsible for inserting a process into one of the scheduling queues. 
+ * The mechanism is implemented here.   The actual scheduling policy is
+ * defined in sched() and pick_proc().
  */
-  register int q;                              /* scheduling queue to use */
-  int time_left;                               /* quantum fully used? */
-
-  /* Check if the process has time left and determine what queue to use. A
-   * process that consumed a full quantum is given a lower priority, so that 
-   * the CPU-bound processes cannot starve I/O-bound processes. When the 
-   * threshold is reached, the scheduling queues are balanced to prevent all
-   * processes from ending up in the lowest queue.
-   */
-  time_left = (rp->p_sched_ticks > 0);         /* check ticks left */
-  if ( ! time_left) {                          /* quantum consumed ? */
-      rp->p_sched_ticks = rp->p_quantum_size;   /* give new quantum */
-#if DEAD_CODE
-      if (proc_nr(rp) != IDLE) {               /* already lowest priority */
-          rp->p_priority ++;                   /* lower the priority */
-          if (rp->p_priority >= IDLE_Q)        /* threshold exceeded */
-              balance_queues(rp);              /* rebalance queues */
-      }
-#endif
-  }
-  q = rp->p_priority;                          /* scheduling queue to use */
+  int q;                                       /* scheduling queue to use */
+  int front;                                   /* add to front or back */
 
 #if DEBUG_SCHED_CHECK
   check_runqueues("enqueue");
   if(rp->p_ready) kprintf("enqueue() already ready process\n");
 #endif
 
+  /* Determine where to insert to process. */
+  sched(rp, &q, &front);
+
   /* Now add the process to the queue. */
   if (rdy_head[q] == NIL_PROC) {               /* add to empty queue */
       rdy_head[q] = rdy_tail[q] = rp;          /* create a new queue */
       rp->p_nextready = NIL_PROC;              /* mark new end */
   } 
-  else if (time_left) {                                /* add to head of queue */
+  else if (front) {                            /* add to head of queue */
       rp->p_nextready = rdy_head[q];           /* chain head of queue */
       rdy_head[q] = rp;                                /* set new queue head */
   } 
@@ -447,7 +430,9 @@ register struct proc *rp;   /* this process is now runnable */
       rdy_tail[q] = rp;                                /* set new queue tail */
       rp->p_nextready = NIL_PROC;              /* mark new end */
   }
-  pick_proc();                                 /* select next to run */
+
+  /* Now select the next process to run. */
+  pick_proc();                 
 
 #if DEBUG_SCHED_CHECK
   rp->p_ready = 1;
@@ -461,8 +446,10 @@ register struct proc *rp;  /* this process is now runnable */
 PRIVATE void dequeue(rp)
 register struct proc *rp;      /* this process is no longer runnable */
 {
-/* A process has blocked. See ready for a description of the queues. */
-
+/* A process must be removed from the scheduling queues, for example, because
+ * it has blocked.  If the currently active process is removed, a new process
+ * is picked to run by calling pick_proc().
+ */
   register int q = rp->p_priority;             /* queue to use */
   register struct proc **xpp;                  /* iterate over queue */
   register struct proc *prev_xp;
@@ -496,15 +483,6 @@ register struct proc *rp;  /* this process is no longer runnable */
       prev_xp = *xpp;                          /* save previous in chain */
   }
   
-#if DEAD_CODE
-  /* The caller blocked. Reset the scheduling priority and quantums allowed.
-   * The process' priority may have been lowered if a process consumed too 
-   * many full quantums in a row to prevent damage from infinite loops 
-   */
-  rp->p_priority = rp->p_max_priority;
-  rp->p_full_quantums = QUANTUMS(rp->p_priority);
-#endif
-
 #if DEBUG_SCHED_CHECK
   rp->p_ready = 0;
   check_runqueues("dequeue");
@@ -515,48 +493,42 @@ register struct proc *rp; /* this process is no longer runnable */
 /*===========================================================================*
  *                             sched                                        * 
  *===========================================================================*/
-PRIVATE void sched(sched_ptr, queue, front)
-struct proc *sched_ptr;                                /* process to be scheduled */
+PRIVATE void sched(rp, queue, front)
+register struct proc *rp;                      /* process to be scheduled */
 int *queue;                                    /* return: queue to use */
 int *front;                                    /* return: front or back */
 {
+/* 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. 
+ */
+  int time_left;
+  int penalty;
 
-}
-
-/*===========================================================================*
- *                             balance_queues                               * 
- *===========================================================================*/
-PRIVATE void balance_queues(pp)
-struct proc *pp;                               /* process that caused this */
-{
-/* To balance the scheduling queues, they will be rebuild whenever a process
- * is put in the lowest queues where IDLE resides. All processes get their 
- * priority raised up to their maximum priority. 
- */ 
-  register struct proc *rp;
-  register int q;
-  int penalty = pp->p_priority - pp->p_max_priority;
-
-  /* First clean up the old scheduling queues. */
-  for (q=0; q<NR_SCHED_QUEUES; q++) {
-      rdy_head[q] = rdy_tail[q] = NIL_PROC;
+  /* Check whether the process has time left. Otherwise give a new quantum.
+   */
+  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 */
   }
 
-  /* Then rebuild the queues, while balancing priorities. Each process that is 
-   * in use may get a higher priority and gets a new quantum. Processes that
-   * are runnable are added to the scheduling queues, unless it concerns the
-   * process that caused this function to be called (it will be added after 
-   * returning from this function). 
+  /* 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.
    */
-  for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
-      if (! (rp->p_rts_flags & SLOT_FREE)) {   /* update in-use slots */
-          rp->p_priority = MAX(rp->p_priority - penalty, rp->p_max_priority);
-          rp->p_sched_ticks = rp->p_quantum_size;
-          if (rp->p_rts_flags == 0) {          /* process is runnable */
-              if (rp != pp) enqueue(rp);       /* add it to a queue */
-          }
-      }
+  penalty = 0;
+  if (priv(rp)->s_flags & BILLABLE) {          /* user process */
   }
+  else {                                       /* system process */
+  }
+  rp->p_priority = MIN((rp->p_max_priority + penalty), (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
+   * process' current priority. 
+   */
+  *queue = rp->p_priority;
+  *front = time_left;
 }
 
 
index 12b88583eddcc344bd8b580601a499489c3eefac..5350779f9b7a9300a061a8d29d2ddb0db8731772 100755 (executable)
@@ -33,8 +33,9 @@ struct proc {
   char p_priority;             /* current scheduling priority */
   char p_max_priority;         /* maximum scheduling priority */
   char p_quantum_size;         /* quantum size in ticks */
-  char p_sched_ticks;          /* number of scheduling ticks left */
-  char p_full_quantums;                /* number of full quantums left */
+  char p_ticks_left;           /* number of scheduling ticks left */
+  char p_history;              /* scheduling history ageing algorithm */
+  short p_block_count;         /* times blocked in current quantum */
 
   struct mem_map p_memmap[NR_LOCAL_SEGS];   /* memory map (T, D, S) */
 
@@ -42,7 +43,6 @@ struct proc {
   clock_t p_sys_time;          /* sys time in ticks */
 
   struct proc *p_nextready;    /* pointer to next ready process */
-  struct notification *p_ntf_q;        /* queue of pending notifications */
   struct proc *p_caller_q;     /* head of list of procs wishing to send */
   struct proc *p_q_link;       /* link to next proc wishing to send */
   message *p_messbuf;          /* pointer to passed message buffer */
@@ -80,9 +80,6 @@ struct proc {
 #define MIN_USER_Q       14    /* minimum priority for user processes */
 #define IDLE_Q           15    /* lowest, only IDLE process goes here */
 
-/* Each queue has a maximum number of full quantums associated with it. */
-#define QUANTUMS(q)    (1 + (NR_SCHED_QUEUES - (q))/2)
-
 /* Magic process table addresses. */
 #define BEG_PROC_ADDR (&proc[0])
 #define BEG_USER_ADDR (&proc[NR_TASKS])
index 6a1ed6a99dd996170d8a399c60ac0184f9cae43d..a500da249d9730a52dfe555149217c078bba41e8 100644 (file)
@@ -51,8 +51,12 @@ register message *m_ptr;     /* pointer to request message */
   rpc->p_user_time = 0;                /* set all the accounting times to 0 */
   rpc->p_sys_time = 0;
 
-  rpc->p_sched_ticks /= 2;     /* parent and child have to share quantum */
-  rpp->p_sched_ticks /= 2;     
+  /* Parent and child have to share the quantum that the forked process had,
+   * so that queued processes do not have to wait longer because of the fork.
+   * If the time left is odd, the child gets an extra tick.
+   */
+  rpc->p_ticks_left = (rpc->p_ticks_left + 1) / 2;
+  rpp->p_ticks_left =  rpp->p_ticks_left / 2;  
 
   /* If the parent is a privileged process, take away the privileges from the 
    * child process and inhibit it from running by setting the NO_PRIV flag.
index 866ced590acd43639925cfa82d42c81e7d4fdec4..ffe0e66bd953c525903ab0a3459dc8e544a277a9 100644 (file)
@@ -57,6 +57,7 @@ PUBLIC int do_fkey_pressed(message *m)
 
   /* Also check Shift F1-F6 keys. */
   if (pressed(SF1))    mproc_dmp();
+  if (pressed(SF2))    sigaction_dmp();
 
   if (pressed(SF3))    fproc_dmp();
   if (pressed(SF4))    dtab_dmp();
index 5b132eb5edc7e93392f006c407ff537fa5f01d9e..12c5480206dc60074bd3f28b35b31ef442b57a3f 100644 (file)
@@ -68,6 +68,7 @@ PUBLIC void dtab_dmp()
     printf("Major  Proc\n");
     printf("-----  ----\n");
     for (i=0; i<NR_DEVICES; i++) {
+        if (dmap[i].dmap_driver == 0) continue;
         printf("%5d  ", i);
         printf("%4d\n", dmap[i].dmap_driver);
         
index fb9df8622492ab9bcc18a83c65e5d356a3117be6..982aedb2fb97be6c2ce2b3117da28fd7a295a2bf 100644 (file)
@@ -472,7 +472,7 @@ PUBLIC void proctab_dmp()
       return;
   }
 
-  printf("\n--nr-name---- -prior-quant-##- -user---sys- -text---data---size- -rts flags-\n");
+  printf("\n--nr-name---- -prior-quant- -user---sys- -text---data---size- -rts flags-\n");
 
   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
        if (isemptyp(rp)) continue;
@@ -484,11 +484,10 @@ PUBLIC void proctab_dmp()
        if (proc_nr(rp) == IDLE)        printf("(%2d) ", proc_nr(rp));  
        else if (proc_nr(rp) < 0)       printf("[%2d] ", proc_nr(rp));
        else                            printf(" %2d  ", proc_nr(rp));
-       printf(" %-8.8s %02u/%02u %02d/%02d %02u %6lu%6lu %6uK%6uK%6uK %s",
+       printf(" %-8.8s %02u/%02u %02u/%02u %6lu%6lu %6uK%6uK%6uK %s",
               rp->p_name,
               rp->p_priority, rp->p_max_priority,
-              rp->p_sched_ticks, rp->p_quantum_size, 
-              rp->p_full_quantums, 
+              rp->p_ticks_left, rp->p_quantum_size, 
               rp->p_user_time, rp->p_sys_time,
               click_to_round_k(text), click_to_round_k(data),
               click_to_round_k(size),
index 938fbf44f864821c40f4ddb5e722d13e288c1251..a813a48656cbaf06dc7e8c2345fdb7375deb6efa 100644 (file)
@@ -17,6 +17,26 @@ PUBLIC struct mproc mproc[NR_PROCS];
 /*===========================================================================*
  *                             mproc_dmp                                    *
  *===========================================================================*/
+PRIVATE char *flags_str(int flags)
+{
+       static char str[10];
+       str[0] = (flags & WAITING) ? 'W' : '-';
+       str[1] = (flags & ZOMBIE)  ? 'Z' : '-';
+       str[2] = (flags & PAUSED)  ? 'P' : '-';
+       str[3] = (flags & ALARM_ON)  ? 'A' : '-';
+       str[4] = (flags & TRACED)  ? 'T' : '-';
+       str[5] = (flags & STOPPED)  ? 'S' : '-';
+       str[6] = (flags & SIGSUSPENDED)  ? 'U' : '-';
+       str[7] = (flags & REPLY)  ? 'R' : '-';
+       str[8] = (flags & ONSWAP)  ? 'O' : '-';
+       str[9] = (flags & SWAPIN)  ? 'I' : '-';
+       str[10] = (flags & DONT_SWAP)  ? 'D' : '-';
+       str[11] = (flags & PRIV_PROC)  ? 'P' : '-';
+       str[12] = '\0';
+
+       return str;
+}
+
 PUBLIC void mproc_dmp()
 {
   struct mproc *mp;
@@ -27,7 +47,7 @@ PUBLIC void mproc_dmp()
 
   getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);
 
-  printf("-process- -nr-prnt- -pid/ppid/grp --uid--gid- -flags- --ignore--catch--block--\n");
+  printf("-process- -nr-prnt- -pid/ppid/grp- -uid--gid- -nice- -flags------\n");
   for (i=prev_i; i<NR_PROCS; i++) {
        mp = &mproc[i];
        if (mp->mp_pid == 0 && i != PM_PROC_NR) continue;
@@ -36,10 +56,8 @@ PUBLIC void mproc_dmp()
                mp->mp_name, i, mp->mp_parent, mp->mp_pid, mproc[mp->mp_parent].mp_pid, mp->mp_procgrp);
        printf("%d(%d)  %d(%d)  ",
                mp->mp_realuid, mp->mp_effuid, mp->mp_realgid, mp->mp_effgid);
-       printf("0x%04x  ", 
-               mp->mp_flags); 
-       printf("0x%05x 0x%05x 0x%05x", 
-               mp->mp_ignore, mp->mp_catch, mp->mp_sigmask); 
+       printf(" %3d  %s  ", 
+               mp->mp_nice, flags_str(mp->mp_flags)); 
        printf("\n");
   }
   if (i >= NR_PROCS) i = 0;
@@ -49,7 +67,36 @@ PUBLIC void mproc_dmp()
 
 
 /*===========================================================================*
- *                             ...._dmp                                     *
+ *                             sigaction_dmp                                *
  *===========================================================================*/
+PUBLIC void sigaction_dmp()
+{
+  struct mproc *mp;
+  int i, n=0;
+  static int prev_i = 0;
+  clock_t uptime;
+
+  printf("Process manager (PM) signal action dump\n");
+
+  getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);
+  getuptime(&uptime);
+
+  printf("-process- -nr- --ignore- --catch- --block- -tomess-- -pending-- -alarm---\n");
+  for (i=prev_i; i<NR_PROCS; i++) {
+       mp = &mproc[i];
+       if (mp->mp_pid == 0 && i != PM_PROC_NR) continue;
+       if (++n > 22) break;
+       printf("%8.8s  %3d  ", mp->mp_name, i);
+       printf(" 0x%06x 0x%06x 0x%06x 0x%06x   ", 
+               mp->mp_ignore, mp->mp_catch, mp->mp_sigmask, mp->mp_sig2mess); 
+       printf("0x%06x  ", mp->mp_sigpending);
+       if (mp->mp_flags & ALARM_ON) printf("%8u", mp->mp_timer.tmr_exp_time-uptime);
+       else printf("       -");
+       printf("\n");
+  }
+  if (i >= NR_PROCS) i = 0;
+  else printf("--more--\r");
+  prev_i = i;
+}
 
 
index c79c8ec5c35d6caa9583ea0bfb35bfeac3afeb6c..5299308a61ca10dd8af23809e55899bd917ce404 100644 (file)
@@ -21,6 +21,7 @@ _PROTOTYPE( void timing_dmp, (void)                                   );
 
 /* dmp_pm.c */
 _PROTOTYPE( void mproc_dmp, (void)                                     );
+_PROTOTYPE( void sigaction_dmp, (void)                                 );
 
 /* dmp_fs.c */
 _PROTOTYPE( void dtab_dmp, (void)                                      );
index 2634843e7474be554a4fa64d746892991ded5ff2..b56f131af81a45e1df044ecb1093db6efcfff536 100644 (file)
@@ -16,7 +16,7 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <fcntl.h>
-#include <sys/ioc_memory.h>
+#include <sys/resource.h>
 #include <string.h>
 #include "mproc.h"
 #include "param.h"
 #include "../../kernel/const.h"
 #include "../../kernel/config.h"
 #include "../../kernel/type.h"
+#include "../../kernel/proc.h"
 
 FORWARD _PROTOTYPE( void get_work, (void)                              );
 FORWARD _PROTOTYPE( void pm_init, (void)                               );
+FORWARD _PROTOTYPE( int get_nice_value, (int queue)                            );
 FORWARD _PROTOTYPE( void get_mem_chunks, (struct memory *mem_chunks)   );
 FORWARD _PROTOTYPE( void patch_mem_chunks, (struct memory *mem_chunks, 
        struct mem_map *map_ptr)        );
@@ -207,6 +209,7 @@ PRIVATE void pm_init()
                rmp = &mproc[ip->proc_nr];      
                strncpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); 
                rmp->mp_parent = SM_PROC_NR;
+               rmp->mp_nice = get_nice_value(ip->priority);
                if (ip->proc_nr == INIT_PROC_NR) {      /* user process */
                        rmp->mp_pid = INIT_PID;
                        rmp->mp_flags |= IN_USE; 
@@ -267,6 +270,22 @@ PRIVATE void pm_init()
   printf(" free %u KB.\n", click_to_round_k(free_clicks));
 }
 
+/*=========================================================================*
+ *                             get_nice_value                             *
+ *=========================================================================*/
+PRIVATE int get_nice_value(queue)
+int queue;                             /* store mem chunks here */
+{
+/* Processes in the boot image have a priority assigned. The PM doesn't know
+ * about priorities, but uses 'nice' values instead. The priority is between 
+ * MIN_USER_Q and MAX_USER_Q. We have to scale between PRIO_MIN and PRIO_MAX.
+ */ 
+  int nice_val = (queue - USER_Q) * (PRIO_MAX-PRIO_MIN+1) / 
+      (MIN_USER_Q-MAX_USER_Q+1);
+  if (nice_val > PRIO_MAX) nice_val = PRIO_MAX;        /* shouldn't happen */
+  if (nice_val < PRIO_MIN) nice_val = PRIO_MIN;        /* shouldn't happen */
+  return nice_val;
+}
 
 #if _WORD_SIZE == 2
 /* In real mode only 1M can be addressed, and in 16-bit protected we can go