diff options
Diffstat (limited to 'libports')
57 files changed, 4035 insertions, 0 deletions
diff --git a/libports/ChangeLog b/libports/ChangeLog new file mode 100644 index 00000000..1d2c0061 --- /dev/null +++ b/libports/ChangeLog @@ -0,0 +1,499 @@ +Sat Mar 6 17:05:45 1999 Thomas Bushnell, BSG <tb@mit.edu> + + * notify-dead-name.c (ports_do_mach_notify_dead_name): Deallocate + newly created reference to DEAD_NAME. + +1999-02-28 Roland McGrath <roland@baalperazim.frob.com> + + * destroy-right.c (ports_destroy_right): Return error_t (always 0). + * ports.h: Update decl. + + * bucket-iterate.c (_ports_bucket_class_iterate): New function, + transmorgified from ports_bucket_iterate. + (ports_bucket_iterate): Now just call that to do the work. + * class-iterate.c: New file. + (ports_class_iterate): New function. + * ports.h: Declare ports_class_iterate and _ports_bucket_class_iterate. + * Makefile (SRCS): Add class-iterate.c. + +Thu Feb 25 10:31:57 1999 Thomas Bushnell, BSG <tb@mit.edu> + + * end-rpc.c (ports_end_rpc): Signal ports_block anytime an rpc + ends and someone is waiting on an inhibition. + +1999-01-01 Roland McGrath <roland@baalperazim.frob.com> + + * interrupt-on-notify.c (ports_interrupt_self_on_notification): Use + assert to check we are in an rpc; don't return EIEIO (not appropriate). + +1997-08-14 Miles Bader <miles@gnu.ai.mit.edu> + + * interrupt-rpcs.c (ports_interrupt_rpcs): Put RPC into the + interrupted list. + * end-rpc.c (ports_end_rpc): Call ports_self_interrupted to remove + the current thread from the interrupted list. + * ports.h (ports_self_interrupted): New declaration. + (struct rpc_info): Add interrupted_next field. + * Makefile (SRCS): Add interrupted.c. + +Wed Aug 20 13:56:40 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * manage-multithread.c (ports_manage_port_operations_multithread): + Drop parms `wire_cthreads' and `wire_threads'. Add parm `hook'. + (thread_function): Call HOOK instead of cthread_wire and/or + thread_wire. + * ports.h (ports_manage_port_operations_multithread): Adjust + declaration. + +Fri Feb 14 00:51:32 1997 Miles Bader <miles@gnu.ai.mit.edu> + + * create-bucket.c (ports_create_bucket): Initialize rpcs, flags, & + count fields in RET. + +Thu Sep 12 16:19:35 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * Makefile (HURDLIBS): New variable. + (libports.so): Delete special depedency. + +Wed Aug 7 15:28:48 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * ports.h (_ports_create_port_internal, + ports_create_port_noinstall): New declarations. + +Thu Jul 18 22:59:14 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * Makefile (SRCS): Add create-port-noinstall.c and create-internal.c. + * create-port-noinstall.c: New file. + * create-port.c (ports_create_port): Guts deleted; call new work + function. + * create-internal.c: New file; all the guts from create-port.c. + +Wed Jul 3 14:13:53 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * get-right.c (ports_get_right): Supply correct sync value in + notification request. + +Mon May 6 16:33:55 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * ports.h (ports_allocate_port, ports_intern_external_port): + Delete obsolete declarations. + * allocate-port.c, intern-external-port.c: Delete files. + * Makefile (SRCS): Delete `intern-external-port.c' and + `allocate-port.c'. + +Sun Apr 28 15:22:58 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> + + * allocate-port.c: Add obsolescence link warning. + * intern-external-port.c: Add obsolescence link warning. + +Fri Mar 29 15:21:31 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * end-rpc.c (ports_end_rpc): Acquire _PORTS_LOCK before calling + _ports_remove_notified_rpc. + +Fri Mar 29 09:04:53 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * reallocate-from-external.c (ports_reallocate_from_external): + Require port to have a current port right. + * reallocate-port.c (ports_reallocate_port): Likewise. + + * complete-deallocate.c (_ports_complete_deallocate): Only drop + port right if it isn't already null. + + * transfer-right.c: New file. + * Makefile (SRCS): Add transfer-right.c. + * ports.h (ports_claim_right): Doc fix. + (ports_transfer_right): New function. + +Thu Mar 28 10:47:58 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * claim-right.c (ports_claim_right): Take right out of port + bucket. + + * manage-multithread.c (ports_manage_port_operations_multithread): + Fill in meaningful statuses and errors rather than just zero. + * manage-one-thread.c (ports_manage_port_operations_one_thread): + Likewise. + + * begin-rpc.c (ports_begin_rpc): Return EOPNOTSUPP, not EDIED, if + receive right is gone. + + * manage-one-thread.c (ports_manage_port_operations_one_thread): + Fill in default reply before doing work; we might return 0 and + mach_msg_server expects us to fill in a reply decently no matter + what. + (ports_manage_port_operations_multithread): Likewise. + + * claim-right.c (ports_claim_right): Hold lock until sendright + frobbing is finished. + +Wed Mar 20 13:32:13 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * destroy-right.c (ports_destroy_right): Don't do anything if port + has already been destroyed. + + * ports.h (ports_claim_right): New declaration. + * claim-right.c: New file. + * Makefile (SRCS): Add `claim-right.c'. + +Tue Mar 5 17:28:54 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * get-right.c (ports_get_right): Check mach_port_request_notification + for error returns, against all odds. + +Mon Feb 26 17:10:38 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * interrupt-on-notify.c (ports_interrupt_rpc_on_notification): + Only set _PORTS_NOTIFICATIONS->prevp if _PORTS_NOTIFICATIONS != 0. + Likewise for PN->prev_req_p. + +Fri Jan 26 00:45:58 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * inhibit-class-rpcs.c (ports_inhibit_class_rpcs): Whoops, we + still have the lock when hurd_condition_wait gets cancelled. + * import-port.c (ports_import_port): Likewise. + * create-port.c (ports_create_port): Likewise. + * inhibit-bucket-rpcs.c (ports_inhibit_bucket_rpcs): Likewise. + * inhibit-all-rpcs.c (ports_inhibit_all_rpcs): Likewise. + * inhibit-port-rpcs.c (ports_inhibit_port_rpcs): Likewise. + + * import-port.c (ports_import_port): Don't lose a send right on + PORT when we return an error. + * create-port.c (ports_create_port): Delete the receive right, not + the send right when we return an error. + +Thu Jan 25 12:10:48 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * manage-multithread.c (ports_manage_port_operations_multithread): + Pass INP->msgh_id, not INP to ports_begin_rpc. + * manage-one-thread.c (ports_manage_port_operations_one_thread): Ditto. + +Wed Jan 24 14:02:30 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * inhibit-all-rpcs.c (ports_inhibit_all_rpcs): Be interruptable; + return EINTR if interrupted, or EBUSY if already inhibited. + * inhibit-class-rpcs.c (ports_inhibit_class_rpcs): Likewise. + * inhibit-port-rpcs.c (ports_inhibit_port_rpcs): Likewise. + * inhibit-bucket-rpcs.c (ports_inhibit_bucket_rpcs): Likewise. + * begin-rpc.c (ports_begin_rpc): Be interruptable. + * create-port.c (ports_create_port): New function. + * import-port.c (ports_import_port): New function. + * allocate-port.c (ports_allocate_port): Call ports_create_port. + * intern-external-port.c (ports_intern_external_port): Call + ports_import_port. + * ports.h (ports_create_port, ports_import_ports): New declarations. + (PORTS_INHIBITED, PORTS_BLOCKED, PORTS_INHIBIT_WAIT, PORTS_NO_ALLOC, + PORTS_ALLOC_WAIT): New macros (global values for common flags). + (PORT_BLOCKED, PORT_INHIBITED, PORT_INHIBIT_WAIT, + PORT_BUCKET_INHIBITED, PORT_BUCKET_BLOCKED, PORT_BUCKET_INHIBIT_WAIT, + PORT_BUCKET_NO_ALLOC, PORT_BUCKET_ALLOC_WAIT, PORT_CLASS_INHIBITED, + PORT_CLASS_BLOCKED, PORT_CLASS_INHIBIT_WAIT, PORT_CLASS_NO_ALLOC, + PORT_CLASS_ALLOC_WAIT, _PORTS_INHIBITED, _PORTS_BLOCKED, + _PORTS_INHIBIT_WAIT): Redefine using global flag values. + (ports_inhibit_port_rpcs, ports_inhibit_all_rpcs, + ports_inhibit_class_rpcs, ports_inhibit_bucket_rpcs): Return error_t. + (ports_interupt_rpcs): Renamed from port_interrupt_rpc. + + * begin-rpc.c (ports_begin_rpc): Take new MSG_ID arg, and use it to + see if the particular rpc shouldn't be inhibitable. + * manage-multithread.c (ports_manage_port_operations_multithread): + Pass INP to ports_begin_rpc, and only call DEMUXER if it returns 0. + * manage-one-thread.c (ports_manage_port_operations_one_thread): Ditto. + * ports.h (ports_begin_rpc): Add MSG_ID arg. + (struct port_class): Add uninhibitable_rpcs field. + (struct ports_msg_id_range): New structure. + (ports_default_uninhibitable_rpcs): New declaration. + * create-class.c (ports_create_class): Initialize the + uninhibitable_rpcs field. + * default-uninhibitable-rpcs.c (interrupt_operation_ids, + ports_default_uninhibitable_rpcs): New variables. + * Makefile (SRCS): Add default-uninhibitable-rpcs.c. + + * interrupt-rpcs.c (ports_interrupt_rpcs): Renamed from + ports_interrupt_rpc. + * Makefile (SRCS): Rename interrupt-rpc.c to interrupt-rpcs.c. + * interrupt-operation.c (ports_S_interrupt_operation): Use + ports_interrupt_rpcs instead of ports_interrupt_rpc. + * no-senders.c (ports_no_senders): Likewise. + + * manage-multithread.c (ports_manage_port_operations_multithread): + Fix spelling of cancel_threshold (was cancel_threshhold). + * interrupt-operation.c (ports_S_interrupt_operation): Likewise. + * ports.h (struct port_info): Likewise. + * reallocate-from-external.c (ports_reallocate_from_external): Ditto. + * reallocate-port.c (ports_reallocate_port): Likewise. + +Wed Jan 17 13:08:49 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * no-senders.c (ports_no_senders): Interrupt RPCs on PI too. Only + do the ports_interrupt_notified_rpcs() if we're actually losing a ref. + +Fri Jan 5 16:40:34 1996 Miles Bader <miles@gnu.ai.mit.edu> + + * interrupt-on-notify.c (ports_interrupt_rpc_on_notification): + If PORT is dead or bogus, interrupt RPC immediately, and don't add + a new request. + +Thu Dec 28 14:27:41 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> + + * interrupt-on-notify.c (ports_interrupt_rpc_on_notification): If + NEW_REQ is not needed, put it on the free list, don't call free on it. + +Thu Dec 28 11:04:06 1995 Miles Bader <miles@gnu.ai.mit.edu> + + * ports.h (ports_interrupt_self_on_port_death): New macro. + + * interrupt-notified-rpcs.c (ports_interrupt_notified_rpcs): Only + bother to lock _PORTS_LOCK if there are notifications. + +Wed Dec 27 16:27:47 1995 Miles Bader <miles@gnu.ai.mit.edu> + + * ports.h (struct rpc_info): Get rid of next_notified/prev_notified_p. + (struct rpc_notify): Get rid of port, what, next fields, and add + rpc, notify, next, pending, next_req, and prev_req_p fields. + (struct ports_notify): New structure. + (_ports_notified_rpcs): Declaration removed. + (_ports_notifications): New declaration. + (_ports_free_ports_notifies): New declaration. + Include <mach/notify.h>. + * interrupt-on-notify.c (ports_interrupt_rpc_on_notification): + Mostly rewrite to use new scheme. + * interrupt-notified-rpcs (_ports_notified_rpcs): Variable removed. + (_ports_notifications, _ports_free_ports_notifications): New variables. + (ports_interrupt_notified_rpcs): Rewrite to use new scheme. + (_ports_remove_notified_rpc): Ditto. + (cancel_notification): Function removed. + (remove_req): New function. + +Tue Dec 26 14:39:51 1995 Miles Bader <miles@gnu.ai.mit.edu> + + * interrupt-notified-rpcs.c (_ports_notified_rpcs, + _ports_free_rpc_notifies): New variables. + (ports_interrupt_notified_rpcs, cancel_notification, + _ports_remove_notified_rpc): New functions. + * interrupt-on-notify.c (ports_interrupt_rpc_on_notification, + ports_interrupt_self_on_notification): New functions, new file. + * ports.h (struct rpc_notify): New structure. + (struct rpc_info): Add rpc_notifies, rpc_next_notified, and + prev_notified_p fields. + (_ports_notified_rpcs, _ports_free_rpc_notifies, + _ports_remove_notified_rpc, ports_interrupt_rpc_on_notification, + ports_interrupt_notified_rpcs, ports_interrupt_self_on_notification): + New declarations. + * begin-rpc.c (ports_begin_rpc): Initialize the notifies field. + * end-rpc.c (ports_end_rpc): Get rid of any rpc notifications. + * no-senders.c (ports_no_senders): Interrupt any rpcs requesting such. + * dead-name.c (ports_dead_name): New function. + * notify-dead-name.c (ports_do_mach_notify_dead_name): Call + ports_dead_name(). + * Makefile (SRCS): Add interrupt-on-notify.c, + interrupt-notified-rpcs.c, and dead-name.c. + +Tue Nov 21 22:04:28 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> + + * manage-multithread.c: Don't wire timeouts to zero. + +Tue Nov 21 09:42:00 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * ports.h (ports_do_mach_notify_dead_name): Declare `extern + kern_return_t'. + (ports_do_mach_notify_msg_accepted): Likewise. + (ports_do_mach_notify_no_senders): Likewise. + (ports_do_mach_notify_port_deleted): Likewise. + (ports_do_mach_notify_port_destroyed): Likewise. + (ports_do_mach_notify_send_once): Likewise. + * notify-send-once.c: Include "notify_S.h". + * notify-port-deleted.c: Likewise. + * notify-msg-accepted.c: Likewise. + * notify-port-destroyed.c: Likewise. + * notify-no-senders.c: Likewise. + * notify-dead-name.c: Likewise. + + * ports.h (struct port_info): New member `cancel_threshhold'. + (ports_S_interrupt_operation): Include seqno arg; declare extern + kern_return_t. + * interrupt-operation.c: Include "interrupt_S.h". + (ports_S_interrupt_operation): Set PI->cancel_threshhold if the + incoming seqno is greater than the current threshhold. + * manage-multithread.c + (ports_manage_port_operations_multithread/internal_demuxer): If + the incoming RPC has already been cancelled, then call + hurd_thread_cancel before the user's demuxer. + * manage-one-thread.c (ports_manage_port_operations_one_thread): + Doc fix. + * intern-external-port.c (ports_intern_external_port): Initialize + PI->cancel_threshhold. + * allocate-port.c (ports_allocate_port): Likewise. + * reallocate-from-external.c (ports_reallocate_from_external): + Clear PI->cancel_threshhold. + * reallocate-port.c (ports_reallocate_port): Likewise. + +Sat Nov 18 08:50:13 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> + + * inhibit-all-rpcs.c: If calling thread is serving an RPC, don't + block waiting for that RPC to finish. + * inhibit-class-rpcs.c: Likewise. + * inhibit-bucket-rpcs.c: Likewise. + * inhibit-port-rpcs.c: Likewise. + + * inhibit-all-rpcs.c (ports_inhibit_all_rpcs): Renamed from + inhibit_all_rpcs. + +Tue Oct 24 13:32:39 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> + + * manage-multithread.c + (ports_manage_port_operations_multithread/internal_demuxer): Don't + attempt RPC if we can't get a valid port struct. + * manage-one-thread.c + (ports_manage_port_operations_one_thread/internal_demuxer): Likewise. + +Mon Oct 9 14:57:48 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> + + * Makefile: Specify shared library dependencies. + +Fri Sep 22 10:19:17 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> + + * ports.h: Include hurd.h. + +Fri Sep 8 14:44:03 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu> + + * end-rpc.c (ports_end_rpc): Call hurd_check_cancel. + +Wed Sep 6 11:20:20 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> + + * ports.h (ports_interrupt_server, ports_S_interrupt_operation): + New declarations. + * Makefile (OBJS): Add interruptServer.o. + (SRCS): Add interrupt-operation.c. + * interrupt-operation.c: New file. + + * ports.h (ports_notify_server, ports_do_mach_notify_*): New decls. + * Makefile (MIGCOMSFLAGS): New variable. + (OBJS): Added notifyServer.o. + (SRCS): Added notify-dead-name.c, notify-no-senders.c, + notify-port-destroyed.c, notify-msg-accepted.c, + notify-port-deleted.c, and notify-send-once.c. + * notify-dead-name.c: New file. + * notify-no-senders.c: New file. + * notify-port-destroyed.c: New file. + * notify-msg-accepted.c: New file. + * notify-port-deleted.c: New file. + * notify-send-once.c: New file. + +Wed Aug 30 16:00:36 1995 Miles Bader <miles@geech.gnu.ai.mit.edu> + + * inhibit-port-rpcs.c (inhibit_port_rpcs): Renamed to + `ports_inhibit_port_rpcs'. + +Tue Aug 29 15:59:49 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu> + + * manage-multithread.c (ports_manage_port_operations_multithread): + Hammer WIRE_CTHREADS on for now. + +Thu Aug 24 10:25:52 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> + + * inhibit-port-rpcs.c (inhibit_port_rpcs): thread_cancel -> + hurd_thread_cancel. Include <hurd.h>. + * inhibit-class-rpcs.c (ports_inhibit_class_rpcs): Ditto. + * inhibit-bucket-rpcs.c (ports_inhibit_bucket_rpcs): Ditto. + * interrupt-rpc.c (ports_interrupt_rpc): Ditto. + * inhibit-all-rpcs.c (inhibit_all_rpcs): Ditto. + + * Makefile (OBJS): Use :.c=.o notation. + +Wed Aug 23 15:03:11 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> + + * Makefile (REMHDRS): Removed. + Order changed a bit. + +Fri Jul 21 11:45:22 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> + + * get-right.c (ports_get_right): If the right is null (because we + are closing down), then just return null. (This helps in a race + in ufs/ex2fs). + + * complete-deallocate.c (_ports_complete_deallocate): Clear + PI->port_right; and do it before releasing _ports_lock. + + * manage-multithread.c (ports_manage_port_operations_multithread): + For now, wire GLOBAL_TIMEOUT and THREAD_TIMEOUT to zero. + +Tue Jul 18 14:29:49 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> + + * manage-multithread.c (ports_manage_port_operations_multithread) + [thread_function]: Return int. Don't cthread_exit child threads; + just let them return normally. + +Wed Jul 12 13:32:22 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> + + * resume-class-rpcs.c (ports_resume_class_rpcs): Clear blocked + flag using correct name. + + * manage-multithread.c (ports_manage_port_operations_multithread) + [internal_demuxer]: Increment NREQTHREADS and TOTALTHREADS + *before* forking newthread. + [thread_function]: Don't increment NREQTHREADS and TOTALTHREADS here. + Initialize NREQTHREADS and TOTALTHREADS in main body of function. + +Sat Jul 8 15:10:50 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> + + * allocate-port.c (ports_allocate_port): Properly add PI to + CLASS's port list when the list is empty (why did this work before?). + * intern-external-port.c (ports_intern_external_port): Ditto. + * begin-rpc.c (ports_begin_rpc): Ditto adding INFO to PI's + current_rpcs list. + * create-class.c (ports_create_class): Initialize the PORTS and + COUNT fields. + +Thu Jul 6 15:36:57 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> + + * Makefile: Removed dependencies that are now automatically + generated. + +Tue Jun 27 15:28:54 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> + + * Makefile (SRCS): Add it *back*. + * stubs.c: New file. + +Mon Jun 26 16:51:42 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> + + * ports.h: Fix spelling error. + + * manage-multithread.c (ports_manage_port_operations_multithread): + Declare NREQTHREADS asd TOTALTHREADS volatile. + + * manage-multithread.c + (ports_manage_port_operations_multithread/thread_function): Don't + hold lock while setting TIMEOUT. + When master goes back to wait for messages, it should unlock LOCK. + Declare ERR inside THREAD_FUNCTION so it doesn't get shared by + multiple threads. + +Thu Jun 22 11:28:56 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> + + * get-right.c (ports_get_right): Parenthesize flag test correctly. + * reallocate-from-external.c (ports_reallocate_from_external): + Likewise. + + * enable-bucket.c (ports_enable_bucket): Clean flag correctly. + + * lookup-port.c (ports_lookup_port): UNlock port lock at exit of + function. + + * bucket-iterate.c: Include <hurd/ihash.h> and <cthreads.h>. + (ports_bucket_iterate): Fix decl of NXT. + +Wed Jun 21 14:25:04 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> + + * Makefile (SRCS): Added bucket-iterate.c. + * bucket-iterate.c: New file. + * ports.h (port_bucket_iterate): New decl. + +Tue Jun 20 12:35:44 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> + + * enable-bucket.c: Include <cthreads.h>. + * enable-class.c: Likewise. + * count-bucket.c: Likewise. + + * libports/lookup-port.c (ports_lookup_port): Remove assignment + from if test. diff --git a/libports/Makefile b/libports/Makefile new file mode 100644 index 00000000..2cc38d63 --- /dev/null +++ b/libports/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 1995,96,97,99 Free Software Foundation, Inc. +# Written by Michael I. Bushnell. +# +# This file is part of the GNU Hurd. +# +# The GNU Hurd 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. +# +# The GNU Hurd 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. + +dir := libports +makemode := library + +libname = libports +SRCS = create-bucket.c create-class.c \ + reallocate-port.c reallocate-from-external.c destroy-right.c \ + lookup-port.c port-ref.c port-ref-weak.c port-deref.c port-deref-weak.c \ + no-senders.c begin-rpc.c end-rpc.c manage-one-thread.c manage-multithread.c \ + inhibit-port-rpcs.c inhibit-class-rpcs.c inhibit-bucket-rpcs.c \ + inhibit-all-rpcs.c resume-port-rpcs.c resume-class-rpcs.c \ + resume-bucket-rpcs.c resume-all-rpcs.c interrupt-rpcs.c \ + init.c complete-deallocate.c get-right.c count-class.c count-bucket.c \ + enable-class.c enable-bucket.c bucket-iterate.c class-iterate.c stubs.c \ + notify-dead-name.c notify-no-senders.c notify-port-destroyed.c \ + notify-msg-accepted.c notify-port-deleted.c notify-send-once.c \ + interrupt-operation.c interrupt-on-notify.c interrupt-notified-rpcs.c \ + dead-name.c create-port.c import-port.c default-uninhibitable-rpcs.c \ + claim-right.c transfer-right.c create-port-noinstall.c create-internal.c \ + interrupted.c + +LCLHDRS = ports.h +installhdrs = ports.h + +HURDLIBS= ihash +OBJS = $(SRCS:.c=.o) notifyServer.o interruptServer.o + +MIGCOMSFLAGS = -prefix ports_ + +include ../Makeconf diff --git a/libports/allocate-port.c b/libports/allocate-port.c new file mode 100644 index 00000000..61e093c8 --- /dev/null +++ b/libports/allocate-port.c @@ -0,0 +1,38 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" + +/* Backward compatibility. */ +void *ports_allocate_port (struct port_bucket *bucket, + size_t size, + struct port_class *class) +{ + void *result; + if (ports_create_port (class, bucket, size, &result)) + result = 0; + return result; +} + + +#include "linkwarn.h" + +link_warning (ports_allocate_port, + "ports_allocate_port is obsolete; use ports_create_port instead") diff --git a/libports/begin-rpc.c b/libports/begin-rpc.c new file mode 100644 index 00000000..ebe3473c --- /dev/null +++ b/libports/begin-rpc.c @@ -0,0 +1,111 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> + +#define INHIBITED (PORTS_INHIBITED | PORTS_INHIBIT_WAIT) + +error_t +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); + + do + { + /* If our receive right is gone, then abandon the RPC. */ + if (pi->port_right == MACH_PORT_NULL) + { + mutex_unlock (&_ports_lock); + return EOPNOTSUPP; + } + + 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; + + 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 (); + info->next = pi->current_rpcs; + info->notifies = 0; + if (pi->current_rpcs) + pi->current_rpcs->prevp = &info->next; + info->prevp = &pi->current_rpcs; + pi->current_rpcs = info; + + pi->class->rpcs++; + pi->bucket->rpcs++; + _ports_total_rpcs++; + + mutex_unlock (&_ports_lock); + + return 0; +} + + diff --git a/libports/bucket-iterate.c b/libports/bucket-iterate.c new file mode 100644 index 00000000..1bfd73e3 --- /dev/null +++ b/libports/bucket-iterate.c @@ -0,0 +1,80 @@ +/* Iterate a function over the ports in a bucket. + Copyright (C) 1995, 1999 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "ports.h" +#include <cthreads.h> +#include <hurd/ihash.h> + + +/* Internal entrypoint for both ports_bucket_iterate and ports_class_iterate. + If CLASS is non-null, call FUN only for ports in that class. */ +error_t +_ports_bucket_class_iterate (struct port_bucket *bucket, + struct port_class *class, + error_t (*fun)(void *)) +{ + /* This is obsecenely ineffecient. ihash and ports need to cooperate + more closely to do it effeciently. */ + struct item + { + struct item *next; + void *p; + } *list = 0; + struct item *i, *nxt; + error_t err; + + error_t enqueue (void *arg) + { + struct port_info *const pi = arg; + struct item *j; + + if (class == 0 || pi->class == class) + { + j = malloc (sizeof (struct item)); + j->next = list; + j->p = pi; + list = j; + pi->refcnt++; + } + return 0; + } + + mutex_lock (&_ports_lock); + ihash_iterate (bucket->htable, enqueue); + mutex_unlock (&_ports_lock); + + err = 0; + for (i = list; i; i = nxt) + { + if (!err) + err = (*fun)(i->p); + ports_port_deref (i->p); + nxt = i->next; + free (i); + } + return err; +} + +error_t +ports_bucket_iterate (struct port_bucket *bucket, + error_t (*fun)(void *)) +{ + return _ports_bucket_class_iterate (bucket, 0, fun); +} diff --git a/libports/claim-right.c b/libports/claim-right.c new file mode 100644 index 00000000..2ddb3aaa --- /dev/null +++ b/libports/claim-right.c @@ -0,0 +1,52 @@ +/* Take a receive right away from a port + Copyright (C) 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell, p/BSG. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + + +#include "ports.h" +#include <hurd/ihash.h> + +mach_port_t +ports_claim_right (void *portstruct) +{ + struct port_info *pi = portstruct; + mach_port_t ret; + + if (pi->port_right != MACH_PORT_NULL) + { + ret = pi->port_right; + + mutex_lock (&_ports_lock); + ihash_locp_remove (pi->bucket->htable, pi->hentry); + mach_port_move_member (mach_task_self (), ret, MACH_PORT_NULL); + pi->port_right = MACH_PORT_NULL; + if (pi->flags & PORT_HAS_SENDRIGHTS) + { + pi->flags &= ~PORT_HAS_SENDRIGHTS; + mutex_unlock (&_ports_lock); + ports_port_deref (pi); + } + else + mutex_unlock (&_ports_lock); + } + else + ret = MACH_PORT_NULL; + return ret; +} + diff --git a/libports/class-iterate.c b/libports/class-iterate.c new file mode 100644 index 00000000..1e349497 --- /dev/null +++ b/libports/class-iterate.c @@ -0,0 +1,37 @@ +/* Iterate a function over the ports in a class. + Copyright (C) 1999 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "ports.h" +#include <cthreads.h> +#include <hurd/ihash.h> + +error_t +ports_class_iterate (struct port_class *class, + error_t (*fun)(void *)) +{ + mutex_lock (&_ports_lock); + if (class->ports != 0) + { + struct port_bucket *bucket = class->ports->bucket; + mutex_unlock (&_ports_lock); + return _ports_bucket_class_iterate (bucket, class, fun); + } + mutex_unlock (&_ports_lock); + return 0; +} diff --git a/libports/complete-deallocate.c b/libports/complete-deallocate.c new file mode 100644 index 00000000..a94ab171 --- /dev/null +++ b/libports/complete-deallocate.c @@ -0,0 +1,53 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <assert.h> +#include <hurd/ihash.h> +#include <cthreads.h> + +void +_ports_complete_deallocate (struct port_info *pi) +{ + assert ((pi->flags & PORT_HAS_SENDRIGHTS) == 0); + + if (pi->port_right) + { + ihash_locp_remove (pi->bucket->htable, pi->hentry); + mach_port_mod_refs (mach_task_self (), pi->port_right, + MACH_PORT_RIGHT_RECEIVE, -1); + pi->port_right = MACH_PORT_NULL; + } + + *pi->prevp = pi->next; + if (pi->next) + pi->next->prevp = pi->prevp; + + pi->bucket->count--; + pi->class->count--; + + mutex_unlock (&_ports_lock); + + if (pi->class->clean_routine) + (*pi->class->clean_routine)(pi); + + free (pi); +} + diff --git a/libports/count-bucket.c b/libports/count-bucket.c new file mode 100644 index 00000000..9aff58e9 --- /dev/null +++ b/libports/count-bucket.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> + +int +ports_count_bucket (struct port_bucket *bucket) +{ + int ret; + + mutex_lock (&_ports_lock); + ret = bucket->count; + bucket->flags |= PORT_BUCKET_NO_ALLOC; + mutex_unlock (&_ports_lock); + + return ret; +} diff --git a/libports/count-class.c b/libports/count-class.c new file mode 100644 index 00000000..6aa88aa9 --- /dev/null +++ b/libports/count-class.c @@ -0,0 +1,37 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> + +int +ports_count_class (struct port_class *class) +{ + int ret; + + mutex_lock (&_ports_lock); + ret = class->count; + class->flags |= PORT_CLASS_NO_ALLOC; + mutex_unlock (&_ports_lock); + return ret; +} + + + diff --git a/libports/create-bucket.c b/libports/create-bucket.c new file mode 100644 index 00000000..d523b788 --- /dev/null +++ b/libports/create-bucket.c @@ -0,0 +1,50 @@ +/* Create a port bucket + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <assert.h> +#include <hurd/ihash.h> +#include <cthreads.h> + +struct port_bucket * +ports_create_bucket () +{ + struct port_bucket *ret; + error_t err; + + ret = malloc (sizeof (struct port_bucket)); + assert (ret); + + err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET, + &ret->portset); + assert_perror (err); + + err = ihash_create (&ret->htable); + assert_perror (err); + + ret->rpcs = ret->flags = ret->count = 0; + + mutex_lock (&_ports_lock); + ret->next = _ports_all_buckets; + _ports_all_buckets = ret; + mutex_unlock (&_ports_lock); + + return ret; +} diff --git a/libports/create-class.c b/libports/create-class.c new file mode 100644 index 00000000..7db99ca1 --- /dev/null +++ b/libports/create-class.c @@ -0,0 +1,42 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <stdlib.h> +#include <assert.h> + +struct port_class * +ports_create_class (void (*clean_routine)(void *), + void (*dropweak_routine)(void *)) +{ + struct port_class *cl; + + cl = malloc (sizeof (struct port_class)); + assert (cl); + cl->clean_routine = clean_routine; + cl->dropweak_routine = dropweak_routine; + cl->flags = 0; + cl->rpcs = 0; + cl->ports = NULL; + cl->count = 0; + cl->uninhibitable_rpcs = ports_default_uninhibitable_rpcs; + + return cl; +} diff --git a/libports/create-internal.c b/libports/create-internal.c new file mode 100644 index 00000000..bc97ce62 --- /dev/null +++ b/libports/create-internal.c @@ -0,0 +1,111 @@ +/* + Copyright (C) 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell, p/BSG. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <assert.h> +#include <cthreads.h> +#include <hurd/ihash.h> +#include "ports.h" + +/* Create and return in RESULT a new port in CLASS and BUCKET; SIZE + bytes will be allocated to hold the port structure and whatever + private data the user desires. If INSTALL is set, put the port + right into BUCKET's port set. */ +error_t +_ports_create_port_internal (struct port_class *class, + struct port_bucket *bucket, + size_t size, void *result, + int install) +{ + mach_port_t port; + error_t err; + struct port_info *pi; + + err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, + &port); + if (err) + return err; + + if (size < sizeof (struct port_info)) + size = sizeof (struct port_info); + + pi = malloc (size); + if (! pi) + { + mach_port_deallocate (mach_task_self (), port); + return ENOMEM; + } + + pi->class = class; + pi->refcnt = 1; + pi->weakrefcnt = 0; + pi->cancel_threshold = 0; + pi->mscount = 0; + pi->flags = 0; + pi->port_right = port; + pi->current_rpcs = 0; + pi->bucket = bucket; + + mutex_lock (&_ports_lock); + + loop: + if (class->flags & PORT_CLASS_NO_ALLOC) + { + class->flags |= PORT_CLASS_ALLOC_WAIT; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + goto cancelled; + goto loop; + } + if (bucket->flags & PORT_BUCKET_NO_ALLOC) + { + bucket->flags |= PORT_BUCKET_ALLOC_WAIT; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + goto cancelled; + goto loop; + } + + err = ihash_add (bucket->htable, port, pi, &pi->hentry); + if (err) + goto lose; + + pi->next = class->ports; + pi->prevp = &class->ports; + if (class->ports) + class->ports->prevp = &pi->next; + class->ports = pi; + bucket->count++; + class->count++; + mutex_unlock (&_ports_lock); + + if (install) + mach_port_move_member (mach_task_self (), pi->port_right, bucket->portset); + + *(void **)result = pi; + return 0; + + cancelled: + err = EINTR; + lose: + mutex_unlock (&_ports_lock); + mach_port_mod_refs (mach_task_self (), port, MACH_PORT_RIGHT_RECEIVE, -1); + free (pi); + + return err; +} + diff --git a/libports/create-port-noinstall.c b/libports/create-port-noinstall.c new file mode 100644 index 00000000..20c26a2f --- /dev/null +++ b/libports/create-port-noinstall.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell, p/BSG. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "ports.h" + +/* Create and return in RESULT a new port in CLASS and BUCKET; SIZE bytes + will be allocated to hold the port structure and whatever private data the + user desires. */ +error_t +ports_create_port_noinstall (struct port_class *class, + struct port_bucket *bucket, + size_t size, void *result) +{ + return _ports_create_port_internal (class, bucket, size, result, 0); +} + + + diff --git a/libports/create-port.c b/libports/create-port.c new file mode 100644 index 00000000..4da92d4a --- /dev/null +++ b/libports/create-port.c @@ -0,0 +1,35 @@ +/* Create a new port structure + + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" + +/* Create and return in RESULT a new port in CLASS and BUCKET; SIZE bytes + will be allocated to hold the port structure and whatever private data the + user desires. */ +error_t +ports_create_port (struct port_class *class, struct port_bucket *bucket, + size_t size, void *result) +{ + return _ports_create_port_internal (class, bucket, size, result, 1); +} + + + diff --git a/libports/dead-name.c b/libports/dead-name.c new file mode 100644 index 00000000..de89ba6b --- /dev/null +++ b/libports/dead-name.c @@ -0,0 +1,28 @@ +/* Handle various ports internal uses of dead-name notification + + Copyright (C) 1995, 1999 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" +#include <mach/notify.h> + +void +ports_dead_name (void *notify, mach_port_t dead_name) +{ + ports_interrupt_notified_rpcs (notify, dead_name, MACH_NOTIFY_DEAD_NAME); +} diff --git a/libports/default-uninhibitable-rpcs.c b/libports/default-uninhibitable-rpcs.c new file mode 100644 index 00000000..60aeccab --- /dev/null +++ b/libports/default-uninhibitable-rpcs.c @@ -0,0 +1,27 @@ +/* Default definition of default_uninhibitable_rpcs + + Copyright (C) 1996 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" + +static struct ports_msg_id_range +interrupt_operation_ids = { 33000, 33001, 0 }; + +struct ports_msg_id_range * +ports_default_uninhibitable_rpcs = &interrupt_operation_ids; diff --git a/libports/destroy-right.c b/libports/destroy-right.c new file mode 100644 index 00000000..32085c80 --- /dev/null +++ b/libports/destroy-right.c @@ -0,0 +1,51 @@ +/* + Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <hurd/ihash.h> +#include <assert.h> + +error_t +ports_destroy_right (void *portstruct) +{ + struct port_info *pi = portstruct; + error_t err; + + if (pi->port_right != MACH_PORT_NULL) + { + mutex_lock (&_ports_lock); + ihash_locp_remove (pi->bucket->htable, pi->hentry); + err = mach_port_mod_refs (mach_task_self (), pi->port_right, + MACH_PORT_RIGHT_RECEIVE, -1); + assert_perror (err); + mutex_unlock (&_ports_lock); + + pi->port_right = MACH_PORT_NULL; + + if (pi->flags & PORT_HAS_SENDRIGHTS) + { + pi->flags &= ~PORT_HAS_SENDRIGHTS; + ports_port_deref (pi); + } + } + + return 0; +} diff --git a/libports/enable-bucket.c b/libports/enable-bucket.c new file mode 100644 index 00000000..278c5bb5 --- /dev/null +++ b/libports/enable-bucket.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> + +void +ports_enable_bucket (struct port_bucket *bucket) +{ + mutex_lock (&_ports_lock); + bucket->flags &= ~PORT_BUCKET_NO_ALLOC; + if (bucket->flags & PORT_BUCKET_ALLOC_WAIT) + { + bucket->flags &= ~PORT_BUCKET_ALLOC_WAIT; + condition_broadcast (&_ports_block); + } + mutex_unlock (&_ports_lock); +} diff --git a/libports/enable-class.c b/libports/enable-class.c new file mode 100644 index 00000000..7aebf685 --- /dev/null +++ b/libports/enable-class.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> + +void +ports_enable_class (struct port_class *class) +{ + mutex_lock (&_ports_lock); + class->flags &= ~PORT_CLASS_NO_ALLOC; + if (class->flags & PORT_CLASS_ALLOC_WAIT) + { + class->flags &= ~PORT_CLASS_ALLOC_WAIT; + condition_broadcast (&_ports_block); + } + mutex_unlock (&_ports_lock); +} diff --git a/libports/end-rpc.c b/libports/end-rpc.c new file mode 100644 index 00000000..47fd1ae7 --- /dev/null +++ b/libports/end-rpc.c @@ -0,0 +1,56 @@ +/* + Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> + +void +ports_end_rpc (void *port, struct rpc_info *info) +{ + struct port_info *pi = port; + + mutex_lock (&_ports_lock); + + if (info->notifies) + _ports_remove_notified_rpc (info); + + *info->prevp = info->next; + if (info->next) + info->next->prevp = info->prevp; + pi->class->rpcs--; + _ports_total_rpcs--; + pi->bucket->rpcs--; + + if ((pi->flags & PORT_INHIBIT_WAIT) + || (pi->bucket->flags & PORT_BUCKET_INHIBIT_WAIT) + || (pi->class->flags & PORT_CLASS_INHIBIT_WAIT) + || (_ports_flags & _PORTS_INHIBIT_WAIT)) + condition_broadcast (&_ports_block); + + /* This removes the current thread's rpc (which should be INFO) from the + ports interrupted list. */ + ports_self_interrupted (); + + /* Clear the cancellation flag for this thread since the current + RPC is now finished anwhow. */ + hurd_check_cancel (); + + mutex_unlock (&_ports_lock); +} diff --git a/libports/get-right.c b/libports/get-right.c new file mode 100644 index 00000000..0c5f13b7 --- /dev/null +++ b/libports/get-right.c @@ -0,0 +1,60 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <mach/notify.h> +#include <assert.h> + +static volatile error_t gdb_loses = 0; + +mach_port_t +ports_get_right (void *port) +{ + struct port_info *pi = port; + mach_port_t foo; + + mutex_lock (&_ports_lock); + + if (pi->port_right == MACH_PORT_NULL) + { + mutex_unlock (&_ports_lock); + return MACH_PORT_NULL; + } + + pi->mscount++; + if ((pi->flags & PORT_HAS_SENDRIGHTS) == 0) + { + pi->flags |= PORT_HAS_SENDRIGHTS; + pi->refcnt++; + gdb_loses = + mach_port_request_notification (mach_task_self (), pi->port_right, + MACH_NOTIFY_NO_SENDERS, pi->mscount, + pi->port_right, + MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo); + assert_perror (gdb_loses); + if (foo != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), foo); + } + mutex_unlock (&_ports_lock); + return pi->port_right; +} + + diff --git a/libports/import-port.c b/libports/import-port.c new file mode 100644 index 00000000..b958245f --- /dev/null +++ b/libports/import-port.c @@ -0,0 +1,116 @@ +/* Create a new port structure using an externally supplied receive right + + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <assert.h> +#include <cthreads.h> +#include <hurd/ihash.h> +#include <mach/notify.h> + +/* For an existing receive right PORT, create and return in RESULT a new port + structure; BUCKET, SIZE, and CLASS args are as for ports_create_port. */ +error_t +ports_import_port (struct port_class *class, struct port_bucket *bucket, + mach_port_t port, size_t size, void *result) +{ + error_t err; + mach_port_status_t stat; + struct port_info *pi; + mach_port_t foo; + + err = mach_port_get_receive_status (mach_task_self (), port, &stat); + if (err) + return err; + + if (size < sizeof (struct port_info)) + size = sizeof (struct port_info); + + pi = malloc (size); + if (! pi) + return ENOMEM; + + pi->class = class; + pi->refcnt = 1 + !!stat.mps_srights; + pi->weakrefcnt = 0; + pi->cancel_threshold = 0; + pi->mscount = stat.mps_mscount; + pi->flags = stat.mps_srights ? PORT_HAS_SENDRIGHTS : 0; + pi->port_right = port; + pi->current_rpcs = 0; + pi->bucket = bucket; + + mutex_lock (&_ports_lock); + + loop: + if (class->flags & PORT_CLASS_NO_ALLOC) + { + class->flags |= PORT_CLASS_ALLOC_WAIT; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + goto cancelled; + goto loop; + } + if (bucket->flags & PORT_BUCKET_NO_ALLOC) + { + bucket->flags |= PORT_BUCKET_ALLOC_WAIT; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + goto cancelled; + goto loop; + } + + err = ihash_add (bucket->htable, port, pi, &pi->hentry); + if (err) + goto lose; + + pi->next = class->ports; + pi->prevp = &class->ports; + if (class->ports) + class->ports->prevp = &pi->next; + class->ports = pi; + bucket->count++; + class->count++; + mutex_unlock (&_ports_lock); + + mach_port_move_member (mach_task_self (), port, bucket->portset); + + if (stat.mps_srights) + { + err = mach_port_request_notification (mach_task_self (), port, + MACH_NOTIFY_NO_SENDERS, + stat.mps_mscount, + port, MACH_MSG_TYPE_MAKE_SEND_ONCE, + &foo); + assert_perror (err); + if (foo != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), foo); + } + + *(void **)result = pi; + return 0; + + cancelled: + err = EINTR; + lose: + mutex_unlock (&_ports_lock); + free (pi); + + return err; +} diff --git a/libports/inhibit-all-rpcs.c b/libports/inhibit-all-rpcs.c new file mode 100644 index 00000000..13aa62c6 --- /dev/null +++ b/libports/inhibit-all-rpcs.c @@ -0,0 +1,74 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <hurd.h> +#include <cthreads.h> +#include <hurd/ihash.h> + +error_t +ports_inhibit_all_rpcs () +{ + error_t err = 0; + + mutex_lock (&_ports_lock); + + if (_ports_flags & (_PORTS_INHIBITED | _PORTS_INHIBIT_WAIT)) + err = EBUSY; + else + { + struct port_bucket *bucket; + int this_one = 0; + error_t interruptor (void *portstruct) + { + struct rpc_info *rpc; + struct port_info *pi = portstruct; + + for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) + if (hurd_thread_cancel (rpc->thread) == EINTR) + this_one = 1; + return 0; + } + + for (bucket = _ports_all_buckets; bucket; bucket = bucket->next) + ihash_iterate (bucket->htable, interruptor); + + while (_ports_total_rpcs > this_one) + { + _ports_flags |= _PORTS_INHIBIT_WAIT; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + /* We got cancelled. */ + { + err = EINTR; + break; + } + } + + _ports_flags &= ~_PORTS_INHIBIT_WAIT; + if (! err) + _ports_flags |= _PORTS_INHIBITED; + } + + mutex_unlock (&_ports_lock); + + return err; +} + + diff --git a/libports/inhibit-bucket-rpcs.c b/libports/inhibit-bucket-rpcs.c new file mode 100644 index 00000000..a04906ff --- /dev/null +++ b/libports/inhibit-bucket-rpcs.c @@ -0,0 +1,70 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <hurd.h> +#include <cthreads.h> +#include <hurd/ihash.h> + +error_t +ports_inhibit_bucket_rpcs (struct port_bucket *bucket) +{ + error_t err = 0; + + mutex_lock (&_ports_lock); + + if (bucket->flags & (PORT_BUCKET_INHIBITED | PORT_BUCKET_INHIBIT_WAIT)) + err = EBUSY; + else + { + int this_one = 0; + error_t interruptor (void *portstruct) + { + struct rpc_info *rpc; + struct port_info *pi = portstruct; + + for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) + if (hurd_thread_cancel (rpc->thread) == EINTR) + this_one = 1; + return 0; + } + + ihash_iterate (bucket->htable, interruptor); + + while (bucket->rpcs > this_one) + { + bucket->flags |= PORT_BUCKET_INHIBIT_WAIT; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + /* We got cancelled. */ + { + err = EINTR; + break; + } + } + + bucket->flags &= ~PORT_BUCKET_INHIBIT_WAIT; + if (! err) + bucket->flags |= PORT_BUCKET_INHIBITED; + } + + mutex_unlock (&_ports_lock); + + return err; +} diff --git a/libports/inhibit-class-rpcs.c b/libports/inhibit-class-rpcs.c new file mode 100644 index 00000000..00b9b361 --- /dev/null +++ b/libports/inhibit-class-rpcs.c @@ -0,0 +1,64 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <hurd.h> +#include <cthreads.h> + +error_t +ports_inhibit_class_rpcs (struct port_class *class) +{ + error_t err = 0; + + mutex_lock (&_ports_lock); + + if (class->flags & (PORT_CLASS_INHIBITED | PORT_CLASS_INHIBIT_WAIT)) + err = EBUSY; + else + { + struct port_info *pi; + struct rpc_info *rpc; + int this_one = 0; + + for (pi = class->ports; pi; pi = pi->next) + for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) + if (hurd_thread_cancel (rpc->thread) == EINTR) + this_one = 1; + + while (class->rpcs > this_one) + { + class->flags |= PORT_CLASS_INHIBIT_WAIT; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + /* We got cancelled. */ + { + err = EINTR; + break; + } + } + + class->flags &= ~PORT_CLASS_INHIBIT_WAIT; + if (! err) + class->flags |= PORT_CLASS_INHIBITED; + } + + mutex_unlock (&_ports_lock); + + return err; +} diff --git a/libports/inhibit-port-rpcs.c b/libports/inhibit-port-rpcs.c new file mode 100644 index 00000000..4ec5d853 --- /dev/null +++ b/libports/inhibit-port-rpcs.c @@ -0,0 +1,65 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <hurd.h> +#include <cthreads.h> + +error_t +ports_inhibit_port_rpcs (void *portstruct) +{ + error_t err = 0; + struct port_info *pi = portstruct; + + mutex_lock (&_ports_lock); + + if (pi->flags & (PORT_INHIBITED | PORT_INHIBIT_WAIT)) + err = EBUSY; + else + { + struct rpc_info *rpc; + struct rpc_info *this_rpc = 0; + + for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) + if (hurd_thread_cancel (rpc->thread) == EINTR) + this_rpc = rpc; + + while (pi->current_rpcs + /* If this thread's RPC is the only one left, it doesn't count. */ + && !(pi->current_rpcs == this_rpc && ! this_rpc->next)) + { + pi->flags |= PORT_INHIBIT_WAIT; + if (hurd_condition_wait (&_ports_block, &_ports_lock)) + /* We got cancelled. */ + { + err = EINTR; + break; + } + } + + pi->flags &= ~PORT_INHIBIT_WAIT; + if (! err) + pi->flags |= PORT_INHIBITED; + } + + mutex_unlock (&_ports_lock); + + return err; +} diff --git a/libports/init.c b/libports/init.c new file mode 100644 index 00000000..44c8bdd4 --- /dev/null +++ b/libports/init.c @@ -0,0 +1,28 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> + +struct mutex _ports_lock = MUTEX_INITIALIZER; +struct condition _ports_block = CONDITION_INITIALIZER; +struct port_bucket *_ports_all_buckets = 0; +int _ports_total_rpcs = 0; +int _ports_flags = 0; diff --git a/libports/intern-external-port.c b/libports/intern-external-port.c new file mode 100644 index 00000000..8ece48e4 --- /dev/null +++ b/libports/intern-external-port.c @@ -0,0 +1,37 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" + +/* Backward compatibility. */ +void *ports_intern_external_port (struct port_bucket *bucket, + mach_port_t port, + size_t size, + struct port_class *class) +{ + void *result; + if (ports_import_port (class, bucket, port, size, &result)) + result = 0; + return result; +} + +#include "linkwarn.h" +link_warning (ports_intern_external_port, + "ports_intern_external_port is obsolete; use ports_import_port") diff --git a/libports/interrupt-notified-rpcs.c b/libports/interrupt-notified-rpcs.c new file mode 100644 index 00000000..061d3d87 --- /dev/null +++ b/libports/interrupt-notified-rpcs.c @@ -0,0 +1,117 @@ +/* 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) +{ + if (_ports_notifications) + { + 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; + } +} + diff --git a/libports/interrupt-on-notify.c b/libports/interrupt-on-notify.c new file mode 100644 index 00000000..42ae4884 --- /dev/null +++ b/libports/interrupt-on-notify.c @@ -0,0 +1,184 @@ +/* Mark an rpc to be interrupted when a port dies + + Copyright (C) 1995, 96, 99 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.org> + + 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" +#include <assert.h> + +/* Arrange for hurd_cancel to be called on RPC's thread if OBJECT gets notified + that any of the things in COND have happened to PORT. RPC should be an + rpc on OBJECT. */ +error_t +ports_interrupt_rpc_on_notification (void *object, + struct rpc_info *rpc, + mach_port_t port, mach_msg_id_t what) +{ + int req_notify; + struct ports_notify *pn; + struct rpc_notify *new_req, *req; + struct port_info *pi = object; + + mutex_lock (&_ports_lock); + + if (! MACH_PORT_VALID (port)) + /* PORT is already dead or bogus, so interrupt the rpc immediately. */ + { + hurd_thread_cancel (rpc->thread); + mutex_unlock (&_ports_lock); + return 0; + } + + new_req = _ports_free_rpc_notifies; + if (new_req) + /* We got a req off the free list. */ + _ports_free_rpc_notifies = new_req->next; + else + /* No free notify structs, allocate one; it's expected that 99% of the + time we'll add a new structure, so we malloc while we don't have the + lock, and free it if we're wrong. */ + { + mutex_unlock (&_ports_lock); /* Don't hold the lock during malloc. */ + new_req = malloc (sizeof (struct rpc_notify)); + if (! new_req) + return ENOMEM; + mutex_lock (&_ports_lock); + } + + /* Find any existing entry for PORT/WHAT. */ + for (pn = _ports_notifications; pn; pn = pn->next) + if (pn->port == port && pn->what == what) + break; + + if (! pn) + /* A notification on a new port. */ + { + pn = _ports_free_ports_notifies; + + if (pn) + _ports_free_ports_notifies = pn->next; + else + { + pn = malloc (sizeof (struct ports_notify)); + if (! pn) + /* sigh. Free what we've alloced and return. */ + { + new_req->next = _ports_free_rpc_notifies; + _ports_free_rpc_notifies = new_req; + mutex_unlock (&_ports_lock); + return ENOMEM; + } + } + + pn->reqs = 0; + pn->port = port; + pn->what = what; + pn->pending = 0; + mutex_init (&pn->lock); + + pn->next = _ports_notifications; + pn->prevp = &_ports_notifications; + if (_ports_notifications) + _ports_notifications->prevp = &pn->next; + _ports_notifications = pn; + } + + for (req = rpc->notifies; req; req = req->next) + if (req->notify == pn) + break; + + if (req) + /* REQ is already pending for PORT/WHAT on RPC, so free NEW_REQ. */ + { + new_req->next = _ports_free_rpc_notifies; + _ports_free_rpc_notifies = new_req; + } + else + /* Add a new request for PORT/WHAT on RPC. */ + { + req = new_req; + + req->rpc = rpc; + req->notify = pn; + req->pending = 0; + + req->next_req = pn->reqs; + req->prev_req_p = &pn->reqs; + if (pn->reqs) + pn->reqs->prev_req_p = &req->next_req; + pn->reqs = req; + + req->next = rpc->notifies; + rpc->notifies = req; + } + + /* Make sure that this request results in an interrupt. */ + req->pending++; + + /* Find out whether we should request a new notification (after we release + _PORTS_LOCK) -- PN may be new, or left over after a previous + notification (in which case our new request is likely to trigger an + immediate notification). */ + req_notify = !pn->pending; + if (req_notify) + mutex_lock (&pn->lock); + + mutex_unlock (&_ports_lock); + + if (req_notify) + { + mach_port_t old; + error_t err = + mach_port_request_notification (mach_task_self (), port, + what, 1, pi->port_right, + MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); + + if (! err && old != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), old); + + pn->pending = 1; + mutex_unlock (&pn->lock); + + return err; + } + else + return 0; +} + +/* Arrange for hurd_cancel to be called on the current thread, which should + be an rpc on OBJECT, if PORT gets notified with the condition WHAT. */ +error_t +ports_interrupt_self_on_notification (void *object, + mach_port_t port, mach_msg_id_t what) +{ + struct rpc_info *rpc; + struct port_info *pi = object; + thread_t thread = hurd_thread_self (); + + mutex_lock (&_ports_lock); + for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) + if (rpc->thread == thread) + break; + mutex_unlock (&_ports_lock); + + assert (rpc); + + /* We don't have to worry about RPC going away after we dropped the lock + because we're that thread, and we're still here. */ + return ports_interrupt_rpc_on_notification (object, rpc, port, what); +} diff --git a/libports/interrupt-operation.c b/libports/interrupt-operation.c new file mode 100644 index 00000000..1545f788 --- /dev/null +++ b/libports/interrupt-operation.c @@ -0,0 +1,40 @@ +/* interrupt_operation + + Copyright (C) 1995, 1996 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" +#include "interrupt_S.h" + +/* Cause a pending request on this object to immediately return. The + exact semantics are dependent on the specific object. */ +kern_return_t +ports_S_interrupt_operation (mach_port_t port, + mach_port_seqno_t seqno) +{ + struct port_info *pi = ports_lookup_port (0, port, 0); + if (!pi) + return EOPNOTSUPP; + mutex_lock (&_ports_lock); + if (pi->cancel_threshold < seqno) + pi->cancel_threshold = seqno; + mutex_unlock (&_ports_lock); + ports_interrupt_rpcs (pi); + ports_port_deref (pi); + return 0; +} diff --git a/libports/interrupt-rpcs.c b/libports/interrupt-rpcs.c new file mode 100644 index 00000000..7c28ff2c --- /dev/null +++ b/libports/interrupt-rpcs.c @@ -0,0 +1,40 @@ +/* + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <hurd.h> +#include <cthreads.h> + +void +ports_interrupt_rpcs (void *portstruct) +{ + struct port_info *pi = portstruct; + struct rpc_info *rpc; + + mutex_lock (&_ports_lock); + + for (rpc = pi->current_rpcs; rpc; rpc = rpc->next) + { + hurd_thread_cancel (rpc->thread); + _ports_record_interruption (rpc); + } + + mutex_unlock (&_ports_lock); +} diff --git a/libports/interrupted.c b/libports/interrupted.c new file mode 100644 index 00000000..e4cb2fc2 --- /dev/null +++ b/libports/interrupted.c @@ -0,0 +1,75 @@ +/* Keeping track of thread interruption + + Copyright (C) 1997 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.ai.mit.edu> + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "ports.h" + +static spin_lock_t interrupted_lock = SPIN_LOCK_INITIALIZER; + +/* True if some active rpc has been interrupted. */ +static struct rpc_info *interrupted = 0; + +/* If the current thread's rpc has been interrupted with + ports_interrupt_rpcs, return true (and clear the interrupted flag). */ +int +ports_self_interrupted () +{ + struct rpc_info **rpc_p, *rpc; + thread_t self = hurd_thread_self (); + + spin_lock (&interrupted_lock); + for (rpc_p = &interrupted; *rpc_p; rpc_p = &rpc->interrupted_next) + { + rpc = *rpc_p; + if (rpc->thread == self) + { + *rpc_p = rpc->interrupted_next; + spin_unlock (&interrupted_lock); + rpc->interrupted_next = 0; + return 1; + } + } + spin_unlock (&interrupted_lock); + + return 0; +} + +/* Add RPC to the list of rpcs that have been interrupted. */ +void +_ports_record_interruption (struct rpc_info *rpc) +{ + struct rpc_info *i; + + spin_lock (&interrupted_lock); + + /* See if RPC is already in the interrupted list. */ + for (i = interrupted; i; i = i->interrupted_next) + if (i == rpc) + /* Yup, it is, so just leave it there. */ + { + spin_unlock (&interrupted_lock); + return; + } + + /* Nope, put it at the beginning. */ + rpc->interrupted_next = interrupted; + interrupted = rpc; + + spin_unlock (&interrupted_lock); +} diff --git a/libports/lookup-port.c b/libports/lookup-port.c new file mode 100644 index 00000000..d0ee8d00 --- /dev/null +++ b/libports/lookup-port.c @@ -0,0 +1,55 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <hurd/ihash.h> + +void * +ports_lookup_port (struct port_bucket *bucket, + mach_port_t port, + struct port_class *class) +{ + struct port_info *pi = 0; + + mutex_lock (&_ports_lock); + + if (bucket) + pi = ihash_find (bucket->htable, port); + else + for (bucket = _ports_all_buckets; bucket; bucket = bucket->next) + { + pi = ihash_find (bucket->htable, port); + if (pi) + break; + } + + if (pi && class && pi->class != class) + pi = 0; + + if (pi) + pi->refcnt++; + + mutex_unlock (&_ports_lock); + + return pi; +} + + diff --git a/libports/manage-multithread.c b/libports/manage-multithread.c new file mode 100644 index 00000000..553a6444 --- /dev/null +++ b/libports/manage-multithread.c @@ -0,0 +1,170 @@ +/* + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <spin-lock.h> +#include <assert.h> +#include <cthreads.h> +#include <mach/message.h> + +void +ports_manage_port_operations_multithread (struct port_bucket *bucket, + ports_demuxer_type demuxer, + int thread_timeout, + int global_timeout, + void (*hook)()) +{ + volatile int nreqthreads; + volatile int totalthreads; + spin_lock_t lock = SPIN_LOCK_INITIALIZER; + + auto int thread_function (int); + + int + internal_demuxer (mach_msg_header_t *inp, + mach_msg_header_t *outheadp) + { + int spawn = 0; + int status; + struct port_info *pi; + struct rpc_info link; + register mig_reply_header_t *outp = (mig_reply_header_t *) outheadp; + static const mach_msg_type_t RetCodeType = { + /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32, + /* msgt_size = */ 32, + /* msgt_number = */ 1, + /* msgt_inline = */ TRUE, + /* msgt_longform = */ FALSE, + /* msgt_deallocate = */ FALSE, + /* msgt_unused = */ 0 + }; + + spin_lock (&lock); + assert (nreqthreads); + nreqthreads--; + if (nreqthreads == 0) + spawn = 1; + spin_unlock (&lock); + + if (spawn) + { + spin_lock (&lock); + totalthreads++; + nreqthreads++; + spin_unlock (&lock); + cthread_detach (cthread_fork ((cthread_fn_t) thread_function, 0)); + } + + /* Fill in default response. */ + outp->Head.msgh_bits + = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(inp->msgh_bits), 0); + outp->Head.msgh_size = sizeof *outp; + outp->Head.msgh_remote_port = inp->msgh_remote_port; + outp->Head.msgh_local_port = MACH_PORT_NULL; + outp->Head.msgh_seqno = 0; + outp->Head.msgh_id = inp->msgh_id + 100; + outp->RetCodeType = RetCodeType; + outp->RetCode = MIG_BAD_ID; + + pi = ports_lookup_port (bucket, inp->msgh_local_port, 0); + if (pi) + { + error_t err = ports_begin_rpc (pi, inp->msgh_id, &link); + if (err) + { + outp->RetCode = err; + status = 1; + } + else + { + mutex_lock (&_ports_lock); + if (inp->msgh_seqno < pi->cancel_threshold) + hurd_thread_cancel (link.thread); + mutex_unlock (&_ports_lock); + status = demuxer (inp, outheadp); + ports_end_rpc (pi, &link); + } + ports_port_deref (pi); + } + else + { + outp->RetCode = EOPNOTSUPP; + status = 1; + } + + spin_lock (&lock); + nreqthreads++; + spin_unlock (&lock); + + return status; + } + + int + thread_function (int master) + { + int timeout; + error_t err; + + if (hook) + (*hook) (); + + if (master) + timeout = global_timeout; + else + timeout = thread_timeout; + + startover: + + do + err = mach_msg_server_timeout (internal_demuxer, 0, bucket->portset, + timeout ? MACH_RCV_TIMEOUT : 0, + timeout); + while (err != MACH_RCV_TIMED_OUT); + + if (master) + { + spin_lock (&lock); + if (totalthreads != 1) + { + spin_unlock (&lock); + goto startover; + } + } + else + { + spin_lock (&lock); + nreqthreads--; + totalthreads--; + spin_unlock (&lock); + } + return 0; + } + + thread_timeout = global_timeout = 0; /* XXX */ + + nreqthreads = 1; + totalthreads = 1; + thread_function (1); +} + + + + + diff --git a/libports/manage-one-thread.c b/libports/manage-one-thread.c new file mode 100644 index 00000000..57b8a9a9 --- /dev/null +++ b/libports/manage-one-thread.c @@ -0,0 +1,93 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Writtenb by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" + +void +ports_manage_port_operations_one_thread (struct port_bucket *bucket, + ports_demuxer_type demuxer, + int timeout) +{ + error_t err; + + int + internal_demuxer (mach_msg_header_t *inp, + mach_msg_header_t *outheadp) + { + struct port_info *pi; + struct rpc_info link; + int status; + error_t err; + register mig_reply_header_t *outp = (mig_reply_header_t *) outheadp; + static const mach_msg_type_t RetCodeType = { + /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32, + /* msgt_size = */ 32, + /* msgt_number = */ 1, + /* msgt_inline = */ TRUE, + /* msgt_longform = */ FALSE, + /* msgt_deallocate = */ FALSE, + /* msgt_unused = */ 0 + }; + + /* Fill in default response. */ + outp->Head.msgh_bits + = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(inp->msgh_bits), 0); + outp->Head.msgh_size = sizeof *outp; + outp->Head.msgh_remote_port = inp->msgh_remote_port; + outp->Head.msgh_local_port = MACH_PORT_NULL; + outp->Head.msgh_seqno = 0; + outp->Head.msgh_id = inp->msgh_id + 100; + outp->RetCodeType = RetCodeType; + outp->RetCode = MIG_BAD_ID; + + pi = ports_lookup_port (bucket, inp->msgh_local_port, 0); + if (pi) + { + err = ports_begin_rpc (pi, inp->msgh_id, &link); + if (err) + { + mach_port_deallocate (mach_task_self (), inp->msgh_remote_port); + outp->RetCode = err; + status = 1; + } + else + { + /* No need to check cancel threshhold here, because + in a single threaded server the cancel is always + handled in order. */ + status = demuxer (inp, outheadp); + ports_end_rpc (pi, &link); + } + ports_port_deref (pi); + } + else + { + outp->RetCode = EOPNOTSUPP; + status = 1; + } + + return status; + } + + do + err = mach_msg_server_timeout (internal_demuxer, 0, bucket->portset, + timeout ? MACH_RCV_TIMEOUT : 0, timeout); + while (err != MACH_RCV_TIMED_OUT); +} diff --git a/libports/no-senders.c b/libports/no-senders.c new file mode 100644 index 00000000..0e8a5f17 --- /dev/null +++ b/libports/no-senders.c @@ -0,0 +1,66 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <mach/notify.h> + +void +ports_no_senders (void *portstruct, + mach_port_mscount_t mscount) +{ + struct port_info *pi = portstruct; + int dealloc; + mach_port_t old; + + mutex_lock (&_ports_lock); + if ((pi->flags & PORT_HAS_SENDRIGHTS) == 0) + { + mutex_unlock (&_ports_lock); + return; + } + if (mscount >= pi->mscount) + { + dealloc = 1; + pi->flags &= ~PORT_HAS_SENDRIGHTS; + } + else + { + /* Request a new notification. The sync value is because + we might have accounted for a new sender but not actually + made the send right yet. */ + mach_port_request_notification (mach_task_self (), pi->port_right, + MACH_NOTIFY_NO_SENDERS, pi->mscount, + pi->port_right, + MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); + if (old) + mach_port_deallocate (mach_task_self (), old); + dealloc = 0; + } + mutex_unlock (&_ports_lock); + + if (dealloc) + { + ports_interrupt_notified_rpcs (portstruct, pi->port_right, + MACH_NOTIFY_NO_SENDERS); + ports_interrupt_rpcs (pi); + ports_port_deref (pi); + } +} diff --git a/libports/notify-dead-name.c b/libports/notify-dead-name.c new file mode 100644 index 00000000..c67145d1 --- /dev/null +++ b/libports/notify-dead-name.c @@ -0,0 +1,37 @@ +/* Dead name notification + + Copyright (C) 1995, 1999 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" +#include "notify_S.h" + +error_t +ports_do_mach_notify_dead_name (mach_port_t notify, mach_port_t dead_name) +{ + void *pi = ports_lookup_port (0, notify, 0); + if (!pi) + return EOPNOTSUPP; + ports_dead_name (pi, dead_name); + ports_port_deref (pi); + + /* Drop gratuitous extra reference that the notification creates. */ + mach_port_deallocate (mach_task_self (), dead_name); + + return 0; +} diff --git a/libports/notify-msg-accepted.c b/libports/notify-msg-accepted.c new file mode 100644 index 00000000..c9750836 --- /dev/null +++ b/libports/notify-msg-accepted.c @@ -0,0 +1,28 @@ +/* Msg accepted 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" +#include "notify_S.h" + +error_t +ports_do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name) +{ + return 0; +} diff --git a/libports/notify-no-senders.c b/libports/notify-no-senders.c new file mode 100644 index 00000000..dc9b316e --- /dev/null +++ b/libports/notify-no-senders.c @@ -0,0 +1,33 @@ +/* No sender 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" +#include "notify_S.h" + +error_t +ports_do_mach_notify_no_senders (mach_port_t port, mach_port_mscount_t count) +{ + void *pi = ports_lookup_port (0, port, 0); + if (!pi) + return EOPNOTSUPP; + ports_no_senders (pi, count); + ports_port_deref (pi); + return 0; +} diff --git a/libports/notify-port-deleted.c b/libports/notify-port-deleted.c new file mode 100644 index 00000000..85012af5 --- /dev/null +++ b/libports/notify-port-deleted.c @@ -0,0 +1,28 @@ +/* Port deleted 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" +#include "notify_S.h" + +error_t +ports_do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name) +{ + return 0; +} diff --git a/libports/notify-port-destroyed.c b/libports/notify-port-destroyed.c new file mode 100644 index 00000000..78eaf211 --- /dev/null +++ b/libports/notify-port-destroyed.c @@ -0,0 +1,28 @@ +/* Port destroyed 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" +#include "notify_S.h" + +error_t +ports_do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t name) +{ + return 0; +} diff --git a/libports/notify-send-once.c b/libports/notify-send-once.c new file mode 100644 index 00000000..09ffcf24 --- /dev/null +++ b/libports/notify-send-once.c @@ -0,0 +1,28 @@ +/* Send once 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" +#include "notify_S.h" + +error_t +ports_do_mach_notify_send_once (mach_port_t notify) +{ + return 0; +} diff --git a/libports/port-deref-weak.c b/libports/port-deref-weak.c new file mode 100644 index 00000000..2bef3338 --- /dev/null +++ b/libports/port-deref-weak.c @@ -0,0 +1,38 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <assert.h> + +void +ports_port_deref_weak (void *portstruct) +{ + struct port_info *pi = portstruct; + + mutex_lock (&_ports_lock); + assert (pi->weakrefcnt); + pi->weakrefcnt--; + if (pi->refcnt == 0 && pi->weakrefcnt == 0) + _ports_complete_deallocate (pi); + else + mutex_unlock (&_ports_lock); +} + diff --git a/libports/port-deref.c b/libports/port-deref.c new file mode 100644 index 00000000..a1238315 --- /dev/null +++ b/libports/port-deref.c @@ -0,0 +1,53 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <assert.h> + +void +ports_port_deref (void *portstruct) +{ + struct port_info *pi = portstruct; + int trieddroppingweakrefs = 0; + + retry: + + mutex_lock (&_ports_lock); + + if (pi->refcnt == 1 && pi->weakrefcnt && !trieddroppingweakrefs) + { + mutex_unlock (&_ports_lock); + if (pi->class->dropweak_routine) + (*pi->class->dropweak_routine) (pi); + trieddroppingweakrefs = 1; + goto retry; + } + + assert (pi->refcnt); + + pi->refcnt--; + if (pi->refcnt == 0 && pi->weakrefcnt == 0) + _ports_complete_deallocate (pi); + else + mutex_unlock (&_ports_lock); +} + + diff --git a/libports/port-ref-weak.c b/libports/port-ref-weak.c new file mode 100644 index 00000000..6ebd5608 --- /dev/null +++ b/libports/port-ref-weak.c @@ -0,0 +1,34 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <assert.h> + +void +ports_port_ref_weak (void *portstruct) +{ + struct port_info *pi = portstruct; + + mutex_lock (&_ports_lock); + assert (pi->refcnt || pi->weakrefcnt); + pi->weakrefcnt++; + mutex_unlock (&_ports_lock); +} diff --git a/libports/port-ref.c b/libports/port-ref.c new file mode 100644 index 00000000..7fd15272 --- /dev/null +++ b/libports/port-ref.c @@ -0,0 +1,36 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <assert.h> + +void +ports_port_ref (void *portstruct) +{ + struct port_info *pi = portstruct; + + mutex_lock (&_ports_lock); + assert (pi->refcnt || pi->weakrefcnt); + pi->refcnt++; + mutex_unlock (&_ports_lock); +} + + diff --git a/libports/ports.h b/libports/ports.h new file mode 100644 index 00000000..ab347c84 --- /dev/null +++ b/libports/ports.h @@ -0,0 +1,405 @@ +/* Ports library for server construction + Copyright (C) 1993,94,95,96,97,99 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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. */ + +#ifndef _HURD_PORTS_ +#define _HURD_PORTS_ + +#include <mach.h> +#include <stdlib.h> +#include <hurd.h> +#include <mach/notify.h> + +/* These are global values for common flags used in the various structures. + Not all of these are meaningful in all flag fields. */ +#define PORTS_INHIBITED 0x0100 /* block RPC's */ +#define PORTS_BLOCKED 0x0200 /* if INHIBITED, someone is blocked */ +#define PORTS_INHIBIT_WAIT 0x0400 /* someone wants to start inhibit */ +#define PORTS_NO_ALLOC 0x0800 /* block allocation */ +#define PORTS_ALLOC_WAIT 0x1000 /* someone wants to allocate */ + +struct port_info +{ + struct port_class *class; + int refcnt; + int weakrefcnt; + mach_port_mscount_t mscount; + mach_msg_seqno_t cancel_threshold; + int flags; + mach_port_t port_right; + struct rpc_info *current_rpcs; + struct port_bucket *bucket; + void **hentry; + struct port_info *next, **prevp; /* links on port_class list */ +}; +/* FLAGS above are the following: */ +#define PORT_HAS_SENDRIGHTS 0x0001 /* send rights extant */ +#define PORT_INHIBITED PORTS_INHIBITED +#define PORT_BLOCKED PORTS_BLOCKED +#define PORT_INHIBIT_WAIT PORTS_INHIBIT_WAIT + +struct port_bucket +{ + mach_port_t portset; + struct ihash *htable; + int rpcs; + int flags; + int count; + struct port_bucket *next; +}; +/* FLAGS above are the following: */ +#define PORT_BUCKET_INHIBITED PORTS_INHIBITED +#define PORT_BUCKET_BLOCKED PORTS_BLOCKED +#define PORT_BUCKET_INHIBIT_WAIT PORTS_INHIBIT_WAIT +#define PORT_BUCKET_NO_ALLOC PORTS_NO_ALLOC +#define PORT_BUCKET_ALLOC_WAIT PORTS_ALLOC_WAIT + +struct port_class +{ + int flags; + int rpcs; + struct port_info *ports; + int count; + void (*clean_routine) (void *); + void (*dropweak_routine) (void *); + struct ports_msg_id_range *uninhibitable_rpcs; +}; +/* FLAGS are the following: */ +#define PORT_CLASS_INHIBITED PORTS_INHIBITED +#define PORT_CLASS_BLOCKED PORTS_BLOCKED +#define PORT_CLASS_INHIBIT_WAIT PORTS_INHIBIT_WAIT +#define PORT_CLASS_NO_ALLOC PORTS_NO_ALLOC +#define PORT_CLASS_ALLOC_WAIT PORTS_ALLOC_WAIT + +struct rpc_info +{ + thread_t thread; + struct rpc_info *next, **prevp; + struct rpc_notify *notifies; + struct rpc_info *interrupted_next; +}; + +/* An rpc has requested interruption on a port notification. */ +struct rpc_notify +{ + struct rpc_info *rpc; /* Which rpc this is for. */ + struct ports_notify *notify; /* Which port/request this refers too. */ + + struct rpc_notify *next; /* Notify for this rpc. */ + unsigned pending; /* Number of requests this represents. */ + + struct rpc_notify *next_req; /* rpc for this notify. */ + struct rpc_notify **prev_req_p; /* who points to this rpc_notify. */ +}; + +/* A notification request on a (not necessarily registered) port. */ +struct ports_notify +{ + mach_port_t port; /* */ + mach_msg_id_t what; /* MACH_NOTIFY_* */ + unsigned pending : 1; /* There's a notification outstanding. */ + struct mutex lock; + + struct rpc_notify *reqs; /* Which rpcs are notified by this port. */ + struct ports_notify *next, **prevp; /* Linked list of all notified ports. */ +}; + +/* A linked list of ports that have had notification requested. */ +extern struct ports_notify *_ports_notifications; + +/* Free lists for notify structures. */ +extern struct ports_notify *_ports_free_ports_notifies; +extern struct rpc_notify *_ports_free_rpc_notifies; + +/* 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 ports_msg_id_range +{ + mach_msg_id_t start, end; + struct ports_msg_id_range *next; +}; + +/* This is the initial value for the uninhibitable_rpcs field in new + port_class structures. The user may define this variable; the default + value contains only an entry for interrupt_operation. */ +extern struct ports_msg_id_range *ports_default_uninhibitable_rpcs; + +/* Port creation and port right frobbing */ + +/* Create and return a new bucket. */ +struct port_bucket *ports_create_bucket (void); + +/* Create and return a new port class. If nonzero, CLEAN_ROUTINE will + be called for each allocated port object in this class when it is + being destroyed. If nonzero, DROPWEAK_ROUTINE will be called + to request weak references to be dropped. (If DROPWEAK_ROUTINE is null, + then normal references and hard references will be identical for + ports of this class.) */ +struct port_class *ports_create_class (void (*clean_routine)(void *), + void (*dropweak_routine)(void *)); + +/* Create and return in RESULT a new port in CLASS and BUCKET; SIZE bytes + will be allocated to hold the port structure and whatever private data the + user desires. */ +error_t ports_create_port (struct port_class *class, + struct port_bucket *bucket, + size_t size, + void *result); + +/* Just like ports_create_port, except don't actually put the port + into the portset underlying BUCKET. This is intended to be used + for cases where the port right must be given out before the port is + fully initialized; with this call you are guaranteed that no RPC + service will occur on the port until you have finished initializing + it and installed it into the portset yourself. */ +error_t +ports_create_port_noinstall (struct port_class *class, + struct port_bucket *bucket, + size_t size, + void *result); + +/* For an existing RECEIVE right, create and return in RESULT a new port + structure; BUCKET, SIZE, and CLASS args are as for ports_create_port. */ +error_t ports_import_port (struct port_class *class, + struct port_bucket *bucket, + mach_port_t port, size_t size, + void *result); + +/* Destroy the receive right currently associated with PORT and allocate + a new one. */ +void ports_reallocate_port (void *port); + +/* Destroy the receive right currently associated with PORT and designate + RECEIVE as the new one. */ +void ports_reallocate_from_external (void *port, mach_port_t receive); + +/* Destroy the receive right currently associated with PORT. After + this call, ports_reallocate_port and ports_reallocate_from_external + may not be used. Always returns 0, for convenient use as an iterator. */ +error_t ports_destroy_right (void *port); + +/* Return the receive right currently associated with PORT. The effects + on PORT are the same as in ports_destroy_right, except that the receive + right itself is not affected. Note that in multi-threaded servers, + messages might already have been dequeued for this port before it gets + removed from the portset; such messages will get EOPNOTSUPP errors. */ +mach_port_t ports_claim_right (void *port); + +/* Transfer the receive right from FROMPT to TOPT. FROMPT ends up + with a destroyed right (as if ports_destroy_right were called) and + TOPT's old right is destroyed (as if ports_reallocate_from_external + were called. */ +error_t ports_transfer_right (void *topt, void *frompt); + +/* Return the name of the receive right associated with PORT. The user + is responsible for creating an ordinary send right from this name. */ +mach_port_t ports_get_right (void *port); + + + +/* Reference counting */ + +/* Look up PORT and return the associated port structure, allocating a + reference. If the call fails, return 0. If BUCKET is nonzero, + then it specifies a bucket to search; otherwise all buckets will be + searched. If CLASS is nonzero, then the lookup will fail if PORT + is not in CLASS. */ +void *ports_lookup_port (struct port_bucket *bucket, + mach_port_t port, struct port_class *class); + +/* Allocate another reference to PORT. */ +void ports_port_ref (void *port); + +/* Allocate a weak reference to PORT. */ +void ports_port_ref_weak (void *port); + +/* Drop a reference to PORT. */ +void ports_port_deref (void *port); + +/* Drop a weak reference to PORT. */ +void ports_port_deref_weak (void *port); + +/* The user is responsible for listening for no senders notifications; + when one arrives, call this routine for the PORT the message was + sent to, providing the MSCOUNT from the notification. */ +void ports_no_senders (void *port, mach_port_mscount_t mscount); +void ports_dead_name (void *notify, mach_port_t dead_name); + +/* Block port creation of new ports in CLASS. Return the number + of ports currently in CLASS. */ +int ports_count_class (struct port_class *class); + +/* Block port creation of new ports in BUCKET. Return the number + of ports currently in BUCKET. */ +int ports_count_bucket (struct port_bucket *bucket); + +/* Permit suspended port creation (blocked by ports_count_class) + to continue. */ +void ports_enable_class (struct port_class *class); + +/* Permit suspend port creation (blocked by ports_count_bucket) + to continue. */ +void ports_enable_bucket (struct port_bucket *bucket); + +/* Call FUN once for each port in BUCKET. */ +error_t ports_bucket_iterate (struct port_bucket *bucket, + error_t (*fun)(void *port)); + +/* Call FUN once for each port in CLASS. */ +error_t ports_class_iterate (struct port_class *class, + error_t (*fun)(void *port)); + +/* Internal entrypoint for above two. */ +error_t _ports_bucket_class_iterate (struct port_bucket *bucket, + struct port_class *class, + error_t (*fun)(void *port)); + +/* RPC management */ + +/* Type of MiG demuxer routines. */ +typedef int (*ports_demuxer_type)(mach_msg_header_t *inp, + mach_msg_header_t *outp); + +/* Call this when an RPC is beginning on PORT. INFO should be + allocated by the caller and will be used to hold dynamic state. + If this RPC should be abandoned, return EDIED; otherwise we + return zero. */ +error_t ports_begin_rpc (void *port, mach_msg_id_t msg_id, + struct rpc_info *info); + +/* Call this when an RPC is concluding. Args must be as for the + paired call to ports_begin_rpc. */ +void ports_end_rpc (void *port, struct rpc_info *info); + +/* Begin handling operations for the ports in BUCKET, calling DEMUXER + for each incoming message. Return if TIMEOUT is nonzero and no + messages have been received for TIMEOUT milliseconds. Use + only one thread (the calling thread). */ +void ports_manage_port_operations_one_thread(struct port_bucket *bucket, + ports_demuxer_type demuxer, + int timeout); + +/* Begin handling operations for the ports in BUCKET, calling DEMUXER + for each incoming message. Return if GLOBAL_TIMEOUT is nonzero and + no messages have been receieved for GLOBAL_TIMEOUT milliseconds. + Create threads as necessary to handle incoming messages so that no + port is starved because of sluggishness on another port. If + LOCAL_TIMEOUT is non-zero, then individual threads will die off if + they handle no incoming messages for LOCAL_TIMEOUT milliseconds. + HOOK (if not null) will be called in each new thread immediately + after it is created. */ +void ports_manage_port_operations_multithread (struct port_bucket *bucket, + ports_demuxer_type demuxer, + int thread_timeout, + int global_timeout, + void (*hook)(void)); + +/* Interrupt any pending RPC on PORT. Wait for all pending RPC's to + finish, and then block any new RPC's starting on that port. */ +error_t ports_inhibit_port_rpcs (void *port); + +/* Similar to ports_inhibit_port_rpcs, but affects all ports in CLASS. */ +error_t ports_inhibit_class_rpcs (struct port_class *class); + +/* Similar to ports_inhibit_port_rpcs, but affects all ports in BUCKET. */ +error_t ports_inhibit_bucket_rpcs (struct port_bucket *bucket); + +/* Similar to ports_inhibit_port_rpcs, but affects all ports whatsoever. */ +error_t ports_inhibit_all_rpcs (void); + +/* Reverse the effect of a previous ports_inhibit_port_rpcs for this PORT, + allowing blocked RPC's to continue. */ +void ports_resume_port_rpcs (void *port); + +/* Reverse the effect of a previous ports_inhibit_class_rpcs for CLASS. */ +void ports_resume_class_rpcs (struct port_class *class); + +/* Reverse the effect of a previous ports_inhibit_bucket_rpcs for BUCKET. */ +void ports_resume_bucket_rpcs (struct port_bucket *bucket); + +/* Reverse the effect of a previous ports_inhibit_all_rpcs. */ +void ports_resume_all_rpcs (void); + +/* Cancel (with thread_cancel) any RPC's in progress on PORT. */ +void ports_interrupt_rpcs (void *port); + +/* If the current thread's rpc has been interrupted with + ports_interrupt_rpcs, return true (and clear the interrupted flag). */ +int ports_self_interrupted (); + +/* Add RPC to the list of rpcs that have been interrupted. */ +void _ports_record_interruption (struct rpc_info *rpc); + +/* Arrange for hurd_cancel to be called on RPC's thread if OBJECT gets notified + that any of the things in COND have happened to PORT. RPC should be an + rpc on OBJECT. */ +error_t +ports_interrupt_rpc_on_notification (void *object, + struct rpc_info *rpc, + mach_port_t port, mach_msg_id_t what); + +/* Arrange for hurd_cancel to be called on the current thread, which should + be an rpc on OBJECT, if PORT gets notified with the condition WHAT. */ +error_t +ports_interrupt_self_on_notification (void *object, + mach_port_t port, mach_msg_id_t what); + +/* Some handy aliases. */ +#define ports_interrupt_self_on_port_death(obj, port) \ + ports_interrupt_self_on_notification (obj, port, MACH_NOTIFY_DEAD_NAME) + +/* 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); + +/* Default servers */ + +/* A notification server that calls the ports_do_mach_notify_* routines. */ +int ports_notify_server (mach_msg_header_t *, mach_msg_header_t *); + +/* Notification server routines called by ports_notify_server. */ +extern kern_return_t ports_do_mach_notify_dead_name (mach_port_t notify, mach_port_t deadport); +extern kern_return_t ports_do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name); +extern kern_return_t ports_do_mach_notify_no_senders (mach_port_t port, mach_port_mscount_t count); +extern kern_return_t ports_do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name); +extern kern_return_t ports_do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t name); +extern kern_return_t + ports_do_mach_notify_send_once (mach_port_t notify); + +/* A default interrupt server */ +int ports_interrupt_server (mach_msg_header_t *, mach_msg_header_t *); +extern kern_return_t ports_S_interrupt_operation (mach_port_t, + mach_port_seqno_t); + +/* Private data */ +extern struct mutex _ports_lock; +extern struct condition _ports_block; +extern struct port_bucket *_ports_all_buckets; +extern int _ports_total_rpcs; +extern int _ports_flags; +#define _PORTS_INHIBITED PORTS_INHIBITED +#define _PORTS_BLOCKED PORTS_BLOCKED +#define _PORTS_INHIBIT_WAIT PORTS_INHIBIT_WAIT +void _ports_complete_deallocate (struct port_info *); +error_t _ports_create_port_internal (struct port_class *, struct port_bucket *, + size_t, void *, int); + +#endif diff --git a/libports/reallocate-from-external.c b/libports/reallocate-from-external.c new file mode 100644 index 00000000..80b2905e --- /dev/null +++ b/libports/reallocate-from-external.c @@ -0,0 +1,83 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <assert.h> +#include <cthreads.h> +#include <hurd/ihash.h> +#include <mach/notify.h> + +void +ports_reallocate_from_external (void *portstruct, mach_port_t receive) +{ + struct port_info *pi = portstruct; + mach_port_status_t stat; + int dropref = 0; + mach_port_t foo; + error_t err; + + err = mach_port_get_receive_status (mach_task_self (), receive, &stat); + assert_perror (err); + + mutex_lock (&_ports_lock); + + assert (pi->port_right); + + err = mach_port_mod_refs (mach_task_self (), pi->port_right, + MACH_PORT_RIGHT_RECEIVE, -1); + assert_perror (err); + + ihash_locp_remove (pi->bucket->htable, pi->hentry); + + if ((pi->flags & PORT_HAS_SENDRIGHTS) && !stat.mps_srights) + { + dropref = 1; + pi->flags &= ~PORT_HAS_SENDRIGHTS; + } + else if (((pi->flags & PORT_HAS_SENDRIGHTS) == 0) && stat.mps_srights) + { + pi->flags |= PORT_HAS_SENDRIGHTS; + pi->refcnt++; + } + + pi->port_right = receive; + pi->cancel_threshold = 0; + pi->mscount = stat.mps_mscount; + + ihash_add (pi->bucket->htable, receive, pi, &pi->hentry); + mutex_unlock (&_ports_lock); + + mach_port_move_member (mach_task_self (), receive, pi->bucket->portset); + + if (stat.mps_srights) + { + err = mach_port_request_notification (mach_task_self (), receive, + MACH_NOTIFY_NO_SENDERS, + stat.mps_mscount, receive, + MACH_MSG_TYPE_MAKE_SEND_ONCE, + &foo); + assert_perror (err); + if (foo != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), foo); + } + + if (dropref) + ports_port_deref (pi); +} diff --git a/libports/reallocate-port.c b/libports/reallocate-port.c new file mode 100644 index 00000000..35dd4883 --- /dev/null +++ b/libports/reallocate-port.c @@ -0,0 +1,65 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <hurd/ihash.h> +#include <assert.h> +#include <cthreads.h> + +void +ports_reallocate_port (void *portstruct) +{ + struct port_info *pi = portstruct; + error_t err; + int dropref = 0; + + mutex_lock (&_ports_lock); + assert (pi->port_right); + + err = mach_port_mod_refs (mach_task_self (), pi->port_right, + MACH_PORT_RIGHT_RECEIVE, -1); + assert_perror (err); + + ihash_locp_remove (pi->bucket->htable, pi->hentry); + + err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, + &pi->port_right); + assert_perror (err); + if (pi->flags & PORT_HAS_SENDRIGHTS) + { + pi->flags &= ~PORT_HAS_SENDRIGHTS; + dropref = 1; + } + pi->cancel_threshold = 0; + pi->mscount = 0; + ihash_add (pi->bucket->htable, pi->port_right, pi, &pi->hentry); + mutex_unlock (&_ports_lock); + + mach_port_move_member (mach_task_self (), pi->port_right, + pi->bucket->portset); + + if (dropref) + ports_port_deref (pi); +} + + + + + diff --git a/libports/resume-all-rpcs.c b/libports/resume-all-rpcs.c new file mode 100644 index 00000000..fa978c1e --- /dev/null +++ b/libports/resume-all-rpcs.c @@ -0,0 +1,39 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <assert.h> + +void +ports_resume_all_rpcs () +{ + mutex_lock (&_ports_lock); + assert (_ports_flags & _PORTS_INHIBITED); + _ports_flags &= ~_PORTS_INHIBITED; + if (_ports_flags | _PORTS_BLOCKED) + { + _ports_flags &= ~_PORTS_BLOCKED; + condition_broadcast (&_ports_block); + } + mutex_unlock (&_ports_lock); +} + + diff --git a/libports/resume-bucket-rpcs.c b/libports/resume-bucket-rpcs.c new file mode 100644 index 00000000..9d968874 --- /dev/null +++ b/libports/resume-bucket-rpcs.c @@ -0,0 +1,37 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <assert.h> + +void +ports_resume_bucket_rpcs (struct port_bucket *bucket) +{ + mutex_lock (&_ports_lock); + assert (bucket->flags & PORT_BUCKET_INHIBITED); + bucket->flags &= ~PORT_BUCKET_INHIBITED; + if (bucket->flags | PORT_BUCKET_BLOCKED) + { + bucket->flags &= ~PORT_BUCKET_BLOCKED; + condition_broadcast (&_ports_block); + } + mutex_unlock (&_ports_lock); +} diff --git a/libports/resume-class-rpcs.c b/libports/resume-class-rpcs.c new file mode 100644 index 00000000..4b35f26c --- /dev/null +++ b/libports/resume-class-rpcs.c @@ -0,0 +1,38 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <assert.h> + +void +ports_resume_class_rpcs (struct port_class *class) +{ + mutex_lock (&_ports_lock); + assert (class->flags & PORT_CLASS_INHIBITED); + class->flags &= ~PORT_CLASS_INHIBITED; + if (class->flags | PORT_CLASS_BLOCKED) + { + class->flags &= ~PORT_CLASS_BLOCKED; + condition_broadcast (&_ports_block); + } + mutex_unlock (&_ports_lock); +} + diff --git a/libports/resume-port-rpcs.c b/libports/resume-port-rpcs.c new file mode 100644 index 00000000..563c9adc --- /dev/null +++ b/libports/resume-port-rpcs.c @@ -0,0 +1,43 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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" +#include <cthreads.h> +#include <assert.h> + +void +ports_resume_port_rpcs (void *portstruct) +{ + struct port_info *pi = portstruct; + + mutex_lock (&_ports_lock); + + assert (pi->flags & PORT_INHIBITED); + pi->flags &= ~PORT_INHIBITED; + if (pi->flags | PORT_BLOCKED) + { + pi->flags &= ~PORT_BLOCKED; + condition_broadcast (&_ports_block); + } + mutex_unlock (&_ports_lock); +} + + + diff --git a/libports/stubs.c b/libports/stubs.c new file mode 100644 index 00000000..23c6a0ea --- /dev/null +++ b/libports/stubs.c @@ -0,0 +1,38 @@ +/* + Copyright (C) 1995 Free Software Foundation, Inc. + Written by Michael I. Bushnell. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +/* This file contains stubs for some cthreads functions. + It should only get used if the user isn't otherwise using cthreads. */ + +#include <cthreads.h> + +void condition_wait (condition_t c, mutex_t m) __attribute__ ((weak)); + +void +condition_wait (condition_t c, mutex_t m) +{ +} + +void cond_broadcast (condition_t c) __attribute__ ((weak)); + +void +cond_broadcast (condition_t c) +{ +} diff --git a/libports/transfer-right.c b/libports/transfer-right.c new file mode 100644 index 00000000..d5844ea2 --- /dev/null +++ b/libports/transfer-right.c @@ -0,0 +1,94 @@ +/* Transfer the receive right from one port structure to another + Copyright (C) 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell, p/BSG. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + + +#include "ports.h" +#include <hurd/ihash.h> + +error_t +ports_transfer_right (void *tostruct, + void *fromstruct) +{ + struct port_info *topi = tostruct; + struct port_info *frompi = fromstruct; + mach_port_t port; + int dereffrompi = 0; + int dereftopi = 0; + int hassendrights = 0; + error_t err; + + mutex_lock (&_ports_lock); + + /* Fetch the port in FROMPI and clear its use */ + port = frompi->port_right; + if (port != MACH_PORT_NULL) + { + ihash_locp_remove (frompi->bucket->htable, frompi->hentry); + frompi->port_right = MACH_PORT_NULL; + if (frompi->flags & PORT_HAS_SENDRIGHTS) + { + frompi->flags &= ~PORT_HAS_SENDRIGHTS; + hassendrights = 1; + dereffrompi = 1; + } + } + + /* Destroy the existing right in TOPI. */ + if (topi->port_right != MACH_PORT_NULL) + { + ihash_locp_remove (topi->bucket->htable, topi->hentry); + err = mach_port_mod_refs (mach_task_self (), topi->port_right, + MACH_PORT_RIGHT_RECEIVE, -1); + if ((topi->flags & PORT_HAS_SENDRIGHTS) && !hassendrights) + { + dereftopi = 1; + topi->flags &= ~PORT_HAS_SENDRIGHTS; + } + else if (((topi->flags & PORT_HAS_SENDRIGHTS) == 0) && hassendrights) + { + topi->flags |= PORT_HAS_SENDRIGHTS; + topi->refcnt++; + } + } + + /* Install the new right in TOPI. */ + topi->port_right = port; + topi->cancel_threshold = frompi->cancel_threshold; + topi->mscount = frompi->mscount; + + if (port) + { + ihash_add (topi->bucket->htable, port, topi, &topi->hentry); + if (topi->bucket != frompi->bucket) + mach_port_move_member (mach_task_self (), port, topi->bucket->portset); + } + + mutex_unlock (&_ports_lock); + + /* Take care of any lowered reference counts. */ + if (dereffrompi) + ports_port_deref (frompi); + if (dereftopi) + ports_port_deref (topi); + return 0; +} + + + |