]> Savannah Git Hosting - gnulib.git/commitdiff
pthread-mutex tests: Strengthen tests.
authorBruno Haible <bruno@clisp.org>
Tue, 6 Aug 2024 13:43:16 +0000 (15:43 +0200)
committerBruno Haible <bruno@clisp.org>
Tue, 6 Aug 2024 13:43:16 +0000 (15:43 +0200)
* 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
doc/posix-functions/pthread_mutex_lock.texi
doc/posix-functions/pthread_mutex_trylock.texi
modules/pthread-mutex-tests
tests/test-pthread-mutex-type.c [new file with mode: 0644]

index db84b220e20997144c283a1cdf97302e14767a57..9e5488a68658b122c114f96ce8d6f2f1088eb805 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2024-08-06  Bruno Haible  <bruno@clisp.org>
+
+       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  <bruno@clisp.org>
 
        windows-timedrecmutex: Add tests.
index e4ee5532069564caf41ba9fa21b5d9f124ed5892..2d04670a1414639f923c9e7f0acbf569d06e7388 100644 (file)
@@ -17,4 +17,9 @@ Minix 3.1.8.
 
 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
index cefd9b46bc487a76831ac839d5b9a1118f91069a..2cfd516868a58ab13a6be2f2fd598253a3be8ea7 100644 (file)
@@ -17,4 +17,9 @@ Minix 3.1.8.
 
 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
index 068dc24f4295d99bc31f5691b65eb496c30913fc..9b242a9852d7dab550b43a4270709ddf74441568 100644 (file)
@@ -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 (file)
index 0000000..3406055
--- /dev/null
@@ -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 <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2024.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <pthread.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#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;
+}