diff options
Diffstat (limited to 'sysdeps/mach')
-rw-r--r-- | sysdeps/mach/hurd/closedir.c | 20 | ||||
-rw-r--r-- | sysdeps/mach/hurd/dirstream.h | 5 | ||||
-rw-r--r-- | sysdeps/mach/hurd/opendir.c | 6 | ||||
-rw-r--r-- | sysdeps/mach/hurd/readdir.c | 19 | ||||
-rw-r--r-- | sysdeps/mach/hurd/seekdir.c | 4 | ||||
-rw-r--r-- | sysdeps/mach/libc-lock.h | 60 |
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 */ |