summary refs log tree commit diff
path: root/hurd/hurdioctl.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1999-12-03 05:01:23 +0000
committerRoland McGrath <roland@gnu.org>1999-12-03 05:01:23 +0000
commit72e1a75071d8c4b269e03c583f84c9a130434062 (patch)
treece119ac1bf830309de109a401f799608390694b3 /hurd/hurdioctl.c
parent63bf605304e93d6eda7aa11b43ace572a3bced30 (diff)
downloadglibc-72e1a75071d8c4b269e03c583f84c9a130434062.tar.gz
glibc-72e1a75071d8c4b269e03c583f84c9a130434062.tar.xz
glibc-72e1a75071d8c4b269e03c583f84c9a130434062.zip
1999-11-18 Roland McGrath <roland@baalperazim.frob.com>
        * hurd/hurdsig.c (_hurdsig_init): If __hurd_threadvar_stack_mask is
        nonzero, use cthread_fork to create the signal thread.
        * hurd/msgportdemux.c (_hurd_msgport_receive): Initialize
        _hurd_msgport_thread here (to self).
        * sysdeps/mach/hurd/fork.c (__fork): When __hurd_sigthread_stack_end
        is zero, instead compute child signal thread's starting SP from parent
        signal thread's current SP and the threadvar_stack variables.
        * hurd/Versions (GLIBC_2.1.3): Add cthread_fork, cthread_detach.
        These are now referenced weakly by _hurdsig_init.

        * hurd/report-wait.c (_S_msg_report_wait): Fix typo:
        &_hurd_itimer_thread not &_hurd_msgport_thread.

1999-10-01  Roland McGrath  <roland@baalperazim.frob.com>

        * hurd/hurdfchdir.c (_hurd_change_directory_port_from_fd): Rewrite
        without HURD_DPORT_USE to clean up warnings.
        * hurd/dtable.c (get_dtable_port): Likewise.

        * hurd/hurdioctl.c (rectty_dtable): Renamed to install_ctty.
        (install_ctty): Do the changing of the cttyid port cell here, inside
        the critical section while we holding the dtable lock.
        (_hurd_setcttyid, tiocsctty, tiocnotty): Use that instead of changing
        the port cell and calling rectty_dtable.
        (_hurd_locked_install_cttyid): New function, split out of install_ctty.
        (install_ctty): Use it inside a critical section, with the lock held.
        * sysdeps/mach/hurd/setsid.c (__setsid): Use
        _hurd_locked_install_cttyid to effect the cttyid and dtable changes
        after proc_setsid, having held the dtable lock throughout.
        * hurd/dtable.c (ctty_new_pgrp): With the dtable lock held, check the
        cttyid port for null and bail out early if so.  The dtable lock
        serializes us after any cttyid change and its associated dtable update.
Diffstat (limited to 'hurd/hurdioctl.c')
-rw-r--r--hurd/hurdioctl.c66
1 files changed, 47 insertions, 19 deletions
diff --git a/hurd/hurdioctl.c b/hurd/hurdioctl.c
index 8482571299..073c15edcc 100644
--- a/hurd/hurdioctl.c
+++ b/hurd/hurdioctl.c
@@ -1,5 +1,5 @@
 /* ioctl commands which must be done in the C library.
-   Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 1997, 1999 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
@@ -132,13 +132,39 @@ _HURD_HANDLE_IOCTLS (fioclex, FIOCLEX, FIONCLEX);
 #include <hurd/term.h>
 #include <hurd/tioctl.h>
 
-static void
-rectty_dtable (mach_port_t cttyid)
+/* Install a new CTTYID port, atomically updating the dtable appropriately.
+   This consumes the send right passed in.  */
+
+void
+_hurd_locked_install_cttyid (mach_port_t cttyid)
 {
+  mach_port_t old;
+  struct hurd_port *const port = &_hurd_ports[INIT_PORT_CTTYID];
+  struct hurd_userlink ulink;
   int i;
 
-  HURD_CRITICAL_BEGIN;
-  __mutex_lock (&_hurd_dtable_lock);
+  /* Install the new cttyid port, and preserve it with a ulink.
+     We unroll the _hurd_port_set + _hurd_port_get here so that
+     there is no window where the cell is unlocked and CTTYID could
+     be changed by another thread.  (We also delay the deallocation
+     of the old port until the end, to minimize the duration of the
+     critical section.)
+
+     It is important that changing the cttyid port is only ever done by
+     holding the dtable lock continuously while updating the port cell and
+     re-ctty'ing the dtable; dtable.c assumes we do this.  Otherwise, the
+     pgrp-change notification code in dtable.c has to worry about racing
+     against us here in odd situations.  The one exception to this is
+     setsid, which holds the dtable lock while changing the pgrp and
+     clearing the cttyid port, and then unlocks the dtable lock to allow
+
+
+  */
+
+  __spin_lock (&port->lock);
+  old = _hurd_userlink_clear (&port->users) ? port->port : MACH_PORT_NULL;
+  port->port = cttyid;
+  cttyid = _hurd_port_locked_get (port, &ulink);
 
   for (i = 0; i < _hurd_dtablesize; ++i)
     {
@@ -178,6 +204,18 @@ rectty_dtable (mach_port_t cttyid)
     }
 
   __mutex_unlock (&_hurd_dtable_lock);
+
+  if (old != MACH_PORT_NULL)
+    __mach_port_deallocate (__mach_task_self (), old);
+  _hurd_port_free (port, &ulink, cttyid);
+}
+
+static void
+install_ctty (mach_port_t cttyid)
+{
+  HURD_CRITICAL_BEGIN;
+  __mutex_lock (&_hurd_dtable_lock);
+  _hurd_locked_install_cttyid (cttyid);
   HURD_CRITICAL_END;
 }
 
@@ -199,10 +237,7 @@ _hurd_setcttyid (mach_port_t cttyid)
     }
 
   /* Install the port, consuming the reference we just created.  */
-  _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid);
-
-  /* Reset all the ctty ports in all the descriptors.  */
-  __USEPORT (CTTYID, (rectty_dtable (cttyid), 0));
+  install_ctty (cttyid);
 
   return 0;
 }
@@ -233,10 +268,7 @@ tiocsctty (int fd,
     return __hurd_fail (err);
 
   /* Make it our own.  */
-  _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid);
-
-  /* Reset all the ctty ports in all the descriptors.  */
-  __USEPORT (CTTYID, (rectty_dtable (cttyid), 0));
+  install_ctty (cttyid);
 
   return 0;
 }
@@ -262,12 +294,8 @@ tiocnotty (int fd,
   if (err)
     return __hurd_fail (err);
 
-  /* Clear our cttyid port cell.  */
-  _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], MACH_PORT_NULL);
-
-  /* Reset all the ctty ports in all the descriptors.  */
-
-  __USEPORT (CTTYID, (rectty_dtable (MACH_PORT_NULL), 0));
+  /* Clear our cttyid port.  */
+  install_ctty (MACH_PORT_NULL);
 
   return 0;
 }