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

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