mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
* allocatestack.c (allocate_stack): Initialize robust_list.
* init.c (__pthread_initialize_minimal_internal): Likewise. * descr.h (struct xid_command): Pretty printing. (struct pthread): Use __pthread_list_t or __pthread_slist_t for robust_list. Adjust macros. * pthread_create.c (start_thread): Adjust robust_list handling. * phtread_mutex_unlock.c: Don't allow unlocking from any thread but the owner for all robust mutex types. * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define __pthread_list_t and __pthread_slist_t. Use them in pthread_mutex_t. * sysdeps/pthread/pthread.h: Adjust mutex initializers.
This commit is contained in:
@ -1,5 +1,17 @@
|
|||||||
2006-02-12 Ulrich Drepper <drepper@redhat.com>
|
2006-02-12 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* allocatestack.c (allocate_stack): Initialize robust_list.
|
||||||
|
* init.c (__pthread_initialize_minimal_internal): Likewise.
|
||||||
|
* descr.h (struct xid_command): Pretty printing.
|
||||||
|
(struct pthread): Use __pthread_list_t or __pthread_slist_t for
|
||||||
|
robust_list. Adjust macros.
|
||||||
|
* pthread_create.c (start_thread): Adjust robust_list handling.
|
||||||
|
* phtread_mutex_unlock.c: Don't allow unlocking from any thread
|
||||||
|
but the owner for all robust mutex types.
|
||||||
|
* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define
|
||||||
|
__pthread_list_t and __pthread_slist_t. Use them in pthread_mutex_t.
|
||||||
|
* sysdeps/pthread/pthread.h: Adjust mutex initializers.
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/i386/not-cancel.h: Define openat_not_cancel,
|
* sysdeps/unix/sysv/linux/i386/not-cancel.h: Define openat_not_cancel,
|
||||||
openat_not_cancel_3, openat64_not_cancel, and openat64_not_cancel_3.
|
openat_not_cancel_3, openat64_not_cancel, and openat64_not_cancel_3.
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
/* Copyright (C) 2002, 2003, 2004, 2005
|
/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||||
Free Software Foundation, Inc.
|
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||||
|
|
||||||
@ -366,6 +365,12 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||||||
/* The process ID is also the same as that of the caller. */
|
/* The process ID is also the same as that of the caller. */
|
||||||
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||||||
|
|
||||||
|
/* List of robust mutexes. */
|
||||||
|
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||||
|
pd->robust_list.__prev = &pd->robust_list;
|
||||||
|
#endif
|
||||||
|
pd->robust_list.__next = &pd->robust_list;
|
||||||
|
|
||||||
/* Allocate the DTV for this thread. */
|
/* Allocate the DTV for this thread. */
|
||||||
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
||||||
{
|
{
|
||||||
@ -500,6 +505,12 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||||||
/* The process ID is also the same as that of the caller. */
|
/* The process ID is also the same as that of the caller. */
|
||||||
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||||||
|
|
||||||
|
/* List of robust mutexes. */
|
||||||
|
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||||
|
pd->robust_list.__prev = &pd->robust_list;
|
||||||
|
#endif
|
||||||
|
pd->robust_list.__next = &pd->robust_list;
|
||||||
|
|
||||||
/* Allocate the DTV for this thread. */
|
/* Allocate the DTV for this thread. */
|
||||||
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
||||||
{
|
{
|
||||||
|
43
nptl/descr.h
43
nptl/descr.h
@ -97,7 +97,7 @@ struct pthread_unwind_buf
|
|||||||
struct xid_command
|
struct xid_command
|
||||||
{
|
{
|
||||||
int syscall_no;
|
int syscall_no;
|
||||||
long id[3];
|
long int id[3];
|
||||||
volatile int cntr;
|
volatile int cntr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -135,46 +135,45 @@ struct pthread
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
/* List of robust mutexes the thread is holding. */
|
/* List of robust mutexes the thread is holding. */
|
||||||
struct __pthread_mutex_s *robust_list;
|
|
||||||
|
|
||||||
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||||
|
__pthread_list_t robust_list;
|
||||||
|
|
||||||
# define ENQUEUE_MUTEX(mutex) \
|
# define ENQUEUE_MUTEX(mutex) \
|
||||||
do { \
|
do { \
|
||||||
mutex->__data.__next = THREAD_GETMEM (THREAD_SELF, robust_list); \
|
__pthread_list_t *next = THREAD_GETMEM (THREAD_SELF, robust_list.__next); \
|
||||||
THREAD_SETMEM (THREAD_SELF, robust_list, &mutex->__data); \
|
next->__prev = &mutex->__data.__list; \
|
||||||
if (mutex->__data.__next != NULL) \
|
mutex->__data.__list.__next = next; \
|
||||||
mutex->__data.__next->__prev = &mutex->__data; \
|
mutex->__data.__list.__prev = &THREAD_SELF->robust_list; \
|
||||||
mutex->__data.__prev = NULL; \
|
THREAD_SETMEM (THREAD_SELF, robust_list.__next, &mutex->__data.__list); \
|
||||||
} while (0)
|
} while (0)
|
||||||
# define DEQUEUE_MUTEX(mutex) \
|
# define DEQUEUE_MUTEX(mutex) \
|
||||||
do { \
|
do { \
|
||||||
if (mutex->__data.__prev == NULL) \
|
mutex->__data.__list.__next->__prev = mutex->__data.__list.__prev; \
|
||||||
THREAD_SETMEM (THREAD_SELF, robust_list, mutex->__data.__next); \
|
mutex->__data.__list.__prev->__next = mutex->__data.__list.__next; \
|
||||||
else \
|
mutex->__data.__list.__prev = NULL; \
|
||||||
mutex->__data.__prev->__next = mutex->__data.__next; \
|
mutex->__data.__list.__next = NULL; \
|
||||||
if (mutex->__data.__next != NULL) \
|
|
||||||
mutex->__data.__next->__prev = mutex->__data.__prev; \
|
|
||||||
mutex->__data.__prev = NULL; \
|
|
||||||
mutex->__data.__next = NULL; \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
|
__pthread_slist_t robust_list;
|
||||||
|
|
||||||
# define ENQUEUE_MUTEX(mutex) \
|
# define ENQUEUE_MUTEX(mutex) \
|
||||||
do { \
|
do { \
|
||||||
mutex->__data.__next = THREAD_GETMEM (THREAD_SELF, robust_list); \
|
mutex->__data.__list.__next \
|
||||||
THREAD_SETMEM (THREAD_SELF, robust_list, &mutex->__data); \
|
= THREAD_GETMEM (THREAD_SELF, robust_list.__next); \
|
||||||
|
THREAD_SETMEM (THREAD_SELF, robust_list.__next, &mutex->__data.__list); \
|
||||||
} while (0)
|
} while (0)
|
||||||
# define DEQUEUE_MUTEX(mutex) \
|
# define DEQUEUE_MUTEX(mutex) \
|
||||||
do { \
|
do { \
|
||||||
struct __pthread_mutex_s *runp = THREAD_GETMEM (THREAD_SELF, robust_list);\
|
__pthread_slist_t *runp = THREAD_GETMEM (THREAD_SELF, robust_list.__next);\
|
||||||
if (runp == &mutex->__data) \
|
if (runp == &mutex->__data.__list) \
|
||||||
THREAD_SETMEM (THREAD_SELF, robust_list, runp->__next); \
|
THREAD_SETMEM (THREAD_SELF, robust_list, runp->__next); \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
while (runp->__next != &mutex->__data) \
|
while (runp->__next != &mutex->__data.__list) \
|
||||||
runp = runp->__next; \
|
runp = runp->__next; \
|
||||||
\
|
\
|
||||||
runp->__next = runp->__next->__next; \
|
runp->__next = runp->__next->__next; \
|
||||||
mutex->__data.__next = NULL; \
|
mutex->__data.__list.__next = NULL; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||||
|
|
||||||
@ -247,6 +247,10 @@ __pthread_initialize_minimal_internal (void)
|
|||||||
struct pthread *pd = THREAD_SELF;
|
struct pthread *pd = THREAD_SELF;
|
||||||
INTERNAL_SYSCALL_DECL (err);
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid);
|
pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid);
|
||||||
|
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||||
|
pd->robust_list.__prev = &pd->robust_list;
|
||||||
|
#endif
|
||||||
|
pd->robust_list.__next = &pd->robust_list;
|
||||||
THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]);
|
THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]);
|
||||||
THREAD_SETMEM (pd, user_stack, true);
|
THREAD_SETMEM (pd, user_stack, true);
|
||||||
if (LLL_LOCK_INITIALIZER != 0)
|
if (LLL_LOCK_INITIALIZER != 0)
|
||||||
|
@ -311,12 +311,17 @@ start_thread (void *arg)
|
|||||||
atomic_bit_set (&pd->cancelhandling, EXITING_BIT);
|
atomic_bit_set (&pd->cancelhandling, EXITING_BIT);
|
||||||
|
|
||||||
/* If this thread has any robust mutexes locked, handle them now. */
|
/* If this thread has any robust mutexes locked, handle them now. */
|
||||||
struct __pthread_mutex_s *robust = THREAD_GETMEM (pd, robust_list);
|
#if __WORDSIZE == 64
|
||||||
if (__builtin_expect (robust != NULL, 0))
|
__pthread_list_t *robust = pd->robust_list.__next;
|
||||||
|
#else
|
||||||
|
__pthread_slist_t *robust = pd->robust_list.__next;
|
||||||
|
#endif
|
||||||
|
if (__builtin_expect (robust != &pd->robust_list, 0))
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
struct __pthread_mutex_s *this = robust;
|
struct __pthread_mutex_s *this = (struct __pthread_mutex_s *)
|
||||||
|
((char *) robust - offsetof (struct __pthread_mutex_s, __list));
|
||||||
robust = robust->__next;
|
robust = robust->__next;
|
||||||
|
|
||||||
assert (lll_mutex_islocked (this->__lock));
|
assert (lll_mutex_islocked (this->__lock));
|
||||||
@ -324,17 +329,20 @@ start_thread (void *arg)
|
|||||||
--this->__nusers;
|
--this->__nusers;
|
||||||
assert (this->__owner != PTHREAD_MUTEX_NOTRECOVERABLE);
|
assert (this->__owner != PTHREAD_MUTEX_NOTRECOVERABLE);
|
||||||
this->__owner = PTHREAD_MUTEX_OWNERDEAD;
|
this->__owner = PTHREAD_MUTEX_OWNERDEAD;
|
||||||
this->__next = NULL;
|
this->__list.__next = NULL;
|
||||||
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||||
this->__prev = NULL;
|
this->__list.__prev = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
lll_mutex_unlock (this->__lock);
|
lll_mutex_unlock (this->__lock);
|
||||||
}
|
}
|
||||||
while (robust != NULL);
|
while (robust != &pd->robust_list);
|
||||||
|
|
||||||
/* Clean up so that the thread descriptor can be reused. */
|
/* Clean up so that the thread descriptor can be reused. */
|
||||||
THREAD_SETMEM (pd, robust_list, NULL);
|
pd->robust_list.__next = &pd->robust_list;
|
||||||
|
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||||
|
pd->robust_list.__prev = &pd->robust_list;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the thread is detached free the TCB. */
|
/* If the thread is detached free the TCB. */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
|
/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||||
|
|
||||||
@ -76,15 +76,12 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
|||||||
goto robust;
|
goto robust;
|
||||||
|
|
||||||
case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
|
case PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP:
|
||||||
/* Error checking mutex. */
|
case PTHREAD_MUTEX_ROBUST_PRIVATE_NP:
|
||||||
|
case PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP:
|
||||||
if (abs (mutex->__data.__owner) != THREAD_GETMEM (THREAD_SELF, tid)
|
if (abs (mutex->__data.__owner) != THREAD_GETMEM (THREAD_SELF, tid)
|
||||||
|| ! lll_mutex_islocked (mutex->__data.__lock))
|
|| ! lll_mutex_islocked (mutex->__data.__lock))
|
||||||
return EPERM;
|
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
|
/* If the previous owner died and the caller did not succeed in
|
||||||
making the state consistent, mark the mutex as unrecoverable
|
making the state consistent, mark the mutex as unrecoverable
|
||||||
and make all waiters. */
|
and make all waiters. */
|
||||||
|
@ -74,14 +74,14 @@ enum
|
|||||||
/* Mutex initializers. */
|
/* Mutex initializers. */
|
||||||
#if __WORDSIZE == 64
|
#if __WORDSIZE == 64
|
||||||
# define PTHREAD_MUTEX_INITIALIZER \
|
# define PTHREAD_MUTEX_INITIALIZER \
|
||||||
{ { 0, 0, 0, 0, 0, 0, 0, 0 } }
|
{ { 0, 0, 0, 0, 0, 0, { 0, 0 } } }
|
||||||
# ifdef __USE_GNU
|
# ifdef __USE_GNU
|
||||||
# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
|
# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
|
||||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, 0 } }
|
{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0, 0 } } }
|
||||||
# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
|
# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
|
||||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, 0, 0 } }
|
{ { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0, 0 } } }
|
||||||
# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
|
# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
|
||||||
{ { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, 0, 0 } }
|
{ { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0, 0 } } }
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# define PTHREAD_MUTEX_INITIALIZER \
|
# define PTHREAD_MUTEX_INITIALIZER \
|
||||||
|
@ -43,6 +43,12 @@ typedef union
|
|||||||
} pthread_attr_t;
|
} pthread_attr_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct __pthread_internal_slist
|
||||||
|
{
|
||||||
|
struct __pthread_internal_slist *__next;
|
||||||
|
} __pthread_slist_t;
|
||||||
|
|
||||||
|
|
||||||
/* Data structures for mutex handling. The structure of the attribute
|
/* Data structures for mutex handling. The structure of the attribute
|
||||||
type is not exposed on purpose. */
|
type is not exposed on purpose. */
|
||||||
typedef union
|
typedef union
|
||||||
@ -59,7 +65,7 @@ typedef union
|
|||||||
__extension__ union
|
__extension__ union
|
||||||
{
|
{
|
||||||
int __spins;
|
int __spins;
|
||||||
struct __pthread_mutex_s *__next;
|
__pthread_slist_t __list;
|
||||||
};
|
};
|
||||||
} __data;
|
} __data;
|
||||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||||
|
@ -57,6 +57,20 @@ typedef union
|
|||||||
} pthread_attr_t;
|
} pthread_attr_t;
|
||||||
|
|
||||||
|
|
||||||
|
#if __WORDSIZE == 64
|
||||||
|
typedef struct __pthread_internal_list
|
||||||
|
{
|
||||||
|
struct __pthread_internal_list *__prev;
|
||||||
|
struct __pthread_internal_list *__next;
|
||||||
|
} __pthread_list_t;
|
||||||
|
#else
|
||||||
|
typedef struct __pthread_internal_slist
|
||||||
|
{
|
||||||
|
struct __pthread_internal_slist *__next;
|
||||||
|
} __pthread_slist_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Data structures for mutex handling. The structure of the attribute
|
/* Data structures for mutex handling. The structure of the attribute
|
||||||
type is not exposed on purpose. */
|
type is not exposed on purpose. */
|
||||||
typedef union
|
typedef union
|
||||||
@ -74,15 +88,14 @@ typedef union
|
|||||||
int __kind;
|
int __kind;
|
||||||
#if __WORDSIZE == 64
|
#if __WORDSIZE == 64
|
||||||
int __spins;
|
int __spins;
|
||||||
struct __pthread_mutex_s *__next;
|
__pthread_list_t __list;
|
||||||
struct __pthread_mutex_s *__prev;
|
|
||||||
# define __PTHREAD_MUTEX_HAVE_PREV 1
|
# define __PTHREAD_MUTEX_HAVE_PREV 1
|
||||||
#else
|
#else
|
||||||
unsigned int __nusers;
|
unsigned int __nusers;
|
||||||
__extension__ union
|
__extension__ union
|
||||||
{
|
{
|
||||||
int __spins;
|
int __spins;
|
||||||
struct __pthread_mutex_s *__next;
|
__pthread_slist_t __list;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
} __data;
|
} __data;
|
||||||
|
Reference in New Issue
Block a user