]> Zhao Yanbai Git Server - minix.git/commitdiff
New NOTIFY trap (IPC call) to send queued notification messages.
authorJorrit Herder <jnherder@minix3.org>
Thu, 19 May 2005 14:05:51 +0000 (14:05 +0000)
committerJorrit Herder <jnherder@minix3.org>
Thu, 19 May 2005 14:05:51 +0000 (14:05 +0000)
The call works. Permission check, restriction of outstanding notifications
to be added. Low level code to make it work from within interrupt handlers
will be added as well.

13 files changed:
include/lib.h
include/minix/com.h
include/unistd.h
kernel/proc.c
kernel/proc.h
kernel/system.c
kernel/system/proctl.c
kernel/type.h
lib/other/Makefile
lib/other/_getsysinfo.c
lib/syscall/Makefile
servers/pm/misc.c
servers/pm/param.h

index 948739a47970f7cdad7f6e2b626687ffdc7174da..d00eda7cf7d5a0240709d9869e3c219da633b5b3 100755 (executable)
@@ -31,9 +31,6 @@ _PROTOTYPE( int _syscall, (int _who, int _syscallnr, message *_msgptr)        );
 _PROTOTYPE( void _loadname, (const char *_name, message *_msgptr)      );
 _PROTOTYPE( int _len, (const char *_s)                                 );
 _PROTOTYPE( void panic, (const char *_message, int _errnum)            );
-#if 0
-_PROTOTYPE( int _sendrec, (int _src_dest, message *_m_ptr)             );
-#endif
 _PROTOTYPE( void _begsig, (int _dummy)                                 );
 
 #endif /* _LIB_H */
index a00c761ca571a35ed36cd5d742ea1de580d23825..f04c220f24b015c14a10140d7e8094b3da52b801 100755 (executable)
@@ -82,7 +82,9 @@
 #define NR_NOTIFY_TYPES               5        /* nr of bits in mask */
 
 /* Shorthands for message parameters passed with notifications. */
-#define NOTIFY_ARG     m2_l1                   /* passed for some types */
+#define NOTIFY_TYPE    m2_i1
+#define NOTIFY_FLAGS   m2_i2
+#define NOTIFY_ARG     m2_i3
 
 
 /*===========================================================================*
index 22c0f9beeacd9af33d216bbe2849ebb1c91d2eaf..a5921db6e8cbd05394cb8dc3310e467aff61fd71 100755 (executable)
@@ -143,9 +143,7 @@ _PROTOTYPE( int ttyslot, (void)                                             );
 _PROTOTYPE( int fttyslot, (int _fd)                                    );
 _PROTOTYPE( char *crypt, (const char *_key, const char *_salt)         );
 _PROTOTYPE( int getsysinfo, (int who, int what, void *where)           );
-#if ENABLE_MESSAGE_STATS
-_PROTOTYPE( int mstats, (struct message_statentry *ms, int entries, int reset) );
-#endif
+_PROTOTYPE( int getprocnr, (int *proc_nr)                              );
 #endif
 
 _PROTOTYPE( int setcache, (int kb));
index c271268a0febc53748bf1f07b864f7a454173806..54d9778645157cd1d11cf7faed268575b18bcb3d 100755 (executable)
@@ -14,7 +14,6 @@
  *   unhold:          repeat all held-up notifications
  *
  * Changes:
- *   Nov 05, 2004     removed lock_mini_send()  (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)
@@ -23,7 +22,6 @@
  *   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) 
- *   May 01, 2004     check p_sendmask in mini_send()  (Jorrit N. Herder) 
  */
 
 #include "kernel.h"
@@ -43,6 +41,8 @@ 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,
@@ -66,8 +66,65 @@ FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m,
 #define clear_bit(mask, n)     ((mask) &= ~(1 << (n)))
 #define isset_bit(mask, n)     ((mask) & (1 << (n)))
 
-/* Declare buffer space for notifications. */
-PRIVATE struct notification notify_buf[NR_NOTIFY_BUFS];
+/* 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. */
+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                              * 
@@ -307,8 +364,8 @@ int may_block;                              /* (dis)allow blocking */
        caller_ptr->p_sendto= dest;
 
        /* Process is now blocked.  Put in on the destination's queue. */
-       if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC)
-               dest_ptr->p_callerq = caller_ptr;
+       if ( (next_ptr = dest_ptr->p_caller_q) == NIL_PROC)
+               dest_ptr->p_caller_q = caller_ptr;
        else {
                while (next_ptr->p_sendlink != NIL_PROC)
                        next_ptr = next_ptr->p_sendlink;
@@ -336,21 +393,22 @@ int may_block;                            /* (dis)allow blocking */
  */
   register struct proc *sender_ptr;
   register struct proc *previous_ptr;
+  register struct notification **ntf_q_pp;
   message m;
-  int i;
+  int bit_nr, i;
 
   /* Check to see if a message from desired source is already available. */
   if (!(caller_ptr->p_flags & SENDING)) {
 
     /* Check caller queue. */
-    for (sender_ptr = caller_ptr->p_callerq; sender_ptr != NIL_PROC;
+    for (sender_ptr = caller_ptr->p_caller_q; sender_ptr != NIL_PROC;
         previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_sendlink) {
        if (src == ANY || src == proc_number(sender_ptr)) {
                /* An acceptable message has been found. */
                CopyMess(proc_number(sender_ptr), sender_ptr,
                         sender_ptr->p_messbuf, caller_ptr, m_ptr);
-               if (sender_ptr == caller_ptr->p_callerq)
-                       caller_ptr->p_callerq = sender_ptr->p_sendlink;
+               if (sender_ptr == caller_ptr->p_caller_q)
+                       caller_ptr->p_caller_q = sender_ptr->p_sendlink;
                else
                        previous_ptr->p_sendlink = sender_ptr->p_sendlink;
                if ((sender_ptr->p_flags &= ~SENDING) == 0)
@@ -359,6 +417,26 @@ int may_block;                             /* (dis)allow blocking */
        }
     }
 
+    /* Check if there are pending notifications. */
+    ntf_q_pp = &caller_ptr->p_ntf_q;           /* get pointer pointer */
+    while (*ntf_q_pp) {
+       if (src == ANY || src == (*ntf_q_pp)->n_source) {
+               /* Found notification. Assemble and copy message. */
+               m.NOTIFY_TYPE = (*ntf_q_pp)->n_type;
+               m.NOTIFY_FLAGS = (*ntf_q_pp)->n_flags;
+               m.NOTIFY_ARG = (*ntf_q_pp)->n_arg;
+                CopyMess((*ntf_q_pp)->n_source, proc_addr(HARDWARE), &m, 
+                       caller_ptr, m_ptr);
+                /* Remove notification from queue and return. */
+                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 */
+                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
@@ -395,12 +473,49 @@ int may_block;                            /* (dis)allow blocking */
  *                             mini_notify                                  * 
  *===========================================================================*/
 PRIVATE int mini_notify(caller_ptr, dst, m_ptr)
-register struct proc *caller_ptr;      /* process trying to get message */
+register struct proc *caller_ptr;      /* process trying to notify */
 int dst;                               /* which process to notify */
 message *m_ptr;                                /* pointer to message buffer */
 {
-  kprintf("Kernel notify from %d", caller_ptr->p_nr);
-  kprintf("for %d\n", dst);
+  register struct proc *dest_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))) {
+       /* 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 {
+
+       /* See if there is a free notification buffer. */
+       if ((ntf_index = alloc_notify_buf()) < 0) 
+               return(ENOSPC);                 /* should be atomic! */
+
+       /* Copy details from notification message. */
+       CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, 
+                proc_addr(HARDWARE), &ntf_mess);
+       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_q_pp = ntf_p;
+       ntf_p->n_next = NULL;
+  }
   return(OK);
 }
 
index 633259d14080d0eaa8859a3c3722a79b90f732a0..db69a2e57f396801b607ff5dd13bebef40ca2f1d 100755 (executable)
@@ -37,7 +37,7 @@ struct proc {
   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_ntfq; /* queue of pending notifications */
+  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) */
@@ -55,7 +55,7 @@ struct proc {
   timer_t p_syncalrm;          /* synchronous alarm timer */ 
 
   send_mask_t p_sendmask;      /* mask indicating to whom proc may send */
-  struct proc *p_callerq;      /* head of list of procs wishing to send */
+  struct proc *p_caller_q;     /* head of list of procs wishing to send */
   struct proc *p_sendlink;     /* link to next proc wishing to send */
   message *p_messbuf;          /* pointer to message buffer */
   int p_getfrom;               /* from whom does process want to receive? */
index 0d93e7fb8703d9f191bc5cade12e7d499dccb6aa..84e429b74bf5c32960df4e38e39ca5d8c1e036a2 100755 (executable)
@@ -198,14 +198,14 @@ int proc_nr;                              /* slot of process to clean up */
   if (rc->p_flags & SENDING) {
       /* Check all proc slots to see if the exiting process is queued. */
       for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
-          if (rp->p_callerq == NIL_PROC) continue;
-          if (rp->p_callerq == rc) {
+          if (rp->p_caller_q == NIL_PROC) continue;
+          if (rp->p_caller_q == rc) {
               /* Exiting process is on front of this queue. */
-              rp->p_callerq = rc->p_sendlink;
+              rp->p_caller_q = rc->p_sendlink;
               break;
           } else {
               /* See if exiting process is in middle of queue. */
-              np = rp->p_callerq;
+              np = rp->p_caller_q;
               while ( ( xp = np->p_sendlink) != NIL_PROC) {
                   if (xp == rc) {
                       np->p_sendlink = xp->p_sendlink;
index 31493b8389e18888f06d9cce22897fbcf0aea4eb..c35b6248f2bbc93c8996611c4c39583efab7782e 100644 (file)
@@ -47,8 +47,8 @@ register message *m_ptr;      /* pointer to request message */
   rpc->p_ldt_sel = old_ldt_sel;
 #endif
   rpc->p_nr = m_ptr->PR_PROC_NR;       /* this was obliterated by copy */
-
-  rpc->p_flags |= NO_MAP;      /* inhibit the process from running */
+  rpc->p_ntf_q = NULL;                 /* remove pending notifications */
+  rpc->p_flags |= NO_MAP;              /* inhibit process from running */
 
   rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
 
index 80a38ae26c9e924db60f3794894a5a7a3315054d..598ad41980c6bcffda79cc9fb49ea9e427bdc7a6 100755 (executable)
@@ -40,7 +40,7 @@ struct notification {
   proc_nr_t     n_source;              /* sender of notification */
   notify_type_t         n_type;                /* notification type */
   notify_arg_t          n_arg;                 /* notification argument */
-  notify_flags_t n_fags;               /* notification flags */
+  notify_flags_t n_flags;              /* notification flags */
   struct notification* n_next;         /* pointer to next notification */
 };
 
index 1654def69186cfd2e10b4629644d908fc065256c..c05c91a7321a939e030a1c4e6780ab3f38beb0a0 100755 (executable)
@@ -15,6 +15,7 @@ OBJECTS       = \
        $(LIBRARY)(_seekdir.o) \
        $(LIBRARY)(_svrctl.o) \
        $(LIBRARY)(_getsysinfo.o) \
+       $(LIBRARY)(_getprocnr.o) \
        $(LIBRARY)(asynchio.o) \
        $(LIBRARY)(configfile.o) \
        $(LIBRARY)(crypt.o) \
@@ -74,6 +75,9 @@ $(LIBRARY)(_seekdir.o):       _seekdir.c
 $(LIBRARY)(_svrctl.o): _svrctl.c
        $(CC1) _svrctl.c
 
+$(LIBRARY)(_getprocnr.o):      _getprocnr.c
+       $(CC1) _getprocnr.c
+
 $(LIBRARY)(_getsysinfo.o):     _getsysinfo.c
        $(CC1) _getsysinfo.c
 
index d98b8833f8b53b18176cd766f0369ed48521c4cf..19675ab1867fa01d72cff149b9a631e3da7d8f05 100644 (file)
@@ -1,6 +1,5 @@
 #include <lib.h>
 #define getsysinfo     _getsysinfo
-#define getsysinfo     _getsysinfo
 #include <unistd.h>
 
 
index 1b179c2e09f6fd058ea986c4611cc8791a20fe3e..41bee90dbbbb010009408a93f1b61f9ed77ef48f 100755 (executable)
@@ -43,6 +43,7 @@ OBJECTS       = \
        $(LIBRARY)(getpid.o) \
        $(LIBRARY)(getppid.o) \
        $(LIBRARY)(getuid.o) \
+       $(LIBRARY)(getprocnr.o) \
        $(LIBRARY)(ioctl.o) \
        $(LIBRARY)(isatty.o) \
        $(LIBRARY)(kill.o) \
@@ -214,6 +215,9 @@ $(LIBRARY)(getpid.o):       getpid.s
 $(LIBRARY)(getppid.o): getppid.s
        $(CC1) getppid.s
 
+$(LIBRARY)(getprocnr.o):       getprocnr.s
+       $(CC1) getprocnr.s
+
 $(LIBRARY)(getuid.o):  getuid.s
        $(CC1) getuid.s
 
index 983435e3821b8a3b8f6f2751fee724d84cba75f4..32aa327d594a566b26b556db3f30b07923163c51 100644 (file)
@@ -36,6 +36,7 @@ PUBLIC int do_getsysinfo()
  *=====================================================================*/
 PUBLIC int do_getprocnr()
 {
+  mp->mp_reply.procnr = who;
   return(OK);
 }
 
index e5764812cb3792978dbd08b46f9a39a54cb56e7d..c39752fbde5baffc85ead9c97268fd3a36b0241e 100644 (file)
@@ -6,6 +6,7 @@
 #define grp_id         m1_i1
 #define namelen                m1_i1
 #define pid            m1_i1
+#define procnr         m1_i1
 #define seconds                m1_i1
 #define sig            m6_i1
 #define stack_bytes    m1_i2