Add runtime check if mutex will be elided in tst-mutex8 testcases.

An elided mutex don't fail destroy. Elision was disabled for the
test nptl/tst-mutex8 in nptl/Makefile. Thus we can run tests which
destroy a locked mutex.

As elision is only disabled for tst-mutex8, the variants
tst-mutex8-static, tst-mutexpi8 and tst-mutexpi8-static are still
failing if lock elision is enabled.

This patch adds a runtime check, if the checked type of mutex will
be elided. This check is using TUNABLE_GET_FULL to determine if
elision is enabled via the tunables framework.
The pthread_mutex_destroy tests are only run if we dont't assume an
elided mutex.

This way, we can run the whole glibc testsuite with or without enabled
lock elision.

ChangeLog:

	* nptl/Makefile (tst-mutex8-ENV): Delete.
	* nptl/tst-mutex8.c (check_type):
	Add runtime check if mutex will be elided.
This commit is contained in:
Stefan Liebler 2018-02-16 09:57:30 +01:00
parent db9881ecd7
commit 8724507385
3 changed files with 89 additions and 47 deletions

View File

@ -1,3 +1,9 @@
2018-02-16 Stefan Liebler <stli@linux.vnet.ibm.com>
* nptl/Makefile (tst-mutex8-ENV): Delete.
* nptl/tst-mutex8.c (check_type):
Add runtime check if mutex will be elided.
2018-02-15 Joseph Myers <joseph@codesourcery.com> 2018-02-15 Joseph Myers <joseph@codesourcery.com>
[BZ #20980] [BZ #20980]

View File

@ -726,10 +726,6 @@ endif
$(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so $(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so
# Disable elision for tst-mutex8 so it can verify error case for
# destroying a mutex.
tst-mutex8-ENV = GLIBC_TUNABLES=glibc.elision.enable=0
# The tests here better do not run in parallel # The tests here better do not run in parallel
ifneq ($(filter %tests,$(MAKECMDGOALS)),) ifneq ($(filter %tests,$(MAKECMDGOALS)),)
.NOTPARALLEL: .NOTPARALLEL:

View File

@ -22,7 +22,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <elf/dl-tunables.h>
static pthread_mutex_t *m; static pthread_mutex_t *m;
static pthread_barrier_t b; static pthread_barrier_t b;
@ -95,6 +96,30 @@ check_type (const char *mas, pthread_mutexattr_t *ma)
{ {
int e; int e;
/* Check if a mutex will be elided. Lock elision can only be activated via
the tunables framework. By default, lock elision is disabled. */
bool assume_elided_mutex = false;
#if HAVE_TUNABLES
int ma_type = PTHREAD_MUTEX_TIMED_NP;
if (ma != NULL)
{
e = pthread_mutexattr_gettype (ma, &ma_type);
if (e != 0)
{
printf ("pthread_mutexattr_gettype failed with %d (%m)\n", e);
return 1;
}
}
if (ma_type == PTHREAD_MUTEX_TIMED_NP)
{
/* This type of mutex can be elided if elision is enabled via the tunables
framework. Some tests below are failing if the mutex is elided.
Thus we only run those if we assume that the mutex won't be elided. */
if (TUNABLE_GET_FULL (glibc, elision, enable, int32_t, NULL) == 1)
assume_elided_mutex = true;
}
#endif
e = pthread_mutex_init (m, ma); e = pthread_mutex_init (m, ma);
if (e != 0) if (e != 0)
{ {
@ -127,8 +152,10 @@ check_type (const char *mas, pthread_mutexattr_t *ma)
return 1; return 1;
} }
/* Elided mutexes don't fail destroy, but this test is run with /* Elided mutexes don't fail destroy, thus only test this if we don't assume
elision disabled so we can test them. */ elision. */
if (assume_elided_mutex == false)
{
e = pthread_mutex_destroy (m); e = pthread_mutex_destroy (m);
if (e == 0) if (e == 0)
{ {
@ -137,10 +164,12 @@ check_type (const char *mas, pthread_mutexattr_t *ma)
} }
if (e != EBUSY) if (e != EBUSY)
{ {
printf ("mutex_destroy of self-locked mutex did not return EBUSY %s\n", printf ("\
mutex_destroy of self-locked mutex did not return EBUSY %s\n",
mas); mas);
return 1; return 1;
} }
}
if (pthread_mutex_unlock (m) != 0) if (pthread_mutex_unlock (m) != 0)
{ {
@ -155,10 +184,13 @@ check_type (const char *mas, pthread_mutexattr_t *ma)
} }
/* Elided mutexes don't fail destroy. */ /* Elided mutexes don't fail destroy. */
if (assume_elided_mutex == false)
{
e = pthread_mutex_destroy (m); e = pthread_mutex_destroy (m);
if (e == 0) if (e == 0)
{ {
printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n", mas); printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n",
mas);
return 1; return 1;
} }
if (e != EBUSY) if (e != EBUSY)
@ -168,6 +200,7 @@ mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
mas); mas);
return 1; return 1;
} }
}
if (pthread_mutex_unlock (m) != 0) if (pthread_mutex_unlock (m) != 0)
{ {
@ -203,10 +236,13 @@ mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
} }
/* Elided mutexes don't fail destroy. */ /* Elided mutexes don't fail destroy. */
if (assume_elided_mutex == false)
{
e = pthread_mutex_destroy (m); e = pthread_mutex_destroy (m);
if (e == 0) if (e == 0)
{ {
printf ("mutex_destroy of condvar-used mutex succeeded for %s\n", mas); printf ("mutex_destroy of condvar-used mutex succeeded for %s\n",
mas);
return 1; return 1;
} }
if (e != EBUSY) if (e != EBUSY)
@ -215,6 +251,7 @@ mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas); mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
return 1; return 1;
} }
}
done = true; done = true;
if (pthread_cond_signal (&c) != 0) if (pthread_cond_signal (&c) != 0)
@ -274,6 +311,8 @@ mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
} }
/* Elided mutexes don't fail destroy. */ /* Elided mutexes don't fail destroy. */
if (assume_elided_mutex == false)
{
e = pthread_mutex_destroy (m); e = pthread_mutex_destroy (m);
if (e == 0) if (e == 0)
{ {
@ -288,6 +327,7 @@ mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
mas); mas);
return 1; return 1;
} }
}
if (pthread_cancel (th) != 0) if (pthread_cancel (th) != 0)
{ {