mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 19:00:07 +00:00
* Versions.def: Add GLIBC_2.4 for libpthread.
This commit is contained in:
parent
08f60b258e
commit
1bcfb5a5eb
@ -1,3 +1,7 @@
|
||||
2005-12-26 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* Versions.def: Add GLIBC_2.4 for libpthread.
|
||||
|
||||
2005-12-25 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* stdlib/Makefile ($(objpfx)isomac.out): Move -I.. to the end so
|
||||
|
@ -80,6 +80,7 @@ libpthread {
|
||||
GLIBC_2.3.2
|
||||
GLIBC_2.3.3
|
||||
GLIBC_2.3.4
|
||||
GLIBC_2.4
|
||||
GLIBC_PRIVATE
|
||||
}
|
||||
libresolv {
|
||||
|
@ -1,3 +1,56 @@
|
||||
2005-12-26 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* pthreadP.h: Define PTHREAD_MUTEX_ROBUST_PRIVATE_NP,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP,
|
||||
PTHREAD_MUTEXATTR_FLAG_ROBUST, PTHREAD_MUTEXATTR_FLAG_PSHARED,
|
||||
and PTHREAD_MUTEXATTR_FLAG_BITS.
|
||||
* descr.h (struct pthread): Add robust_list field and define
|
||||
ENQUEUE_MUTEX and DEQUEUE_MUTEX macros.
|
||||
* pthread_mutexattr_getrobust.c: New file.
|
||||
* pthread_mutexattr_setrobust.c: New file.
|
||||
* pthread_mutex_consistent.c: New file.
|
||||
* sysdeps/pthread/pthread.h: Declare pthread_mutexattr_getrobust,
|
||||
pthread_mutexattr_setrobust, and pthread_mutex_consistent.
|
||||
Define PTHREAD_MUTEX_STALLED_NP and PTHREAD_MUTEX_ROBUST_NP.
|
||||
Adjust pthread_mutex_t initializers.
|
||||
* nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Add __next
|
||||
field to pthread_mutex_t.
|
||||
* nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Add __next
|
||||
and __prev field to pthread_mutex_t.
|
||||
* Versions [GLIBC_2.4]: Export pthread_mutexattr_getrobust_np,
|
||||
pthread_mutexattr_setrobust_np, and pthread_mutex_consistent_np.
|
||||
* pthread_mutexattr_getpshared.c: Use PTHREAD_MUTEXATTR_FLAG_PSHARED
|
||||
and PTHREAD_MUTEXATTR_FLAG_BITS macros instead of magic numbers.
|
||||
* pthread_mutexattr_gettype.c: Likewise.
|
||||
* pthread_mutexattr_setpshared.c: Likewise.
|
||||
* pthread_mutexattr_settype.c: Likewise.
|
||||
* pthread_mutex_init.c: Reject robust+pshared attribute for now.
|
||||
Initialize mutex kind according to robust flag.
|
||||
* pthread_mutex_lock.c: Implement local robust mutex.
|
||||
* pthread_mutex_timedlock.c: Likewise.
|
||||
* pthread_mutex_trylock.c: Likewise.
|
||||
* pthread_mutex_unlock.c: Likewise.
|
||||
* pthread_create.c (start_thread): Mark robust mutexes which remained
|
||||
locked as dead.
|
||||
* tst-robust1.c: New file.
|
||||
* tst-robust2.c: New file.
|
||||
* tst-robust3.c: New file.
|
||||
* tst-robust4.c: New file.
|
||||
* tst-robust5.c: New file.
|
||||
* tst-robust6.c: New file.
|
||||
* tst-robust7.c: New file.
|
||||
* Makefile (libpthread-routines): Add pthread_mutexattr_getrobust,
|
||||
pthread_mutexattr_setrobust, and pthread_mutex_consistent.
|
||||
(tests): Add tst-robust1, tst-robust2, tst-robust3, tst-robust4,
|
||||
tst-robust5, tst-robust6, and tst-robust7.
|
||||
|
||||
* tst-typesizes.c: New file.
|
||||
* Makefile (tests): Add tst-typesizes.
|
||||
|
||||
* tst-once3.c: More debug output.
|
||||
|
||||
2005-12-24 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* pthread_mutex_trylock.c (__pthread_mutex_trylock): Add break
|
||||
|
@ -116,6 +116,8 @@ libpthread-routines = init vars events version \
|
||||
pthread_kill_other_threads \
|
||||
pthread_getaffinity pthread_setaffinity \
|
||||
pthread_attr_getaffinity pthread_attr_setaffinity \
|
||||
pthread_mutexattr_getrobust pthread_mutexattr_setrobust \
|
||||
pthread_mutex_consistent \
|
||||
cleanup_routine unwind-forcedunwind
|
||||
# pthread_setuid pthread_seteuid pthread_setreuid \
|
||||
# pthread_setresuid \
|
||||
@ -189,7 +191,8 @@ CFLAGS-pt-system.c = -fexceptions
|
||||
omit-deps = $(unix-syscalls:%=ptw-%)
|
||||
|
||||
|
||||
tests = tst-attr1 tst-attr2 tst-attr3 \
|
||||
tests = tst-typesizes \
|
||||
tst-attr1 tst-attr2 tst-attr3 \
|
||||
tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
|
||||
tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \
|
||||
tst-spin1 tst-spin2 tst-spin3 \
|
||||
@ -197,6 +200,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
|
||||
tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
|
||||
tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
|
||||
tst-cond20 tst-cond21 \
|
||||
tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
|
||||
tst-robust6 tst-robust7 \
|
||||
tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \
|
||||
tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \
|
||||
tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \
|
||||
|
@ -232,6 +232,11 @@ libpthread {
|
||||
pthread_setschedprio;
|
||||
}
|
||||
|
||||
GLIBC_2.4 {
|
||||
pthread_mutexattr_getrobust_np; pthread_mutexattr_setrobust_np;
|
||||
pthread_mutex_consistent_np;
|
||||
};
|
||||
|
||||
GLIBC_PRIVATE {
|
||||
__pthread_initialize_minimal;
|
||||
__pthread_clock_gettime; __pthread_clock_settime;
|
||||
|
45
nptl/descr.h
45
nptl/descr.h
@ -134,6 +134,51 @@ struct pthread
|
||||
/* Process ID - thread group ID in kernel speak. */
|
||||
pid_t pid;
|
||||
|
||||
/* List of robust mutexes the thread is holding. */
|
||||
pthread_mutex_t *robust_list;
|
||||
|
||||
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||
# define ENQUEUE_MUTEX(mutex) \
|
||||
do { \
|
||||
mutex->__data.__next = THREAD_GETMEM (THREAD_SELF, robust_list); \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list, mutex); \
|
||||
if (mutex->__data.__next != NULL) \
|
||||
mutex->__data.__next->__data.__prev = mutex; \
|
||||
mutex->__data.__prev = NULL; \
|
||||
} while (0)
|
||||
# define DEQUEUE_MUTEX(mutex) \
|
||||
do { \
|
||||
if (mutex->__data.__prev == NULL) \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list, mutex->__data.__next); \
|
||||
else \
|
||||
mutex->__data.__prev->__data.__next = mutex->__data.__next; \
|
||||
if (mutex->__data.__next != NULL) \
|
||||
mutex->__data.__next->__data.__prev = mutex->__data.__prev; \
|
||||
mutex->__data.__prev = NULL; \
|
||||
mutex->__data.__next = NULL; \
|
||||
} while (0)
|
||||
#else
|
||||
# define ENQUEUE_MUTEX(mutex) \
|
||||
do { \
|
||||
mutex->__data.__next = THREAD_GETMEM (THREAD_SELF, robust_list); \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list, mutex); \
|
||||
} while (0)
|
||||
# define DEQUEUE_MUTEX(mutex) \
|
||||
do { \
|
||||
pthread_mutex_t *runp = THREAD_GETMEM (THREAD_SELF, robust_list); \
|
||||
if (runp == mutex) \
|
||||
THREAD_SETMEM (THREAD_SELF, robust_list, runp->__data.__next); \
|
||||
else \
|
||||
{ \
|
||||
while (runp->__data.__next != mutex) \
|
||||
runp = runp->__data.__next; \
|
||||
\
|
||||
runp->__data.__next = runp->__data.__next->__data.__next; \
|
||||
mutex->__data.__next = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* List of cleanup buffers. */
|
||||
struct _pthread_cleanup_buffer *cleanup;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -51,6 +51,32 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Magic cookie representing robust mutex with dead owner. */
|
||||
#define PTHREAD_MUTEX_OWNERDEAD INT_MAX
|
||||
/* Magic cookie representing not recoverable robust mutex. */
|
||||
#define PTHREAD_MUTEX_NOTRECOVERABLE (INT_MAX - 1)
|
||||
|
||||
|
||||
/* Internal mutex type value. */
|
||||
enum
|
||||
{
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_NP = 256,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP
|
||||
= PTHREAD_MUTEX_ROBUST_PRIVATE_NP | PTHREAD_MUTEX_RECURSIVE_NP,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP
|
||||
= PTHREAD_MUTEX_ROBUST_PRIVATE_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
|
||||
PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP
|
||||
= PTHREAD_MUTEX_ROBUST_PRIVATE_NP | PTHREAD_MUTEX_ADAPTIVE_NP
|
||||
};
|
||||
|
||||
|
||||
/* Flags in mutex attr. */
|
||||
#define PTHREAD_MUTEXATTR_FLAG_ROBUST 0x40000000
|
||||
#define PTHREAD_MUTEXATTR_FLAG_PSHARED 0x80000000
|
||||
#define PTHREAD_MUTEXATTR_FLAG_BITS \
|
||||
(PTHREAD_MUTEXATTR_FLAG_ROBUST | PTHREAD_MUTEXATTR_FLAG_PSHARED)
|
||||
|
||||
|
||||
/* Internal variables. */
|
||||
|
||||
|
||||
|
@ -310,6 +310,33 @@ start_thread (void *arg)
|
||||
the breakpoint reports TD_THR_RUN state rather than TD_THR_ZOMBIE. */
|
||||
atomic_bit_set (&pd->cancelhandling, EXITING_BIT);
|
||||
|
||||
/* If this thread has any robust mutexes locked, handle them now. */
|
||||
pthread_mutex_t *robust = THREAD_GETMEM (pd, robust_list);
|
||||
if (__builtin_expect (robust != NULL, 0))
|
||||
{
|
||||
do
|
||||
{
|
||||
pthread_mutex_t *this = robust;
|
||||
robust = robust->__data.__next;
|
||||
|
||||
assert (lll_mutex_islocked (this->__data.__lock));
|
||||
this->__data.__count = 0;
|
||||
--this->__data.__nusers;
|
||||
assert (this->__data.__owner != PTHREAD_MUTEX_NOTRECOVERABLE);
|
||||
this->__data.__owner = PTHREAD_MUTEX_OWNERDEAD;
|
||||
this->__data.__next = NULL;
|
||||
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||
this->__data.__prev = NULL;
|
||||
#endif
|
||||
|
||||
lll_mutex_unlock (this->__data.__lock);
|
||||
}
|
||||
while (robust != NULL);
|
||||
|
||||
/* Clean up so that the thread descriptor can be reused. */
|
||||
THREAD_SETMEM (pd, robust_list, NULL);
|
||||
}
|
||||
|
||||
/* If the thread is detached free the TCB. */
|
||||
if (IS_DETACHED (pd))
|
||||
/* Free the TCB. */
|
||||
|
36
nptl/pthread_mutex_consistent.c
Normal file
36
nptl/pthread_mutex_consistent.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
|
||||
|
||||
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. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
int
|
||||
pthread_mutex_consistent_np (mutex)
|
||||
pthread_mutex_t *mutex;
|
||||
{
|
||||
/* Test whether this is a robust mutex with a dead owner. */
|
||||
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_PRIVATE_NP) == 0
|
||||
|| mutex->__data.__owner != -THREAD_GETMEM (THREAD_SELF, tid))
|
||||
return EINVAL;
|
||||
|
||||
mutex->__data.__owner = -mutex->__data.__owner;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "pthreadP.h"
|
||||
|
||||
@ -40,17 +41,26 @@ __pthread_mutex_init (mutex, mutexattr)
|
||||
|
||||
imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;
|
||||
|
||||
/* Sanity checks. */
|
||||
// XXX For now we cannot implement robust mutexes if they are shared.
|
||||
if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0
|
||||
&& (imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0)
|
||||
return ENOTSUP;
|
||||
|
||||
/* Clear the whole variable. */
|
||||
memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T);
|
||||
|
||||
/* Copy the values from the attribute. */
|
||||
mutex->__data.__kind = imutexattr->mutexkind & ~0x80000000;
|
||||
mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
|
||||
if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0)
|
||||
mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_PRIVATE_NP;
|
||||
|
||||
/* Default values: mutex not used yet. */
|
||||
// mutex->__count = 0; already done by memset
|
||||
// mutex->__owner = 0; already done by memset
|
||||
// mutex->__nusers = 0; already done by memset
|
||||
// mutex->__spins = 0; already done by memset
|
||||
// mutex->__next = NULL; already done by memset
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "pthreadP.h"
|
||||
#include <lowlevellock.h>
|
||||
|
||||
@ -37,6 +38,7 @@ __pthread_mutex_lock (mutex)
|
||||
|
||||
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
|
||||
int retval = 0;
|
||||
switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
|
||||
{
|
||||
/* Recursive mutex. */
|
||||
@ -57,13 +59,14 @@ __pthread_mutex_lock (mutex)
|
||||
/* We have to get the mutex. */
|
||||
LLL_MUTEX_LOCK (mutex->__data.__lock);
|
||||
|
||||
assert (mutex->__data.__owner == 0);
|
||||
mutex->__data.__count = 1;
|
||||
break;
|
||||
|
||||
/* Error checking mutex. */
|
||||
case PTHREAD_MUTEX_ERRORCHECK_NP:
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (mutex->__data.__owner == id)
|
||||
if (__builtin_expect (mutex->__data.__owner == id, 0))
|
||||
return EDEADLK;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
@ -72,6 +75,7 @@ __pthread_mutex_lock (mutex)
|
||||
simple:
|
||||
/* Normal mutex. */
|
||||
LLL_MUTEX_LOCK (mutex->__data.__lock);
|
||||
assert (mutex->__data.__owner == 0);
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_ADAPTIVE_NP:
|
||||
@ -99,6 +103,65 @@ __pthread_mutex_lock (mutex)
|
||||
|
||||
mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
|
||||
}
|
||||
assert (mutex->__data.__owner == 0);
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (abs (mutex->__data.__owner) == id)
|
||||
{
|
||||
/* Just bump the counter. */
|
||||
if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
|
||||
/* Overflow of the counter. */
|
||||
return EAGAIN;
|
||||
|
||||
++mutex->__data.__count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We have to get the mutex. */
|
||||
LLL_MUTEX_LOCK (mutex->__data.__lock);
|
||||
|
||||
mutex->__data.__count = 1;
|
||||
|
||||
goto robust;
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (__builtin_expect (abs (mutex->__data.__owner) == id, 0))
|
||||
return EDEADLK;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
|
||||
LLL_MUTEX_LOCK (mutex->__data.__lock);
|
||||
|
||||
robust:
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
{
|
||||
/* This mutex is now not recoverable. */
|
||||
mutex->__data.__count = 0;
|
||||
lll_mutex_unlock (mutex->__data.__lock);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
/* This mutex is either healthy or we can try to recover it. */
|
||||
assert (mutex->__data.__owner == 0
|
||||
|| mutex->__data.__owner == PTHREAD_MUTEX_OWNERDEAD);
|
||||
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_OWNERDEAD, 0))
|
||||
{
|
||||
retval = EOWNERDEAD;
|
||||
/* We signal ownership of a not yet recovered robust mutex
|
||||
by storing the negative thread ID. */
|
||||
id = -id;
|
||||
}
|
||||
|
||||
ENQUEUE_MUTEX (mutex);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -107,13 +170,12 @@ __pthread_mutex_lock (mutex)
|
||||
}
|
||||
|
||||
/* Record the ownership. */
|
||||
assert (mutex->__data.__owner == 0);
|
||||
mutex->__data.__owner = id;
|
||||
#ifndef NO_INCR
|
||||
++mutex->__data.__nusers;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
#ifndef __pthread_mutex_lock
|
||||
strong_alias (__pthread_mutex_lock, pthread_mutex_lock)
|
||||
|
@ -17,6 +17,7 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include "pthreadP.h"
|
||||
#include <lowlevellock.h>
|
||||
@ -49,17 +50,15 @@ pthread_mutex_timedlock (mutex, abstime)
|
||||
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have to get the mutex. */
|
||||
result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
|
||||
|
||||
if (result != 0)
|
||||
goto out;
|
||||
/* We have to get the mutex. */
|
||||
result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
|
||||
|
||||
/* Only locked once so far. */
|
||||
mutex->__data.__count = 1;
|
||||
}
|
||||
if (result != 0)
|
||||
goto out;
|
||||
|
||||
/* Only locked once so far. */
|
||||
mutex->__data.__count = 1;
|
||||
break;
|
||||
|
||||
/* Error checking mutex. */
|
||||
@ -103,6 +102,71 @@ pthread_mutex_timedlock (mutex, abstime)
|
||||
}
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (abs (mutex->__data.__owner) == id)
|
||||
{
|
||||
/* Just bump the counter. */
|
||||
if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
|
||||
/* Overflow of the counter. */
|
||||
return EAGAIN;
|
||||
|
||||
++mutex->__data.__count;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We have to get the mutex. */
|
||||
result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
|
||||
|
||||
if (result != 0)
|
||||
goto out;
|
||||
|
||||
/* Only locked once so far. */
|
||||
mutex->__data.__count = 1;
|
||||
goto robust;
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (__builtin_expect (abs (mutex->__data.__owner) == id, 0))
|
||||
return EDEADLK;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
|
||||
result = lll_mutex_timedlock (mutex->__data.__lock, abstime);
|
||||
|
||||
if (result != 0)
|
||||
goto out;
|
||||
|
||||
robust:
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
{
|
||||
/* This mutex is now not recoverable. */
|
||||
mutex->__data.__count = 0;
|
||||
lll_mutex_unlock (mutex->__data.__lock);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
/* This mutex is either healthy or we can try to recover it. */
|
||||
assert (mutex->__data.__owner == 0
|
||||
|| mutex->__data.__owner == PTHREAD_MUTEX_OWNERDEAD);
|
||||
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_OWNERDEAD, 0))
|
||||
{
|
||||
result = EOWNERDEAD;
|
||||
/* We signal ownership of a not yet recovered robust mutex
|
||||
by storing the negative thread ID. */
|
||||
mutex->__data.__owner = -id;
|
||||
++mutex->__data.__nusers;
|
||||
}
|
||||
|
||||
ENQUEUE_MUTEX (mutex);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Correct code cannot set any other type. */
|
||||
return EINVAL;
|
||||
|
@ -17,7 +17,9 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "pthreadP.h"
|
||||
#include <lowlevellock.h>
|
||||
|
||||
@ -26,13 +28,12 @@ int
|
||||
__pthread_mutex_trylock (mutex)
|
||||
pthread_mutex_t *mutex;
|
||||
{
|
||||
pid_t id;
|
||||
pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
|
||||
switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
|
||||
{
|
||||
/* Recursive mutex. */
|
||||
case PTHREAD_MUTEX_RECURSIVE_NP:
|
||||
id = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (mutex->__data.__owner == id)
|
||||
{
|
||||
@ -56,20 +57,93 @@ __pthread_mutex_trylock (mutex)
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_ERRORCHECK_NP:
|
||||
/* Error checking mutex. We do not check for deadlocks. */
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (__builtin_expect (mutex->__data.__owner == id, 0))
|
||||
return EDEADLK;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PTHREAD_MUTEX_TIMED_NP:
|
||||
case PTHREAD_MUTEX_ADAPTIVE_NP:
|
||||
/* Normal mutex. */
|
||||
if (lll_mutex_trylock (mutex->__data.__lock) == 0)
|
||||
if (lll_mutex_trylock (mutex->__data.__lock) != 0)
|
||||
break;
|
||||
|
||||
/* Record the ownership. */
|
||||
mutex->__data.__owner = id;
|
||||
++mutex->__data.__nusers;
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (abs (mutex->__data.__owner) == id)
|
||||
{
|
||||
/* Record the ownership. */
|
||||
mutex->__data.__owner = THREAD_GETMEM (THREAD_SELF, tid);
|
||||
++mutex->__data.__nusers;
|
||||
/* Just bump the counter. */
|
||||
if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
|
||||
/* Overflow of the counter. */
|
||||
return EAGAIN;
|
||||
|
||||
++mutex->__data.__count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We have to get the mutex. */
|
||||
if (lll_mutex_trylock (mutex->__data.__lock) == 0)
|
||||
{
|
||||
mutex->__data.__count = 1;
|
||||
|
||||
goto robust;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
|
||||
/* Check whether we already hold the mutex. */
|
||||
if (__builtin_expect (abs (mutex->__data.__owner) == id, 0))
|
||||
return EDEADLK;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
|
||||
if (lll_mutex_trylock (mutex->__data.__lock) != 0)
|
||||
break;
|
||||
|
||||
robust:
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE, 0))
|
||||
{
|
||||
/* This mutex is now not recoverable. */
|
||||
mutex->__data.__count = 0;
|
||||
lll_mutex_unlock (mutex->__data.__lock);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
/* This mutex is either healthy or we can try to recover it. */
|
||||
assert (mutex->__data.__owner == 0
|
||||
|| mutex->__data.__owner == PTHREAD_MUTEX_OWNERDEAD);
|
||||
|
||||
/* Record the ownership. */
|
||||
int retval = 0;
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_OWNERDEAD, 0))
|
||||
{
|
||||
retval = EOWNERDEAD;
|
||||
/* We signal ownership of a not yet recovered robust
|
||||
mutex by storing the negative thread ID. */
|
||||
id = -id;
|
||||
}
|
||||
|
||||
ENQUEUE_MUTEX (mutex);
|
||||
|
||||
mutex->__data.__owner = id;
|
||||
++mutex->__data.__nusers;
|
||||
|
||||
return retval
|
||||
;
|
||||
default:
|
||||
/* Correct code cannot set any other type. */
|
||||
return EINVAL;
|
||||
|
@ -18,6 +18,7 @@
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "pthreadP.h"
|
||||
#include <lowlevellock.h>
|
||||
|
||||
@ -28,6 +29,8 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
||||
pthread_mutex_t *mutex;
|
||||
int decr;
|
||||
{
|
||||
int newowner = 0;
|
||||
|
||||
switch (__builtin_expect (mutex->__data.__kind, PTHREAD_MUTEX_TIMED_NP))
|
||||
{
|
||||
case PTHREAD_MUTEX_RECURSIVE_NP:
|
||||
@ -52,13 +55,58 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
||||
/* Normal mutex. Nothing special to do. */
|
||||
break;
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP:
|
||||
/* Recursive mutex. */
|
||||
if (mutex->__data.__owner == -THREAD_GETMEM (THREAD_SELF, tid))
|
||||
{
|
||||
if (--mutex->__data.__count != 0)
|
||||
/* We still hold the mutex. */
|
||||
return ENOTRECOVERABLE;
|
||||
|
||||
goto notrecoverable;
|
||||
}
|
||||
|
||||
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
|
||||
return EPERM;
|
||||
|
||||
if (--mutex->__data.__count != 0)
|
||||
/* We still hold the mutex. */
|
||||
return 0;
|
||||
|
||||
goto robust;
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
|
||||
/* Error checking mutex. */
|
||||
if (abs (mutex->__data.__owner) != THREAD_GETMEM (THREAD_SELF, tid)
|
||||
|| ! lll_mutex_islocked (mutex->__data.__lock))
|
||||
return EPERM;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
|
||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
|
||||
/* If the previous owner died and the caller did not succeed in
|
||||
making the state consistent, mark the mutex as unrecoverable
|
||||
and make all waiters. */
|
||||
if (__builtin_expect (mutex->__data.__owner
|
||||
== -THREAD_GETMEM (THREAD_SELF, tid)
|
||||
|| (mutex->__data.__owner
|
||||
== PTHREAD_MUTEX_NOTRECOVERABLE), 0))
|
||||
notrecoverable:
|
||||
newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
|
||||
|
||||
robust:
|
||||
/* Remove mutex from the list. */
|
||||
DEQUEUE_MUTEX (mutex);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Correct code cannot set any other type. */
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Always reset the owner field. */
|
||||
mutex->__data.__owner = 0;
|
||||
mutex->__data.__owner = newowner;
|
||||
if (decr)
|
||||
/* One less user. */
|
||||
--mutex->__data.__nusers;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -29,9 +29,7 @@ pthread_mutexattr_getpshared (attr, pshared)
|
||||
|
||||
iattr = (const struct pthread_mutexattr *) attr;
|
||||
|
||||
/* We use bit 31 to signal whether the mutex is going to be
|
||||
process-shared or not. */
|
||||
*pshared = ((iattr->mutexkind & 0x80000000) != 0
|
||||
*pshared = ((iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0
|
||||
? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE);
|
||||
|
||||
return 0;
|
||||
|
36
nptl/pthread_mutexattr_getrobust.c
Normal file
36
nptl/pthread_mutexattr_getrobust.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
|
||||
|
||||
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. */
|
||||
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
int
|
||||
pthread_mutexattr_getrobust_np (attr, robustness)
|
||||
const pthread_mutexattr_t *attr;
|
||||
int *robustness;
|
||||
{
|
||||
const struct pthread_mutexattr *iattr;
|
||||
|
||||
iattr = (const struct pthread_mutexattr *) attr;
|
||||
|
||||
*robustness = ((iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0
|
||||
? PTHREAD_MUTEX_ROBUST_NP : PTHREAD_MUTEX_STALLED_NP);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -29,9 +29,7 @@ pthread_mutexattr_gettype (attr, kind)
|
||||
|
||||
iattr = (const struct pthread_mutexattr *) attr;
|
||||
|
||||
/* We use bit 31 to signal whether the mutex is going to be
|
||||
process-shared or not. */
|
||||
*kind = iattr->mutexkind & ~0x80000000;
|
||||
*kind = iattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -34,12 +34,10 @@ pthread_mutexattr_setpshared (attr, pshared)
|
||||
|
||||
iattr = (struct pthread_mutexattr *) attr;
|
||||
|
||||
/* We use bit 31 to signal whether the mutex is going to be
|
||||
process-shared or not. */
|
||||
if (pshared == PTHREAD_PROCESS_PRIVATE)
|
||||
iattr->mutexkind &= ~0x80000000;
|
||||
iattr->mutexkind &= ~PTHREAD_MUTEXATTR_FLAG_PSHARED;
|
||||
else
|
||||
iattr->mutexkind |= 0x80000000;
|
||||
iattr->mutexkind |= PTHREAD_MUTEXATTR_FLAG_PSHARED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
43
nptl/pthread_mutexattr_setrobust.c
Normal file
43
nptl/pthread_mutexattr_setrobust.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
|
||||
|
||||
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. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
int
|
||||
pthread_mutexattr_setrobust_np (attr, robustness)
|
||||
pthread_mutexattr_t *attr;
|
||||
int robustness;
|
||||
{
|
||||
if (robustness != PTHREAD_MUTEX_STALLED_NP
|
||||
&& __builtin_expect (robustness != PTHREAD_MUTEX_ROBUST_NP, 0))
|
||||
return EINVAL;
|
||||
|
||||
struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr;
|
||||
|
||||
/* We use bit 30 to signal whether the mutex is going to be
|
||||
robust or not. */
|
||||
if (robustness == PTHREAD_MUTEX_STALLED_NP)
|
||||
iattr->mutexkind &= ~PTHREAD_MUTEXATTR_FLAG_ROBUST;
|
||||
else
|
||||
iattr->mutexkind |= PTHREAD_MUTEXATTR_FLAG_ROBUST;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -33,9 +33,7 @@ __pthread_mutexattr_settype (attr, kind)
|
||||
|
||||
iattr = (struct pthread_mutexattr *) attr;
|
||||
|
||||
/* We use bit 31 to signal whether the mutex is going to be
|
||||
process-shared or not. */
|
||||
iattr->mutexkind = (iattr->mutexkind & 0x80000000) | kind;
|
||||
iattr->mutexkind = (iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_BITS) | kind;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -60,24 +60,39 @@ enum
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Mutex initializers. */
|
||||
#define PTHREAD_MUTEX_INITIALIZER \
|
||||
{ { 0, 0, 0, 0, 0, 0 } }
|
||||
|
||||
#ifdef __USE_GNU
|
||||
# if __WORDSIZE == 64
|
||||
/* Robust mutex or not flags. */
|
||||
enum
|
||||
{
|
||||
PTHREAD_MUTEX_STALLED_NP,
|
||||
PTHREAD_MUTEX_ROBUST_NP
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* Mutex initializers. */
|
||||
#if __WORDSIZE == 64
|
||||
# define PTHREAD_MUTEX_INITIALIZER \
|
||||
{ { 0, 0, 0, 0, 0, 0, (void *) 0, (void *) 0 } }
|
||||
# ifdef __USE_GNU
|
||||
# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
|
||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0 } }
|
||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, (void *) 0, (void *) 0 } }
|
||||
# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
|
||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0 } }
|
||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, (void *) 0, (void *) 0 } }
|
||||
# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
|
||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0 } }
|
||||
# else
|
||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, (void *) 0, (void *) 0 } }
|
||||
# endif
|
||||
#else
|
||||
# define PTHREAD_MUTEX_INITIALIZER \
|
||||
{ { 0, 0, 0, 0, 0, { 0 } } }
|
||||
# ifdef __USE_GNU
|
||||
# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
|
||||
{ { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0 } }
|
||||
{ { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0 } } }
|
||||
# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
|
||||
{ { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, 0 } }
|
||||
{ { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0 } } }
|
||||
# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
|
||||
{ { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, 0 } }
|
||||
{ { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0 } } }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -696,6 +711,12 @@ extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
|
||||
extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW;
|
||||
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* Declare the state protected by MUTEX as consistent. */
|
||||
extern int pthread_mutex_consistent_np (pthread_mutex_t *__mutex) __THROW;
|
||||
#endif
|
||||
|
||||
|
||||
/* Functions for handling mutex attributes. */
|
||||
|
||||
/* Initialize mutex attribute object ATTR with default attributes
|
||||
@ -726,6 +747,16 @@ extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
|
||||
__THROW;
|
||||
#endif
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* Get the robustness flag of the mutex attribute ATTR. */
|
||||
extern int pthread_mutexattr_getrobust_np (__const pthread_mutexattr_t *__attr,
|
||||
int *__robustness) __THROW;
|
||||
|
||||
/* Set the robustness flag of the mutex attribute ATTR. */
|
||||
extern int pthread_mutexattr_setrobust_np (pthread_mutexattr_t *__attr,
|
||||
int __robustness) __THROW;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined __USE_UNIX98 || defined __USE_XOPEN2K
|
||||
/* Functions for handling read-write locks. */
|
||||
|
@ -45,7 +45,7 @@ typedef union
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is not exposed on purpose. */
|
||||
typedef union
|
||||
typedef union __pthread_mutex_u
|
||||
{
|
||||
struct
|
||||
{
|
||||
@ -56,7 +56,11 @@ typedef union
|
||||
binary compatibility. */
|
||||
int __kind;
|
||||
unsigned int __nusers;
|
||||
int __spins;
|
||||
union
|
||||
{
|
||||
int __spins;
|
||||
union __pthread_mutex_u *__next;
|
||||
};
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||
long int __align;
|
||||
|
@ -59,7 +59,7 @@ typedef union
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is not exposed on purpose. */
|
||||
typedef union
|
||||
typedef union __pthread_mutex_u
|
||||
{
|
||||
struct
|
||||
{
|
||||
@ -72,10 +72,19 @@ typedef union
|
||||
/* KIND must stay at this position in the structure to maintain
|
||||
binary compatibility. */
|
||||
int __kind;
|
||||
#if __WORDSIZE != 64
|
||||
unsigned int __nusers;
|
||||
#endif
|
||||
#if __WORDSIZE == 64
|
||||
int __spins;
|
||||
union __pthread_mutex_u *__next;
|
||||
union __pthread_mutex_u *__prev;
|
||||
# define __PTHREAD_MUTEX_HAVE_PREV 1
|
||||
#else
|
||||
unsigned int __nusers;
|
||||
union
|
||||
{
|
||||
int __spins;
|
||||
union __pthread_mutex_u *__next;
|
||||
};
|
||||
#endif
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||
long int __align;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
@ -52,6 +52,8 @@ once_handler1 (void)
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("once_handler1: going to wait on cond");
|
||||
|
||||
pthread_cond_wait (&cond, &mut);
|
||||
|
||||
/* We should never get here. */
|
||||
@ -139,6 +141,9 @@ do_test (void)
|
||||
puts ("join didn't return PTHREAD_CANCELED");
|
||||
return 1;
|
||||
}
|
||||
puts ("joined successfully");
|
||||
|
||||
printf ("once = %d\n", *(int *) &once);
|
||||
|
||||
if (cl_called != 1)
|
||||
{
|
||||
|
245
nptl/tst-robust1.c
Normal file
245
nptl/tst-robust1.c
Normal file
@ -0,0 +1,245 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
|
||||
|
||||
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. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static pthread_mutex_t m;
|
||||
static pthread_barrier_t b;
|
||||
|
||||
|
||||
#ifndef LOCK
|
||||
# define LOCK(m) pthread_mutex_lock (m)
|
||||
#endif
|
||||
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
long int round = (long int) arg;
|
||||
|
||||
if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
|
||||
{
|
||||
printf ("%ld: setcancelstate failed\n", round);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int e = LOCK (&m);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("%ld: child: mutex_lock failed with error %d\n", round, e);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
printf ("%ld: child: 1st barrier_wait failed\n", round);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
printf ("%ld: child: 2nd barrier_wait failed\n", round);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_testcancel ();
|
||||
|
||||
printf ("%ld: testcancel returned\n", round);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef PREPARE_TMO
|
||||
PREPARE_TMO;
|
||||
#endif
|
||||
|
||||
pthread_mutexattr_t a;
|
||||
if (pthread_mutexattr_init (&a) != 0)
|
||||
{
|
||||
puts ("mutexattr_init failed");
|
||||
return 1;
|
||||
}
|
||||
if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0)
|
||||
{
|
||||
puts ("mutexattr_setrobust failed");
|
||||
return 1;
|
||||
}
|
||||
#ifndef NOT_CONSISTENT
|
||||
if (pthread_mutex_init (&m, &a) != 0)
|
||||
{
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("barrier_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (long int round = 1; round < 5; ++round)
|
||||
{
|
||||
#ifdef NOT_CONSISTENT
|
||||
if (pthread_mutex_init (&m, &a) != 0)
|
||||
{
|
||||
puts ("mutex_init failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, tf, (void *) round) != 0)
|
||||
{
|
||||
printf ("%ld: create failed\n", round);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
printf ("%ld: parent: 1st barrier_wait failed\n", round);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
printf ("%ld: cancel failed\n", round);
|
||||
return 1;
|
||||
}
|
||||
|
||||
e = pthread_barrier_wait (&b);
|
||||
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
printf ("%ld: parent: 2nd barrier_wait failed\n", round);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef AFTER_JOIN
|
||||
if (round & 1)
|
||||
#endif
|
||||
{
|
||||
void *res;
|
||||
if (pthread_join (th, &res) != 0)
|
||||
{
|
||||
printf ("%ld: join failed\n", round);
|
||||
return 1;
|
||||
}
|
||||
if (res != PTHREAD_CANCELED)
|
||||
{
|
||||
printf ("%ld: thread not canceled\n", round);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
e = LOCK (&m);
|
||||
if (e == 0)
|
||||
{
|
||||
printf ("%ld: parent: mutex_lock succeeded\n", round);
|
||||
return 1;
|
||||
}
|
||||
if (e != EOWNERDEAD)
|
||||
{
|
||||
printf ("%ld: parent: mutex_lock returned wrong code\n", round);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef AFTER_JOIN
|
||||
if ((round & 1) == 0)
|
||||
{
|
||||
void *res;
|
||||
if (pthread_join (th, &res) != 0)
|
||||
{
|
||||
printf ("%ld: join failed\n", round);
|
||||
return 1;
|
||||
}
|
||||
if (res != PTHREAD_CANCELED)
|
||||
{
|
||||
printf ("%ld: thread not canceled\n", round);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NOT_CONSISTENT
|
||||
e = pthread_mutex_consistent_np (&m);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("%ld: mutex_consistent failed with error %d\n", round, e);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
e = pthread_mutex_unlock (&m);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("%ld: mutex_unlocked failed\n", round);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef NOT_CONSISTENT
|
||||
e = LOCK (&m);
|
||||
if (e == 0)
|
||||
{
|
||||
printf ("%ld: locking inconsistent mutex succeeded\n", round);
|
||||
return 1;
|
||||
}
|
||||
if (e != ENOTRECOVERABLE)
|
||||
{
|
||||
printf ("%ld: locking inconsistent mutex failed with error %d\n",
|
||||
round, e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_destroy (&m) != 0)
|
||||
{
|
||||
puts ("mutex_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NOT_CONSISTENT
|
||||
if (pthread_mutex_destroy (&m) != 0)
|
||||
{
|
||||
puts ("mutex_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pthread_mutexattr_destroy (&a) != 0)
|
||||
{
|
||||
puts ("mutexattr_destroy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
3
nptl/tst-robust2.c
Normal file
3
nptl/tst-robust2.c
Normal file
@ -0,0 +1,3 @@
|
||||
#define AFTER_JOIN 1
|
||||
#define LOCK(m) pthread_mutex_trylock (m)
|
||||
#include "tst-robust1.c"
|
20
nptl/tst-robust3.c
Normal file
20
nptl/tst-robust3.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
static struct timespec tmo;
|
||||
|
||||
|
||||
#define PREPARE_TMO \
|
||||
do { \
|
||||
struct timeval tv; \
|
||||
gettimeofday (&tv, NULL); \
|
||||
\
|
||||
/* Define the timeout as one hour in the future. */ \
|
||||
tmo.tv_sec = tv.tv_sec + 3600; \
|
||||
tmo.tv_nsec = 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define LOCK(m) pthread_mutex_timedlock (m, &tmo)
|
||||
#include "tst-robust1.c"
|
2
nptl/tst-robust4.c
Normal file
2
nptl/tst-robust4.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define NOT_CONSISTENT 1
|
||||
#include "tst-robust1.c"
|
2
nptl/tst-robust5.c
Normal file
2
nptl/tst-robust5.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define NOT_CONSISTENT 1
|
||||
#include "tst-robust2.c"
|
2
nptl/tst-robust6.c
Normal file
2
nptl/tst-robust6.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define NOT_CONSISTENT 1
|
||||
#include "tst-robust3.c"
|
68
nptl/tst-typesizes.c
Normal file
68
nptl/tst-typesizes.c
Normal file
@ -0,0 +1,68 @@
|
||||
/* Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
|
||||
|
||||
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. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthreadP.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
#define TEST_TYPE(name) \
|
||||
printf ("%s: ", #name); \
|
||||
if (sizeof (name) != sizeof (((name *) 0)->__size)) \
|
||||
{ \
|
||||
printf ("expected %zu, is %zu\n", \
|
||||
sizeof (((name *) 0)->__size), sizeof (name)); \
|
||||
result = 1; \
|
||||
} \
|
||||
else \
|
||||
puts ("OK")
|
||||
|
||||
TEST_TYPE (pthread_mutex_t);
|
||||
TEST_TYPE (pthread_cond_t);
|
||||
TEST_TYPE (pthread_rwlock_t);
|
||||
|
||||
#define TEST_TYPE2(name, internal) \
|
||||
printf ("%s: ", #name); \
|
||||
if (sizeof (((name *) 0)->__size) < sizeof (internal)) \
|
||||
{ \
|
||||
printf ("expected %zu, is %zu\n", \
|
||||
sizeof (((name *) 0)->__size), sizeof (internal)); \
|
||||
result = 1; \
|
||||
} \
|
||||
else \
|
||||
puts ("OK")
|
||||
|
||||
TEST_TYPE2 (pthread_attr_t, struct pthread_attr);
|
||||
TEST_TYPE2 (pthread_mutexattr_t, struct pthread_mutexattr);
|
||||
TEST_TYPE2 (pthread_condattr_t, struct pthread_condattr);
|
||||
TEST_TYPE2 (pthread_rwlockattr_t, struct pthread_rwlockattr);
|
||||
TEST_TYPE2 (pthread_barrier_t, struct pthread_barrier);
|
||||
TEST_TYPE2 (pthread_barrierattr_t, struct pthread_barrierattr);
|
||||
TEST_TYPE2 (sem_t, struct sem);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
Loading…
Reference in New Issue
Block a user