From bde2109b7c21f3bed0ffa49e410f78cef6dd374b Mon Sep 17 00:00:00 2001 From: Cristiano Giuffrida Date: Tue, 23 Mar 2010 00:09:11 +0000 Subject: [PATCH] IPC status code for receive(). 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. --- include/Makefile | 6 +++--- include/minix/com.h | 3 ++- include/minix/ipc.h | 3 ++- include/minix/ipcconst.h | 20 ++++++++++++++++++++ include/minix/sef.h | 12 +++++++----- kernel/ipc.h | 14 ++++++-------- kernel/proc.c | 21 +++++++++++++++++++-- lib/libc/arch/i386/rts/_ipc.S | 13 ++++++------- lib/libc/arch/i386/rts/_senda.S | 3 ++- lib/libsys/sef.c | 20 +++++++++++--------- lib/libsys/tickdelay.c | 2 +- servers/rs/main.c | 21 ++++++++++++--------- 12 files changed, 91 insertions(+), 47 deletions(-) create mode 100644 include/minix/ipcconst.h diff --git a/include/Makefile b/include/Makefile index f49bd609a..b33a8b9f1 100644 --- a/include/Makefile +++ b/include/Makefile @@ -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 \ diff --git a/include/minix/com.h b/include/minix/com.h index 3a13fcb55..fb77ab070 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -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)) diff --git a/include/minix/ipc.h b/include/minix/ipc.h index 6302db085..5585e4ab0 100644 --- a/include/minix/ipc.h +++ b/include/minix/ipc.h @@ -1,6 +1,7 @@ #ifndef _IPC_H #define _IPC_H +#include #include /*==========================================================================* @@ -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 index 000000000..04aca7954 --- /dev/null +++ b/include/minix/ipcconst.h @@ -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 */ diff --git a/include/minix/sef.h b/include/minix/sef.h index 9883f92b9..85ae34b9f 100644 --- a/include/minix/sef.h +++ b/include/minix/sef.h @@ -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 @@ -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); diff --git a/kernel/ipc.h b/kernel/ipc.h index 5311eac56..8000ea692 100644 --- a/kernel/ipc.h +++ b/kernel/ipc.h @@ -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 */ diff --git a/kernel/proc.c b/kernel/proc.c index bed06360d..193b6862d 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -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; diff --git a/lib/libc/arch/i386/rts/_ipc.S b/lib/libc/arch/i386/rts/_ipc.S index 515603b71..399bd7508 100644 --- a/lib/libc/arch/i386/rts/_ipc.S +++ b/lib/libc/arch/i386/rts/_ipc.S @@ -1,21 +1,18 @@ +#include + .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 diff --git a/lib/libc/arch/i386/rts/_senda.S b/lib/libc/arch/i386/rts/_senda.S index 3b5deec41..614b1ae00 100644 --- a/lib/libc/arch/i386/rts/_senda.S +++ b/lib/libc/arch/i386/rts/_senda.S @@ -1,6 +1,7 @@ +#include + .globl __senda - SENDA = 16 SYSVEC = 33 MSGTAB = 8 /* message table */ diff --git a/lib/libsys/sef.c b/lib/libsys/sef.c index 7dd784940..6e8d920d6 100644 --- a/lib/libsys/sef.c +++ b/lib/libsys/sef.c @@ -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; } diff --git a/lib/libsys/tickdelay.c b/lib/libsys/tickdelay.c index 096b36006..c7b3ae7ce 100644 --- a/lib/libsys/tickdelay.c +++ b/lib/libsys/tickdelay.c @@ -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) { diff --git a/servers/rs/main.c b/servers/rs/main.c index aa48f68a4..e7fdea351 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -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); }