1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-01 10:06:57 +03:00

htl: Add clock variants

* htl/pt-join.c (__pthread_join): Move implementation to...
(__pthread_join_common): ... new function. Add try, timed and clock support.
(__pthread_join): Reimplement on top of __pthread_join_common.
(__pthread_tryjoin_np, __pthread_timedjoin_np, __pthread_clockjoin_np):
Implement on top of __pthread_join_common.
(pthread_tryjoin_np, pthread_timedjoin_np, pthread_clockjoin_np): New
aliases.

* hurd/hurdlock.c (__lll_abstimed_wait, __lll_abstimed_xwait,
__lll_abstimed_lock): Check for supported clock.

* sysdeps/htl/pt-cond-timedwait.c (__pthread_cond_timedwait_internal):
Add clockid parameter and support it.
(__pthread_cond_timedwait): Pass -1 as clockid.
(__pthread_cond_clockwait): New function.
(pthread_cond_clockwait): New alias.
* sysdeps/htl/pt-cond-wait.c (__pthread_cond_timedwait_internal): Update
prototype.
(__pthread_cond_wait): Pass -1 as clockid.

* sysdeps/htl/pt-rwlock-timedrdlock.c
(__pthread_rwlock_timedrdlock_internal): Add clockid parameter, and
support id.
(__pthread_rwlock_clockrdlock): New function.
(pthread_rwlock_clockrdlock): New alias.
* sysdeps/htl/pt-rwlock-rdlock.c (__pthread_rwlock_timedrdlock_internal): Update
prototype.
(__pthread_rwlock_rdlock): Pass -1 as clockid.

* sysdeps/htl/pt-rwlock-timedwrlock.c
(__pthread_rwlock_timedwrlock_internal): Add clockid parameter, and
support id.
(__pthread_rwlock_clockwrlock): New function.
(pthread_rwlock_clockwrlock): New alias.
* sysdeps/htl/pt-rwlock-wrlock.c (__pthread_rwlock_timedwrlock_internal): Update
prototype.
(__pthread_rwlock_wrlock): Pass -1 as clockid.

* sysdeps/mach/hurd/htl/pt-mutex-timedlock.c (__pthread_mutex_timedlock): Move implementation to
(__pthread_mutex_clocklock): New function with additional clockid
parameter and support it.
(pthread_mutex_clocklock): New alias.
(__pthread_mutex_timedlock): Reimplement on top of __pthread_mutex_clocklock.

* sysdeps/htl/pthread.h (pthread_tryjoin_np, pthread_timedjoin_np,
pthread_clockjoin_np, pthread_mutex_clocklock, pthread_cond_clockwait,
pthread_rwlock_clockrdlock, pthread_rwlock_clockwrlock): New prototypes.
* sysdeps/htl/pthreadP.h (__pthread_cond_clockwait): New prototype.

* htl/Versions (GLIBC_2.32): Add pthread_cond_clockwait,
pthread_mutex_clocklock, pthread_rwlock_clockrdlock, pthread_rwlock_clockwrlock,
pthread_tryjoin_np, pthread_timedjoin_np, pthread_clockjoin_np.
* sysdeps/mach/hurd/i386/libpthread.abilist (pthread_clockjoin_np,
pthread_cond_clockwait, pthread_mutex_clocklock, pthread_rwlock_clockrdlock,
pthread_rwlock_clockwrlock, pthread_timedjoin_np, pthread_tryjoin_np):
New functions.

* nptl/tst-abstime.c, nptl/tst-join10.c, nptl/tst-join11.c, nptl/tst-join12.c,
nptl/tst-join13.c, nptl/tst-join14.c, nptl/tst-join2.c, nptl/tst-join3.c,
nptl/tst-join8.c, nptl/tst-join9.c, nptl/tst-mutex-errorcheck.c,
nptl/tst-pthread-mutexattr.c, nptl/tst-mutex11.c, nptl/tst-mutex5.c,
nptl/tst-mutex7.c, nptl/tst-mutex7robus.c, nptl/tst-mutex9.c,
nptl/tst-rwlock12.c, nptl/tst-rwlock14.c: Move to sysdeps/pthread.
* sysdeps/pthread/tst-mutex8.c: Move back to nptl.
* nptl/Makefile (tests): Move tst-mutex5, tst-mutex7, tst-mutex7robust,
tst-mutex9, tst-mutex11, tst-rwlock12, tst-rwlock14, tst-join2, tst-join3,
tst-join8, tst-join9 tst-join10, tst-join11, tst-join12, tst-join13, tst-join14,
tst-abstime, tst-mutex-errorcheck, tst-pthread-mutexattr to ...
* sysdeps/pthread/Makefile (tests): ... here.
This commit is contained in:
Samuel Thibault
2020-05-26 00:09:11 +00:00
parent 02802fafcf
commit 28cada0418
35 changed files with 236 additions and 40 deletions

View File

@ -51,17 +51,23 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
tst-cond23 tst-cond24 tst-cond25 \
tst-cond-except \
tst-join1 tst-join4 tst-join5 tst-join6 tst-join7 \
tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 tst-join7 \
tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \
tst-join14 \
tst-key1 tst-key2 tst-key3 tst-key4 \
tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex6 tst-mutex10 \
tst-mutex-errorcheck tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 \
tst-mutex5 tst-mutex6 tst-mutex7 tst-mutex7robust tst-mutex9 \
tst-mutex10 tst-mutex11 tst-pthread-mutexattr \
tst-once1 tst-once2 tst-once3 tst-once4 \
tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
tst-robust6 tst-robust7 tst-robust9 tst-robust10 \
tst-rwlock1 tst-rwlock4 tst-rwlock5 tst-rwlock13 tst-rwlock16 \
tst-rwlock1 tst-rwlock4 tst-rwlock5 tst-rwlock12 \
tst-rwlock13 tst-rwlock14 tst-rwlock16 \
tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem6 tst-sem7 \
tst-sem8 tst-sem9 tst-sem10 tst-sem14 tst-sem15 tst-sem16 \
tst-spin1 tst-spin2 tst-spin3 tst-spin4
tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
tst-abstime
tests-internal += tst-robust8

View File

@ -0,0 +1,73 @@
/* Copyright (C) 2010-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Schwab <schwab@redhat.com>, 2010.
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, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <support/check.h>
#include <support/xthread.h>
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
static pthread_rwlock_t rw1 = PTHREAD_RWLOCK_INITIALIZER;
static pthread_rwlock_t rw2 = PTHREAD_RWLOCK_INITIALIZER;
static sem_t sem;
static void *
th (void *arg)
{
struct timespec t = { -2, 0 };
TEST_COMPARE (pthread_mutex_timedlock (&m1, &t), ETIMEDOUT);
TEST_COMPARE (pthread_mutex_clocklock (&m1, CLOCK_REALTIME, &t), ETIMEDOUT);
TEST_COMPARE (pthread_mutex_clocklock (&m1, CLOCK_MONOTONIC, &t), ETIMEDOUT);
TEST_COMPARE (pthread_rwlock_timedrdlock (&rw1, &t), ETIMEDOUT);
TEST_COMPARE (pthread_rwlock_timedwrlock (&rw2, &t), ETIMEDOUT);
TEST_COMPARE (pthread_rwlock_clockrdlock (&rw1, CLOCK_REALTIME, &t),
ETIMEDOUT);
TEST_COMPARE (pthread_rwlock_clockwrlock (&rw2, CLOCK_REALTIME, &t),
ETIMEDOUT);
TEST_COMPARE (pthread_rwlock_clockrdlock (&rw1, CLOCK_MONOTONIC, &t),
ETIMEDOUT);
TEST_COMPARE (pthread_rwlock_clockwrlock (&rw2, CLOCK_MONOTONIC, &t),
ETIMEDOUT);
return NULL;
}
static int
do_test (void)
{
struct timespec t = { -2, 0 };
sem_init (&sem, 0, 0);
TEST_COMPARE (sem_timedwait (&sem, &t), -1);
TEST_COMPARE (errno, ETIMEDOUT);
xpthread_mutex_lock (&m1);
xpthread_rwlock_wrlock (&rw1);
xpthread_rwlock_rdlock (&rw2);
xpthread_mutex_lock (&m2);
pthread_t pth = xpthread_create (0, th, 0);
TEST_COMPARE (pthread_cond_timedwait (&c, &m2, &t), ETIMEDOUT);
xpthread_join (pth);
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,20 @@
/* Check if pthread_clockjoin_np is a cancellation entrypoint.
Copyright (C) 2019-2020 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; if not, see
<http://www.gnu.org/licenses/>. */
#define USE_PTHREAD_CLOCKJOIN_NP_REALTIME 1
#include <sysdeps/pthread/tst-join5.c>

View File

@ -0,0 +1,21 @@
/* Check if pthread_clockjoin_np is a cancellation entrypoint.
Copyright (C) 2019-2020 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; if not, see
<http://www.gnu.org/licenses/>. */
#define USE_PTHREAD_CLOCKJOIN_NP_REALTIME 1
#define WAIT_IN_CHILD 1
#include <sysdeps/pthread/tst-join5.c>

View File

@ -0,0 +1,20 @@
/* Check if pthread_clockjoin_np is a cancellation entrypoint.
Copyright (C) 2019-2020 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; if not, see
<http://www.gnu.org/licenses/>. */
#define USE_PTHREAD_CLOCKJOIN_NP_MONOTONIC 1
#include <sysdeps/pthread/tst-join5.c>

View File

@ -0,0 +1,21 @@
/* Check if pthread_clockjoin_np is a cancellation entrypoint.
Copyright (C) 2019-2020 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; if not, see
<http://www.gnu.org/licenses/>. */
#define USE_PTHREAD_CLOCKJOIN_NP_MONOTONIC 1
#define WAIT_IN_CHILD 1
#include <sysdeps/pthread/tst-join5.c>

View File

@ -0,0 +1,74 @@
/* pthread_timedjoin_np, pthread_clockjoin_np NULL timeout test.
Copyright (C) 2019-2020 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; if not, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <support/check.h>
#include <support/timespec.h>
#include <support/xthread.h>
#include <support/xtime.h>
#define CLOCK_USE_TIMEDJOIN (-1)
static void *
tf (void *arg)
{
struct timespec ts = make_timespec(0, 100000);
nanosleep(&ts, NULL);
return (void *) 42l;
}
/* Check that pthread_timedjoin_np and pthread_clockjoin_np wait "forever" if
* passed a timeout parameter of NULL. We can't actually wait forever, but we
* can be sure that we did at least wait for some time by checking the exit
* status of the thread. */
static int
do_test_clock (clockid_t clockid)
{
pthread_t th = xpthread_create (NULL, tf, NULL);
void *status;
int val = (clockid == CLOCK_USE_TIMEDJOIN)
? pthread_timedjoin_np (th, &status, NULL)
: pthread_clockjoin_np (th, &status, clockid, NULL);
TEST_COMPARE (val, 0);
if (status != (void *) 42l)
FAIL_EXIT1 ("return value %p, expected %p\n", status, (void *) 42l);
return 0;
}
static int
do_test (void)
{
do_test_clock (CLOCK_USE_TIMEDJOIN);
do_test_clock (CLOCK_REALTIME);
do_test_clock (CLOCK_MONOTONIC);
return 0;
}
#include <support/test-driver.c>

103
sysdeps/pthread/tst-join2.c Normal file
View File

@ -0,0 +1,103 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static void *
tf (void *arg)
{
if (pthread_mutex_lock (&lock) != 0)
{
puts ("child: mutex_lock failed");
return NULL;
}
return (void *) 42l;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_mutex_lock (&lock) != 0)
{
puts ("mutex_lock failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("mutex_create failed");
exit (1);
}
void *status;
int val = pthread_tryjoin_np (th, &status);
if (val == 0)
{
puts ("1st tryjoin succeeded");
exit (1);
}
else if (val != EBUSY)
{
puts ("1st tryjoin didn't return EBUSY");
exit (1);
}
if (pthread_mutex_unlock (&lock) != 0)
{
puts ("mutex_unlock failed");
exit (1);
}
while ((val = pthread_tryjoin_np (th, &status)) != 0)
{
if (val != EBUSY)
{
printf ("tryjoin returned %s (%d), expected only 0 or EBUSY\n",
strerror (val), val);
exit (1);
}
/* Delay minimally. */
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
nanosleep (&ts, NULL);
}
if (status != (void *) 42l)
{
printf ("return value %p, expected %p\n", status, (void *) 42l);
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,99 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <support/check.h>
#include <support/timespec.h>
#include <support/xthread.h>
#include <support/xtime.h>
#define CLOCK_USE_TIMEDJOIN (-1)
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static void *
tf (void *arg)
{
xpthread_mutex_lock (&lock);
xpthread_mutex_unlock (&lock);
return (void *) 42l;
}
static int
do_test_clock (clockid_t clockid)
{
const clockid_t clockid_for_get =
(clockid == CLOCK_USE_TIMEDJOIN) ? CLOCK_REALTIME : clockid;
xpthread_mutex_lock (&lock);
pthread_t th = xpthread_create (NULL, tf, NULL);
void *status;
struct timespec timeout = timespec_add (xclock_now (clockid_for_get),
make_timespec (0, 200000000));
int val;
if (clockid == CLOCK_USE_TIMEDJOIN)
val = pthread_timedjoin_np (th, &status, &timeout);
else
val = pthread_clockjoin_np (th, &status, clockid, &timeout);
TEST_COMPARE (val, ETIMEDOUT);
xpthread_mutex_unlock (&lock);
while (1)
{
timeout = timespec_add (xclock_now (clockid_for_get),
make_timespec (0, 200000000));
if (clockid == CLOCK_USE_TIMEDJOIN)
val = pthread_timedjoin_np (th, &status, &timeout);
else
val = pthread_clockjoin_np (th, &status, clockid, &timeout);
if (val == 0)
break;
TEST_COMPARE (val, ETIMEDOUT);
}
if (status != (void *) 42l)
FAIL_EXIT1 ("return value %p, expected %p\n", status, (void *) 42l);
return 0;
}
static int
do_test (void)
{
do_test_clock (CLOCK_USE_TIMEDJOIN);
do_test_clock (CLOCK_REALTIME);
do_test_clock (CLOCK_MONOTONIC);
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,20 @@
/* Check if pthread_timedjoin_np is a cancellation entrypoint.
Copyright (C) 2019-2020 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; if not, see
<https://www.gnu.org/licenses/>. */
#define USE_PTHREAD_TIMEDJOIN_NP 1
#include <sysdeps/pthread/tst-join5.c>

View File

@ -0,0 +1,21 @@
/* Check if pthread_timedjoin_np is a cancellation entrypoint.
Copyright (C) 2019-2020 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; if not, see
<https://www.gnu.org/licenses/>. */
#define USE_PTHREAD_TIMEDJOIN_NP 1
#define WAIT_IN_CHILD 1
#include <sysdeps/pthread/tst-join5.c>

View File

@ -0,0 +1,52 @@
/* Check that error checking mutexes are not subject to lock elision.
Copyright (C) 2016-2020 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; if not, see
<https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#include <support/check.h>
static int
do_test (void)
{
struct timespec tms = { 0 };
pthread_mutex_t mutex;
pthread_mutexattr_t mutexattr;
int ret = 0;
TEST_COMPARE (pthread_mutexattr_init (&mutexattr), 0);
TEST_COMPARE (pthread_mutexattr_settype (&mutexattr,
PTHREAD_MUTEX_ERRORCHECK), 0);
TEST_COMPARE (pthread_mutex_init (&mutex, &mutexattr), 0);
TEST_COMPARE (pthread_mutexattr_destroy (&mutexattr), 0);
/* The call to pthread_mutex_timedlock erroneously enabled lock elision
on the mutex, which then triggered an assertion failure in
pthread_mutex_unlock. It would also defeat the error checking nature
of the mutex. */
TEST_COMPARE (pthread_mutex_timedlock (&mutex, &tms), 0);
TEST_COMPARE (pthread_mutex_timedlock (&mutex, &tms), EDEADLK);
TEST_COMPARE (pthread_mutex_unlock (&mutex), 0);
return ret;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,69 @@
/* Test unsupported/bad clocks passed to pthread_mutex_clocklock.
Copyright (C) 2019-2020 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; if not, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <support/check.h>
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static void test_bad_clockid (clockid_t clockid)
{
const struct timespec ts = {0,0};
TEST_COMPARE (pthread_mutex_clocklock (&mut, clockid, &ts), EINVAL);
}
#define NOT_A_VALID_CLOCK 123456
static int
do_test (void)
{
/* These clocks are meaningless to pthread_mutex_clocklock. */
#if defined(CLOCK_PROCESS_CPUTIME_ID)
test_bad_clockid (CLOCK_PROCESS_CPUTIME_ID);
#endif
#if defined(CLOCK_THREAD_CPUTIME_ID)
test_bad_clockid (CLOCK_PROCESS_CPUTIME_ID);
#endif
/* These clocks might be meaningful, but are currently unsupported by
pthread_mutex_clocklock. */
#if defined(CLOCK_REALTIME_COARSE)
test_bad_clockid (CLOCK_REALTIME_COARSE);
#endif
#if defined(CLOCK_MONOTONIC_RAW)
test_bad_clockid (CLOCK_MONOTONIC_RAW);
#endif
#if defined(CLOCK_MONOTONIC_COARSE)
test_bad_clockid (CLOCK_MONOTONIC_COARSE);
#endif
#if defined(CLOCK_BOOTTIME)
test_bad_clockid (CLOCK_BOOTTIME);
#endif
/* This is a completely invalid clock. */
test_bad_clockid (NOT_A_VALID_CLOCK);
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,119 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <stdint.h>
#include <config.h>
#include <support/check.h>
#include <support/timespec.h>
#ifndef TYPE
# define TYPE PTHREAD_MUTEX_NORMAL
#endif
/* A bogus clock value that tells run_test to use
pthread_mutex_timedlock rather than pthread_mutex_clocklock. */
#define CLOCK_USE_TIMEDLOCK (-1)
static int
do_test_clock (clockid_t clockid, const char *fnname)
{
pthread_mutex_t m;
pthread_mutexattr_t a;
const clockid_t clockid_for_get =
(clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
TEST_COMPARE (pthread_mutexattr_init (&a), 0);
TEST_COMPARE (pthread_mutexattr_settype (&a, TYPE), 0);
#ifdef ENABLE_PI
TEST_COMPARE (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT), 0);
#endif
int err = pthread_mutex_init (&m, &a);
if (err != 0)
{
#ifdef ENABLE_PI
if (err == ENOTSUP)
FAIL_UNSUPPORTED ("PI mutexes unsupported");
#endif
FAIL_EXIT1 ("mutex_init failed");
}
TEST_COMPARE (pthread_mutexattr_destroy (&a), 0);
TEST_COMPARE (pthread_mutex_lock (&m), 0);
if (pthread_mutex_trylock (&m) == 0)
FAIL_EXIT1 ("mutex_trylock succeeded");
/* Wait 2 seconds. */
struct timespec ts_timeout = timespec_add (xclock_now (clockid_for_get),
make_timespec (2, 0));
if (clockid == CLOCK_USE_TIMEDLOCK)
TEST_COMPARE (pthread_mutex_timedlock (&m, &ts_timeout), ETIMEDOUT);
else
TEST_COMPARE (pthread_mutex_clocklock (&m, clockid, &ts_timeout),
ETIMEDOUT);
TEST_TIMESPEC_BEFORE_NOW (ts_timeout, clockid_for_get);
/* The following makes the ts value invalid. */
ts_timeout.tv_nsec += 1000000000;
if (clockid == CLOCK_USE_TIMEDLOCK)
TEST_COMPARE (pthread_mutex_timedlock (&m, &ts_timeout), EINVAL);
else
TEST_COMPARE (pthread_mutex_clocklock (&m, clockid, &ts_timeout), EINVAL);
TEST_COMPARE (pthread_mutex_unlock (&m), 0);
const struct timespec ts_start = xclock_now (CLOCK_REALTIME);
/* Wait 2 seconds. */
ts_timeout = timespec_add (ts_start, make_timespec (2, 0));
if (clockid == CLOCK_USE_TIMEDLOCK)
TEST_COMPARE (pthread_mutex_timedlock (&m, &ts_timeout), 0);
else
TEST_COMPARE (pthread_mutex_clocklock (&m, clockid, &ts_timeout), 0);
const struct timespec ts_end = xclock_now (clockid_for_get);
/* Check that timedlock didn't delay. We use a limit of 0.1 secs. */
TEST_TIMESPEC_BEFORE (ts_end,
timespec_add (ts_start, make_timespec (0, 100000000)));
TEST_COMPARE (pthread_mutex_unlock (&m), 0);
TEST_COMPARE (pthread_mutex_destroy (&m), 0);
return 0;
}
static int do_test (void)
{
do_test_clock (CLOCK_USE_TIMEDLOCK, "timedlock");
do_test_clock (CLOCK_REALTIME, "clocklock(realtime)");
do_test_clock (CLOCK_MONOTONIC, "clocklock(monotonic)");
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,189 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* This test is a template for other tests to use. Other tests define
the following macros to change the behaviour of the template test.
The test is very simple, it configures N threads given the parameters
below and then proceeds to go through mutex lock and unlock
operations in each thread as described before for the thread
function. */
#ifndef TYPE
# define TYPE PTHREAD_MUTEX_DEFAULT
#endif
#ifndef ROBUST
# define ROBUST PTHREAD_MUTEX_STALLED
#endif
#ifndef DELAY_NSEC
# define DELAY_NSEC 11000
#endif
#ifndef ROUNDS
# define ROUNDS 1000
#endif
#ifndef N
# define N 100
#endif
static pthread_mutex_t lock;
/* Each thread locks and the subsequently unlocks the lock, yielding
the smallest critical section possible. After the unlock the thread
waits DELAY_NSEC nanoseconds before doing the lock and unlock again.
Every thread does this ROUNDS times. The lock and unlock are
checked for errors. */
static void *
tf (void *arg)
{
int nr = (long int) arg;
int cnt;
struct timespec ts = { .tv_sec = 0, .tv_nsec = DELAY_NSEC };
for (cnt = 0; cnt < ROUNDS; ++cnt)
{
if (pthread_mutex_lock (&lock) != 0)
{
printf ("thread %d: failed to get the lock\n", nr);
return (void *) 1l;
}
if (pthread_mutex_unlock (&lock) != 0)
{
printf ("thread %d: failed to release the lock\n", nr);
return (void *) 1l;
}
if ((ts.tv_sec > 0) || (ts.tv_nsec > 0))
nanosleep (&ts, NULL);
}
return NULL;
}
/* Setup and run N threads, where each thread does as described
in the above thread function. The threads are given a minimal 1MiB
stack since they don't do anything between the lock and unlock. */
static int
do_test (void)
{
pthread_mutexattr_t a;
if (pthread_mutexattr_init (&a) != 0)
{
puts ("mutexattr_init failed");
exit (1);
}
if (pthread_mutexattr_settype (&a, TYPE) != 0)
{
puts ("mutexattr_settype failed");
exit (1);
}
if (pthread_mutexattr_setrobust (&a, ROBUST) != 0)
{
puts ("mutexattr_setrobust failed");
exit (1);
}
#ifdef ENABLE_PI
if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
{
puts ("pthread_mutexattr_setprotocol failed");
return 1;
}
#endif
int e = pthread_mutex_init (&lock, &a);
if (e != 0)
{
#ifdef ENABLE_PI
if (e == ENOTSUP)
{
puts ("PI mutexes unsupported");
return 0;
}
#endif
puts ("mutex_init failed");
return 1;
}
if (pthread_mutexattr_destroy (&a) != 0)
{
puts ("mutexattr_destroy failed");
return 1;
}
pthread_attr_t at;
pthread_t th[N];
int cnt;
if (pthread_attr_init (&at) != 0)
{
puts ("attr_init failed");
return 1;
}
if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
{
puts ("attr_setstacksize failed");
return 1;
}
if (pthread_mutex_lock (&lock) != 0)
{
puts ("locking in parent failed");
return 1;
}
for (cnt = 0; cnt < N; ++cnt)
if (pthread_create (&th[cnt], &at, tf, (void *) (long int) cnt) != 0)
{
printf ("creating thread %d failed\n", cnt);
return 1;
}
if (pthread_attr_destroy (&at) != 0)
{
puts ("attr_destroy failed");
return 1;
}
if (pthread_mutex_unlock (&lock) != 0)
{
puts ("unlocking in parent failed");
return 1;
}
for (cnt = 0; cnt < N; ++cnt)
if (pthread_join (th[cnt], NULL) != 0)
{
printf ("joining thread %d failed\n", cnt);
return 1;
}
return 0;
}
#define TIMEOUT 60
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,7 @@
/* Bug 21778: Fix oversight in robust mutex lock acquisition. */
#define TYPE PTHREAD_MUTEX_NORMAL
#define ROBUST PTHREAD_MUTEX_ROBUST
#define DELAY_NSEC 0
#define ROUNDS 1000
#define N 32
#include "tst-mutex7.c"

View File

@ -1,435 +0,0 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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, see
<https://www.gnu.org/licenses/>. */
/* This test checks behavior not required by POSIX. */
#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <elf/dl-tunables.h>
static pthread_mutex_t *m;
static pthread_barrier_t b;
static pthread_cond_t c;
static bool done;
static void
cl (void *arg)
{
if (pthread_mutex_unlock (m) != 0)
{
puts ("cl: mutex_unlocked failed");
exit (1);
}
}
static void *
tf (void *arg)
{
if (pthread_mutex_lock (m) != 0)
{
puts ("tf: mutex_lock failed");
return (void *) 1l;
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
return (void *) 1l;
}
if (arg == NULL)
do
if (pthread_cond_wait (&c, m) != 0)
{
puts ("tf: cond_wait failed");
return (void *) 1l;
}
while (! done);
else
do
{
pthread_cleanup_push (cl, NULL);
if (pthread_cond_wait (&c, m) != 0)
{
puts ("tf: cond_wait failed");
return (void *) 1l;
}
pthread_cleanup_pop (0);
}
while (! done);
if (pthread_mutex_unlock (m) != 0)
{
puts ("tf: mutex_unlock failed");
return (void *) 1l;
}
return NULL;
}
static int
check_type (const char *mas, pthread_mutexattr_t *ma)
{
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);
if (e != 0)
{
#ifdef ENABLE_PI
if (e == ENOTSUP)
{
puts ("PI mutexes unsupported");
return 0;
}
#endif
printf ("1st mutex_init failed for %s\n", mas);
return 1;
}
if (pthread_mutex_destroy (m) != 0)
{
printf ("immediate mutex_destroy failed for %s\n", mas);
return 1;
}
if (pthread_mutex_init (m, ma) != 0)
{
printf ("2nd mutex_init failed for %s\n", mas);
return 1;
}
if (pthread_mutex_lock (m) != 0)
{
printf ("1st mutex_lock failed for %s\n", mas);
return 1;
}
/* Elided mutexes don't fail destroy, thus only test this if we don't assume
elision. */
if (assume_elided_mutex == false)
{
e = pthread_mutex_destroy (m);
if (e == 0)
{
printf ("mutex_destroy of self-locked mutex succeeded for %s\n", mas);
return 1;
}
if (e != EBUSY)
{
printf ("\
mutex_destroy of self-locked mutex did not return EBUSY %s\n",
mas);
return 1;
}
}
if (pthread_mutex_unlock (m) != 0)
{
printf ("1st mutex_unlock failed for %s\n", mas);
return 1;
}
if (pthread_mutex_trylock (m) != 0)
{
printf ("mutex_trylock failed for %s\n", mas);
return 1;
}
/* Elided mutexes don't fail destroy. */
if (assume_elided_mutex == false)
{
e = pthread_mutex_destroy (m);
if (e == 0)
{
printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n",
mas);
return 1;
}
if (e != EBUSY)
{
printf ("\
mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
mas);
return 1;
}
}
if (pthread_mutex_unlock (m) != 0)
{
printf ("2nd mutex_unlock failed for %s\n", mas);
return 1;
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("1st create failed");
return 1;
}
done = false;
e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("1st barrier_wait failed");
return 1;
}
if (pthread_mutex_lock (m) != 0)
{
printf ("2nd mutex_lock failed for %s\n", mas);
return 1;
}
if (pthread_mutex_unlock (m) != 0)
{
printf ("3rd mutex_unlock failed for %s\n", mas);
return 1;
}
/* Elided mutexes don't fail destroy. */
if (assume_elided_mutex == false)
{
e = pthread_mutex_destroy (m);
if (e == 0)
{
printf ("mutex_destroy of condvar-used mutex succeeded for %s\n",
mas);
return 1;
}
if (e != EBUSY)
{
printf ("\
mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
return 1;
}
}
done = true;
if (pthread_cond_signal (&c) != 0)
{
puts ("cond_signal failed");
return 1;
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
return 1;
}
if (r != NULL)
{
puts ("thread didn't return NULL");
return 1;
}
if (pthread_mutex_destroy (m) != 0)
{
printf ("mutex_destroy after condvar-use failed for %s\n", mas);
return 1;
}
if (pthread_mutex_init (m, ma) != 0)
{
printf ("3rd mutex_init failed for %s\n", mas);
return 1;
}
if (pthread_create (&th, NULL, tf, (void *) 1) != 0)
{
puts ("2nd create failed");
return 1;
}
done = false;
e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("2nd barrier_wait failed");
return 1;
}
if (pthread_mutex_lock (m) != 0)
{
printf ("3rd mutex_lock failed for %s\n", mas);
return 1;
}
if (pthread_mutex_unlock (m) != 0)
{
printf ("4th mutex_unlock failed for %s\n", mas);
return 1;
}
/* Elided mutexes don't fail destroy. */
if (assume_elided_mutex == false)
{
e = pthread_mutex_destroy (m);
if (e == 0)
{
printf ("2nd mutex_destroy of condvar-used mutex succeeded for %s\n",
mas);
return 1;
}
if (e != EBUSY)
{
printf ("\
2nd mutex_destroy of condvar-used mutex did not return EBUSY for %s\n",
mas);
return 1;
}
}
if (pthread_cancel (th) != 0)
{
puts ("cond_cancel failed");
return 1;
}
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
return 1;
}
if (r != PTHREAD_CANCELED)
{
puts ("thread not canceled");
return 1;
}
if (pthread_mutex_destroy (m) != 0)
{
printf ("mutex_destroy after condvar-canceled failed for %s\n", mas);
return 1;
}
return 0;
}
static int
do_test (void)
{
pthread_mutex_t mm;
m = &mm;
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
return 1;
}
if (pthread_cond_init (&c, NULL) != 0)
{
puts ("cond_init failed");
return 1;
}
puts ("check normal mutex");
int res = check_type ("normal", NULL);
pthread_mutexattr_t ma;
if (pthread_mutexattr_init (&ma) != 0)
{
puts ("1st mutexattr_init failed");
return 1;
}
if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE) != 0)
{
puts ("1st mutexattr_settype failed");
return 1;
}
#ifdef ENABLE_PI
if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT))
{
puts ("1st pthread_mutexattr_setprotocol failed");
return 1;
}
#endif
puts ("check recursive mutex");
res |= check_type ("recursive", &ma);
if (pthread_mutexattr_destroy (&ma) != 0)
{
puts ("1st mutexattr_destroy failed");
return 1;
}
if (pthread_mutexattr_init (&ma) != 0)
{
puts ("2nd mutexattr_init failed");
return 1;
}
if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
{
puts ("2nd mutexattr_settype failed");
return 1;
}
#ifdef ENABLE_PI
if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT))
{
puts ("2nd pthread_mutexattr_setprotocol failed");
return 1;
}
#endif
puts ("check error-checking mutex");
res |= check_type ("error-checking", &ma);
if (pthread_mutexattr_destroy (&ma) != 0)
{
puts ("2nd mutexattr_destroy failed");
return 1;
}
return res;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,140 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <support/check.h>
#include <support/timespec.h>
#include <support/xunistd.h>
/* A bogus clock value that tells run_test to use pthread_mutex_timedlock
rather than pthread_mutex_clocklock. */
#define CLOCK_USE_TIMEDLOCK (-1)
static void
do_test_clock (clockid_t clockid)
{
const clockid_t clockid_for_get =
(clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
size_t ps = sysconf (_SC_PAGESIZE);
char tmpfname[] = "/tmp/tst-mutex9.XXXXXX";
char data[ps];
void *mem;
int fd;
pthread_mutex_t *m;
pthread_mutexattr_t a;
pid_t pid;
fd = mkstemp (tmpfname);
if (fd == -1)
FAIL_EXIT1 ("cannot open temporary file: %m\n");
/* Make sure it is always removed. */
unlink (tmpfname);
/* Create one page of data. */
memset (data, '\0', ps);
/* Write the data to the file. */
xwrite (fd, data, ps);
mem = xmmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd);
m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t))
& ~(__alignof (pthread_mutex_t) - 1));
TEST_COMPARE (pthread_mutexattr_init (&a), 0);
TEST_COMPARE (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED), 0);
TEST_COMPARE (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE), 0);
#ifdef ENABLE_PI
TEST_COMPARE (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT), 0);
#endif
int e;
if ((e = pthread_mutex_init (m, &a)) != 0)
{
#ifdef ENABLE_PI
if (e == ENOTSUP)
FAIL_UNSUPPORTED ("PI mutexes unsupported");
#endif
FAIL_EXIT1 ("mutex_init failed");
}
TEST_COMPARE (pthread_mutex_lock (m), 0);
TEST_COMPARE (pthread_mutexattr_destroy (&a), 0);
puts ("going to fork now");
pid = xfork ();
if (pid == 0)
{
if (pthread_mutex_trylock (m) == 0)
FAIL_EXIT1 ("child: mutex_trylock succeeded");
if (pthread_mutex_unlock (m) == 0)
FAIL_EXIT1 ("child: mutex_unlock succeeded");
const struct timespec ts = timespec_add (xclock_now (clockid_for_get),
make_timespec (0, 500000000));
if (clockid == CLOCK_USE_TIMEDLOCK)
TEST_COMPARE (pthread_mutex_timedlock (m, &ts), ETIMEDOUT);
else
TEST_COMPARE (pthread_mutex_clocklock (m, clockid, &ts), ETIMEDOUT);
alarm (1);
pthread_mutex_lock (m);
puts ("child: mutex_lock returned");
exit (0);
}
sleep (2);
int status;
if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
FAIL_EXIT1 ("waitpid failed");
if (! WIFSIGNALED (status))
FAIL_EXIT1 ("child not killed by signal");
TEST_COMPARE (WTERMSIG (status), SIGALRM);
}
static int
do_test (void)
{
do_test_clock (CLOCK_USE_TIMEDLOCK);
do_test_clock (CLOCK_REALTIME);
do_test_clock (CLOCK_MONOTONIC);
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,60 @@
/* Make sure that pthread_mutexattr_gettype returns a valid kind.
Copyright (C) 2015-2020 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; if not, see
<https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <string.h>
#include <pthread.h>
static int
do_test (void)
{
pthread_mutexattr_t attr;
int kind;
int error;
error = pthread_mutexattr_init (&attr);
if (error)
{
printf ("pthread_mutexattr_init: %s\n", strerror (error));
return 1;
}
error = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_DEFAULT);
if (error)
{
printf ("pthread_mutexattr_settype (1): %s\n", strerror (error));
return 1;
}
error = pthread_mutexattr_gettype (&attr, &kind);
if (error)
{
printf ("pthread_mutexattr_gettype: %s\n", strerror (error));
return 1;
}
error = pthread_mutexattr_settype (&attr, kind);
if (error)
{
printf ("pthread_mutexattr_settype (2): %s\n", strerror (error));
return 1;
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,207 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
static int
do_test (void)
{
size_t ps = sysconf (_SC_PAGESIZE);
char tmpfname[] = "/tmp/tst-rwlock12.XXXXXX";
char data[ps];
void *mem;
int fd;
pthread_mutex_t *m;
pthread_mutexattr_t ma;
pthread_rwlock_t *r;
pthread_rwlockattr_t ra;
pid_t pid;
int status = 0;
fd = mkstemp (tmpfname);
if (fd == -1)
{
printf ("cannot open temporary file: %m\n");
return 1;
}
/* Make sure it is always removed. */
unlink (tmpfname);
/* Create one page of data. */
memset (data, '\0', ps);
/* Write the data to the file. */
if (write (fd, data, ps) != (ssize_t) ps)
{
puts ("short write");
return 1;
}
mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mem == MAP_FAILED)
{
printf ("mmap failed: %m\n");
return 1;
}
r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
& ~(__alignof (pthread_rwlock_t) - 1));
/* The following assumes alignment for a mutex is at least as high
as that for a rwlock. Which is true in our case. */
m = (pthread_mutex_t *) (r + 1);
if (pthread_rwlockattr_init (&ra) != 0)
{
puts ("rwlockattr_init failed");
return 1;
}
if (pthread_rwlockattr_setpshared (&ra, PTHREAD_PROCESS_SHARED) != 0)
{
puts ("rwlockattr_setpshared failed");
return 1;
}
if (pthread_rwlock_init (r, &ra) != 0)
{
puts ("rwlock_init failed");
return 1;
}
if (pthread_mutexattr_init (&ma) != 0)
{
puts ("rwlockattr_init failed");
return 1;
}
if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
{
puts ("mutexattr_setpshared failed");
return 1;
}
if (pthread_mutex_init (m, &ma) != 0)
{
puts ("mutex_init failed");
return 1;
}
/* Lock the mutex. */
if (pthread_mutex_lock (m) != 0)
{
puts ("mutex_lock failed");
return 1;
}
puts ("going to fork now");
pid = fork ();
if (pid == -1)
{
puts ("fork failed");
return 1;
}
else if (pid == 0)
{
/* Lock the mutex. */
if (pthread_mutex_lock (m) != 0)
{
puts ("child: mutex_lock failed");
return 1;
}
/* Try to get the rwlock. */
if (pthread_rwlock_trywrlock (r) == 0)
{
puts ("rwlock_trywrlock succeeded");
return 1;
}
/* Try again. */
struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000000 };
int e = pthread_rwlock_timedwrlock (r, &ts);
if (e == 0)
{
puts ("rwlock_timedwrlock succeeded");
return 1;
}
if (e != ETIMEDOUT)
{
puts ("rwlock_timedwrlock didn't return ETIMEDOUT");
status = 1;
}
if (pthread_rwlock_tryrdlock (r) == 0)
{
puts ("rwlock_tryrdlock succeeded");
return 1;
}
e = pthread_rwlock_timedrdlock (r, &ts);
if (e == 0)
{
puts ("rwlock_timedrdlock succeeded");
return 1;
}
if (e != ETIMEDOUT)
{
puts ("rwlock_timedrdlock didn't return ETIMEDOUT");
status = 1;
}
}
else
{
/* Lock the rwlock for writing. */
if (pthread_rwlock_wrlock (r) != 0)
{
puts ("rwlock_wrlock failed");
kill (pid, SIGTERM);
return 1;
}
/* Allow the child to run. */
if (pthread_mutex_unlock (m) != 0)
{
puts ("mutex_unlock failed");
kill (pid, SIGTERM);
return 1;
}
/* Just wait for the child. */
if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
{
puts ("waitpid failed");
kill (pid, SIGTERM);
return 1;
}
}
return status;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,96 @@
/* Copyright (C) 2004-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
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, see
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <support/check.h>
#include <support/xthread.h>
#include <support/xtime.h>
static pthread_barrier_t b;
static pthread_rwlock_t r = PTHREAD_RWLOCK_INITIALIZER;
static void *
tf (void *arg)
{
/* Lock the read-write lock. */
TEST_COMPARE (pthread_rwlock_wrlock (&r), 0);
pthread_t mt = *(pthread_t *) arg;
xpthread_barrier_wait (&b);
/* This call will never return. */
xpthread_join (mt);
return NULL;
}
static int
do_test (void)
{
struct timespec ts;
xclock_gettime (CLOCK_REALTIME, &ts);
xpthread_barrier_init (&b, NULL, 2);
pthread_t me = pthread_self ();
xpthread_create (NULL, tf, &me);
/* Wait until the rwlock is locked. */
xpthread_barrier_wait (&b);
ts.tv_nsec = -1;
TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
ts.tv_nsec = 1000000000;
TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
ts.tv_nsec = (__typeof (ts.tv_nsec)) 0x100001000LL;
if ((__typeof (ts.tv_nsec)) 0x100001000LL != 0x100001000LL)
ts.tv_nsec = 2000000000;
TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
return 0;
}
#include <support/test-driver.c>