]> Zhao Yanbai Git Server - minix.git/commitdiff
IPC status code for receive().
authorCristiano Giuffrida <cristiano@minix3.org>
Tue, 23 Mar 2010 00:09:11 +0000 (00:09 +0000)
committerCristiano Giuffrida <cristiano@minix3.org>
Tue, 23 Mar 2010 00:09:11 +0000 (00:09 +0000)
IPC changes:
- receive() is changed to take an additional parameter, which is a pointer to
a status code.
- The status code is filled in by the kernel to provide additional information
to the caller. For now, the kernel only fills in the IPC call used by the
sender.

Syslib changes:
- sef_receive() has been split into sef_receive() (with the original semantics)
and sef_receive_status() which exposes the status code to userland.
- Ideally, every sys process should gradually switch to sef_receive_status()
and use is_ipc_notify() as a dependable way to check for notify.
- SEF has been modified to use is_ipc_notify() and demonstrate how to use the
new status code.

12 files changed:
include/Makefile
include/minix/com.h
include/minix/ipc.h
include/minix/ipcconst.h [new file with mode: 0644]
include/minix/sef.h
kernel/ipc.h
kernel/proc.c
lib/libc/arch/i386/rts/_ipc.S
lib/libc/arch/i386/rts/_senda.S
lib/libsys/sef.c
lib/libsys/tickdelay.c
servers/rs/main.c

index f49bd609a5b8649998d6096ef6b6c8edaf9a518f..b33a8b9f176d486a596e4e760c9bb194b3e446c3 100644 (file)
@@ -15,9 +15,9 @@ INCS+=        minix/a.out.h minix/bitmap.h minix/callnr.h minix/cdrom.h \
        minix/crtso.h minix/debug.h minix/devio.h minix/dirent.h \
        minix/dir.h minix/dl_eth.h minix/dmap.h minix/driver.h \
        minix/drivers.h minix/drvlib.h minix/ds.h minix/endpoint.h \
-       minix/fslib.h minix/ioctl.h minix/ipc.h minix/keymap.h \
-       minix/minlib.h minix/mq.h minix/partition.h minix/paths.h \
-       minix/portio.h minix/profile.h minix/queryparam.h \
+       minix/fslib.h minix/ioctl.h minix/ipc.h minix/ipcconst.h \
+       minix/keymap.h minix/minlib.h minix/mq.h minix/partition.h \
+       minix/paths.h minix/portio.h minix/profile.h minix/queryparam.h \
        minix/rs.h minix/safecopies.h minix/sef.h minix/sound.h \
        minix/sys_config.h minix/sysinfo.h minix/syslib.h \
        minix/sysutil.h minix/tty.h minix/type.h minix/types.h \
index 3a13fcb55513e8114a6d3db086166370e676a4f8..fb77ab070fecc2a1f7973a1dc0b2291ff4436e26 100644 (file)
@@ -96,7 +96,8 @@
  * offset are used for the per-process notification bit maps. 
  */
 #define NOTIFY_MESSAGE           0x1000
-/* FIXME will be is_notify(a)          ((a) == NOTIFY_MESSAGE) */
+/* FIXME the old is_notify(a) should be replaced by is_ipc_notify(status). */
+#define is_ipc_notify(status)   (IPC_STATUS_CALL(status) == NOTIFY)
 #define is_notify(a)            ((unsigned) ((a) - NOTIFY_MESSAGE) < 0x100)
 #define NOTIFY_FROM(p_nr)       (NOTIFY_MESSAGE | ((p_nr) + NR_TASKS)) 
 
index 6302db085a7679eb3fd148937e2067507e888fa8..5585e4ab09dea876981925d587f05ac727253e82 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _IPC_H
 #define _IPC_H
 
+#include <minix/ipcconst.h>
 #include <minix/type.h>
 
 /*==========================================================================* 
@@ -147,7 +148,7 @@ typedef struct asynmsg
 _PROTOTYPE( int echo, (message *m_ptr)                                 );
 _PROTOTYPE( int notify, (endpoint_t dest)                              );
 _PROTOTYPE( int sendrec, (endpoint_t src_dest, message *m_ptr)         );
-_PROTOTYPE( int receive, (endpoint_t src, message *m_ptr)              );
+_PROTOTYPE( int receive, (endpoint_t src, message *m_ptr, int *status_ptr));
 _PROTOTYPE( int send, (endpoint_t dest, message *m_ptr)                        );
 _PROTOTYPE( int sendnb, (endpoint_t dest, message *m_ptr)              );
 _PROTOTYPE( int senda, (asynmsg_t *table, size_t count)                        );
diff --git a/include/minix/ipcconst.h b/include/minix/ipcconst.h
new file mode 100644 (file)
index 0000000..04aca79
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _IPC_CONST_H
+#define _IPC_CONST_H
+
+ /* System call numbers that are passed when trapping to the kernel. */
+#define SEND              1    /* blocking send */
+#define RECEIVE                   2    /* blocking receive */
+#define SENDREC                   3    /* SEND + RECEIVE */
+#define NOTIFY            4    /* asynchronous notify */
+#define SENDNB             5    /* nonblocking send */
+#define SENDA             16   /* asynchronous send */
+
+/* Macros for IPC status code manipulation. */
+#define IPC_STATUS_CALL_SHIFT  0
+#define IPC_STATUS_CALL_MASK   0x3F
+#define IPC_STATUS_CALL(status)        \
+       (((status) >> IPC_STATUS_CALL_SHIFT) & IPC_STATUS_CALL_MASK)
+#define IPC_STATUS_CALL_TO(call) \
+       (((call) & IPC_STATUS_CALL_MASK) << IPC_STATUS_CALL_SHIFT)
+
+#endif /* IPC_CONST_H */
index 9883f92b9fed6fc3a84ab4eed0a373b7fd3f243f..85ae34b9f63e2fe3f74f668b4bf6c6efd8a37d1a 100644 (file)
@@ -7,8 +7,10 @@
 
 /* SEF entry points for system processes. */
 _PROTOTYPE( void sef_startup, (void) );
-_PROTOTYPE( int sef_receive, (endpoint_t src, message *m_ptr) );
+_PROTOTYPE( int sef_receive_status, (endpoint_t src, message *m_ptr,
+    int *status_ptr) );
 _PROTOTYPE( void sef_exit, (int status) );
+#define sef_receive(src, m_ptr) sef_receive_status(src, m_ptr, NULL)
 
 /* SEF Debug. */
 #include <stdio.h>
@@ -73,7 +75,7 @@ _PROTOTYPE( int sef_cb_init_crash, (int type, sef_init_info_t *info) );
  *===========================================================================*/
 /* What to intercept. */
 #define INTERCEPT_SEF_PING_REQUESTS 1
-#define IS_SEF_PING_REQUEST(mp) (is_notify((mp)->m_type) \
+#define IS_SEF_PING_REQUEST(mp, status) (is_ipc_notify(status) \
     && (mp)->m_source == RS_PROC_NR)
 
 /* Callback type definitions. */
@@ -108,7 +110,7 @@ _PROTOTYPE( void sef_cb_ping_reply_pong, (endpoint_t source) );
  *===========================================================================*/
 /* What to intercept. */
 #define INTERCEPT_SEF_LU_REQUESTS 1
-#define IS_SEF_LU_REQUEST(mp) ((mp)->m_type == RS_LU_PREPARE \
+#define IS_SEF_LU_REQUEST(mp, status) ((mp)->m_type == RS_LU_PREPARE \
     && (mp)->m_source == RS_PROC_NR)
 
 /* Callback type definitions. */
@@ -175,9 +177,9 @@ _PROTOTYPE(  int sef_cb_lu_state_isvalid_standard, (int state) );
  *===========================================================================*/
 /* What to intercept. */
 #define INTERCEPT_SEF_SIGNAL_REQUESTS 1
-#define IS_SEF_SIGNAL_REQUEST(mp) \
+#define IS_SEF_SIGNAL_REQUEST(mp, status) \
     (((mp)->m_type == SIGS_SIGNAL_RECEIVED && (mp)->m_source < INIT_PROC_NR) \
-    || (is_notify((mp)->m_type) && (mp)->m_source == SYSTEM))
+    || (is_ipc_notify(status) && (mp)->m_source == SYSTEM))
 
 /* Callback type definitions. */
 typedef void(*sef_cb_signal_handler_t)(int signo);
index 5311eac5619b387f2bd56d1157c0e1b5f9dd8d19..8000ea692857f2863f058bbd46ad41bb5f970d92 100644 (file)
@@ -9,17 +9,15 @@
 /* Masks and flags for system calls. */
 #define NON_BLOCKING    0x0080  /* do not block if target not ready */
 
-/* System call numbers that are passed when trapping to the kernel. */
-#define SEND              1    /* blocking send */
-#define RECEIVE                   2    /* blocking receive */
-#define SENDREC                   3    /* SEND + RECEIVE */
-#define NOTIFY            4    /* asynchronous notify */
-#define SENDNB             5    /* nonblocking send */
-#define SENDA             16   /* asynchronous send */
-
 #define WILLRECEIVE(target, source_ep) \
   ((RTS_ISSET(target, RTS_RECEIVING) && !RTS_ISSET(target, RTS_SENDING)) &&    \
     (target->p_getfrom_e == ANY || target->p_getfrom_e == source_ep))
 
+/* IPC status code macros. */
+#define IPC_STATUS_REG         bx
+#define IPC_STATUS_GET(p)      ((p)->p_reg.IPC_STATUS_REG)
+#define IPC_STATUS_SET(p, m)   ((p)->p_reg.IPC_STATUS_REG = m)
+#define IPC_STATUS_CLEAR(p)    IPC_STATUS_SET(p, 0)
+#define IPC_STATUS_ADD(p, m)   ((p)->p_reg.IPC_STATUS_REG |= m)
 
 #endif /* IPC_H */
index bed06360d1f9cae0367f9c6377aee6097fb483ed..193b6862d9ca7a347f01e72169e5cf5afd57527d 100644 (file)
@@ -319,6 +319,9 @@ long bit_map;                       /* notification event set or flags */
                caller_ptr->p_name, caller_ptr->p_endpoint);
   }
 
+  /* Clear IPC status code. */
+  IPC_STATUS_CLEAR(caller_ptr);
+
   /* Check destination. SENDA is special because its argument is a table and
    * not a single destination. RECEIVE is the only call that accepts ANY (in
    * addition to a real endpoint). The other calls (SEND, SENDREC,
@@ -563,10 +566,14 @@ int flags;
    * RTS_SENDING flag may be set when its SENDREC call blocked while sending.  
    */
   if (WILLRECEIVE(dst_ptr, caller_ptr->p_endpoint)) {
+       int call;
        /* Destination is indeed waiting for this message. */
        assert(!(dst_ptr->p_misc_flags & MF_DELIVERMSG));       
        if((r=QueueMess(caller_ptr->p_endpoint, linaddr, dst_ptr)) != OK)
                return r;
+       call = (caller_ptr->p_misc_flags & MF_REPLY_PEND ? SENDREC
+               : (flags & NON_BLOCKING ? SENDNB : SEND));
+       IPC_STATUS_ADD(dst_ptr, IPC_STATUS_CALL_TO(call));
        RTS_UNSET(dst_ptr, RTS_RECEIVING);
   } else {
        if(flags & NON_BLOCKING) {
@@ -672,6 +679,7 @@ int flags;
            if((r=QueueMess(hisep, vir2phys(&m), caller_ptr)) != OK)  {
                panic("mini_receive: local QueueMess failed");
            }
+           IPC_STATUS_ADD(caller_ptr, IPC_STATUS_CALL_TO(NOTIFY));
             return(OK);                                        /* report success */
         }
     }
@@ -680,6 +688,7 @@ int flags;
     xpp = &caller_ptr->p_caller_q;
     while (*xpp != NIL_PROC) {
         if (src_e == ANY || src_p == proc_nr(*xpp)) {
+            int call;
            assert(!RTS_ISSET(*xpp, RTS_SLOT_FREE));
            assert(!RTS_ISSET(*xpp, RTS_NO_ENDPOINT));
 
@@ -687,6 +696,8 @@ int flags;
            assert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));
            QueueMess((*xpp)->p_endpoint,
                vir2phys(&(*xpp)->p_sendmsg), caller_ptr);
+           call = ((*xpp)->p_misc_flags & MF_REPLY_PEND ? SENDREC : SEND);
+           IPC_STATUS_ADD(caller_ptr, IPC_STATUS_CALL_TO(call));
            if ((*xpp)->p_misc_flags & MF_SIG_DELAY)
                sig_delay_done(*xpp);
            RTS_UNSET(*xpp, RTS_SENDING);
@@ -703,8 +714,10 @@ int flags;
        else
                r= try_async(caller_ptr);
 
-       if (r == OK)
+       if (r == OK) {
+               IPC_STATUS_ADD(caller_ptr, IPC_STATUS_CALL_TO(SENDA));
                return OK;      /* Got a message */
+       }
     }
   }
 
@@ -760,6 +773,7 @@ endpoint_t dst_e;                   /* which process to notify */
       if((r=QueueMess(caller_ptr->p_endpoint, vir2phys(&m), dst_ptr)) != OK) {
        panic("mini_notify: local QueueMess failed");
       }
+      IPC_STATUS_ADD(dst_ptr, IPC_STATUS_CALL_TO(NOTIFY));
       RTS_UNSET(dst_ptr, RTS_RECEIVING);
       return(OK);
   } 
@@ -945,8 +959,11 @@ PRIVATE int mini_senda(struct proc *caller_ptr, asynmsg_t *table, size_t size)
                        tabent.result= QueueMess(caller_ptr->p_endpoint,
                                linaddr + (vir_bytes) &table[i].msg -
                                        (vir_bytes) table, dst_ptr);
-                       if(tabent.result == OK)
+                       if(tabent.result == OK) {
+                               IPC_STATUS_ADD(dst_ptr,
+                                       IPC_STATUS_CALL_TO(SENDA));
                                RTS_UNSET(dst_ptr, RTS_RECEIVING);
+                       }
 
                        A_INSERT(i, result);
                        tabent.flags= flags | AMF_DONE;
index 515603b71e189a0c42a1cfa221dc6be728341146..399bd7508fb2dfdc04341fe21e518c9254b4c4e5 100644 (file)
@@ -1,21 +1,18 @@
+#include <minix/ipcconst.h>
+
 .globl __notify, __send, __senda, __sendnb, __receive, __sendrec, __do_kernel_call
 
-/* See src/kernel/ipc.h for C definitions */
-       SEND = 1
-       RECEIVE = 2
-       SENDREC = 3
-       NOTIFY = 4
-       SENDNB = 5
        IPCVEC = 33     /* ipc trap to kernel  */
        KERVEC = 32     /* syscall trap to kernel */
 
        SRC_DST = 8     /* source/ destination process  */
        MESSAGE = 12    /* message pointer  */
+       STATUS = 16     /* status pointer  */
 
 /**========================================================================* */
 /*                           IPC assembly routines                       * */
 /**========================================================================* */
-/* all message passing routines save ebp, but destroy eax and ecx. */
+/* all message passing routines save ebx, but destroy eax and ecx. */
 .text
 __send:
        push    %ebp
@@ -37,6 +34,8 @@ __receive:
        movl    MESSAGE(%ebp), %ebx     /* ebx = message pointer */
        movl    $RECEIVE, %ecx  /* _receive(src, ptr) */
        int     $IPCVEC /* trap to the kernel */
+       movl    STATUS(%ebp), %ecx      /* ecx = status pointer */
+       movl    %ebx, (%ecx)
        pop     %ebx
        pop     %ebp
        ret
index 3b5deec41746e5cc0b1b342751e33ce867eacf61..614b1ae00d83970dbde4a34b7bf064ed2d10a0de 100644 (file)
@@ -1,6 +1,7 @@
+#include <minix/ipcconst.h>
+
 .globl __senda
 
-       SENDA = 16
        SYSVEC = 33
 
        MSGTAB = 8      /* message table */
index 7dd78494025a425da4d16b8de4a6e798451b7be4..6e8d920d67ad8c03e7401787f95fbff0d1350500 100644 (file)
@@ -38,7 +38,7 @@ EXTERN _PROTOTYPE( int do_sef_signal_request, (message *m_ptr) );
 PUBLIC void sef_startup()
 {
 /* SEF startup interface for system services. */
-  int r;
+  int r, status;
 
   /* Get information about self. */
   r = sys_whoami(&sef_self_endpoint, sef_self_name, SEF_SELF_NAME_MAXLEN);
@@ -57,7 +57,8 @@ PUBLIC void sef_startup()
   else {
       message m;
 
-      if((r = receive(RS_PROC_NR, &m)) != OK) {
+      r = receive(RS_PROC_NR, &m, &status);
+      if(r != OK) {
           panic("unable to receive from RS: %d", r);
       }
       if(IS_SEF_INIT_REQUEST(&m)) {
@@ -73,12 +74,12 @@ PUBLIC void sef_startup()
 }
 
 /*===========================================================================*
- *                             sef_receive                                  *
+ *                             sef_receive_status                           *
  *===========================================================================*/
-PUBLIC int sef_receive(endpoint_t src, message *m_ptr)
+PUBLIC int sef_receive_status(endpoint_t src, message *m_ptr, int *status_ptr)
 {
 /* SEF receive() interface for system services. */
-  int r;
+  int r, status;
 
   while(TRUE) {
 
@@ -88,14 +89,15 @@ PUBLIC int sef_receive(endpoint_t src, message *m_ptr)
 #endif
 
       /* Receive and return in case of error. */
-      r = receive(src, m_ptr);
+      r = receive(src, m_ptr, &status);
+      if(status_ptr) *status_ptr = status;
       if(r != OK) {
           return r;
       }
 
 #if INTERCEPT_SEF_PING_REQUESTS
       /* Intercept SEF Ping requests. */
-      if(IS_SEF_PING_REQUEST(m_ptr)) {
+      if(IS_SEF_PING_REQUEST(m_ptr, status)) {
           if(do_sef_ping_request(m_ptr) == OK) {
               continue;
           }
@@ -104,7 +106,7 @@ PUBLIC int sef_receive(endpoint_t src, message *m_ptr)
 
 #if INTERCEPT_SEF_LU_REQUESTS
       /* Intercept SEF Live update requests. */
-      if(IS_SEF_LU_REQUEST(m_ptr)) {
+      if(IS_SEF_LU_REQUEST(m_ptr, status)) {
           if(do_sef_lu_request(m_ptr) == OK) {
               continue;
           }
@@ -113,7 +115,7 @@ PUBLIC int sef_receive(endpoint_t src, message *m_ptr)
 
 #if INTERCEPT_SEF_SIGNAL_REQUESTS
       /* Intercept SEF Signal requests. */
-      if(IS_SEF_SIGNAL_REQUEST(m_ptr)) {
+      if(IS_SEF_SIGNAL_REQUEST(m_ptr, status)) {
           if(do_sef_signal_request(m_ptr) == OK) {
               continue;
           }
index 096b36006f909e1b9d3adaaae5407d3f2c419af3..c7b3ae7cee80dc4c7c47917039e28c35737ba169 100644 (file)
@@ -23,7 +23,7 @@ long ticks;                           /* number of ticks to wait */
     s = _kernel_call(SYS_SETALARM, &m);
     if (s != OK) return(s);
 
-    receive(CLOCK,&m_alarm);           /* await synchronous alarm */
+    sef_receive(CLOCK,&m_alarm);               /* await synchronous alarm */
 
     /* Check if we must reschedule the current alarm. */
     if (m.ALRM_TIME_LEFT > 0 && m.ALRM_TIME_LEFT != TMR_NEVER) {
index aa48f68a485f6a82e7597a3dfbcc11c36d79d403..e7fdea351f586cbbf3a499f0284c1fcf707a0d18 100644 (file)
@@ -25,7 +25,7 @@ FORWARD _PROTOTYPE(void boot_image_info_lookup, ( endpoint_t endpoint,
     struct boot_image **ip, struct boot_image_priv **pp,
     struct boot_image_sys **sp, struct boot_image_dev **dp)             );
 FORWARD _PROTOTYPE(void catch_boot_init_ready, (endpoint_t endpoint)   );
-FORWARD _PROTOTYPE(void get_work, (message *m)                         );
+FORWARD _PROTOTYPE(void get_work, (message *m_ptr, int *status_ptr)    );
 
 /* The buffer where the boot image is copied during initialization. */
 PRIVATE int boot_image_buffer_size;
@@ -50,6 +50,7 @@ PUBLIC int main(void)
  * sending the reply. The loop never terminates, unless a panic occurs.
  */
   message m;                                   /* request message */
+  int status;                                  /* status code */
   int call_nr, who_e,who_p;                    /* call number and caller */
   int result;                                  /* result to return */
 
@@ -60,7 +61,7 @@ PUBLIC int main(void)
   while (TRUE) {              
 
       /* Wait for request message. */
-      get_work(&m);
+      get_work(&m, &status);
       who_e = m.m_source;
       if(rs_isokendpt(who_e, &who_p) != OK) {
           panic("message from bogus source: %d", who_e);
@@ -78,7 +79,7 @@ PUBLIC int main(void)
       /* Notification messages are control messages and do not need a reply.
        * These include heartbeat messages and system notifications.
        */
-      if (is_notify(m.m_type)) {
+      if (is_ipc_notify(status)) {
           switch (who_p) {
           case CLOCK:
              do_period(&m);                    /* check services status */
@@ -671,12 +672,13 @@ endpoint_t endpoint;
 {
 /* Block and catch an init ready message from the given source. */
   int r;
+  int status;
   message m;
   struct rproc *rp;
   int result;
 
   /* Receive init ready message. */
-  if ((r = receive(endpoint, &m)) != OK) {
+  if ((r = sef_receive_status(endpoint, &m, &status)) != OK) {
       panic("unable to receive init reply: %d", r);
   }
   if(m.m_type != RS_INIT) {
@@ -703,11 +705,12 @@ endpoint_t endpoint;
 /*===========================================================================*
  *                             get_work                                     *
  *===========================================================================*/
-PRIVATE void get_work(m_in)
-message *m_in;                         /* pointer to message */
+PRIVATE void get_work(m_ptr, status_ptr)
+message *m_ptr;                                /* pointer to message */
+int *status_ptr;                       /* pointer to status */
 {
-    int s;                             /* receive status */
-    if (OK != (s=sef_receive(ANY, m_in)))      /* wait for message */
-        panic("sef_receive failed: %d", s);
+    int r;
+    if (OK != (r=sef_receive_status(ANY, m_ptr, status_ptr)))
+        panic("sef_receive_status failed: %d", r);
 }