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_sig_mgr; /* signal manager for system signals */
|
||||||
endpoint_t s_bak_sig_mgr; /* backup 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_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 */
|
irq_id_t s_int_pending; /* pending hardware interrupts */
|
||||||
sigset_t s_sig_pending; /* pending signals */
|
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,
|
FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, endpoint_t dst_e,
|
||||||
message *m_ptr, int flags));
|
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,
|
FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, endpoint_t src,
|
||||||
message *m_ptr, int flags));
|
message *m_ptr, int flags));
|
||||||
FORWARD _PROTOTYPE( int mini_senda, (struct proc *caller_ptr,
|
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,
|
FORWARD _PROTOTYPE( int deadlock, (int function,
|
||||||
register struct proc *caller, endpoint_t src_dst_e));
|
register struct proc *caller, endpoint_t src_dst_e));
|
||||||
FORWARD _PROTOTYPE( int try_async, (struct proc *caller_ptr));
|
FORWARD _PROTOTYPE( int try_async, (struct proc *caller_ptr));
|
||||||
FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr,
|
FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr));
|
||||||
int *postponed));
|
|
||||||
FORWARD _PROTOTYPE( struct proc * pick_proc, (void));
|
FORWARD _PROTOTYPE( struct proc * pick_proc, (void));
|
||||||
FORWARD _PROTOTYPE( void enqueue_head, (struct proc *rp));
|
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 */
|
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 *
|
* mini_send *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -799,7 +834,7 @@ PRIVATE int mini_receive(struct proc * caller_ptr,
|
||||||
*/
|
*/
|
||||||
register struct proc **xpp;
|
register struct proc **xpp;
|
||||||
sys_map_t *map;
|
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));
|
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)) {
|
if (! (caller_ptr->p_misc_flags & MF_REPLY_PEND)) {
|
||||||
map = &priv(caller_ptr)->s_notify_pending;
|
map = &priv(caller_ptr)->s_notify_pending;
|
||||||
|
|
||||||
/* Either check a specific bit in the pending notifications mask, or
|
/* Check for pending notifications */
|
||||||
* find the first bit set in it (if any), depending on whether the
|
if ((src_id = has_pending(map, src_p)) != NULL_PRIV_ID) {
|
||||||
* 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) {
|
|
||||||
endpoint_t hisep;
|
endpoint_t hisep;
|
||||||
|
|
||||||
src_proc_nr = id_to_nr(src_id); /* get source proc */
|
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(). */
|
/* Check for pending asynchronous messages */
|
||||||
if (caller_ptr->p_misc_flags & MF_ASYNMSG) {
|
map = &priv(caller_ptr)->s_asyn_pending;
|
||||||
if (src_e != ANY)
|
|
||||||
r = try_one(proc_addr(src_p), caller_ptr, NULL);
|
if (has_pending(map, src_p) != NULL_PRIV_ID) {
|
||||||
|
if (src_p != ANY)
|
||||||
|
r = try_one(proc_addr(src_p), caller_ptr);
|
||||||
else
|
else
|
||||||
r = try_async(caller_ptr);
|
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)
|
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;
|
unsigned flags;
|
||||||
endpoint_t dst;
|
endpoint_t dst;
|
||||||
struct proc *dst_ptr;
|
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);
|
IPC_STATUS_ADD_CALL(dst_ptr, SENDA);
|
||||||
RTS_UNSET(dst_ptr, RTS_RECEIVING);
|
RTS_UNSET(dst_ptr, RTS_RECEIVING);
|
||||||
} else if (r == OK) {
|
} else if (r == OK) {
|
||||||
/* Should inform receiver that something is pending */
|
/* Inform receiver that something is pending */
|
||||||
dst_ptr->p_misc_flags |= MF_ASYNMSG;
|
set_sys_bit(priv(dst_ptr)->s_asyn_pending,
|
||||||
|
priv(caller_ptr)->s_id);
|
||||||
pending_recv = TRUE;
|
pending_recv = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1164,7 +1184,6 @@ struct proc *caller_ptr;
|
||||||
int r;
|
int r;
|
||||||
struct priv *privp;
|
struct priv *privp;
|
||||||
struct proc *src_ptr;
|
struct proc *src_ptr;
|
||||||
int postponed = FALSE;
|
|
||||||
|
|
||||||
/* Try all privilege structures */
|
/* Try all privilege structures */
|
||||||
for (privp = BEG_PRIV_ADDR; privp < END_PRIV_ADDR; ++privp) {
|
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);
|
src_ptr = proc_addr(privp->s_proc_nr);
|
||||||
|
|
||||||
assert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));
|
assert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));
|
||||||
r = try_one(src_ptr, caller_ptr, &postponed);
|
if ((r = try_one(src_ptr, caller_ptr)) == OK)
|
||||||
if (r == OK)
|
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing found, clear MF_ASYNMSG unless messages were postponed */
|
|
||||||
if (postponed == FALSE)
|
|
||||||
caller_ptr->p_misc_flags &= ~MF_ASYNMSG;
|
|
||||||
|
|
||||||
return(ESRCH);
|
return(ESRCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1190,10 +1204,11 @@ struct proc *caller_ptr;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* try_one *
|
* 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;
|
/* Try to receive an asynchronous message from 'src_ptr' */
|
||||||
unsigned flags;
|
int r = EAGAIN, done, do_notify, pending_recv = FALSE;
|
||||||
|
unsigned int flags, i;
|
||||||
size_t size;
|
size_t size;
|
||||||
endpoint_t dst;
|
endpoint_t dst;
|
||||||
struct proc *caller_ptr;
|
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;
|
size = privp->s_asynsize;
|
||||||
table_v = privp->s_asyntab;
|
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_asyntab = -1;
|
||||||
privp->s_asynsize = 0;
|
privp->s_asynsize = 0;
|
||||||
|
unset_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id);
|
||||||
|
|
||||||
if (size == 0) return(EAGAIN);
|
if (size == 0) return(EAGAIN);
|
||||||
if (!may_send_to(src_ptr, proc_nr(dst_ptr))) 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 and thus should not satisfy the receiving part of the
|
||||||
* SENDREC. This message is to be delivered later.
|
* SENDREC. This message is to be delivered later.
|
||||||
*/
|
*/
|
||||||
if ((flags & AMF_NOREPLY) && (dst_ptr->p_misc_flags & MF_REPLY_PEND)) {
|
if ((flags & AMF_NOREPLY) && (dst_ptr->p_misc_flags & MF_REPLY_PEND))
|
||||||
if (postponed != NULL)
|
|
||||||
*postponed = TRUE;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/* Destination is ready to receive the message; deliver it */
|
/* Destination is ready to receive the message; deliver it */
|
||||||
dst_ptr->p_delivermsg = tabent.msg;
|
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) {
|
if (!done) {
|
||||||
privp->s_asyntab = table_v;
|
privp->s_asyntab = table_v;
|
||||||
privp->s_asynsize = size;
|
privp->s_asynsize = size;
|
||||||
|
set_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(r);
|
return(r);
|
||||||
|
|
|
@ -599,12 +599,8 @@ int caller_ret; /* code to return on callers */
|
||||||
/* Unset pending notification bits. */
|
/* Unset pending notification bits. */
|
||||||
unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
|
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
|
/* Unset pending asynchronous messages */
|
||||||
* done in a realistic way, we need a better implementation of senda
|
unset_sys_bit(priv(rp)->s_asyn_pending, priv(rc)->s_id);
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Check if process depends on given process. */
|
/* Check if process depends on given process. */
|
||||||
if (P_BLOCKEDON(rp) == rc->p_endpoint) {
|
if (P_BLOCKEDON(rp) == rc->p_endpoint) {
|
||||||
|
|
Loading…
Reference in a new issue