summary refs log tree commit diff
diff options
context:
space:
mode:
-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 */