aboutsummaryrefslogtreecommitdiff
path: root/libports
diff options
context:
space:
mode:
Diffstat (limited to 'libports')
-rw-r--r--libports/ChangeLog499
-rw-r--r--libports/Makefile49
-rw-r--r--libports/allocate-port.c38
-rw-r--r--libports/begin-rpc.c111
-rw-r--r--libports/bucket-iterate.c80
-rw-r--r--libports/claim-right.c52
-rw-r--r--libports/class-iterate.c37
-rw-r--r--libports/complete-deallocate.c53
-rw-r--r--libports/count-bucket.c35
-rw-r--r--libports/count-class.c37
-rw-r--r--libports/create-bucket.c50
-rw-r--r--libports/create-class.c42
-rw-r--r--libports/create-internal.c111
-rw-r--r--libports/create-port-noinstall.c35
-rw-r--r--libports/create-port.c35
-rw-r--r--libports/dead-name.c28
-rw-r--r--libports/default-uninhibitable-rpcs.c27
-rw-r--r--libports/destroy-right.c51
-rw-r--r--libports/enable-bucket.c35
-rw-r--r--libports/enable-class.c35
-rw-r--r--libports/end-rpc.c56
-rw-r--r--libports/get-right.c60
-rw-r--r--libports/import-port.c116
-rw-r--r--libports/inhibit-all-rpcs.c74
-rw-r--r--libports/inhibit-bucket-rpcs.c70
-rw-r--r--libports/inhibit-class-rpcs.c64
-rw-r--r--libports/inhibit-port-rpcs.c65
-rw-r--r--libports/init.c28
-rw-r--r--libports/intern-external-port.c37
-rw-r--r--libports/interrupt-notified-rpcs.c117
-rw-r--r--libports/interrupt-on-notify.c184
-rw-r--r--libports/interrupt-operation.c40
-rw-r--r--libports/interrupt-rpcs.c40
-rw-r--r--libports/interrupted.c75
-rw-r--r--libports/lookup-port.c55
-rw-r--r--libports/manage-multithread.c170
-rw-r--r--libports/manage-one-thread.c93
-rw-r--r--libports/no-senders.c66
-rw-r--r--libports/notify-dead-name.c37
-rw-r--r--libports/notify-msg-accepted.c28
-rw-r--r--libports/notify-no-senders.c33
-rw-r--r--libports/notify-port-deleted.c28
-rw-r--r--libports/notify-port-destroyed.c28
-rw-r--r--libports/notify-send-once.c28
-rw-r--r--libports/port-deref-weak.c38
-rw-r--r--libports/port-deref.c53
-rw-r--r--libports/port-ref-weak.c34
-rw-r--r--libports/port-ref.c36
-rw-r--r--libports/ports.h405
-rw-r--r--libports/reallocate-from-external.c83
-rw-r--r--libports/reallocate-port.c65
-rw-r--r--libports/resume-all-rpcs.c39
-rw-r--r--libports/resume-bucket-rpcs.c37
-rw-r--r--libports/resume-class-rpcs.c38
-rw-r--r--libports/resume-port-rpcs.c43
-rw-r--r--libports/stubs.c38
-rw-r--r--libports/transfer-right.c94
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;
+}
+
+
+