diff options
author | Miles Bader <miles@gnu.org> | 1996-01-27 17:08:43 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 1996-01-27 17:08:43 +0000 |
commit | e08da7524e5bbb2c92a2773343ca633be726c3a8 (patch) | |
tree | 4a8436d0451c5af2d1f9f61b8efc9e336487fe46 | |
parent | 79e3fec7afb19f7a6556a9079b8452400af3b7c7 (diff) |
(ports_begin_rpc):
Be interruptable.
Take new MSG_ID arg, and use it to see if the particular rpc shouldn't be
inhibitable.
-rw-r--r-- | libports/begin-rpc.c | 97 |
1 files changed, 60 insertions, 37 deletions
diff --git a/libports/begin-rpc.c b/libports/begin-rpc.c index e86d8f68..73b3646b 100644 --- a/libports/begin-rpc.c +++ b/libports/begin-rpc.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. Written by Michael I. Bushnell. This file is part of the GNU Hurd. @@ -21,52 +21,74 @@ #include "ports.h" #include <cthreads.h> +#define INHIBITED (PORTS_INHIBITED | PORTS_INHIBIT_WAIT) + error_t -ports_begin_rpc (void *portstruct, struct rpc_info *info) +ports_begin_rpc (void *portstruct, mach_msg_id_t msg_id, struct rpc_info *info) { + int *block_flags = 0; + struct port_info *pi = portstruct; mutex_lock (&_ports_lock); - start_over: - - /* If our receive right is gone, then abandon the RPC. */ - if (pi->port_right == MACH_PORT_NULL) - { - mutex_unlock (&_ports_lock); - return EDIED; - } - - /* Check to see if RPC's are inhibited */ - while (_ports_flags & (_PORTS_INHIBITED | _PORTS_INHIBIT_WAIT)) + do { - _ports_flags |= _PORTS_BLOCKED; - condition_wait (&_ports_block, &_ports_lock); - } + /* If our receive right is gone, then abandon the RPC. */ + if (pi->port_right == MACH_PORT_NULL) + { + mutex_unlock (&_ports_lock); + return EDIED; + } - /* Check to see if RPC's are inhibited for this port's bucket */ - if (pi->bucket->flags & (PORT_BUCKET_INHIBITED | PORT_BUCKET_INHIBIT_WAIT)) - { - pi->bucket->flags |= PORT_BUCKET_BLOCKED; - condition_wait (&_ports_block, &_ports_lock); - goto start_over; - } + if (_ports_flags & INHIBITED) + /* All RPC's are inhibited. */ + block_flags = &_ports_flags; + else if (pi->bucket->flags & INHIBITED) + /* RPC's are inhibited for this port's bucket. */ + block_flags = &pi->bucket->flags; + else if (pi->class->flags & INHIBITED) + /* RPC's are inhibited for this port's class. */ + block_flags = &pi->class->flags; + else if (pi->flags & INHIBITED) + /* RPC's are inhibited for this port itself. */ + block_flags = &pi->flags; + else + block_flags = 0; - /* Check to see if RPC's are inhibited for this port's class */ - if (pi->class->flags & (PORT_CLASS_INHIBITED | PORT_CLASS_INHIBIT_WAIT)) - { - pi->class->flags |= PORT_CLASS_BLOCKED; - condition_wait (&_ports_block, &_ports_lock); - goto start_over; - } - - /* Check to see if RPC's are inhibited for this port itself */ - if (pi->flags & (PORT_INHIBITED | PORT_INHIBIT_WAIT)) - { - pi->flags |= PORT_BLOCKED; - condition_wait (&_ports_block, &_ports_lock); - goto start_over; + if (block_flags) + /* We maybe want to block. */ + { + if (msg_id) + /* See if this particular RPC shouldn'be be inhibitable. */ + { + struct ports_msg_id_range *range = pi->class->uninhibitable_rpcs; + while (range) + if (msg_id >= range->start && msg_id < range->end) + { + block_flags = 0; + break; + } + else + range = range->next; + } + + if (block_flags) + { + *block_flags |= PORTS_BLOCKED; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + /* We've been cancelled, just return EINTR. If we were the + only one blocking, PORTS_BLOCKED will still be turned on, + but that's ok, it will just cause a (harmless) extra + condition_broadcast(). */ + { + mutex_unlock (&_ports_lock); + return EINTR; + } + } + } } + while (block_flags); /* Record that that an RPC is in progress */ info->thread = hurd_thread_self (); @@ -80,6 +102,7 @@ ports_begin_rpc (void *portstruct, struct rpc_info *info) pi->class->rpcs++; pi->bucket->rpcs++; _ports_total_rpcs++; + mutex_unlock (&_ports_lock); return 0; |