>From f9f125c4f414ec1a85016353319bfa141f120fdb Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Tue, 6 Aug 2024 15:43:16 +0200 Subject: [PATCH 1/2] pthread-mutex tests: Strengthen tests. * tests/test-pthread-mutex-type.c: New file. * modules/pthread-mutex-tests (Files): Add it. (Makefile.am): Arrange to test test-pthread-mutex-type. * doc/posix-functions/pthread_mutex_lock.texi: Mention FreeBSD and NetBSD problem. * doc/posix-functions/pthread_mutex_trylock.texi: Likewise. --- ChangeLog | 10 ++ doc/posix-functions/pthread_mutex_lock.texi | 5 + .../pthread_mutex_trylock.texi | 5 + modules/pthread-mutex-tests | 8 +- tests/test-pthread-mutex-type.c | 127 ++++++++++++++++++ 5 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 tests/test-pthread-mutex-type.c diff --git a/ChangeLog b/ChangeLog index db84b220e2..9e5488a686 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2024-08-06 Bruno Haible + + pthread-mutex tests: Strengthen tests. + * tests/test-pthread-mutex-type.c: New file. + * modules/pthread-mutex-tests (Files): Add it. + (Makefile.am): Arrange to test test-pthread-mutex-type. + * doc/posix-functions/pthread_mutex_lock.texi: Mention FreeBSD and + NetBSD problem. + * doc/posix-functions/pthread_mutex_trylock.texi: Likewise. + 2024-08-06 Bruno Haible windows-timedrecmutex: Add tests. diff --git a/doc/posix-functions/pthread_mutex_lock.texi b/doc/posix-functions/pthread_mutex_lock.texi index e4ee553206..2d04670a14 100644 --- a/doc/posix-functions/pthread_mutex_lock.texi +++ b/doc/posix-functions/pthread_mutex_lock.texi @@ -17,4 +17,9 @@ Portability problems not fixed by Gnulib: @itemize +@item +This function does not behave as required by POSIX for mutexes of type +NORMAL and ERRORCHECK, by allowing RECURSIVE locking, +in programs linked without @code{-lpthread} on some platforms: +FreeBSD 14.0, NetBSD 10.0. @end itemize diff --git a/doc/posix-functions/pthread_mutex_trylock.texi b/doc/posix-functions/pthread_mutex_trylock.texi index cefd9b46bc..2cfd516868 100644 --- a/doc/posix-functions/pthread_mutex_trylock.texi +++ b/doc/posix-functions/pthread_mutex_trylock.texi @@ -17,4 +17,9 @@ Portability problems not fixed by Gnulib: @itemize +@item +This function does not behave as required by POSIX for mutexes of type +NORMAL and ERRORCHECK, by allowing RECURSIVE locking, +in programs linked without @code{-lpthread} on some platforms: +FreeBSD 14.0, NetBSD 10.0. @end itemize diff --git a/modules/pthread-mutex-tests b/modules/pthread-mutex-tests index 068dc24f42..9b242a9852 100644 --- a/modules/pthread-mutex-tests +++ b/modules/pthread-mutex-tests @@ -1,5 +1,6 @@ Files: tests/test-pthread-mutex.c +tests/test-pthread-mutex-type.c tests/atomic-int-posix.h tests/macros.h m4/semaphore.m4 @@ -15,6 +16,9 @@ AC_CHECK_DECLS_ONCE([alarm]) AC_REQUIRE([gl_SEMAPHORE]) Makefile.am: -TESTS += test-pthread-mutex -check_PROGRAMS += test-pthread-mutex +TESTS += test-pthread-mutex test-pthread-mutex-type +check_PROGRAMS += test-pthread-mutex test-pthread-mutex-type test_pthread_mutex_LDADD = $(LDADD) @LIBPMULTITHREAD@ @SCHED_YIELD_LIB@ @LIB_SEMAPHORE@ +# If we were to link test-pthread-mutex-type only with @LIBPTHREAD@ instead of +# @LIBPMULTITHREAD@, this test would fail on FreeBSD and NetBSD. +test_pthread_mutex_type_LDADD = $(LDADD) @LIBPMULTITHREAD@ diff --git a/tests/test-pthread-mutex-type.c b/tests/test-pthread-mutex-type.c new file mode 100644 index 0000000000..3406055912 --- /dev/null +++ b/tests/test-pthread-mutex-type.c @@ -0,0 +1,127 @@ +/* Test of locking in multithreaded situations. + Copyright (C) 2024 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2024. */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +#include "macros.h" + +/* Returns the effective type of a lock. */ +static const char * +get_effective_type (pthread_mutex_t *lock) +{ + /* Lock once. */ + ASSERT (pthread_mutex_lock (lock) == 0); + + /* Try to lock a second time. */ + int err = pthread_mutex_trylock (lock); + if (err == 0) + return "RECURSIVE"; + if (err == EBUSY) + return "NORMAL"; + + /* We can't really check whether the lock is effectively ERRORCHECK, without + risking a deadlock. */ + + return "unknown!"; +} + +int +main () +{ + /* Find the effective type of a NORMAL lock. */ + const char *type_normal; + { + pthread_mutex_t lock; + pthread_mutexattr_t attr; + ASSERT (pthread_mutexattr_init (&attr) == 0); + ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL) == 0); + ASSERT (pthread_mutex_init (&lock, &attr) == 0); + ASSERT (pthread_mutexattr_destroy (&attr) == 0); + type_normal = get_effective_type (&lock); + } + + /* Find the effective type of an ERRORCHECK lock. */ + const char *type_errorcheck; + { + pthread_mutex_t lock; + pthread_mutexattr_t attr; + ASSERT (pthread_mutexattr_init (&attr) == 0); + ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK) == 0); + ASSERT (pthread_mutex_init (&lock, &attr) == 0); + ASSERT (pthread_mutexattr_destroy (&attr) == 0); + type_errorcheck = get_effective_type (&lock); + } + + /* Find the effective type of a RECURSIVE lock. */ + const char *type_recursive; + { + pthread_mutex_t lock; + pthread_mutexattr_t attr; + ASSERT (pthread_mutexattr_init (&attr) == 0); + ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE) == 0); + ASSERT (pthread_mutex_init (&lock, &attr) == 0); + ASSERT (pthread_mutexattr_destroy (&attr) == 0); + type_recursive = get_effective_type (&lock); + } + + /* Find the effective type of a DEFAULT lock. */ + const char *type_default; + { + pthread_mutex_t lock; + pthread_mutexattr_t attr; + ASSERT (pthread_mutexattr_init (&attr) == 0); + ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_DEFAULT) == 0); + ASSERT (pthread_mutex_init (&lock, &attr) == 0); + ASSERT (pthread_mutexattr_destroy (&attr) == 0); + type_default = get_effective_type (&lock); + } + + /* Find the effective type of a default-initialized lock. */ + const char *type_def; + { + pthread_mutex_t lock; + ASSERT (pthread_mutex_init (&lock, NULL) == 0); + type_def = get_effective_type (&lock); + } + + printf ("PTHREAD_MUTEX_NORMAL -> type = %s\n", type_normal); + printf ("PTHREAD_MUTEX_ERRORCHECK -> type = %s\n", type_errorcheck); + printf ("PTHREAD_MUTEX_RECURSIVE -> type = %s\n", type_recursive); + printf ("PTHREAD_MUTEX_DEFAULT -> type = %s\n", type_default); + printf ("Default -> type = %s\n", type_def); + + ASSERT (strcmp (type_normal, "NORMAL") == 0); + ASSERT (strcmp (type_errorcheck, "NORMAL") == 0); + ASSERT (strcmp (type_recursive, "RECURSIVE") == 0); + + ASSERT (strcmp (type_default, type_def) == 0); + + /* This is not required by POSIX, but happens to be the case on all + platforms. */ + ASSERT (strcmp (type_default, "NORMAL") == 0); + ASSERT (strcmp (type_def, "NORMAL") == 0); + + return test_exit_status; +} -- 2.34.1