diff options
author | Miles Bader <miles@gnu.org> | 1995-12-27 21:46:29 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 1995-12-27 21:46:29 +0000 |
commit | b815fe0a4b061cf4e83be6ec8a37adde2a9ccf4e (patch) | |
tree | e42747e18adbdea4ed70c6a21b9fa106d2e11cc7 /libports/interrupt-notified-rpcs.c | |
parent | 8e58b40a959ef8b93c75cc7ddb8bc08abafd1a50 (diff) |
Initial revision
Diffstat (limited to 'libports/interrupt-notified-rpcs.c')
-rw-r--r-- | libports/interrupt-notified-rpcs.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/libports/interrupt-notified-rpcs.c b/libports/interrupt-notified-rpcs.c new file mode 100644 index 00000000..a88e398a --- /dev/null +++ b/libports/interrupt-notified-rpcs.c @@ -0,0 +1,114 @@ +/* Handle interruping rpcs because of notification + + Copyright (C) 1995 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "ports.h" + +/* A linked list of ports for which notification has been requested. */ +struct ports_notify *_ports_notifications = 0; + +/* Free lists for notify structures. */ +struct ports_notify *_ports_free_ports_notifies = 0; +struct rpc_notify *_ports_free_rpc_notifies = 0; + +/* Interrupt any rpcs on OBJECT that have requested such. */ +void +ports_interrupt_notified_rpcs (void *object, + mach_port_t port, mach_msg_id_t what) +{ + struct ports_notify *np; + + mutex_lock (&_ports_lock); + for (np = _ports_notifications; np; np = np->next) + if (np->port == port && np->what == what) + { + struct rpc_notify *req; + for (req = np->reqs; req; req = req->next_req) + if (req->pending) + { + req->pending--; + hurd_thread_cancel (req->rpc->thread); + } + break; + } + mutex_unlock (&_ports_lock); +} + +static void +remove_req (struct rpc_notify *req) +{ + struct ports_notify *np = req->notify; + + /* Take REQ out of the list of notified rpcs. */ + if (req->next_req) + req->next_req->prev_req_p = req->prev_req_p; + *req->prev_req_p = req->next_req; + + if (np->reqs == 0) + /* Now NP has no more reqests, so we can free it too. */ + { + /* Take NP out of the active list... */ + if (np->next) + np->next->prevp = np->prevp; + *np->prevp = np->next; + + /* And put it on the free list. */ + np->next = _ports_free_ports_notifies; + _ports_free_ports_notifies = np; + + if (np->pending) + /* And cancel the associated notification. */ + { + mach_port_t old; + error_t err = + mach_port_request_notification (mach_task_self (), np->port, + np->what, 0, MACH_PORT_NULL, + MACH_MSG_TYPE_MAKE_SEND_ONCE, + &old); + if (! err && old != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), old); + } + } +} + +/* Remove RPC from the list of notified rpcs, cancelling any pending + notifications. _PORTS_LOCK should be held. */ +void +_ports_remove_notified_rpc (struct rpc_info *rpc) +{ + struct rpc_notify *req = rpc->notifies; + + if (req) + /* Cancel RPC's notify requests. */ + { + struct rpc_notify *last = req; + + while (last->next) + { + remove_req (last); + last = last->next; + } + remove_req (last); + + /* Put the whole chain on the free list. */ + last->next = _ports_free_rpc_notifies; + _ports_free_rpc_notifies = req; + } +} + |