1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

NPTL: Conditionalize direct futex syscall uses.

This commit is contained in:
Roland McGrath
2014-10-17 14:30:16 -07:00
parent 327ae25707
commit 184ee94010
7 changed files with 62 additions and 22 deletions

View File

@ -1,5 +1,17 @@
2014-10-17 Roland McGrath <roland@hack.frob.com> 2014-10-17 Roland McGrath <roland@hack.frob.com>
* nptl/nptl-init.c (__pthread_initialize_minimal_internal):
Conditionalize FUTEX_PRIVATE_FLAG and FUTEX_CLOCK_REALTIME probes
on [__NR_futex].
* nptl/pthread_mutex_init.c (prio_inherit_missing): New function,
broken out of ...
(__pthread_mutex_init): ... here. Call it.
* nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full):
Conditionalize PI cases on [__NR_futex].
* nptl/pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise.
* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise.
* nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise.
* nptl/nptl-init.c (sighandler_setxid, __xidcmd): Make definitions * nptl/nptl-init.c (sighandler_setxid, __xidcmd): Make definitions
conditional on [SIGSETXID]. conditional on [SIGSETXID].
(sigcancel_handler): Make definition conditional on [SIGCANCEL]. (sigcancel_handler): Make definition conditional on [SIGCANCEL].

View File

@ -329,7 +329,8 @@ __pthread_initialize_minimal_internal (void)
#endif #endif
set_robust_list_not_avail (); set_robust_list_not_avail ();
#ifndef __ASSUME_PRIVATE_FUTEX #ifdef __NR_futex
# ifndef __ASSUME_PRIVATE_FUTEX
/* Private futexes are always used (at least internally) so that /* Private futexes are always used (at least internally) so that
doing the test once this early is beneficial. */ doing the test once this early is beneficial. */
{ {
@ -345,8 +346,8 @@ __pthread_initialize_minimal_internal (void)
know the former are not supported. This also means we know the know the former are not supported. This also means we know the
kernel will return ENOSYS for unknown operations. */ kernel will return ENOSYS for unknown operations. */
if (THREAD_GETMEM (pd, header.private_futex) != 0) if (THREAD_GETMEM (pd, header.private_futex) != 0)
#endif # endif
#ifndef __ASSUME_FUTEX_CLOCK_REALTIME # ifndef __ASSUME_FUTEX_CLOCK_REALTIME
{ {
int word = 0; int word = 0;
/* NB: the syscall actually takes six parameters. The last is the /* NB: the syscall actually takes six parameters. The last is the
@ -361,6 +362,7 @@ __pthread_initialize_minimal_internal (void)
if (INTERNAL_SYSCALL_ERRNO (word, err) != ENOSYS) if (INTERNAL_SYSCALL_ERRNO (word, err) != ENOSYS)
__set_futex_clock_realtime (); __set_futex_clock_realtime ();
} }
# endif
#endif #endif
/* Set initial thread's stack block from 0 up to __libc_stack_end. /* Set initial thread's stack block from 0 up to __libc_stack_end.

View File

@ -18,6 +18,7 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include <kernel-features.h> #include <kernel-features.h>
#include "pthreadP.h" #include "pthreadP.h"
@ -31,10 +32,26 @@ static const struct pthread_mutexattr default_mutexattr =
}; };
#ifndef __ASSUME_FUTEX_LOCK_PI static bool
static int tpi_supported; prio_inherit_missing (void)
{
#ifdef __NR_futex
# ifndef __ASSUME_FUTEX_LOCK_PI
static int tpi_supported;
if (__glibc_unlikely (tpi_supported == 0))
{
int lock = 0;
INTERNAL_SYSCALL_DECL (err);
int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI, 0, 0);
assert (INTERNAL_SYSCALL_ERROR_P (ret, err));
tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1;
}
return __glibc_unlikely (tpi_supported < 0);
# endif
return false;
#endif #endif
return true;
}
int int
__pthread_mutex_init (mutex, mutexattr) __pthread_mutex_init (mutex, mutexattr)
@ -58,19 +75,8 @@ __pthread_mutex_init (mutex, mutexattr)
break; break;
case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
#ifndef __ASSUME_FUTEX_LOCK_PI if (__glibc_unlikely (prio_inherit_missing ()))
if (__glibc_unlikely (tpi_supported == 0))
{
int lock = 0;
INTERNAL_SYSCALL_DECL (err);
int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI,
0, 0);
assert (INTERNAL_SYSCALL_ERROR_P (ret, err));
tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1;
}
if (__glibc_unlikely (tpi_supported < 0))
return ENOTSUP; return ENOTSUP;
#endif
break; break;
default: default:

View File

@ -276,6 +276,10 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
break; break;
/* The PI support requires the Linux futex system call. If that's not
available, pthread_mutex_init should never have allowed the type to
be set. So it will get the default case for an invalid type. */
#ifdef __NR_futex
case PTHREAD_MUTEX_PI_RECURSIVE_NP: case PTHREAD_MUTEX_PI_RECURSIVE_NP:
case PTHREAD_MUTEX_PI_ERRORCHECK_NP: case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
case PTHREAD_MUTEX_PI_NORMAL_NP: case PTHREAD_MUTEX_PI_NORMAL_NP:
@ -321,9 +325,9 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
} }
int newval = id; int newval = id;
#ifdef NO_INCR # ifdef NO_INCR
newval |= FUTEX_WAITERS; newval |= FUTEX_WAITERS;
#endif # endif
oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
newval, 0); newval, 0);
@ -377,9 +381,9 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
incremented which is not correct because the old owner incremented which is not correct because the old owner
has to be discounted. If we are not supposed to has to be discounted. If we are not supposed to
increment __nusers we actually have to decrement it here. */ increment __nusers we actually have to decrement it here. */
#ifdef NO_INCR # ifdef NO_INCR
--mutex->__data.__nusers; --mutex->__data.__nusers;
#endif # endif
return EOWNERDEAD; return EOWNERDEAD;
} }
@ -409,6 +413,7 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
} }
} }
break; break;
#endif /* __NR_futex. */
case PTHREAD_MUTEX_PP_RECURSIVE_NP: case PTHREAD_MUTEX_PP_RECURSIVE_NP:
case PTHREAD_MUTEX_PP_ERRORCHECK_NP: case PTHREAD_MUTEX_PP_ERRORCHECK_NP:

View File

@ -230,6 +230,10 @@ pthread_mutex_timedlock (mutex, abstime)
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
break; break;
/* The PI support requires the Linux futex system call. If that's not
available, pthread_mutex_init should never have allowed the type to
be set. So it will get the default case for an invalid type. */
#ifdef __NR_futex
case PTHREAD_MUTEX_PI_RECURSIVE_NP: case PTHREAD_MUTEX_PI_RECURSIVE_NP:
case PTHREAD_MUTEX_PI_ERRORCHECK_NP: case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
case PTHREAD_MUTEX_PI_NORMAL_NP: case PTHREAD_MUTEX_PI_NORMAL_NP:
@ -382,6 +386,7 @@ pthread_mutex_timedlock (mutex, abstime)
} }
} }
break; break;
#endif /* __NR_futex. */
case PTHREAD_MUTEX_PP_RECURSIVE_NP: case PTHREAD_MUTEX_PP_RECURSIVE_NP:
case PTHREAD_MUTEX_PP_ERRORCHECK_NP: case PTHREAD_MUTEX_PP_ERRORCHECK_NP:

View File

@ -191,6 +191,10 @@ __pthread_mutex_trylock (mutex)
return 0; return 0;
/* The PI support requires the Linux futex system call. If that's not
available, pthread_mutex_init should never have allowed the type to
be set. So it will get the default case for an invalid type. */
#ifdef __NR_futex
case PTHREAD_MUTEX_PI_RECURSIVE_NP: case PTHREAD_MUTEX_PI_RECURSIVE_NP:
case PTHREAD_MUTEX_PI_ERRORCHECK_NP: case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
case PTHREAD_MUTEX_PI_NORMAL_NP: case PTHREAD_MUTEX_PI_NORMAL_NP:
@ -319,6 +323,7 @@ __pthread_mutex_trylock (mutex)
return 0; return 0;
} }
#endif /* __NR_futex. */
case PTHREAD_MUTEX_PP_RECURSIVE_NP: case PTHREAD_MUTEX_PP_RECURSIVE_NP:
case PTHREAD_MUTEX_PP_ERRORCHECK_NP: case PTHREAD_MUTEX_PP_ERRORCHECK_NP:

View File

@ -158,6 +158,10 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
break; break;
/* The PI support requires the Linux futex system call. If that's not
available, pthread_mutex_init should never have allowed the type to
be set. So it will get the default case for an invalid type. */
#ifdef __NR_futex
case PTHREAD_MUTEX_PI_RECURSIVE_NP: case PTHREAD_MUTEX_PI_RECURSIVE_NP:
/* Recursive mutex. */ /* Recursive mutex. */
if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
@ -245,6 +249,7 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
break; break;
#endif /* __NR_futex. */
case PTHREAD_MUTEX_PP_RECURSIVE_NP: case PTHREAD_MUTEX_PP_RECURSIVE_NP:
/* Recursive mutex. */ /* Recursive mutex. */