>From 145e16d89f89e000ff6a4f1892b17e34560f9e96 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 20 Jun 2019 04:02:52 +0200 Subject: [PATCH 05/26] pthread_mutex_timedlock: New module. * lib/pthread.in.h (pthread_mutex_timedlock): New dummy function and new declaration. * lib/pthread_mutex_timedlock.c: New file. * m4/pthread_mutex_timedlock.m4: New file. * m4/pthread.m4 (gl_PTHREAD_CHECK): Don't call AC_LIBOBJ here. Test whether pthread_mutex_timedlock is declared. (gl_PTHREAD_MODULE_INDICATOR): New macro. (gl_PTHREAD_DEFAULTS): Initialize GNULIB_PTHREAD_MUTEX_TIMEDLOCK, HAVE_PTHREAD_MUTEX_TIMEDLOCK. * modules/pthread (configure.ac): Call AC_LIBOBJ here. (Makefile.am): Substitute GNULIB_PTHREAD_MUTEX_TIMEDLOCK, HAVE_PTHREAD_MUTEX_TIMEDLOCK. * modules/pthread_mutex_timedlock: New file. * doc/posix-functions/pthread_mutex_timedlock.texi: Mention the new module. --- ChangeLog | 19 ++++++ doc/posix-functions/pthread_mutex_timedlock.texi | 10 +-- lib/pthread.in.h | 26 +++++++ lib/pthread_mutex_timedlock.c | 87 ++++++++++++++++++++++++ m4/pthread.m4 | 32 ++++++--- m4/pthread_mutex_timedlock.m4 | 13 ++++ modules/pthread | 5 ++ modules/pthread_mutex_timedlock | 28 ++++++++ 8 files changed, 207 insertions(+), 13 deletions(-) create mode 100644 lib/pthread_mutex_timedlock.c create mode 100644 m4/pthread_mutex_timedlock.m4 create mode 100644 modules/pthread_mutex_timedlock diff --git a/ChangeLog b/ChangeLog index a9fe91e..d9afc4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2019-06-20 Bruno Haible + pthread_mutex_timedlock: New module. + * lib/pthread.in.h (pthread_mutex_timedlock): New dummy function and + new declaration. + * lib/pthread_mutex_timedlock.c: New file. + * m4/pthread_mutex_timedlock.m4: New file. + * m4/pthread.m4 (gl_PTHREAD_CHECK): Don't call AC_LIBOBJ here. Test + whether pthread_mutex_timedlock is declared. + (gl_PTHREAD_MODULE_INDICATOR): New macro. + (gl_PTHREAD_DEFAULTS): Initialize GNULIB_PTHREAD_MUTEX_TIMEDLOCK, + HAVE_PTHREAD_MUTEX_TIMEDLOCK. + * modules/pthread (configure.ac): Call AC_LIBOBJ here. + (Makefile.am): Substitute GNULIB_PTHREAD_MUTEX_TIMEDLOCK, + HAVE_PTHREAD_MUTEX_TIMEDLOCK. + * modules/pthread_mutex_timedlock: New file. + * doc/posix-functions/pthread_mutex_timedlock.texi: Mention the new + module. + +2019-06-20 Bruno Haible + thread, lock, cond, tls: Recognize C11 multithreaded applications. * m4/threadlib.m4 (gl_THREADLIB_BODY): Test for . * lib/glthread/thread.h (c11_threads_in_use): New macro. diff --git a/doc/posix-functions/pthread_mutex_timedlock.texi b/doc/posix-functions/pthread_mutex_timedlock.texi index 888b310..aaa76eb 100644 --- a/doc/posix-functions/pthread_mutex_timedlock.texi +++ b/doc/posix-functions/pthread_mutex_timedlock.texi @@ -4,15 +4,17 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_timedlock.html} -Gnulib module: --- +Gnulib module: pthread_mutex_timedlock Portability problems fixed by Gnulib: @itemize +@item +This function is missing on some platforms: +Mac OS X 10.5, FreeBSD 5.2.1, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 9, Cygwin, mingw, MSVC 14, BeOS, Android 4.4. +But the provided replacement is just a dummy on some of these platforms: +Minix 3.1.8, HP-UX 11, IRIX 5.3, Solaris 2.4, mingw, MSVC 14, BeOS. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on some platforms: -Mac OS X 10.5, FreeBSD 5.2.1, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 9, Cygwin, mingw, MSVC 14, BeOS, Android 4.4. @end itemize diff --git a/lib/pthread.in.h b/lib/pthread.in.h index 1deef7d..cd3cf1f 100644 --- a/lib/pthread.in.h +++ b/lib/pthread.in.h @@ -252,6 +252,14 @@ pthread_mutex_trylock (pthread_mutex_t *mutex) } _GL_PTHREAD_INLINE int +pthread_mutex_timedlock (pthread_mutex_t *mutex, const struct timespec *abstime) +{ + /* There is only one thread, so it always gets the lock. This + implementation does not support PTHREAD_MUTEX_ERRORCHECK. */ + return 0; +} + +_GL_PTHREAD_INLINE int pthread_mutex_unlock (pthread_mutex_t *mutex) { /* There is only one thread, so it always unlocks successfully. @@ -263,6 +271,24 @@ pthread_mutex_unlock (pthread_mutex_t *mutex) # define GNULIB_defined_pthread_functions 1 # endif +#else + +# if @GNULIB_PTHREAD_MUTEX_TIMEDLOCK@ +# if !@HAVE_PTHREAD_MUTEX_TIMEDLOCK@ +_GL_FUNCDECL_SYS (pthread_mutex_timedlock, int, + (pthread_mutex_t *, const struct timespec *)); +# endif +_GL_CXXALIAS_SYS (pthread_mutex_timedlock, int, + (pthread_mutex_t *, const struct timespec *)); +_GL_CXXALIASWARN (pthread_mutex_timedlock); +# elif defined GNULIB_POSIXCHECK +# undef pthread_mutex_timedlock +# if HAVE_RAW_DECL_PTHREAD_MUTEX_TIMEDLOCK +_GL_WARN_ON_USE (pthread_mutex_timedlock, "pthread_mutex_timedlock is unportable - " + "use gnulib module pthread_mutex_timedlock for portability"); +# endif +# endif + #endif #if ! @HAVE_PTHREAD_SPINLOCK_T@ diff --git a/lib/pthread_mutex_timedlock.c b/lib/pthread_mutex_timedlock.c new file mode 100644 index 0000000..9b6bc63 --- /dev/null +++ b/lib/pthread_mutex_timedlock.c @@ -0,0 +1,87 @@ +/* Lock a mutex, abandoning after a certain time. + 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 . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include + +int +pthread_mutex_timedlock (pthread_mutex_t *mutex, const struct timespec *abstime) +{ + /* Poll the mutex's state in regular intervals. Ugh. */ + /* POSIX says: + "Under no circumstance shall the function fail with a timeout if + the mutex can be locked immediately. The validity of the abstime + parameter need not be checked if the mutex can be locked + immediately." + Therefore start the loop with a pthread_mutex_trylock call. */ + for (;;) + { + int err; + struct timeval currtime; + unsigned long remaining; + struct timespec duration; + + err = pthread_mutex_trylock (mutex); + if (err != EBUSY) + return err; + + gettimeofday (&currtime, NULL); + + if (currtime.tv_sec > abstime->tv_sec) + remaining = 0; + else + { + unsigned long seconds = abstime->tv_sec - currtime.tv_sec; + remaining = seconds * 1000000000; + if (remaining / 1000000000 != seconds) /* overflow? */ + remaining = ULONG_MAX; + else + { + long nanoseconds = + abstime->tv_nsec - currtime.tv_usec * 1000; + if (nanoseconds >= 0) + { + remaining += nanoseconds; + if (remaining < nanoseconds) /* overflow? */ + remaining = ULONG_MAX; + } + else + { + if (remaining >= - nanoseconds) + remaining -= (- nanoseconds); + else + remaining = 0; + } + } + } + if (remaining == 0) + return ETIMEDOUT; + + /* Sleep 1 ms. */ + duration.tv_sec = 0; + duration.tv_nsec = 1000000; + if (duration.tv_nsec > remaining) + duration.tv_nsec = remaining; + nanosleep (&duration, NULL); + } +} diff --git a/m4/pthread.m4 b/m4/pthread.m4 index 0a219d7..bccac96 100644 --- a/m4/pthread.m4 +++ b/m4/pthread.m4 @@ -1,4 +1,4 @@ -# pthread.m4 serial 10 +# pthread.m4 serial 11 dnl Copyright (C) 2009-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, @@ -39,19 +39,22 @@ AC_DEFUN([gl_PTHREAD_CHECK], HAVE_PTHREAD_SPINLOCK_T=0 fi - if test $ac_cv_header_pthread_h != yes || - test $ac_cv_type_pthread_t != yes || - test $ac_cv_type_pthread_spinlock_t != yes; then + if test $HAVE_PTHREAD_H = 0 || test $HAVE_PTHREAD_T = 0 || test $HAVE_PTHREAD_SPINLOCK_T = 0; then PTHREAD_H='pthread.h' - AC_LIBOBJ([pthread]) elif test $gl_cv_header_pthread_h_pollution = yes; then - PTHREAD_H=pthread.h + PTHREAD_H='pthread.h' else PTHREAD_H= fi AC_SUBST([PTHREAD_H]) AM_CONDITIONAL([GL_GENERATE_PTHREAD_H], [test -n "$PTHREAD_H"]) + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use, if it is not common + dnl enough to be declared everywhere. + gl_WARN_ON_USE_PREPARE([[#include + ]], [pthread_mutex_timedlock]) + LIB_PTHREAD= if test $ac_cv_header_pthread_h = yes; then dnl We cannot use AC_SEARCH_LIBS here, because on OSF/1 5.1 pthread_join @@ -91,10 +94,21 @@ AC_DEFUN([gl_PTHREAD_CHECK], AC_REQUIRE([AC_C_RESTRICT]) ]) +AC_DEFUN([gl_PTHREAD_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_PTHREAD_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_PTHREAD_DEFAULTS], [ + GNULIB_PTHREAD_MUTEX_TIMEDLOCK=0; AC_SUBST([GNULIB_PTHREAD_MUTEX_TIMEDLOCK]) dnl Assume proper GNU behavior unless another module says otherwise. - HAVE_PTHREAD_H=1; AC_SUBST([HAVE_PTHREAD_H]) - HAVE_PTHREAD_T=1; AC_SUBST([HAVE_PTHREAD_T]) - HAVE_PTHREAD_SPINLOCK_T=1; AC_SUBST([HAVE_PTHREAD_SPINLOCK_T]) + HAVE_PTHREAD_H=1; AC_SUBST([HAVE_PTHREAD_H]) + HAVE_PTHREAD_T=1; AC_SUBST([HAVE_PTHREAD_T]) + HAVE_PTHREAD_SPINLOCK_T=1; AC_SUBST([HAVE_PTHREAD_SPINLOCK_T]) + HAVE_PTHREAD_MUTEX_TIMEDLOCK=1; AC_SUBST([HAVE_PTHREAD_MUTEX_TIMEDLOCK]) ]) diff --git a/m4/pthread_mutex_timedlock.m4 b/m4/pthread_mutex_timedlock.m4 new file mode 100644 index 0000000..664670f --- /dev/null +++ b/m4/pthread_mutex_timedlock.m4 @@ -0,0 +1,13 @@ +# pthread_mutex_timedlock.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_PTHREAD_MUTEX_TIMEDLOCK], +[ + AC_REQUIRE([gl_PTHREAD_DEFAULTS]) + + AC_CHECK_DECL([pthread_mutex_timedlock], , [HAVE_PTHREAD_MUTEX_TIMEDLOCK=0], + [[#include ]]) +]) diff --git a/modules/pthread b/modules/pthread index 3fb3920..81e2aad 100644 --- a/modules/pthread +++ b/modules/pthread @@ -18,6 +18,9 @@ AC_DEFINE([_THREAD_SAFE], 1, [For thread-safety on AIX, FreeBSD.]) configure.ac: gl_PTHREAD_CHECK +if test $HAVE_PTHREAD_H = 0 || test $HAVE_PTHREAD_T = 0 || test $HAVE_PTHREAD_SPINLOCK_T = 0; then + AC_LIBOBJ([pthread]) +fi gl_MODULE_INDICATOR([pthread]) Makefile.am: @@ -35,8 +38,10 @@ pthread.h: pthread.in.h $(top_builddir)/config.status -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_PTHREAD_H''@|$(NEXT_PTHREAD_H)|g' \ + -e 's/@''GNULIB_PTHREAD_MUTEX_TIMEDLOCK''@/$(GNULIB_PTHREAD_MUTEX_TIMEDLOCK)/g' \ -e 's|@''HAVE_PTHREAD_T''@|$(HAVE_PTHREAD_T)|g' \ -e 's|@''HAVE_PTHREAD_SPINLOCK_T''@|$(HAVE_PTHREAD_SPINLOCK_T)|g' \ + -e 's|@''HAVE_PTHREAD_MUTEX_TIMEDLOCK''@|$(HAVE_PTHREAD_MUTEX_TIMEDLOCK)|g' \ < $(srcdir)/pthread.in.h; \ } > $@-t && \ mv $@-t $@ diff --git a/modules/pthread_mutex_timedlock b/modules/pthread_mutex_timedlock new file mode 100644 index 0000000..2ae39f4 --- /dev/null +++ b/modules/pthread_mutex_timedlock @@ -0,0 +1,28 @@ +Description: +Lock a mutex, abandoning after a certain time. + +Files: +lib/pthread_mutex_timedlock.c +m4/pthread_mutex_timedlock.m4 + +Depends-on: +pthread +nanosleep [test $HAVE_PTHREAD_T = 1 && test $HAVE_PTHREAD_MUTEX_TIMEDLOCK = 0] + +configure.ac: +gl_FUNC_PTHREAD_MUTEX_TIMEDLOCK +if test $HAVE_PTHREAD_T = 1 && test $HAVE_PTHREAD_MUTEX_TIMEDLOCK = 0; then + AC_LIBOBJ([pthread_mutex_timedlock]) +fi +gl_PTHREAD_MODULE_INDICATOR([pthread_mutex_timedlock]) + +Makefile.am: + +Include: + + +License: +LGPLv2+ + +Maintainer: +all -- 2.7.4