* 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.
This commit is contained in:
Roland McGrath 2001-08-24 03:21:51 +00:00
parent 28cb929572
commit 0dce3d154c
7 changed files with 222 additions and 76 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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. */

View file

@ -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); \

View file

@ -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); \

View file

@ -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 */

View file

@ -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 */