From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 209.51.188.0/24 X-Spam-Status: No, score=-3.7 required=3.0 tests=AWL,BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 6B1271F462 for ; Thu, 20 Jun 2019 10:56:07 +0000 (UTC) Received: from localhost ([::1]:46064 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hdujd-0006u5-Kf for normalperson@yhbt.net; Thu, 20 Jun 2019 06:56:05 -0400 Received: from eggs.gnu.org ([209.51.188.92]:45550) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hduel-0002J8-A1 for bug-gnulib@gnu.org; Thu, 20 Jun 2019 06:51:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hduZO-0006rU-N0 for bug-gnulib@gnu.org; Thu, 20 Jun 2019 06:45:45 -0400 Received: from mo6-p00-ob.smtp.rzone.de ([2a01:238:20a:202:5300::8]:28509) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hduZN-0006ns-Pf for bug-gnulib@gnu.org; Thu, 20 Jun 2019 06:45:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1561027528; s=strato-dkim-0002; d=clisp.org; h=References:In-Reply-To:Message-ID:Date:Subject:To:From: X-RZG-CLASS-ID:X-RZG-AUTH:From:Subject:Sender; bh=/CIxMCedngsDDG6Deg7A/kUkbkdi7N2rahx7GZod4sY=; b=NjZxtDAWqxzDhiT7W7hnjXTJhK2F1kYl8NRdt35ySs0zqmQ6CUfHqAXpxZTDRMWQO7 /pGJ/z7Vt8MCj5RYXOgYfB48aKJHDmFlff+5ecrODn8kntRbDBs1yQuDlWS9uN8SAesf u79KUOCmKvyY+ZH7zigOLGokI9hHntTNs/q+z7Cwdc51AKKFPAqQIypxn/Aj97l293g6 s0N5LzCNk4Rsy/fsEC6wzz54pZ55JgJg4rqZnbYTta6G8vGCpgoIwJFlP1i7JIc+oRaF sK7cTsNGMFjyBcp8My1LaZUMN5vgspMgjK4rXPw9mnRYNnkknE9ymBc3KL0zb6uHhW8Z +hGA== X-RZG-AUTH: ":Ln4Re0+Ic/6oZXR1YgKryK8brlshOcZlIWs+iCP5vnk6shH+AHjwLuWOGaf0y5RW" X-RZG-CLASS-ID: mo00 Received: from bruno.haible.de by smtp.strato.de (RZmta 44.24 DYNA|AUTH) with ESMTPSA id J01134v5KAjQDY8 (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (curve secp521r1 with 521 ECDH bits, eq. 15360 bits RSA)) (Client did not present a certificate); Thu, 20 Jun 2019 12:45:26 +0200 (CEST) From: Bruno Haible To: bug-gnulib@gnu.org Subject: [PATCH] ISO C 11 threads implementation Date: Thu, 20 Jun 2019 12:45:25 +0200 Message-ID: <4934999.OEDBPbr2Oh@omega> User-Agent: KMail/5.1.3 (Linux/4.4.0-145-generic; KDE/5.18.0; x86_64; ; ) In-Reply-To: <2006820.U7yMURXysu@omega> References: <2006820.U7yMURXysu@omega> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart10702591.pDCx4yai7z" Content-Transfer-Encoding: 7Bit X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a01:238:20a:202:5300::8 X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Sender: "bug-gnulib" This is a multi-part message in MIME format. --nextPart10702591.pDCx4yai7z Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" These are the patches that provide the ISO C 11 (except for 'thread_local'). The implementation is based on for POSIX threads and on the windows-* modules for native Windows. The only major headache was how to work around the terrible AIX bugs. The unit tests are adapted from the unit tests of 'thread', 'lock', 'cond', 'tls'. 16 threads-h: New module. 17 threads-h: Add tests. This is just the header file. 18 thrd: New module. 19 mtx: New module. 20 cnd: New module. 21 tss: New module. 22 thrd: Add tests. 23 mtx: Add tests. 24 cnd: Add tests. 25 tss: Add tests. These are the function implementations. 26 threads: New module. This is just a convenience module that requests all of the function implementations. --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0016-threads-h-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0016-threads-h-New-module.patch" >From 80d24481060742c00cfe83a6a772db3856d1e7cb Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:17:30 +0200 Subject: [PATCH 16/26] threads-h: New module. * lib/threads.in.h: New file. * m4/threads.m4: New file. * m4/yield.m4 (gl_YIELD): Update comment. * modules/threads-h: New file. * modules/yields (configure.ac): Use AC_REQUIRE. * doc/posix-headers/threads.texi: Mention the new module and the AIX bugs. --- ChangeLog | 11 + doc/posix-headers/threads.texi | 14 +- lib/threads.in.h | 649 +++++++++++++++++++++++++++++++++++++++++ m4/threads.m4 | 126 ++++++++ m4/yield.m4 | 4 +- modules/threads-h | 73 +++++ modules/yield | 2 +- 7 files changed, 872 insertions(+), 7 deletions(-) create mode 100644 lib/threads.in.h create mode 100644 m4/threads.m4 create mode 100644 modules/threads-h diff --git a/ChangeLog b/ChangeLog index ab97f37..22b942b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2019-06-20 Bruno Haible + threads-h: New module. + * lib/threads.in.h: New file. + * m4/threads.m4: New file. + * m4/yield.m4 (gl_YIELD): Update comment. + * modules/threads-h: New file. + * modules/yields (configure.ac): Use AC_REQUIRE. + * doc/posix-headers/threads.texi: Mention the new module and the AIX + bugs. + +2019-06-20 Bruno Haible + windows-thread: New module. * lib/windows-thread.h: New file, based on lib/glthread/thread.h. * lib/windows-thread.c: New file, based on lib/glthread/thread.c. diff --git a/doc/posix-headers/threads.texi b/doc/posix-headers/threads.texi index 9892539..71ae43a 100644 --- a/doc/posix-headers/threads.texi +++ b/doc/posix-headers/threads.texi @@ -3,15 +3,21 @@ Defines the multithreading facility of ISO C11. -Gnulib module: --- +Gnulib module: threads-h Portability problems fixed by Gnulib: @itemize +@item +This header file is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. +@item +This header file defines @code{thrd_start_t} incorrectly on some platforms: +AIX 7.2. +@item +This header file does not define @code{TSS_DTOR_ITERATIONS} on some platforms: +AIX 7.2. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This header file is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/lib/threads.in.h b/lib/threads.in.h new file mode 100644 index 0000000..a18d64b --- /dev/null +++ b/lib/threads.in.h @@ -0,0 +1,649 @@ +/* An ISO C 11 compatible . + + Copyright (C) 2019 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 2, 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 . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#ifndef _@GUARD_PREFIX@_THREADS_H + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_THREADS_H@ +# @INCLUDE_NEXT@ @NEXT_THREADS_H@ +#endif + +#ifndef _@GUARD_PREFIX@_THREADS_H +#define _@GUARD_PREFIX@_THREADS_H + +#if !@HAVE_THREADS_H@ + +# include + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# else +/* Use POSIX threads. */ + +# include + +# endif + +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _Noreturn is copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Storage class specifier for thread-local storage. */ +#ifdef _AIX +/* The macro definition from AIX 7.1..7.2 is unusable, because + its expansion ends in a semicolon. */ +# undef thread_local +#endif +#if !@HAVE_THREADS_H@ || !defined thread_local +# define thread_local _Thread_local +#endif + + +/* =========== ISO C 11 7.26.5 Thread functions =========== */ + +#if !@HAVE_THREADS_H@ + +/* Return codes. */ +enum +{ + thrd_success = 0, + thrd_timedout = 1, + thrd_busy = 2, + thrd_nomem = 3, + thrd_error = 4 +}; + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# include "windows-thread.h" + +typedef glwthread_thread_t thrd_t; + +# else +/* Use POSIX threads. */ + +typedef pthread_t thrd_t; + +# endif + +#endif + +#if @BROKEN_THRD_START_T@ +/* Need to override thrd_start_t, to make thrd_create work. */ +# define thrd_start_t rpl_thrd_start_t +/* Need to override thrd_t, to make thrd_join work. */ +struct thrd_with_exitcode +{ + thrd_t volatile tid; + int volatile detached; + int volatile exitcode; +}; +typedef struct thrd_with_exitcode *rpl_thrd_t; +# define thrd_t rpl_thrd_t +#endif +/* Type of the main function of a thread. */ +#if !@HAVE_THREADS_H@ || @BROKEN_THRD_START_T@ +typedef int (* thrd_start_t) (void *); +#endif + +#if @GNULIB_THRD@ +# if @REPLACE_THRD_CREATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define thrd_create rpl_thrd_create +# endif +_GL_FUNCDECL_RPL (thrd_create, int, (thrd_t *, thrd_start_t, void *) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (thrd_create, int, (thrd_t *, thrd_start_t, void *)); +# else +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (thrd_create, int, (thrd_t *, thrd_start_t, void *) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (thrd_create, int, (thrd_t *, thrd_start_t, void *)); +# endif +_GL_CXXALIASWARN (thrd_create); +#elif defined GNULIB_POSIXCHECK +# undef thrd_create +# if HAVE_RAW_DECL_THRD_CREATE +_GL_WARN_ON_USE (thrd_create, "thrd_create is unportable - " + "use gnulib module thrd for portability"); +# endif +#endif + +#if @GNULIB_THRD@ +# if @REPLACE_THRD_CURRENT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define thrd_current rpl_thrd_current +# endif +_GL_FUNCDECL_RPL (thrd_current, thrd_t, (void) _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (thrd_current, thrd_t, (void)); +# else +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (thrd_current, thrd_t, (void) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (thrd_current, thrd_t, (void)); +# endif +_GL_CXXALIASWARN (thrd_current); +#elif defined GNULIB_POSIXCHECK +# undef thrd_current +# if HAVE_RAW_DECL_THRD_CURRENT +_GL_WARN_ON_USE (thrd_current, "thrd_current is unportable - " + "use gnulib module thrd for portability"); +# endif +#endif + +#if @GNULIB_THRD@ +# if @REPLACE_THRD_EQUAL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define thrd_equal rpl_thrd_equal +# endif +_GL_FUNCDECL_RPL (thrd_equal, int, (thrd_t, thrd_t) _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (thrd_equal, int, (thrd_t, thrd_t)); +# else +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (thrd_equal, int, (thrd_t, thrd_t) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (thrd_equal, int, (thrd_t, thrd_t)); +# endif +_GL_CXXALIASWARN (thrd_equal); +#elif defined GNULIB_POSIXCHECK +# undef thrd_equal +# if HAVE_RAW_DECL_THRD_EQUAL +_GL_WARN_ON_USE (thrd_equal, "thrd_equal is unportable - " + "use gnulib module thrd for portability"); +# endif +#endif + +#if @GNULIB_THRD@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (thrd_sleep, int, + (const struct timespec *, struct timespec *) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (thrd_sleep, int, + (const struct timespec *, struct timespec *)); +_GL_CXXALIASWARN (thrd_sleep); +#elif defined GNULIB_POSIXCHECK +# undef thrd_sleep +# if HAVE_RAW_DECL_THRD_SLEEP +_GL_WARN_ON_USE (thrd_sleep, "thrd_sleep is unportable - " + "use gnulib module thrd for portability"); +# endif +#endif + +#if @GNULIB_THRD@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (thrd_yield, void, (void)); +# endif +_GL_CXXALIAS_SYS (thrd_yield, void, (void)); +_GL_CXXALIASWARN (thrd_yield); +#elif defined GNULIB_POSIXCHECK +# undef thrd_yield +# if HAVE_RAW_DECL_THRD_YIELD +_GL_WARN_ON_USE (thrd_yield, "thrd_yield is unportable - " + "use gnulib module thrd for portability"); +# endif +#endif + +#if @GNULIB_THRD@ +# if @REPLACE_THRD_DETACH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define thrd_detach rpl_thrd_detach +# endif +_GL_FUNCDECL_RPL (thrd_detach, int, (thrd_t)); +_GL_CXXALIAS_RPL (thrd_detach, int, (thrd_t)); +# else +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (thrd_detach, int, (thrd_t)); +# endif +_GL_CXXALIAS_SYS (thrd_detach, int, (thrd_t)); +# endif +_GL_CXXALIASWARN (thrd_detach); +#elif defined GNULIB_POSIXCHECK +# undef thrd_detach +# if HAVE_RAW_DECL_THRD_DETACH +_GL_WARN_ON_USE (thrd_detach, "thrd_detach is unportable - " + "use gnulib module thrd for portability"); +# endif +#endif + +#if @GNULIB_THRD@ +# if @REPLACE_THRD_JOIN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define thrd_join rpl_thrd_join +# endif +_GL_FUNCDECL_RPL (thrd_join, int, (thrd_t, int *)); +_GL_CXXALIAS_RPL (thrd_join, int, (thrd_t, int *)); +# else +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (thrd_join, int, (thrd_t, int *)); +# endif +_GL_CXXALIAS_SYS (thrd_join, int, (thrd_t, int *)); +# endif +_GL_CXXALIASWARN (thrd_join); +#elif defined GNULIB_POSIXCHECK +# undef thrd_join +# if HAVE_RAW_DECL_THRD_JOIN +_GL_WARN_ON_USE (thrd_join, "thrd_join is unportable - " + "use gnulib module thrd for portability"); +# endif +#endif + +#if @GNULIB_THRD@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (thrd_exit, _Noreturn void, (int)); +# endif +_GL_CXXALIAS_SYS (thrd_exit, _Noreturn void, (int)); +_GL_CXXALIASWARN (thrd_exit); +#elif defined GNULIB_POSIXCHECK +# undef thrd_exit +# if HAVE_RAW_DECL_THRD_EXIT +_GL_WARN_ON_USE (thrd_exit, "thrd_exit is unportable - " + "use gnulib module thrd for portability"); +# endif +#endif + + +/* =========== ISO C 11 7.26.4 Mutex functions =========== */ + +#if !@HAVE_THREADS_H@ + +/* Types of mutexes. */ +enum +{ + mtx_plain = 0, + mtx_timed = 1, + mtx_recursive = 2 +}; + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# include "windows-mutex.h" +# include "windows-recmutex.h" +# include "windows-timedmutex.h" +# include "windows-timedrecmutex.h" + +typedef struct + { + int type; + union + { + glwthread_mutex_t u_mutex; + glwthread_recmutex_t u_recmutex; + glwthread_timedmutex_t u_timedmutex; + glwthread_timedrecmutex_t u_timedrecmutex; + } + u; + } + mtx_t; + +# else +/* Use POSIX threads. */ + +typedef pthread_mutex_t mtx_t; + +# endif + +#endif + +#if @GNULIB_MTX@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (mtx_init, int, (mtx_t *, int) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mtx_init, int, (mtx_t *, int)); +_GL_CXXALIASWARN (mtx_init); +#elif defined GNULIB_POSIXCHECK +# undef mtx_init +# if HAVE_RAW_DECL_MTX_INIT +_GL_WARN_ON_USE (mtx_init, "mtx_init is unportable - " + "use gnulib module mtx for portability"); +# endif +#endif + +#if @GNULIB_MTX@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (mtx_lock, int, (mtx_t *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mtx_lock, int, (mtx_t *)); +_GL_CXXALIASWARN (mtx_lock); +#elif defined GNULIB_POSIXCHECK +# undef mtx_lock +# if HAVE_RAW_DECL_MTX_LOCK +_GL_WARN_ON_USE (mtx_lock, "mtx_lock is unportable - " + "use gnulib module mtx for portability"); +# endif +#endif + +#if @GNULIB_MTX@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (mtx_trylock, int, (mtx_t *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mtx_trylock, int, (mtx_t *)); +_GL_CXXALIASWARN (mtx_trylock); +#elif defined GNULIB_POSIXCHECK +# undef mtx_trylock +# if HAVE_RAW_DECL_MTX_TRYLOCK +_GL_WARN_ON_USE (mtx_trylock, "mtx_trylock is unportable - " + "use gnulib module mtx for portability"); +# endif +#endif + +#if @GNULIB_MTX@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (mtx_timedlock, int, (mtx_t *, const struct timespec *) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (mtx_timedlock, int, (mtx_t *, const struct timespec *)); +_GL_CXXALIASWARN (mtx_timedlock); +#elif defined GNULIB_POSIXCHECK +# undef mtx_timedlock +# if HAVE_RAW_DECL_MTX_TIMEDLOCK +_GL_WARN_ON_USE (mtx_timedlock, "mtx_timedlock is unportable - " + "use gnulib module mtx for portability"); +# endif +#endif + +#if @GNULIB_MTX@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (mtx_unlock, int, (mtx_t *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mtx_unlock, int, (mtx_t *)); +_GL_CXXALIASWARN (mtx_unlock); +#elif defined GNULIB_POSIXCHECK +# undef mtx_unlock +# if HAVE_RAW_DECL_MTX_UNLOCK +_GL_WARN_ON_USE (mtx_unlock, "mtx_unlock is unportable - " + "use gnulib module mtx for portability"); +# endif +#endif + +#if @GNULIB_MTX@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (mtx_destroy, void, (mtx_t *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mtx_destroy, void, (mtx_t *)); +_GL_CXXALIASWARN (mtx_destroy); +#elif defined GNULIB_POSIXCHECK +# undef mtx_destroy +# if HAVE_RAW_DECL_MTX_DESTROY +_GL_WARN_ON_USE (mtx_destroy, "mtx_destroy is unportable - " + "use gnulib module mtx for portability"); +# endif +#endif + + +/* =========== ISO C 11 7.26.2 Initialization functions =========== */ + +#if !@HAVE_THREADS_H@ + +/* Type that contains a flag for use by call_once. */ +# if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# include "windows-once.h" + +typedef glwthread_once_t once_flag; +# define ONCE_FLAG_INIT GLWTHREAD_ONCE_INIT + +# else +/* Use POSIX threads. */ + +typedef pthread_once_t once_flag; +# define ONCE_FLAG_INIT PTHREAD_ONCE_INIT + +# endif + +#endif + +#if @GNULIB_MTX@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (call_once, void, (once_flag *, void (*) (void)) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (call_once, void, (once_flag *, void (*) (void))); +_GL_CXXALIASWARN (call_once); +#elif defined GNULIB_POSIXCHECK +# undef call_once +# if HAVE_RAW_DECL_CALL_ONCE +_GL_WARN_ON_USE (call_once, "call_once is unportable - " + "use gnulib module mtx for portability"); +# endif +#endif + + +/* =========== ISO C 11 7.26.3 Condition variable functions =========== */ + +#if !@HAVE_THREADS_H@ + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# include "windows-cond.h" + +typedef glwthread_cond_t cnd_t; + +# else +/* Use POSIX threads. */ + +typedef pthread_cond_t cnd_t; + +# endif + +#endif + +#if @GNULIB_CND@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (cnd_init, int, (cnd_t *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (cnd_init, int, (cnd_t *)); +_GL_CXXALIASWARN (cnd_init); +#elif defined GNULIB_POSIXCHECK +# undef cnd_init +# if HAVE_RAW_DECL_CND_INIT +_GL_WARN_ON_USE (cnd_init, "cnd_init is unportable - " + "use gnulib module cnd for portability"); +# endif +#endif + +#if @GNULIB_CND@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (cnd_wait, int, (cnd_t *, mtx_t *) _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (cnd_wait, int, (cnd_t *, mtx_t *)); +_GL_CXXALIASWARN (cnd_wait); +#elif defined GNULIB_POSIXCHECK +# undef cnd_wait +# if HAVE_RAW_DECL_CND_WAIT +_GL_WARN_ON_USE (cnd_wait, "cnd_wait is unportable - " + "use gnulib module cnd for portability"); +# endif +#endif + +#if @GNULIB_CND@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (cnd_timedwait, int, + (cnd_t *, mtx_t *, const struct timespec *) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (cnd_timedwait, int, + (cnd_t *, mtx_t *, const struct timespec *)); +_GL_CXXALIASWARN (cnd_timedwait); +#elif defined GNULIB_POSIXCHECK +# undef cnd_timedwait +# if HAVE_RAW_DECL_CND_TIMEDWAIT +_GL_WARN_ON_USE (cnd_timedwait, "cnd_timedwait is unportable - " + "use gnulib module cnd for portability"); +# endif +#endif + +#if @GNULIB_CND@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (cnd_signal, int, (cnd_t *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (cnd_signal, int, (cnd_t *)); +_GL_CXXALIASWARN (cnd_signal); +#elif defined GNULIB_POSIXCHECK +# undef cnd_signal +# if HAVE_RAW_DECL_CND_SIGNAL +_GL_WARN_ON_USE (cnd_signal, "cnd_signal is unportable - " + "use gnulib module cnd for portability"); +# endif +#endif + +#if @GNULIB_CND@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (cnd_broadcast, int, (cnd_t *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (cnd_broadcast, int, (cnd_t *)); +_GL_CXXALIASWARN (cnd_broadcast); +#elif defined GNULIB_POSIXCHECK +# undef cnd_broadcast +# if HAVE_RAW_DECL_CND_BROADCAST +_GL_WARN_ON_USE (cnd_broadcast, "cnd_broadcast is unportable - " + "use gnulib module cnd for portability"); +# endif +#endif + +#if @GNULIB_CND@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (cnd_destroy, void, (cnd_t *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (cnd_destroy, void, (cnd_t *)); +_GL_CXXALIASWARN (cnd_destroy); +#elif defined GNULIB_POSIXCHECK +# undef cnd_destroy +# if HAVE_RAW_DECL_CND_DESTROY +_GL_WARN_ON_USE (cnd_destroy, "cnd_destroy is unportable - " + "use gnulib module cnd for portability"); +# endif +#endif + + +/* =========== ISO C 11 7.26.6 Thread-specific storage functions =========== */ + +#if !@HAVE_THREADS_H@ + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# include "windows-tls.h" + +typedef glwthread_tls_key_t tss_t; +# define TSS_DTOR_ITERATIONS 0 /* Destructors are currently unsupported. */ + +# else +/* Use POSIX threads. */ + +# include + +typedef pthread_key_t tss_t; + +# endif + +/* Type for the destructor of a thread-specific storage pointer. */ +typedef void (*tss_dtor_t) (void *); + +#endif + +/* AIX 7.1 does not define TSS_DTOR_ITERATIONS. */ +#ifndef TSS_DTOR_ITERATIONS +# ifdef PTHREAD_DESTRUCTOR_ITERATIONS +# define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS +# else + /* IRIX 6.5 does not define PTHREAD_DESTRUCTOR_ITERATIONS. + This value is a wild guess. */ +# define TSS_DTOR_ITERATIONS 1 +# endif +#endif + +#if @GNULIB_TSS@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (tss_create, int, (tss_t *, tss_dtor_t) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (tss_create, int, (tss_t *, tss_dtor_t)); +_GL_CXXALIASWARN (tss_create); +#elif defined GNULIB_POSIXCHECK +# undef tss_create +# if HAVE_RAW_DECL_TSS_CREATE +_GL_WARN_ON_USE (tss_create, "tss_create is unportable - " + "use gnulib module tss for portability"); +# endif +#endif + +#if @GNULIB_TSS@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (tss_set, int, (tss_t, void *)); +# endif +_GL_CXXALIAS_SYS (tss_set, int, (tss_t, void *)); +_GL_CXXALIASWARN (tss_set); +#elif defined GNULIB_POSIXCHECK +# undef tss_set +# if HAVE_RAW_DECL_TSS_SET +_GL_WARN_ON_USE (tss_set, "tss_set is unportable - " + "use gnulib module tss for portability"); +# endif +#endif + +#if @GNULIB_TSS@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (tss_get, void *, (tss_t)); +# endif +_GL_CXXALIAS_SYS (tss_get, void *, (tss_t)); +_GL_CXXALIASWARN (tss_get); +#elif defined GNULIB_POSIXCHECK +# undef tss_get +# if HAVE_RAW_DECL_TSS_GET +_GL_WARN_ON_USE (tss_get, "tss_get is unportable - " + "use gnulib module tss for portability"); +# endif +#endif + +#if @GNULIB_TSS@ +# if !@HAVE_THREADS_H@ +_GL_FUNCDECL_SYS (tss_delete, void, (tss_t)); +# endif +_GL_CXXALIAS_SYS (tss_delete, void, (tss_t)); +_GL_CXXALIASWARN (tss_delete); +#elif defined GNULIB_POSIXCHECK +# undef tss_delete +# if HAVE_RAW_DECL_TSS_DELETE +_GL_WARN_ON_USE (tss_delete, "tss_delete is unportable - " + "use gnulib module tss for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_THREADS_H */ +#endif /* _@GUARD_PREFIX@_THREADS_H */ diff --git a/m4/threads.m4 b/m4/threads.m4 new file mode 100644 index 0000000..3cb3ae1 --- /dev/null +++ b/m4/threads.m4 @@ -0,0 +1,126 @@ +# threads.m4 serial 1 +dnl Copyright (C) 2019 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_THREADS_H], +[ + AC_REQUIRE([gl_THREADS_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([gl_THREADLIB_BODY]) + AC_REQUIRE([gl_YIELD]) + + gl_CHECK_NEXT_HEADERS([threads.h]) + if test $ac_cv_header_threads_h = yes; then + HAVE_THREADS_H=1 + else + HAVE_THREADS_H=0 + fi + AC_SUBST([HAVE_THREADS_H]) + + if test $HAVE_THREADS_H = 1; then + dnl AIX 7.1..7.2 defines thrd_start_t incorrectly, namely as + dnl 'void * (*) (void *)' instead of 'int (*) (void *)'. + AC_CACHE_CHECK([whether thrd_start_t is correct], + [gl_cv_thrd_start_t_correct], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #ifdef __cplusplus + extern "C" { + #endif + extern void foo (thrd_start_t); + extern void foo (int (*) (void *)); + #ifdef __cplusplus + } + #endif + ]], [[]])], + [gl_cv_thrd_start_t_correct=yes], + [gl_cv_thrd_start_t_correct=no]) + ]) + if test $gl_cv_thrd_start_t_correct != yes; then + BROKEN_THRD_START_T=1 + fi + fi + + case "$host_os" in + mingw*) + LIBSTDTHREAD= + LTLIBSTDTHREAD= + ;; + *) + if test $ac_cv_header_threads_h = yes; then + dnl glibc >= 2.29 has thrd_create in libpthread. + dnl FreeBSD >= 10 has thrd_create in libstdthreads. + dnl AIX >= 7.1 and Solaris >= 11.4 have thrd_create in libc. + AC_CHECK_FUNCS([thrd_create]) + if test $ac_cv_func_thrd_create = yes; then + LIBSTDTHREAD= + LTLIBSTDTHREAD= + else + AC_CHECK_LIB([stdthreads], [thrd_create], [ + LIBSTDTHREAD='-lstdthreads' + LTLIBSTDTHREAD='-lstdthreads' + ], [ + dnl Guess that thrd_create is in libpthread. + LIBSTDTHREAD="$LIBMULTITHREAD" + LTLIBSTDTHREAD="$LTLIBMULTITHREAD" + ]) + fi + else + dnl Libraries needed by thrd.c, mtx.c, cnd.c, tss.c. + LIBSTDTHREAD="$LIBMULTITHREAD $YIELD_LIB" + LTLIBSTDTHREAD="$LTLIBMULTITHREAD $YIELD_LIB" + fi + ;; + esac + AC_SUBST([LIBSTDTHREAD]) + AC_SUBST([LTLIBSTDTHREAD]) + + AH_VERBATIM([thread_local], +[/* The _Thread_local keyword of C11. */ +#ifndef _Thread_local +# if defined __GNUC__ +# define _Thread_local __thread +# elif defined _MSC_VER +# define _Thread_local __declspec (thread) +# endif +#endif +]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use, and which is not + dnl guaranteed by C89. + gl_WARN_ON_USE_PREPARE([[#include + ]], [call_once + cnd_broadcast cnd_destroy cnd_init cnd_signal cnd_timedwait cnd_wait + mtx_destroy mtx_init mtx_lock mtx_timedlock mtx_trylock mtx_unlock + thrd_create thrd_current thrd_detach thrd_equal thrd_exit thrd_join + thrd_sleep thrd_yield + tss_create tss_delete tss_get tss_set]) +]) + +AC_DEFUN([gl_THREADS_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_THREADS_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) + dnl Define it also as a C macro, for the benefit of the unit tests. + gl_MODULE_INDICATOR_FOR_TESTS([$1]) +]) + +AC_DEFUN([gl_THREADS_H_DEFAULTS], +[ + GNULIB_CND=0; AC_SUBST([GNULIB_CND]) + GNULIB_MTX=0; AC_SUBST([GNULIB_MTX]) + GNULIB_THRD=0; AC_SUBST([GNULIB_THRD]) + GNULIB_TSS=0; AC_SUBST([GNULIB_TSS]) + dnl Assume proper GNU behavior unless another module says otherwise. + BROKEN_THRD_START_T=0; AC_SUBST([BROKEN_THRD_START_T]) + REPLACE_THRD_CREATE=0; AC_SUBST([REPLACE_THRD_CREATE]) + REPLACE_THRD_CURRENT=0; AC_SUBST([REPLACE_THRD_CURRENT]) + REPLACE_THRD_DETACH=0; AC_SUBST([REPLACE_THRD_DETACH]) + REPLACE_THRD_EQUAL=0; AC_SUBST([REPLACE_THRD_EQUAL]) + REPLACE_THRD_JOIN=0; AC_SUBST([REPLACE_THRD_JOIN]) +]) diff --git a/m4/yield.m4 b/m4/yield.m4 index 13f6f20..59c8c38 100644 --- a/m4/yield.m4 +++ b/m4/yield.m4 @@ -1,4 +1,4 @@ -# yield.m4 serial 2 +# yield.m4 serial 3 dnl Copyright (C) 2005-2019 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -10,7 +10,7 @@ AC_DEFUN([gl_YIELD], dnl On some systems, sched_yield is in librt, rather than in libpthread. YIELD_LIB= if test $gl_threads_api = posix; then - dnl Solaris has sched_yield in librt, not in libpthread or libc. + dnl Solaris 7...10 has sched_yield in librt, not in libpthread or libc. AC_CHECK_LIB([rt], [sched_yield], [YIELD_LIB=-lrt], [dnl Solaris 2.5.1, 2.6 has sched_yield in libposix4, not librt. AC_CHECK_LIB([posix4], [sched_yield], [YIELD_LIB=-lposix4])]) diff --git a/modules/threads-h b/modules/threads-h new file mode 100644 index 0000000..238955c --- /dev/null +++ b/modules/threads-h @@ -0,0 +1,73 @@ +Description: +An ISO C 11 compatible . + +Files: +lib/threads.in.h +lib/windows-thread.h +lib/windows-mutex.h +lib/windows-recmutex.h +lib/windows-timedmutex.h +lib/windows-timedrecmutex.h +lib/windows-once.h +lib/windows-cond.h +lib/windows-tls.h +lib/windows-spinlock.h +m4/threads.m4 +m4/threadlib.m4 +m4/yield.m4 +build-aux/config.rpath + +Depends-on: +include_next +snippet/c++defs +snippet/_Noreturn +snippet/arg-nonnull +snippet/warn-on-use +time +havelib + +configure.ac-early: +gl_THREADLIB_EARLY + +configure.ac: +AC_REQUIRE([gl_THREADS_H]) + +Makefile.am: +BUILT_SOURCES += threads.h + +# We need the following in order to create when the system +# doesn't have one. +threads.h: threads.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|g' \ + -e 's|@''HAVE_THREADS_H''@|$(HAVE_THREADS_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_THREADS_H''@|$(NEXT_THREADS_H)|g' \ + -e 's/@''GNULIB_CND''@/$(GNULIB_CND)/g' \ + -e 's/@''GNULIB_MTX''@/$(GNULIB_MTX)/g' \ + -e 's/@''GNULIB_THRD''@/$(GNULIB_THRD)/g' \ + -e 's/@''GNULIB_TSS''@/$(GNULIB_TSS)/g' \ + -e 's|@''BROKEN_THRD_START_T''@|$(BROKEN_THRD_START_T)|g' \ + -e 's|@''REPLACE_THRD_CREATE''@|$(REPLACE_THRD_CREATE)|g' \ + -e 's|@''REPLACE_THRD_CURRENT''@|$(REPLACE_THRD_CURRENT)|g' \ + -e 's|@''REPLACE_THRD_DETACH''@|$(REPLACE_THRD_DETACH)|g' \ + -e 's|@''REPLACE_THRD_EQUAL''@|$(REPLACE_THRD_EQUAL)|g' \ + -e 's|@''REPLACE_THRD_JOIN''@|$(REPLACE_THRD_JOIN)|g' \ + < $(srcdir)/threads.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += threads.h threads.h-t + +Include: + + +Link: + +License: +LGPLv2+ + +Maintainer: +all diff --git a/modules/yield b/modules/yield index 24ffcdd..71e00ea 100644 --- a/modules/yield +++ b/modules/yield @@ -9,7 +9,7 @@ Depends-on: threadlib configure.ac: -gl_YIELD +AC_REQUIRE([gl_YIELD]) Makefile.am: lib_SOURCES += glthread/yield.h -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0017-threads-h-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0017-threads-h-Add-tests.patch" >From bf6dd504cc2fcd8481ad5787999b845a3c00f54d Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:25:58 +0200 Subject: [PATCH 17/26] threads-h: Add tests. * tests/test-threads.c: New file. * modules/threads-h-tests: New file. * tests/test-threads-c++.cc: New file. * modules/threads-h-c++-tests: New file. --- ChangeLog | 8 +++++ modules/threads-h-c++-tests | 19 ++++++++++++ modules/threads-h-tests | 12 ++++++++ tests/test-threads-c++.cc | 73 +++++++++++++++++++++++++++++++++++++++++++++ tests/test-threads.c | 65 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 modules/threads-h-c++-tests create mode 100644 modules/threads-h-tests create mode 100644 tests/test-threads-c++.cc create mode 100644 tests/test-threads.c diff --git a/ChangeLog b/ChangeLog index 22b942b..b536bcb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2019-06-20 Bruno Haible + threads-h: Add tests. + * tests/test-threads.c: New file. + * modules/threads-h-tests: New file. + * tests/test-threads-c++.cc: New file. + * modules/threads-h-c++-tests: New file. + +2019-06-20 Bruno Haible + threads-h: New module. * lib/threads.in.h: New file. * m4/threads.m4: New file. diff --git a/modules/threads-h-c++-tests b/modules/threads-h-c++-tests new file mode 100644 index 0000000..8553bd6 --- /dev/null +++ b/modules/threads-h-c++-tests @@ -0,0 +1,19 @@ +Files: +tests/test-threads-c++.cc +tests/signature.h + +Status: +c++-test + +Depends-on: +ansi-c++-opt + +configure.ac: + +Makefile.am: +if ANSICXX +TESTS += test-threads-c++ +check_PROGRAMS += test-threads-c++ +test_threads_c___SOURCES = test-threads-c++.cc +test_threads_c___LDADD = $(LDADD) @LIBSTDTHREAD@ +endif diff --git a/modules/threads-h-tests b/modules/threads-h-tests new file mode 100644 index 0000000..e4f399d --- /dev/null +++ b/modules/threads-h-tests @@ -0,0 +1,12 @@ +Files: +tests/test-threads.c + +Depends-on: +threads-h-c++-tests + +configure.ac: + +Makefile.am: +TESTS += test-threads +check_PROGRAMS += test-threads +test_threads_LDADD = $(LDADD) @LIBSTDTHREAD@ diff --git a/tests/test-threads-c++.cc b/tests/test-threads-c++.cc new file mode 100644 index 0000000..66877d4 --- /dev/null +++ b/tests/test-threads-c++.cc @@ -0,0 +1,73 @@ +/* Test of substitute in C++ mode. + Copyright (C) 2019 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 , 2019. */ + +#define GNULIB_NAMESPACE gnulib +#include + +#include + +#include "signature.h" + + +#if GNULIB_TEST_THRD +SIGNATURE_CHECK (GNULIB_NAMESPACE::thrd_create, int, + (thrd_t *, thrd_start_t, void *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::thrd_current, thrd_t, (void)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::thrd_equal, int, (thrd_t, thrd_t)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::thrd_sleep, int, + (const struct timespec *, struct timespec *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::thrd_yield, void, (void)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::thrd_detach, int, (thrd_t)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::thrd_join, int, (thrd_t, int *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::thrd_exit, _Noreturn void, (int)); +#endif + +#if GNULIB_TEST_MTX +SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_init, int, (mtx *, int)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_lock, int, (mtx *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_trylock, int, (mtx *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_timedlock, int, + (mtx *, const struct timespec *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_unlock, int, (mtx *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_destroy, void, (mtx *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::call_once, void, + (once_flag *, void (*) (void))); +#endif + +#if GNULIB_TEST_CND +SIGNATURE_CHECK (GNULIB_NAMESPACE::cnd_init, int, (cnd_t *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::cnd_wait, int, (cnd_t *, mtx_t *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::cnd_timedwait, int, + (cnd_t *, mtx_t *, const struct timespec *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::cnd_signal, int, (cnd_t *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::cnd_broadcast, int, (cnd_t *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::cnd_destroy, void, (cnd_t *)); +#endif + +#if GNULIB_TEST_TSS +SIGNATURE_CHECK (GNULIB_NAMESPACE::tss_create, int, (tss_t *, tss_dtor_t)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::tss_set, int, (tss_t, void *)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::tss_get, void *, (tss_t)); +SIGNATURE_CHECK (GNULIB_NAMESPACE::tss_delete, void, (tss_t)); +#endif + + +int +main () +{ +} diff --git a/tests/test-threads.c b/tests/test-threads.c new file mode 100644 index 0000000..39a0f3c --- /dev/null +++ b/tests/test-threads.c @@ -0,0 +1,65 @@ +/* Test of substitute. + Copyright (C) 2019 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 , 2019. */ + +#include + +#include + +/* Check that thread_local is defined. */ +#ifndef thread_local +"oops" +#endif + +/* Check that ONCE_FLAG_INIT is defined. */ +#ifndef ONCE_FLAG_INIT +"oops1" +#endif +once_flag a = ONCE_FLAG_INIT; + +/* Check that TSS_DTOR_ITERATIONS is defined. */ +#ifndef TSS_DTOR_ITERATIONS +"oops2" +#endif +int b = TSS_DTOR_ITERATIONS; + +int +main (void) +{ + /* Ensure no overlap in thrd_*. */ + switch (0) + { + case thrd_success: + case thrd_timedout: + case thrd_busy: + case thrd_nomem: + case thrd_error: + ; + } + + /* Ensure no overlap among valid types for mtx_init. */ + switch (0) + { + case mtx_plain: + case mtx_timed: + case mtx_plain | mtx_recursive: + case mtx_timed | mtx_recursive: + ; + } + + return 0; +} -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0018-thrd-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0018-thrd-New-module.patch" >From 3696a934e60b3c390bc217bf3273e0c5399e5fd4 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:26:31 +0200 Subject: [PATCH 18/26] thrd: New module. * lib/thrd.c: New file. * m4/thrd.m4: New file. * modules/thrd: New file. * doc/posix-functions/thrd_current.texi: Mention the new module. * doc/posix-functions/thrd_detach.texi: Likewise. * doc/posix-functions/thrd_equal.texi: Likewise. * doc/posix-functions/thrd_exit.texi: Likewise. * doc/posix-functions/thrd_sleep.texi: Likewise. * doc/posix-functions/thrd_yield.texi: Likewise. * doc/posix-functions/thrd_create.texi: Mention the new module and the AIX bug. * doc/posix-functions/thrd_join.texi: Mention the new module and the AIX and Solaris bugs. --- ChangeLog | 17 ++ doc/posix-functions/thrd_create.texi | 11 +- doc/posix-functions/thrd_current.texi | 8 +- doc/posix-functions/thrd_detach.texi | 8 +- doc/posix-functions/thrd_equal.texi | 8 +- doc/posix-functions/thrd_exit.texi | 8 +- doc/posix-functions/thrd_join.texi | 14 +- doc/posix-functions/thrd_sleep.texi | 8 +- doc/posix-functions/thrd_yield.texi | 8 +- lib/thrd.c | 427 ++++++++++++++++++++++++++++++++++ m4/thrd.m4 | 63 +++++ modules/thrd | 33 +++ 12 files changed, 581 insertions(+), 32 deletions(-) create mode 100644 lib/thrd.c create mode 100644 m4/thrd.m4 create mode 100644 modules/thrd diff --git a/ChangeLog b/ChangeLog index b536bcb..5d96988 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,22 @@ 2019-06-20 Bruno Haible + thrd: New module. + * lib/thrd.c: New file. + * m4/thrd.m4: New file. + * modules/thrd: New file. + * doc/posix-functions/thrd_current.texi: Mention the new module. + * doc/posix-functions/thrd_detach.texi: Likewise. + * doc/posix-functions/thrd_equal.texi: Likewise. + * doc/posix-functions/thrd_exit.texi: Likewise. + * doc/posix-functions/thrd_sleep.texi: Likewise. + * doc/posix-functions/thrd_yield.texi: Likewise. + * doc/posix-functions/thrd_create.texi: Mention the new module and the + AIX bug. + * doc/posix-functions/thrd_join.texi: Mention the new module and the + AIX and Solaris bugs. + +2019-06-20 Bruno Haible + threads-h: Add tests. * tests/test-threads.c: New file. * modules/threads-h-tests: New file. diff --git a/doc/posix-functions/thrd_create.texi b/doc/posix-functions/thrd_create.texi index eb3fd50..9fe35f4 100644 --- a/doc/posix-functions/thrd_create.texi +++ b/doc/posix-functions/thrd_create.texi @@ -10,15 +10,18 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread-Management.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: thrd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. +@item +This function uses an incorrectly defined @code{thrd_start_t} on some platforms: +AIX 7.2. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/thrd_current.texi b/doc/posix-functions/thrd_current.texi index 03f33a5..ea81185 100644 --- a/doc/posix-functions/thrd_current.texi +++ b/doc/posix-functions/thrd_current.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread-Management.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: thrd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/thrd_detach.texi b/doc/posix-functions/thrd_detach.texi index 3cfb318..bb8f6c3 100644 --- a/doc/posix-functions/thrd_detach.texi +++ b/doc/posix-functions/thrd_detach.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread-Management.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: thrd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/thrd_equal.texi b/doc/posix-functions/thrd_equal.texi index 58f5a02..18555024 100644 --- a/doc/posix-functions/thrd_equal.texi +++ b/doc/posix-functions/thrd_equal.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread-Management.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: thrd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/thrd_exit.texi b/doc/posix-functions/thrd_exit.texi index a2683b6..75ae888 100644 --- a/doc/posix-functions/thrd_exit.texi +++ b/doc/posix-functions/thrd_exit.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread-Management.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: thrd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/thrd_join.texi b/doc/posix-functions/thrd_join.texi index 2199a8f..51b2ec9 100644 --- a/doc/posix-functions/thrd_join.texi +++ b/doc/posix-functions/thrd_join.texi @@ -10,15 +10,21 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread-Management.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: thrd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. +@item +This function never stores an exit code on some platforms: +AIX 7.2. +@item +This function crashes when the second argument is NULL on some platforms: +Solaris 11.4. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/thrd_sleep.texi b/doc/posix-functions/thrd_sleep.texi index afdb3ea..5e02eb1 100644 --- a/doc/posix-functions/thrd_sleep.texi +++ b/doc/posix-functions/thrd_sleep.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread-Management.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: thrd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/thrd_yield.texi b/doc/posix-functions/thrd_yield.texi index a787a69..dde2a71 100644 --- a/doc/posix-functions/thrd_yield.texi +++ b/doc/posix-functions/thrd_yield.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread-Management.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: thrd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/lib/thrd.c b/lib/thrd.c new file mode 100644 index 0000000..e8f29bc --- /dev/null +++ b/lib/thrd.c @@ -0,0 +1,427 @@ +/* Creating and controlling ISO C 11 threads. + Copyright (C) 2005-2019 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 2, 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 , 2005, 2019. + Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */ + +#include + +#include + +#include + +#if HAVE_THREADS_H +/* Provide workarounds. */ + +# if BROKEN_THRD_START_T + +# undef thrd_t + +/* AIX 7.1..7.2 defines thrd_start_t incorrectly, namely as + 'void * (*) (void *)' instead of 'int (*) (void *)'. + As a consequence, its thrd_join function never stores an exit code. */ + +/* The Thread-Specific Storage (TSS) key that allows to access each thread's + 'struct thrd_with_exitcode *' pointer. */ +static tss_t thrd_with_exitcode_key; + +/* Initializes thrd_with_exitcode_key. + This function must only be called once. */ +static void +do_init_thrd_with_exitcode_key (void) +{ + if (tss_create (&thrd_with_exitcode_key, NULL) != thrd_success) + abort (); +} + +/* Initializes thrd_with_exitcode_key. */ +static void +init_thrd_with_exitcode_key (void) +{ + static once_flag once = ONCE_FLAG_INIT; + call_once (&once, do_init_thrd_with_exitcode_key); +} + +typedef union + { + struct thrd_with_exitcode t; + struct + { + thrd_t tid; /* reserve memory for t.tid */ + int detached; /* reserve memory for t.detached */ + thrd_start_t mainfunc; + void *arg; + } a; + } + main_arg_t; + +static void * +thrd_main_func (void *pmarg) +{ + /* Unpack the object that combines mainfunc and arg. */ + main_arg_t *main_arg = (main_arg_t *) pmarg; + thrd_start_t mainfunc = main_arg->a.mainfunc; + void *arg = main_arg->a.arg; + + if (tss_set (thrd_with_exitcode_key, &main_arg->t) != thrd_success) + abort (); + + /* Execute mainfunc, with arg as argument. */ + { + int exitcode = mainfunc (arg); + /* Store the exitcode, for use by thrd_join(). */ + main_arg->t.exitcode = exitcode; + if (main_arg->t.detached) + { + /* Clean up the thread, like thrd_join would do. */ + free (&main_arg->t); + } + return NULL; + } +} + +int +rpl_thrd_create (rpl_thrd_t *threadp, thrd_start_t mainfunc, void *arg) +# undef thrd_create +{ + init_thrd_with_exitcode_key (); + { + /* Combine mainfunc and arg in a single object. + A stack-allocated object does not work, because it would be out of + existence when thrd_create returns before pthread_main_func is + entered. So, allocate it in the heap. */ + main_arg_t *main_arg = (main_arg_t *) malloc (sizeof (main_arg_t)); + if (main_arg == NULL) + return thrd_nomem; + main_arg->a.mainfunc = mainfunc; + main_arg->a.arg = arg; + main_arg->t.detached = 0; + { + int err = + thrd_create ((thrd_t *) &main_arg->t.tid, thrd_main_func, main_arg); + if (err == thrd_success) + *threadp = &main_arg->t; + else + free (main_arg); + return err; + } + } +} + +rpl_thrd_t +rpl_thrd_current (void) +# undef thrd_current +{ + init_thrd_with_exitcode_key (); + { + rpl_thrd_t thread = + (struct thrd_with_exitcode *) tss_get (thrd_with_exitcode_key); + if (thread == NULL) + { + /* This happens only in threads that have not been created through + thrd_create(), such as the main thread. */ + for (;;) + { + thread = + (struct thrd_with_exitcode *) + malloc (sizeof (struct thrd_with_exitcode)); + if (thread != NULL) + break; + /* Memory allocation failed. There is not much we can do. Have to + busy-loop, waiting for the availability of memory. */ + { + struct timespec ts; + ts.tv_sec = 1; + ts.tv_nsec = 0; + thrd_sleep (&ts, NULL); + } + } + thread->tid = thrd_current (); + thread->detached = 0; /* This can lead to a memory leak. */ + thread->exitcode = 0; /* just to be deterministic */ + if (tss_set (thrd_with_exitcode_key, thread) != thrd_success) + abort (); + } + return thread; + } +} + +int +rpl_thrd_equal (rpl_thrd_t thread1, rpl_thrd_t thread2) +{ + return thread1 == thread2; +} + +int +rpl_thrd_detach (rpl_thrd_t thread) +# undef thrd_detach +{ + if (thread->detached) + return thrd_error; + { + int err = + thrd_detach (thread == rpl_thrd_current () + ? /* thread->tid may not be initialized at this point. */ + thrd_current () + : thread->tid); + if (err == thrd_success) + thread->detached = 1; + return err; + } +} + +int +rpl_thrd_join (rpl_thrd_t thread, int *exitcodep) +# undef thrd_join +{ + if (thread == rpl_thrd_current () || thread->detached) + return thrd_error; + { + int err = thrd_join (thread->tid, NULL); + if (err == thrd_success) + { + if (exitcodep != NULL) + *exitcodep = thread->exitcode; + free (thread); + } + return err; + } +} + +# endif + +# if BROKEN_THRD_JOIN + +/* On Solaris 11.4, thrd_join crashes when the second argument is NULL. */ +int +rpl_thrd_join (thrd_t thread, int *exitcodep) +# undef thrd_join +{ + int exitcode; + int err = thrd_join (thread, &exitcode); + if (err == 0 && exitcodep != NULL) + *exitcodep = exitcode; + return err; +} + +# endif + +#else + +# include +# include + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# else +/* Use POSIX threads. */ + +# include +# include + +# endif + +/* The main functions passed to thrd_create and + pthread_create/glwthread_thread_create have different return types: + 'int' vs. 'void *'. */ + +struct pthread_main_arg_t +{ + thrd_start_t mainfunc; + void *arg; +}; + +static void * +pthread_main_func (void *pmarg) +{ + /* Unpack the object that combines mainfunc and arg. */ + struct pthread_main_arg_t *pthread_main_arg = + (struct pthread_main_arg_t *) pmarg; + thrd_start_t mainfunc = pthread_main_arg->mainfunc; + void *arg = pthread_main_arg->arg; + + /* Free it. */ + free (pmarg); + + /* Execute mainfunc, with arg as argument. */ + { + int exitcode = mainfunc (arg); + return (void *) (intptr_t) exitcode; + } +} + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +int +thrd_create (thrd_t *threadp, thrd_start_t mainfunc, void *arg) +{ + /* Combine mainfunc and arg in a single object. + A stack-allocated object does not work, because it would be out of + existence when thrd_create returns before pthread_main_func is + entered. So, allocate it in the heap. */ + struct pthread_main_arg_t *pthread_main_arg = + (struct pthread_main_arg_t *) malloc (sizeof (struct pthread_main_arg_t)); + if (pthread_main_arg == NULL) + return thrd_nomem; + pthread_main_arg->mainfunc = mainfunc; + pthread_main_arg->arg = arg; + + { + int err = glwthread_thread_create (threadp, + pthread_main_func, pthread_main_arg); + if (err != 0) + free (pthread_main_arg); + return (err == 0 ? thrd_success : + err == ENOMEM /* || err == EAGAIN */ ? thrd_nomem : + thrd_error); + } +} + +thrd_t +thrd_current (void) +{ + return glwthread_thread_self (); +} + +int +thrd_equal (thrd_t thread1, thrd_t thread2) +{ + return thread1 == thread2; +} + +void +thrd_yield (void) +{ + Sleep (0); +} + +int +thrd_detach (thrd_t thread) +{ + int err = glwthread_thread_detach (thread); + return (err == 0 ? thrd_success : thrd_error); +} + +int +thrd_join (thrd_t thread, int *exitcodep) +{ + void *exitptr; + int err = glwthread_thread_join (thread, &exitptr); + if (err == 0) + { + if (exitcodep != NULL) + *exitcodep = (int) (intptr_t) exitptr; + return thrd_success; + } + else + return thrd_error; +} + +_Noreturn void +thrd_exit (int exitcode) +{ + glwthread_thread_exit ((void *) (intptr_t) exitcode); +} + +# else +/* Use POSIX threads. */ + +int +thrd_create (thrd_t *threadp, thrd_start_t mainfunc, void *arg) +{ + /* Combine mainfunc and arg in a single object. + A stack-allocated object does not work, because it would be out of + existence when thrd_create returns before pthread_main_func is + entered. So, allocate it in the heap. */ + struct pthread_main_arg_t *pthread_main_arg = + (struct pthread_main_arg_t *) malloc (sizeof (struct pthread_main_arg_t)); + if (pthread_main_arg == NULL) + return thrd_nomem; + pthread_main_arg->mainfunc = mainfunc; + pthread_main_arg->arg = arg; + + { + int err = pthread_create (threadp, NULL, + pthread_main_func, pthread_main_arg); + if (err != 0) + free (pthread_main_arg); + return (err == 0 ? thrd_success : + err == ENOMEM /* || err == EAGAIN */ ? thrd_nomem : + thrd_error); + } +} + +thrd_t +thrd_current (void) +{ + return pthread_self (); +} + +int +thrd_equal (thrd_t thread1, thrd_t thread2) +{ + return pthread_equal (thread1, thread2); +} + +void +thrd_yield (void) +{ + sched_yield (); +} + +int +thrd_detach (thrd_t thread) +{ + int err = pthread_detach (thread); + return (err == 0 ? thrd_success : thrd_error); +} + +int +thrd_join (thrd_t thread, int *exitcodep) +{ + void *exitptr; + int err = pthread_join (thread, &exitptr); + if (err == 0) + { + if (exitcodep != NULL) + *exitcodep = (int) (intptr_t) exitptr; + return thrd_success; + } + else + return thrd_error; +} + +_Noreturn void +thrd_exit (int exitcode) +{ + pthread_exit ((void *) (intptr_t) exitcode); +} + +# endif + +int +thrd_sleep (const struct timespec *duration, struct timespec *remaining) +{ + int ret = nanosleep (duration, remaining); + return (ret == 0 ? 0 : errno == EINTR ? -1 : -2); +} + +#endif diff --git a/m4/thrd.m4 b/m4/thrd.m4 new file mode 100644 index 0000000..6e9c8f4 --- /dev/null +++ b/m4/thrd.m4 @@ -0,0 +1,63 @@ +# thrd.m4 serial 1 +dnl Copyright (C) 2019 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_THRD_JOIN], +[ + AC_REQUIRE([gl_THREADS_H]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + if test $ac_cv_header_threads_h = yes; then + if test $BROKEN_THRD_START_T = 1; then + REPLACE_THRD_CREATE=1 + REPLACE_THRD_CURRENT=1 + REPLACE_THRD_DETACH=1 + REPLACE_THRD_EQUAL=1 + REPLACE_THRD_JOIN=1 + AC_DEFINE([BROKEN_THRD_START_T], [1], + [Define if the thrd_start_t type is not as described in ISO C 11.]) + fi + + dnl On Solaris 11.4, thrd_join crashes when the second argument is NULL. + AC_CACHE_CHECK([whether thrd_join works], + [gl_cv_func_thrd_join_works], + [save_LIBS="$LIBS" + LIBS="$LIBS $LIBSTDTHREAD" + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + static int func (void *arg) + { + return (arg != NULL); + } + ]], + [[thrd_t thread; + if (thrd_create (&thread, func, NULL) != thrd_success) + return 1; + if (thrd_join (thread, NULL) != thrd_success) + return 2; + return 0; + ]])], + [gl_cv_func_thrd_join_works=yes], + [gl_cv_func_thrd_join_works=no], + [case "$host_os" in + # Only Solaris is known to be broken. + solaris*) gl_cv_func_thrd_join_works="guessing no" ;; + *) gl_cv_func_thrd_join_works="guessing yes" ;; + esac + ]) + LIBS="$save_LIBS" + ]) + case "$gl_cv_func_thrd_join_works" in + *yes) ;; + *) + REPLACE_THRD_JOIN=1 + AC_DEFINE([BROKEN_THRD_JOIN], [1], + [Define if the thrd_join function does not behave as in ISO C 11.]) + ;; + esac + fi +]) diff --git a/modules/thrd b/modules/thrd new file mode 100644 index 0000000..3fd6063 --- /dev/null +++ b/modules/thrd @@ -0,0 +1,33 @@ +Description: +ISO C 11 thread functions. + +Files: +lib/thrd.c +m4/thrd.m4 + +Depends-on: +threads-h +windows-thread +nanosleep + +configure.ac: +AC_REQUIRE([gl_THREADS_H]) +gl_FUNC_THRD_JOIN +if test $HAVE_THREADS_H = 0 || test $REPLACE_THRD_CREATE = 1 || test $REPLACE_THRD_JOIN = 1; then + AC_LIBOBJ([thrd]) +fi +gl_THREADS_MODULE_INDICATOR([thrd]) + +Makefile.am: + +Include: + + +Link: +$(LTLIBSTDTHREAD) when linking with libtool, $(LIBSTDTHREAD) otherwise + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0019-mtx-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0019-mtx-New-module.patch" >From 6b4c64f06648b95f942d5428991979b9d8f2c69b Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:30:11 +0200 Subject: [PATCH 19/26] mtx: New module. * lib/mtx.c: New file. * modules/mtx: New file. * doc/posix-functions/call_once.texi: Mention the new module. * doc/posix-functions/mtx_init.texi: Likewise. * doc/posix-functions/mtx_lock.texi: Likewise. * doc/posix-functions/mtx_trylock.texi: Likewise. * doc/posix-functions/mtx_timedlock.texi: Likewise. * doc/posix-functions/mtx_unlock.texi: Likewise. * doc/posix-functions/mtx_destroy.texi: Likewise. --- ChangeLog | 13 ++ doc/posix-functions/call_once.texi | 8 +- doc/posix-functions/mtx_destroy.texi | 8 +- doc/posix-functions/mtx_init.texi | 8 +- doc/posix-functions/mtx_lock.texi | 8 +- doc/posix-functions/mtx_timedlock.texi | 8 +- doc/posix-functions/mtx_trylock.texi | 8 +- doc/posix-functions/mtx_unlock.texi | 8 +- lib/mtx.c | 288 +++++++++++++++++++++++++++++++++ modules/mtx | 34 ++++ 10 files changed, 363 insertions(+), 28 deletions(-) create mode 100644 lib/mtx.c create mode 100644 modules/mtx diff --git a/ChangeLog b/ChangeLog index 5d96988..0e73bd6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2019-06-20 Bruno Haible + mtx: New module. + * lib/mtx.c: New file. + * modules/mtx: New file. + * doc/posix-functions/call_once.texi: Mention the new module. + * doc/posix-functions/mtx_init.texi: Likewise. + * doc/posix-functions/mtx_lock.texi: Likewise. + * doc/posix-functions/mtx_trylock.texi: Likewise. + * doc/posix-functions/mtx_timedlock.texi: Likewise. + * doc/posix-functions/mtx_unlock.texi: Likewise. + * doc/posix-functions/mtx_destroy.texi: Likewise. + +2019-06-20 Bruno Haible + thrd: New module. * lib/thrd.c: New file. * m4/thrd.m4: New file. diff --git a/doc/posix-functions/call_once.texi b/doc/posix-functions/call_once.texi index c3b10fb..84b9dfe 100644 --- a/doc/posix-functions/call_once.texi +++ b/doc/posix-functions/call_once.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/Call-Once.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: mtx Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/mtx_destroy.texi b/doc/posix-functions/mtx_destroy.texi index ec8fe87..fda5048 100644 --- a/doc/posix-functions/mtx_destroy.texi +++ b/doc/posix-functions/mtx_destroy.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Mutexes.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: mtx Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/mtx_init.texi b/doc/posix-functions/mtx_init.texi index 867f6a2..297ad34 100644 --- a/doc/posix-functions/mtx_init.texi +++ b/doc/posix-functions/mtx_init.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Mutexes.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: mtx Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/mtx_lock.texi b/doc/posix-functions/mtx_lock.texi index 8e43992..958589d 100644 --- a/doc/posix-functions/mtx_lock.texi +++ b/doc/posix-functions/mtx_lock.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Mutexes.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: mtx Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/mtx_timedlock.texi b/doc/posix-functions/mtx_timedlock.texi index 31e766e..d42f1ae 100644 --- a/doc/posix-functions/mtx_timedlock.texi +++ b/doc/posix-functions/mtx_timedlock.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Mutexes.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: mtx Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/mtx_trylock.texi b/doc/posix-functions/mtx_trylock.texi index 26c38d6..e5beb64 100644 --- a/doc/posix-functions/mtx_trylock.texi +++ b/doc/posix-functions/mtx_trylock.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Mutexes.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: mtx Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/mtx_unlock.texi b/doc/posix-functions/mtx_unlock.texi index e7779d8..f77ea17 100644 --- a/doc/posix-functions/mtx_unlock.texi +++ b/doc/posix-functions/mtx_unlock.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Mutexes.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: mtx Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/lib/mtx.c b/lib/mtx.c new file mode 100644 index 0000000..6acb8ae --- /dev/null +++ b/lib/mtx.c @@ -0,0 +1,288 @@ +/* ISO C 11 locking in multithreaded situations. + Copyright (C) 2005-2019 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 2, 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 , 2005, 2019. + Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */ + +#include + +#include + +#include + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# include + +#else +/* Use POSIX threads. */ + +# include + +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +int +mtx_init (mtx_t *mutex, int type) +{ + switch (type) + { + case mtx_plain: + glwthread_mutex_init (&mutex->u.u_mutex); + break; + case mtx_plain | mtx_recursive: + glwthread_recmutex_init (&mutex->u.u_recmutex); + break; + case mtx_timed: + if (glwthread_timedmutex_init (&mutex->u.u_timedmutex) != 0) + return thrd_error; + break; + case mtx_timed | mtx_recursive: + if (glwthread_timedrecmutex_init (&mutex->u.u_timedrecmutex) != 0) + return thrd_error; + break; + default: + return thrd_error; + } + mutex->type = type; + return thrd_success; +} + +int +mtx_lock (mtx_t *mutex) +{ + int err; + + switch (mutex->type) + { + case mtx_plain: + err = glwthread_mutex_lock (&mutex->u.u_mutex); + break; + case mtx_plain | mtx_recursive: + err = glwthread_recmutex_lock (&mutex->u.u_recmutex); + break; + case mtx_timed: + err = glwthread_timedmutex_lock (&mutex->u.u_timedmutex); + break; + case mtx_timed | mtx_recursive: + err = glwthread_timedrecmutex_lock (&mutex->u.u_timedrecmutex); + break; + default: + abort (); + } + return (err == 0 ? thrd_success : thrd_error); +} + +int +mtx_trylock (mtx_t *mutex) +{ + int err; + + switch (mutex->type) + { + case mtx_plain: + err = glwthread_mutex_trylock (&mutex->u.u_mutex); + break; + case mtx_plain | mtx_recursive: + err = glwthread_recmutex_trylock (&mutex->u.u_recmutex); + break; + case mtx_timed: + err = glwthread_timedmutex_trylock (&mutex->u.u_timedmutex); + break; + case mtx_timed | mtx_recursive: + err = glwthread_timedrecmutex_trylock (&mutex->u.u_timedrecmutex); + break; + default: + abort (); + } + return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error); +} + +int +mtx_timedlock (mtx_t *mutex, const struct timespec *abstime) +{ + int err; + + switch (mutex->type) + { + case mtx_plain: + case mtx_plain | mtx_recursive: + return thrd_error; + case mtx_timed: + err = glwthread_timedmutex_timedlock (&mutex->u.u_timedmutex, abstime); + break; + case mtx_timed | mtx_recursive: + err = + glwthread_timedrecmutex_timedlock (&mutex->u.u_timedrecmutex, abstime); + break; + default: + abort (); + } + return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error); +} + +int +mtx_unlock (mtx_t *mutex) +{ + int err; + + switch (mutex->type) + { + case mtx_plain: + err = glwthread_mutex_unlock (&mutex->u.u_mutex); + break; + case mtx_plain | mtx_recursive: + err = glwthread_recmutex_unlock (&mutex->u.u_recmutex); + break; + case mtx_timed: + err = glwthread_timedmutex_unlock (&mutex->u.u_timedmutex); + break; + case mtx_timed | mtx_recursive: + err = glwthread_timedrecmutex_unlock (&mutex->u.u_timedrecmutex); + break; + default: + abort (); + } + return (err == 0 ? thrd_success : thrd_error); +} + +void +mtx_destroy (mtx_t *mutex) +{ + switch (mutex->type) + { + case mtx_plain: + glwthread_mutex_destroy (&mutex->u.u_mutex); + break; + case mtx_plain | mtx_recursive: + glwthread_recmutex_destroy (&mutex->u.u_recmutex); + break; + case mtx_timed: + glwthread_timedmutex_destroy (&mutex->u.u_timedmutex); + break; + case mtx_timed | mtx_recursive: + glwthread_timedrecmutex_destroy (&mutex->u.u_timedrecmutex); + break; + default: + abort (); + } +} + +void +call_once (once_flag *flagp, void (*func) (void)) +{ + glwthread_once (flagp, func); +} + +#else +/* Use POSIX threads. */ + +int +mtx_init (mtx_t *mutex, int type) +{ + switch (type) + { + case mtx_plain: + case mtx_timed: + case mtx_plain | mtx_recursive: + case mtx_timed | mtx_recursive: + break; + default: + return thrd_error; + } + + if ((type & mtx_recursive) != 0) + { + pthread_mutexattr_t attributes; + int err; + + err = pthread_mutexattr_init (&attributes); + if (err != 0) + return thrd_error; + err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return thrd_error; + } + err = pthread_mutex_init (mutex, &attributes); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return thrd_error; + } + err = pthread_mutexattr_destroy (&attributes); + if (err != 0) + return thrd_error; + } + else + { + int err = pthread_mutex_init (mutex, NULL); + if (err != 0) + return thrd_error; + } + return thrd_success; +} + +int +mtx_lock (mtx_t *mutex) +{ + int err = pthread_mutex_lock (mutex); + return (err == 0 ? thrd_success : thrd_error); +} + +int +mtx_trylock (mtx_t *mutex) +{ + int err = pthread_mutex_trylock (mutex); + return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error); +} + +int +mtx_timedlock (mtx_t *mutex, const struct timespec *abstime) +{ + int err = pthread_mutex_timedlock (mutex, abstime); + return (err == 0 ? thrd_success : + err == ETIMEDOUT ? thrd_timedout : + thrd_error); +} + +int +mtx_unlock (mtx_t *mutex) +{ + int err = pthread_mutex_unlock (mutex); + return (err == 0 ? thrd_success : thrd_error); +} + +void +mtx_destroy (mtx_t *mutex) +{ + pthread_mutex_destroy (mutex); +} + +void +call_once (once_flag *flagp, void (*func) (void)) +{ + pthread_once (flagp, func); +} + +#endif diff --git a/modules/mtx b/modules/mtx new file mode 100644 index 0000000..a1d2a8a --- /dev/null +++ b/modules/mtx @@ -0,0 +1,34 @@ +Description: +ISO C 11 mutex functions. + +Files: +lib/mtx.c + +Depends-on: +threads-h +pthread_mutex_timedlock +windows-mutex +windows-recmutex +windows-timedmutex +windows-timedrecmutex + +configure.ac: +AC_REQUIRE([gl_THREADS_H]) +if test $HAVE_THREADS_H = 0; then + AC_LIBOBJ([mtx]) +fi +gl_THREADS_MODULE_INDICATOR([mtx]) + +Makefile.am: + +Include: + + +Link: +$(LTLIBSTDTHREAD) when linking with libtool, $(LIBSTDTHREAD) otherwise + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0020-cnd-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0020-cnd-New-module.patch" >From 36307d84f7bed226e8059c61ea611cf01b1dfdc4 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:32:42 +0200 Subject: [PATCH 20/26] cnd: New module. * lib/cnd.c: New file. * modules/cnd: New file. * doc/posix-functions/cnd_init.texi: Mention the new module. * doc/posix-functions/cnd_wait.texi: Likewise. * doc/posix-functions/cnd_timedwait.texi: Likewise. * doc/posix-functions/cnd_signal.texi: Likewise. * doc/posix-functions/cnd_broadcast.texi: Likewise. * doc/posix-functions/cnd_destroy.texi: Likewise. --- ChangeLog | 12 +++ doc/posix-functions/cnd_broadcast.texi | 8 +- doc/posix-functions/cnd_destroy.texi | 8 +- doc/posix-functions/cnd_init.texi | 8 +- doc/posix-functions/cnd_signal.texi | 8 +- doc/posix-functions/cnd_timedwait.texi | 8 +- doc/posix-functions/cnd_wait.texi | 8 +- lib/cnd.c | 185 +++++++++++++++++++++++++++++++++ modules/cnd | 31 ++++++ 9 files changed, 252 insertions(+), 24 deletions(-) create mode 100644 lib/cnd.c create mode 100644 modules/cnd diff --git a/ChangeLog b/ChangeLog index 0e73bd6..68eeea7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2019-06-20 Bruno Haible + cnd: New module. + * lib/cnd.c: New file. + * modules/cnd: New file. + * doc/posix-functions/cnd_init.texi: Mention the new module. + * doc/posix-functions/cnd_wait.texi: Likewise. + * doc/posix-functions/cnd_timedwait.texi: Likewise. + * doc/posix-functions/cnd_signal.texi: Likewise. + * doc/posix-functions/cnd_broadcast.texi: Likewise. + * doc/posix-functions/cnd_destroy.texi: Likewise. + +2019-06-20 Bruno Haible + mtx: New module. * lib/mtx.c: New file. * modules/mtx: New file. diff --git a/doc/posix-functions/cnd_broadcast.texi b/doc/posix-functions/cnd_broadcast.texi index a11d52d..e44a908 100644 --- a/doc/posix-functions/cnd_broadcast.texi +++ b/doc/posix-functions/cnd_broadcast.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Condition-Variables.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: cnd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/cnd_destroy.texi b/doc/posix-functions/cnd_destroy.texi index 1ae39fd..13783a3 100644 --- a/doc/posix-functions/cnd_destroy.texi +++ b/doc/posix-functions/cnd_destroy.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Condition-Variables.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: cnd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/cnd_init.texi b/doc/posix-functions/cnd_init.texi index 55c7489..a741303 100644 --- a/doc/posix-functions/cnd_init.texi +++ b/doc/posix-functions/cnd_init.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Condition-Variables.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: cnd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/cnd_signal.texi b/doc/posix-functions/cnd_signal.texi index 83071e5..22e2ecc 100644 --- a/doc/posix-functions/cnd_signal.texi +++ b/doc/posix-functions/cnd_signal.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Condition-Variables.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: cnd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/cnd_timedwait.texi b/doc/posix-functions/cnd_timedwait.texi index 3fa6985..0b5f29d 100644 --- a/doc/posix-functions/cnd_timedwait.texi +++ b/doc/posix-functions/cnd_timedwait.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Condition-Variables.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: cnd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/cnd_wait.texi b/doc/posix-functions/cnd_wait.texi index 89e9864..626a6aa 100644 --- a/doc/posix-functions/cnd_wait.texi +++ b/doc/posix-functions/cnd_wait.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Condition-Variables.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: cnd Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/lib/cnd.c b/lib/cnd.c new file mode 100644 index 0000000..48c4854 --- /dev/null +++ b/lib/cnd.c @@ -0,0 +1,185 @@ +/* ISO C 11 condition variables for multithreading. + Copyright (C) 2008-2019 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 2, 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 Yoann Vandoorselaere , 2008, + and Bruno Haible , 2008, 2019. */ + +#include + +#include + +#include + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# include "windows-mutex.h" +# include "windows-recmutex.h" +# include "windows-timedmutex.h" +# include "windows-timedrecmutex.h" + +#else +/* Use POSIX threads. */ + +# include + +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +int +cnd_init (cnd_t *cond) +{ + int err = glwthread_cond_init (cond); + return (err == 0 ? thrd_success : + err == ENOMEM ? thrd_nomem : + thrd_error); +} + +static int +mutex_lock (mtx_t *mutex) +{ + switch (mutex->type) + { + case mtx_plain: + return glwthread_mutex_lock (&mutex->u.u_mutex); + case mtx_plain | mtx_recursive: + return glwthread_recmutex_lock (&mutex->u.u_recmutex); + case mtx_timed: + return glwthread_timedmutex_lock (&mutex->u.u_timedmutex); + case mtx_timed | mtx_recursive: + return glwthread_timedrecmutex_lock (&mutex->u.u_timedrecmutex); + default: + abort (); + } +} + +static int +mutex_unlock (mtx_t *mutex) +{ + switch (mutex->type) + { + case mtx_plain: + return glwthread_mutex_unlock (&mutex->u.u_mutex); + case mtx_plain | mtx_recursive: + return glwthread_recmutex_unlock (&mutex->u.u_recmutex); + case mtx_timed: + return glwthread_timedmutex_unlock (&mutex->u.u_timedmutex); + case mtx_timed | mtx_recursive: + return glwthread_timedrecmutex_unlock (&mutex->u.u_timedrecmutex); + default: + abort (); + } +} + +int +cnd_wait (cnd_t *cond, mtx_t *mutex) +{ + int err = glwthread_cond_wait (cond, mutex, + (int (*) (void *)) mutex_lock, + (int (*) (void *)) mutex_unlock); + return (err == 0 ? thrd_success : thrd_error); +} + +int +cnd_timedwait (cnd_t *cond, mtx_t *mutex, const struct timespec *abstime) +{ + int err = glwthread_cond_timedwait (cond, mutex, + (int (*) (void *)) mutex_lock, + (int (*) (void *)) mutex_unlock, + abstime); + return (err == 0 ? thrd_success : + err == ETIMEDOUT ? thrd_timedout : + thrd_error); +} + +int +cnd_signal (cnd_t *cond) +{ + int err = glwthread_cond_signal (cond); + return (err == 0 ? thrd_success : + err == ENOMEM ? thrd_nomem : + thrd_error); +} + +int +cnd_broadcast (cnd_t *cond) +{ + int err = glwthread_cond_broadcast (cond); + return (err == 0 ? thrd_success : thrd_error); +} + +void +cnd_destroy (cnd_t *cond) +{ + glwthread_cond_destroy (cond); +} + +#else +/* Use POSIX threads. */ + +int +cnd_init (cnd_t *cond) +{ + int err = pthread_cond_init (cond, NULL); + return (err == 0 ? thrd_success : + err == ENOMEM ? thrd_nomem : + thrd_error); +} + +int +cnd_wait (cnd_t *cond, mtx_t *mutex) +{ + int err = pthread_cond_wait (cond, mutex); + return (err == 0 ? thrd_success : thrd_error); +} + +int +cnd_timedwait (cnd_t *cond, mtx_t *mutex, const struct timespec *abstime) +{ + int err = pthread_cond_timedwait (cond, mutex, abstime); + return (err == 0 ? thrd_success : + err == ETIMEDOUT ? thrd_timedout : + thrd_error); +} + +int +cnd_signal (cnd_t *cond) +{ + int err = pthread_cond_signal (cond); + return (err == 0 ? thrd_success : + err == ENOMEM ? thrd_nomem : + thrd_error); +} + +int +cnd_broadcast (cnd_t *cond) +{ + int err = pthread_cond_broadcast (cond); + return (err == 0 ? thrd_success : thrd_error); +} + +void +cnd_destroy (cnd_t *cond) +{ + pthread_cond_destroy (cond); +} + +#endif diff --git a/modules/cnd b/modules/cnd new file mode 100644 index 0000000..635a4224 --- /dev/null +++ b/modules/cnd @@ -0,0 +1,31 @@ +Description: +ISO C 11 condition variable functions. + +Files: +lib/cnd.c + +Depends-on: +threads-h +windows-cond +gettimeofday + +configure.ac: +AC_REQUIRE([gl_THREADS_H]) +if test $HAVE_THREADS_H = 0; then + AC_LIBOBJ([cnd]) +fi +gl_THREADS_MODULE_INDICATOR([cnd]) + +Makefile.am: + +Include: + + +Link: +$(LTLIBSTDTHREAD) when linking with libtool, $(LIBSTDTHREAD) otherwise + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0021-tss-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0021-tss-New-module.patch" >From ee2f4139e12114621dc1e4db54c0b1658a9fadac Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:34:49 +0200 Subject: [PATCH 21/26] tss: New module. * lib/tss.c: New file. * modules/tss: New file. * doc/posix-functions/tss_create.texi: Mention the new module. * doc/posix-functions/tss_set.texi: Likewise. * doc/posix-functions/tss_get.texi: Likewise. * doc/posix-functions/tss_delete.texi: Likewise. --- ChangeLog | 10 ++++ doc/posix-functions/tss_create.texi | 8 +-- doc/posix-functions/tss_delete.texi | 8 +-- doc/posix-functions/tss_get.texi | 8 +-- doc/posix-functions/tss_set.texi | 8 +-- lib/tss.c | 108 ++++++++++++++++++++++++++++++++++++ modules/tss | 30 ++++++++++ 7 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 lib/tss.c create mode 100644 modules/tss diff --git a/ChangeLog b/ChangeLog index 68eeea7..4c75b69 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2019-06-20 Bruno Haible + tss: New module. + * lib/tss.c: New file. + * modules/tss: New file. + * doc/posix-functions/tss_create.texi: Mention the new module. + * doc/posix-functions/tss_set.texi: Likewise. + * doc/posix-functions/tss_get.texi: Likewise. + * doc/posix-functions/tss_delete.texi: Likewise. + +2019-06-20 Bruno Haible + cnd: New module. * lib/cnd.c: New file. * modules/cnd: New file. diff --git a/doc/posix-functions/tss_create.texi b/doc/posix-functions/tss_create.texi index 833cd87..86fab4e 100644 --- a/doc/posix-functions/tss_create.texi +++ b/doc/posix-functions/tss_create.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread_002dlocal-Storage.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: tss Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/tss_delete.texi b/doc/posix-functions/tss_delete.texi index c122828..8527324 100644 --- a/doc/posix-functions/tss_delete.texi +++ b/doc/posix-functions/tss_delete.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread_002dlocal-Storage.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: tss Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/tss_get.texi b/doc/posix-functions/tss_get.texi index 0cc14d8..b8109cb 100644 --- a/doc/posix-functions/tss_get.texi +++ b/doc/posix-functions/tss_get.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread_002dlocal-Storage.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: tss Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/doc/posix-functions/tss_set.texi b/doc/posix-functions/tss_set.texi index 533ad89..d0091f0 100644 --- a/doc/posix-functions/tss_set.texi +++ b/doc/posix-functions/tss_set.texi @@ -10,15 +10,15 @@ Documentation:@* @url{https://www.gnu.org/software/libc/manual/html_node/ISO-C-Thread_002dlocal-Storage.html}. @end ifnotinfo -Gnulib module: --- +Gnulib module: tss Portability problems fixed by Gnulib: @itemize +@item +This function is missing on many platforms: +glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on many platforms: -glibc 2.27, Mac OS X 10.5, FreeBSD 9.3, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS, Android 9.0. @end itemize diff --git a/lib/tss.c b/lib/tss.c new file mode 100644 index 0000000..d8c0bb5 --- /dev/null +++ b/lib/tss.c @@ -0,0 +1,108 @@ +/* ISO C 11 thread-specific storage in multithreaded situations. + Copyright (C) 2005-2019 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 , 2005, 2019. */ + +#include + +#include + +#include + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +#else +/* Use POSIX threads. */ + +# include + +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Use Windows threads. */ + +int +tss_create (tss_t *keyp, tss_dtor_t destructor) +{ + int err = glwthread_tls_key_create (keyp, destructor); + if (err == 0) + return thrd_success; + else + { + memset (keyp, '\0', sizeof (tss_t)); + return thrd_error; + } +} + +int +tss_set (tss_t key, void *value) +{ + int err = glwthread_tls_set (key, value); + return (err == 0 ? thrd_success : thrd_error); +} + +void * +tss_get (tss_t key) +{ + return glwthread_tls_get (key); +} + +void +tss_delete (tss_t key) +{ + glwthread_tls_key_delete (key); +} + +#else +/* Use POSIX threads. */ + +int +tss_create (tss_t *keyp, tss_dtor_t destructor) +{ + int err = pthread_key_create (keyp, destructor); + if (err == 0) + return thrd_success; + else + { + memset (keyp, '\0', sizeof (tss_t)); + return thrd_error; + } +} + +int +tss_set (tss_t key, void *value) +{ + int err = pthread_setspecific (key, value); + return (err == 0 ? thrd_success : thrd_error); +} + +void * +tss_get (tss_t key) +{ + return pthread_getspecific (key); +} + +void +tss_delete (tss_t key) +{ + pthread_key_delete (key); +} + +#endif diff --git a/modules/tss b/modules/tss new file mode 100644 index 0000000..4a28200 --- /dev/null +++ b/modules/tss @@ -0,0 +1,30 @@ +Description: +ISO C 11 thread-specific storage functions. + +Files: +lib/tss.c + +Depends-on: +threads-h +windows-tls + +configure.ac: +AC_REQUIRE([gl_THREADS_H]) +if test $HAVE_THREADS_H = 0; then + AC_LIBOBJ([tss]) +fi +gl_THREADS_MODULE_INDICATOR([tss]) + +Makefile.am: + +Include: + + +Link: +$(LTLIBSTDTHREAD) when linking with libtool, $(LIBSTDTHREAD) otherwise + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0022-thrd-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0022-thrd-Add-tests.patch" >From 6ac18d06d0234f85c41af69fb6319592e2d4f5c6 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:37:23 +0200 Subject: [PATCH 22/26] thrd: Add tests. * tests/test-thrd_create.c: New file, based on tests/test-thread_create.c. * tests/test-thrd_current.c: New file, based on tests/test-thread_self.c. * modules/thrd-tests: New file. --- ChangeLog | 9 ++++++ modules/thrd-tests | 14 +++++++++ tests/test-thrd_create.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test-thrd_current.c | 31 ++++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 modules/thrd-tests create mode 100644 tests/test-thrd_create.c create mode 100644 tests/test-thrd_current.c diff --git a/ChangeLog b/ChangeLog index 4c75b69..b17e751 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2019-06-20 Bruno Haible + thrd: Add tests. + * tests/test-thrd_create.c: New file, based on + tests/test-thread_create.c. + * tests/test-thrd_current.c: New file, based on + tests/test-thread_self.c. + * modules/thrd-tests: New file. + +2019-06-20 Bruno Haible + tss: New module. * lib/tss.c: New file. * modules/tss: New file. diff --git a/modules/thrd-tests b/modules/thrd-tests new file mode 100644 index 0000000..fdb6600 --- /dev/null +++ b/modules/thrd-tests @@ -0,0 +1,14 @@ +Files: +tests/test-thrd_current.c +tests/test-thrd_create.c +tests/macros.h + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-thrd_current test-thrd_create +check_PROGRAMS += test-thrd_current test-thrd_create +test_thrd_current_LDADD = $(LDADD) @LIBSTDTHREAD@ +test_thrd_create_LDADD = $(LDADD) @LIBSTDTHREAD@ diff --git a/tests/test-thrd_create.c b/tests/test-thrd_create.c new file mode 100644 index 0000000..af1eb53 --- /dev/null +++ b/tests/test-thrd_create.c @@ -0,0 +1,73 @@ +/* Test of thrd_create () macro. + Copyright (C) 2011-2019 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 , 2011. */ + +#include + +#include + +#include +#include + +#include "macros.h" + +static thrd_t main_thread_before; +static thrd_t main_thread_after; +static thrd_t worker_thread; + +#define MAGIC 1266074729 +static volatile int work_done; + +static int +worker_thread_func (void *arg) +{ + work_done = 1; + return MAGIC; +} + +int +main () +{ + main_thread_before = thrd_current (); + + if (thrd_create (&worker_thread, worker_thread_func, NULL) == thrd_success) + { + int ret; + + /* Check that thrd_current () has the same value before than after the + first call to thrd_create (). */ + main_thread_after = thrd_current (); + ASSERT (memcmp (&main_thread_before, &main_thread_after, + sizeof (thrd_t)) + == 0); + + ASSERT (thrd_join (worker_thread, &ret) == thrd_success); + + /* Check the return value of the thread. */ + ASSERT (ret == MAGIC); + + /* Check that worker_thread_func () has finished executing. */ + ASSERT (work_done); + + return 0; + } + else + { + fputs ("thrd_create failed\n", stderr); + return 1; + } +} diff --git a/tests/test-thrd_current.c b/tests/test-thrd_current.c new file mode 100644 index 0000000..9bb5258 --- /dev/null +++ b/tests/test-thrd_current.c @@ -0,0 +1,31 @@ +/* Test of thrd_current () function. + Copyright (C) 2011-2019 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 , 2011. */ + +#include + +#include + +thrd_t main_thread; + +int +main () +{ + main_thread = thrd_current (); + + return 0; +} -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0023-mtx-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0023-mtx-Add-tests.patch" >From 4a440ef9b6c2568f54b0487b1ebaffc597efb399 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:38:06 +0200 Subject: [PATCH 23/26] mtx: Add tests. * tests/test-mtx.c: New file, based on tests/test-lock.c. * tests/test-call_once.c: New file, based on tests/test-once.c. * modules/mtx-tests: New file. --- ChangeLog | 7 + modules/mtx-tests | 19 ++ tests/test-call_once.c | 43 ++++ tests/test-mtx.c | 649 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 718 insertions(+) create mode 100644 modules/mtx-tests create mode 100644 tests/test-call_once.c create mode 100644 tests/test-mtx.c diff --git a/ChangeLog b/ChangeLog index b17e751..1f658d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2019-06-20 Bruno Haible + mtx: Add tests. + * tests/test-mtx.c: New file, based on tests/test-lock.c. + * tests/test-call_once.c: New file, based on tests/test-once.c. + * modules/mtx-tests: New file. + +2019-06-20 Bruno Haible + thrd: Add tests. * tests/test-thrd_create.c: New file, based on tests/test-thread_create.c. diff --git a/modules/mtx-tests b/modules/mtx-tests new file mode 100644 index 0000000..7714ebc --- /dev/null +++ b/modules/mtx-tests @@ -0,0 +1,19 @@ +Files: +tests/test-mtx.c +tests/test-call_once.c +tests/macros.h + +Depends-on: +thrd +lock +stdint + +configure.ac: +AC_CHECK_HEADERS_ONCE([semaphore.h]) +AC_CHECK_DECLS_ONCE([alarm]) + +Makefile.am: +TESTS += test-mtx test-call_once +check_PROGRAMS += test-mtx test-call_once +test_mtx_LDADD = $(LDADD) @LIBSTDTHREAD@ @LIBTHREAD@ +test_call_once_LDADD = $(LDADD) @LIBSTDTHREAD@ diff --git a/tests/test-call_once.c b/tests/test-call_once.c new file mode 100644 index 0000000..8d2b785 --- /dev/null +++ b/tests/test-call_once.c @@ -0,0 +1,43 @@ +/* Test of once-only execution in multithreaded situations. + Copyright (C) 2018-2019 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 , 2018. */ + +#include + +#include + +#include "macros.h" + +static once_flag a_once = ONCE_FLAG_INIT; + +static int a; + +static void +a_init (void) +{ + a = 42; +} + +int +main () +{ + call_once (&a_once, a_init); + + ASSERT (a == 42); + + return 0; +} diff --git a/tests/test-mtx.c b/tests/test-mtx.c new file mode 100644 index 0000000..0d74492 --- /dev/null +++ b/tests/test-mtx.c @@ -0,0 +1,649 @@ +/* Test of locking in multithreaded situations. + Copyright (C) 2005, 2008-2019 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 , 2005. */ + +#include + +/* Whether to enable locking. + Uncomment this to get a test program without locking, to verify that + it crashes. */ +#define ENABLE_LOCKING 1 + +/* Which tests to perform. + Uncomment some of these, to verify that all tests crash if no locking + is enabled. */ +#define DO_TEST_LOCK 1 +#define DO_TEST_RECURSIVE_LOCK 1 +#define DO_TEST_ONCE 1 + +/* Whether to help the scheduler through explicit thrd_yield(). + Uncomment this to see if the operating system has a fair scheduler. */ +#define EXPLICIT_YIELD 1 + +/* Whether to use 'volatile' on some variables that communicate information + between threads. If set to 0, a semaphore or a lock is used to protect + these variables. If set to 1, 'volatile' is used; this is theoretically + equivalent but can lead to much slower execution (e.g. 30x slower total + run time on a 40-core machine), because 'volatile' does not imply any + synchronization/communication between different CPUs. */ +#define USE_VOLATILE 0 + +#if USE_POSIX_THREADS && HAVE_SEMAPHORE_H +/* Whether to use a semaphore to communicate information between threads. + If set to 0, a lock is used. If set to 1, a semaphore is used. + Uncomment this to reduce the dependencies of this test. */ +# define USE_SEMAPHORE 1 +/* Mac OS X provides only named semaphores (sem_open); its facility for + unnamed semaphores (sem_init) does not work. */ +# if defined __APPLE__ && defined __MACH__ +# define USE_NAMED_SEMAPHORE 1 +# else +# define USE_UNNAMED_SEMAPHORE 1 +# endif +#endif + +/* Whether to print debugging messages. */ +#define ENABLE_DEBUGGING 0 + +/* Number of simultaneous threads. */ +#define THREAD_COUNT 10 + +/* Number of operations performed in each thread. + This is quite high, because with a smaller count, say 5000, we often get + an "OK" result even without ENABLE_LOCKING (on Linux/x86). */ +#define REPEAT_COUNT 50000 + +#include +#include +#include +#include +#include + +#include "glthread/lock.h" + +#if USE_SEMAPHORE +# include +# include +# include +# include +#endif + +#if HAVE_DECL_ALARM +# include +# include +#endif + +#include "macros.h" + +#if ENABLE_DEBUGGING +# define dbgprintf printf +#else +# define dbgprintf if (0) printf +#endif + +#if EXPLICIT_YIELD +# define yield() thrd_yield () +#else +# define yield() +#endif + +#if USE_VOLATILE +struct atomic_int { + volatile int value; +}; +static void +init_atomic_int (struct atomic_int *ai) +{ +} +static int +get_atomic_int_value (struct atomic_int *ai) +{ + return ai->value; +} +static void +set_atomic_int_value (struct atomic_int *ai, int new_value) +{ + ai->value = new_value; +} +#elif USE_SEMAPHORE +/* This atomic_int implementation can only support the values 0 and 1. + It is initially 0 and can be set to 1 only once. */ +# if USE_UNNAMED_SEMAPHORE +struct atomic_int { + sem_t semaphore; +}; +#define atomic_int_semaphore(ai) (&(ai)->semaphore) +static void +init_atomic_int (struct atomic_int *ai) +{ + sem_init (&ai->semaphore, 0, 0); +} +# endif +# if USE_NAMED_SEMAPHORE +struct atomic_int { + sem_t *semaphore; +}; +#define atomic_int_semaphore(ai) ((ai)->semaphore) +static void +init_atomic_int (struct atomic_int *ai) +{ + sem_t *s; + unsigned int count; + for (count = 0; ; count++) + { + char name[80]; + /* Use getpid() in the name, so that different processes running at the + same time will not interfere. Use ai in the name, so that different + atomic_int in the same process will not interfere. Use a count in + the name, so that even in the (unlikely) case that a semaphore with + the specified name already exists, we can try a different name. */ + sprintf (name, "test-lock-%lu-%p-%u", + (unsigned long) getpid (), ai, count); + s = sem_open (name, O_CREAT | O_EXCL, 0600, 0); + if (s == SEM_FAILED) + { + if (errno == EEXIST) + /* Retry with a different name. */ + continue; + else + { + perror ("sem_open failed"); + abort (); + } + } + else + { + /* Try not to leave a semaphore hanging around on the file system + eternally, if we can avoid it. */ + sem_unlink (name); + break; + } + } + ai->semaphore = s; +} +# endif +static int +get_atomic_int_value (struct atomic_int *ai) +{ + if (sem_trywait (atomic_int_semaphore (ai)) == 0) + { + if (sem_post (atomic_int_semaphore (ai))) + abort (); + return 1; + } + else if (errno == EAGAIN) + return 0; + else + abort (); +} +static void +set_atomic_int_value (struct atomic_int *ai, int new_value) +{ + if (new_value == 0) + /* It's already initialized with 0. */ + return; + /* To set the value 1: */ + if (sem_post (atomic_int_semaphore (ai))) + abort (); +} +#else +struct atomic_int { + mtx_t lock; + int value; +}; +static void +init_atomic_int (struct atomic_int *ai) +{ + ASSERT (mtx_init (&ai->lock, mtx_plain) == thrd_success); +} +static int +get_atomic_int_value (struct atomic_int *ai) +{ + ASSERT (mtx_lock (&ai->lock) == thrd_success); + int ret = ai->value; + ASSERT (mtx_unlock (&ai->lock) == thrd_success); + return ret; +} +static void +set_atomic_int_value (struct atomic_int *ai, int new_value) +{ + ASSERT (mtx_lock (&ai->lock) == thrd_success); + ai->value = new_value; + ASSERT (mtx_unlock (&ai->lock) == thrd_success); +} +#endif + +/* Returns a reference to the current thread as a pointer, for debugging. */ +#if defined __MVS__ + /* On IBM z/OS, pthread_t is a struct with an 8-byte '__' field. + The first three bytes of this field appear to uniquely identify a + pthread_t, though not necessarily representing a pointer. */ +# define thrd_current_pointer() (*((void **) thrd_current ().__)) +#elif defined __sun + /* On Solaris, thrd_t is merely an 'unsigned int'. */ +# define thrd_current_pointer() ((void *) (uintptr_t) thrd_current ()) +#else +# define thrd_current_pointer() ((void *) thrd_current ()) +#endif + +#define ACCOUNT_COUNT 4 + +static int account[ACCOUNT_COUNT]; + +static int +random_account (void) +{ + return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT; +} + +static void +check_accounts (void) +{ + int i, sum; + + sum = 0; + for (i = 0; i < ACCOUNT_COUNT; i++) + sum += account[i]; + if (sum != ACCOUNT_COUNT * 1000) + abort (); +} + + +/* ------------------- Test normal (non-recursive) locks ------------------- */ + +/* Test normal locks by having several bank accounts and several threads + which shuffle around money between the accounts and another thread + checking that all the money is still there. */ + +static mtx_t my_lock; + +static int +lock_mutator_thread (void *arg) +{ + int repeat; + + for (repeat = REPEAT_COUNT; repeat > 0; repeat--) + { + int i1, i2, value; + + dbgprintf ("Mutator %p before lock\n", thrd_current_pointer ()); + ASSERT (mtx_lock (&my_lock) == thrd_success); + dbgprintf ("Mutator %p after lock\n", thrd_current_pointer ()); + + i1 = random_account (); + i2 = random_account (); + value = ((unsigned int) rand () >> 3) % 10; + account[i1] += value; + account[i2] -= value; + + dbgprintf ("Mutator %p before unlock\n", thrd_current_pointer ()); + ASSERT (mtx_unlock (&my_lock) == thrd_success); + dbgprintf ("Mutator %p after unlock\n", thrd_current_pointer ()); + + dbgprintf ("Mutator %p before check lock\n", thrd_current_pointer ()); + ASSERT (mtx_lock (&my_lock) == thrd_success); + check_accounts (); + ASSERT (mtx_unlock (&my_lock) == thrd_success); + dbgprintf ("Mutator %p after check unlock\n", thrd_current_pointer ()); + + yield (); + } + + dbgprintf ("Mutator %p dying.\n", thrd_current_pointer ()); + return 0; +} + +static struct atomic_int lock_checker_done; + +static int +lock_checker_thread (void *arg) +{ + while (get_atomic_int_value (&lock_checker_done) == 0) + { + dbgprintf ("Checker %p before check lock\n", thrd_current_pointer ()); + ASSERT (mtx_lock (&my_lock) == thrd_success); + check_accounts (); + ASSERT (mtx_unlock (&my_lock) == thrd_success); + dbgprintf ("Checker %p after check unlock\n", thrd_current_pointer ()); + + yield (); + } + + dbgprintf ("Checker %p dying.\n", thrd_current_pointer ()); + return 0; +} + +static void +test_mtx_plain (void) +{ + int i; + thrd_t checkerthread; + thrd_t threads[THREAD_COUNT]; + + /* Initialization. */ + for (i = 0; i < ACCOUNT_COUNT; i++) + account[i] = 1000; + init_atomic_int (&lock_checker_done); + set_atomic_int_value (&lock_checker_done, 0); + + /* Spawn the threads. */ + ASSERT (thrd_create (&checkerthread, lock_checker_thread, NULL) + == thrd_success); + for (i = 0; i < THREAD_COUNT; i++) + ASSERT (thrd_create (&threads[i], lock_mutator_thread, NULL) + == thrd_success); + + /* Wait for the threads to terminate. */ + for (i = 0; i < THREAD_COUNT; i++) + ASSERT (thrd_join (threads[i], NULL) == thrd_success); + set_atomic_int_value (&lock_checker_done, 1); + ASSERT (thrd_join (checkerthread, NULL) == thrd_success); + check_accounts (); +} + + +/* -------------------------- Test recursive locks -------------------------- */ + +/* Test recursive locks by having several bank accounts and several threads + which shuffle around money between the accounts (recursively) and another + thread checking that all the money is still there. */ + +static mtx_t my_reclock; + +static void +recshuffle (void) +{ + int i1, i2, value; + + dbgprintf ("Mutator %p before lock\n", thrd_current_pointer ()); + ASSERT (mtx_lock (&my_reclock) == thrd_success); + dbgprintf ("Mutator %p after lock\n", thrd_current_pointer ()); + + i1 = random_account (); + i2 = random_account (); + value = ((unsigned int) rand () >> 3) % 10; + account[i1] += value; + account[i2] -= value; + + /* Recursive with probability 0.5. */ + if (((unsigned int) rand () >> 3) % 2) + recshuffle (); + + dbgprintf ("Mutator %p before unlock\n", thrd_current_pointer ()); + ASSERT (mtx_unlock (&my_reclock) == thrd_success); + dbgprintf ("Mutator %p after unlock\n", thrd_current_pointer ()); +} + +static int +reclock_mutator_thread (void *arg) +{ + int repeat; + + for (repeat = REPEAT_COUNT; repeat > 0; repeat--) + { + recshuffle (); + + dbgprintf ("Mutator %p before check lock\n", thrd_current_pointer ()); + ASSERT (mtx_lock (&my_reclock) == thrd_success); + check_accounts (); + ASSERT (mtx_unlock (&my_reclock) == thrd_success); + dbgprintf ("Mutator %p after check unlock\n", thrd_current_pointer ()); + + yield (); + } + + dbgprintf ("Mutator %p dying.\n", thrd_current_pointer ()); + return 0; +} + +static struct atomic_int reclock_checker_done; + +static int +reclock_checker_thread (void *arg) +{ + while (get_atomic_int_value (&reclock_checker_done) == 0) + { + dbgprintf ("Checker %p before check lock\n", thrd_current_pointer ()); + ASSERT (mtx_lock (&my_reclock) == thrd_success); + check_accounts (); + ASSERT (mtx_unlock (&my_reclock) == thrd_success); + dbgprintf ("Checker %p after check unlock\n", thrd_current_pointer ()); + + yield (); + } + + dbgprintf ("Checker %p dying.\n", thrd_current_pointer ()); + return 0; +} + +static void +test_mtx_recursive (void) +{ + int i; + thrd_t checkerthread; + thrd_t threads[THREAD_COUNT]; + + /* Initialization. */ + for (i = 0; i < ACCOUNT_COUNT; i++) + account[i] = 1000; + init_atomic_int (&reclock_checker_done); + set_atomic_int_value (&reclock_checker_done, 0); + + /* Spawn the threads. */ + ASSERT (thrd_create (&checkerthread, reclock_checker_thread, NULL) + == thrd_success); + for (i = 0; i < THREAD_COUNT; i++) + ASSERT (thrd_create (&threads[i], reclock_mutator_thread, NULL) + == thrd_success); + + /* Wait for the threads to terminate. */ + for (i = 0; i < THREAD_COUNT; i++) + ASSERT (thrd_join (threads[i], NULL) == thrd_success); + set_atomic_int_value (&reclock_checker_done, 1); + ASSERT (thrd_join (checkerthread, NULL) == thrd_success); + check_accounts (); +} + + +/* ------------------------ Test once-only execution ------------------------ */ + +/* Test once-only execution by having several threads attempt to grab a + once-only task simultaneously (triggered by releasing a read-write lock). */ + +static once_flag fresh_once = ONCE_FLAG_INIT; +static int ready[THREAD_COUNT]; +static mtx_t ready_lock[THREAD_COUNT]; +#if ENABLE_LOCKING +static gl_rwlock_t fire_signal[REPEAT_COUNT]; +#else +static volatile int fire_signal_state; +#endif +static once_flag once_control; +static int performed; +static mtx_t performed_lock; + +static void +once_execute (void) +{ + ASSERT (mtx_lock (&performed_lock) == thrd_success); + performed++; + ASSERT (mtx_unlock (&performed_lock) == thrd_success); +} + +static int +once_contender_thread (void *arg) +{ + int id = (int) (intptr_t) arg; + int repeat; + + for (repeat = 0; repeat <= REPEAT_COUNT; repeat++) + { + /* Tell the main thread that we're ready. */ + ASSERT (mtx_lock (&ready_lock[id]) == thrd_success); + ready[id] = 1; + ASSERT (mtx_unlock (&ready_lock[id]) == thrd_success); + + if (repeat == REPEAT_COUNT) + break; + + dbgprintf ("Contender %p waiting for signal for round %d\n", + thrd_current_pointer (), repeat); +#if ENABLE_LOCKING + /* Wait for the signal to go. */ + gl_rwlock_rdlock (fire_signal[repeat]); + /* And don't hinder the others (if the scheduler is unfair). */ + gl_rwlock_unlock (fire_signal[repeat]); +#else + /* Wait for the signal to go. */ + while (fire_signal_state <= repeat) + yield (); +#endif + dbgprintf ("Contender %p got the signal for round %d\n", + thrd_current_pointer (), repeat); + + /* Contend for execution. */ + call_once (&once_control, once_execute); + } + + return 0; +} + +static void +test_once (void) +{ + int i, repeat; + thrd_t threads[THREAD_COUNT]; + + /* Initialize all variables. */ + for (i = 0; i < THREAD_COUNT; i++) + { + ready[i] = 0; + ASSERT (mtx_init (&ready_lock[i], mtx_plain) == thrd_success); + } +#if ENABLE_LOCKING + for (i = 0; i < REPEAT_COUNT; i++) + gl_rwlock_init (fire_signal[i]); +#else + fire_signal_state = 0; +#endif + +#if ENABLE_LOCKING + /* Block all fire_signals. */ + for (i = REPEAT_COUNT-1; i >= 0; i--) + gl_rwlock_wrlock (fire_signal[i]); +#endif + + /* Spawn the threads. */ + for (i = 0; i < THREAD_COUNT; i++) + ASSERT (thrd_create (&threads[i], + once_contender_thread, (void *) (intptr_t) i) + == thrd_success); + + for (repeat = 0; repeat <= REPEAT_COUNT; repeat++) + { + /* Wait until every thread is ready. */ + dbgprintf ("Main thread before synchronizing for round %d\n", repeat); + for (;;) + { + int ready_count = 0; + for (i = 0; i < THREAD_COUNT; i++) + { + ASSERT (mtx_lock (&ready_lock[i]) == thrd_success); + ready_count += ready[i]; + ASSERT (mtx_unlock (&ready_lock[i]) == thrd_success); + } + if (ready_count == THREAD_COUNT) + break; + yield (); + } + dbgprintf ("Main thread after synchronizing for round %d\n", repeat); + + if (repeat > 0) + { + /* Check that exactly one thread executed the once_execute() + function. */ + if (performed != 1) + abort (); + } + + if (repeat == REPEAT_COUNT) + break; + + /* Preparation for the next round: Initialize once_control. */ + memcpy (&once_control, &fresh_once, sizeof (once_flag)); + + /* Preparation for the next round: Reset the performed counter. */ + performed = 0; + + /* Preparation for the next round: Reset the ready flags. */ + for (i = 0; i < THREAD_COUNT; i++) + { + ASSERT (mtx_lock (&ready_lock[i]) == thrd_success); + ready[i] = 0; + ASSERT (mtx_unlock (&ready_lock[i]) == thrd_success); + } + + /* Signal all threads simultaneously. */ + dbgprintf ("Main thread giving signal for round %d\n", repeat); +#if ENABLE_LOCKING + gl_rwlock_unlock (fire_signal[repeat]); +#else + fire_signal_state = repeat + 1; +#endif + } + + /* Wait for the threads to terminate. */ + for (i = 0; i < THREAD_COUNT; i++) + ASSERT (thrd_join (threads[i], NULL) == thrd_success); +} + + +/* -------------------------------------------------------------------------- */ + +int +main () +{ +#if HAVE_DECL_ALARM + /* Declare failure if test takes too long, by using default abort + caused by SIGALRM. */ + int alarm_value = 600; + signal (SIGALRM, SIG_DFL); + alarm (alarm_value); +#endif + + ASSERT (mtx_init (&my_lock, mtx_plain) == thrd_success); + ASSERT (mtx_init (&my_reclock, mtx_plain | mtx_recursive) == thrd_success); + ASSERT (mtx_init (&performed_lock, mtx_plain) == thrd_success); + +#if DO_TEST_LOCK + printf ("Starting test_mtx_plain ..."); fflush (stdout); + test_mtx_plain (); + printf (" OK\n"); fflush (stdout); +#endif +#if DO_TEST_RECURSIVE_LOCK + printf ("Starting test_mtx_recursive ..."); fflush (stdout); + test_mtx_recursive (); + printf (" OK\n"); fflush (stdout); +#endif +#if DO_TEST_ONCE + printf ("Starting test_once ..."); fflush (stdout); + test_once (); + printf (" OK\n"); fflush (stdout); +#endif + + return 0; +} -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0024-cnd-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0024-cnd-Add-tests.patch" >From c94b90fcd6f6bdbfff9ccf17bc570065bba51752 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:40:02 +0200 Subject: [PATCH 24/26] cnd: Add tests. * tests/test-cnd.c: New file, based on tests/test-cond.c. * modules/cnd-tests: New file. --- ChangeLog | 6 ++ modules/cnd-tests | 16 +++++ tests/test-cnd.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 modules/cnd-tests create mode 100644 tests/test-cnd.c diff --git a/ChangeLog b/ChangeLog index 1f658d1..2d3ee5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2019-06-20 Bruno Haible + cnd: Add tests. + * tests/test-cnd.c: New file, based on tests/test-cond.c. + * modules/cnd-tests: New file. + +2019-06-20 Bruno Haible + mtx: Add tests. * tests/test-mtx.c: New file, based on tests/test-lock.c. * tests/test-call_once.c: New file, based on tests/test-once.c. diff --git a/modules/cnd-tests b/modules/cnd-tests new file mode 100644 index 0000000..f9dc79e --- /dev/null +++ b/modules/cnd-tests @@ -0,0 +1,16 @@ +Files: +tests/test-cnd.c +tests/macros.h + +Depends-on: +mtx +thrd +gettimeofday + +configure.ac: +AC_CHECK_DECLS_ONCE([alarm]) + +Makefile.am: +TESTS += test-cnd +check_PROGRAMS += test-cnd +test_cnd_LDADD = $(LDADD) @LIBSTDTHREAD@ diff --git a/tests/test-cnd.c b/tests/test-cnd.c new file mode 100644 index 0000000..2d8cabc --- /dev/null +++ b/tests/test-cnd.c @@ -0,0 +1,209 @@ +/* Test of condition variables in multithreaded situations. + Copyright (C) 2008-2019 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 . */ + +#include + +/* Which tests to perform. + Uncomment some of these, to verify that all tests crash if no locking + is enabled. */ +#define DO_TEST_COND 1 +#define DO_TEST_TIMEDCOND 1 + + +/* Whether to help the scheduler through explicit yield(). + Uncomment this to see if the operating system has a fair scheduler. */ +#define EXPLICIT_YIELD 1 + +/* Whether to print debugging messages. */ +#define ENABLE_DEBUGGING 0 + +#include +#include +#include +#include +#include + +#if HAVE_DECL_ALARM +# include +# include +#endif + +#include "macros.h" + +#if ENABLE_DEBUGGING +# define dbgprintf printf +#else +# define dbgprintf if (0) printf +#endif + +#if EXPLICIT_YIELD +# define yield() thrd_yield () +#else +# define yield() +#endif + + +/* + * Condition check + */ +static int cond_value = 0; +static cnd_t condtest; +static mtx_t lockcond; + +static int +cnd_wait_routine (void *arg) +{ + ASSERT (mtx_lock (&lockcond) == thrd_success); + while (!cond_value) + { + ASSERT (cnd_wait (&condtest, &lockcond) == thrd_success); + } + ASSERT (mtx_unlock (&lockcond) == thrd_success); + + cond_value = 2; + + return 0; +} + +void +test_cnd_wait () +{ + struct timespec remain; + thrd_t thread; + int ret; + + remain.tv_sec = 2; + remain.tv_nsec = 0; + + cond_value = 0; + + ASSERT (thrd_create (&thread, cnd_wait_routine, NULL) == thrd_success); + do + { + yield (); + ret = thrd_sleep (&remain, &remain); + ASSERT (ret >= -1); + } + while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0)); + + /* signal condition */ + ASSERT (mtx_lock (&lockcond) == thrd_success); + cond_value = 1; + ASSERT (cnd_signal (&condtest) == thrd_success); + ASSERT (mtx_unlock (&lockcond) == thrd_success); + + ASSERT (thrd_join (thread, NULL) == thrd_success); + + if (cond_value != 2) + abort (); +} + + +/* + * Timed Condition check + */ +static int cond_timeout; + +static void +get_ts (struct timespec *ts) +{ + struct timeval now; + + gettimeofday (&now, NULL); + + ts->tv_sec = now.tv_sec + 1; + ts->tv_nsec = now.tv_usec * 1000; +} + +static int +cnd_timedwait_routine (void *arg) +{ + int ret; + struct timespec ts; + + ASSERT (mtx_lock (&lockcond) == thrd_success); + while (!cond_value) + { + get_ts (&ts); + ret = cnd_timedwait (&condtest, &lockcond, &ts); + if (ret == thrd_timedout) + cond_timeout = 1; + } + ASSERT (mtx_unlock (&lockcond) == thrd_success); + + return 0; +} + +static void +test_cnd_timedwait (void) +{ + struct timespec remain; + thrd_t thread; + int ret; + + remain.tv_sec = 2; + remain.tv_nsec = 0; + + cond_value = cond_timeout = 0; + + ASSERT (thrd_create (&thread, cnd_timedwait_routine, NULL) == thrd_success); + do + { + yield (); + ret = thrd_sleep (&remain, &remain); + ASSERT (ret >= -1); + } + while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0)); + + /* signal condition */ + ASSERT (mtx_lock (&lockcond) == thrd_success); + cond_value = 1; + ASSERT (cnd_signal (&condtest) == thrd_success); + ASSERT (mtx_unlock (&lockcond) == thrd_success); + + ASSERT (thrd_join (thread, NULL) == thrd_success); + + if (!cond_timeout) + abort (); +} + +int +main () +{ +#if HAVE_DECL_ALARM + /* Declare failure if test takes too long, by using default abort + caused by SIGALRM. */ + int alarm_value = 600; + signal (SIGALRM, SIG_DFL); + alarm (alarm_value); +#endif + + ASSERT (cnd_init (&condtest) == thrd_success); + ASSERT (mtx_init (&lockcond, mtx_plain) == thrd_success); + +#if DO_TEST_COND + printf ("Starting test_cnd_wait ..."); fflush (stdout); + test_cnd_wait (); + printf (" OK\n"); fflush (stdout); +#endif +#if DO_TEST_TIMEDCOND + printf ("Starting test_cnd_timedwait ..."); fflush (stdout); + test_cnd_timedwait (); + printf (" OK\n"); fflush (stdout); +#endif + + return 0; +} -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0025-tss-Add-tests.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0025-tss-Add-tests.patch" >From 14a5f1378bf1a062cf2163a300cc1991ebe6443f Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:40:39 +0200 Subject: [PATCH 25/26] tss: Add tests. * tests/test-tss.c: New file, based on tests/test-tls.c. * modules/tss-tests: New file. --- ChangeLog | 6 ++ modules/tss-tests | 15 ++++ tests/test-tss.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 modules/tss-tests create mode 100644 tests/test-tss.c diff --git a/ChangeLog b/ChangeLog index 2d3ee5e..4f1d724 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2019-06-20 Bruno Haible + tss: Add tests. + * tests/test-tss.c: New file, based on tests/test-tls.c. + * modules/tss-tests: New file. + +2019-06-20 Bruno Haible + cnd: Add tests. * tests/test-cnd.c: New file, based on tests/test-cond.c. * modules/cnd-tests: New file. diff --git a/modules/tss-tests b/modules/tss-tests new file mode 100644 index 0000000..0fbb20e --- /dev/null +++ b/modules/tss-tests @@ -0,0 +1,15 @@ +Files: +tests/test-tss.c +tests/macros.h + +Depends-on: +thrd +stdint + +configure.ac: +AC_CHECK_DECLS_ONCE([alarm]) + +Makefile.am: +TESTS += test-tss +check_PROGRAMS += test-tss +test_tss_LDADD = $(LDADD) @LIBSTDTHREAD@ diff --git a/tests/test-tss.c b/tests/test-tss.c new file mode 100644 index 0000000..b23767d --- /dev/null +++ b/tests/test-tss.c @@ -0,0 +1,203 @@ +/* Test of thread-local storage in multithreaded situations. + Copyright (C) 2005, 2008-2019 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 , 2005. */ + +#include + +/* Whether to help the scheduler through explicit yield(). + Uncomment this to see if the operating system has a fair scheduler. */ +#define EXPLICIT_YIELD 1 + +/* Whether to print debugging messages. */ +#define ENABLE_DEBUGGING 0 + +/* Number of simultaneous threads. */ +#define THREAD_COUNT 16 + +/* Number of operations performed in each thread. */ +#define REPEAT_COUNT 50000 + +#include +#include +#include +#include +#include + +#if HAVE_DECL_ALARM +# include +# include +#endif + +#include "macros.h" + +#if ENABLE_DEBUGGING +# define dbgprintf printf +#else +# define dbgprintf if (0) printf +#endif + +#if EXPLICIT_YIELD +# define yield() thrd_yield () +#else +# define yield() +#endif + +/* Returns a reference to the current thread as a pointer, for debugging. */ +#if defined __MVS__ + /* On IBM z/OS, pthread_t is a struct with an 8-byte '__' field. + The first three bytes of this field appear to uniquely identify a + pthread_t, though not necessarily representing a pointer. */ +# define thrd_current_pointer() (*((void **) thrd_current ().__)) +#elif defined __sun + /* On Solaris, thrd_t is merely an 'unsigned int'. */ +# define thrd_current_pointer() ((void *) (uintptr_t) thrd_current ()) +#else +# define thrd_current_pointer() ((void *) thrd_current ()) +#endif + +static void +perhaps_yield (void) +{ + /* Call yield () only with a certain probability, otherwise the + sequence of thread activations may be too predictable. */ + if ((((unsigned int) rand () >> 3) % 4) == 0) + yield (); +} + + +/* ----------------------- Test thread-local storage ----------------------- */ + +#define KEYS_COUNT 4 + +static tss_t mykeys[KEYS_COUNT]; + +static int +worker_thread (void *arg) +{ + unsigned int id = (unsigned int) (uintptr_t) arg; + int i, j, repeat; + unsigned int values[KEYS_COUNT]; + + dbgprintf ("Worker %p started\n", thrd_current_pointer ()); + + /* Initialize the per-thread storage. */ + for (i = 0; i < KEYS_COUNT; i++) + { + values[i] = (((unsigned int) rand () >> 3) % 1000000) * THREAD_COUNT + id; + /* Hopefully no arithmetic overflow. */ + if ((values[i] % THREAD_COUNT) != id) + abort (); + } + perhaps_yield (); + + /* Verify that the initial value is NULL. */ + dbgprintf ("Worker %p before initial verify\n", thrd_current_pointer ()); + for (i = 0; i < KEYS_COUNT; i++) + if (tss_get (mykeys[i]) != NULL) + abort (); + dbgprintf ("Worker %p after initial verify\n", thrd_current_pointer ()); + perhaps_yield (); + + /* Initialize the per-thread storage. */ + dbgprintf ("Worker %p before first tls_set\n", thrd_current_pointer ()); + for (i = 0; i < KEYS_COUNT; i++) + { + unsigned int *ptr = (unsigned int *) malloc (sizeof (unsigned int)); + *ptr = values[i]; + ASSERT (tss_set (mykeys[i], ptr) == thrd_success); + } + dbgprintf ("Worker %p after first tls_set\n", thrd_current_pointer ()); + perhaps_yield (); + + /* Shuffle around the pointers. */ + for (repeat = REPEAT_COUNT; repeat > 0; repeat--) + { + dbgprintf ("Worker %p doing value swapping\n", thrd_current_pointer ()); + i = ((unsigned int) rand () >> 3) % KEYS_COUNT; + j = ((unsigned int) rand () >> 3) % KEYS_COUNT; + if (i != j) + { + void *vi = tss_get (mykeys[i]); + void *vj = tss_get (mykeys[j]); + + ASSERT (tss_set (mykeys[i], vj) == thrd_success); + ASSERT (tss_set (mykeys[j], vi) == thrd_success); + } + perhaps_yield (); + } + + /* Verify that all the values are from this thread. */ + dbgprintf ("Worker %p before final verify\n", thrd_current_pointer ()); + for (i = 0; i < KEYS_COUNT; i++) + if ((*(unsigned int *) tss_get (mykeys[i]) % THREAD_COUNT) != id) + abort (); + dbgprintf ("Worker %p after final verify\n", thrd_current_pointer ()); + perhaps_yield (); + + dbgprintf ("Worker %p dying.\n", thrd_current_pointer ()); + return 0; +} + +static void +test_tss (void) +{ + int pass, i; + + for (pass = 0; pass < 2; pass++) + { + thrd_t threads[THREAD_COUNT]; + + if (pass == 0) + for (i = 0; i < KEYS_COUNT; i++) + ASSERT (tss_create (&mykeys[i], free) == thrd_success); + else + for (i = KEYS_COUNT - 1; i >= 0; i--) + ASSERT (tss_create (&mykeys[i], free) == thrd_success); + + /* Spawn the threads. */ + for (i = 0; i < THREAD_COUNT; i++) + ASSERT (thrd_create (&threads[i], worker_thread, NULL) == thrd_success); + + /* Wait for the threads to terminate. */ + for (i = 0; i < THREAD_COUNT; i++) + ASSERT (thrd_join (threads[i], NULL) == thrd_success); + + for (i = 0; i < KEYS_COUNT; i++) + tss_delete (mykeys[i]); + } +} + + +/* -------------------------------------------------------------------------- */ + +int +main () +{ +#if HAVE_DECL_ALARM + /* Declare failure if test takes too long, by using default abort + caused by SIGALRM. */ + int alarm_value = 600; + signal (SIGALRM, SIG_DFL); + alarm (alarm_value); +#endif + + printf ("Starting test_tss ..."); fflush (stdout); + test_tss (); + printf (" OK\n"); fflush (stdout); + + return 0; +} -- 2.7.4 --nextPart10702591.pDCx4yai7z Content-Disposition: attachment; filename="0026-threads-New-module.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0026-threads-New-module.patch" >From 0dbc0378bf27549034a43acb123a36e29866e399 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:41:03 +0200 Subject: [PATCH 26/26] threads: New module. * modules/threads: New file. --- ChangeLog | 5 +++++ modules/threads | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 modules/threads diff --git a/ChangeLog b/ChangeLog index 4f1d724..0807690 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2019-06-20 Bruno Haible + threads: New module. + * modules/threads: New file. + +2019-06-20 Bruno Haible + tss: Add tests. * tests/test-tss.c: New file, based on tests/test-tls.c. * modules/tss-tests: New file. diff --git a/modules/threads b/modules/threads new file mode 100644 index 0000000..2693bd5 --- /dev/null +++ b/modules/threads @@ -0,0 +1,27 @@ +Description: +ISO C 11 multithreading functions. + +Files: + +Depends-on: +threads-h +thrd +mtx +cnd +tss + +configure.ac: + +Makefile.am: + +Include: + + +Link: +$(LTLIBSTDTHREAD) when linking with libtool, $(LIBSTDTHREAD) otherwise + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4 --nextPart10702591.pDCx4yai7z--