libroot.so: libc-lock.h: use a pthread mutex based impl.

* based on current glibc sysdeps/nptl/bits/libc-lock.h file.
* include missing headers which were previously included by libc-lock.h.
* This fixes #11182.
This commit is contained in:
Jérôme Duval
2015-03-28 22:02:53 +01:00
parent c6a4fee579
commit f5e61f7174
3 changed files with 57 additions and 216 deletions
@@ -1,45 +1,41 @@
/* libc-internal interface for mutex locks. BeOS version.
Copyright (C) 1998 Be Inc.
*/
/* libc-internal interface for mutex locks. NPTL version.
Copyright (C) 1996-2015 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; see the file COPYING.LIB. If
not, see <http://www.gnu.org/licenses/>. */
#ifndef _BITS_LIBC_LOCK_H
#define _BITS_LIBC_LOCK_H 1
#include <Errors.h>
#include <OS.h>
#include <SupportDefs.h>
/* Helper definitions and prototypes. */
/* Atomic operations. */
extern char _single_threaded;
static inline int
__compare_and_swap (volatile int32 *p, int oldval, int newval)
{
int32 readval = atomic_test_and_set((int32*)p, newval, oldval);
return (readval == oldval ? 1 : 0);
}
#include <pthread.h>
#define __need_NULL
#include <stddef.h>
#define __libc_maybe_call(func, args, else) func args
#define __pthread_mutex_init pthread_mutex_init
#define __pthread_mutex_destroy pthread_mutex_destroy
#define __pthread_mutexattr_init pthread_mutexattr_init
#define __pthread_mutexattr_destroy pthread_mutexattr_destroy
#define __pthread_mutexattr_settype pthread_mutexattr_settype
#define __pthread_mutex_lock pthread_mutex_lock
#define __pthread_mutex_unlock pthread_mutex_unlock
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
/* Mutex type. */
typedef struct __libc_lock_t {
volatile int32 count;
sem_id sem;
thread_id owner;
int owner_count;
} __libc_lock_t;
#define __LIBC_LOCK_INITIALIZER { 0, 0, 0, 0 }
#define _LIBC_LOCK_RECURSIVE_INITIALIZER { 0, 0, 0, 0 }
/* Type for object to ensure once-only execution. */
typedef struct {
int __initialized;
__libc_lock_t __lock;
} __libc_once_t;
typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
/* 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
@@ -48,199 +44,41 @@ typedef struct {
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 __libc_lock_define_recursive(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 = __LIBC_LOCK_INITIALIZER;
#define __libc_lock_define_recursive(CLASS,NAME) \
CLASS __libc_lock_recursive_t NAME;
/* Define an initialized recursive lock variable NAME with storage
class CLASS. */
#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
__libc_lock_define_initialized (CLASS, NAME)
# define __libc_lock_define_initialized_recursive(CLASS,NAME) \
CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
# define _LIBC_LOCK_RECURSIVE_INITIALIZER \
{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
/* Initialize the named lock variable, leaving it in a consistent, unlocked
state. */
#define __libc_lock_init(NAME) \
(NAME).count = (NAME).sem = (NAME).owner_count = (NAME).owner = 0 \
/* Same as last but this time we initialize a recursive mutex. */
#define __libc_lock_init_recursive(NAME) \
__libc_lock_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) \
do { \
if ((NAME).sem) \
delete_sem((NAME).sem); \
} while(0)
/* Initialize a recursive mutex. */
# define __libc_lock_init_recursive(NAME) \
do { \
pthread_mutexattr_t __attr; \
__pthread_mutexattr_init (&__attr); \
__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
__pthread_mutex_init (&(NAME).mutex, &__attr); \
__pthread_mutexattr_destroy (&__attr); \
} while (0)
/* Finalize recursive named lock. */
#define __libc_lock_fini_recursive(NAME) __libc_lock_fini(NAME)
/* Lock the named lock variable. */
#define __libc_lock_lock(NAME) \
do { \
if (!_single_threaded) { \
long err; \
long old = atomic_add(&(NAME).count, 1); \
if (old > 0) { \
if ((NAME).sem == 0) { \
sem_id __new_sem = create_sem (0, "libc:" #NAME); \
if (!__compare_and_swap ((volatile int32 *)&(NAME).sem, 0, __new_sem)) \
/* We do not need the semaphore. */ \
delete_sem (__new_sem); \
} \
do { \
err = acquire_sem((NAME).sem); \
} while (err == B_INTERRUPTED); \
} \
} \
} while (0)
# define __libc_lock_fini_recursive(NAME) \
__libc_maybe_call (__pthread_mutex_destroy, (&(NAME).mutex), 0)
/* Lock the recursive named lock variable. */
#define __libc_lock_lock_recursive(NAME) \
do { \
if (!_single_threaded) { \
thread_id owner = find_thread(NULL); \
long old, err = B_OK; \
if (owner == (NAME).owner) { \
(NAME).owner_count++; \
break; \
} \
old = atomic_add(&(NAME).count, 1); \
if (old > 0) { \
if ((NAME).sem == 0) { \
sem_id __new_sem = create_sem (0, "libc:" #NAME); \
if (!__compare_and_swap ((volatile int32 *)&(NAME).sem, 0, __new_sem)) \
/* We do not need the semaphore. */ \
delete_sem (__new_sem); \
} \
do { \
err = acquire_sem((NAME).sem); \
} while (err == B_INTERRUPTED); \
} \
if (err == B_OK) { \
(NAME).owner = owner; \
(NAME).owner_count = 1; \
} \
} \
} while (0)
# define __libc_lock_lock_recursive(NAME) \
__libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0)
#if 0
/* Try to lock the named lock variable. */
#define __libc_lock_trylock(NAME) \
({ \
int __result = EBUSY; \
status_t err; \
if (!(NAME).sem) { \
__libc_sem_id __new_sem = create_sem (1, "libc:" #NAME); \
if (!__compare_and_swap (&(NAME).sem, 0, __new_sem)) \
/* We do not need the semaphore. */ \
delete_sem (__new_sem); \
} \
do { \
err = acquire_sem_etc ((NAME).sem, 1, B_TIMEOUT, 0); \
if (err == B_OK) { \
NAME.__count = 1; \
__result = 0; \
} \
} while (err == B_INTERRUPTED); \
__result; })
#endif
#if 0
/* Try to lock the recursive named lock variable. */
#define __libc_lock_trylock_recursive(NAME) \
({ \
__libc_thread_id __me = find_thread (NULL); \
int __result = EBUSY; \
status_t err; \
if (!(NAME).sem) { \
__libc_sem_id __new_sem = create_sem (1, "libc:" #NAME); \
if (!__compare_and_swap (&(NAME).sem, 0, __new_sem)) \
/* We do not need the semaphore. */ \
delete_sem (__new_sem); \
} \
if ((NAME).__owner == __me) {\
++(NAME).__count; \
__result = 0; \
} else \
do { \
err = acquire_sem_etc ((NAME).sem, 1, B_TIMEOUT, 0); \
if (err == B_OK) { \
(NAME).__owner = __me; \
(NAME).__count = 1; \
__result = 0; \
} \
} while (err == B_INTERRUPTED); \
__result; })
#endif
/* Unlock the named lock variable. */
#define __libc_lock_unlock(NAME) \
do { \
if (!_single_threaded) { \
if (atomic_add(&(NAME).count, -1) > 1) { \
if ((NAME).sem == 0) { \
sem_id __new_sem = create_sem (0, "libc:" #NAME); \
if (!__compare_and_swap ((volatile int32 *)&(NAME).sem, 0, __new_sem)) \
/* We do not need the semaphore. */ \
delete_sem (__new_sem); \
} \
release_sem((NAME).sem); \
} \
} \
} while(0)
# define __libc_lock_trylock_recursive(NAME) \
__libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0)
/* Unlock the recursive named lock variable. */
#define __libc_lock_unlock_recursive(NAME) \
do { \
if (!_single_threaded) { \
(NAME).owner_count--; \
if ((NAME).owner_count == 0) { \
(NAME).owner = 0; \
if (atomic_add(&(NAME).count, -1) > 1) { \
if ((NAME).sem == 0) { \
sem_id __new_sem = create_sem (0, "libc:" #NAME); \
if (!__compare_and_swap ((volatile int32 *)&(NAME).sem, 0, __new_sem)) \
/* We do not need the semaphore. */ \
delete_sem (__new_sem); \
} \
release_sem((NAME).sem); \
} \
} \
} \
} while(0)
/* Define once control variable. */
#define __libc_once_define(CLASS, NAME) \
CLASS __libc_once_t NAME = { 0, __LIBC_LOCK_INITIALIZER }
/* Call handler iff the first call. */
#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
do { \
if (! ONCE_CONTROL.__initialized) \
{ \
__libc_lock_lock (ONCE_CONTROL.__lock); \
if (! ONCE_CONTROL.__initialized) \
{ \
/* Still not initialized, then call the function. */ \
INIT_FUNCTION (); \
ONCE_CONTROL.__initialized = 1; \
} \
__libc_lock_unlock (ONCE_CONTROL.__lock); \
} \
} while (0)
# define __libc_lock_unlock_recursive(NAME) \
__libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0)
/* Start critical region with cleanup. */
#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
@@ -33,6 +33,7 @@
#include <gconv.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#ifndef _LIBC
@@ -19,6 +19,8 @@
#include <stdio_private.h>
#include <limits.h>
#include <string.h>