]> Zhao Yanbai Git Server - minix.git/commitdiff
New NOTIFY system call! Queued at kernel. Duplicate messages (with same source
authorJorrit Herder <jnherder@minix3.org>
Tue, 24 May 2005 10:06:17 +0000 (10:06 +0000)
committerJorrit Herder <jnherder@minix3.org>
Tue, 24 May 2005 10:06:17 +0000 (10:06 +0000)
and type) are overwritten with newer flags/ arguments. The interface from
within the kernel is lock_notify(). User processes can make a system call with
notify(). NOTIFY fully replaces the old notification mechanism.

22 files changed:
commands/reboot/halt.c
drivers/at_wini/at_wini.c
include/ibm/interrupt.h
include/minix/com.h
include/minix/config.h
include/minix/type.h
kernel/clock.c
kernel/const.h
kernel/glo.h
kernel/i8259.c
kernel/klibc.c
kernel/main.c
kernel/misc.c
kernel/mpx386.s
kernel/proc.c
kernel/proc.h
kernel/proto.h
kernel/system.c
kernel/system/clock.c
kernel/type.h
servers/is/dmp.c
test/Makefile

index 6fbdca4bdd87fcd05778bf9a8ee0c6ce701b86e6..f5cab5a3b14c28c17c351a256488918a565d3b5d 100755 (executable)
@@ -127,7 +127,7 @@ char **argv;
     /* Give everybody a chance to die peacefully. */
     printf("Sending SIGTERM to all processes ...\n");
     kill(-1, SIGTERM);
-    sleep(3);
+    sleep(2);
   }
 
   reboot(flag, monitor_code, strlen(monitor_code));
index aa0390d20c0e0727d404684554a1bf4a60f68c57..86f36695283fcd88485b959d6f681a65fc43234f 100644 (file)
@@ -833,6 +833,10 @@ PRIVATE void w_intr_wait()
                } else if (m.m_type == HARD_INT) {
                    sys_inb((w_wn->base + REG_STATUS), &w_status);
                }
+               else {
+                       printf("AT_WINI got unexpected message %d from %d\n",
+                               m.m_type, m.m_source);
+               }
        }
   } else {
        /* Interrupt not yet allocated; use polling. */
index deb9c46cf4930464fb28ead985b24becc431730c..40ad5b114841126c4e40afdc54558f7a10ea8779 100644 (file)
@@ -12,7 +12,7 @@
 #define INT2_CTLMASK    0xA1   /* setting bits in this port disables ints */
 
 /* Magic numbers for interrupt controller. */
-#define ENABLE          0x20   /* code used to re-enable after an interrupt */
+#define END_OF_INT      0x20   /* code used to re-enable after an interrupt */
 
 
 /* Interrupt vectors defined/reserved by processor. */
index f04c220f24b015c14a10140d7e8094b3da52b801..a7a5ad8e45e6a38c17ce3cd9ad7bc9829ce15904 100755 (executable)
 #define NR_NOTIFY_TYPES               5        /* nr of bits in mask */
 
 /* Shorthands for message parameters passed with notifications. */
-#define NOTIFY_TYPE    m2_i1
-#define NOTIFY_FLAGS   m2_i2
-#define NOTIFY_ARG     m2_i3
+#define NOTIFY_SOURCE  m_source
+#define NOTIFY_TYPE    m_type
+#define NOTIFY_FLAGS   m2_i1
+#define NOTIFY_ARG     m2_l1
 
 
 /*===========================================================================*
index f62bc7d3c655d8e97af107ee66dcf9c92c47df58..90d5b21c74937841c83b73b16a88fb9a2b574de1 100755 (executable)
@@ -3,7 +3,7 @@
 
 /* Minix release and version numbers. */
 #define OS_RELEASE "3"
-#define OS_VERSION "0.3"
+#define OS_VERSION "0.4"
 
 /* This file sets configuration parameters for the MINIX kernel, FS, and PM.
  * It is divided up into two main sections.  The first section contains
index 6b53612afee1e38f0e1a728311236c60cc54dbf9..ae322e01f12449d687543e5b6b9bd8c818adbe5e 100755 (executable)
@@ -106,6 +106,7 @@ struct kinfo {
   long notify_blocked;
   long notify_switching;
   long notify_reenter;
+  long notify_taskcall;
   long notify_ok;
   long notify_unhold;
   long notify_int;
index c41119beefac23d6bd95ea82898c6b69973959ba..77a90934872bf51fd86af63a27286f339adf1730 100755 (executable)
@@ -128,7 +128,7 @@ PUBLIC void clock_task()
        */
       if (result != EDONTREPLY) {
           m.m_type = result;
-          lock_send(proc_addr(CLOCK), m.m_source, &m);
+          lock_send(CLOCK, m.m_source, &m);
       }
   }
 }
@@ -222,6 +222,7 @@ irq_hook_t *hook;
  */
   register struct proc *rp;
   register unsigned ticks;
+  message m;
   clock_t now;
 
   /* Acknowledge the PS/2 clock interrupt. */
@@ -247,7 +248,8 @@ irq_hook_t *hook;
   if (next_timeout <= now || (sched_ticks == 1 && bill_ptr == prev_ptr
           && rdy_head[PPRI_USER] != NIL_PROC))
   {  
-      lock_notify(CLOCK, HARD_INT);
+      m.NOTIFY_TYPE = HARD_INT;
+      lock_notify(HARDWARE, CLOCK, &m);
   } 
   else if (--sched_ticks == 0) {
       sched_ticks = SCHED_RATE;        /* reset quantum */
index 3aa549e435325432d7073cb187880293831f5ab8..b120f02b3ee78719e120781a9333a96c9d6ed0b6 100755 (executable)
 /* How many IRQ hooks are there in total. */
 #define NR_IRQ_HOOKS     16
 
-/* How many notification buffers (12B each) should there be? */
-#define NR_NOTIFY_BUFS  128
+/* How many buffers for notification messages should there be? */
+#define NR_NOTIFY_BUFS   64
+
+/* Constants and macros for bit map manipulation. */
+#define BITCHUNK_BITS   (sizeof(bitchunk_t) * CHAR_BIT)
+#define BITMAP_CHUNKS(nr_bits) (((nr_bits)+BITCHUNK_BITS-1)/BITCHUNK_BITS)  
+#define MAP_CHUNK(map,bit) (map)[((bit)/BITCHUNK_BITS)]
+#define CHUNK_OFFSET(bit) ((bit)%BITCHUNK_BITS))
+#define GET_BIT(map,bit) ( MAP_CHUNK(map,bit) & (1 << CHUNK_OFFSET(bit) )
+#define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) )
+#define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) )
 
 /* Program stack words and masks. */
 #define INIT_PSW      0x0200   /* initial psw */
index 68ba887e899e0394ff9f88e206b8eb759127d2d7..41eae15f50ca9fffb119b26bec07c08b95d5c621 100755 (executable)
@@ -23,17 +23,12 @@ EXTERN struct machine machine;      /* machine information for users */
 EXTERN struct kmessages kmess;  /* diagnostic messages in kernel */
 EXTERN struct memory mem[NR_MEMS];     /* base and size of chunks of memory */
 
-/* Low level notifications may be put on the 'held' queue to prevent races. */
-EXTERN struct proc *held_head; /* head of queue of held-up interrupts */
-EXTERN struct proc *held_tail; /* tail of queue of held-up interrupts */
-EXTERN unsigned char k_reenter;        /* kernel reentry count (entry count less 1)*/
-EXTERN unsigned char switching;        /* nonzero if process switching in progress */
-
 /* Process table.  Here to stop too many things having to include proc.h. */
 EXTERN struct proc *proc_ptr;  /* pointer to currently running process */
 
 /* Miscellaneous. */
-EXTERN unsigned lost_ticks;    /* clock ticks counted outside the clock task */
+EXTERN char k_reenter;         /* kernel reentry count (entry count less 1) */
+EXTERN unsigned lost_ticks;    /* clock ticks counted outside clock task */
 
 #if (CHIP == INTEL)
 
index a752c6bd4093eb7a70774865710e5674111c14c7..7bc396bf640f6bbff97b671b06b40e7071c0eb7e 100755 (executable)
 #define ICW1_AT         0x11   /* edge triggered, cascade, need ICW4 */
 #define ICW1_PC         0x13   /* edge triggered, no cascade, need ICW4 */
 #define ICW1_PS         0x19   /* level triggered, cascade, need ICW4 */
-#define ICW4_AT         0x01   /* not SFNM, not buffered, normal EOI, 8086 */
-#define ICW4_PC         0x09   /* not SFNM, buffered, normal EOI, 8086 */
+#define ICW4_AT_SLAVE   0x01   /* not SFNM, not buffered, normal EOI, 8086 */
+#define ICW4_AT_MASTER  0x05   /* not SFNM, not buffered, normal EOI, 8086 */
+#define ICW4_PC_SLAVE   0x09   /* not SFNM, buffered, normal EOI, 8086 */
+#define ICW4_PC_MASTER  0x0D   /* not SFNM, buffered, normal EOI, 8086 */
 
 #if _WORD_SIZE == 2
 typedef _PROTOTYPE( void (*vecaddr_t), (void) );
@@ -54,13 +56,13 @@ int mine;
        outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
                                                        /* ICW2 for master */
        outb(INT_CTLMASK, (1 << CASCADE_IRQ));          /* ICW3 tells slaves */
-       outb(INT_CTLMASK, ICW4_AT);
+       outb(INT_CTLMASK, ICW4_AT_MASTER);
        outb(INT_CTLMASK, ~(1 << CASCADE_IRQ));         /* IRQ 0-7 mask */
        outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
        outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
                                                        /* ICW2 for slave */
        outb(INT2_CTLMASK, CASCADE_IRQ);                /* ICW3 is slave nr */
-       outb(INT2_CTLMASK, ICW4_AT);
+       outb(INT2_CTLMASK, ICW4_AT_SLAVE);
        outb(INT2_CTLMASK, ~0);                         /* IRQ 8-15 mask */
 
        /* Copy the BIOS vectors from the BIOS to the Minix location, so we
index 609bff7d5788e2fc5a8a1d3fdfda95d0a5bde29b..9bdb54775e5c8839b0e746e1cfdd218939ffba3d 100644 (file)
@@ -154,13 +154,15 @@ int c;                                    /* character to append */
 /* Accumulate a single character for a kernel message. Send a notification
  * the to TTY driver if the buffer if a END_OF_KMESS is encountered. 
  */
+  message m;
   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 {
-      lock_notify(TTY, NEW_KMESS);     /* let TTY display the message */
+      m.NOTIFY_TYPE = NEW_KMESS;
+      lock_notify(HARDWARE, TTY, &m);
   }
 }
 
index 9cd66d332d784d82cc50945bb3aad922e5125fdf..3b29037b8b03ba372610df19e7d84e7f3073ab9e 100755 (executable)
@@ -217,6 +217,7 @@ int how;            /* 0 = halt, 1 = reboot, 2 = panic!, ... */
  * sure it is only executed once. Unless a CPU exception occurred, the 
  * stop_sequence() is started. 
  */
+  message m;
   if (shutting_down)
        return;
 
@@ -225,7 +226,6 @@ int how;            /* 0 = halt, 1 = reboot, 2 = panic!, ... */
    * We rely on TTY to call sys_abort() when it is done with the dumps.
    */
   if (how == RBT_PANIC) {
-      message m;
       m.m_type = PANIC_DUMPS;
       if (nb_send(TTY, &m) == OK)      /* don't block if TTY isn't ready */
           return;                      /* await sys_abort() from TTY */
@@ -234,7 +234,8 @@ int how;            /* 0 = halt, 1 = reboot, 2 = panic!, ... */
   /* The TTY expects two HARD_STOP notifications. One to switch to the 
    * primary console for stop sequence output, and one to actually exit.
    */
-  lock_notify(TTY, HARD_STOP);         /* let TTY switch to console 0 */
+  m.NOTIFY_TYPE = HARD_STOP;
+  lock_notify(HARDWARE, TTY, &m);
 
   /* Run the stop sequence. The timer argument passes the shutdown status.
    * The stop sequence is skipped for fatal CPU exceptions.
@@ -266,6 +267,7 @@ timer_t *tp;
   static int level = P_SERVER;         /* start at the highest level */
   static struct proc *p = NIL_PROC;    /* next process to stop */
   static char *types[] = {"task","system","driver","server","user"}; 
+  static message m;
 
   /* See if the last process' shutdown was successful. Else, force exit. */
   if (p != NIL_PROC) { 
@@ -288,7 +290,9 @@ timer_t *tp;
           kprintf("- Stopping %s ", karg(p->p_name));
           kprintf("%s ... ", karg(types[p->p_type]));
           shutdown_process = p;                /* directly continue if exited */
-          lock_notify(proc_number(p), HARD_STOP);
+          m.NOTIFY_TYPE = HARD_STOP;
+          m.NOTIFY_ARG = tmr_arg(tp)->ta_int;          /* how */
+          lock_notify(HARDWARE, proc_number(p), &m);
           set_timer(tp, get_uptime()+STOP_TICKS, stop_sequence);
           return;                      /* allow the process to shut down */ 
       } 
@@ -330,7 +334,7 @@ PRIVATE void shutdown(int how)
         * For RBT_MONITOR, the MM has provided the program.
         */
        if (how == RBT_HALT) {
-               phys_copy(vir2phys("delay;"), kinfo.params_base, 7); 
+               phys_copy(vir2phys("delay;menu"), kinfo.params_base, 11); 
        } else if (how == RBT_REBOOT) {
                phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
        }
index a7b48bf8290f83e2517ff99b9d49df515943182b..c4b8195cac0e598841e91e593576add47780ee6b 100755 (executable)
@@ -2,6 +2,9 @@
  *   panic         abort MINIX due to a fatal error
  *   bad_assertion  for debugging
  *   bad_compare    for debugging
+ *   alloc_bit      bit map manipulation
+ *   free_bit       bit map manipulation
+ *   print_bitmap   bit map manipulation
  */
 
 #include "kernel.h"
@@ -35,6 +38,78 @@ int n;
 }
 
 
+/*===========================================================================*
+ *                        print_bitmap                                      * 
+ *===========================================================================*/
+PUBLIC void print_bitmap(bitmap, nr_bits)
+bitchunk_t *bitmap; 
+bit_t nr_bits;
+{
+    bit_t bit_i;
+    
+    for (bit_i=0; bit_i < nr_bits; bit_i++) {
+
+        kprintf("%d", GET_BIT(bitmap, bit_i) > 0 );
+        if (! ((bit_i+1) % 8) )   kprintf(" ", NO_ARG);
+        if (! ((bit_i+1) % 64) )   kprintf("\n", NO_ARG);
+    }
+    kprintf("\n", NO_ARG);
+}
+
+/*===========================================================================*
+ *                             free_bit                                     * 
+ *===========================================================================*/
+PUBLIC void free_bit(bit_nr, bitmap, nr_bits) 
+bit_t bit_nr;
+bitchunk_t *bitmap;
+bit_t nr_bits;
+{
+  bitchunk_t *chunk;
+  if (bit_nr >= nr_bits) {
+       kprintf("Warning, free_bit: %d illegal index\n", bit_nr);
+       return;
+  }
+  chunk = &bitmap[(bit_nr/BITCHUNK_BITS)];
+  *chunk &= ~(1 << (bit_nr % BITCHUNK_BITS));
+}
+
+/*===========================================================================*
+ *                             alloc_bit                                    * 
+ *===========================================================================*/
+PUBLIC int alloc_bit(bitmap, nr_bits) 
+bitchunk_t *bitmap;
+bit_t nr_bits;
+{
+    bitchunk_t *chunk;
+    int nr_chunks;
+    int bit_nr;
+    int i;
+    
+    /* Iterate over the words in block. */
+    nr_chunks = BITMAP_CHUNKS(nr_bits);
+    for (chunk = &bitmap[0]; chunk < &bitmap[nr_chunks]; chunk++) {
+
+        /* Does this chunk contain a free bit? */
+        if (*chunk == (bitchunk_t) ~0) continue;
+        
+        /* Get bit number from the start of the bit map. */
+        for (i = 0; (*chunk & (1 << i)) != 0; ++i) {}
+        bit_nr = (chunk - &bitmap[0]) * BITCHUNK_BITS + i;
+        
+        /* Don't allocate bits beyond the end of the map. */
+        if (bit_nr >= nr_bits) break;
+
+        *chunk |= 1 << bit_nr % BITCHUNK_BITS;
+        return(bit_nr);        
+        
+    }
+    kprintf("Warning, all %d bits in map busy\n", nr_bits);
+    return(-1);    
+}
+
+
+
+
 #if !NDEBUG
 /*=========================================================================*
  *                             bad_assertion                              *
index efebfbfad8fbd1bf9428d6cb1a4bdd493ab22418..1cd4140bd61ab56a6990a241cf78d02a7d3ed7dd 100755 (executable)
@@ -55,6 +55,7 @@ begbss:
 #include <minix/config.h>
 #include <minix/const.h>
 #include <minix/com.h>
+#include <ibm/interrupt.h>
 #include "const.h"
 #include "protect.h"
 #include "sconst.h"
@@ -212,24 +213,48 @@ csinit:
 !*                             hwint00 - 07                                 *
 !*===========================================================================*
 ! Note this is a macro, it just looks like a subroutine.
-#define hwint_master(irq)      \
+#define hwint_master_slave_fail(irq)   \
        call    save                    /* save interrupted process state */;\
-       inb     INT_CTLMASK                                                 ;\
-       orb     al, [1<<irq]                                                ;\
-       outb    INT_CTLMASK             /* disable the irq                */;\
-       movb    al, ENABLE                                                  ;\
+       cli                             ;\
+       inb     INT2_CTLMASK            /* get current mask */              ;\
+       movb    ah, al                  ;\
+       inb     INT_CTLMASK             /* get current mask */              ;\
+       push    eax                     ;\
+       cli                             ;\
+       movb    al, ~[0]                ;\
+       outb    INT_CTLMASK             /* mask all */;\
+       outb    INT2_CTLMASK            /* */;\
+       cli                             ;\
+       push    (_irq_handlers+4*irq)   /* irq_handlers[irq]              */;\
+       call    _intr_handle            /* intr_handle(irq_handlers[irq]) */;\
+       pop     ecx                                                         ;\
+       pop     eax                                                         ;\
+       cmp     (_irq_actids+4*irq), 0  /* interrupt still active?        */;\
+       jz      0f                                                          ;\
+       or      eax, [1<<irq]           /* mask irq */                      ;\
+0:     outb    INT_CTLMASK             /* restore master irq mask */;\
+       movb    al, ah                  ;\
+       outb    INT2_CTLMASK            /* restore slave irq mask */;\
+       movb    al, END_OF_INT                                              ;\
        outb    INT_CTL                 /* reenable master 8259           */;\
+       cmp     (irq), 8                ;\
+       jb      1f                      ;\
+       outb    INT2_CTL                /* reenable slave 8259            */;\
+1:     ret                             /* restart (another) process      */
+
+#define hwint_master(irq)      \
+       call    save                    /* save interrupted process state */;\
        push    (_irq_handlers+4*irq)   /* irq_handlers[irq]              */;\
-       sti                             /* enable interrupts              */;\
        call    _intr_handle            /* intr_handle(irq_handlers[irq]) */;\
-       cli                             /* disable interrupts             */;\
        pop     ecx                                                         ;\
        cmp     (_irq_actids+4*irq), 0  /* interrupt still active?        */;\
-       jnz     0f                                                          ;\
-       inb     INT_CTLMASK                                                 ;\
-       andb    al, ~[1<<irq]                                               ;\
-       outb    INT_CTLMASK             /* enable the irq                 */;\
-0:     ret                             /* restart (another) process      */
+       jz      0f                                                          ;\
+       inb     INT_CTLMASK             /* get current mask */              ;\
+       orb     al, [1<<irq]            /* mask irq */                      ;\
+       outb    INT_CTLMASK             /* disable the irq                */;\
+0:     movb    al, END_OF_INT                                              ;\
+       outb    INT_CTL                 /* reenable master 8259           */;\
+       ret                             /* restart (another) process      */
 
 ! Each of these entry points is an expansion of the hwint_master macro
        .align  16
@@ -270,23 +295,18 @@ _hwint07:         ! Interrupt routine for irq 7 (printer)
 ! Note this is a macro, it just looks like a subroutine.
 #define hwint_slave(irq)       \
        call    save                    /* save interrupted process state */;\
-       inb     INT2_CTLMASK                                                ;\
-       orb     al, [1<<[irq-8]]                                            ;\
-       outb    INT2_CTLMASK            /* disable the irq                */;\
-       movb    al, ENABLE                                                  ;\
-       outb    INT_CTL                 /* reenable master 8259           */;\
        push    (_irq_handlers+4*irq)   /* irq_handlers[irq]              */;\
-       outb    INT2_CTL                /* reenable slave 8259            */;\
-       sti                             /* enable interrupts              */;\
        call    _intr_handle            /* intr_handle(irq_handlers[irq])         */;\
-       cli                             /* disable interrupts             */;\
        pop     ecx                                                         ;\
        cmp     (_irq_actids+4*irq), 0  /* interrupt still active?        */;\
-       jnz     0f                                                          ;\
+       j     0f                                                          ;\
        inb     INT2_CTLMASK                                                ;\
-       andb    al, ~[1<<[irq-8]]                                           ;\
-       outb    INT2_CTLMASK            /* enable the irq                 */;\
-0:     ret                             /* restart (another) process      */
+       orb     al, [1<<[irq-8]]                                            ;\
+       outb    INT2_CTLMASK            /* disable the irq                */;\
+0:     movb    al, END_OF_INT                                              ;\
+       outb    INT_CTL                 /* reenable master 8259           */;\
+       outb    INT2_CTL                /* reenable slave 8259            */;\
+       ret                             /* restart (another) process      */
 
 ! Each of these entry points is an expansion of the hwint_slave macro
        .align  16
@@ -375,7 +395,6 @@ _p_s_call:
        mov     esp, k_stktop
        xor     ebp, ebp        ! for stacktrace
                                ! end of inline save
-       sti                     ! allow SWITCHER to be interrupted
                                ! now set up parameters for sys_call()
        push    ebx             ! pointer to user message
        push    eax             ! src/dest
@@ -383,7 +402,6 @@ _p_s_call:
        call    _sys_call       ! sys_call(function, src_dest, m_ptr)
                                ! caller is now explicitly in proc_ptr
        mov     AXREG(esi), eax ! sys_call MUST PRESERVE si
-       cli                     ! disable interrupts 
 
 ! Fall into code to restart proc/task running.
 
@@ -392,17 +410,8 @@ _p_s_call:
 !*===========================================================================*
 _restart:
 
-! Flush any held-up notifications.
-! This reenables interrupts, so the current interrupt handler may reenter.
-! This does not matter, because the current handler is about to exit and no
-! other handlers can reenter since flushing is only done when k_reenter == 0.
-
-       cmp     (_held_head), 0 ! do fast test to usually avoid function call
-       jz      over_call_unhold
-       cmp     (_switching), 0 ! do fast test to usually avoid function call
-       jnz     over_call_unhold
-       call    _unhold         ! this is rare so overhead acceptable
-over_call_unhold:
+! Restart the current process or the next process if it is set. 
+
        mov     esp, (_proc_ptr)        ! will assume P_STACKBASE == 0
        lldt    P_LDT_SEL(esp)          ! enable segment descriptors for task
        lea     eax, P_STACKTOP(esp)    ! arrange for next interrupt
@@ -522,7 +531,6 @@ exception1:                         ! Common for all exceptions.
        call    _exception              ! (ex_number, trap_errno, old_eip,
                                        !       old_cs, old_eflags)
        add     esp, 5*4
-       cli
        ret
 
 !*===========================================================================*
index 8c92ee87f566e9365fd69bac0fb09f3babc6667f..b103ff2c7611031814f475ba4585e5b9cc3ef54d 100755 (executable)
@@ -1,27 +1,24 @@
 /* This file contains essentially all of the process and message handling.
- * It has two main entry points from the outside:
+ * It has one main entry point from the outside:
  *
- *   sys_call:              a system call, that is, the kernel is trapped with an INT 
- *   lock_notify:    send a notification to inform a process of a system event
+ *   sys_call:               a system call, i.e., the kernel is trapped with an INT 
  *
  * It also has several minor entry points to be used from the task level:
  *
+ *   lock_notify:     send a notification to inform a process of a system event
  *   lock_send:              send a message to a process
  *   lock_ready:      put a process on one of the ready queues so it can be run
  *   lock_unready:    remove a process from the ready queues
  *   lock_sched:      a process has run too long; schedule another one
  *   lock_pick_proc:  pick a process to run (used by system initialization)
- *   unhold:          repeat all held-up notifications
  *
  * Changes:
+ *   May 24, 2005     new, queued NOTIFY system call  (Jorrit N. Herder)
  *   Oct 28, 2004     non-blocking SEND and RECEIVE  (Jorrit N. Herder)
  *   Oct 28, 2004     rewrite of sys_call()  (Jorrit N. Herder)
  *   Oct 10, 2004     require BOTH for kernel sys_call()  (Jorrit N. Herder)
  *                   (to protect kernel tasks from being blocked)
- *   Sep 25, 2004     generalized notify() function  (Jorrit N. Herder)
- *   Sep 23, 2004     removed PM sig check in mini_rec()  (Jorrit N. Herder)
  *   Aug 19, 2004     generalized ready()/unready()  (Jorrit N. Herder)
- *   Aug 18, 2004     added notify() function  (Jorrit N. Herder) 
  */
 
 #include "kernel.h"
 #include "sendmask.h"
 
 
-FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dest,
+/* Scheduling and message passing functions. The functions are available to 
+ * other parts of the kernel through lock_...(). The lock temporarily disables 
+ * interrupts to prevent race conditions. 
+ */
+FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst,
                message *m_ptr, int may_block) );
 FORWARD _PROTOTYPE( int mini_rec, (struct proc *caller_ptr, int src,
                message *m_ptr, int may_block) );
-FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dest,
+FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst,
                message *m_ptr ) );
+
 FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
 FORWARD _PROTOTYPE( void sched, (void) );
 FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
 FORWARD _PROTOTYPE( void pick_proc, (void) );
-FORWARD _PROTOTYPE( int alloc_notify_buf, (void) ); 
-FORWARD _PROTOTYPE( void free_notify_buf, (int index) ); 
 
 #if (CHIP == M68000)
 FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m,
@@ -61,161 +61,9 @@ FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m,
 #endif /* (CHIP == M68000) */
 
 
-/* Bit mask operations used to bits of the notification mask. */
-#define set_bit(mask, n)       ((mask) |= (1 << (n)))
-#define clear_bit(mask, n)     ((mask) &= ~(1 << (n)))
-#define isset_bit(mask, n)     ((mask) & (1 << (n)))
-
-/* Constants and macros for the notification bit map. */
-#define BITCHUNK_BITS   (sizeof(bitchunk_t) * CHAR_BIT)
-#define BITMAP_CHUNKS   ((NR_NOTIFY_BUFS + BITCHUNK_BITS - 1)/BITCHUNK_BITS)  
-
-#define MAP_CHUNK(map,bit) (map)[((bit)/BITCHUNK_BITS)]
-#define CHUNK_OFFSET(bit) ((bit)%BITCHUNK_BITS))
-
-#define GET_BIT(map,bit) ( MAP_CHUNK(map,bit) & (1 << CHUNK_OFFSET(bit) )
-#define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) )
-#define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) )
-
-/* Declare buffer space for notifications and bit map for administration. */
+/* Declare buffer space and a bit map for notification messages. */
 PRIVATE struct notification notify_buffer[NR_NOTIFY_BUFS];
-PRIVATE bitchunk_t notify_bitmap[BITMAP_CHUNKS];     
-
-
-/*===========================================================================*
- *                        free_notify_buf                                   * 
- *===========================================================================*/
-PRIVATE void free_notify_buf(buf_index) 
-int buf_index;                         /* buffer to release */
-{
-  bitchunk_t *chunk;
-  if (buf_index >= NR_NOTIFY_BUFS) return;
-  chunk = &notify_bitmap[(buf_index/BITCHUNK_BITS)];
-  *chunk &= ~(buf_index % BITCHUNK_BITS);
-}
-
-/*===========================================================================*
- *                        alloc_notify_buf                                  * 
- *===========================================================================*/
-PRIVATE int alloc_notify_buf() 
-{
-    bitchunk_t *chunk;
-    int i, bit_nr;
-    
-    /* Iterate over the words in block. */
-    for (chunk = &notify_bitmap[0]; 
-            chunk < &notify_bitmap[BITMAP_CHUNKS]; chunk++) {
-
-        /* Does this chunk contain a free bit? */
-        if (*chunk == (bitchunk_t) ~0) continue;
-        
-        /* Get bit number from the start of the bit map. */
-        for (i = 0; (*chunk & (1 << i)) != 0; ++i) {}
-        bit_nr = (chunk - &notify_bitmap[0]) * BITCHUNK_BITS + i;
-        
-        /* Don't allocate bits beyond the end of the map. */
-        if (bit_nr >= NR_NOTIFY_BUFS) break;
-
-        *chunk |= 1 << bit_nr % BITCHUNK_BITS;
-        kprintf("Allocated bit %d\n", bit_nr);
-        return(bit_nr);        
-        
-    }
-    return(-1);    
-}
-
-
-
-/*===========================================================================*
- *                                 lock_notify                              * 
- *===========================================================================*/
-PUBLIC void lock_notify(proc_nr, notify_type)
-int proc_nr;                   /* number of process to be started */
-int notify_type;               /* notification to be sent */
-{
-/* A system event has occurred. Send a notification with source HARDWARE to
- * the given process. The notify() function was carefully designed so that it
- * (1) can be used safely from both interrupt handlers and the task level, and
- * (2) realizes asynchronous message passing with at least once semantics, 
- * that is, the notifications are not queued. If a race condition occurs, the
- * notification is queued and repeated later by unhold(). If the receiver is
- * not ready, the notification is blocked and checked later in receive().   
- */
-  register struct proc *rp;    /* pointer to task's proc entry */
-  message m;                   /* message to send the notification */
-  unsigned int notify_bit;     /* bit for this notification */
-
-  /* Get notify bit and process pointer. */
-  notify_bit = (unsigned int) (notify_type  & ~NOTIFICATION);
-  rp = proc_addr(proc_nr);
-
-  /* If this call would compete with other process-switching functions, put
-   * it on the 'held' queue to be flushed at the next non-competing restart().
-   * The competing conditions are:
-   * (1) k_reenter == (typeof k_reenter) -1:
-   *     Call from the task level, typically from an output interrupt 
-   *     routine. An interrupt handler might reenter notify(). Rare,
-   *     so not worth special treatment.
-   * (2) k_reenter > 0:
-   *     Call from a nested interrupt handler. A previous interrupt 
-   *     handler might be inside notify() or sys_call().
-   * (3) switching != 0:
-   *     A process-switching function other than notify() is being called 
-   *     from the task level, typically sched() from CLOCK. An interrupt
-   *    handler might call notify() and pass the 'k_reenter' test.
-   */
-  if (k_reenter != 0 || switching) {
-       kinfo.notify_held ++;
-       if (switching) kinfo.notify_switching ++;
-       if (k_reenter > 0) kinfo.notify_reenter ++;
-       switch(notify_type) {
-       case HARD_INT: kinfo.notify_int ++; break;
-       case HARD_STOP: kinfo.notify_stop ++; break;
-       case SYN_ALARM: kinfo.notify_alarm ++; break;
-       case KSIG_PENDING: kinfo.notify_sig ++; break;
-       case NEW_KMESS: kinfo.notify_kmess ++; break;
-       }
-       lock(); 
-                               /* already on held queue? */
-       if (! isset_bit(rp->p_ntf_held, notify_bit)) {
-               if (held_head != NIL_PROC)
-                       held_tail->p_ntf_nextheld = rp;
-               else
-                       held_head = rp;
-               held_tail = rp;
-               rp->p_ntf_nextheld = NIL_PROC;
-       }
-       set_bit(rp->p_ntf_held, notify_bit);    /* add bit to held mask */
-       unlock();
-       return;
-  }
-
-  /* If process is not waiting for a notification, record the blockage. Else, 
-   * send it a message with source HARDWARE and type 'notify_type'. No more 
-   * information can be reliably provided since notifications are not queued.
-   */
-  switching = TRUE;
-
-  if ( (rp->p_flags & (RECEIVING | SENDING)) != RECEIVING ||
-      !isrxhardware(rp->p_getfrom)) {
-       kinfo.notify_blocked ++;
-       set_bit(rp->p_ntf_blocked, notify_bit);     /* update blocked mask */
-  } else {
-
-      /* Assemble notification message and send it. */
-      m.m_source = HARDWARE;           
-      m.m_type = notify_type;
-      CopyMess(HARDWARE, proc_addr(HARDWARE), &m, rp, rp->p_messbuf);
-      clear_bit(rp->p_ntf_blocked, notify_bit);
-      rp->p_flags &= ~RECEIVING;
-      kinfo.notify_ok ++;
-
-      /* Announce the process ready and select a fresh process to run. */
-      ready(rp);                       
-      pick_proc();
-  }
-  switching = FALSE;
-}
+PRIVATE bitchunk_t notify_bitmap[BITMAP_CHUNKS(NR_NOTIFY_BUFS)];     
 
 
 /*===========================================================================*
@@ -223,7 +71,7 @@ int notify_type;             /* notification to be sent */
  *===========================================================================*/
 PUBLIC int sys_call(call_nr, src_dst, m_ptr)
 int call_nr;                   /* (NB_)SEND, (NB_)RECEIVE, BOTH */
-int src_dst;                   /* source to receive from or dest to send to */
+int src_dst;                   /* src to receive from or dst to send to */
 message *m_ptr;                        /* pointer to message in the caller's space */
 {
 /* System calls are done by trapping to the kernel with an INT instruction.
@@ -298,21 +146,21 @@ message *m_ptr;                   /* pointer to message in the caller's space */
 /*===========================================================================*
  *                             mini_send                                    * 
  *===========================================================================*/
-PRIVATE int mini_send(caller_ptr, dest, m_ptr, may_block)
+PRIVATE int mini_send(caller_ptr, dst, m_ptr, may_block)
 register struct proc *caller_ptr;      /* who is trying to send a message? */
-int dest;                              /* to whom is message being sent? */
+int dst;                               /* to whom is message being sent? */
 message *m_ptr;                                /* pointer to message buffer */
 int may_block;                         /* (dis)allow blocking */
 {
-/* Send a message from 'caller_ptr' to 'dest'. If 'dest' is blocked waiting
- * for this message, copy the message to it and unblock 'dest'. If 'dest' is
+/* Send a message from 'caller_ptr' to 'dst'. If 'dst' is blocked waiting
+ * for this message, copy the message to it and unblock 'dst'. If 'dst' is
  * not waiting at all, or is waiting for another source, queue 'caller_ptr'.
  */
-  register struct proc *dest_ptr, *next_ptr;
+  register struct proc *dst_ptr, *next_ptr;
   vir_bytes vb;                        /* message buffer pointer as vir_bytes */
   vir_clicks vlo, vhi;         /* virtual clicks containing message to send */
 
-  dest_ptr = proc_addr(dest);  /* pointer to destination's proc entry */
+  dst_ptr = proc_addr(dst);    /* pointer to destination's proc entry */
 
 #if ALLOW_GAP_MESSAGES
   /* This check allows a message to be anywhere in data or stack or gap. 
@@ -335,9 +183,9 @@ int may_block;                              /* (dis)allow blocking */
        return(EFAULT);
 #endif
 
-  /* Check for deadlock by 'caller_ptr' and 'dest' sending to each other. */
-  if (dest_ptr->p_flags & SENDING) {
-       next_ptr = proc_addr(dest_ptr->p_sendto);
+  /* Check for deadlock by 'caller_ptr' and 'dst' sending to each other. */
+  if (dst_ptr->p_flags & SENDING) {
+       next_ptr = proc_addr(dst_ptr->p_sendto);
        while (TRUE) {
                if (next_ptr == caller_ptr) return(ELOCKED);
                if (next_ptr->p_flags & SENDING)
@@ -347,25 +195,25 @@ int may_block;                            /* (dis)allow blocking */
        }
   }
 
-  /* Check to see if 'dest' is blocked waiting for this message. */
-  if ( (dest_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
-       (dest_ptr->p_getfrom == ANY ||
-        dest_ptr->p_getfrom == proc_number(caller_ptr))) {
+  /* Check to see if 'dst' is blocked waiting for this message. */
+  if ( (dst_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
+       (dst_ptr->p_getfrom == ANY ||
+        dst_ptr->p_getfrom == proc_number(caller_ptr))) {
        /* Destination is indeed waiting for this message. */
-       CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dest_ptr,
-                dest_ptr->p_messbuf);
-       dest_ptr->p_flags &= ~RECEIVING;        /* deblock destination */
-       if (dest_ptr->p_flags == 0) ready(dest_ptr);
+       CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dst_ptr,
+                dst_ptr->p_messbuf);
+       dst_ptr->p_flags &= ~RECEIVING; /* deblock destination */
+       if (dst_ptr->p_flags == 0) ready(dst_ptr);
   } else if (may_block) {
        /* Destination is not waiting.  Block and queue caller. */
        caller_ptr->p_messbuf = m_ptr;
        if (caller_ptr->p_flags == 0) unready(caller_ptr);
        caller_ptr->p_flags |= SENDING;
-       caller_ptr->p_sendto= dest;
+       caller_ptr->p_sendto = dst;
 
        /* Process is now blocked.  Put in on the destination's queue. */
-       if ( (next_ptr = dest_ptr->p_caller_q) == NIL_PROC)
-               dest_ptr->p_caller_q = caller_ptr;
+       if ( (next_ptr = dst_ptr->p_caller_q) == NIL_PROC)
+               dst_ptr->p_caller_q = caller_ptr;
        else {
                while (next_ptr->p_sendlink != NIL_PROC)
                        next_ptr = next_ptr->p_sendlink;
@@ -422,6 +270,7 @@ int may_block;                              /* (dis)allow blocking */
     while (*ntf_q_pp) {
        if (src == ANY || src == (*ntf_q_pp)->n_source) {
                /* Found notification. Assemble and copy message. */
+               m.NOTIFY_SOURCE = (*ntf_q_pp)->n_source;
                m.NOTIFY_TYPE = (*ntf_q_pp)->n_type;
                m.NOTIFY_FLAGS = (*ntf_q_pp)->n_flags;
                m.NOTIFY_ARG = (*ntf_q_pp)->n_arg;
@@ -431,28 +280,11 @@ int may_block;                            /* (dis)allow blocking */
                 bit_nr = ((long)(*ntf_q_pp) - (long) &notify_buffer[0]) / 
                         sizeof(struct notification);
                 *ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */
-                free_notify_buf(bit_nr);       /* afterwards: prevent race */
+                free_bit(bit_nr, notify_bitmap, NR_NOTIFY_BUFS);
                 return(OK);                    /* report success */
        }
        ntf_q_pp = &(*ntf_q_pp)->n_next;        /* proceed to next */
     }
-
-    /* Check bit mask for blocked notifications. If multiple bits are set, 
-     * send the first notification encountered; the rest is handled later.
-     * This effectively prioritizes notifications. Notification also have
-     * priority of other messages. 
-     */
-    if (caller_ptr->p_ntf_blocked && isrxhardware(src)) {
-        for (i=0; i<NR_NOTIFY_TYPES; i++) {
-            if (isset_bit(caller_ptr->p_ntf_blocked, i)) {
-                m.m_source = HARDWARE;  
-                m.m_type = NOTIFICATION | i;
-                CopyMess(HARDWARE, proc_addr(HARDWARE), &m, caller_ptr, m_ptr);
-               clear_bit(caller_ptr->p_ntf_blocked, i);
-               return(OK);
-           }
-       }
-    }
   }
 
   /* No suitable message is available.  Block the process trying to receive,
@@ -469,6 +301,7 @@ int may_block;                              /* (dis)allow blocking */
   }
 }
 
+
 /*===========================================================================*
  *                             mini_notify                                  * 
  *===========================================================================*/
@@ -477,48 +310,75 @@ register struct proc *caller_ptr; /* process trying to notify */
 int dst;                               /* which process to notify */
 message *m_ptr;                                /* pointer to message buffer */
 {
-  register struct proc *dest_ptr = proc_addr(dst);
+  register struct proc *dst_ptr = proc_addr(dst);
   register struct notification *ntf_p ;
   register struct notification **ntf_q_pp;
   int ntf_index;
   message ntf_mess;
 
   /* Check to see if target is blocked waiting for this message. */
-  if ( (dest_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
-       (dest_ptr->p_getfrom == ANY ||
-        dest_ptr->p_getfrom == proc_number(caller_ptr))) {
+  if ( (dst_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
+       (dst_ptr->p_getfrom == ANY ||
+        dst_ptr->p_getfrom == proc_number(caller_ptr))) {
+
        /* Destination is indeed waiting for this message. */
-       CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dest_ptr,
-                dest_ptr->p_messbuf);
-       dest_ptr->p_flags &= ~RECEIVING;        /* deblock destination */
-       if (dest_ptr->p_flags == 0) ready(dest_ptr);
-  } else {
+       CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dst_ptr,
+                dst_ptr->p_messbuf);
+       dst_ptr->p_flags &= ~RECEIVING; /* deblock destination */
+       if (dst_ptr->p_flags == 0) ready(dst_ptr);
+  } 
+  /* Destination is not ready. Add the notification to the pending queue. */
+  else {
+       /* Get pointer to notification message. */
+       if (! istaskp(caller_ptr)) {
+           CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, 
+                proc_addr(HARDWARE), &ntf_mess);
+           m_ptr = &ntf_mess;
+       }
 
-       /* See if there is a free notification buffer. */
-       if ((ntf_index = alloc_notify_buf()) < 0) 
-               return(ENOSPC);                 /* should be atomic! */
+       /* Enqueue the message. Existing notifications are overwritten with 
+        * the newer one. New notifications are added to the end of the list.
+        */
+       ntf_q_pp = &dst_ptr->p_ntf_q;
+       while (*ntf_q_pp) {
+               /* Replace notifications with same source and type. */
+               if ((*ntf_q_pp)->n_type == m_ptr->m_type && 
+                   (*ntf_q_pp)->n_source == m_ptr->m_source) {
+                       (*ntf_q_pp)->n_flags = m_ptr->NOTIFY_FLAGS;
+                       (*ntf_q_pp)->n_arg = m_ptr->NOTIFY_ARG;
+                       break;
+               }
+               return(OK);
+       }
 
-       /* Copy details from notification message. */
-       CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, 
-                proc_addr(HARDWARE), &ntf_mess);
+       /* Add to end of queue. Get a free notification buffer. */
+       if ((ntf_index = alloc_bit(notify_bitmap, NR_NOTIFY_BUFS)) < 0) 
+               return(ENOSPC);                 /* should be atomic! */
        ntf_p = &notify_buffer[ntf_index];
        ntf_p->n_source = proc_number(caller_ptr);
-       ntf_p->n_type = ntf_mess.NOTIFY_TYPE;
-       ntf_p->n_flags = ntf_mess.NOTIFY_FLAGS;
-       ntf_p->n_arg = ntf_mess.NOTIFY_ARG;
-
-       /* Enqueue the notification message for later. New notifications
-        * are added to the end of the list. First find the NULL pointer, 
-        * then add the new pointer to the end.
-        */
-       ntf_q_pp = &dest_ptr->p_ntf_q;
-       while (*ntf_q_pp) ntf_q_pp = &(*ntf_q_pp)->n_next;
+       ntf_p->n_type = m_ptr->NOTIFY_TYPE;
+       ntf_p->n_flags = m_ptr->NOTIFY_FLAGS;
+       ntf_p->n_arg = m_ptr->NOTIFY_ARG;
        *ntf_q_pp = ntf_p;
-       ntf_p->n_next = NULL;
   }
   return(OK);
 }
 
+/*==========================================================================*
+ *                             lock_notify                                 *
+ *==========================================================================*/
+PUBLIC int lock_notify(src, dst, m_ptr)
+int src;                       /* who is trying to send a message? */
+int dst;                       /* to whom is message being sent? */
+message *m_ptr;                        /* pointer to message buffer */
+{
+/* Safe gateway to mini_notify() for tasks. */
+  int result;
+  lock();
+  result = mini_notify(proc_addr(src), dst, m_ptr); 
+  unlock();
+  return(result);
+}
 
 /*===========================================================================*
  *                             pick_proc                                    * 
@@ -618,16 +478,6 @@ register struct proc *rp;  /* this process is no longer runnable */
               rdy_tail[q] = rp;
       }
   }
-
-  
-#if DEAD_CODE
-  while (xp->p_nextready != rp)                        /* find rp */
-       if ( (xp = xp->p_nextready) == NIL_PROC) 
-               return;
-  xp->p_nextready = xp->p_nextready->p_nextready;
-  qtail = &rdy_tail[q];
-  if (*qtail == rp) *qtail = xp;
-#endif
 }
 
 /*===========================================================================*
@@ -655,25 +505,25 @@ PRIVATE void sched()
 PUBLIC void lock_pick_proc()
 {
 /* Safe gateway to pick_proc() for tasks. */
-  switching = TRUE;
+  lock();
   pick_proc();
-  switching = FALSE;
+  unlock();
 }
 
 
 /*==========================================================================*
  *                             lock_send                                   *
  *==========================================================================*/
-PUBLIC int lock_send(caller_ptr, dest, m_ptr)
-register struct proc *caller_ptr;      /* who is trying to send a message? */
-int dest;                              /* to whom is message being sent? */
-message *m_ptr;                                /* pointer to message buffer */
+PUBLIC int lock_send(src, dst, m_ptr)
+int src;                       /* who is trying to send a message? */
+int dst;                       /* to whom is message being sent? */
+message *m_ptr;                        /* pointer to message buffer */
 {
 /* Safe gateway to mini_send() for tasks. */
   int result;
-  switching = TRUE;
-  result = mini_send(caller_ptr, dest, m_ptr, FALSE);
-  switching = FALSE;
+  lock();
+  result = mini_send(proc_addr(src), dst, m_ptr, FALSE);
+  unlock();
   return(result);
 }
 
@@ -685,9 +535,9 @@ PUBLIC void lock_ready(rp)
 struct proc *rp;               /* this process is now runnable */
 {
 /* Safe gateway to ready() for tasks. */
-  switching = TRUE;
+  lock();
   ready(rp);
-  switching = FALSE;
+  unlock();
 }
 
 /*==========================================================================*
@@ -697,9 +547,9 @@ PUBLIC void lock_unready(rp)
 struct proc *rp;               /* this process is no longer runnable */
 {
 /* Safe gateway to unready() for tasks. */
-  switching = TRUE;
+  lock();
   unready(rp);
-  switching = FALSE;
+  unlock();
 }
 
 /*==========================================================================*
@@ -708,45 +558,8 @@ struct proc *rp;           /* this process is no longer runnable */
 PUBLIC void lock_sched()
 {
 /* Safe gateway to sched() for tasks. */
-  switching = TRUE;
+  lock();
   sched();
-  switching = FALSE;
-}
-
-/*==========================================================================*
- *                             unhold                                      *
- *==========================================================================*/
-PUBLIC void unhold()
-{
-/* Flush any held-up notifications. 'k_reenter' must be 0. 'held_head' must 
- * not be NIL_PROC.  Interrupts must be disabled.  They will be enabled but 
- * will be disabled when this returns.
- */
-  register struct proc *rp;    /* current head of held queue */
-  int i;
-
-  kinfo.notify_unhold ++;
-
-  if (switching) return;
-  rp = held_head;
-  do {
-      for (i=0; i<NR_NOTIFY_TYPES; i++) {
-          if (isset_bit(rp->p_ntf_held,i)) {
-              clear_bit(rp->p_ntf_held,i);
-              if (! rp->p_ntf_held)    /* proceed to next in queue? */
-                  if ( (held_head = rp->p_ntf_nextheld) == NIL_PROC)
-                      held_tail = NIL_PROC;
-#if DEAD_CODE
-              unlock();                /* reduce latency; held queue may change! */
-#endif
-              lock_notify(proc_number(rp), NOTIFICATION | i);
-#if DEAD_CODE
-              lock();          /* protect the held queue again */
-#endif
-          }
-      }
-  }
-  while ( (rp = held_head) != NIL_PROC);
+  unlock();
 }
 
-
index db69a2e57f396801b607ff5dd13bebef40ca2f1d..0c0b7b27da1c52efda26a37d2d4133dc2c43c7e4 100755 (executable)
@@ -33,12 +33,6 @@ struct proc {
 
   proc_nr_t p_nr;              /* number of this process (for fast access) */
 
-  notify_mask_t p_ntf_blocked; /* bit mask for blocked notifications */
-  notify_mask_t p_ntf_held;    /* bit mask for held up notify() calls */
-  struct proc *p_ntf_nextheld; /* next in chain of held-up int processes */
-
-  struct notification *p_ntf_q;        /* queue of pending notifications */
-
   int p_flags;                 /* SENDING, RECEIVING, etc. */
   struct mem_map p_memmap[NR_LOCAL_SEGS];   /* local memory map (T, D, S) */
   struct far_mem p_farmem[NR_REMOTE_SEGS];  /* remote memory map */
@@ -61,6 +55,8 @@ struct proc {
   int p_getfrom;               /* from whom does process want to receive? */
   int p_sendto;                        /* to whom does process want to send? */
 
+  struct notification *p_ntf_q;        /* queue of pending notifications */
+
   struct proc *p_nextready;    /* pointer to next ready process */
   sigset_t p_pending;          /* bit map for pending signals */
   unsigned p_pendcount;                /* count of pending and unfinished signals */
index 733f3c9fb155904f25f145213177740703021a1c..e2e9971e71b84fcfec3cde9e3446d1eceb65d175 100755 (executable)
@@ -38,16 +38,18 @@ _PROTOTYPE( void stop_sequence, (struct timer *tp)                  );
 
 /* misc.c */
 _PROTOTYPE( void panic, (_CONST char *s, int n)                                );
+_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)  ); 
+_PROTOTYPE( void print_bitmap, (bitchunk_t *map, bit_t nr_bits)        );
 
 /* proc.c */
 _PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) );
-_PROTOTYPE( void unhold, (void)                                                );
+_PROTOTYPE( int lock_notify, (int src, int dst, message *m_ptr)                );
+_PROTOTYPE( int lock_send, (int src, int dst, message *m_ptr)          );
 _PROTOTYPE( void lock_pick_proc, (void)                                        );
 _PROTOTYPE( void lock_ready, (struct proc *rp)                         );
 _PROTOTYPE( void lock_sched, (void)                                    );
 _PROTOTYPE( void lock_unready, (struct proc *rp)                       );
-_PROTOTYPE( void lock_notify, (int proc_nr, int notify_type)           );
-_PROTOTYPE( int lock_send, (struct proc *rp, int to, message *m_ptr)           );
 
 /* start.c */
 _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
index 84e429b74bf5c32960df4e38e39ca5d8c1e036a2..e9174c0e1546e37d12109f0b909e05ad29e02bf0 100755 (executable)
@@ -89,7 +89,7 @@ PUBLIC void sys_task()
        */
       if (result != EDONTREPLY) {
          m.m_type = result;    /* report status of call */
-          lock_send(proc_addr(SYSTASK), m.m_source, &m);
+          lock_send(SYSTASK, m.m_source, &m);
       }
   }
 }
@@ -243,7 +243,10 @@ irq_hook_t *hook;
  * interrupts are transformed into messages to a driver. The IRQ line will be
  * reenabled if the policy says so.
  */
-  lock_notify(hook->proc_nr, HARD_INT); 
+  message m;
+  m.NOTIFY_TYPE = HARD_INT;
+  m.NOTIFY_ARG = hook->irq;
+  lock_notify(HARDWARE, hook->proc_nr, &m);
   return(hook->policy & IRQ_REENABLE);
 }
 
@@ -268,6 +271,7 @@ int sig_nr;                 /* signal to be sent, 1 to _NSIG */
  * do a core dump.
  */
   register struct proc *rp, *mmp;
+  message m;
 
   rp = proc_addr(proc_nr);
   if (sigismember(&rp->p_pending, sig_nr))
@@ -278,12 +282,15 @@ int sig_nr;                       /* signal to be sent, 1 to _NSIG */
        return;                 /* another signal already pending */
   if (rp->p_flags == 0) lock_unready(rp);
   rp->p_flags |= PENDING | SIG_PENDING;
-  lock_notify(PM_PROC_NR, KSIG_PENDING);
+  m.NOTIFY_TYPE = KSIG_PENDING;
+  m.NOTIFY_ARG = 0;
+  m.NOTIFY_FLAGS = 0;
+  lock_notify(HARDWARE, PM_PROC_NR, &m);
 }
 
 
 /*===========================================================================*
- *                             umap_bios                                            *
+ *                             umap_bios                                    *
  *===========================================================================*/
 PUBLIC phys_bytes umap_bios(rp, vir_addr, bytes)
 register struct proc *rp;      /* pointer to proc table entry for process */
index 55b18073df733a8a24c1a23fe145f974fb4d3599..d07074697c793fdfc1f14995d86565202ce27105 100644 (file)
@@ -164,7 +164,12 @@ timer_t *tp;
  * alarm. The process number is stored in timer argument 'ta_int'. Notify that
  * process given with a SYN_ALARM message.
  */
-  lock_notify(tmr_arg(tp)->ta_int, SYN_ALARM);
+  message m;
+  m.NOTIFY_SOURCE = HARDWARE;
+  m.NOTIFY_TYPE = SYN_ALARM;
+  m.NOTIFY_ARG = get_uptime();
+  m.NOTIFY_FLAGS = 0;
+  lock_notify(HARDWARE, tmr_arg(tp)->ta_int, &m);
 }
 
 
index 598ad41980c6bcffda79cc9fb49ea9e427bdc7a6..cca1815f2f8e2b29a8cd45be0bfcdb25a152f8b7 100755 (executable)
@@ -13,7 +13,7 @@ typedef long karg_t;                  /* use largest type here */
  * short we can support up to 256 user processes and more kernel tasks than
  * one can ever create.
  */ 
-typedef int proc_nr_t;                 /* process table entry number */
+typedef short proc_nr_t;               /* process table entry number */
 typedef unsigned long send_mask_t;     /* bit mask for sender */
 
 struct system_image {
@@ -32,8 +32,8 @@ struct memory {
 };
 
 typedef unsigned long notify_mask_t;   /* bit mask for notifications */
-typedef char notify_type_t;            /* notification type */
-typedef char notify_flags_t;           /* notification flags */
+typedef short notify_type_t;           /* notification type */
+typedef short notify_flags_t;          /* notification flags */
 typedef int notify_arg_t;              /* notification argument */
 
 struct notification {
index 4cd399a29acdd12fdffdf752259bf099448a4e09..c71b0708fe71eabfa396840817a5349ddf05002e 100644 (file)
@@ -325,11 +325,12 @@ PRIVATE void kenv_dmp()
     printf("- bootdev_size:  %5u\n", kinfo.bootdev_size); 
     printf("- params_base:   %5u\n", kinfo.params_base); 
     printf("- params_size:   %5u\n", kinfo.params_size); 
-    printf("- notify_held:   %8u\n", kinfo.notify_held); 
     printf("- notify_blocked:%8u\n", kinfo.notify_blocked); 
-    printf("- notify_switch: %8u\n", kinfo.notify_switching); 
-    printf("- notify_reenter:%8u\n", kinfo.notify_reenter); 
     printf("- notify_ok:     %8u\n", kinfo.notify_ok); 
+    printf("- notify_held:   %8u\n", kinfo.notify_held); 
+    printf("-   notify_switch: %8u\n", kinfo.notify_switching); 
+    printf("-   notify_reenter:%8u\n", kinfo.notify_reenter); 
+    printf("-   notify_taskcall:%7u\n", kinfo.notify_taskcall); 
     printf("- notify_unhold: %8u\n", kinfo.notify_unhold); 
     printf("- hard_int:      %8u\n", kinfo.notify_int); 
     printf("- hard_stop:     %8u\n", kinfo.notify_stop); 
index 5e9663d95e831cdae5d1b3e692d75313f804cb72..0ee5053d0c54fc08c37fe7d5bd1f67dac2c96d0a 100644 (file)
@@ -28,7 +28,7 @@ $(ROOTOBJ):
        rm a.out
 
 clean: 
-       @rm -f *.o *.s *.bak test? test?? t10a t11a t11b DIR*
+       rm -rf *.o *.s *.bak test? test?? t10a t11a t11b DIR*
 
 test1: test1.c
 test2: test2.c