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.
This commit is contained in:
Cristiano Giuffrida 2010-03-23 00:09:11 +00:00
parent 45db6482e8
commit bde2109b7c
12 changed files with 91 additions and 47 deletions

View 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 \

View 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))

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

20
include/minix/ipcconst.h Normal file
View file

@ -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 */

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

View 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 */

View 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;

View 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

View file

@ -1,6 +1,7 @@
#include <minix/ipcconst.h>
.globl __senda
SENDA = 16
SYSVEC = 33
MSGTAB = 8 /* message table */

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

View 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) {

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