Use a bitmap for pending asynchronous messages instead of a global flag.
That way it works similar to pending notifications.
This commit is contained in:
parent
9db2311b22
commit
16e0e9370e
|
@ -38,6 +38,7 @@ struct priv {
|
|||
endpoint_t s_sig_mgr; /* signal manager for system signals */
|
||||
endpoint_t s_bak_sig_mgr; /* backup signal manager for system signals */
|
||||
sys_map_t s_notify_pending; /* bit map with pending notifications */
|
||||
sys_map_t s_asyn_pending; /* bit map with pending asyn messages */
|
||||
irq_id_t s_int_pending; /* pending hardware interrupts */
|
||||
sigset_t s_sig_pending; /* pending signals */
|
||||
|
||||
|
|
107
kernel/proc.c
107
kernel/proc.c
|
@ -54,6 +54,7 @@ FORWARD _PROTOTYPE( void idle, (void));
|
|||
FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, endpoint_t dst_e,
|
||||
message *m_ptr, int flags));
|
||||
*/
|
||||
FORWARD _PROTOTYPE( int has_pending, (sys_map_t *map, int src_p) );
|
||||
FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, endpoint_t src,
|
||||
message *m_ptr, int flags));
|
||||
FORWARD _PROTOTYPE( int mini_senda, (struct proc *caller_ptr,
|
||||
|
@ -61,8 +62,7 @@ FORWARD _PROTOTYPE( int mini_senda, (struct proc *caller_ptr,
|
|||
FORWARD _PROTOTYPE( int deadlock, (int function,
|
||||
register struct proc *caller, endpoint_t src_dst_e));
|
||||
FORWARD _PROTOTYPE( int try_async, (struct proc *caller_ptr));
|
||||
FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr,
|
||||
int *postponed));
|
||||
FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr));
|
||||
FORWARD _PROTOTYPE( struct proc * pick_proc, (void));
|
||||
FORWARD _PROTOTYPE( void enqueue_head, (struct proc *rp));
|
||||
|
||||
|
@ -688,6 +688,41 @@ endpoint_t src_dst_e; /* src or dst process */
|
|||
return(0); /* not a deadlock */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* has_pending *
|
||||
*===========================================================================*/
|
||||
PRIVATE int has_pending(sys_map_t *map, int src_p)
|
||||
{
|
||||
/* Check to see if there is a pending message from the desired source
|
||||
* available.
|
||||
*/
|
||||
|
||||
int src_id;
|
||||
sys_id_t id = NULL_PRIV_ID;
|
||||
|
||||
/* Either check a specific bit in the mask map, or find the first bit set in
|
||||
* it (if any), depending on whether the receive was called on a specific
|
||||
* source endpoint.
|
||||
*/
|
||||
if (src_p != ANY) {
|
||||
src_id = nr_to_id(src_p);
|
||||
if (get_sys_bit(*map, src_id))
|
||||
id = src_id;
|
||||
} else {
|
||||
/* Find a source with a pending message */
|
||||
for (src_id = 0; src_id < NR_SYS_PROCS; src_id += BITCHUNK_BITS) {
|
||||
if (get_sys_bits(*map, src_id) != 0) {
|
||||
while(!get_sys_bit(*map, src_id)) src_id++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (src_id < NR_SYS_PROCS) /* Found one */
|
||||
id = src_id;
|
||||
}
|
||||
|
||||
return(id);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* mini_send *
|
||||
*===========================================================================*/
|
||||
|
@ -799,7 +834,7 @@ PRIVATE int mini_receive(struct proc * caller_ptr,
|
|||
*/
|
||||
register struct proc **xpp;
|
||||
sys_map_t *map;
|
||||
int i, r, src_id, found, src_proc_nr, src_p;
|
||||
int i, r, src_id, src_proc_nr, src_p;
|
||||
|
||||
assert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));
|
||||
|
||||
|
@ -827,27 +862,8 @@ PRIVATE int mini_receive(struct proc * caller_ptr,
|
|||
if (! (caller_ptr->p_misc_flags & MF_REPLY_PEND)) {
|
||||
map = &priv(caller_ptr)->s_notify_pending;
|
||||
|
||||
/* Either check a specific bit in the pending notifications mask, or
|
||||
* find the first bit set in it (if any), depending on whether the
|
||||
* receive was called on a specific source endpoint.
|
||||
*/
|
||||
if (src_p != ANY) {
|
||||
src_id = nr_to_id(src_p);
|
||||
|
||||
found = get_sys_bit(*map, src_id);
|
||||
} else {
|
||||
for (src_id = 0; src_id < NR_SYS_PROCS; src_id += BITCHUNK_BITS) {
|
||||
if (get_sys_bits(*map, src_id) != 0) {
|
||||
while (!get_sys_bit(*map, src_id)) src_id++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
found = (src_id < NR_SYS_PROCS);
|
||||
}
|
||||
|
||||
if (found) {
|
||||
/* Check for pending notifications */
|
||||
if ((src_id = has_pending(map, src_p)) != NULL_PRIV_ID) {
|
||||
endpoint_t hisep;
|
||||
|
||||
src_proc_nr = id_to_nr(src_id); /* get source proc */
|
||||
|
@ -874,10 +890,12 @@ PRIVATE int mini_receive(struct proc * caller_ptr,
|
|||
}
|
||||
}
|
||||
|
||||
/* Check if there are pending senda(). */
|
||||
if (caller_ptr->p_misc_flags & MF_ASYNMSG) {
|
||||
if (src_e != ANY)
|
||||
r = try_one(proc_addr(src_p), caller_ptr, NULL);
|
||||
/* Check for pending asynchronous messages */
|
||||
map = &priv(caller_ptr)->s_asyn_pending;
|
||||
|
||||
if (has_pending(map, src_p) != NULL_PRIV_ID) {
|
||||
if (src_p != ANY)
|
||||
r = try_one(proc_addr(src_p), caller_ptr);
|
||||
else
|
||||
r = try_async(caller_ptr);
|
||||
|
||||
|
@ -1050,7 +1068,8 @@ field, caller->p_name, entry, priv(caller)->s_asynsize, priv(caller)->s_asyntab)
|
|||
*===========================================================================*/
|
||||
PRIVATE int mini_senda(struct proc *caller_ptr, asynmsg_t *table, size_t size)
|
||||
{
|
||||
int r = OK, i, dst_p, done, do_notify;
|
||||
int r = OK, dst_p, done, do_notify;
|
||||
unsigned int i;
|
||||
unsigned flags;
|
||||
endpoint_t dst;
|
||||
struct proc *dst_ptr;
|
||||
|
@ -1126,8 +1145,9 @@ PRIVATE int mini_senda(struct proc *caller_ptr, asynmsg_t *table, size_t size)
|
|||
IPC_STATUS_ADD_CALL(dst_ptr, SENDA);
|
||||
RTS_UNSET(dst_ptr, RTS_RECEIVING);
|
||||
} else if (r == OK) {
|
||||
/* Should inform receiver that something is pending */
|
||||
dst_ptr->p_misc_flags |= MF_ASYNMSG;
|
||||
/* Inform receiver that something is pending */
|
||||
set_sys_bit(priv(dst_ptr)->s_asyn_pending,
|
||||
priv(caller_ptr)->s_id);
|
||||
pending_recv = TRUE;
|
||||
}
|
||||
|
||||
|
@ -1164,7 +1184,6 @@ struct proc *caller_ptr;
|
|||
int r;
|
||||
struct priv *privp;
|
||||
struct proc *src_ptr;
|
||||
int postponed = FALSE;
|
||||
|
||||
/* Try all privilege structures */
|
||||
for (privp = BEG_PRIV_ADDR; privp < END_PRIV_ADDR; ++privp) {
|
||||
|
@ -1174,15 +1193,10 @@ struct proc *caller_ptr;
|
|||
src_ptr = proc_addr(privp->s_proc_nr);
|
||||
|
||||
assert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));
|
||||
r = try_one(src_ptr, caller_ptr, &postponed);
|
||||
if (r == OK)
|
||||
if ((r = try_one(src_ptr, caller_ptr)) == OK)
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* Nothing found, clear MF_ASYNMSG unless messages were postponed */
|
||||
if (postponed == FALSE)
|
||||
caller_ptr->p_misc_flags &= ~MF_ASYNMSG;
|
||||
|
||||
return(ESRCH);
|
||||
}
|
||||
|
||||
|
@ -1190,10 +1204,11 @@ struct proc *caller_ptr;
|
|||
/*===========================================================================*
|
||||
* try_one *
|
||||
*===========================================================================*/
|
||||
PRIVATE int try_one(struct proc *src_ptr, struct proc *dst_ptr, int *postponed)
|
||||
PRIVATE int try_one(struct proc *src_ptr, struct proc *dst_ptr)
|
||||
{
|
||||
int r = EAGAIN, i, done, do_notify, pending_recv = FALSE;
|
||||
unsigned flags;
|
||||
/* Try to receive an asynchronous message from 'src_ptr' */
|
||||
int r = EAGAIN, done, do_notify, pending_recv = FALSE;
|
||||
unsigned int flags, i;
|
||||
size_t size;
|
||||
endpoint_t dst;
|
||||
struct proc *caller_ptr;
|
||||
|
@ -1206,9 +1221,10 @@ PRIVATE int try_one(struct proc *src_ptr, struct proc *dst_ptr, int *postponed)
|
|||
size = privp->s_asynsize;
|
||||
table_v = privp->s_asyntab;
|
||||
|
||||
/* Clear table */
|
||||
/* Clear table pending message flag. We're done unless we're not. */
|
||||
privp->s_asyntab = -1;
|
||||
privp->s_asynsize = 0;
|
||||
unset_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id);
|
||||
|
||||
if (size == 0) return(EAGAIN);
|
||||
if (!may_send_to(src_ptr, proc_nr(dst_ptr))) return(EAGAIN);
|
||||
|
@ -1253,12 +1269,8 @@ PRIVATE int try_one(struct proc *src_ptr, struct proc *dst_ptr, int *postponed)
|
|||
* SENDREC and thus should not satisfy the receiving part of the
|
||||
* SENDREC. This message is to be delivered later.
|
||||
*/
|
||||
if ((flags & AMF_NOREPLY) && (dst_ptr->p_misc_flags & MF_REPLY_PEND)) {
|
||||
if (postponed != NULL)
|
||||
*postponed = TRUE;
|
||||
|
||||
if ((flags & AMF_NOREPLY) && (dst_ptr->p_misc_flags & MF_REPLY_PEND))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Destination is ready to receive the message; deliver it */
|
||||
dst_ptr->p_delivermsg = tabent.msg;
|
||||
|
@ -1280,6 +1292,7 @@ PRIVATE int try_one(struct proc *src_ptr, struct proc *dst_ptr, int *postponed)
|
|||
if (!done) {
|
||||
privp->s_asyntab = table_v;
|
||||
privp->s_asynsize = size;
|
||||
set_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id);
|
||||
}
|
||||
|
||||
return(r);
|
||||
|
|
|
@ -599,12 +599,8 @@ int caller_ret; /* code to return on callers */
|
|||
/* Unset pending notification bits. */
|
||||
unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
|
||||
|
||||
/* XXX FIXME: Cleanup should be done for senda() as well. For this to be
|
||||
* done in a realistic way, we need a better implementation of senda
|
||||
* with a bitmap similar to s_notify_pending for notify() rather than
|
||||
* a single global MF_ASYNMSG flag. The current arrangement exposes
|
||||
* several performance issues.
|
||||
*/
|
||||
/* Unset pending asynchronous messages */
|
||||
unset_sys_bit(priv(rp)->s_asyn_pending, priv(rc)->s_id);
|
||||
|
||||
/* Check if process depends on given process. */
|
||||
if (P_BLOCKEDON(rp) == rc->p_endpoint) {
|
||||
|
|
Loading…
Reference in a new issue