]> Zhao Yanbai Git Server - minix.git/commitdiff
Various fixes and improvements.
authorJorrit Herder <jnherder@minix3.org>
Wed, 20 Jul 2005 15:25:38 +0000 (15:25 +0000)
committerJorrit Herder <jnherder@minix3.org>
Wed, 20 Jul 2005 15:25:38 +0000 (15:25 +0000)
- fixed bug that caused IDLE to panic (irq hook inconsistency);
- kprintf() now accepts multiple arguments; moved to utility.c;
- prepare_shutdown() signals system processes with SIGKSTOP;
- phys_fill() renamed to phys_memset(), argument order changed;
- kmemset() removed in favor of phys_kmemset();
- kstrncpy() removed in favor of phys_copy();
- katoi, kstrncmp replaced by normal library procedure again;
- rm_irq_handler() interface changed (simply pass hook pointer);

19 files changed:
kernel/Makefile
kernel/config.h
kernel/debug.c
kernel/exception.c
kernel/i8259.c
kernel/klib386.s
kernel/klibc.c [deleted file]
kernel/main.c
kernel/priv.h
kernel/proc.h
kernel/proto.h
kernel/start.c
kernel/system.c
kernel/system/do_exec.c
kernel/system/do_exit.c
kernel/system/do_irqctl.c
kernel/system/do_memset.c
kernel/type.h
kernel/utility.c

index dd6d214735f5e53eaa2ce4dccedff65dd174b603..3d1b42260e2edafba9f2004650e8275196b2928c 100755 (executable)
@@ -14,7 +14,7 @@ CFLAGS = -I$i
 LDFLAGS = -i 
 
 HEAD = mpx.o
-OBJS = start.o protect.o klibc.o klib.o table.o main.o proc.o \
+OBJS = start.o protect.o klib.o table.o main.o proc.o \
        i8259.o exception.o system.o clock.o utility.o debug.o
 SYSTEM = system.a
 LIBS = -ltimers 
index 31e7e6bc6080bec5717ed5cf7b5b52447f038a4e..eb5676b8e2ecaca218985fff5437b1c3ca29e10d 100644 (file)
@@ -53,7 +53,7 @@
  * a system server is notified and a copy of the buffer can be retrieved to 
  * display the message. The buffers size can safely be reduced.  
  */
-#define KMESS_BUF_SIZE   128           
+#define KMESS_BUF_SIZE   256           
 
 /* Buffer to gather randomness. This is used to generate a random stream by 
  * the MEMORY driver when reading from /dev/random. 
index 05ad2716b71a3b59286795adc55c1119688bfa3e..d4b4858592b32871265be7dae4c90460659bf7f5 100644 (file)
@@ -120,35 +120,35 @@ check_runqueues(char *when)
 
   for (q=0; q < NR_SCHED_QUEUES; q++) {
     if(rdy_head[q] && !rdy_tail[q]) {
-       kprintf("head but no tail: %s", (karg_t) when);
+       kprintf("head but no tail: %s", when);
                 panic("scheduling error", NO_NUM);
     }
     if(!rdy_head[q] && rdy_tail[q]) {
-       kprintf("tail but no head: %s", (karg_t) when);
+       kprintf("tail but no head: %s", when);
                 panic("scheduling error", NO_NUM);
     }
     if(rdy_tail[q] && rdy_tail[q]->p_nextready != NIL_PROC) {
-       kprintf("tail and tail->next not null; %s", (karg_t) when);
+       kprintf("tail and tail->next not null; %s", when);
                 panic("scheduling error", NO_NUM);
     }
     for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) {
         if (!xp->p_ready) {
-               kprintf("scheduling error: unready on runq: %s\n", (karg_t) when);
+               kprintf("scheduling error: unready on runq: %s\n", when);
                
                panic("found unready process on run queue", NO_NUM);
         }
         if(xp->p_priority != q) {
-               kprintf("scheduling error: wrong priority: %s\n", (karg_t) when);
+               kprintf("scheduling error: wrong priority: %s\n", when);
                
                panic("wrong priority", NO_NUM);
        }
        if(xp->p_found) {
-               kprintf("scheduling error: double scheduling: %s\n", (karg_t) when);
+               kprintf("scheduling error: double scheduling: %s\n", when);
                panic("proc more than once on scheduling queue", NO_NUM);
        }
        xp->p_found = 1;
        if(xp->p_nextready == NIL_PROC && rdy_tail[q] != xp) {
-               kprintf("scheduling error: last element not tail: %s\n", (karg_t) when);
+               kprintf("scheduling error: last element not tail: %s\n", when);
                panic("scheduling error", NO_NUM);
        }
        if(l++ > PROCLIMIT) panic("loop in schedule queue?", NO_NUM);
@@ -157,7 +157,7 @@ check_runqueues(char *when)
 
   for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
        if(! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
-               kprintf("scheduling error: ready not on queue: %s\n", (karg_t) when);
+               kprintf("scheduling error: ready not on queue: %s\n", when);
                panic("ready proc not on scheduling queue", NO_NUM);
                if(l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); }
        }
index 59eb67553f3bbacc0456ffa2102eadc7af1f8953..f822154e7c64a4cc4ffd6dbfb1215d46160bcb5a 100755 (executable)
@@ -65,13 +65,12 @@ unsigned vec_nr;
   if (ep->msg == NIL_PTR || machine.processor < ep->minprocessor)
        kprintf("\nIntel-reserved exception %d\n", vec_nr);
   else
-       kprintf("\n%s\n", karg(ep->msg));
-  kprintf("process number %d ", proc_nr(saved_proc));
-  kprintf("(%s), ", saved_proc->p_name);
-  kprintf("pc = %d:",  (unsigned) saved_proc->p_reg.cs);
-  kprintf("0x%x\n", (unsigned) saved_proc->p_reg.pc);
+       kprintf("\n%s\n", ep->msg);
+  kprintf("k_reenter = %d ", k_reenter);
+  kprintf("process %d (%s)", proc_nr(saved_proc), saved_proc->p_name);
+  kprintf("pc = %d:0x%x", (unsigned) saved_proc->p_reg.cs,
+  (unsigned) saved_proc->p_reg.pc);
 
-  kernel_exception = TRUE;             /* directly shutdown */
   panic("exception in a kernel task", NO_NUM);
 }
 
index 71d0f3bbb03e7157627acbb2d953ac190ff96997..f6ea9d8d1357f1662618a9147b5ddebcbbf9e4fe 100755 (executable)
@@ -123,29 +123,30 @@ irq_handler_t handler;
 /*=========================================================================*
  *                             rm_irq_handler                             *
  *=========================================================================*/
-PUBLIC int rm_irq_handler(irq, id)
-int irq;
-int id;
+PUBLIC void rm_irq_handler(hook)
+irq_hook_t *hook;
 {
 /* Unregister an interrupt handler. */
+  int irq = hook->irq; 
+  int id = hook->id;
   irq_hook_t **line;
 
-  if (irq < 0 || irq >= NR_IRQ_VECTORS) return(EINVAL);
+  if (irq < 0 || irq >= NR_IRQ_VECTORS) 
+      panic("invalid call to rm_irq_handler", irq);
 
   line = &irq_handlers[irq];
   while (*line != NULL) {
       if((*line)->id == id) {
           (*line) = (*line)->next;
-          if(! irq_handlers[irq])
-              irq_use &= ~(1 << irq);
-          return(OK);
+          if(! irq_handlers[irq]) irq_use &= ~(1 << irq);
+          return;
       }
       line = &(*line)->next;
   }
-
-  return(ENOENT);
+  /* When the handler is not found, normally return here. */
 }
 
+
 /*==========================================================================*
  *                             intr_handle                                 *
  *==========================================================================*/
index 8439aff8eb6df6e511c10e07ea3a4772691688f7..dc20841836cc35fe545925f86fbc4a5387bcbd74 100755 (executable)
@@ -26,7 +26,7 @@
 .define        _enable_irq     ! enable an irq at the 8259 controller
 .define        _disable_irq    ! disable an irq
 .define        _phys_copy      ! copy data from anywhere to anywhere in memory
-.define        _phys_fill      ! zero data anywhere in memory
+.define        _phys_memset    ! write pattern anywhere in memory
 .define        _mem_rdw        ! copy one word from [segment:offset]
 .define        _reset          ! reset the system
 .define        _idle_task      ! task executed when there is no work
@@ -440,25 +440,24 @@ pc_small:
        ret
 
 !*===========================================================================*
-!*                             phys_fill                                    *
+!*                             phys_memset                                  *
 !*===========================================================================*
-! PUBLIC void phys_fill(phys_bytes source, phys_bytes bytecount,
-!      unsigned long pattern);
+! PUBLIC void phys_memset(phys_bytes source, unsigned long pattern,
+!      phys_bytes bytecount);
 ! Fill a block of physical memory with pattern.
 
        .align  16
-
-_phys_fill:
+_phys_memset:
        push    ebp
        mov     ebp, esp
        push    esi
        push    ebx
        push    ds
        mov     esi, 8(ebp)
-       mov     eax, 12(ebp)
+       mov     eax, 16(ebp)
        mov     ebx, FLAT_DS_SELECTOR
        mov     ds, bx
-       mov     ebx, 16(ebp)
+       mov     ebx, 12(ebp)
        shr     eax, 2
 fill_start:
        mov     (esi), ebx
@@ -466,12 +465,12 @@ fill_start:
        dec     eax
        jnz     fill_start
        ! Any remaining bytes?
-       mov     eax, 12(ebp)
+       mov     eax, 16(ebp)
        and     eax, 3
 remain_fill:
        cmp     eax, 0
        jz      fill_done
-       movb    bl, 16(ebp)
+       movb    bl, 12(ebp)
        movb    (esi), bl
        add     esi, 1
        inc     ebp
diff --git a/kernel/klibc.c b/kernel/klibc.c
deleted file mode 100644 (file)
index ab885b9..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/* This file contains simplified versions of the standard libary functions for
- * use with the kernel. This way the kernel sources remain separate from user
- * sources and can easily be verified. Note that the functionality provided
- * can be slightly different.  
- *                                             March 2005, Jorrit N. Herder.
- * Entrypoints into this file:
- *     kmemcpy:                copy n bytes from pointer p1 to pointer p2
- *     kmemset:                set n bytes to c starting at pointer p
- *     kprintf:                printf for the kernel (see working below) 
- *     kstrcmp:                lexicographical comparison of two strings
- *     kstrncpy:       copy string and pad or copy up to n chars 
- *
- * This file contains the routines that take care of kernel messages, i.e.,
- * diagnostic output within the kernel. Kernel messages are not directly
- * displayed on the console, because this must be done by the PRINT driver. 
- * Instead, the kernel accumulates characters in a buffer and notifies the
- * output driver when a new message is ready. 
- */
-
-#include "kernel.h"
-
-#include <signal.h>
-#include <minix/com.h>
-
-#define isdigit(c)     ((unsigned) ((c) - '0') <  (unsigned) 10)
-#define END_OF_KMESS   -1
-FORWARD _PROTOTYPE(void kputc, (int c));
-
-
-/*=========================================================================*
- *                             kmemcpy                                    *
- *=========================================================================*/
-PUBLIC void *kmemcpy(void *s1, const void *s2, register size_t n)
-{
-  register char *p1 = s1;
-  register const char *p2 = s2;
-
-  while (n-- > 0) 
-      *p1++ = *p2++;
-  return s1;
-}
-
-
-/*=========================================================================*
- *                             kmemset                                    *
- *=========================================================================*/
-PUBLIC void *kmemset(void *s, register int c, register size_t n)
-{
-  register char *s1 = s;
-  if (n++>0) {                 /* optimized for speed */
-      while (--n > 0) 
-          *s1++ = c;
-  }
-  return s;
-}
-
-
-/*===========================================================================*
- *                             kprintf                                      *
- *===========================================================================*/
-PUBLIC void kprintf(fmt, arg)
-const char *fmt;               /* format string to be printed */
-karg_t arg;                    /* argument for format string */
-{
-  int c;                                       /* next character in fmt */
-  unsigned long u;                             /* hold number argument */
-  int base;                                    /* base of number arg */
-  int negative = 0;                            /* print minus sign */
-  static char x2c[] = "0123456789ABCDEF";      /* nr conversion table */
-  char ascii[8 * sizeof(long) / 3 + 2];                /* string for ascii number */
-  char *s = NULL;                              /* string to be printed */
-
-  while((c=*fmt++) != 0) {
-
-      if (c == '%') {                          /* expect format '%key' */
-          switch(c = *fmt++) {                 /* determine what to do */
-
-          /* Known keys are %d, %u, %x, %s, and %%. This is easily extended 
-           * with number types like %b and %o by providing a different base.
-           * Number type keys don't set a string to 's', but use the general
-           * conversion after the switch statement.
-           */ 
-          case 'd':                            /* output decimal */
-              u = arg < 0 ? -arg : arg;
-              if (arg < 0) negative = 1;
-              base = 10;
-              break;
-          case 'u':                            /* output unsigned long */
-              u = (unsigned long) arg;
-              base = 10;
-              break;
-          case 'x':                            /* output hexadecimal */
-              u = (unsigned long) arg;
-              base = 0x10;
-              break;
-          case 's':                            /* output string */
-              if ((s=(char *)arg) == NULL)
-                  s = "(null)";
-              break;
-          case '%':                            /* output percent */
-              s = "%";                          
-              break;                   
-
-          /* Unrecognized key. */
-          default:                             /* echo back %key */
-              s = "%?";                                
-              s[1] = c;                                /* set unknown key */
-          }
-
-          /* Assume a number if no string is set. Convert to ascii. */
-          if (s == NULL) {
-              s = ascii + sizeof(ascii)-1;
-              *s = 0;                  
-              do {  *--s = x2c[(u % base)]; }  /* work backwards */
-              while ((u /= base) > 0); 
-          }
-
-          /* This is where the actual output for format "%key" is done. */
-          if (negative) kputc('-');            /* print sign if negative */
-          while(*s != 0) { kputc(*s++); }      /* print string/ number */
-      }
-      else {
-          kputc(c);                            /* print and continue */
-      }
-  }
-  kputc(END_OF_KMESS);                         /* terminate output */
-}
-
-
-/*===========================================================================*
- *                                 kputc                                    *
- *===========================================================================*/
-PRIVATE void kputc(c)
-int c;                                 /* character to append */
-{
-/* Accumulate a single character for a kernel message. Send a notification
- * the to PRINTF_PROC driver if an END_OF_KMESS is encountered. 
- */
-  if (c != END_OF_KMESS) {
-      kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
-      if (kmess.km_size < KMESS_BUF_SIZE)
-          kmess.km_size += 1;          
-      kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
-  } else {
-      send_sig(PRINTF_PROC, SIGKMESS);
-  }
-}
-
-
-
-/*=========================================================================*
- *                             kstrcmp                                    *
- *=========================================================================*/
-int kstrcmp(register const char *s1, register const char *s2) 
-{
-  while (*s1 == *s2++)
-      if (*s1++ == '\0') return 0;
-  if (*s1 == '\0') return -1;
-  if (*--s2 == '\0') return 1;
-  return (unsigned char) *s1 - (unsigned char) *s2;
-}
-
-
-/*=========================================================================*
- *                             kstrncpy                                   *
- *=========================================================================*/
-PUBLIC char *kstrncpy(char *ret, register const char *s2, register ssize_t n)
-{
-  register char *s1 = ret;
-  while((n-- > 0) && (*s1++ = *s2++))  /* copy up to n chars */
-      /* EMPTY */ ;
-  while(n-- > 0)                       /* possibly pad target */
-      *s1++ = '\0';
-  return ret;
-}
-
-
index 27cedbe3d437f97a6771f0f65b4217b4503320da..7f13a77c14116b6146f7cf3a30804d00faa228cb 100755 (executable)
@@ -14,6 +14,7 @@
  */
 #include "kernel.h"
 #include <signal.h>
+#include <string.h>
 #include <unistd.h>
 #include <a.out.h>
 #include <minix/callnr.h>
@@ -24,6 +25,8 @@
 FORWARD _PROTOTYPE( void announce, (void));    
 FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
 
+#define SHUTDOWN_TICKS 5       /* time allowed to do cleanup */
+
 
 /*===========================================================================*
  *                                   main                                    *
@@ -31,15 +34,14 @@ FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
 PUBLIC void main()
 {
 /* Start the ball rolling. */
-  register struct proc *rp;
-  register struct priv *sp;
-  register int i,s;
+  struct system_image *ip;     /* boot image pointer */
+  register struct proc *rp;    /* process pointer */
+  register struct priv *sp;    /* privilege structure pointer */
+  register int i, s;
   int hdrindex;                        /* index to array of a.out headers */
   phys_clicks text_base;
-  vir_clicks text_clicks;
-  vir_clicks data_clicks;
+  vir_clicks text_clicks, data_clicks;
   reg_t ktsb;                  /* kernel task stack base */
-  struct system_image *ip;     /* boot image pointer */
   struct exec e_hdr;           /* for a copy of an a.out header */
 
   /* Initialize the interrupt controller. */
@@ -73,9 +75,13 @@ PUBLIC void main()
 
   for (i=0; i < NR_BOOT_PROCS; ++i) {
        ip = &image[i];                         /* process' attributes */
-       (void) init_proc(ip->proc_nr, NONE);    /* initialize new process */
        rp = proc_addr(ip->proc_nr);            /* get process pointer */
-       kstrncpy(rp->p_name, ip->proc_name, P_NAME_LEN);  /* set name */
+       (void) init_proc(rp, NIL_SYS_PROC);
+#if DEAD_CODE
+               (ip->flags & SYS_PROC) ?
+               NIL_SYS_PROC : NIL_PROC);       /* initialize new process */
+#endif
+       strncpy(rp->p_name, ip->proc_name, P_NAME_LEN);  /* set name */
        rp->p_name[P_NAME_LEN-1] = '\0';        /* just for safety */
        rp->p_max_priority = ip->priority;      /* max scheduling priority */
        rp->p_priority = ip->priority;          /* current priority */
@@ -106,7 +112,7 @@ PUBLIC void main()
        /* Convert addresses to clicks and build process memory map */
        text_base = e_hdr.a_syms >> CLICK_SHIFT;
        text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
-       if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0;  /* Common I&D */
+       if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0;     /* common I&D */
        data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
        rp->p_memmap[T].mem_phys = text_base;
        rp->p_memmap[T].mem_len  = text_clicks;
@@ -168,13 +174,13 @@ PUBLIC void main()
 PRIVATE void announce(void)
 {
   /* Display the MINIX startup banner. */
-  kprintf("MINIX %s.  Copyright 2001 Prentice-Hall, Inc.\n", 
-      karg(OS_RELEASE "." OS_VERSION));
+  kprintf("MINIX %s.%s.  Copyright 2001 Prentice-Hall, Inc.\n", 
+      OS_RELEASE, OS_VERSION);
 
 #if (CHIP == INTEL)
   /* Real mode, or 16/32-bit protected mode? */
   kprintf("Executing in %s mode\n\n",
-      machine.protected ? karg("32-bit protected") : karg("real"));
+      machine.protected ? "32-bit protected" : "real");
 #endif
 }
 
@@ -189,6 +195,7 @@ int how;                            /* reason to shut down */
  * sure it is only executed once. Unless a CPU exception occurred, the 
  */
   static timer_t shutdown_timer;       /* timer for watchdog function */ 
+  register struct proc *rp; 
   message m;
 
   /* Show debugging dumps on panics. Make sure that the TTY task is still 
@@ -201,21 +208,26 @@ int how;                          /* reason to shut down */
           return;                      /* await sys_abort() from TTY */
   }
 
-  /* Send signal to TTY so that it can switch to the primary console. */
-  send_sig(TTY, SIGKSTOP);
+  /* Send a signal to all system processes that are still alive to inform 
+   * them that the MINIX kernel is shutting down. A proper shutdown sequence
+   * should be implemented by a user-space server. This mechanism is useful
+   * as a backup in case of system panics, so that system processes can still
+   * run their shutdown code, e.g, to synchronize the FS or to let the TTY
+   * switch to the first console. 
+   */
+  for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
+      if (! isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && ! iskernelp(rp))
+          send_sig(proc_nr(rp), SIGKSTOP);
+  }
 
-  /* Allow processes to be scheduled to clean up, unless a CPU exception 
-   * occurred. This is done by setting a timer. The timer argument passes
-   * the shutdown status.
+  /* Notify system processes of the upcoming shutdown and allow them to be 
+   * scheduled by setting a watchog timer that calls shutdown(). The timer 
+   * argument passes the shutdown status. 
    */
+  kprintf("Informed system about upcoming shutdown with SIGKSTOP signal.\n"); 
+  kprintf("Time for cleanup is allowed.  MINIX will now be brought down.\n");
   tmr_arg(&shutdown_timer)->ta_int = how;      /* pass how in timer */
-  if (kernel_exception) {                      /* set in exception() */
-      kprintf("\nAn exception occured; skipping stop sequence.\n", NO_NUM);
-      shutdown(&shutdown_timer);               /* TTY isn't scheduled */
-  } else {
-      kprintf("\nNotifying system services about MINIX shutdown.\n", NO_NUM); 
-      set_timer(&shutdown_timer, get_uptime(), shutdown);
-  }
+  set_timer(&shutdown_timer, get_uptime() + SHUTDOWN_TICKS, shutdown);
 }
 
 
index 37dc8925440a83fc7349bbcff8c0a27431bf9d6f..ce66e41b8a5375cd7ebd96f9a868a699f019cee2 100755 (executable)
@@ -61,7 +61,9 @@ struct priv {
 EXTERN struct priv priv[NR_SYS_PROCS];         /* system properties table */
 EXTERN struct priv *ppriv_addr[NR_SYS_PROCS];  /* direct slot pointers */
 
-/* Unprivileged user processes all share the same privilege structure. */
+/* Unprivileged user processes all share the same privilege structure.
+ * This id must be fixed because it is used to check send mask entries.
+ */
 #define USER_PRIV_ID   0
 
 /* Make sure the system can boot. The following sanity check verifies that
index e1050e159033fbbfee4e2ebf14a175331cad06e1..2501572057d0bcfae785c8818b9d6e434ccb65d1 100755 (executable)
@@ -88,6 +88,7 @@ struct proc {
 #define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS])
 
 #define NIL_PROC          ((struct proc *) 0)          
+#define NIL_SYS_PROC      ((struct proc *) 1)          
 #define cproc_addr(n)     (&(proc + NR_TASKS)[(n)])
 #define proc_addr(n)      (pproc_addr + NR_TASKS)[(n)]
 #define proc_nr(p)       ((p)->p_nr)
index 265ce8e70fc5f99e472c4d5fedfdab5788e34a8f..74fd1250990b11fb68a388e41f468bea2a144e71 100755 (executable)
@@ -15,24 +15,14 @@ _PROTOTYPE( unsigned long read_clock, (void)                                );
 _PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f)        );
 _PROTOTYPE( void reset_timer, (struct timer *tp)                       );
 
-/* klibc.c */
-_PROTOTYPE( void *kmemcpy, (void *s1, const void *s2, register size_t n));
-_PROTOTYPE( void *kmemset, (void *s, register int c, register size_t n));
-_PROTOTYPE( int kstrcmp, (register const char *s1, register const char *s2));
-_PROTOTYPE( char *kstrncpy, 
-       (char *s1, register const char *s2, register const ssize_t n));
-#define karg(arg) (karg_t) (arg)
-_PROTOTYPE( void kprintf, (const char *fmt, karg_t arg)                        );
-
 /* main.c */
 _PROTOTYPE( void main, (void)                                          );
 _PROTOTYPE( void prepare_shutdown, (int how)                           );
 _PROTOTYPE( void stop_sequence, (struct timer *tp)                     );
 
 /* utility.c */
+_PROTOTYPE( void kprintf, (const char *fmt, ...)                       );
 _PROTOTYPE( void panic, (_CONST char *s, int n)                                );
-_PROTOTYPE( void safe_lock, (int c, char *v)                           );
-_PROTOTYPE( void safe_unlock, (void)                                   );
 _PROTOTYPE( int alloc_bit, (bitchunk_t *map, bit_t nr_bits)            ); 
 _PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits)  ); 
 
@@ -51,8 +41,8 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
 /* system.c */
 _PROTOTYPE( void send_sig, (int proc_nr, int sig_nr)                   );
 _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr)                  );
-_PROTOTYPE( int init_proc, (int proc_nr, int proto_nr)                 );
-_PROTOTYPE( void clear_proc, (int proc_nr)                             );
+_PROTOTYPE( int init_proc, (register struct proc *rc, struct proc *rp) );
+_PROTOTYPE( void clear_proc, (register struct proc *rc)                                );
 _PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr, 
                vir_bytes bytes)                                        );
 _PROTOTYPE( void sys_task, (void)                                      );
@@ -77,7 +67,7 @@ _PROTOTYPE( void intr_init, (int mine)                                        );
 _PROTOTYPE( void intr_handle, (irq_hook_t *hook)                       );
 _PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq,
                                                irq_handler_t handler)  );
-_PROTOTYPE( int rm_irq_handler, (int irq, int id)                      );
+_PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook)                    );
 
 /* klib*.s */
 _PROTOTYPE( void int86, (void)                                         );
@@ -88,11 +78,12 @@ _PROTOTYPE( int disable_irq, (irq_hook_t *hook)                             );
 _PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset)              );
 _PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
                phys_bytes count)                                       );
-_PROTOTYPE( void phys_fill, (phys_bytes source, phys_bytes count, unsigned long pattern)       );
+_PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern,
+               phys_bytes count)                                       );
 _PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) );
 _PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
-_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count));
-_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count));
+_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count)        );
+_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count)        );
 _PROTOTYPE( void reset, (void)                                         );
 _PROTOTYPE( void level0, (void (*func)(void))                          );
 _PROTOTYPE( void monitor, (void)                                       );
index ab7d83214eb6bbc554bcd5b4a5d7b823415b438e..1f9472bda84e9348bb4461698bcd86a90deb8820 100755 (executable)
@@ -12,6 +12,7 @@
 #include "protect.h"
 #include "proc.h"
 #include <stdlib.h>
+#include <string.h>
 
 FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key));
 
@@ -56,9 +57,9 @@ U16_t parmoff, parmsize;      /* boot parameters offset and length */
   /* Record miscellaneous information for user-space servers. */
   kinfo.nr_procs = NR_PROCS;
   kinfo.nr_tasks = NR_TASKS;
-  kstrncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
+  strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
   kinfo.release[sizeof(kinfo.release)-1] = '\0';
-  kstrncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
+  strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
   kinfo.version[sizeof(kinfo.version)-1] = '\0';
   kinfo.proc_addr = (vir_bytes) proc;
   kinfo.kmem_base = vir2phys(0);
@@ -75,16 +76,16 @@ U16_t parmoff, parmsize;    /* boot parameters offset and length */
 
   /* XT, AT or MCA bus? */
   value = get_value(params, "bus");
-  if (value == NIL_PTR || kstrcmp(value, "at") == 0) {
+  if (value == NIL_PTR || strcmp(value, "at") == 0) {
       machine.pc_at = TRUE;                    /* PC-AT compatible hardware */
-  } else if (kstrcmp(value, "mca") == 0) {
+  } else if (strcmp(value, "mca") == 0) {
       machine.pc_at = machine.ps_mca = TRUE;   /* PS/2 with micro channel */
   }
 
   /* Type of VDU: */
   value = get_value(params, "video");                  /* EGA or VGA video unit */
-  if (kstrcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
-  if (kstrcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
+  if (strcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
+  if (strcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
 
   /* Return to assembler code to switch to protected mode (if 286), 
    * reload selectors and call main().
index bfe5968957cfd4888ee516db1358c85af247679c..ebd463a4436f51c5052ada0e21c6458d762affab 100755 (executable)
@@ -92,7 +92,7 @@ PUBLIC void sys_task()
       if (result != EDONTREPLY) {
          m.m_type = result;                    /* report status of call */
           if (OK != lock_send(m.m_source, &m)) {
-              kprintf("Warning, SYSTASK couldn't reply to request from %d\n", 
+              kprintf("Warning, SYSTASK couldn't reply to request from %d.\n", 
                    m.m_source);
           }
       }
@@ -171,34 +171,36 @@ PRIVATE void initialize(void)
 /*===========================================================================*
  *                              init_proc                                   *
  *===========================================================================*/
-PUBLIC int init_proc(proc_nr, proto_nr)
-int proc_nr;                           /* slot of process to initialize */
-int proto_nr;                          /* prototype process to copy from */
+PUBLIC int init_proc(rc, rp)
+register struct proc *rc;              /* new (child) process pointer */
+struct proc *rp;                       /* prototype (parent) process */
 {
-  register struct proc *rc, *rp;
-  register struct priv *sp;
+  register struct priv *sp;            /* process' privilege structure */
   int i;
 
-  /* Get a pointer to the process to initialize. */
-  rc = proc_addr(proc_nr);
-  
   /* If there is a prototype process to initialize from, use it. Otherwise,
    * assume the caller will take care of initialization, but make sure that 
    * the new process gets a pointer to a system properties structure.
    */
-  if (isokprocn(proto_nr)) {
-      kprintf("INIT proc from prototype %d\n", proto_nr);
-
-  } else {
+  if (rp == NIL_PROC) {                                /* new user process */
+      kprintf("init_proc() for new user proc %d\n", proc_nr(rc));
+      sp = &priv[USER_PRIV_ID];
+      sp->s_proc_nr = ANY;                     /* misuse for users */
+      rc->p_priv = sp;                         /* assign to process */
+      return(OK);
+  } else if (rp == NIL_SYS_PROC) {             /* new system process */
       for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
           if (sp->s_proc_nr == NONE) {         /* found free slot */
-              sp->s_proc_nr = proc_nr;         /* set association */
+              sp->s_proc_nr = proc_nr(rc);     /* set association */
               rc->p_priv = sp;                 /* assign to process */
               return(OK);
           }
       }
       kprintf("No free PRIV structure!\n", NO_NUM);
       return(ENOSPC);                          /* out of resources */
+  } else {                                     /* forked process */
+
+      kprintf("init_proc() from prototype %d\n", proc_nr(rp));
   }
 }
 
@@ -206,26 +208,22 @@ int proto_nr;                             /* prototype process to copy from */
 /*===========================================================================*
  *                              clear_proc                                  *
  *===========================================================================*/
-PUBLIC void clear_proc(proc_nr)
-int proc_nr;                           /* slot of process to clean up */
+PUBLIC void clear_proc(rc)
+register struct proc *rc;              /* slot of process to clean up */
 {
-  register struct proc *rp, *rc;
+  register struct proc *rp;            /* iterate over process table */
   register struct proc **xpp;          /* iterate over caller queue */
   int i;
 
-  /* Get a pointer to the process that exited. */
-  rc = proc_addr(proc_nr);
-
   /* Turn off any alarm timers at the clock. */   
   reset_timer(&priv(rc)->s_alarm_timer);
 
-  /* Make sure the exiting process is no longer scheduled. */
+  /* Make sure that the exiting process is no longer scheduled. */
   if (rc->p_rts_flags == 0) lock_unready(rc);
 
   /* If the process being terminated happens to be queued trying to send a
    * message (e.g., the process was killed by a signal, rather than it doing 
-   * an exit or it is forcibly shutdown in the stop sequence), then it must
-   * be removed from the message queues.
+   * a normal exit), then it must be removed from the message queues.
    */
   if (rc->p_rts_flags & SENDING) {
       /* Check all proc slots to see if the exiting process is queued. */
@@ -245,18 +243,11 @@ int proc_nr;                              /* slot of process to clean up */
 
   /* Check the table with IRQ hooks to see if hooks should be released. */
   for (i=0; i < NR_IRQ_HOOKS; i++) {
-      if (irq_hooks[i].proc_nr == proc_nr)
-          irq_hooks[i].proc_nr = NONE; 
-  }
-
-#if TEMP_CODE
-  /* Check if there are pending notifications. Release the buffers. */
-  while (rc->p_ntf_q != NULL) {
-      i = (int) (rc->p_ntf_q - &notify_buffer[0]);
-      free_bit(i, notify_bitmap, NR_NOTIFY_BUFS); 
-      rc->p_ntf_q = rc->p_ntf_q->n_next;
+      if (irq_hooks[i].proc_nr == proc_nr(rc)) {
+          rm_irq_handler(&irq_hooks[i]);       /* remove interrupt handler */
+          irq_hooks[i].proc_nr = NONE;                 /* mark hook as free */
+      }
   }
-#endif
 
   /* Now it is safe to release the process table slot. If this is a system 
    * process, also release its privilege structure.  Further cleanup is not
@@ -264,7 +255,7 @@ int proc_nr;                                /* slot of process to clean up */
    * slots are assigned to another, new process. 
    */
   rc->p_rts_flags = SLOT_FREE;         
-  if (priv(rp)->s_flags & SYS_PROC) priv(rp)->s_proc_nr = NONE;
+  if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
 }
 
 
index b7ba512e0f23b10c2d09724588f60b6cdaa012e5..fa5828cb3d25f4132775c1fdb10ec834e2e8de64 100644 (file)
@@ -8,6 +8,7 @@
  *    m1_p3:   PR_IP_PTR               (new instruction pointer)
  */
 #include "../system.h"
+#include <string.h>
 #include <signal.h>
 
 #if USE_EXEC
@@ -35,7 +36,7 @@ register message *m_ptr;      /* pointer to request message */
 #endif
 #endif
 #if (CHIP == INTEL)            /* wipe extra LDT entries */
-  kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0,
+  phys_memset(vir2phys(&rp->p_ldt[EXTRA_LDT_INDEX]), 0,
        (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
 #endif
   rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR;     /* set pc */
@@ -50,7 +51,7 @@ register message *m_ptr;      /* pointer to request message */
        for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
        *np = 0;                                        /* mark end */
   } else {
-       kstrncpy(rp->p_name, "<unset>", P_NAME_LEN);
+       strncpy(rp->p_name, "<unset>", P_NAME_LEN);
   }
   return(OK);
 }
index c690b0914b096f551e5feae204224405db2f1beb..b17091639e163721219787b38f1fc1d2a900bc85 100644 (file)
@@ -28,13 +28,13 @@ message *m_ptr;                     /* pointer to request message */
       exit_proc_nr = m_ptr->PR_PROC_NR;                /* get exiting process */
       if (exit_proc_nr != SELF) {              /* PM tries to exit self */
           if (! isokprocn(exit_proc_nr)) return(EINVAL);
-          clear_proc(exit_proc_nr);            /* exit a user process */
+          clear_proc(proc_addr(exit_proc_nr)); /* exit a user process */
           return(OK);                          /* report back to PM */
       }
   } 
 
   /* The PM or some other system process requested to be exited. */
-  clear_proc(m_ptr->m_source);
+  clear_proc(proc_addr(m_ptr->m_source));
   return(EDONTREPLY);
 }
 #endif /* USE_EXIT */
index a30a06895762e51f2e4788b6124c69efdefe27c9..c87b21597409bfec0cd758a7fb54a76655412cdf 100644 (file)
@@ -80,9 +80,9 @@ register message *m_ptr;      /* pointer to request message */
            return(EINVAL);
       } else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) {
            return(EPERM);
-      } else {
-           r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id);
       }
+      /* Remove the handler and return. */
+      rm_irq_handler(&irq_hooks[irq_hook_id]);
       break;
 
   default:
index 224c4372440e2ac0db80a66612a6a3e6b93f0f5f..65e825dc56c9605583f5859c374a9d3520b6a73a 100644 (file)
@@ -18,10 +18,10 @@ PUBLIC int do_memset(m_ptr)
 register message *m_ptr;
 {
 /* Handle sys_memset(). */
-  unsigned long pat;
+  unsigned long p;
   unsigned char c = m_ptr->MEM_CHAR;
-  pat = c | (c << 8) | (c << 16) | (c << 24);
-  phys_fill((phys_bytes) m_ptr->MEM_PTR, (phys_bytes) m_ptr->MEM_COUNT, pat);
+  p = c | (c << 8) | (c << 16) | (c << 24);
+  phys_memset((phys_bytes) m_ptr->MEM_PTR, p, (phys_bytes) m_ptr->MEM_COUNT);
   return(OK);
 }
 
index c65e25fa6611e3485f1f4ccd0169e7a7e5dde573..98c16a09423a93a98af8431319adaa4591523489 100755 (executable)
@@ -3,11 +3,6 @@
 
 typedef _PROTOTYPE( void task_t, (void) );
 
-/* Type accepted by kprintf(). This is a hack to accept both integers and
- * char pointers in the same argument. 
- */
-typedef long karg_t;                   /* use largest type here */
-
 /* Process table and system property related types. */ 
 typedef int proc_nr_t;                 /* process table entry number */
 typedef short sys_id_t;                        /* system process index */
index 7d8753fa41b46e44db0353271108891e8d3ebf91..f8b827941af57811547cbf5c8835df0813a9334c 100755 (executable)
 /* This file contains a collection of miscellaneous procedures:
- *   panic         abort MINIX due to a fatal error
+ *     panic:          abort MINIX due to a fatal error
+ *     kprintf:                diagnostic output for the kernel 
+ *
+ * Changes:
+ *                      simple printing to circular buffer  (Jorrit N. Herder)
+ * 
+ * This file contains the routines that take care of kernel messages, i.e.,
+ * diagnostic output within the kernel. Kernel messages are not directly
+ * displayed on the console, because this must be done by the PRINT driver. 
+ * Instead, the kernel accumulates characters in a buffer and notifies the
+ * output driver when a new message is ready. 
  */
 
 #include "kernel.h"
-#include "assert.h"
 #include <unistd.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <signal.h>
 #include <minix/com.h>
 
+#define END_OF_KMESS   -1
+FORWARD _PROTOTYPE(void kputc, (int c));
 
 
 /*===========================================================================*
  *                                   panic                                   *
  *===========================================================================*/
-PUBLIC void panic(s,n)
-_CONST char *s;
-int n;
+PUBLIC void panic(mess,nr)
+_CONST char *mess;
+int nr;
 {
 /* The system has run aground of a fatal kernel error. Terminate execution. */
   static int panicking = 0;
   if (panicking ++) return;            /* prevent recursive panics */
 
-  if (s != NULL) {
-       kprintf("\nKernel panic: %s", karg(s));
-       if (n != NO_NUM) kprintf(" %d", n);
+  if (mess != NULL) {
+       kprintf("\nKernel panic: %s", mess);
+       if (nr != NO_NUM) kprintf(" %d", nr);
        kprintf("\n",NO_NUM);
   }
   prepare_shutdown(RBT_PANIC);
 }
 
 
+/*===========================================================================*
+ *                             kprintf                                      *
+ *===========================================================================*/
+PUBLIC void kprintf(const char *fmt, ...)      /* format to be printed */
+{
+  int c;                                       /* next character in fmt */
+  unsigned long u;                             /* hold number argument */
+  int base;                                    /* base of number arg */
+  int negative = 0;                            /* print minus sign */
+  static char x2c[] = "0123456789ABCDEF";      /* nr conversion table */
+  char ascii[8 * sizeof(long) / 3 + 2];                /* string for ascii number */
+  char *s = NULL;                              /* string to be printed */
+  va_list argp;                                        /* optional arguments */
+  
+  va_start(argp, fmt);                         /* init variable arguments */
+
+  while((c=*fmt++) != 0) {
+
+      if (c == '%') {                          /* expect format '%key' */
+          switch(c = *fmt++) {                 /* determine what to do */
+
+          /* Known keys are %d, %u, %x, %s, and %%. This is easily extended 
+           * with number types like %b and %o by providing a different base.
+           * Number type keys don't set a string to 's', but use the general
+           * conversion after the switch statement.
+           */ 
+          case 'd':                            /* output decimal */
+              u = va_arg(argp, int);
+              if (u < 0) { negative = 1; u = -u; }
+              base = 10;
+              break;
+          case 'u':                            /* output unsigned long */
+              u = va_arg(argp, unsigned long);
+              base = 10;
+              break;
+          case 'x':                            /* output hexadecimal */
+              u = va_arg(argp, unsigned long);
+              base = 0x10;
+              break;
+          case 's':                            /* output string */
+              s = va_arg(argp, char *);
+              if (s == NULL) s = "(null)";
+              break;
+          case '%':                            /* output percent */
+              s = "%";                          
+              break;                   
+
+          /* Unrecognized key. */
+          default:                             /* echo back %key */
+              s = "%?";                                
+              s[1] = c;                                /* set unknown key */
+          }
+
+          /* Assume a number if no string is set. Convert to ascii. */
+          if (s == NULL) {
+              s = ascii + sizeof(ascii)-1;
+              *s = 0;                  
+              do {  *--s = x2c[(u % base)]; }  /* work backwards */
+              while ((u /= base) > 0); 
+          }
+
+          /* This is where the actual output for format "%key" is done. */
+          if (negative) kputc('-');            /* print sign if negative */
+          while(*s != 0) { kputc(*s++); }      /* print string/ number */
+      }
+      else {
+          kputc(c);                            /* print and continue */
+      }
+  }
+  kputc(END_OF_KMESS);                         /* terminate output */
+  va_end(argp);                                        /* end variable arguments */
+}
+
+
+/*===========================================================================*
+ *                                 kputc                                    *
+ *===========================================================================*/
+PRIVATE void kputc(c)
+int c;                                 /* character to append */
+{
+/* Accumulate a single character for a kernel message. Send a notification
+ * the to PRINTF_PROC driver if an END_OF_KMESS is encountered. 
+ */
+  if (c != END_OF_KMESS) {
+      kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
+      if (kmess.km_size < KMESS_BUF_SIZE)
+          kmess.km_size += 1;          
+      kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
+  } else {
+      send_sig(PRINTF_PROC, SIGKMESS);
+  }
+}
+
+
 
 #if TEMP_CODE