summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2001-08-24 03:21:51 +0000
committerRoland McGrath <roland@gnu.org>2001-08-24 03:21:51 +0000
commit0dce3d154c4af198a042bd2d1fd9241e6890a9b2 (patch)
tree5f8f58b370b2a254ba44f49bf42c6896663a1c54
parent28cb9295720d06156b7c6b577086b199a47902d3 (diff)
* sysdeps/mach/hurd/bits/libc-lock.h: New file, initially copied from
sysdeps/mach version. Implement counting ("recursive") mutexes on top of cthreads mutexes. * sysdeps/mach/hurd/bits/stdio-lock.h: File removed; generic now works. * sysdeps/generic/bits/stdio-lock.h (_IO_lock_initializer): Define to _LIBC_LOCK_RECURSIVE_INITIALIZER if defined, else do an #error. (__libc_cleanup_region_start, __libc_cleanup_region_end, __libc_clean_end): Define these to call the cleanup function after normal exit when they're supposed to. * sysdeps/mach/bits/libc-lock.h (__libc_cleanup_region_start): Take new first arg DOIT, a boolean saying whether to really install any cleanup handler. (__libc_cleanup_region_end): Do nothing if start's DOIT arg was zero. (__libc_cleanup_end): Likewise. * stdio-common/vfscanf.c (LOCK_STREAM): Pass new arg. * stdio-common/vfprintf.c (buffered_vfprintf, vfprintf): Likewise. * sysdeps/mach/hurd/bits/stdio-lock.h (_IO_cleanup_region_start): Likewise. * misc/syslog.c (vsyslog, openlog, closelog): Likewise. * sysdeps/generic/bits/stdio-lock.h (_IO_cleanup_region_start, _IO_cleanup_region_start_noarg): Likewise.
-rw-r--r--ChangeLog26
-rw-r--r--misc/syslog.c8
-rw-r--r--stdio-common/vfprintf.c6
-rw-r--r--stdio-common/vfscanf.c2
-rw-r--r--sysdeps/mach/bits/libc-lock.h8
-rw-r--r--sysdeps/mach/hurd/bits/libc-lock.h183
-rw-r--r--sysdeps/mach/hurd/bits/stdio-lock.h65
7 files changed, 222 insertions, 76 deletions
diff --git a/ChangeLog b/ChangeLog
index d6e9aeb69f..279224393f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2001-08-23 Roland McGrath <roland@frob.com>
+
+ * sysdeps/mach/hurd/bits/libc-lock.h: New file, initially copied from
+ sysdeps/mach version. Implement counting ("recursive") mutexes
+ on top of cthreads mutexes.
+ * sysdeps/mach/hurd/bits/stdio-lock.h: File removed; generic now works.
+
+ * sysdeps/generic/bits/stdio-lock.h (_IO_lock_initializer): Define to
+ _LIBC_LOCK_RECURSIVE_INITIALIZER if defined, else do an #error.
+ (__libc_cleanup_region_start, __libc_cleanup_region_end,
+ __libc_clean_end): Define these to call the cleanup function after
+ normal exit when they're supposed to.
+
+ * sysdeps/mach/bits/libc-lock.h (__libc_cleanup_region_start):
+ Take new first arg DOIT, a boolean saying whether to really install
+ any cleanup handler.
+ (__libc_cleanup_region_end): Do nothing if start's DOIT arg was zero.
+ (__libc_cleanup_end): Likewise.
+ * stdio-common/vfscanf.c (LOCK_STREAM): Pass new arg.
+ * stdio-common/vfprintf.c (buffered_vfprintf, vfprintf): Likewise.
+ * sysdeps/mach/hurd/bits/stdio-lock.h (_IO_cleanup_region_start):
+ Likewise.
+ * misc/syslog.c (vsyslog, openlog, closelog): Likewise.
+ * sysdeps/generic/bits/stdio-lock.h
+ (_IO_cleanup_region_start, _IO_cleanup_region_start_noarg): Likewise.
+
2001-08-23 Jakub Jelinek <jakub@redhat.com>
* elf/ldconfig.c (search_dir): Remove stale symlinks.
diff --git a/misc/syslog.c b/misc/syslog.c
index b89055b7b2..9553c296ea 100644
--- a/misc/syslog.c
+++ b/misc/syslog.c
@@ -216,7 +216,7 @@ vsyslog(pri, fmt, ap)
/* Prepare for multiple users. We have to take care: open and
write are cancellation points. */
- __libc_cleanup_region_start ((void (*) (void *)) cancel_handler,
+ __libc_cleanup_region_start (1, (void (*) (void *)) cancel_handler,
&oldaction_ptr);
__libc_lock_lock (syslog_lock);
@@ -315,7 +315,8 @@ void
openlog (const char *ident, int logstat, int logfac)
{
/* Protect against multiple users. */
- __libc_cleanup_region_start ((void (*) __P ((void *))) __libc_mutex_unlock,
+ __libc_cleanup_region_start (1,
+ (void (*) __P ((void *))) __libc_mutex_unlock,
&syslog_lock);
__libc_lock_lock (syslog_lock);
@@ -346,7 +347,8 @@ void
closelog ()
{
/* Protect against multiple users. */
- __libc_cleanup_region_start ((void (*) __P ((void *))) __libc_mutex_unlock,
+ __libc_cleanup_region_start (1,
+ (void (*) __P ((void *))) __libc_mutex_unlock,
&syslog_lock);
__libc_lock_lock (syslog_lock);
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 68631fe903..c5e78c7499 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -1296,10 +1296,10 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
/* Lock stream. */
#ifdef USE_IN_LIBIO
- __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, s);
+ __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, s);
_IO_flockfile (s);
#else
- __libc_cleanup_region_start ((void (*) (void *)) &__funlockfile, s);
+ __libc_cleanup_region_start (1, (void (*) (void *)) &__funlockfile, s);
__flockfile (s);
#endif
@@ -2086,7 +2086,7 @@ buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format,
result = vfprintf (hp, format, args);
/* Lock stream. */
- __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, s);
+ __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, s);
_IO_flockfile (s);
/* Now flush anything from the helper to the S. */
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 4dc9cfe3a2..0b53d7e0b6 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -168,7 +168,7 @@
} \
} while (0)
# define LOCK_STREAM(S) \
- __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \
+ __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, (S)); \
_IO_flockfile (S)
# define UNLOCK_STREAM(S) \
_IO_funlockfile (S); \
diff --git a/sysdeps/mach/bits/libc-lock.h b/sysdeps/mach/bits/libc-lock.h
index 57c36cba0b..2484297c8a 100644
--- a/sysdeps/mach/bits/libc-lock.h
+++ b/sysdeps/mach/bits/libc-lock.h
@@ -76,21 +76,21 @@ typedef cthread_key_t __libc_key_t;
/* Start a critical region with a cleanup function */
-#define __libc_cleanup_region_start(FCT, ARG) \
+#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
{ \
- typeof (***(FCT)) *__save_FCT = FCT; \
+ typeof (***(FCT)) *__save_FCT = (DOIT) ? (FCT) : 0; \
typeof (ARG) __save_ARG = ARG; \
/* close brace is in __libc_cleanup_region_end below. */
/* End a critical region started with __libc_cleanup_region_start. */
#define __libc_cleanup_region_end(DOIT) \
- if (DOIT) \
+ if ((DOIT) && __save_FCT != 0) \
(*__save_FCT)(__save_ARG); \
}
/* Sometimes we have to exit the block in the middle. */
#define __libc_cleanup_end(DOIT) \
- if (DOIT) \
+ if ((DOIT) && __save_FCT != 0) \
(*__save_FCT)(__save_ARG); \
diff --git a/sysdeps/mach/hurd/bits/libc-lock.h b/sysdeps/mach/hurd/bits/libc-lock.h
new file mode 100644
index 0000000000..6e3835371c
--- /dev/null
+++ b/sysdeps/mach/hurd/bits/libc-lock.h
@@ -0,0 +1,183 @@
+/* libc-internal interface for mutex locks. Hurd version using Mach cthreads.
+ Copyright (C) 1996,97,98,2000,01 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 Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _BITS_LIBC_LOCK_H
+#define _BITS_LIBC_LOCK_H 1
+
+#if (_LIBC - 0) || (_CTHREADS_ - 0)
+#include <cthreads.h>
+#include <hurd/threadvar.h>
+
+typedef struct mutex __libc_lock_t;
+typedef struct
+{
+ struct mutex mutex;
+ void *owner;
+ int count;
+} __libc_lock_recursive_t;
+
+#define __libc_lock_owner_self() ((void *) __hurd_threadvar_location (0))
+
+#else
+typedef struct __libc_lock_opaque__ __libc_lock_t;
+typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_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 you must use a pointer to the lock structure (i.e., NAME
+ begins with a `*'), because its storage size will not be known outside
+ of libc. */
+#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))
+#define __libc_lock_fini_recursive(NAME) __mutex_unlock (&(NAME).mutex)
+
+
+/* Lock the named lock variable. */
+#define __libc_lock_lock(NAME) __mutex_lock (&(NAME))
+
+/* Lock the named lock variable. */
+#define __libc_lock_trylock(NAME) (!__mutex_trylock (&(NAME)))
+
+/* Unlock the named lock variable. */
+#define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME))
+
+
+#define __libc_lock_define_recursive(CLASS,NAME) \
+ CLASS __libc_lock_recursive_t NAME;
+#define _LIBC_LOCK_RECURSIVE_INITIALIZER { MUTEX_INITIALIZER, 0, 0 }
+#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
+ CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
+
+#define __libc_lock_init_recursive(NAME) \
+ ({ __libc_lock_recursive_t *const __lock = &(NAME); \
+ __lock->owner = 0; mutex_init (&__lock->mutex); })
+
+#define __libc_lock_trylock_recursive(NAME) \
+ ({ __libc_lock_recursive_t *const __lock = &(NAME); \
+ void *__self = __libc_lock_owner_self (); \
+ __mutex_trylock (&__lock->mutex) \
+ ? (__lock->owner = __self, __lock->count = 1, 0) \
+ : __lock->owner == __self ? (++__lock->count, 0) : 1; })
+
+#define __libc_lock_lock_recursive(NAME) \
+ ({ __libc_lock_recursive_t *const __lock = &(NAME); \
+ void *__self = __libc_lock_owner_self (); \
+ if (__mutex_trylock (&__lock->mutex) \
+ || (__lock->owner != __self \
+ && (__mutex_lock (&__lock->mutex), 1))) \
+ __lock->owner = __self, __lock->count = 1; \
+ else \
+ ++__lock->count; \
+ })
+#define __libc_lock_unlock_recursive(NAME) \
+ ({ __libc_lock_recursive_t *const __lock = &(NAME); \
+ if (--__lock->count == 0) \
+ { \
+ __lock->owner = 0; \
+ __mutex_unlock (&__lock->mutex); \
+ } \
+ })
+
+
+/* XXX for now */
+#define __libc_rwlock_define __libc_lock_define
+#define __libc_rwlock_define_initialized __libc_lock_define_initialized
+#define __libc_rwlock_init __libc_lock_init
+#define __libc_rwlock_fini __libc_lock_fini
+#define __libc_rwlock_rdlock __libc_lock_lock
+#define __libc_rwlock_wrlock __libc_lock_lock
+#define __libc_rwlock_tryrdlock __libc_lock_trylock
+#define __libc_rwlock_trywrlock __libc_lock_trylock
+#define __libc_rwlock_unlock __libc_lock_unlock
+
+
+/* Start a critical region with a cleanup function */
+#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
+{ \
+ typeof (***(FCT)) *__save_FCT = (DOIT) ? (FCT) : 0; \
+ typeof (ARG) __save_ARG = ARG; \
+ /* close brace is in __libc_cleanup_region_end below. */
+
+/* End a critical region started with __libc_cleanup_region_start. */
+#define __libc_cleanup_region_end(DOIT) \
+ if ((DOIT) && __save_FCT != 0) \
+ (*__save_FCT)(__save_ARG); \
+}
+
+/* Sometimes we have to exit the block in the middle. */
+#define __libc_cleanup_end(DOIT) \
+ if ((DOIT) && __save_FCT != 0) \
+ (*__save_FCT)(__save_ARG); \
+
+
+#if (_CTHREADS_ - 0)
+
+/* Use mutexes as once control variables. */
+
+struct __libc_once
+ {
+ __libc_lock_t lock;
+ int done;
+ };
+
+#define __libc_once_define(CLASS,NAME) \
+ CLASS struct __libc_once NAME = { MUTEX_INITIALIZER, 0 }
+
+/* Call handler iff the first call. */
+#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
+ do { \
+ __libc_lock_lock (ONCE_CONTROL.lock); \
+ if (!ONCE_CONTROL.done) \
+ (INIT_FUNCTION) (); \
+ ONCE_CONTROL.done = 1; \
+ __libc_lock_unlock (ONCE_CONTROL.lock); \
+ } while (0)
+
+#ifdef _LIBC
+/* We need portable names for some functions. E.g., when they are
+ used as argument to __libc_cleanup_region_start. */
+#define __libc_mutex_unlock __mutex_unlock
+#endif
+
+/* Type for key of thread specific data. */
+typedef cthread_key_t __libc_key_t;
+
+#define __libc_key_create(KEY,DEST) cthread_keycreate (KEY)
+#define __libc_setspecific(KEY,VAL) cthread_setspecific (KEY, VAL)
+void *__libc_getspecific (__libc_key_t key);
+
+#endif /* _CTHREADS_ */
+
+#endif /* bits/libc-lock.h */
diff --git a/sysdeps/mach/hurd/bits/stdio-lock.h b/sysdeps/mach/hurd/bits/stdio-lock.h
deleted file mode 100644
index e2b39578a9..0000000000
--- a/sysdeps/mach/hurd/bits/stdio-lock.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Thread package specific definitions of stream lock type. Hurd version.
- Copyright (C) 2000, 2001 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 Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _BITS_STDIO_LOCK_H
-#define _BITS_STDIO_LOCK_H 1
-
-/* We need recursive (counting) mutexes. Since cthreads doesn't really
- have them, we implement them just for libio. The implementation is
- partially here and partially in Hurd's version of cthreads (i.e. the
- libthreads library, libthreads/lockfile.c). */
-
-#if (_LIBC - 0) || (_CTHREADS_ - 0)
-#include <cthreads.h>
-
-struct _IO_cthreads_lock
-{
- struct mutex mutex;
- cthread_t owner;
- unsigned int count;
-};
-#else
-struct _IO_cthreads_lock;
-#endif
-typedef struct _IO_cthreads_lock _IO_lock_t;
-
-#define _IO_lock_initializer { MUTEX_INITIALIZER, 0, 0 }
-
-#define _IO_lock_init(_name) ({ (_name) = (_IO_lock_t) _IO_lock_initializer; })
-#define _IO_lock_fini(_name) ((void) 0) /* nothing to do */
-
-/* These are in fact only used for `list_all_lock' (libio/genops.c),
- which does not need a recursive lock. The per-FILE locks are only
- accessed through _IO_flockfile et al, which Hurd's libthreads overrides. */
-#define _IO_lock_lock(_name) __libc_lock_lock ((_name).mutex)
-#define _IO_lock_unlock(_name) __libc_lock_unlock ((_name).mutex)
-
-#ifdef _LIBC
-#include <bits/libc-lock.h>
-
-#define _IO_cleanup_region_start(_fct, _fp) \
- __libc_cleanup_region_start (_fct, _fp)
-#define _IO_cleanup_region_start_noarg(_fct) \
- __libc_cleanup_region_start (_fct, NULL)
-#define _IO_cleanup_region_end(_doit) \
- __libc_cleanup_region_end (_doit)
-#endif
-
-
-#endif /* bits/stdio-lock.h */