From 0dce3d154c4af198a042bd2d1fd9241e6890a9b2 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 24 Aug 2001 03:21:51 +0000 Subject: [PATCH] * 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. --- ChangeLog | 26 +++++ misc/syslog.c | 8 +- stdio-common/vfprintf.c | 6 +- stdio-common/vfscanf.c | 2 +- sysdeps/mach/bits/libc-lock.h | 8 +- sysdeps/mach/hurd/bits/libc-lock.h | 183 ++++++++++++++++++++++++++++++++++++ sysdeps/mach/hurd/bits/stdio-lock.h | 65 ------------- 7 files changed, 222 insertions(+), 76 deletions(-) create mode 100644 sysdeps/mach/hurd/bits/libc-lock.h delete mode 100644 sysdeps/mach/hurd/bits/stdio-lock.h diff --git a/ChangeLog b/ChangeLog index d6e9aeb..2792243 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2001-08-23 Roland McGrath + + * 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 * elf/ldconfig.c (search_dir): Remove stale symlinks. diff --git a/misc/syslog.c b/misc/syslog.c index b89055b..9553c29 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 68631fe..c5e78c7 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 4dc9cfe..0b53d7e 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 57c36cb..2484297 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 0000000..6e38353 --- /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 +#include + +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 e2b3957..0000000 --- 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 - -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 - -#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 */ -- 2.7.4