about summary refs log tree commit diff
path: root/hurd
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-03-27 10:00:09 +0000
committerRoland McGrath <roland@gnu.org>1995-03-27 10:00:09 +0000
commit1474b80f017c2fcc18b1de5bbc51884650d30582 (patch)
tree1baa3c89ef3802cda051fa7f8f9c9bb8c0bf6abd /hurd
parentd365fd2cfa4248fcce18fc60d3d90598aa1f534b (diff)
downloadglibc-1474b80f017c2fcc18b1de5bbc51884650d30582.tar.gz
glibc-1474b80f017c2fcc18b1de5bbc51884650d30582.tar.xz
glibc-1474b80f017c2fcc18b1de5bbc51884650d30582.zip
Mon Mar 27 02:23:15 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
	* posix/unistd.h [__USE_BSD] (ttyslot): Declare it.

	* posix/unistd.h [__USE_BSD] (L_SET, L_INCR, L_XTND): Define
 	unless L_SET already defined.
	* misc/sys/file.h (L_SET, L_INCR, L_XTND): Don't define if L_SET
 	already defined.

	Incorporated -lutil library from 4.4-Lite.
	* misc/Makefile (extra-libs, libutil-routines): New variables.
	* misc/login.c, misc/login_tty.c, misc/logout.c, misc/logwtmp.c,
	sysdeps/generic/pty.c: New files for -lutil incorporated from 4.4-Lite.

	Support simple, light-weight unwind-protect mechanism for longjmp.
	* setjmp/longjmp.c: Call _longjmp_unwind first thing.
	* sysdeps/mach/hurd/jmp-unwind.c: New file.
	* sysdeps/stub/jmp-unwind.c: New file.
	* sysdeps/i386/jmp_buf.h (_JMPBUF_UNWINDS): New macro.
	* sysdeps/mips/jmp_buf.h (_JMPBUF_UNWINDS): New macro.
	* setjmp/Makefile (routines): Add jmp-unwind.
	* hurd/hurd/userlink.h (struct hurd_userlink): Move `next' and
 	`prevp' members into new substructure `resource'; add another such
 	substructure `thread' and members `cleanup' (function ptr) and
 	`cleanup_data' (generic ptr).
	(_hurd_userlink_link, _hurd_userlink_unlink): Insert/remove LINK
	into the `_hurd_self_sigstate ()->active_resources' list via the
	`thread' substructure.
	* hurd/hurd/port.h (_hurd_port_cleanup): Declare it.
	(_hurd_port_locked_get): Set LINK->cleanup to _hurd_port_cleanup and
	LINK->cleanup_data' to the port extracted.
	* hurd/hurd/signal.h (struct hurd_sigstate): New member
	`active_resources'.
	* hurd/port-cleanup.c: New file.
	* hurd/Makefile (routines): Add port-cleanup.

	* malloc/malloc.c: Include errno.h.

Sat Mar 25 18:24:21 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>

	* locale/loadlocale.c (_nl_load_locale): Avoid */ inside comment.
Diffstat (limited to 'hurd')
-rw-r--r--hurd/Makefile2
-rw-r--r--hurd/hurd/port.h11
-rw-r--r--hurd/hurd/signal.h5
-rw-r--r--hurd/hurd/userlink.h99
-rw-r--r--hurd/port-cleanup.c31
5 files changed, 117 insertions, 31 deletions
diff --git a/hurd/Makefile b/hurd/Makefile
index 386267c649..278d8ec315 100644
--- a/hurd/Makefile
+++ b/hurd/Makefile
@@ -49,7 +49,7 @@ routines = hurdinit hurdid hurdlookup hurdpid hurdrlimit hurdprio hurdexec \
 	   fopenport \
  	   vpprintf \
 	   ports-get ports-set hurdports hurdmsg \
-	   $(sig) $(dtable) hurdinline
+	   $(sig) $(dtable) hurdinline port-cleanup
 sig	= hurdsig hurdfault faultexc siginfo hurd-raise preempt-sig \
 	  trampoline longjmp-ts catch-exc exc2signal hurdkill
 dtable	= dtable port2fd new-fd alloc-fd intern-fd \
diff --git a/hurd/hurd/port.h b/hurd/hurd/port.h
index a057503d4a..9de021c45a 100644
--- a/hurd/hurd/port.h
+++ b/hurd/hurd/port.h
@@ -1,5 +1,5 @@
 /* Lightweight user references for ports.
-Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
@@ -70,6 +70,9 @@ _hurd_port_init (struct hurd_port *port, mach_port_t init)
 }
 
 
+/* Cleanup function for non-local exits.  */
+extern void _hurd_port_cleanup (void *, jmp_buf, int);
+
 /* Get a reference to *PORT, which is locked.
    Pass return value and LINK to _hurd_port_free when done.  */
 
@@ -80,7 +83,11 @@ _hurd_port_locked_get (struct hurd_port *port,
   mach_port_t result;
   result = port->port;
   if (result != MACH_PORT_NULL)
-    _hurd_userlink_link (&port->users, link);
+    {
+      link->cleanup = &_hurd_port_cleanup;
+      link->cleanup_data = (void *) result;
+      _hurd_userlink_link (&port->users, link);
+    }
   __spin_unlock (&port->lock);
   return result;
 }
diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
index 76007d5037..d88d287de3 100644
--- a/hurd/hurd/signal.h
+++ b/hurd/hurd/signal.h
@@ -79,6 +79,11 @@ struct hurd_sigstate
        will be passed to sigreturn after running the handler for a pending
        signal, instead of examining the thread state.  */
     struct sigcontext *context;
+
+    /* This is the head of the thread's list of active resources; see
+       <hurd/userlink.h> for details.  This member is only used by the
+       thread itself, and always inside a critical section.  */
+    struct hurd_userlink *active_resources;
   };
 
 /* Linked list of states of all threads whose state has been asked for.  */
diff --git a/hurd/hurd/userlink.h b/hurd/hurd/userlink.h
index 337d46aef6..d61e2e2a7e 100644
--- a/hurd/hurd/userlink.h
+++ b/hurd/hurd/userlink.h
@@ -1,5 +1,5 @@
 /* Support for chains recording users of a resource; `struct hurd_userlink'.
-Copyright (C) 1994 Free Software Foundation, Inc.
+Copyright (C) 1994, 1995 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
@@ -25,19 +25,48 @@ Cambridge, MA 02139, USA.  */
 #define __need_NULL
 #include <stddef.h>
 
-
-/* This structure is simply a doubly-linked list.  Users of a given
-   resource are recorded by their presence in a list associated with that
-   resource.  A user attaches his own link (in local storage) to a shared
-   chain at the time he begins using some resource.  When finished with
-   that resource, the user removes his link from the chain.  If his link is
-   the last (there are no other users of the resource), and his chain has
-   been detached from the shared cell (the resource in the cell has been
-   replaced), then the user deallocates the resource that he used.  */
+#include <hurd/signal.h>
+#include <setjmp.h>
+
+
+/* This structure records a link in two doubly-linked lists.
+   We call these the per-resource user list and the per-thread
+   active-resource list. 
+
+   Users of a given resource are recorded by their presence in a list
+   associated with that resource.  A user attaches his own link (in local
+   storage on his stack) to a shared chain at the time he begins using some
+   resource.  When finished with that resource, the user removes his link
+   from the chain.  If his link is the last (there are no other users of
+   the resource), and his chain has been detached from the shared cell (the
+   resource in the cell has been replaced), then the user deallocates the
+   resource that he used.
+
+   All uses of shared resources by a single thread are linked together by
+   its `active-resource' list; the head of this list is stored in the
+   per-thread sigstate structure.  When the thread makes a non-local exit
+   (i.e. longjmp), it will examine its active-resource list, and each link
+   residing in a stack frame being jumped out of will be unlinked from both
+   the resource's user list and the thread's active-resource list, and
+   deallocate the resource if that was the last user link for that resource.
+
+   NOTE: Access to a thread's active-resource list must always be done
+   inside a signal-proof critical section; the functions in this file
+   assume they are called inside a critical section, and do no locking of
+   their own.  Also important: the longjmp cleanup relies on all userlink
+   structures residing on the stack of the using thread.  */
 
 struct hurd_userlink
   {
-    struct hurd_userlink *next, **prevp;
+    struct
+      {
+	struct hurd_userlink *next, **prevp;
+      } resource, thread;
+
+    /* This function is called when a non-local exit
+       unwinds the frame containing this link.  */
+    void (*cleanup) (void *cleanup_data, jmp_buf env, int val);
+    void *cleanup_data;
   };
 
 
@@ -52,32 +81,46 @@ _EXTERN_INLINE void
 _hurd_userlink_link (struct hurd_userlink **chainp,
 		     struct hurd_userlink *link)
 {
-  link->next = *chainp;
-  if (link->next)
-    link->next->prevp = &link->next;
-  link->prevp = chainp;
+  struct hurd_userlink **thread_chainp;
+
+  link->resource.next = *chainp;
+  if (link->resource.next)
+    link->resource.next->thread.prevp = &link->resource.next;
+  link->resource.prevp = chainp;
   *chainp = link;
+
+  /* Also chain it on the current thread's list of active resources.  */
+  thread_chainp = &_hurd_self_sigstate ()->active_resources;
+  link->thread.next = *thread_chainp;
+  if (link->thread.next)
+    link->thread.next->thread.prevp = &link->thread.next;
+  link->thread.prevp = thread_chainp;
+  *thread_chainp = link;
 }
 
 
-/* Detach LINK from its chain.  If the return value is nonzero, the caller
-   should deallocate the resource he started using after attaching LINK to
-   the chain it's on.  If the return value is zero, then someone else is
-   still using the resource.  */
+/* Detach LINK from its chain.  Returns nonzero iff this was the
+   last user of the resource and it should be deallocated.  */
 
 _EXTERN_INLINE int
 _hurd_userlink_unlink (struct hurd_userlink *link)
 {
-  /* The caller should deallocate the resource he used if his chain has
-     been detached from the cell (and thus has a nil `prevp'), and there is
-     no next link representing another user reference to the same resource. */
-  int dealloc = ! link->next && ! link->prevp;
+  /* We should deallocate the resource used if this chain has been detached
+     from the cell (and thus has a nil `prevp'), and there is no next link
+     representing another user reference to the same resource. */
+  int dealloc = ! link->resource.next && ! link->resource.prevp;
 
   /* Remove our link from the chain of current users.  */
-  if (link->prevp)
-    *link->prevp = link->next;
-  if (link->next)
-    link->next->prevp = link->prevp;
+  if (link->resource.prevp)
+    *link->resource.prevp = link->resource.next;
+  if (link->resource.next)
+    link->resource.next->resource.prevp = link->resource.prevp;
+
+  /* Remove our link from the chain of currently active resources
+     for this thread.  */
+  *link->thread.prevp = link->thread.next;
+  if (link->thread.next)
+    link->thread.next->thread.prevp = link->thread.prevp;
 
   return dealloc;
 }
@@ -97,7 +140,7 @@ _hurd_userlink_clear (struct hurd_userlink **chainp)
 
   /* Detach the chain of current users from the cell.  The last user to
      remove his link from that chain will deallocate the old resource.  */
-  (*chainp)->prevp = NULL;
+  (*chainp)->resource.prevp = NULL;
   *chainp = NULL;
   return 0;
 }
diff --git a/hurd/port-cleanup.c b/hurd/port-cleanup.c
new file mode 100644
index 0000000000..556baaace0
--- /dev/null
+++ b/hurd/port-cleanup.c
@@ -0,0 +1,31 @@
+/* Cleanup function for `struct hurd_port' users who longjmp.
+Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <mach.h>
+#include <hurd/port.h>
+
+/* The last user of the send right CLEANUP_DATA is now doing
+   `longjmp (ENV, VAL)', and this will unwind the frame of
+   that last user.  Deallocate the right he will never get back to using.  */
+
+void
+_hurd_port_cleanup (void *cleanup_data, jmp_buf env, int val)
+{
+  __mach_port_deallocate (__mach_task_self (), (mach_port_t) cleanup_data);
+}