about summary refs log tree commit diff
path: root/sysdeps/mach
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach')
-rw-r--r--sysdeps/mach/hurd/closedir.c20
-rw-r--r--sysdeps/mach/hurd/dirstream.h5
-rw-r--r--sysdeps/mach/hurd/opendir.c6
-rw-r--r--sysdeps/mach/hurd/readdir.c19
-rw-r--r--sysdeps/mach/hurd/seekdir.c4
-rw-r--r--sysdeps/mach/libc-lock.h60
6 files changed, 100 insertions, 14 deletions
diff --git a/sysdeps/mach/hurd/closedir.c b/sysdeps/mach/hurd/closedir.c
index 521787d02d..4c62783584 100644
--- a/sysdeps/mach/hurd/closedir.c
+++ b/sysdeps/mach/hurd/closedir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995, 1996 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
@@ -39,14 +39,22 @@ DEFUN(closedir, (dirp), DIR *dirp)
       return -1;
     }
 
-  if (err = __vm_deallocate (__mach_task_self (),
-			     (vm_address_t) dirp->__data, dirp->__allocation))
-    return __hurd_fail (err);
+  __libc_lock_lock (dirp->__lock);
+  err = __vm_deallocate (__mach_task_self (),
+			 (vm_address_t) dirp->__data, dirp->__allocation);
   dirp->__data = NULL;
+  err = _hurd_fd_close (dirp->__fd);
 
-  if (err = _hurd_fd_close (dirp->__fd))
-    return __hurd_fail (err);
+  if (err)
+    {
+      /* Unlock the DIR.  A failing closedir can be repeated (and may fail
+	 again, but shouldn't deadlock).  */
+      __libc_lock_unlock (dirp->__lock);
+      return __hurd_fail (err);
+    }
 
+  /* Clean up the lock and free the structure.  */
+  __libc_lock_fini (dirp->__lock);
   free (dirp);
 
   return 0;
diff --git a/sysdeps/mach/hurd/dirstream.h b/sysdeps/mach/hurd/dirstream.h
index a8c5fd12cb..d17baf2b03 100644
--- a/sysdeps/mach/hurd/dirstream.h
+++ b/sysdeps/mach/hurd/dirstream.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996 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
@@ -20,6 +20,8 @@ Cambridge, MA 02139, USA.  */
 
 #define	_DIRSTREAM_H	1
 
+#include <libc-lock.h>
+
 /* Directory stream type.
 
    The Hurd directory format is the same as `struct dirent', so `readdir'
@@ -34,6 +36,7 @@ struct __dirstream
     int __entry_ptr;		/* Entry number `__ptr' corresponds to.  */
     unsigned long int __allocation; /* Space allocated for the block.  */
     unsigned long int __size;	/* Total valid data in the block.  */
+    __libc_lock_define (, __lock); /* Mutex lock for this structure.  */
   };
 
 #endif	/* dirstream.h */
diff --git a/sysdeps/mach/hurd/opendir.c b/sysdeps/mach/hurd/opendir.c
index 8ab964a11d..bab84d52f0 100644
--- a/sysdeps/mach/hurd/opendir.c
+++ b/sysdeps/mach/hurd/opendir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996 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
@@ -49,7 +49,7 @@ DEFUN(opendir, (name), CONST char *name)
     {
       __close (fd);
       return NULL;
-    }    
+    }
 
   /* Extract the pointer to the descriptor structure.  */
   __mutex_lock (&_hurd_dtable_lock);
@@ -66,5 +66,7 @@ DEFUN(opendir, (name), CONST char *name)
   dirp->__allocation = 0;
   dirp->__size = 0;
 
+  __libc_lock_init (dirp->__lock);
+
   return dirp;
 }
diff --git a/sysdeps/mach/hurd/readdir.c b/sysdeps/mach/hurd/readdir.c
index 3c17d248e1..715f9278a2 100644
--- a/sysdeps/mach/hurd/readdir.c
+++ b/sysdeps/mach/hurd/readdir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996 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
@@ -41,6 +41,8 @@ DEFUN(readdir, (dirp), DIR *dirp)
       return NULL;
     }
 
+  __libc_lock_lock (dirp->__lock);
+
   do
     {
       if (dirp->__ptr - dirp->__data >= dirp->__size)
@@ -56,7 +58,11 @@ DEFUN(readdir, (dirp), DIR *dirp)
 						     &data, &dirp->__size,
 						     dirp->__entry_ptr,
 						     -1, 0, &nentries)))
-	    return __hurd_fail (err), NULL;
+	    {
+	      __hurd_fail (err);
+	      dp = NULL;
+	      break;
+	    }
 
 	  /* DATA now corresponds to entry index DIRP->__entry_ptr.  */
 	  dirp->__entry_data = dirp->__entry_ptr;
@@ -77,8 +83,11 @@ DEFUN(readdir, (dirp), DIR *dirp)
 	  dirp->__ptr = dirp->__data;
 
 	  if (nentries == 0)
-	    /* End of file.  */
-	    return NULL;
+	    {
+	      /* End of file.  */
+	      dp = NULL;
+	      break;
+	    }
 
 	  /* We trust the filesystem to return correct data and so we
 	     ignore NENTRIES.  */
@@ -91,5 +100,7 @@ DEFUN(readdir, (dirp), DIR *dirp)
       /* Loop to ignore deleted files.  */
     } while (dp->d_fileno == 0);
 
+  __libc_lock_unlock (dirp->__lock);
+
   return dp;
 }
diff --git a/sysdeps/mach/hurd/seekdir.c b/sysdeps/mach/hurd/seekdir.c
index fa4f1f4f52..a44ac7d246 100644
--- a/sysdeps/mach/hurd/seekdir.c
+++ b/sysdeps/mach/hurd/seekdir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996 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
@@ -27,10 +27,12 @@ Cambridge, MA 02139, USA.  */
 void
 DEFUN(seekdir, (dirp, pos), DIR *dirp AND __off_t pos)
 {
+  __libc_lock_lock (dirp->__lock);
   /* Change our entry index pointer to POS and discard any data already
      read.  The next `readdir' call will notice the empty block and read
      anew from the location in DIRP->__entry_ptr and reset the other state
      variables.  */
   dirp->__entry_ptr = pos;
   dirp->__size = 0;
+  __libc_lock_unlock (dirp->__lock);
 }
diff --git a/sysdeps/mach/libc-lock.h b/sysdeps/mach/libc-lock.h
new file mode 100644
index 0000000000..0639fc6b22
--- /dev/null
+++ b/sysdeps/mach/libc-lock.h
@@ -0,0 +1,60 @@
+/* libc-internal interface for mutex locks.  Mach cthreads version.
+Copyright (C) 1996 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.  */
+
+#ifndef _LIBC_LOCK_H
+#define _LIBC_LOCK_H 1
+
+#ifdef _LIBC
+#include <cthreads.h>
+#define __libc_lock_t struct mutex
+#else
+typedef struct __libc_lock_opaque__ __libc_lock_t;
+#endif
+
+/* Define a lock variable NAME with storage class CLASS.  The lock must be
+   initialized with __libc_lock_init before it can be used (or define it
+   with __libc_lock_define_initialized, below).  Use `extern' for CLASS to
+   declare a lock defined in another module.  In public structure
+   definitions, the lock element must come last, because its storage size
+   will not be known outside of libc.  (Or you can use a pointer to the
+   lock structure; i.e. NAME begins with a `*'.)  */
+#define __libc_lock_define(CLASS,NAME)
+  CLASS __libc_lock_t NAME;
+
+/* Define an initialized lock variable NAME with storage class CLASS.  */
+#define __libc_lock_define_initialized(CLASS,NAME) \
+  CLASS __libc_lock_t NAME = MUTEX_INITIALIZER;
+
+/* Initialize the named lock variable, leaving it in a consistent, unlocked
+   state.  */
+#define __libc_lock_init(NAME) __mutex_init (&(NAME))
+
+/* Finalize the named lock variable, which must be locked.  It cannot be
+   used again until __libc_lock_init is called again on it.  This must be
+   called on a lock variable before the containing storage is reused.  */
+#define __libc_lock_fini(NAME) __mutex_unlock (&(NAME))
+
+/* Lock the named lock variable.  */
+#define __libc_lock_lock(NAME) __mutex_lock (&(NAME))
+
+/* Unlock the named lock variable.  */
+#define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME))
+
+
+#endif	/* libc-lock.h */