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); }