Discussion:
lock: more tests
Bruno Haible
2018-02-17 09:11:15 UTC
Permalink
Let me add a test of the gl_once API of glthread/lock.h.


2018-02-17 Bruno Haible <***@clisp.org>

lock: Add test of gl_once.
* tests/test-once.c: New file.
* modules/lock-tests (Files): Add it.
(Makefile.am): Build and test programs 'test-once1' and 'test-once2'.

============================== tests/test-once.c ==============================
/* Test of once-only execution in multithreaded situations.
Copyright (C) 2018 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 <***@clisp.org>, 2018. */

#include <config.h>

#include "glthread/lock.h"

#include "macros.h"

gl_once_define(static, a_once)

static int a;

static void
a_init (void)
{
a = 42;
}

int
main ()
{
gl_once (a_once, a_init);

ASSERT (a == 42);

return 0;
}
===============================================================================
diff --git a/modules/lock-tests b/modules/lock-tests
index bfab1f4..52858f7 100644
--- a/modules/lock-tests
+++ b/modules/lock-tests
@@ -1,6 +1,7 @@
Files:
tests/test-rwlock1.c
tests/test-lock.c
+tests/test-once.c

Depends-on:
thread
@@ -11,7 +12,11 @@ configure.ac:
AC_CHECK_HEADERS_ONCE([semaphore.h])

Makefile.am:
-TESTS += test-rwlock1 test-lock
-check_PROGRAMS += test-rwlock1 test-lock
+TESTS += test-rwlock1 test-lock test-once1 test-once2
+check_PROGRAMS += test-rwlock1 test-lock test-once1 test-once2
test_rwlock1_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@
test_lock_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@
+test_once1_SOURCES = test-once.c
+test_once1_LDADD = $(LDADD) @LIBTHREAD@
+test_once2_SOURCES = test-once.c
+test_once2_LDADD = $(LDADD) @LIBMULTITHREAD@
Bruno Haible
2018-02-17 09:25:30 UTC
Permalink
The new test-once1 test crashes on FreeBSD 11, through abort().
This is because newer versions of FreeBSD now have pthread_cancel
in libc (older versions had it only in libthread, libthr), thus
the macro pthread_in_use() produces the value 1, but pthread_once()
returns ENOSYS. (Cf.
https://github.com/freebsd/freebsd/blob/master/lib/libc/gen/_pthread_stubs.c )

This fixes it.

I considered adding an autoconf test for the presence of pthread_cancel
versus pthread_create in libc vs. libpthread (rather than a #ifdef __FreeBSD__).
But we want binaries built with older versions of FreeBSD to work with newer
versions of FreeBSD as well; an autoconf test cannot do this.


2018-02-17 Bruno Haible <***@clisp.org>

lock: Fix test-once1 crash on FreeBSD11.
* lib/glthread/lock.h: On FreeBSD, test the weak value of the symbol
'pthread_create', not 'pthread_cancel'.

diff --git a/lib/glthread/lock.h b/lib/glthread/lock.h
index 87d9df1..dd8e1f8 100644
--- a/lib/glthread/lock.h
+++ b/lib/glthread/lock.h
@@ -149,8 +149,18 @@ extern int glthread_in_use (void);
# endif

# if !PTHREAD_IN_USE_DETECTION_HARD
-# pragma weak pthread_cancel
-# define pthread_in_use() (pthread_cancel != NULL)
+ /* On most platforms, pthread_cancel or pthread_kill can be used to
+ determine whether libpthread is in use.
+ On newer versions of FreeBSD, however, this is no longer possible,
+ because pthread_cancel and pthread_kill got added to libc. Therefore
+ use pthread_create to test whether libpthread is in use. */
+# if defined __FreeBSD__ || defined __DragonFly__ /* FreeBSD */
+# pragma weak pthread_create
+# define pthread_in_use() (pthread_create != NULL)
+# else /* glibc, NetBSD, OpenBSD, IRIX, OSF/1, Solaris */
+# pragma weak pthread_cancel
+# define pthread_in_use() (pthread_cancel != NULL)
+# endif
# endif

# else

Loading...