diff options
author | Simon Josefsson <simon@josefsson.org> | 2011-05-20 22:37:02 +0200 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2011-05-20 22:37:02 +0200 |
commit | 2bd4123f0ad3b694e8cfadc15d0fe1b16e36bc49 (patch) | |
tree | afe003c7902bc7367b573967c6c217956bfdfa48 /gl | |
parent | 14cdffd508a834f0df1935732455c40432ad36b0 (diff) | |
download | gnutls-2bd4123f0ad3b694e8cfadc15d0fe1b16e36bc49.tar.gz |
Update gnulib files.
Diffstat (limited to 'gl')
-rw-r--r-- | gl/Makefile.am | 30 | ||||
-rw-r--r-- | gl/alignof.h | 2 | ||||
-rw-r--r-- | gl/glthread/lock.c | 1058 | ||||
-rw-r--r-- | gl/glthread/lock.h | 927 | ||||
-rw-r--r-- | gl/glthread/threadlib.c | 74 | ||||
-rw-r--r-- | gl/hmac-md5.c | 4 | ||||
-rw-r--r-- | gl/intprops.h | 29 | ||||
-rw-r--r-- | gl/m4/gnulib-cache.m4 | 3 | ||||
-rw-r--r-- | gl/m4/gnulib-comp.m4 | 29 | ||||
-rw-r--r-- | gl/m4/strerror.m4 | 21 | ||||
-rw-r--r-- | gl/m4/strerror_r.m4 | 108 | ||||
-rw-r--r-- | gl/m4/thread.m4 | 18 | ||||
-rw-r--r-- | gl/m4/valgrind-tests.m4 | 2 | ||||
-rw-r--r-- | gl/m4/yield.m4 | 19 | ||||
-rw-r--r-- | gl/memxor.c | 2 | ||||
-rw-r--r-- | gl/memxor.h | 2 | ||||
-rw-r--r-- | gl/stdint.in.h | 2 | ||||
-rw-r--r-- | gl/strerror-impl.h | 42 | ||||
-rw-r--r-- | gl/strerror.c | 327 | ||||
-rw-r--r-- | gl/strerror_r.c | 650 | ||||
-rw-r--r-- | gl/tests/Makefile.am | 33 | ||||
-rw-r--r-- | gl/tests/dummy.c | 42 | ||||
-rw-r--r-- | gl/tests/glthread/thread.c | 218 | ||||
-rw-r--r-- | gl/tests/glthread/thread.h | 376 | ||||
-rw-r--r-- | gl/tests/glthread/yield.h | 121 | ||||
-rw-r--r-- | gl/tests/test-intprops.c | 456 | ||||
-rw-r--r-- | gl/tests/test-lock.c | 601 | ||||
-rw-r--r-- | gl/tests/test-strerror.c | 18 | ||||
-rw-r--r-- | gl/tests/test-strerror_r.c | 112 |
29 files changed, 624 insertions, 4702 deletions
diff --git a/gl/Makefile.am b/gl/Makefile.am index 98f9f45c33..b295abeee2 100644 --- a/gl/Makefile.am +++ b/gl/Makefile.am @@ -9,9 +9,9 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lseek-tests --libtool --macro-prefix=gl alloca byteswap c-ctype crypto/hmac-md5 crypto/md5 error extensions func getpass gettext gettime havelib lib-msvc-compat lib-symbol-versions manywarnings memmem-simple minmax netdb netinet_in progname read-file snprintf sockets socklen stdint strcase strverscmp sys_socket sys_stat time_r timespec u64 unistd valgrind-tests vasprintf version-etc version-etc-fsf vsnprintf warnings +# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lseek-tests --libtool --macro-prefix=gl --no-vc-files alloca byteswap c-ctype crypto/hmac-md5 crypto/md5 error extensions func getpass gettext gettime havelib lib-msvc-compat lib-symbol-versions manywarnings memmem-simple minmax netdb netinet_in progname read-file snprintf sockets socklen stdint strcase strverscmp sys_socket sys_stat time_r timespec u64 unistd valgrind-tests vasprintf version-etc version-etc-fsf vsnprintf warnings -AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects +AUTOMAKE_OPTIONS = 1.5 gnits SUBDIRS = noinst_HEADERS = @@ -42,7 +42,6 @@ libgnu_la_LDFLAGS += -no-undefined libgnu_la_LDFLAGS += $(LIBSOCKET) libgnu_la_LDFLAGS += $(LIB_CLOCK_GETTIME) libgnu_la_LDFLAGS += $(LTLIBINTL) -libgnu_la_LDFLAGS += $(LTLIBTHREAD) ## begin gnulib module alignof @@ -356,12 +355,6 @@ EXTRA_DIST += intprops.h ## end gnulib module intprops -## begin gnulib module lock - -libgnu_la_SOURCES += glthread/lock.h glthread/lock.c - -## end gnulib module lock - ## begin gnulib module lseek @@ -884,21 +877,12 @@ EXTRA_libgnu_la_SOURCES += strdup.c ## begin gnulib module strerror -EXTRA_DIST += strerror-impl.h strerror.c +EXTRA_DIST += strerror.c EXTRA_libgnu_la_SOURCES += strerror.c ## end gnulib module strerror -## begin gnulib module strerror_r-posix - - -EXTRA_DIST += strerror_r.c - -EXTRA_libgnu_la_SOURCES += strerror_r.c - -## end gnulib module strerror_r-posix - ## begin gnulib module string BUILT_SOURCES += string.h @@ -1194,14 +1178,6 @@ EXTRA_DIST += sys_uio.in.h ## end gnulib module sys_uio -## begin gnulib module threadlib - -libgnu_la_SOURCES += glthread/threadlib.c - -EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath - -## end gnulib module threadlib - ## begin gnulib module time BUILT_SOURCES += time.h diff --git a/gl/alignof.h b/gl/alignof.h index 1c1f75c5e7..03bed6f4a9 100644 --- a/gl/alignof.h +++ b/gl/alignof.h @@ -31,7 +31,7 @@ # define alignof_slot(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) #endif -/* Determine the good alignment of an object of the given type at compile time. +/* Determine the good alignment of a object of the given type at compile time. Note that this is not necessarily the same as alignof_slot(type). For example, with GNU C on x86 platforms: alignof_type(double) = 8, but - when -malign-double is not specified: alignof_slot(double) = 4, diff --git a/gl/glthread/lock.c b/gl/glthread/lock.c deleted file mode 100644 index 64dbd3f518..0000000000 --- a/gl/glthread/lock.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* Locking in multithreaded situations. - Copyright (C) 2005-2011 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, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Bruno Haible <bruno@clisp.org>, 2005. - Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, - gthr-win32.h. */ - -#include <config.h> - -#include "glthread/lock.h" - -/* ========================================================================= */ - -#if USE_POSIX_THREADS - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -# if HAVE_PTHREAD_RWLOCK - -# if !defined PTHREAD_RWLOCK_INITIALIZER - -int -glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) -{ - int err; - - err = pthread_rwlock_init (&lock->rwlock, NULL); - if (err != 0) - return err; - lock->initialized = 1; - return 0; -} - -int -glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) -{ - if (!lock->initialized) - { - int err; - - err = pthread_mutex_lock (&lock->guard); - if (err != 0) - return err; - if (!lock->initialized) - { - err = glthread_rwlock_init_multithreaded (lock); - if (err != 0) - { - pthread_mutex_unlock (&lock->guard); - return err; - } - } - err = pthread_mutex_unlock (&lock->guard); - if (err != 0) - return err; - } - return pthread_rwlock_rdlock (&lock->rwlock); -} - -int -glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) -{ - if (!lock->initialized) - { - int err; - - err = pthread_mutex_lock (&lock->guard); - if (err != 0) - return err; - if (!lock->initialized) - { - err = glthread_rwlock_init_multithreaded (lock); - if (err != 0) - { - pthread_mutex_unlock (&lock->guard); - return err; - } - } - err = pthread_mutex_unlock (&lock->guard); - if (err != 0) - return err; - } - return pthread_rwlock_wrlock (&lock->rwlock); -} - -int -glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) -{ - if (!lock->initialized) - return EINVAL; - return pthread_rwlock_unlock (&lock->rwlock); -} - -int -glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) -{ - int err; - - if (!lock->initialized) - return EINVAL; - err = pthread_rwlock_destroy (&lock->rwlock); - if (err != 0) - return err; - lock->initialized = 0; - return 0; -} - -# endif - -# else - -int -glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) -{ - int err; - - err = pthread_mutex_init (&lock->lock, NULL); - if (err != 0) - return err; - err = pthread_cond_init (&lock->waiting_readers, NULL); - if (err != 0) - return err; - err = pthread_cond_init (&lock->waiting_writers, NULL); - if (err != 0) - return err; - lock->waiting_writers_count = 0; - lock->runcount = 0; - return 0; -} - -int -glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) -{ - int err; - - err = pthread_mutex_lock (&lock->lock); - if (err != 0) - return err; - /* Test whether only readers are currently running, and whether the runcount - field will not overflow. */ - /* POSIX says: "It is implementation-defined whether the calling thread - acquires the lock when a writer does not hold the lock and there are - writers blocked on the lock." Let's say, no: give the writers a higher - priority. */ - while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0)) - { - /* This thread has to wait for a while. Enqueue it among the - waiting_readers. */ - err = pthread_cond_wait (&lock->waiting_readers, &lock->lock); - if (err != 0) - { - pthread_mutex_unlock (&lock->lock); - return err; - } - } - lock->runcount++; - return pthread_mutex_unlock (&lock->lock); -} - -int -glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) -{ - int err; - - err = pthread_mutex_lock (&lock->lock); - if (err != 0) - return err; - /* Test whether no readers or writers are currently running. */ - while (!(lock->runcount == 0)) - { - /* This thread has to wait for a while. Enqueue it among the - waiting_writers. */ - lock->waiting_writers_count++; - err = pthread_cond_wait (&lock->waiting_writers, &lock->lock); - if (err != 0) - { - lock->waiting_writers_count--; - pthread_mutex_unlock (&lock->lock); - return err; - } - lock->waiting_writers_count--; - } - lock->runcount--; /* runcount becomes -1 */ - return pthread_mutex_unlock (&lock->lock); -} - -int -glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) -{ - int err; - - err = pthread_mutex_lock (&lock->lock); - if (err != 0) - return err; - if (lock->runcount < 0) - { - /* Drop a writer lock. */ - if (!(lock->runcount == -1)) - { - pthread_mutex_unlock (&lock->lock); - return EINVAL; - } - lock->runcount = 0; - } - else - { - /* Drop a reader lock. */ - if (!(lock->runcount > 0)) - { - pthread_mutex_unlock (&lock->lock); - return EINVAL; - } - lock->runcount--; - } - if (lock->runcount == 0) - { - /* POSIX recommends that "write locks shall take precedence over read - locks", to avoid "writer starvation". */ - if (lock->waiting_writers_count > 0) - { - /* Wake up one of the waiting writers. */ - err = pthread_cond_signal (&lock->waiting_writers); - if (err != 0) - { - pthread_mutex_unlock (&lock->lock); - return err; - } - } - else - { - /* Wake up all waiting readers. */ - err = pthread_cond_broadcast (&lock->waiting_readers); - if (err != 0) - { - pthread_mutex_unlock (&lock->lock); - return err; - } - } - } - return pthread_mutex_unlock (&lock->lock); -} - -int -glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) -{ - int err; - - err = pthread_mutex_destroy (&lock->lock); - if (err != 0) - return err; - err = pthread_cond_destroy (&lock->waiting_readers); - if (err != 0) - return err; - err = pthread_cond_destroy (&lock->waiting_writers); - if (err != 0) - return err; - return 0; -} - -# endif - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -# if HAVE_PTHREAD_MUTEX_RECURSIVE - -# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP - -int -glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) -{ - pthread_mutexattr_t attributes; - int err; - - err = pthread_mutexattr_init (&attributes); - if (err != 0) - return err; - err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); - if (err != 0) - { - pthread_mutexattr_destroy (&attributes); - return err; - } - err = pthread_mutex_init (lock, &attributes); - if (err != 0) - { - pthread_mutexattr_destroy (&attributes); - return err; - } - err = pthread_mutexattr_destroy (&attributes); - if (err != 0) - return err; - return 0; -} - -# else - -int -glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) -{ - pthread_mutexattr_t attributes; - int err; - - err = pthread_mutexattr_init (&attributes); - if (err != 0) - return err; - err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); - if (err != 0) - { - pthread_mutexattr_destroy (&attributes); - return err; - } - err = pthread_mutex_init (&lock->recmutex, &attributes); - if (err != 0) - { - pthread_mutexattr_destroy (&attributes); - return err; - } - err = pthread_mutexattr_destroy (&attributes); - if (err != 0) - return err; - lock->initialized = 1; - return 0; -} - -int -glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) -{ - if (!lock->initialized) - { - int err; - - err = pthread_mutex_lock (&lock->guard); - if (err != 0) - return err; - if (!lock->initialized) - { - err = glthread_recursive_lock_init_multithreaded (lock); - if (err != 0) - { - pthread_mutex_unlock (&lock->guard); - return err; - } - } - err = pthread_mutex_unlock (&lock->guard); - if (err != 0) - return err; - } - return pthread_mutex_lock (&lock->recmutex); -} - -int -glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) -{ - if (!lock->initialized) - return EINVAL; - return pthread_mutex_unlock (&lock->recmutex); -} - -int -glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) -{ - int err; - - if (!lock->initialized) - return EINVAL; - err = pthread_mutex_destroy (&lock->recmutex); - if (err != 0) - return err; - lock->initialized = 0; - return 0; -} - -# endif - -# else - -int -glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) -{ - int err; - - err = pthread_mutex_init (&lock->mutex, NULL); - if (err != 0) - return err; - lock->owner = (pthread_t) 0; - lock->depth = 0; - return 0; -} - -int -glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) -{ - pthread_t self = pthread_self (); - if (lock->owner != self) - { - int err; - - err = pthread_mutex_lock (&lock->mutex); - if (err != 0) - return err; - lock->owner = self; - } - if (++(lock->depth) == 0) /* wraparound? */ - { - lock->depth--; - return EAGAIN; - } - return 0; -} - -int -glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) -{ - if (lock->owner != pthread_self ()) - return EPERM; - if (lock->depth == 0) - return EINVAL; - if (--(lock->depth) == 0) - { - lock->owner = (pthread_t) 0; - return pthread_mutex_unlock (&lock->mutex); - } - else - return 0; -} - -int -glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) -{ - if (lock->owner != (pthread_t) 0) - return EBUSY; - return pthread_mutex_destroy (&lock->mutex); -} - -# endif - -/* -------------------------- gl_once_t datatype -------------------------- */ - -static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT; - -int -glthread_once_singlethreaded (pthread_once_t *once_control) -{ - /* We don't know whether pthread_once_t is an integer type, a floating-point - type, a pointer type, or a structure type. */ - char *firstbyte = (char *)once_control; - if (*firstbyte == *(const char *)&fresh_once) - { - /* First time use of once_control. Invert the first byte. */ - *firstbyte = ~ *(const char *)&fresh_once; - return 1; - } - else - return 0; -} - -#endif - -/* ========================================================================= */ - -#if USE_PTH_THREADS - -/* Use the GNU Pth threads library. */ - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -/* -------------------------- gl_once_t datatype -------------------------- */ - -static void -glthread_once_call (void *arg) -{ - void (**gl_once_temp_addr) (void) = (void (**) (void)) arg; - void (*initfunction) (void) = *gl_once_temp_addr; - initfunction (); -} - -int -glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)) -{ - void (*temp) (void) = initfunction; - return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0); -} - -int -glthread_once_singlethreaded (pth_once_t *once_control) -{ - /* We know that pth_once_t is an integer type. */ - if (*once_control == PTH_ONCE_INIT) - { - /* First time use of once_control. Invert the marker. */ - *once_control = ~ PTH_ONCE_INIT; - return 1; - } - else - return 0; -} - -#endif - -/* ========================================================================= */ - -#if USE_SOLARIS_THREADS - -/* Use the old Solaris threads library. */ - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -int -glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) -{ - int err; - - err = mutex_init (&lock->mutex, USYNC_THREAD, NULL); - if (err != 0) - return err; - lock->owner = (thread_t) 0; - lock->depth = 0; - return 0; -} - -int -glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) -{ - thread_t self = thr_self (); - if (lock->owner != self) - { - int err; - - err = mutex_lock (&lock->mutex); - if (err != 0) - return err; - lock->owner = self; - } - if (++(lock->depth) == 0) /* wraparound? */ - { - lock->depth--; - return EAGAIN; - } - return 0; -} - -int -glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) -{ - if (lock->owner != thr_self ()) - return EPERM; - if (lock->depth == 0) - return EINVAL; - if (--(lock->depth) == 0) - { - lock->owner = (thread_t) 0; - return mutex_unlock (&lock->mutex); - } - else - return 0; -} - -int -glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) -{ - if (lock->owner != (thread_t) 0) - return EBUSY; - return mutex_destroy (&lock->mutex); -} - -/* -------------------------- gl_once_t datatype -------------------------- */ - -int -glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)) -{ - if (!once_control->inited) - { - int err; - - /* Use the mutex to guarantee that if another thread is already calling - the initfunction, this thread waits until it's finished. */ - err = mutex_lock (&once_control->mutex); - if (err != 0) - return err; - if (!once_control->inited) - { - once_control->inited = 1; - initfunction (); - } - return mutex_unlock (&once_control->mutex); - } - else - return 0; -} - -int -glthread_once_singlethreaded (gl_once_t *once_control) -{ - /* We know that gl_once_t contains an integer type. */ - if (!once_control->inited) - { - /* First time use of once_control. Invert the marker. */ - once_control->inited = ~ 0; - return 1; - } - else - return 0; -} - -#endif - -/* ========================================================================= */ - -#if USE_WIN32_THREADS - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -void -glthread_lock_init_func (gl_lock_t *lock) -{ - InitializeCriticalSection (&lock->lock); - lock->guard.done = 1; -} - -int -glthread_lock_lock_func (gl_lock_t *lock) -{ - if (!lock->guard.done) - { - if (InterlockedIncrement (&lock->guard.started) == 0) - /* This thread is the first one to need this lock. Initialize it. */ - glthread_lock_init (lock); - else - /* Yield the CPU while waiting for another thread to finish - initializing this lock. */ - while (!lock->guard.done) - Sleep (0); - } - EnterCriticalSection (&lock->lock); - return 0; -} - -int -glthread_lock_unlock_func (gl_lock_t *lock) -{ - if (!lock->guard.done) - return EINVAL; - LeaveCriticalSection (&lock->lock); - return 0; -} - -int -glthread_lock_destroy_func (gl_lock_t *lock) -{ - if (!lock->guard.done) - return EINVAL; - DeleteCriticalSection (&lock->lock); - lock->guard.done = 0; - return 0; -} - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -/* In this file, the waitqueues are implemented as circular arrays. */ -#define gl_waitqueue_t gl_carray_waitqueue_t - -static inline void -gl_waitqueue_init (gl_waitqueue_t *wq) -{ - wq->array = NULL; - wq->count = 0; - wq->alloc = 0; - wq->offset = 0; -} - -/* Enqueues the current thread, represented by an event, in a wait queue. - Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */ -static HANDLE -gl_waitqueue_add (gl_waitqueue_t *wq) -{ - HANDLE event; - unsigned int index; - - if (wq->count == wq->alloc) - { - unsigned int new_alloc = 2 * wq->alloc + 1; - HANDLE *new_array = - (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE)); - if (new_array == NULL) - /* No more memory. */ - return INVALID_HANDLE_VALUE; - /* Now is a good opportunity to rotate the array so that its contents - starts at offset 0. */ - if (wq->offset > 0) - { - unsigned int old_count = wq->count; - unsigned int old_alloc = wq->alloc; - unsigned int old_offset = wq->offset; - unsigned int i; - if (old_offset + old_count > old_alloc) - { - unsigned int limit = old_offset + old_count - old_alloc; - for (i = 0; i < limit; i++) - new_array[old_alloc + i] = new_array[i]; - } - for (i = 0; i < old_count; i++) - new_array[i] = new_array[old_offset + i]; - wq->offset = 0; - } - wq->array = new_array; - wq->alloc = new_alloc; - } - /* Whether the created event is a manual-reset one or an auto-reset one, - does not matter, since we will wait on it only once. */ - event = CreateEvent (NULL, TRUE, FALSE, NULL); - if (event == INVALID_HANDLE_VALUE) - /* No way to allocate an event. */ - return INVALID_HANDLE_VALUE; - index = wq->offset + wq->count; - if (index >= wq->alloc) - index -= wq->alloc; - wq->array[index] = event; - wq->count++; - return event; -} - -/* Notifies the first thread from a wait queue and dequeues it. */ -static inline void -gl_waitqueue_notify_first (gl_waitqueue_t *wq) -{ - SetEvent (wq->array[wq->offset + 0]); - wq->offset++; - wq->count--; - if (wq->count == 0 || wq->offset == wq->alloc) - wq->offset = 0; -} - -/* Notifies all threads from a wait queue and dequeues them all. */ -static inline void -gl_waitqueue_notify_all (gl_waitqueue_t *wq) -{ - unsigned int i; - - for (i = 0; i < wq->count; i++) - { - unsigned int index = wq->offset + i; - if (index >= wq->alloc) - index -= wq->alloc; - SetEvent (wq->array[index]); - } - wq->count = 0; - wq->offset = 0; -} - -void -glthread_rwlock_init_func (gl_rwlock_t *lock) -{ - InitializeCriticalSection (&lock->lock); - gl_waitqueue_init (&lock->waiting_readers); - gl_waitqueue_init (&lock->waiting_writers); - lock->runcount = 0; - lock->guard.done = 1; -} - -int -glthread_rwlock_rdlock_func (gl_rwlock_t *lock) -{ - if (!lock->guard.done) - { - if (InterlockedIncrement (&lock->guard.started) == 0) - /* This thread is the first one to need this lock. Initialize it. */ - glthread_rwlock_init (lock); - else - /* Yield the CPU while waiting for another thread to finish - initializing this lock. */ - while (!lock->guard.done) - Sleep (0); - } - EnterCriticalSection (&lock->lock); - /* Test whether only readers are currently running, and whether the runcount - field will not overflow. */ - if (!(lock->runcount + 1 > 0)) - { - /* This thread has to wait for a while. Enqueue it among the - waiting_readers. */ - HANDLE event = gl_waitqueue_add (&lock->waiting_readers); - if (event != INVALID_HANDLE_VALUE) - { - DWORD result; - LeaveCriticalSection (&lock->lock); - /* Wait until another thread signals this event. */ - result = WaitForSingleObject (event, INFINITE); - if (result == WAIT_FAILED || result == WAIT_TIMEOUT) - abort (); - CloseHandle (event); - /* The thread which signalled the event already did the bookkeeping: - removed us from the waiting_readers, incremented lock->runcount. */ - if (!(lock->runcount > 0)) - abort (); - return 0; - } - else - { - /* Allocation failure. Weird. */ - do - { - LeaveCriticalSection (&lock->lock); - Sleep (1); - EnterCriticalSection (&lock->lock); - } - while (!(lock->runcount + 1 > 0)); - } - } - lock->runcount++; - LeaveCriticalSection (&lock->lock); - return 0; -} - -int -glthread_rwlock_wrlock_func (gl_rwlock_t *lock) -{ - if (!lock->guard.done) - { - if (InterlockedIncrement (&lock->guard.started) == 0) - /* This thread is the first one to need this lock. Initialize it. */ - glthread_rwlock_init (lock); - else - /* Yield the CPU while waiting for another thread to finish - initializing this lock. */ - while (!lock->guard.done) - Sleep (0); - } - EnterCriticalSection (&lock->lock); - /* Test whether no readers or writers are currently running. */ - if (!(lock->runcount == 0)) - { - /* This thread has to wait for a while. Enqueue it among the - waiting_writers. */ - HANDLE event = gl_waitqueue_add (&lock->waiting_writers); - if (event != INVALID_HANDLE_VALUE) - { - DWORD result; - LeaveCriticalSection (&lock->lock); - /* Wait until another thread signals this event. */ - result = WaitForSingleObject (event, INFINITE); - if (result == WAIT_FAILED || result == WAIT_TIMEOUT) - abort (); - CloseHandle (event); - /* The thread which signalled the event already did the bookkeeping: - removed us from the waiting_writers, set lock->runcount = -1. */ - if (!(lock->runcount == -1)) - abort (); - return 0; - } - else - { - /* Allocation failure. Weird. */ - do - { - LeaveCriticalSection (&lock->lock); - Sleep (1); - EnterCriticalSection (&lock->lock); - } - while (!(lock->runcount == 0)); - } - } - lock->runcount--; /* runcount becomes -1 */ - LeaveCriticalSection (&lock->lock); - return 0; -} - -int -glthread_rwlock_unlock_func (gl_rwlock_t *lock) -{ - if (!lock->guard.done) - return EINVAL; - EnterCriticalSection (&lock->lock); - if (lock->runcount < 0) - { - /* Drop a writer lock. */ - if (!(lock->runcount == -1)) - abort (); - lock->runcount = 0; - } - else - { - /* Drop a reader lock. */ - if (!(lock->runcount > 0)) - { - LeaveCriticalSection (&lock->lock); - return EPERM; - } - lock->runcount--; - } - if (lock->runcount == 0) - { - /* POSIX recommends that "write locks shall take precedence over read - locks", to avoid "writer starvation". */ - if (lock->waiting_writers.count > 0) - { - /* Wake up one of the waiting writers. */ - lock->runcount--; - gl_waitqueue_notify_first (&lock->waiting_writers); - } - else - { - /* Wake up all waiting readers. */ - lock->runcount += lock->waiting_readers.count; - gl_waitqueue_notify_all (&lock->waiting_readers); - } - } - LeaveCriticalSection (&lock->lock); - return 0; -} - -int -glthread_rwlock_destroy_func (gl_rwlock_t *lock) -{ - if (!lock->guard.done) - return EINVAL; - if (lock->runcount != 0) - return EBUSY; - DeleteCriticalSection (&lock->lock); - if (lock->waiting_readers.array != NULL) - free (lock->waiting_readers.array); - if (lock->waiting_writers.array != NULL) - free (lock->waiting_writers.array); - lock->guard.done = 0; - return 0; -} - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -void -glthread_recursive_lock_init_func (gl_recursive_lock_t *lock) -{ - lock->owner = 0; - lock->depth = 0; - InitializeCriticalSection (&lock->lock); - lock->guard.done = 1; -} - -int -glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock) -{ - if (!lock->guard.done) - { - if (InterlockedIncrement (&lock->guard.started) == 0) - /* This thread is the first one to need this lock. Initialize it. */ - glthread_recursive_lock_init (lock); - else - /* Yield the CPU while waiting for another thread to finish - initializing this lock. */ - while (!lock->guard.done) - Sleep (0); - } - { - DWORD self = GetCurrentThreadId (); - if (lock->owner != self) - { - EnterCriticalSection (&lock->lock); - lock->owner = self; - } - if (++(lock->depth) == 0) /* wraparound? */ - { - lock->depth--; - return EAGAIN; - } - } - return 0; -} - -int -glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock) -{ - if (lock->owner != GetCurrentThreadId ()) - return EPERM; - if (lock->depth == 0) - return EINVAL; - if (--(lock->depth) == 0) - { - lock->owner = 0; - LeaveCriticalSection (&lock->lock); - } - return 0; -} - -int -glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock) -{ - if (lock->owner != 0) - return EBUSY; - DeleteCriticalSection (&lock->lock); - lock->guard.done = 0; - return 0; -} - -/* -------------------------- gl_once_t datatype -------------------------- */ - -void -glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)) -{ - if (once_control->inited <= 0) - { - if (InterlockedIncrement (&once_control->started) == 0) - { - /* This thread is the first one to come to this once_control. */ - InitializeCriticalSection (&once_control->lock); - EnterCriticalSection (&once_control->lock); - once_control->inited = 0; - initfunction (); - once_control->inited = 1; - LeaveCriticalSection (&once_control->lock); - } - else - { - /* Undo last operation. */ - InterlockedDecrement (&once_control->started); - /* Some other thread has already started the initialization. - Yield the CPU while waiting for the other thread to finish - initializing and taking the lock. */ - while (once_control->inited < 0) - Sleep (0); - if (once_control->inited <= 0) - { - /* Take the lock. This blocks until the other thread has - finished calling the initfunction. */ - EnterCriticalSection (&once_control->lock); - LeaveCriticalSection (&once_control->lock); - if (!(once_control->inited > 0)) - abort (); - } - } - } -} - -#endif - -/* ========================================================================= */ diff --git a/gl/glthread/lock.h b/gl/glthread/lock.h deleted file mode 100644 index 6267500d52..0000000000 --- a/gl/glthread/lock.h +++ /dev/null @@ -1,927 +0,0 @@ -/* Locking in multithreaded situations. - Copyright (C) 2005-2011 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, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Bruno Haible <bruno@clisp.org>, 2005. - Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, - gthr-win32.h. */ - -/* This file contains locking primitives for use with a given thread library. - It does not contain primitives for creating threads or for other - synchronization primitives. - - Normal (non-recursive) locks: - Type: gl_lock_t - Declaration: gl_lock_define(extern, name) - Initializer: gl_lock_define_initialized(, name) - Initialization: gl_lock_init (name); - Taking the lock: gl_lock_lock (name); - Releasing the lock: gl_lock_unlock (name); - De-initialization: gl_lock_destroy (name); - Equivalent functions with control of error handling: - Initialization: err = glthread_lock_init (&name); - Taking the lock: err = glthread_lock_lock (&name); - Releasing the lock: err = glthread_lock_unlock (&name); - De-initialization: err = glthread_lock_destroy (&name); - - Read-Write (non-recursive) locks: - Type: gl_rwlock_t - Declaration: gl_rwlock_define(extern, name) - Initializer: gl_rwlock_define_initialized(, name) - Initialization: gl_rwlock_init (name); - Taking the lock: gl_rwlock_rdlock (name); - gl_rwlock_wrlock (name); - Releasing the lock: gl_rwlock_unlock (name); - De-initialization: gl_rwlock_destroy (name); - Equivalent functions with control of error handling: - Initialization: err = glthread_rwlock_init (&name); - Taking the lock: err = glthread_rwlock_rdlock (&name); - err = glthread_rwlock_wrlock (&name); - Releasing the lock: err = glthread_rwlock_unlock (&name); - De-initialization: err = glthread_rwlock_destroy (&name); - - Recursive locks: - Type: gl_recursive_lock_t - Declaration: gl_recursive_lock_define(extern, name) - Initializer: gl_recursive_lock_define_initialized(, name) - Initialization: gl_recursive_lock_init (name); - Taking the lock: gl_recursive_lock_lock (name); - Releasing the lock: gl_recursive_lock_unlock (name); - De-initialization: gl_recursive_lock_destroy (name); - Equivalent functions with control of error handling: - Initialization: err = glthread_recursive_lock_init (&name); - Taking the lock: err = glthread_recursive_lock_lock (&name); - Releasing the lock: err = glthread_recursive_lock_unlock (&name); - De-initialization: err = glthread_recursive_lock_destroy (&name); - - Once-only execution: - Type: gl_once_t - Initializer: gl_once_define(extern, name) - Execution: gl_once (name, initfunction); - Equivalent functions with control of error handling: - Execution: err = glthread_once (&name, initfunction); -*/ - - -#ifndef _LOCK_H -#define _LOCK_H - -#include <errno.h> -#include <stdlib.h> - -/* ========================================================================= */ - -#if USE_POSIX_THREADS - -/* Use the POSIX threads library. */ - -# include <pthread.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# if PTHREAD_IN_USE_DETECTION_HARD - -/* The pthread_in_use() detection needs to be done at runtime. */ -# define pthread_in_use() \ - glthread_in_use () -extern int glthread_in_use (void); - -# endif - -# if USE_POSIX_THREADS_WEAK - -/* Use weak references to the POSIX threads library. */ - -/* Weak references avoid dragging in external libraries if the other parts - of the program don't use them. Here we use them, because we don't want - every program that uses libintl to depend on libpthread. This assumes - that libpthread would not be loaded after libintl; i.e. if libintl is - loaded first, by an executable that does not depend on libpthread, and - then a module is dynamically loaded that depends on libpthread, libintl - will not be multithread-safe. */ - -/* The way to test at runtime whether libpthread is present is to test - whether a function pointer's value, such as &pthread_mutex_init, is - non-NULL. However, some versions of GCC have a bug through which, in - PIC mode, &foo != NULL always evaluates to true if there is a direct - call to foo(...) in the same function. To avoid this, we test the - address of a function in libpthread that we don't use. */ - -# pragma weak pthread_mutex_init -# pragma weak pthread_mutex_lock -# pragma weak pthread_mutex_unlock -# pragma weak pthread_mutex_destroy -# pragma weak pthread_rwlock_init -# pragma weak pthread_rwlock_rdlock -# pragma weak pthread_rwlock_wrlock -# pragma weak pthread_rwlock_unlock -# pragma weak pthread_rwlock_destroy -# pragma weak pthread_once -# pragma weak pthread_cond_init -# pragma weak pthread_cond_wait -# pragma weak pthread_cond_signal -# pragma weak pthread_cond_broadcast -# pragma weak pthread_cond_destroy -# pragma weak pthread_mutexattr_init -# pragma weak pthread_mutexattr_settype -# pragma weak pthread_mutexattr_destroy -# ifndef pthread_self -# pragma weak pthread_self -# endif - -# if !PTHREAD_IN_USE_DETECTION_HARD -# pragma weak pthread_cancel -# define pthread_in_use() (pthread_cancel != NULL) -# endif - -# else - -# if !PTHREAD_IN_USE_DETECTION_HARD -# define pthread_in_use() 1 -# endif - -# endif - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -typedef pthread_mutex_t gl_lock_t; -# define gl_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS pthread_mutex_t NAME; -# define gl_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer; -# define gl_lock_initializer \ - PTHREAD_MUTEX_INITIALIZER -# define glthread_lock_init(LOCK) \ - (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0) -# define glthread_lock_lock(LOCK) \ - (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) -# define glthread_lock_unlock(LOCK) \ - (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) -# define glthread_lock_destroy(LOCK) \ - (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -# if HAVE_PTHREAD_RWLOCK - -# ifdef PTHREAD_RWLOCK_INITIALIZER - -typedef pthread_rwlock_t gl_rwlock_t; -# define gl_rwlock_define(STORAGECLASS, NAME) \ - STORAGECLASS pthread_rwlock_t NAME; -# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer; -# define gl_rwlock_initializer \ - PTHREAD_RWLOCK_INITIALIZER -# define glthread_rwlock_init(LOCK) \ - (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0) -# define glthread_rwlock_rdlock(LOCK) \ - (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0) -# define glthread_rwlock_wrlock(LOCK) \ - (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0) -# define glthread_rwlock_unlock(LOCK) \ - (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0) -# define glthread_rwlock_destroy(LOCK) \ - (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0) - -# else - -typedef struct - { - int initialized; - pthread_mutex_t guard; /* protects the initialization */ - pthread_rwlock_t rwlock; /* read-write lock */ - } - gl_rwlock_t; -# define gl_rwlock_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_rwlock_t NAME; -# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; -# define gl_rwlock_initializer \ - { 0, PTHREAD_MUTEX_INITIALIZER } -# define glthread_rwlock_init(LOCK) \ - (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) -# define glthread_rwlock_rdlock(LOCK) \ - (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) -# define glthread_rwlock_wrlock(LOCK) \ - (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) -# define glthread_rwlock_unlock(LOCK) \ - (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) -# define glthread_rwlock_destroy(LOCK) \ - (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) -extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); -extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); -extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); -extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); -extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); - -# endif - -# else - -typedef struct - { - pthread_mutex_t lock; /* protects the remaining fields */ - pthread_cond_t waiting_readers; /* waiting readers */ - pthread_cond_t waiting_writers; /* waiting writers */ - unsigned int waiting_writers_count; /* number of waiting writers */ - int runcount; /* number of readers running, or -1 when a writer runs */ - } - gl_rwlock_t; -# define gl_rwlock_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_rwlock_t NAME; -# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; -# define gl_rwlock_initializer \ - { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 } -# define glthread_rwlock_init(LOCK) \ - (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) -# define glthread_rwlock_rdlock(LOCK) \ - (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) -# define glthread_rwlock_wrlock(LOCK) \ - (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) -# define glthread_rwlock_unlock(LOCK) \ - (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) -# define glthread_rwlock_destroy(LOCK) \ - (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) -extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); -extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); -extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); -extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); -extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); - -# endif - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -# if HAVE_PTHREAD_MUTEX_RECURSIVE - -# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP - -typedef pthread_mutex_t gl_recursive_lock_t; -# define gl_recursive_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS pthread_mutex_t NAME; -# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer; -# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER -# define gl_recursive_lock_initializer \ - PTHREAD_RECURSIVE_MUTEX_INITIALIZER -# else -# define gl_recursive_lock_initializer \ - PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -# endif -# define glthread_recursive_lock_init(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_lock(LOCK) \ - (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) -# define glthread_recursive_lock_unlock(LOCK) \ - (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) -# define glthread_recursive_lock_destroy(LOCK) \ - (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) -extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); - -# else - -typedef struct - { - pthread_mutex_t recmutex; /* recursive mutex */ - pthread_mutex_t guard; /* protects the initialization */ - int initialized; - } - gl_recursive_lock_t; -# define gl_recursive_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_recursive_lock_t NAME; -# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; -# define gl_recursive_lock_initializer \ - { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 } -# define glthread_recursive_lock_init(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_lock(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_unlock(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_destroy(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) -extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); - -# endif - -# else - -/* Old versions of POSIX threads on Solaris did not have recursive locks. - We have to implement them ourselves. */ - -typedef struct - { - pthread_mutex_t mutex; - pthread_t owner; - unsigned long depth; - } - gl_recursive_lock_t; -# define gl_recursive_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_recursive_lock_t NAME; -# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; -# define gl_recursive_lock_initializer \ - { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 } -# define glthread_recursive_lock_init(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_lock(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_unlock(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_destroy(LOCK) \ - (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) -extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); - -# endif - -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef pthread_once_t gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT; -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (pthread_in_use () \ - ? pthread_once (ONCE_CONTROL, INITFUNCTION) \ - : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) -extern int glthread_once_singlethreaded (pthread_once_t *once_control); - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_PTH_THREADS - -/* Use the GNU Pth threads library. */ - -# include <pth.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# if USE_PTH_THREADS_WEAK - -/* Use weak references to the GNU Pth threads library. */ - -# pragma weak pth_mutex_init -# pragma weak pth_mutex_acquire -# pragma weak pth_mutex_release -# pragma weak pth_rwlock_init -# pragma weak pth_rwlock_acquire -# pragma weak pth_rwlock_release -# pragma weak pth_once - -# pragma weak pth_cancel -# define pth_in_use() (pth_cancel != NULL) - -# else - -# define pth_in_use() 1 - -# endif - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -typedef pth_mutex_t gl_lock_t; -# define gl_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS pth_mutex_t NAME; -# define gl_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS pth_mutex_t NAME = gl_lock_initializer; -# define gl_lock_initializer \ - PTH_MUTEX_INIT -# define glthread_lock_init(LOCK) \ - (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0) -# define glthread_lock_lock(LOCK) \ - (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0) -# define glthread_lock_unlock(LOCK) \ - (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0) -# define glthread_lock_destroy(LOCK) \ - ((void)(LOCK), 0) - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -typedef pth_rwlock_t gl_rwlock_t; -# define gl_rwlock_define(STORAGECLASS, NAME) \ - STORAGECLASS pth_rwlock_t NAME; -# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer; -# define gl_rwlock_initializer \ - PTH_RWLOCK_INIT -# define glthread_rwlock_init(LOCK) \ - (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0) -# define glthread_rwlock_rdlock(LOCK) \ - (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0) -# define glthread_rwlock_wrlock(LOCK) \ - (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0) -# define glthread_rwlock_unlock(LOCK) \ - (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0) -# define glthread_rwlock_destroy(LOCK) \ - ((void)(LOCK), 0) - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -/* In Pth, mutexes are recursive by default. */ -typedef pth_mutex_t gl_recursive_lock_t; -# define gl_recursive_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS pth_mutex_t NAME; -# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer; -# define gl_recursive_lock_initializer \ - PTH_MUTEX_INIT -# define glthread_recursive_lock_init(LOCK) \ - (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0) -# define glthread_recursive_lock_lock(LOCK) \ - (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0) -# define glthread_recursive_lock_unlock(LOCK) \ - (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0) -# define glthread_recursive_lock_destroy(LOCK) \ - ((void)(LOCK), 0) - -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef pth_once_t gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT; -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (pth_in_use () \ - ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ - : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) -extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)); -extern int glthread_once_singlethreaded (pth_once_t *once_control); - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_SOLARIS_THREADS - -/* Use the old Solaris threads library. */ - -# include <thread.h> -# include <synch.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# if USE_SOLARIS_THREADS_WEAK - -/* Use weak references to the old Solaris threads library. */ - -# pragma weak mutex_init -# pragma weak mutex_lock -# pragma weak mutex_unlock -# pragma weak mutex_destroy -# pragma weak rwlock_init -# pragma weak rw_rdlock -# pragma weak rw_wrlock -# pragma weak rw_unlock -# pragma weak rwlock_destroy -# pragma weak thr_self - -# pragma weak thr_suspend -# define thread_in_use() (thr_suspend != NULL) - -# else - -# define thread_in_use() 1 - -# endif - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -typedef mutex_t gl_lock_t; -# define gl_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS mutex_t NAME; -# define gl_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS mutex_t NAME = gl_lock_initializer; -# define gl_lock_initializer \ - DEFAULTMUTEX -# define glthread_lock_init(LOCK) \ - (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0) -# define glthread_lock_lock(LOCK) \ - (thread_in_use () ? mutex_lock (LOCK) : 0) -# define glthread_lock_unlock(LOCK) \ - (thread_in_use () ? mutex_unlock (LOCK) : 0) -# define glthread_lock_destroy(LOCK) \ - (thread_in_use () ? mutex_destroy (LOCK) : 0) - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -typedef rwlock_t gl_rwlock_t; -# define gl_rwlock_define(STORAGECLASS, NAME) \ - STORAGECLASS rwlock_t NAME; -# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS rwlock_t NAME = gl_rwlock_initializer; -# define gl_rwlock_initializer \ - DEFAULTRWLOCK -# define glthread_rwlock_init(LOCK) \ - (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0) -# define glthread_rwlock_rdlock(LOCK) \ - (thread_in_use () ? rw_rdlock (LOCK) : 0) -# define glthread_rwlock_wrlock(LOCK) \ - (thread_in_use () ? rw_wrlock (LOCK) : 0) -# define glthread_rwlock_unlock(LOCK) \ - (thread_in_use () ? rw_unlock (LOCK) : 0) -# define glthread_rwlock_destroy(LOCK) \ - (thread_in_use () ? rwlock_destroy (LOCK) : 0) - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -/* Old Solaris threads did not have recursive locks. - We have to implement them ourselves. */ - -typedef struct - { - mutex_t mutex; - thread_t owner; - unsigned long depth; - } - gl_recursive_lock_t; -# define gl_recursive_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_recursive_lock_t NAME; -# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; -# define gl_recursive_lock_initializer \ - { DEFAULTMUTEX, (thread_t) 0, 0 } -# define glthread_recursive_lock_init(LOCK) \ - (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_lock(LOCK) \ - (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_unlock(LOCK) \ - (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) -# define glthread_recursive_lock_destroy(LOCK) \ - (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) -extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); - -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef struct - { - volatile int inited; - mutex_t mutex; - } - gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX }; -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (thread_in_use () \ - ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ - : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) -extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)); -extern int glthread_once_singlethreaded (gl_once_t *once_control); - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_WIN32_THREADS - -# include <windows.h> - -# ifdef __cplusplus -extern "C" { -# endif - -/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex, - Semaphore types, because - - we need only to synchronize inside a single process (address space), - not inter-process locking, - - we don't need to support trylock operations. (TryEnterCriticalSection - does not work on Windows 95/98/ME. Packages that need trylock usually - define their own mutex type.) */ - -/* There is no way to statically initialize a CRITICAL_SECTION. It needs - to be done lazily, once only. For this we need spinlocks. */ - -typedef struct { volatile int done; volatile long started; } gl_spinlock_t; - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -typedef struct - { - gl_spinlock_t guard; /* protects the initialization */ - CRITICAL_SECTION lock; - } - gl_lock_t; -# define gl_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_lock_t NAME; -# define gl_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS gl_lock_t NAME = gl_lock_initializer; -# define gl_lock_initializer \ - { { 0, -1 } } -# define glthread_lock_init(LOCK) \ - (glthread_lock_init_func (LOCK), 0) -# define glthread_lock_lock(LOCK) \ - glthread_lock_lock_func (LOCK) -# define glthread_lock_unlock(LOCK) \ - glthread_lock_unlock_func (LOCK) -# define glthread_lock_destroy(LOCK) \ - glthread_lock_destroy_func (LOCK) -extern void glthread_lock_init_func (gl_lock_t *lock); -extern int glthread_lock_lock_func (gl_lock_t *lock); -extern int glthread_lock_unlock_func (gl_lock_t *lock); -extern int glthread_lock_destroy_func (gl_lock_t *lock); - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -/* It is impossible to implement read-write locks using plain locks, without - introducing an extra thread dedicated to managing read-write locks. - Therefore here we need to use the low-level Event type. */ - -typedef struct - { - HANDLE *array; /* array of waiting threads, each represented by an event */ - unsigned int count; /* number of waiting threads */ - unsigned int alloc; /* length of allocated array */ - unsigned int offset; /* index of first waiting thread in array */ - } - gl_carray_waitqueue_t; -typedef struct - { - gl_spinlock_t guard; /* protects the initialization */ - CRITICAL_SECTION lock; /* protects the remaining fields */ - gl_carray_waitqueue_t waiting_readers; /* waiting readers */ - gl_carray_waitqueue_t waiting_writers; /* waiting writers */ - int runcount; /* number of readers running, or -1 when a writer runs */ - } - gl_rwlock_t; -# define gl_rwlock_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_rwlock_t NAME; -# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; -# define gl_rwlock_initializer \ - { { 0, -1 } } -# define glthread_rwlock_init(LOCK) \ - (glthread_rwlock_init_func (LOCK), 0) -# define glthread_rwlock_rdlock(LOCK) \ - glthread_rwlock_rdlock_func (LOCK) -# define glthread_rwlock_wrlock(LOCK) \ - glthread_rwlock_wrlock_func (LOCK) -# define glthread_rwlock_unlock(LOCK) \ - glthread_rwlock_unlock_func (LOCK) -# define glthread_rwlock_destroy(LOCK) \ - glthread_rwlock_destroy_func (LOCK) -extern void glthread_rwlock_init_func (gl_rwlock_t *lock); -extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock); -extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock); -extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock); -extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock); - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -/* The Win32 documentation says that CRITICAL_SECTION already implements a - recursive lock. But we need not rely on it: It's easy to implement a - recursive lock without this assumption. */ - -typedef struct - { - gl_spinlock_t guard; /* protects the initialization */ - DWORD owner; - unsigned long depth; - CRITICAL_SECTION lock; - } - gl_recursive_lock_t; -# define gl_recursive_lock_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_recursive_lock_t NAME; -# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ - STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; -# define gl_recursive_lock_initializer \ - { { 0, -1 }, 0, 0 } -# define glthread_recursive_lock_init(LOCK) \ - (glthread_recursive_lock_init_func (LOCK), 0) -# define glthread_recursive_lock_lock(LOCK) \ - glthread_recursive_lock_lock_func (LOCK) -# define glthread_recursive_lock_unlock(LOCK) \ - glthread_recursive_lock_unlock_func (LOCK) -# define glthread_recursive_lock_destroy(LOCK) \ - glthread_recursive_lock_destroy_func (LOCK) -extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock); -extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock); - -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef struct - { - volatile int inited; - volatile long started; - CRITICAL_SECTION lock; - } - gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_once_t NAME = { -1, -1 }; -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0) -extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)); - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS) - -/* Provide dummy implementation if threads are not supported. */ - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -typedef int gl_lock_t; -# define gl_lock_define(STORAGECLASS, NAME) -# define gl_lock_define_initialized(STORAGECLASS, NAME) -# define glthread_lock_init(NAME) 0 -# define glthread_lock_lock(NAME) 0 -# define glthread_lock_unlock(NAME) 0 -# define glthread_lock_destroy(NAME) 0 - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -typedef int gl_rwlock_t; -# define gl_rwlock_define(STORAGECLASS, NAME) -# define gl_rwlock_define_initialized(STORAGECLASS, NAME) -# define glthread_rwlock_init(NAME) 0 -# define glthread_rwlock_rdlock(NAME) 0 -# define glthread_rwlock_wrlock(NAME) 0 -# define glthread_rwlock_unlock(NAME) 0 -# define glthread_rwlock_destroy(NAME) 0 - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -typedef int gl_recursive_lock_t; -# define gl_recursive_lock_define(STORAGECLASS, NAME) -# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) -# define glthread_recursive_lock_init(NAME) 0 -# define glthread_recursive_lock_lock(NAME) 0 -# define glthread_recursive_lock_unlock(NAME) 0 -# define glthread_recursive_lock_destroy(NAME) 0 - -/* -------------------------- gl_once_t datatype -------------------------- */ - -typedef int gl_once_t; -# define gl_once_define(STORAGECLASS, NAME) \ - STORAGECLASS gl_once_t NAME = 0; -# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ - (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0) - -#endif - -/* ========================================================================= */ - -/* Macros with built-in error handling. */ - -/* -------------------------- gl_lock_t datatype -------------------------- */ - -#define gl_lock_init(NAME) \ - do \ - { \ - if (glthread_lock_init (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_lock_lock(NAME) \ - do \ - { \ - if (glthread_lock_lock (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_lock_unlock(NAME) \ - do \ - { \ - if (glthread_lock_unlock (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_lock_destroy(NAME) \ - do \ - { \ - if (glthread_lock_destroy (&NAME)) \ - abort (); \ - } \ - while (0) - -/* ------------------------- gl_rwlock_t datatype ------------------------- */ - -#define gl_rwlock_init(NAME) \ - do \ - { \ - if (glthread_rwlock_init (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_rwlock_rdlock(NAME) \ - do \ - { \ - if (glthread_rwlock_rdlock (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_rwlock_wrlock(NAME) \ - do \ - { \ - if (glthread_rwlock_wrlock (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_rwlock_unlock(NAME) \ - do \ - { \ - if (glthread_rwlock_unlock (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_rwlock_destroy(NAME) \ - do \ - { \ - if (glthread_rwlock_destroy (&NAME)) \ - abort (); \ - } \ - while (0) - -/* --------------------- gl_recursive_lock_t datatype --------------------- */ - -#define gl_recursive_lock_init(NAME) \ - do \ - { \ - if (glthread_recursive_lock_init (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_recursive_lock_lock(NAME) \ - do \ - { \ - if (glthread_recursive_lock_lock (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_recursive_lock_unlock(NAME) \ - do \ - { \ - if (glthread_recursive_lock_unlock (&NAME)) \ - abort (); \ - } \ - while (0) -#define gl_recursive_lock_destroy(NAME) \ - do \ - { \ - if (glthread_recursive_lock_destroy (&NAME)) \ - abort (); \ - } \ - while (0) - -/* -------------------------- gl_once_t datatype -------------------------- */ - -#define gl_once(NAME, INITFUNCTION) \ - do \ - { \ - if (glthread_once (&NAME, INITFUNCTION)) \ - abort (); \ - } \ - while (0) - -/* ========================================================================= */ - -#endif /* _LOCK_H */ diff --git a/gl/glthread/threadlib.c b/gl/glthread/threadlib.c deleted file mode 100644 index 646defa21b..0000000000 --- a/gl/glthread/threadlib.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Multithreading primitives. - Copyright (C) 2005-2011 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, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Bruno Haible <bruno@clisp.org>, 2005. */ - -#include <config.h> - -/* ========================================================================= */ - -#if USE_POSIX_THREADS - -/* Use the POSIX threads library. */ - -# include <pthread.h> -# include <stdlib.h> - -# if PTHREAD_IN_USE_DETECTION_HARD - -/* The function to be executed by a dummy thread. */ -static void * -dummy_thread_func (void *arg) -{ - return arg; -} - -int -glthread_in_use (void) -{ - static int tested; - static int result; /* 1: linked with -lpthread, 0: only with libc */ - - if (!tested) - { - pthread_t thread; - - if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0) - /* Thread creation failed. */ - result = 0; - else - { - /* Thread creation works. */ - void *retval; - if (pthread_join (thread, &retval) != 0) - abort (); - result = 1; - } - tested = 1; - } - return result; -} - -# endif - -#endif - -/* ========================================================================= */ - -/* This declaration is solely to ensure that after preprocessing - this file is never empty. */ -typedef int dummy; diff --git a/gl/hmac-md5.c b/gl/hmac-md5.c index 2c0edf5e86..eed16573ba 100644 --- a/gl/hmac-md5.c +++ b/gl/hmac-md5.c @@ -58,7 +58,7 @@ hmac_md5 (const void *key, size_t keylen, md5_init_ctx (&inner); memset (block, IPAD, sizeof (block)); - gl_memxor (block, key, keylen); + memxor (block, key, keylen); md5_process_block (block, 64, &inner); md5_process_bytes (in, inlen, &inner); @@ -70,7 +70,7 @@ hmac_md5 (const void *key, size_t keylen, md5_init_ctx (&outer); memset (block, OPAD, sizeof (block)); - gl_memxor (block, key, keylen); + memxor (block, key, keylen); md5_process_block (block, 64, &outer); md5_process_bytes (innerhash, 16, &outer); diff --git a/gl/intprops.h b/gl/intprops.h index bd9f04042e..a84bd6af53 100644 --- a/gl/intprops.h +++ b/gl/intprops.h @@ -27,10 +27,6 @@ E should not have side effects. */ #define _GL_INT_CONVERT(e, v) ((e) - (e) + (v)) -/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see - <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>. */ -#define _GL_INT_NEGATE_CONVERT(e, v) ((e) - (e) - (v)) - /* The extra casts in the following macros work around compiler bugs, e.g., in Cray C 5.0.3.0. */ @@ -54,7 +50,7 @@ /* Return 1 if the integer expression E, after integer promotion, has a signed type. E should not have side effects. */ -#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) +#define _GL_INT_SIGNED(e) (_GL_INT_CONVERT (e, -1) < 0) /* Minimum and maximum values for integer types and expressions. These @@ -83,7 +79,7 @@ #define _GL_INT_MAXIMUM(e) \ (_GL_INT_SIGNED (e) \ ? _GL_SIGNED_INT_MAXIMUM (e) \ - : _GL_INT_NEGATE_CONVERT (e, 1)) + : _GL_INT_CONVERT (e, -1)) #define _GL_SIGNED_INT_MAXIMUM(e) \ (((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1) @@ -183,21 +179,16 @@ : 0 < (a)) /* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. - See above for restrictions. Avoid && and || as they tickle - bugs in Sun C 5.11 2010/08/13 and other compilers; see - <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>. */ + See above for restrictions. */ #define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ ((b) < 0 \ ? ((a) < 0 \ ? (a) < (max) / (b) \ - : (b) == -1 \ - ? 0 \ - : (min) / (b) < (a)) \ - : (b) == 0 \ - ? 0 \ - : ((a) < 0 \ - ? (a) < (min) / (b) \ - : (max) / (b) < (a))) + : (b) < -1 && (min) / (b) < (a)) \ + : (0 < (b) \ + && ((a) < 0 \ + ? (a) < (min) / (b) \ + : (max) / (b) < (a)))) /* Return 1 if A / B would overflow in [MIN,MAX] arithmetic. See above for restrictions. Do not check for division by zero. */ @@ -243,11 +234,11 @@ (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) #define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ - ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + ((min) < 0 ? (b) == _GL_INT_CONVERT (min, -1) && (a) < - (max) \ : (a) < 0 ? (b) <= (a) + (b) - 1 \ : (b) < 0 && (a) + (b) <= (a)) #define _GL_REMAINDER_OVERFLOW(a, b, min, max) \ - ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + ((min) < 0 ? (b) == _GL_INT_CONVERT (min, -1) && (a) < - (max) \ : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \ : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max)) diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4 index f67b5e49eb..d1d4636e8b 100644 --- a/gl/m4/gnulib-cache.m4 +++ b/gl/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lseek-tests --libtool --macro-prefix=gl alloca byteswap c-ctype crypto/hmac-md5 crypto/md5 error extensions func getpass gettext gettime havelib lib-msvc-compat lib-symbol-versions manywarnings memmem-simple minmax netdb netinet_in progname read-file snprintf sockets socklen stdint strcase strverscmp sys_socket sys_stat time_r timespec u64 unistd valgrind-tests vasprintf version-etc version-etc-fsf vsnprintf warnings +# gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lseek-tests --libtool --macro-prefix=gl --no-vc-files alloca byteswap c-ctype crypto/hmac-md5 crypto/md5 error extensions func getpass gettext gettime havelib lib-msvc-compat lib-symbol-versions manywarnings memmem-simple minmax netdb netinet_in progname read-file snprintf sockets socklen stdint strcase strverscmp sys_socket sys_stat time_r timespec u64 unistd valgrind-tests vasprintf version-etc version-etc-fsf vsnprintf warnings # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([gl/override]) @@ -72,3 +72,4 @@ gl_MAKEFILE_NAME([]) gl_LIBTOOL gl_MACRO_PREFIX([gl]) gl_PO_DOMAIN([]) +gl_VC_FILES([false]) diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4 index 1776453d68..0dd6d5da85 100644 --- a/gl/m4/gnulib-comp.m4 +++ b/gl/m4/gnulib-comp.m4 @@ -26,7 +26,6 @@ AC_DEFUN([gl_EARLY], m4_pattern_allow([^gl_LIBOBJS$])dnl a variable m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable AC_REQUIRE([AC_PROG_RANLIB]) - AC_REQUIRE([AM_PROG_CC_C_O]) # Code from module alignof: # Code from module alloca: # Code from module alloca-opt: @@ -81,8 +80,6 @@ AC_DEFUN([gl_EARLY], # Code from module inttypes-tests: # Code from module lib-msvc-compat: # Code from module lib-symbol-versions: - # Code from module lock: - # Code from module lock-tests: # Code from module lseek: # Code from module malloc-posix: # Code from module manywarnings: @@ -127,8 +124,6 @@ AC_DEFUN([gl_EARLY], # Code from module strdup-posix: # Code from module strerror: # Code from module strerror-tests: - # Code from module strerror_r-posix: - # Code from module strerror_r-posix-tests: # Code from module string: # Code from module string-tests: # Code from module strings: @@ -143,9 +138,6 @@ AC_DEFUN([gl_EARLY], # Code from module sys_time-tests: # Code from module sys_uio: # Code from module sys_uio-tests: - # Code from module thread: - # Code from module threadlib: - gl_THREADLIB_EARLY # Code from module time: # Code from module time-tests: # Code from module time_r: @@ -171,7 +163,6 @@ AC_DEFUN([gl_EARLY], # Code from module wchar: # Code from module wchar-tests: # Code from module xsize: - # Code from module yield: ]) # This macro should be invoked from ./configure.ac, in the section @@ -222,7 +213,6 @@ gl_FUNC_GETTIMEOFDAY gl_SYS_TIME_MODULE_INDICATOR([gettimeofday]) gl_LD_OUTPUT_DEF gl_LD_VERSION_SCRIPT -gl_LOCK gl_FUNC_LSEEK gl_UNISTD_MODULE_INDICATOR([lseek]) gl_FUNC_MALLOC_POSIX @@ -260,8 +250,6 @@ gl_FUNC_STRDUP_POSIX gl_STRING_MODULE_INDICATOR([strdup]) gl_FUNC_STRERROR gl_STRING_MODULE_INDICATOR([strerror]) -gl_FUNC_STRERROR_R -gl_STRING_MODULE_INDICATOR([strerror_r]) gl_HEADER_STRING_H gl_HEADER_STRINGS_H gl_FUNC_STRVERSCMP @@ -274,7 +262,6 @@ gl_HEADER_SYS_TIME_H AC_PROG_MKDIR_P gl_HEADER_SYS_UIO AC_PROG_MKDIR_P -gl_THREADLIB gl_HEADER_TIME_H gl_TIME_R gl_TIME_MODULE_INDICATOR([time_r]) @@ -354,9 +341,7 @@ AC_CHECK_FUNCS_ONCE([mprotect]) gt_TYPE_WCHAR_T gt_TYPE_WINT_T AC_CHECK_FUNCS_ONCE([shutdown]) -gl_THREAD gl_VALGRIND_TESTS -gl_YIELD m4_popdef([gl_MODULE_INDICATOR_CONDITION]) m4_ifval(gltests_LIBSOURCES_LIST, [ m4_syscmd([test ! -d ]m4_defn([gltests_LIBSOURCES_DIR])[ || @@ -477,9 +462,6 @@ AC_DEFUN([gl_FILE_LIST], [ lib/gettext.h lib/gettime.c lib/gettimeofday.c - lib/glthread/lock.c - lib/glthread/lock.h - lib/glthread/threadlib.c lib/hmac-md5.c lib/hmac.h lib/intprops.h @@ -518,9 +500,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/str-two-way.h lib/strcasecmp.c lib/strdup.c - lib/strerror-impl.h lib/strerror.c - lib/strerror_r.c lib/string.in.h lib/strings.in.h lib/strncasecmp.c @@ -624,7 +604,6 @@ AC_DEFUN([gl_FILE_LIST], [ m4/strcase.m4 m4/strdup.m4 m4/strerror.m4 - m4/strerror_r.m4 m4/string_h.m4 m4/strings_h.m4 m4/strverscmp.m4 @@ -632,7 +611,6 @@ AC_DEFUN([gl_FILE_LIST], [ m4/sys_stat_h.m4 m4/sys_time_h.m4 m4/sys_uio_h.m4 - m4/thread.m4 m4/threadlib.m4 m4/time_h.m4 m4/time_r.m4 @@ -652,7 +630,6 @@ AC_DEFUN([gl_FILE_LIST], [ m4/wchar_t.m4 m4/wint_t.m4 m4/xsize.m4 - m4/yield.m4 tests/init.sh tests/macros.h tests/signature.h @@ -677,7 +654,6 @@ AC_DEFUN([gl_FILE_LIST], [ tests/test-hmac-md5.c tests/test-intprops.c tests/test-inttypes.c - tests/test-lock.c tests/test-md5.c tests/test-memchr.c tests/test-netdb.c @@ -691,7 +667,6 @@ AC_DEFUN([gl_FILE_LIST], [ tests/test-stdio.c tests/test-stdlib.c tests/test-strerror.c - tests/test-strerror_r.c tests/test-string.c tests/test-strings.c tests/test-strverscmp.c @@ -713,10 +688,8 @@ AC_DEFUN([gl_FILE_LIST], [ tests/test-wchar.c tests/zerosize-ptr.h tests=lib/binary-io.h + tests=lib/dummy.c tests=lib/fcntl.in.h tests=lib/getpagesize.c - tests=lib/glthread/thread.c - tests=lib/glthread/thread.h - tests=lib/glthread/yield.h tests=lib/inttypes.in.h ]) diff --git a/gl/m4/strerror.m4 b/gl/m4/strerror.m4 index d891031f61..73d1d54d81 100644 --- a/gl/m4/strerror.m4 +++ b/gl/m4/strerror.m4 @@ -1,4 +1,4 @@ -# strerror.m4 serial 10 +# strerror.m4 serial 9 dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -25,18 +25,19 @@ AC_DEFUN([gl_FUNC_STRERROR_SEPARATE], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#include <string.h> - #include <errno.h> ]], - [[int result = 0; - if (!*strerror (-2)) result |= 1; - errno = 0; - if (!*strerror (0)) result |= 2; - if (errno) result |= 4; - return result;]])], + [[return !*strerror (-2);]])], [gl_cv_func_working_strerror=yes], [gl_cv_func_working_strerror=no], - [dnl Be pessimistic on cross-compiles for now. - gl_cv_func_working_strerror=no]) + [dnl Assume crossbuild works if it compiles. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <string.h> + ]], + [[return !*strerror (-2);]])], + [gl_cv_func_working_strerror=yes], + [gl_cv_func_working_strerror=no]) + ]) ]) if test $gl_cv_func_working_strerror = no; then dnl The system's strerror() fails to return a string for out-of-range diff --git a/gl/m4/strerror_r.m4 b/gl/m4/strerror_r.m4 deleted file mode 100644 index 190472c959..0000000000 --- a/gl/m4/strerror_r.m4 +++ /dev/null @@ -1,108 +0,0 @@ -# strerror_r.m4 serial 6 -dnl Copyright (C) 2002, 2007-2011 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_STRERROR_R], -[ - AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) - AC_REQUIRE([gl_HEADER_ERRNO_H]) - AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles - - dnl Persuade Solaris <string.h> to declare strerror_r(). - AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) - - dnl Some systems don't declare strerror_r() if _THREAD_SAFE and _REENTRANT - dnl are not defined. - AC_CHECK_DECLS_ONCE([strerror_r]) - if test $ac_cv_have_decl_strerror_r = no; then - HAVE_DECL_STRERROR_R=0 - fi - - AC_CHECK_FUNCS([strerror_r]) - if test $ac_cv_func_strerror_r = yes; then - if test -z "$ERRNO_H"; then - dnl The POSIX prototype is: int strerror_r (int, char *, size_t); - dnl glibc, Cygwin: char *strerror_r (int, char *, size_t); - dnl AIX 5.1, OSF/1 5.1: int strerror_r (int, char *, int); - AC_CACHE_CHECK([for strerror_r with POSIX signature], - [gl_cv_func_strerror_r_posix_signature], - [AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#include <string.h> - int strerror_r (int, char *, size_t); - ]], - [[return strerror (0);]])], - [gl_cv_func_strerror_r_posix_signature=yes], - [gl_cv_func_strerror_r_posix_signature=no]) - ]) - if test $gl_cv_func_strerror_r_posix_signature = yes; then - dnl AIX 6.1 strerror_r fails by returning -1, not an error number. - dnl HP-UX 11.31 strerror_r always fails when the buffer length argument - dnl is less than 80. - dnl FreeBSD 8.s strerror_r claims failure on 0 - AC_CACHE_CHECK([whether strerror_r works], - [gl_cv_func_strerror_r_works], - [AC_RUN_IFELSE( - [AC_LANG_PROGRAM( - [[#include <errno.h> - #include <string.h> - int strerror_r (int, char *, size_t); - ]], - [[int result = 0; - char buf[79]; - if (strerror_r (EACCES, buf, 0) < 0) - result |= 1; - errno = 0; - if (strerror_r (EACCES, buf, sizeof buf) != 0) - result |= 2; - if (strerror_r (0, buf, sizeof buf) != 0) - result |= 4; - if (errno) - result |= 8; - return result; - ]])], - [gl_cv_func_strerror_r_works=yes], - [gl_cv_func_strerror_r_works=no], - [ -changequote(,)dnl - case "$host_os" in - # Guess no on AIX. - aix*) gl_cv_func_strerror_r_works="guessing no";; - # Guess no on HP-UX. - hpux*) gl_cv_func_strerror_r_works="guessing no";; - # Guess no on FreeBSD. - freebsd*) gl_cv_func_strerror_r_works="guessing no";; - # Guess yes otherwise. - *) gl_cv_func_strerror_r_works="guessing yes";; - esac -changequote([,])dnl - ]) - ]) - case "$gl_cv_func_strerror_r_works" in - *no) REPLACE_STRERROR_R=1 ;; - esac - else - dnl The system's strerror() has a wrong signature. Replace it. - REPLACE_STRERROR_R=1 - dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r. - AC_CHECK_FUNCS([__xpg_strerror_r]) - fi - else - dnl The system's strerror_r() cannot know about the new errno values we - dnl add to <errno.h>. Replace it. - REPLACE_STRERROR_R=1 - fi - fi - if test $HAVE_DECL_STRERROR_R = 0 || test $REPLACE_STRERROR_R = 1; then - AC_LIBOBJ([strerror_r]) - gl_PREREQ_STRERROR_R - fi -]) - -# Prerequisites of lib/strerror_r.c. -AC_DEFUN([gl_PREREQ_STRERROR_R], [ - AC_CHECK_FUNCS_ONCE([catgets]) - : -]) diff --git a/gl/m4/thread.m4 b/gl/m4/thread.m4 deleted file mode 100644 index 49a4bc772f..0000000000 --- a/gl/m4/thread.m4 +++ /dev/null @@ -1,18 +0,0 @@ -# thread.m4 serial 2 -dnl Copyright (C) 2008-2011 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_THREAD], -[ - AC_REQUIRE([gl_THREADLIB]) - AC_REQUIRE([AC_C_INLINE]) - - if test $gl_threads_api = posix; then - gl_save_LIBS="$LIBS" - LIBS="$LIBS $LIBMULTITHREAD" - AC_CHECK_FUNCS([pthread_atfork]) - LIBS="$gl_save_LIBS" - fi -]) diff --git a/gl/m4/valgrind-tests.m4 b/gl/m4/valgrind-tests.m4 index 98d4487857..ab9e25a841 100644 --- a/gl/m4/valgrind-tests.m4 +++ b/gl/m4/valgrind-tests.m4 @@ -23,7 +23,7 @@ AC_DEFUN([gl_VALGRIND_TESTS], if test -n "$VALGRIND" && $VALGRIND -q true > /dev/null 2>&1; then opt_valgrind_tests=yes - VALGRIND="$VALGRIND -q --error-exitcode=1" + VALGRIND="$VALGRIND -q --error-exitcode=1 --leak-check=full" else opt_valgrind_tests=no VALGRIND= diff --git a/gl/m4/yield.m4 b/gl/m4/yield.m4 deleted file mode 100644 index 15d5ac208c..0000000000 --- a/gl/m4/yield.m4 +++ /dev/null @@ -1,19 +0,0 @@ -# yield.m4 serial 2 -dnl Copyright (C) 2005-2011 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_YIELD], -[ - AC_REQUIRE([gl_THREADLIB]) - 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. - 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])]) - fi - AC_SUBST([YIELD_LIB]) -]) diff --git a/gl/memxor.c b/gl/memxor.c index b80b4308ef..4eeebcbd56 100644 --- a/gl/memxor.c +++ b/gl/memxor.c @@ -23,7 +23,7 @@ #include "memxor.h" void * -gl_memxor (void *restrict dest, const void *restrict src, size_t n) +memxor (void *restrict dest, const void *restrict src, size_t n) { char const *s = src; char *d = dest; diff --git a/gl/memxor.h b/gl/memxor.h index fbf2ac3c54..dafa2cfca7 100644 --- a/gl/memxor.h +++ b/gl/memxor.h @@ -26,6 +26,6 @@ /* Compute binary exclusive OR of memory areas DEST and SRC, putting the result in DEST, of length N bytes. Returns a pointer to DEST. */ -void *gl_memxor (void *restrict dest, const void *restrict src, size_t n); +void *memxor (void *restrict dest, const void *restrict src, size_t n); #endif /* MEMXOR_H */ diff --git a/gl/stdint.in.h b/gl/stdint.in.h index 376b96a785..b32227bb04 100644 --- a/gl/stdint.in.h +++ b/gl/stdint.in.h @@ -93,7 +93,7 @@ #undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H -/* Minimum and maximum values for an integer type under the usual assumption. +/* Minimum and maximum values for a integer type under the usual assumption. Return an unspecified value if BITS == 0, adding a check to pacify picky compilers. */ diff --git a/gl/strerror-impl.h b/gl/strerror-impl.h deleted file mode 100644 index a2042433cc..0000000000 --- a/gl/strerror-impl.h +++ /dev/null @@ -1,42 +0,0 @@ -/* strerror-impl.h --- Implementation of POSIX compatible strerror() function. - - Copyright (C) 2007-2011 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 <http://www.gnu.org/licenses/>. */ - -#ifdef STATIC -STATIC -#endif -char * -strerror (int n) -{ - static char buf[256]; - - int ret = strerror_r (n, buf, sizeof (buf)); - - if (ret == 0) - return buf; - - if (ret == ERANGE) - /* If this happens, increase the size of buf. */ - abort (); - - { - static char const fmt[] = "Unknown error (%d)"; - verify (sizeof (buf) >= sizeof (fmt) + INT_STRLEN_BOUND (n)); - sprintf (buf, fmt, n); - errno = ret; - return buf; - } -} diff --git a/gl/strerror.c b/gl/strerror.c index f0e03df95d..5dae1111a2 100644 --- a/gl/strerror.c +++ b/gl/strerror.c @@ -17,21 +17,340 @@ #include <config.h> -/* Specification. */ #include <string.h> #if REPLACE_STRERROR # include <errno.h> # include <stdio.h> -# include <stdlib.h> + +# if GNULIB_defined_ESOCK /* native Windows platforms */ +# if HAVE_WINSOCK2_H +# include <winsock2.h> +# endif +# endif # include "intprops.h" -# include "verify.h" /* Use the system functions, not the gnulib overrides in this file. */ # undef sprintf -# include "strerror-impl.h" +# undef strerror +# if ! HAVE_DECL_STRERROR +# define strerror(n) NULL +# endif + +char * +rpl_strerror (int n) +{ + char const *msg = NULL; + /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ + switch (n) + { +# if GNULIB_defined_ETXTBSY + case ETXTBSY: + msg = "Text file busy"; + break; +# endif + +# if GNULIB_defined_ESOCK /* native Windows platforms */ + /* EWOULDBLOCK is the same as EAGAIN. */ + case EINPROGRESS: + msg = "Operation now in progress"; + break; + case EALREADY: + msg = "Operation already in progress"; + break; + case ENOTSOCK: + msg = "Socket operation on non-socket"; + break; + case EDESTADDRREQ: + msg = "Destination address required"; + break; + case EMSGSIZE: + msg = "Message too long"; + break; + case EPROTOTYPE: + msg = "Protocol wrong type for socket"; + break; + case ENOPROTOOPT: + msg = "Protocol not available"; + break; + case EPROTONOSUPPORT: + msg = "Protocol not supported"; + break; + case ESOCKTNOSUPPORT: + msg = "Socket type not supported"; + break; + case EOPNOTSUPP: + msg = "Operation not supported"; + break; + case EPFNOSUPPORT: + msg = "Protocol family not supported"; + break; + case EAFNOSUPPORT: + msg = "Address family not supported by protocol"; + break; + case EADDRINUSE: + msg = "Address already in use"; + break; + case EADDRNOTAVAIL: + msg = "Cannot assign requested address"; + break; + case ENETDOWN: + msg = "Network is down"; + break; + case ENETUNREACH: + msg = "Network is unreachable"; + break; + case ENETRESET: + msg = "Network dropped connection on reset"; + break; + case ECONNABORTED: + msg = "Software caused connection abort"; + break; + case ECONNRESET: + msg = "Connection reset by peer"; + break; + case ENOBUFS: + msg = "No buffer space available"; + break; + case EISCONN: + msg = "Transport endpoint is already connected"; + break; + case ENOTCONN: + msg = "Transport endpoint is not connected"; + break; + case ESHUTDOWN: + msg = "Cannot send after transport endpoint shutdown"; + break; + case ETOOMANYREFS: + msg = "Too many references: cannot splice"; + break; + case ETIMEDOUT: + msg = "Connection timed out"; + break; + case ECONNREFUSED: + msg = "Connection refused"; + break; + case ELOOP: + msg = "Too many levels of symbolic links"; + break; + case EHOSTDOWN: + msg = "Host is down"; + break; + case EHOSTUNREACH: + msg = "No route to host"; + break; + case EPROCLIM: + msg = "Too many processes"; + break; + case EUSERS: + msg = "Too many users"; + break; + case EDQUOT: + msg = "Disk quota exceeded"; + break; + case ESTALE: + msg = "Stale NFS file handle"; + break; + case EREMOTE: + msg = "Object is remote"; + break; +# if HAVE_WINSOCK2_H + /* WSA_INVALID_HANDLE maps to EBADF */ + /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */ + /* WSA_INVALID_PARAMETER maps to EINVAL */ + case WSA_OPERATION_ABORTED: + msg = "Overlapped operation aborted"; + break; + case WSA_IO_INCOMPLETE: + msg = "Overlapped I/O event object not in signaled state"; + break; + case WSA_IO_PENDING: + msg = "Overlapped operations will complete later"; + break; + /* WSAEINTR maps to EINTR */ + /* WSAEBADF maps to EBADF */ + /* WSAEACCES maps to EACCES */ + /* WSAEFAULT maps to EFAULT */ + /* WSAEINVAL maps to EINVAL */ + /* WSAEMFILE maps to EMFILE */ + /* WSAEWOULDBLOCK maps to EWOULDBLOCK */ + /* WSAEINPROGRESS is EINPROGRESS */ + /* WSAEALREADY is EALREADY */ + /* WSAENOTSOCK is ENOTSOCK */ + /* WSAEDESTADDRREQ is EDESTADDRREQ */ + /* WSAEMSGSIZE is EMSGSIZE */ + /* WSAEPROTOTYPE is EPROTOTYPE */ + /* WSAENOPROTOOPT is ENOPROTOOPT */ + /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */ + /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */ + /* WSAEOPNOTSUPP is EOPNOTSUPP */ + /* WSAEPFNOSUPPORT is EPFNOSUPPORT */ + /* WSAEAFNOSUPPORT is EAFNOSUPPORT */ + /* WSAEADDRINUSE is EADDRINUSE */ + /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */ + /* WSAENETDOWN is ENETDOWN */ + /* WSAENETUNREACH is ENETUNREACH */ + /* WSAENETRESET is ENETRESET */ + /* WSAECONNABORTED is ECONNABORTED */ + /* WSAECONNRESET is ECONNRESET */ + /* WSAENOBUFS is ENOBUFS */ + /* WSAEISCONN is EISCONN */ + /* WSAENOTCONN is ENOTCONN */ + /* WSAESHUTDOWN is ESHUTDOWN */ + /* WSAETOOMANYREFS is ETOOMANYREFS */ + /* WSAETIMEDOUT is ETIMEDOUT */ + /* WSAECONNREFUSED is ECONNREFUSED */ + /* WSAELOOP is ELOOP */ + /* WSAENAMETOOLONG maps to ENAMETOOLONG */ + /* WSAEHOSTDOWN is EHOSTDOWN */ + /* WSAEHOSTUNREACH is EHOSTUNREACH */ + /* WSAENOTEMPTY maps to ENOTEMPTY */ + /* WSAEPROCLIM is EPROCLIM */ + /* WSAEUSERS is EUSERS */ + /* WSAEDQUOT is EDQUOT */ + /* WSAESTALE is ESTALE */ + /* WSAEREMOTE is EREMOTE */ + case WSASYSNOTREADY: + msg = "Network subsystem is unavailable"; + break; + case WSAVERNOTSUPPORTED: + msg = "Winsock.dll version out of range"; + break; + case WSANOTINITIALISED: + msg = "Successful WSAStartup not yet performed"; + break; + case WSAEDISCON: + msg = "Graceful shutdown in progress"; + break; + case WSAENOMORE: case WSA_E_NO_MORE: + msg = "No more results"; + break; + case WSAECANCELLED: case WSA_E_CANCELLED: + msg = "Call was canceled"; + break; + case WSAEINVALIDPROCTABLE: + msg = "Procedure call table is invalid"; + break; + case WSAEINVALIDPROVIDER: + msg = "Service provider is invalid"; + break; + case WSAEPROVIDERFAILEDINIT: + msg = "Service provider failed to initialize"; + break; + case WSASYSCALLFAILURE: + msg = "System call failure"; + break; + case WSASERVICE_NOT_FOUND: + msg = "Service not found"; + break; + case WSATYPE_NOT_FOUND: + msg = "Class type not found"; + break; + case WSAEREFUSED: + msg = "Database query was refused"; + break; + case WSAHOST_NOT_FOUND: + msg = "Host not found"; + break; + case WSATRY_AGAIN: + msg = "Nonauthoritative host not found"; + break; + case WSANO_RECOVERY: + msg = "Nonrecoverable error"; + break; + case WSANO_DATA: + msg = "Valid name, no data record of requested type"; + break; + /* WSA_QOS_* omitted */ +# endif +# endif + +# if GNULIB_defined_ENOMSG + case ENOMSG: + msg = "No message of desired type"; + break; +# endif + +# if GNULIB_defined_EIDRM + case EIDRM: + msg = "Identifier removed"; + break; +# endif + +# if GNULIB_defined_ENOLINK + case ENOLINK: + msg = "Link has been severed"; + break; +# endif + +# if GNULIB_defined_EPROTO + case EPROTO: + msg = "Protocol error"; + break; +# endif + +# if GNULIB_defined_EMULTIHOP + case EMULTIHOP: + msg = "Multihop attempted"; + break; +# endif + +# if GNULIB_defined_EBADMSG + case EBADMSG: + msg = "Bad message"; + break; +# endif + +# if GNULIB_defined_EOVERFLOW + case EOVERFLOW: + msg = "Value too large for defined data type"; + break; +# endif + +# if GNULIB_defined_ENOTSUP + case ENOTSUP: + msg = "Not supported"; + break; +# endif + +# if GNULIB_defined_ESTALE + case ESTALE: + msg = "Stale NFS file handle"; + break; +# endif + +# if GNULIB_defined_EDQUOT + case EDQUOT: + msg = "Disk quota exceeded"; + break; +# endif + +# if GNULIB_defined_ECANCELED + case ECANCELED: + msg = "Operation canceled"; + break; +# endif + } + + if (msg) + return (char *) msg; + + { + char *result = strerror (n); + + if (result == NULL || result[0] == '\0') + { + static char const fmt[] = "Unknown error (%d)"; + static char msg_buf[sizeof fmt + INT_STRLEN_BOUND (n)]; + sprintf (msg_buf, fmt, n); + return msg_buf; + } + + return result; + } +} #endif diff --git a/gl/strerror_r.c b/gl/strerror_r.c deleted file mode 100644 index 30dcd44e7c..0000000000 --- a/gl/strerror_r.c +++ /dev/null @@ -1,650 +0,0 @@ -/* strerror_r.c --- POSIX compatible system error routine - - Copyright (C) 2010-2011 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 <http://www.gnu.org/licenses/>. */ - -/* Written by Bruno Haible <bruno@clisp.org>, 2010. */ - -#include <config.h> - -/* Enable declaration of sys_nerr and sys_errlist in <errno.h> on NetBSD. */ -#define _NETBSD_SOURCE 1 - -/* Specification. */ -#include <string.h> - -#include <errno.h> - -# if GNULIB_defined_ESOCK /* native Windows platforms */ -# if HAVE_WINSOCK2_H -# include <winsock2.h> -# endif -# endif - - -#if (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__) && HAVE___XPG_STRERROR_R /* glibc >= 2.3.4, cygwin >= 1.7.9 */ - -# define USE_XPG_STRERROR_R 1 - -#elif HAVE_DECL_STRERROR_R && !(__GLIBC__ >= 2 || defined __UCLIBC__) - -/* The system's strerror_r function is OK, except that its third argument - is 'int', not 'size_t', or its return type is wrong. */ - -# include <limits.h> - -# define USE_SYSTEM_STRERROR_R 1 - -#else /* (__GLIBC__ >= 2 || defined __UCLIBC__ ? !HAVE___XPG_STRERROR_R : !HAVE_DECL_STRERROR_R) */ - -/* Use the system's strerror(). */ -# undef strerror - -# define USE_SYSTEM_STRERROR 1 - -# if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __sgi || (defined __sun && !defined _LP64) - -/* No locking needed. */ - -/* Get catgets internationalization functions. */ -# if HAVE_CATGETS -# include <nl_types.h> -# endif - -/* Get sys_nerr, sys_errlist on HP-UX (otherwise only declared in C++ mode). - Get sys_nerr, sys_errlist on IRIX (otherwise only declared with _SGIAPI). */ -# if defined __hpux || defined __sgi -extern int sys_nerr; -extern char *sys_errlist[]; -# endif - -/* Get sys_nerr on Solaris. */ -# if defined __sun && !defined _LP64 -extern int sys_nerr; -# endif - -/* Get sys_nerr, sys_errlist on native Windows. */ -# include <stdlib.h> - -# else - -# include "glthread/lock.h" - -/* This lock protects the buffer returned by strerror(). We assume that - no other uses of strerror() exist in the program. */ -gl_lock_define_initialized(static, strerror_lock) - -# endif - -#endif - - -int -strerror_r (int errnum, char *buf, size_t buflen) -#undef strerror_r -{ -#if GNULIB_defined_ETXTBSY \ - || GNULIB_defined_ESOCK \ - || GNULIB_defined_ENOMSG \ - || GNULIB_defined_EIDRM \ - || GNULIB_defined_ENOLINK \ - || GNULIB_defined_EPROTO \ - || GNULIB_defined_EMULTIHOP \ - || GNULIB_defined_EBADMSG \ - || GNULIB_defined_EOVERFLOW \ - || GNULIB_defined_ENOTSUP \ - || GNULIB_defined_ESTALE \ - || GNULIB_defined_EDQUOT \ - || GNULIB_defined_ECANCELED - { - char const *msg = NULL; - /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ - switch (errnum) - { -# if GNULIB_defined_ETXTBSY - case ETXTBSY: - msg = "Text file busy"; - break; -# endif - -# if GNULIB_defined_ESOCK /* native Windows platforms */ - /* EWOULDBLOCK is the same as EAGAIN. */ - case EINPROGRESS: - msg = "Operation now in progress"; - break; - case EALREADY: - msg = "Operation already in progress"; - break; - case ENOTSOCK: - msg = "Socket operation on non-socket"; - break; - case EDESTADDRREQ: - msg = "Destination address required"; - break; - case EMSGSIZE: - msg = "Message too long"; - break; - case EPROTOTYPE: - msg = "Protocol wrong type for socket"; - break; - case ENOPROTOOPT: - msg = "Protocol not available"; - break; - case EPROTONOSUPPORT: - msg = "Protocol not supported"; - break; - case ESOCKTNOSUPPORT: - msg = "Socket type not supported"; - break; - case EOPNOTSUPP: - msg = "Operation not supported"; - break; - case EPFNOSUPPORT: - msg = "Protocol family not supported"; - break; - case EAFNOSUPPORT: - msg = "Address family not supported by protocol"; - break; - case EADDRINUSE: - msg = "Address already in use"; - break; - case EADDRNOTAVAIL: - msg = "Cannot assign requested address"; - break; - case ENETDOWN: - msg = "Network is down"; - break; - case ENETUNREACH: - msg = "Network is unreachable"; - break; - case ENETRESET: - msg = "Network dropped connection on reset"; - break; - case ECONNABORTED: - msg = "Software caused connection abort"; - break; - case ECONNRESET: - msg = "Connection reset by peer"; - break; - case ENOBUFS: - msg = "No buffer space available"; - break; - case EISCONN: - msg = "Transport endpoint is already connected"; - break; - case ENOTCONN: - msg = "Transport endpoint is not connected"; - break; - case ESHUTDOWN: - msg = "Cannot send after transport endpoint shutdown"; - break; - case ETOOMANYREFS: - msg = "Too many references: cannot splice"; - break; - case ETIMEDOUT: - msg = "Connection timed out"; - break; - case ECONNREFUSED: - msg = "Connection refused"; - break; - case ELOOP: - msg = "Too many levels of symbolic links"; - break; - case EHOSTDOWN: - msg = "Host is down"; - break; - case EHOSTUNREACH: - msg = "No route to host"; - break; - case EPROCLIM: - msg = "Too many processes"; - break; - case EUSERS: - msg = "Too many users"; - break; - case EDQUOT: - msg = "Disk quota exceeded"; - break; - case ESTALE: - msg = "Stale NFS file handle"; - break; - case EREMOTE: - msg = "Object is remote"; - break; -# if HAVE_WINSOCK2_H - /* WSA_INVALID_HANDLE maps to EBADF */ - /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */ - /* WSA_INVALID_PARAMETER maps to EINVAL */ - case WSA_OPERATION_ABORTED: - msg = "Overlapped operation aborted"; - break; - case WSA_IO_INCOMPLETE: - msg = "Overlapped I/O event object not in signaled state"; - break; - case WSA_IO_PENDING: - msg = "Overlapped operations will complete later"; - break; - /* WSAEINTR maps to EINTR */ - /* WSAEBADF maps to EBADF */ - /* WSAEACCES maps to EACCES */ - /* WSAEFAULT maps to EFAULT */ - /* WSAEINVAL maps to EINVAL */ - /* WSAEMFILE maps to EMFILE */ - /* WSAEWOULDBLOCK maps to EWOULDBLOCK */ - /* WSAEINPROGRESS is EINPROGRESS */ - /* WSAEALREADY is EALREADY */ - /* WSAENOTSOCK is ENOTSOCK */ - /* WSAEDESTADDRREQ is EDESTADDRREQ */ - /* WSAEMSGSIZE is EMSGSIZE */ - /* WSAEPROTOTYPE is EPROTOTYPE */ - /* WSAENOPROTOOPT is ENOPROTOOPT */ - /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */ - /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */ - /* WSAEOPNOTSUPP is EOPNOTSUPP */ - /* WSAEPFNOSUPPORT is EPFNOSUPPORT */ - /* WSAEAFNOSUPPORT is EAFNOSUPPORT */ - /* WSAEADDRINUSE is EADDRINUSE */ - /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */ - /* WSAENETDOWN is ENETDOWN */ - /* WSAENETUNREACH is ENETUNREACH */ - /* WSAENETRESET is ENETRESET */ - /* WSAECONNABORTED is ECONNABORTED */ - /* WSAECONNRESET is ECONNRESET */ - /* WSAENOBUFS is ENOBUFS */ - /* WSAEISCONN is EISCONN */ - /* WSAENOTCONN is ENOTCONN */ - /* WSAESHUTDOWN is ESHUTDOWN */ - /* WSAETOOMANYREFS is ETOOMANYREFS */ - /* WSAETIMEDOUT is ETIMEDOUT */ - /* WSAECONNREFUSED is ECONNREFUSED */ - /* WSAELOOP is ELOOP */ - /* WSAENAMETOOLONG maps to ENAMETOOLONG */ - /* WSAEHOSTDOWN is EHOSTDOWN */ - /* WSAEHOSTUNREACH is EHOSTUNREACH */ - /* WSAENOTEMPTY maps to ENOTEMPTY */ - /* WSAEPROCLIM is EPROCLIM */ - /* WSAEUSERS is EUSERS */ - /* WSAEDQUOT is EDQUOT */ - /* WSAESTALE is ESTALE */ - /* WSAEREMOTE is EREMOTE */ - case WSASYSNOTREADY: - msg = "Network subsystem is unavailable"; - break; - case WSAVERNOTSUPPORTED: - msg = "Winsock.dll version out of range"; - break; - case WSANOTINITIALISED: - msg = "Successful WSAStartup not yet performed"; - break; - case WSAEDISCON: - msg = "Graceful shutdown in progress"; - break; - case WSAENOMORE: case WSA_E_NO_MORE: - msg = "No more results"; - break; - case WSAECANCELLED: case WSA_E_CANCELLED: - msg = "Call was canceled"; - break; - case WSAEINVALIDPROCTABLE: - msg = "Procedure call table is invalid"; - break; - case WSAEINVALIDPROVIDER: - msg = "Service provider is invalid"; - break; - case WSAEPROVIDERFAILEDINIT: - msg = "Service provider failed to initialize"; - break; - case WSASYSCALLFAILURE: - msg = "System call failure"; - break; - case WSASERVICE_NOT_FOUND: - msg = "Service not found"; - break; - case WSATYPE_NOT_FOUND: - msg = "Class type not found"; - break; - case WSAEREFUSED: - msg = "Database query was refused"; - break; - case WSAHOST_NOT_FOUND: - msg = "Host not found"; - break; - case WSATRY_AGAIN: - msg = "Nonauthoritative host not found"; - break; - case WSANO_RECOVERY: - msg = "Nonrecoverable error"; - break; - case WSANO_DATA: - msg = "Valid name, no data record of requested type"; - break; - /* WSA_QOS_* omitted */ -# endif -# endif - -# if GNULIB_defined_ENOMSG - case ENOMSG: - msg = "No message of desired type"; - break; -# endif - -# if GNULIB_defined_EIDRM - case EIDRM: - msg = "Identifier removed"; - break; -# endif - -# if GNULIB_defined_ENOLINK - case ENOLINK: - msg = "Link has been severed"; - break; -# endif - -# if GNULIB_defined_EPROTO - case EPROTO: - msg = "Protocol error"; - break; -# endif - -# if GNULIB_defined_EMULTIHOP - case EMULTIHOP: - msg = "Multihop attempted"; - break; -# endif - -# if GNULIB_defined_EBADMSG - case EBADMSG: - msg = "Bad message"; - break; -# endif - -# if GNULIB_defined_EOVERFLOW - case EOVERFLOW: - msg = "Value too large for defined data type"; - break; -# endif - -# if GNULIB_defined_ENOTSUP - case ENOTSUP: - msg = "Not supported"; - break; -# endif - -# if GNULIB_defined_ESTALE - case ESTALE: - msg = "Stale NFS file handle"; - break; -# endif - -# if GNULIB_defined_EDQUOT - case EDQUOT: - msg = "Disk quota exceeded"; - break; -# endif - -# if GNULIB_defined_ECANCELED - case ECANCELED: - msg = "Operation canceled"; - break; -# endif - } - - if (msg) - { - int saved_errno = errno; - size_t len = strlen (msg); - int ret = ERANGE; - - if (len < buflen) - { - memcpy (buf, msg, len + 1); - ret = 0; - } - errno = saved_errno; - return ret; - } - } -#endif - - { - int ret; - int saved_errno = errno; - -#if USE_XPG_STRERROR_R - - { - extern int __xpg_strerror_r (int errnum, char *buf, size_t buflen); - - ret = __xpg_strerror_r (errnum, buf, buflen); - if (ret < 0) - ret = errno; - } - -#elif USE_SYSTEM_STRERROR_R - - if (buflen > INT_MAX) - buflen = INT_MAX; - -# ifdef __hpux - /* On HP-UX 11.31, strerror_r always fails when buflen < 80. */ - { - char stackbuf[80]; - - if (buflen < sizeof (stackbuf)) - { - ret = strerror_r (errnum, stackbuf, sizeof (stackbuf)); - if (ret == 0) - { - size_t len = strlen (stackbuf); - - if (len < buflen) - memcpy (buf, stackbuf, len + 1); - else - ret = ERANGE; - } - } - else - ret = strerror_r (errnum, buf, buflen); - } -# elif defined __CYGWIN__ - /* Cygwin <= 1.7.7 only provides the glibc interface, is thread-safe, and - always succeeds (although it may truncate). In Cygwin >= 1.7.8, for - valid errnum values, instead of truncating, it leaves the buffer - untouched. */ - { - char stackbuf[256]; - - if (buflen < sizeof (stackbuf)) - { - size_t len; - - stackbuf[0] = '\0'; /* in case strerror_r does nothing */ - strerror_r (errnum, stackbuf, sizeof (stackbuf)); - len = strlen (stackbuf); - if (len < buflen) - { - memcpy (buf, stackbuf, len + 1); - ret = 0; - } - else - ret = ERANGE; - } - else - { - buf[0] = '\0'; /* in case strerror_r does nothing */ - strerror_r (errnum, buf, buflen); - ret = 0; - } - } -# else - ret = strerror_r (errnum, buf, buflen); -# endif - -# ifdef _AIX - /* On AIX 6.1, strerror_r returns -1 and sets errno to EINVAL - if buflen <= 1. */ - if (ret < 0 && errno == EINVAL && buflen <= 1) - { - /* Retry with a larger buffer. */ - char largerbuf[10]; - ret = strerror_r (errnum, largerbuf, sizeof (largerbuf)); - if (ret < 0 && errno == EINVAL) - { - /* errnum was out of range. */ - ret = EINVAL; - } - else - { - /* buf was too small. */ - ret = ERANGE; - } - } -# endif - - /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */ - if (ret < 0) - ret = errno; - - /* FreeBSD rejects 0; see http://austingroupbugs.net/view.php?id=382. */ - if (errnum == 0 && ret == EINVAL) - { - if (buflen <= strlen ("Success")) - { - ret = ERANGE; - if (buflen) - buf[0] = 0; - } - else - { - ret = 0; - strcpy (buf, "Success"); - } - } - -#else /* USE_SYSTEM_STRERROR */ - - /* Try to do what strerror (errnum) does, but without clobbering the - buffer used by strerror(). */ - -# if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) /* NetBSD, HP-UX, native Win32 */ - - /* NetBSD: sys_nerr, sys_errlist are declared through _NETBSD_SOURCE - and <errno.h> above. - HP-UX: sys_nerr, sys_errlist are declared explicitly above. - native Win32: sys_nerr, sys_errlist are declared in <stdlib.h>. */ - if (errnum >= 0 && errnum < sys_nerr) - { -# if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux) -# if defined __NetBSD__ - nl_catd catd = catopen ("libc", NL_CAT_LOCALE); - const char *errmsg = - (catd != (nl_catd)-1 - ? catgets (catd, 1, errnum, sys_errlist[errnum]) - : sys_errlist[errnum]); -# endif -# if defined __hpux - nl_catd catd = catopen ("perror", NL_CAT_LOCALE); - const char *errmsg = - (catd != (nl_catd)-1 - ? catgets (catd, 1, 1 + errnum, sys_errlist[errnum]) - : sys_errlist[errnum]); -# endif -# else - const char *errmsg = sys_errlist[errnum]; -# endif - if (errmsg == NULL || *errmsg == '\0') - ret = EINVAL; - else - { - size_t len = strlen (errmsg); - - if (len < buflen) - { - memcpy (buf, errmsg, len + 1); - ret = 0; - } - else - ret = ERANGE; - } -# if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux) - if (catd != (nl_catd)-1) - catclose (catd); -# endif - } - else - ret = EINVAL; - -# elif defined __sgi || (defined __sun && !defined _LP64) /* IRIX, Solaris <= 9 32-bit */ - - /* For a valid error number, the system's strerror() function returns - a pointer to a not copied string, not to a buffer. */ - if (errnum >= 0 && errnum < sys_nerr) - { - char *errmsg = strerror (errnum); - - if (errmsg == NULL || *errmsg == '\0') - ret = EINVAL; - else - { - size_t len = strlen (errmsg); - - if (len < buflen) - { - memcpy (buf, errmsg, len + 1); - ret = 0; - } - else - ret = ERANGE; - } - } - else - ret = EINVAL; - -# else - - gl_lock_lock (strerror_lock); - - { - char *errmsg = strerror (errnum); - - /* For invalid error numbers, strerror() on - - IRIX 6.5 returns NULL, - - HP-UX 11 returns an empty string. */ - if (errmsg == NULL || *errmsg == '\0') - ret = EINVAL; - else - { - size_t len = strlen (errmsg); - - if (len < buflen) - { - memcpy (buf, errmsg, len + 1); - ret = 0; - } - else - ret = ERANGE; - } - } - - gl_lock_unlock (strerror_lock); - -# endif - -#endif - - errno = saved_errno; - return ret; - } -} diff --git a/gl/tests/Makefile.am b/gl/tests/Makefile.am index 703b7b45d5..4d0a31733c 100644 --- a/gl/tests/Makefile.am +++ b/gl/tests/Makefile.am @@ -10,7 +10,7 @@ # # Generated by gnulib-tool. -AUTOMAKE_OPTIONS = 1.5 foreign subdir-objects +AUTOMAKE_OPTIONS = 1.5 foreign SUBDIRS = . TESTS = @@ -267,7 +267,7 @@ EXTRA_DIST += signature.h test-gettimeofday.c TESTS += test-intprops check_PROGRAMS += test-intprops -EXTRA_DIST += test-intprops.c macros.h +EXTRA_DIST += test-intprops.c ## end gnulib module intprops-tests @@ -321,15 +321,6 @@ EXTRA_DIST += test-inttypes.c ## end gnulib module inttypes-tests -## begin gnulib module lock-tests - -TESTS += test-lock -check_PROGRAMS += test-lock -test_lock_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@ -EXTRA_DIST += test-lock.c - -## end gnulib module lock-tests - ## begin gnulib module memchr-tests TESTS += test-memchr @@ -428,14 +419,6 @@ EXTRA_DIST += test-strerror.c signature.h macros.h ## end gnulib module strerror-tests -## begin gnulib module strerror_r-posix-tests - -TESTS += test-strerror_r -check_PROGRAMS += test-strerror_r -EXTRA_DIST += test-strerror_r.c signature.h macros.h - -## end gnulib module strerror_r-posix-tests - ## begin gnulib module string-tests TESTS += test-string @@ -492,12 +475,6 @@ EXTRA_DIST += test-sys_uio.c ## end gnulib module sys_uio-tests -## begin gnulib module thread - -libtests_a_SOURCES += glthread/thread.h glthread/thread.c - -## end gnulib module thread - ## begin gnulib module time-tests TESTS += test-time @@ -594,11 +571,11 @@ EXTRA_DIST += test-wchar.c ## end gnulib module wchar-tests -## begin gnulib module yield +## begin gnulib module dummy -libtests_a_SOURCES += glthread/yield.h +libtests_a_SOURCES += dummy.c -## end gnulib module yield +## end gnulib module dummy # Clean up after Solaris cc. clean-local: diff --git a/gl/tests/dummy.c b/gl/tests/dummy.c new file mode 100644 index 0000000000..c958ea05d8 --- /dev/null +++ b/gl/tests/dummy.c @@ -0,0 +1,42 @@ +/* A dummy file, to prevent empty libraries from breaking builds. + Copyright (C) 2004, 2007, 2009-2011 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 <http://www.gnu.org/licenses/>. */ + +/* Some systems, reportedly OpenBSD and Mac OS X, refuse to create + libraries without any object files. You might get an error like: + + > ar cru .libs/libgl.a + > ar: no archive members specified + + Compiling this file, and adding its object file to the library, will + prevent the library from being empty. */ + +/* Some systems, such as Solaris with cc 5.0, refuse to work with libraries + that don't export any symbol. You might get an error like: + + > cc ... libgnu.a + > ild: (bad file) garbled symbol table in archive ../gllib/libgnu.a + + Compiling this file, and adding its object file to the library, will + prevent the library from exporting no symbols. */ + +#ifdef __sun +/* This declaration ensures that the library will export at least 1 symbol. */ +int gl_dummy_symbol; +#else +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; +#endif diff --git a/gl/tests/glthread/thread.c b/gl/tests/glthread/thread.c deleted file mode 100644 index bb40092fc2..0000000000 --- a/gl/tests/glthread/thread.c +++ /dev/null @@ -1,218 +0,0 @@ -/* Creating and controlling threads. - Copyright (C) 2005-2011 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, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Bruno Haible <bruno@clisp.org>, 2005. - Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, - gthr-win32.h. */ - -#include <config.h> - -/* Specification. */ -#include "glthread/thread.h" - -#include <stdlib.h> -#include "glthread/lock.h" - -/* ========================================================================= */ - -#if USE_WIN32_THREADS - -#include <process.h> - -/* -------------------------- gl_thread_t datatype -------------------------- */ - -/* The Thread-Local Storage (TLS) key that allows to access each thread's - 'struct gl_thread_struct *' pointer. */ -static DWORD self_key = (DWORD)-1; - -/* Initializes self_key. This function must only be called once. */ -static void -do_init_self_key (void) -{ - self_key = TlsAlloc (); - /* If this fails, we're hosed. */ - if (self_key == (DWORD)-1) - abort (); -} - -/* Initializes self_key. */ -static void -init_self_key (void) -{ - gl_once_define(static, once) - gl_once (once, do_init_self_key); -} - -/* This structure contains information about a thread. - It is stored in TLS under key self_key. */ -struct gl_thread_struct -{ - /* Fields for managing the handle. */ - HANDLE volatile handle; - CRITICAL_SECTION handle_lock; - /* Fields for managing the exit value. */ - void * volatile result; - /* Fields for managing the thread start. */ - void * (*func) (void *); - void *arg; -}; - -/* Return a real HANDLE object for the current thread. */ -static inline HANDLE -get_current_thread_handle (void) -{ - HANDLE this_handle; - - /* GetCurrentThread() returns a pseudo-handle, i.e. only a symbolic - identifier, not a real handle. */ - if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), - GetCurrentProcess (), &this_handle, - 0, FALSE, DUPLICATE_SAME_ACCESS)) - abort (); - return this_handle; -} - -gl_thread_t -gl_thread_self_func (void) -{ - gl_thread_t thread; - - if (self_key == (DWORD)-1) - init_self_key (); - thread = TlsGetValue (self_key); - if (thread == NULL) - { - /* This happens only in threads that have not been created through - glthread_create(), such as the main thread. */ - for (;;) - { - thread = - (struct gl_thread_struct *) - malloc (sizeof (struct gl_thread_struct)); - if (thread != NULL) - break; - /* Memory allocation failed. There is not much we can do. Have to - busy-loop, waiting for the availability of memory. */ - Sleep (1); - } - - thread->handle = get_current_thread_handle (); - InitializeCriticalSection (&thread->handle_lock); - thread->result = NULL; /* just to be deterministic */ - TlsSetValue (self_key, thread); - } - return thread; -} - -/* The main function of a freshly creating thread. It's a wrapper around - the FUNC and ARG arguments passed to glthread_create_func. */ -static unsigned int WINAPI -wrapper_func (void *varg) -{ - struct gl_thread_struct *thread = (struct gl_thread_struct *)varg; - - EnterCriticalSection (&thread->handle_lock); - /* Create a new handle for the thread only if the parent thread did not yet - fill in the handle. */ - if (thread->handle == NULL) - thread->handle = get_current_thread_handle (); - LeaveCriticalSection (&thread->handle_lock); - - if (self_key == (DWORD)-1) - init_self_key (); - TlsSetValue (self_key, thread); - - /* Run the thread. Store the exit value if the thread was not terminated - otherwise. */ - thread->result = thread->func (thread->arg); - return 0; -} - -int -glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg) -{ - struct gl_thread_struct *thread = - (struct gl_thread_struct *) malloc (sizeof (struct gl_thread_struct)); - if (thread == NULL) - return ENOMEM; - thread->handle = NULL; - InitializeCriticalSection (&thread->handle_lock); - thread->result = NULL; /* just to be deterministic */ - thread->func = func; - thread->arg = arg; - - { - unsigned int thread_id; - HANDLE thread_handle; - - thread_handle = (HANDLE) - _beginthreadex (NULL, 100000, wrapper_func, thread, 0, &thread_id); - /* calls CreateThread with the same arguments */ - if (thread_handle == NULL) - { - DeleteCriticalSection (&thread->handle_lock); - free (thread); - return EAGAIN; - } - - EnterCriticalSection (&thread->handle_lock); - if (thread->handle == NULL) - thread->handle = thread_handle; - else - /* thread->handle was already set by the thread itself. */ - CloseHandle (thread_handle); - LeaveCriticalSection (&thread->handle_lock); - - *threadp = thread; - return 0; - } -} - -int -glthread_join_func (gl_thread_t thread, void **retvalp) -{ - if (thread == NULL) - return EINVAL; - - if (thread == gl_thread_self ()) - return EDEADLK; - - if (WaitForSingleObject (thread->handle, INFINITE) == WAIT_FAILED) - return EINVAL; - - if (retvalp != NULL) - *retvalp = thread->result; - - DeleteCriticalSection (&thread->handle_lock); - CloseHandle (thread->handle); - free (thread); - - return 0; -} - -int -gl_thread_exit_func (void *retval) -{ - gl_thread_t thread = gl_thread_self (); - thread->result = retval; - _endthreadex (0); /* calls ExitThread (0) */ - abort (); -} - -#endif - -/* ========================================================================= */ diff --git a/gl/tests/glthread/thread.h b/gl/tests/glthread/thread.h deleted file mode 100644 index 370f09a378..0000000000 --- a/gl/tests/glthread/thread.h +++ /dev/null @@ -1,376 +0,0 @@ -/* Creating and controlling threads. - Copyright (C) 2005-2011 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, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Bruno Haible <bruno@clisp.org>, 2005. - Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, - gthr-win32.h. */ - -/* This file contains primitives for creating and controlling threads. - - Thread data type: gl_thread_t. - - Creating a thread: - thread = gl_thread_create (func, arg); - Or with control of error handling: - err = glthread_create (&thread, func, arg); - extern int glthread_create (gl_thread_t *result, - void *(*func) (void *), void *arg); - - Querying and changing the signal mask of a thread (not supported on all - platforms): - gl_thread_sigmask (how, newmask, oldmask); - Or with control of error handling: - err = glthread_sigmask (how, newmask, oldmask); - extern int glthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask); - - Waiting for termination of another thread: - gl_thread_join (thread, &return_value); - Or with control of error handling: - err = glthread_join (thread, &return_value); - extern int glthread_join (gl_thread_t thread, void **return_value_ptr); - - Getting a reference to the current thread: - current = gl_thread_self (); - extern gl_thread_t gl_thread_self (void); - - Terminating the current thread: - gl_thread_exit (return_value); - extern void gl_thread_exit (void *return_value) __attribute__ ((noreturn)); - - Requesting custom code to be executed at fork() time(not supported on all - platforms): - gl_thread_atfork (prepare_func, parent_func, child_func); - Or with control of error handling: - err = glthread_atfork (prepare_func, parent_func, child_func); - extern int glthread_atfork (void (*prepare_func) (void), - void (*parent_func) (void), - void (*child_func) (void)); - Note that even on platforms where this is supported, use of fork() and - threads together is problematic, see - <http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00062.html> - */ - - -#ifndef _GLTHREAD_THREAD_H -#define _GLTHREAD_THREAD_H - -#include <errno.h> -#include <stdlib.h> - -/* ========================================================================= */ - -#if USE_POSIX_THREADS - -/* Use the POSIX threads library. */ - -# include <pthread.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# if PTHREAD_IN_USE_DETECTION_HARD - -/* The pthread_in_use() detection needs to be done at runtime. */ -# define pthread_in_use() \ - glthread_in_use () -extern int glthread_in_use (void); - -# endif - -# if USE_POSIX_THREADS_WEAK - -/* Use weak references to the POSIX threads library. */ - -/* Weak references avoid dragging in external libraries if the other parts - of the program don't use them. Here we use them, because we don't want - every program that uses libintl to depend on libpthread. This assumes - that libpthread would not be loaded after libintl; i.e. if libintl is - loaded first, by an executable that does not depend on libpthread, and - then a module is dynamically loaded that depends on libpthread, libintl - will not be multithread-safe. */ - -/* The way to test at runtime whether libpthread is present is to test - whether a function pointer's value, such as &pthread_mutex_init, is - non-NULL. However, some versions of GCC have a bug through which, in - PIC mode, &foo != NULL always evaluates to true if there is a direct - call to foo(...) in the same function. To avoid this, we test the - address of a function in libpthread that we don't use. */ - -# pragma weak pthread_create -# pragma weak pthread_sigmask -# pragma weak pthread_join -# ifndef pthread_self -# pragma weak pthread_self -# endif -# pragma weak pthread_exit -# if HAVE_PTHREAD_ATFORK -# pragma weak pthread_atfork -# endif - -# if !PTHREAD_IN_USE_DETECTION_HARD -# pragma weak pthread_cancel -# define pthread_in_use() (pthread_cancel != NULL) -# endif - -# else - -# if !PTHREAD_IN_USE_DETECTION_HARD -# define pthread_in_use() 1 -# endif - -# endif - -/* -------------------------- gl_thread_t datatype -------------------------- */ - -/* This choice of gl_thread_t assumes that - pthread_equal (a, b) is equivalent to ((a) == (b)). - This is the case on all platforms in use in 2008. */ -typedef pthread_t gl_thread_t; -# define glthread_create(THREADP, FUNC, ARG) \ - (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS) -# define glthread_sigmask(HOW, SET, OSET) \ - (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0) -# define glthread_join(THREAD, RETVALP) \ - (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0) -# define gl_thread_self() \ - (pthread_in_use () ? (void *) pthread_self () : NULL) -# define gl_thread_exit(RETVAL) \ - (pthread_in_use () ? pthread_exit (RETVAL) : 0) - -# if HAVE_PTHREAD_ATFORK -# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \ - (pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) : 0) -# else -# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 -# endif - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_PTH_THREADS - -/* Use the GNU Pth threads library. */ - -# include <pth.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# if USE_PTH_THREADS_WEAK - -/* Use weak references to the GNU Pth threads library. */ - -# pragma weak pth_spawn -# pragma weak pth_sigmask -# pragma weak pth_join -# pragma weak pth_self -# pragma weak pth_exit - -# pragma weak pth_cancel -# define pth_in_use() (pth_cancel != NULL) - -# else - -# define pth_in_use() 1 - -# endif -/* -------------------------- gl_thread_t datatype -------------------------- */ - -typedef pth_t gl_thread_t; -# define glthread_create(THREADP, FUNC, ARG) \ - (pth_in_use () ? ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errno) : 0) -# define glthread_sigmask(HOW, SET, OSET) \ - (pth_in_use () && !pth_sigmask (HOW, SET, OSET) ? errno : 0) -# define glthread_join(THREAD, RETVALP) \ - (pth_in_use () && !pth_join (THREAD, RETVALP) ? errno : 0) -# define gl_thread_self() \ - (pth_in_use () ? (void *) pth_self () : 0) -# define gl_thread_exit(RETVAL) \ - (pth_in_use () ? pth_exit (RETVAL) : 0) -# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_SOLARIS_THREADS - -/* Use the old Solaris threads library. */ - -# include <thread.h> -# include <synch.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# if USE_SOLARIS_THREADS_WEAK - -/* Use weak references to the old Solaris threads library. */ - -# pragma weak thr_create -# pragma weak thr_join -# pragma weak thr_self -# pragma weak thr_exit - -# pragma weak thr_suspend -# define thread_in_use() (thr_suspend != NULL) - -# else - -# define thread_in_use() 1 - -# endif - -/* -------------------------- gl_thread_t datatype -------------------------- */ - -typedef thread_t gl_thread_t; -# define glthread_create(THREADP, FUNC, ARG) \ - (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0) -# define glthread_sigmask(HOW, SET, OSET) \ - (thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0) -# define glthread_join(THREAD, RETVALP) \ - (thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0) -# define gl_thread_self() \ - (thread_in_use () ? (void *) thr_self () : 0) -# define gl_thread_exit(RETVAL) \ - (thread_in_use () ? thr_exit (RETVAL) : 0) -# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_WIN32_THREADS - -# include <windows.h> - -# ifdef __cplusplus -extern "C" { -# endif - -/* -------------------------- gl_thread_t datatype -------------------------- */ - -/* The gl_thread_t is a pointer to a structure in memory. - Why not the thread handle? If it were the thread handle, it would be hard - to implement gl_thread_self() (since GetCurrentThread () returns a pseudo- - handle, DuplicateHandle (GetCurrentThread ()) returns a handle that must be - closed afterwards, and there is no function for quickly retrieving a thread - handle from its id). - Why not the thread id? I tried it. It did not work: Sometimes ids appeared - that did not belong to running threads, and glthread_join failed with ESRCH. - */ -typedef struct gl_thread_struct *gl_thread_t; -# define glthread_create(THREADP, FUNC, ARG) \ - glthread_create_func (THREADP, FUNC, ARG) -# define glthread_sigmask(HOW, SET, OSET) \ - /* unsupported */ 0 -# define glthread_join(THREAD, RETVALP) \ - glthread_join_func (THREAD, RETVALP) -# define gl_thread_self() \ - gl_thread_self_func () -# define gl_thread_exit(RETVAL) \ - gl_thread_exit_func (RETVAL) -# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 -extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg); -extern int glthread_join_func (gl_thread_t thread, void **retvalp); -extern gl_thread_t gl_thread_self_func (void); -extern int gl_thread_exit_func (void *retval); - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS) - -/* Provide dummy implementation if threads are not supported. */ - -typedef int gl_thread_t; -# define glthread_create(THREADP, FUNC, ARG) ENOSYS -# define glthread_sigmask(HOW, SET, OSET) 0 -# define glthread_join(THREAD, RETVALP) 0 -# define gl_thread_self() NULL -# define gl_thread_exit(RETVAL) 0 -# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 - -#endif - -/* ========================================================================= */ - -/* Macros with built-in error handling. */ - -#ifdef __cplusplus -extern "C" { -#endif - -static inline gl_thread_t -gl_thread_create (void *(*func) (void *arg), void *arg) -{ - gl_thread_t thread; - int ret; - - ret = glthread_create (&thread, func, arg); - if (ret != 0) - abort (); - return thread; -} -#define gl_thread_sigmask(HOW, SET, OSET) \ - do \ - { \ - if (glthread_sigmask (HOW, SET, OSET)) \ - abort (); \ - } \ - while (0) -#define gl_thread_join(THREAD, RETVAL) \ - do \ - { \ - if (glthread_join (THREAD, RETVAL)) \ - abort (); \ - } \ - while (0) -#define gl_thread_atfork(PREPARE, PARENT, CHILD) \ - do \ - { \ - if (glthread_atfork (PREPARE, PARENT, CHILD)) \ - abort (); \ - } \ - while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* _GLTHREAD_THREAD_H */ diff --git a/gl/tests/glthread/yield.h b/gl/tests/glthread/yield.h deleted file mode 100644 index 4eb1cb845b..0000000000 --- a/gl/tests/glthread/yield.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Yielding the processor to other threads and processes. - Copyright (C) 2005-2011 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, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* This file contains a primitive for yielding the processor to other threads. - extern void gl_thread_yield (void); - */ - -#ifndef _GLTHREAD_YIELD_H -#define _GLTHREAD_YIELD_H - -#include <errno.h> - -/* ========================================================================= */ - -#if USE_POSIX_THREADS - -/* Use the POSIX threads library. */ - -# include <sched.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# define gl_thread_yield() \ - sched_yield () - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_PTH_THREADS - -/* Use the GNU Pth threads library. */ - -# include <pth.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# define gl_thread_yield() \ - pth_yield (NULL) - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_SOLARIS_THREADS - -/* Use the old Solaris threads library. */ - -# include <thread.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# define gl_thread_yield() \ - thr_yield () - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_WIN32_THREADS - -# include <windows.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# define gl_thread_yield() \ - Sleep (0) - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS) - -/* Provide dummy implementation if threads are not supported. */ - -# define gl_thread_yield() 0 - -#endif - -/* ========================================================================= */ - -#endif /* _GLTHREAD_YIELD_H */ diff --git a/gl/tests/test-intprops.c b/gl/tests/test-intprops.c index 8fc582b90f..aae261432a 100644 --- a/gl/tests/test-intprops.c +++ b/gl/tests/test-intprops.c @@ -24,246 +24,230 @@ #include <stdbool.h> #include <inttypes.h> -#include "macros.h" - -/* VERIFY (X) uses a static assertion for compilers that are known to work, - and falls back on a dynamic assertion for other compilers. - These tests should be checkable via 'verify' rather than 'ASSERT', but - using 'verify' would run into a bug with HP-UX 11.23 cc; see - <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>. */ -#if __GNUC__ || __SUNPRO_C -# define VERIFY(x) do { verify (x); } while (0) -#else -# define VERIFY(x) ASSERT (x) +/* TYPE_IS_INTEGER. */ +verify (TYPE_IS_INTEGER (bool)); +verify (TYPE_IS_INTEGER (char)); +verify (TYPE_IS_INTEGER (signed char)); +verify (TYPE_IS_INTEGER (unsigned char)); +verify (TYPE_IS_INTEGER (short int)); +verify (TYPE_IS_INTEGER (unsigned short int)); +verify (TYPE_IS_INTEGER (int)); +verify (TYPE_IS_INTEGER (unsigned int)); +verify (TYPE_IS_INTEGER (long int)); +verify (TYPE_IS_INTEGER (unsigned long int)); +verify (TYPE_IS_INTEGER (intmax_t)); +verify (TYPE_IS_INTEGER (uintmax_t)); +verify (! TYPE_IS_INTEGER (float)); +verify (! TYPE_IS_INTEGER (double)); +verify (! TYPE_IS_INTEGER (long double)); + +/* Integer representation. */ +verify (INT_MIN + INT_MAX < 0 + ? (TYPE_TWOS_COMPLEMENT (int) + && ! TYPE_ONES_COMPLEMENT (int) && ! TYPE_SIGNED_MAGNITUDE (int)) + : (! TYPE_TWOS_COMPLEMENT (int) + && (TYPE_ONES_COMPLEMENT (int) || TYPE_SIGNED_MAGNITUDE (int)))); + +/* TYPE_SIGNED. */ +/* verify (! TYPE_SIGNED (bool)); */ /* not guaranteed by gnulib substitute */ +verify (TYPE_SIGNED (signed char)); +verify (! TYPE_SIGNED (unsigned char)); +verify (TYPE_SIGNED (short int)); +verify (! TYPE_SIGNED (unsigned short int)); +verify (TYPE_SIGNED (int)); +verify (! TYPE_SIGNED (unsigned int)); +verify (TYPE_SIGNED (long int)); +verify (! TYPE_SIGNED (unsigned long int)); +verify (TYPE_SIGNED (intmax_t)); +verify (! TYPE_SIGNED (uintmax_t)); +verify (TYPE_SIGNED (float)); +verify (TYPE_SIGNED (double)); +verify (TYPE_SIGNED (long double)); + +/* TYPE_MINIMUM, TYPE_MAXIMUM. */ +verify (TYPE_MINIMUM (char) == CHAR_MIN); +verify (TYPE_MAXIMUM (char) == CHAR_MAX); +verify (TYPE_MINIMUM (unsigned char) == 0); +verify (TYPE_MAXIMUM (unsigned char) == UCHAR_MAX); +verify (TYPE_MINIMUM (signed char) == SCHAR_MIN); +verify (TYPE_MAXIMUM (signed char) == SCHAR_MAX); +verify (TYPE_MINIMUM (short int) == SHRT_MIN); +verify (TYPE_MAXIMUM (short int) == SHRT_MAX); +verify (TYPE_MINIMUM (unsigned short int) == 0); +verify (TYPE_MAXIMUM (unsigned short int) == USHRT_MAX); +verify (TYPE_MINIMUM (int) == INT_MIN); +verify (TYPE_MAXIMUM (int) == INT_MAX); +verify (TYPE_MINIMUM (unsigned int) == 0); +verify (TYPE_MAXIMUM (unsigned int) == UINT_MAX); +verify (TYPE_MINIMUM (long int) == LONG_MIN); +verify (TYPE_MAXIMUM (long int) == LONG_MAX); +verify (TYPE_MINIMUM (unsigned long int) == 0); +verify (TYPE_MAXIMUM (unsigned long int) == ULONG_MAX); +verify (TYPE_MINIMUM (intmax_t) == INTMAX_MIN); +verify (TYPE_MAXIMUM (intmax_t) == INTMAX_MAX); +verify (TYPE_MINIMUM (uintmax_t) == 0); +verify (TYPE_MAXIMUM (uintmax_t) == UINTMAX_MAX); + +/* INT_BITS_STRLEN_BOUND. */ +verify (INT_BITS_STRLEN_BOUND (1) == 1); +verify (INT_BITS_STRLEN_BOUND (2620) == 789); + +/* INT_STRLEN_BOUND, INT_BUFSIZE_BOUND. */ +#ifdef INT32_MAX /* POSIX guarantees int32_t; this ports to non-POSIX hosts */ +verify (INT_STRLEN_BOUND (int32_t) == sizeof ("-2147483648") - 1); +verify (INT_BUFSIZE_BOUND (int32_t) == sizeof ("-2147483648")); +#endif +#ifdef INT64_MAX +verify (INT_STRLEN_BOUND (int64_t) == sizeof ("-9223372036854775808") - 1); +verify (INT_BUFSIZE_BOUND (int64_t) == sizeof ("-9223372036854775808")); #endif +/* All the INT_<op>_RANGE_OVERFLOW tests are equally valid as + INT_<op>_OVERFLOW tests, so define a single macro to do both. */ +#define check_binop(op, a, b, min, max, overflow) \ + (INT_##op##_RANGE_OVERFLOW (a, b, min, max) == (overflow) \ + && INT_##op##_OVERFLOW (a, b) == (overflow)) +#define check_unop(op, a, min, max, overflow) \ + (INT_##op##_RANGE_OVERFLOW (a, min, max) == (overflow) \ + && INT_##op##_OVERFLOW (a) == (overflow)) + +/* INT_<op>_RANGE_OVERFLOW, INT_<op>_OVERFLOW. */ +verify (INT_ADD_RANGE_OVERFLOW (INT_MAX, 1, INT_MIN, INT_MAX)); +verify (INT_ADD_OVERFLOW (INT_MAX, 1)); +verify (check_binop (ADD, INT_MAX, 1, INT_MIN, INT_MAX, true)); +verify (check_binop (ADD, INT_MAX, -1, INT_MIN, INT_MAX, false)); +verify (check_binop (ADD, INT_MIN, 1, INT_MIN, INT_MAX, false)); +verify (check_binop (ADD, INT_MIN, -1, INT_MIN, INT_MAX, true)); +verify (check_binop (ADD, UINT_MAX, 1u, 0u, UINT_MAX, true)); +verify (check_binop (ADD, 0u, 1u, 0u, UINT_MAX, false)); + +verify (check_binop (SUBTRACT, INT_MAX, 1, INT_MIN, INT_MAX, false)); +verify (check_binop (SUBTRACT, INT_MAX, -1, INT_MIN, INT_MAX, true)); +verify (check_binop (SUBTRACT, INT_MIN, 1, INT_MIN, INT_MAX, true)); +verify (check_binop (SUBTRACT, INT_MIN, -1, INT_MIN, INT_MAX, false)); +verify (check_binop (SUBTRACT, UINT_MAX, 1u, 0u, UINT_MAX, false)); +verify (check_binop (SUBTRACT, 0u, 1u, 0u, UINT_MAX, true)); + +verify (check_unop (NEGATE, INT_MIN, INT_MIN, INT_MAX, + TYPE_TWOS_COMPLEMENT (int))); +verify (check_unop (NEGATE, 0, INT_MIN, INT_MAX, false)); +verify (check_unop (NEGATE, INT_MAX, INT_MIN, INT_MAX, false)); +verify (check_unop (NEGATE, 0u, 0u, UINT_MAX, false)); +verify (check_unop (NEGATE, 1u, 0u, UINT_MAX, true)); +verify (check_unop (NEGATE, UINT_MAX, 0u, UINT_MAX, true)); + +verify (check_binop (MULTIPLY, INT_MAX, INT_MAX, INT_MIN, INT_MAX, true)); +verify (check_binop (MULTIPLY, INT_MAX, INT_MIN, INT_MIN, INT_MAX, true)); +verify (check_binop (MULTIPLY, INT_MIN, INT_MAX, INT_MIN, INT_MAX, true)); +verify (check_binop (MULTIPLY, INT_MIN, INT_MIN, INT_MIN, INT_MAX, true)); +verify (check_binop (MULTIPLY, -1, INT_MIN, INT_MIN, INT_MAX, + INT_NEGATE_OVERFLOW (INT_MIN))); +verify (check_binop (MULTIPLY, LONG_MIN / INT_MAX, (long int) INT_MAX, + LONG_MIN, LONG_MIN, false)); + +verify (check_binop (DIVIDE, INT_MIN, -1, INT_MIN, INT_MAX, + INT_NEGATE_OVERFLOW (INT_MIN))); +verify (check_binop (DIVIDE, INT_MAX, 1, INT_MIN, INT_MAX, false)); +verify (check_binop (DIVIDE, (unsigned int) INT_MIN, + -1u, 0u, UINT_MAX, false)); + +verify (check_binop (REMAINDER, INT_MIN, -1, INT_MIN, INT_MAX, + INT_NEGATE_OVERFLOW (INT_MIN))); +verify (check_binop (REMAINDER, INT_MAX, 1, INT_MIN, INT_MAX, false)); +verify (check_binop (REMAINDER, (unsigned int) INT_MIN, + -1u, 0u, UINT_MAX, false)); + +verify (check_binop (LEFT_SHIFT, UINT_MAX, 1, 0u, UINT_MAX, true)); +verify (check_binop (LEFT_SHIFT, UINT_MAX / 2 + 1, 1, 0u, UINT_MAX, true)); +verify (check_binop (LEFT_SHIFT, UINT_MAX / 2, 1, 0u, UINT_MAX, false)); + +/* INT_<op>_OVERFLOW with mixed types. */ +#define check_sum(a, b, overflow) \ + verify (INT_ADD_OVERFLOW (a, b) == (overflow)); \ + verify (INT_ADD_OVERFLOW (b, a) == (overflow)) +check_sum (-1, LONG_MIN, true); +check_sum (-1, UINT_MAX, false); +check_sum (-1L, INT_MIN, INT_MIN == LONG_MIN); +check_sum (0u, -1, true); +check_sum (0u, 0, false); +check_sum (0u, 1, false); +check_sum (1, LONG_MAX, true); +check_sum (1, UINT_MAX, true); +check_sum (1L, INT_MAX, INT_MAX == LONG_MAX); +check_sum (1u, INT_MAX, INT_MAX == UINT_MAX); +check_sum (1u, INT_MIN, true); + +verify (! INT_SUBTRACT_OVERFLOW (INT_MAX, 1u)); +verify (! INT_SUBTRACT_OVERFLOW (UINT_MAX, 1)); +verify (! INT_SUBTRACT_OVERFLOW (0u, -1)); +verify (INT_SUBTRACT_OVERFLOW (UINT_MAX, -1)); +verify (INT_SUBTRACT_OVERFLOW (INT_MIN, 1u)); +verify (INT_SUBTRACT_OVERFLOW (-1, 0u)); + +#define check_product(a, b, overflow) \ + verify (INT_MULTIPLY_OVERFLOW (a, b) == (overflow)); \ + verify (INT_MULTIPLY_OVERFLOW (b, a) == (overflow)) + +check_product (-1, 1u, true); +check_product (-1, INT_MIN, INT_NEGATE_OVERFLOW (INT_MIN)); +check_product (-1, UINT_MAX, true); +check_product (-12345, LONG_MAX / -12345 - 1, true); +check_product (-12345, LONG_MAX / -12345, false); +check_product (0, -1, false); +check_product (0, 0, false); +check_product (0, 0u, false); +check_product (0, 1, false); +check_product (0, INT_MAX, false); +check_product (0, INT_MIN, false); +check_product (0, UINT_MAX, false); +check_product (0u, -1, false); +check_product (0u, 0, false); +check_product (0u, 0u, false); +check_product (0u, 1, false); +check_product (0u, INT_MAX, false); +check_product (0u, INT_MIN, false); +check_product (0u, UINT_MAX, false); +check_product (1, INT_MAX, false); +check_product (1, INT_MIN, false); +check_product (1, UINT_MAX, false); +check_product (1u, INT_MIN, true); +check_product (1u, INT_MAX, UINT_MAX < INT_MAX); +check_product (INT_MAX, UINT_MAX, true); +check_product (INT_MAX, ULONG_MAX, true); +check_product (INT_MIN, LONG_MAX / INT_MIN - 1, true); +check_product (INT_MIN, LONG_MAX / INT_MIN, false); +check_product (INT_MIN, UINT_MAX, true); +check_product (INT_MIN, ULONG_MAX, true); + +verify (INT_DIVIDE_OVERFLOW (INT_MIN, -1L) + == (TYPE_TWOS_COMPLEMENT (long int) && INT_MIN == LONG_MIN)); +verify (! INT_DIVIDE_OVERFLOW (INT_MIN, UINT_MAX)); +verify (! INT_DIVIDE_OVERFLOW (INTMAX_MIN, UINTMAX_MAX)); +verify (! INT_DIVIDE_OVERFLOW (INTMAX_MIN, UINT_MAX)); +verify (INT_DIVIDE_OVERFLOW (-11, 10u)); +verify (INT_DIVIDE_OVERFLOW (-10, 10u)); +verify (! INT_DIVIDE_OVERFLOW (-9, 10u)); +verify (INT_DIVIDE_OVERFLOW (11u, -10)); +verify (INT_DIVIDE_OVERFLOW (10u, -10)); +verify (! INT_DIVIDE_OVERFLOW (9u, -10)); + +verify (INT_REMAINDER_OVERFLOW (INT_MIN, -1L) + == (TYPE_TWOS_COMPLEMENT (long int) && INT_MIN == LONG_MIN)); +verify (INT_REMAINDER_OVERFLOW (-1, UINT_MAX)); +verify (INT_REMAINDER_OVERFLOW ((intmax_t) -1, UINTMAX_MAX)); +verify (INT_REMAINDER_OVERFLOW (INTMAX_MIN, UINT_MAX) + == (INTMAX_MAX < UINT_MAX + && - (unsigned int) INTMAX_MIN % UINT_MAX != 0)); +verify (INT_REMAINDER_OVERFLOW (INT_MIN, ULONG_MAX) + == (INT_MIN % ULONG_MAX != 1)); +verify (! INT_REMAINDER_OVERFLOW (1u, -1)); +verify (! INT_REMAINDER_OVERFLOW (37*39u, -39)); +verify (INT_REMAINDER_OVERFLOW (37*39u + 1, -39)); +verify (INT_REMAINDER_OVERFLOW (37*39u - 1, -39)); +verify (! INT_REMAINDER_OVERFLOW (LONG_MAX, -INT_MAX)); + int main (void) { - /* Use VERIFY for tests that must be integer constant expressions, - ASSERT otherwise. */ - - /* TYPE_IS_INTEGER. */ - ASSERT (TYPE_IS_INTEGER (bool)); - ASSERT (TYPE_IS_INTEGER (char)); - ASSERT (TYPE_IS_INTEGER (signed char)); - ASSERT (TYPE_IS_INTEGER (unsigned char)); - ASSERT (TYPE_IS_INTEGER (short int)); - ASSERT (TYPE_IS_INTEGER (unsigned short int)); - ASSERT (TYPE_IS_INTEGER (int)); - ASSERT (TYPE_IS_INTEGER (unsigned int)); - ASSERT (TYPE_IS_INTEGER (long int)); - ASSERT (TYPE_IS_INTEGER (unsigned long int)); - ASSERT (TYPE_IS_INTEGER (intmax_t)); - ASSERT (TYPE_IS_INTEGER (uintmax_t)); - ASSERT (! TYPE_IS_INTEGER (float)); - ASSERT (! TYPE_IS_INTEGER (double)); - ASSERT (! TYPE_IS_INTEGER (long double)); - - /* TYPE_SIGNED. */ - /* VERIFY (! TYPE_SIGNED (bool)); // not guaranteed by gnulib substitute */ - VERIFY (TYPE_SIGNED (signed char)); - VERIFY (! TYPE_SIGNED (unsigned char)); - VERIFY (TYPE_SIGNED (short int)); - VERIFY (! TYPE_SIGNED (unsigned short int)); - VERIFY (TYPE_SIGNED (int)); - VERIFY (! TYPE_SIGNED (unsigned int)); - VERIFY (TYPE_SIGNED (long int)); - VERIFY (! TYPE_SIGNED (unsigned long int)); - VERIFY (TYPE_SIGNED (intmax_t)); - VERIFY (! TYPE_SIGNED (uintmax_t)); - ASSERT (TYPE_SIGNED (float)); - ASSERT (TYPE_SIGNED (double)); - ASSERT (TYPE_SIGNED (long double)); - - /* Integer representation. */ - VERIFY (INT_MIN + INT_MAX < 0 - ? (TYPE_TWOS_COMPLEMENT (int) - && ! TYPE_ONES_COMPLEMENT (int) && ! TYPE_SIGNED_MAGNITUDE (int)) - : (! TYPE_TWOS_COMPLEMENT (int) - && (TYPE_ONES_COMPLEMENT (int) || TYPE_SIGNED_MAGNITUDE (int)))); - - /* TYPE_MINIMUM, TYPE_MAXIMUM. */ - VERIFY (TYPE_MINIMUM (char) == CHAR_MIN); - VERIFY (TYPE_MAXIMUM (char) == CHAR_MAX); - VERIFY (TYPE_MINIMUM (unsigned char) == 0); - VERIFY (TYPE_MAXIMUM (unsigned char) == UCHAR_MAX); - VERIFY (TYPE_MINIMUM (signed char) == SCHAR_MIN); - VERIFY (TYPE_MAXIMUM (signed char) == SCHAR_MAX); - VERIFY (TYPE_MINIMUM (short int) == SHRT_MIN); - VERIFY (TYPE_MAXIMUM (short int) == SHRT_MAX); - VERIFY (TYPE_MINIMUM (unsigned short int) == 0); - VERIFY (TYPE_MAXIMUM (unsigned short int) == USHRT_MAX); - VERIFY (TYPE_MINIMUM (int) == INT_MIN); - VERIFY (TYPE_MAXIMUM (int) == INT_MAX); - VERIFY (TYPE_MINIMUM (unsigned int) == 0); - VERIFY (TYPE_MAXIMUM (unsigned int) == UINT_MAX); - VERIFY (TYPE_MINIMUM (long int) == LONG_MIN); - VERIFY (TYPE_MAXIMUM (long int) == LONG_MAX); - VERIFY (TYPE_MINIMUM (unsigned long int) == 0); - VERIFY (TYPE_MAXIMUM (unsigned long int) == ULONG_MAX); - VERIFY (TYPE_MINIMUM (intmax_t) == INTMAX_MIN); - VERIFY (TYPE_MAXIMUM (intmax_t) == INTMAX_MAX); - VERIFY (TYPE_MINIMUM (uintmax_t) == 0); - VERIFY (TYPE_MAXIMUM (uintmax_t) == UINTMAX_MAX); - - /* INT_BITS_STRLEN_BOUND. */ - VERIFY (INT_BITS_STRLEN_BOUND (1) == 1); - VERIFY (INT_BITS_STRLEN_BOUND (2620) == 789); - - /* INT_STRLEN_BOUND, INT_BUFSIZE_BOUND. */ - #ifdef INT32_MAX /* POSIX guarantees int32_t; this ports to non-POSIX. */ - VERIFY (INT_STRLEN_BOUND (int32_t) == sizeof ("-2147483648") - 1); - VERIFY (INT_BUFSIZE_BOUND (int32_t) == sizeof ("-2147483648")); - #endif - #ifdef INT64_MAX - VERIFY (INT_STRLEN_BOUND (int64_t) == sizeof ("-9223372036854775808") - 1); - VERIFY (INT_BUFSIZE_BOUND (int64_t) == sizeof ("-9223372036854775808")); - #endif - - /* All the INT_<op>_RANGE_OVERFLOW tests are equally valid as - INT_<op>_OVERFLOW tests, so define a single macro to do both. */ - #define CHECK_BINOP(op, a, b, min, max, overflow) \ - (INT_##op##_RANGE_OVERFLOW (a, b, min, max) == (overflow) \ - && INT_##op##_OVERFLOW (a, b) == (overflow)) - #define CHECK_UNOP(op, a, min, max, overflow) \ - (INT_##op##_RANGE_OVERFLOW (a, min, max) == (overflow) \ - && INT_##op##_OVERFLOW (a) == (overflow)) - - /* INT_<op>_RANGE_OVERFLOW, INT_<op>_OVERFLOW. */ - VERIFY (INT_ADD_RANGE_OVERFLOW (INT_MAX, 1, INT_MIN, INT_MAX)); - VERIFY (INT_ADD_OVERFLOW (INT_MAX, 1)); - VERIFY (CHECK_BINOP (ADD, INT_MAX, 1, INT_MIN, INT_MAX, true)); - VERIFY (CHECK_BINOP (ADD, INT_MAX, -1, INT_MIN, INT_MAX, false)); - VERIFY (CHECK_BINOP (ADD, INT_MIN, 1, INT_MIN, INT_MAX, false)); - VERIFY (CHECK_BINOP (ADD, INT_MIN, -1, INT_MIN, INT_MAX, true)); - VERIFY (CHECK_BINOP (ADD, UINT_MAX, 1u, 0u, UINT_MAX, true)); - VERIFY (CHECK_BINOP (ADD, 0u, 1u, 0u, UINT_MAX, false)); - - VERIFY (CHECK_BINOP (SUBTRACT, INT_MAX, 1, INT_MIN, INT_MAX, false)); - VERIFY (CHECK_BINOP (SUBTRACT, INT_MAX, -1, INT_MIN, INT_MAX, true)); - VERIFY (CHECK_BINOP (SUBTRACT, INT_MIN, 1, INT_MIN, INT_MAX, true)); - VERIFY (CHECK_BINOP (SUBTRACT, INT_MIN, -1, INT_MIN, INT_MAX, false)); - VERIFY (CHECK_BINOP (SUBTRACT, UINT_MAX, 1u, 0u, UINT_MAX, false)); - VERIFY (CHECK_BINOP (SUBTRACT, 0u, 1u, 0u, UINT_MAX, true)); - - VERIFY (CHECK_UNOP (NEGATE, INT_MIN, INT_MIN, INT_MAX, - TYPE_TWOS_COMPLEMENT (int))); - VERIFY (CHECK_UNOP (NEGATE, 0, INT_MIN, INT_MAX, false)); - VERIFY (CHECK_UNOP (NEGATE, INT_MAX, INT_MIN, INT_MAX, false)); - VERIFY (CHECK_UNOP (NEGATE, 0u, 0u, UINT_MAX, false)); - VERIFY (CHECK_UNOP (NEGATE, 1u, 0u, UINT_MAX, true)); - VERIFY (CHECK_UNOP (NEGATE, UINT_MAX, 0u, UINT_MAX, true)); - - VERIFY (CHECK_BINOP (MULTIPLY, INT_MAX, INT_MAX, INT_MIN, INT_MAX, true)); - VERIFY (CHECK_BINOP (MULTIPLY, INT_MAX, INT_MIN, INT_MIN, INT_MAX, true)); - VERIFY (CHECK_BINOP (MULTIPLY, INT_MIN, INT_MAX, INT_MIN, INT_MAX, true)); - VERIFY (CHECK_BINOP (MULTIPLY, INT_MIN, INT_MIN, INT_MIN, INT_MAX, true)); - VERIFY (CHECK_BINOP (MULTIPLY, -1, INT_MIN, INT_MIN, INT_MAX, - INT_NEGATE_OVERFLOW (INT_MIN))); - VERIFY (CHECK_BINOP (MULTIPLY, LONG_MIN / INT_MAX, (long int) INT_MAX, - LONG_MIN, LONG_MIN, false)); - - VERIFY (CHECK_BINOP (DIVIDE, INT_MIN, -1, INT_MIN, INT_MAX, - INT_NEGATE_OVERFLOW (INT_MIN))); - VERIFY (CHECK_BINOP (DIVIDE, INT_MAX, 1, INT_MIN, INT_MAX, false)); - VERIFY (CHECK_BINOP (DIVIDE, (unsigned int) INT_MIN, - -1u, 0u, UINT_MAX, false)); - - VERIFY (CHECK_BINOP (REMAINDER, INT_MIN, -1, INT_MIN, INT_MAX, - INT_NEGATE_OVERFLOW (INT_MIN))); - VERIFY (CHECK_BINOP (REMAINDER, INT_MAX, 1, INT_MIN, INT_MAX, false)); - VERIFY (CHECK_BINOP (REMAINDER, (unsigned int) INT_MIN, - -1u, 0u, UINT_MAX, false)); - - VERIFY (CHECK_BINOP (LEFT_SHIFT, UINT_MAX, 1, 0u, UINT_MAX, true)); - VERIFY (CHECK_BINOP (LEFT_SHIFT, UINT_MAX / 2 + 1, 1, 0u, UINT_MAX, true)); - VERIFY (CHECK_BINOP (LEFT_SHIFT, UINT_MAX / 2, 1, 0u, UINT_MAX, false)); - - /* INT_<op>_OVERFLOW with mixed types. */ - #define CHECK_SUM(a, b, overflow) \ - VERIFY (INT_ADD_OVERFLOW (a, b) == (overflow)); \ - VERIFY (INT_ADD_OVERFLOW (b, a) == (overflow)) - CHECK_SUM (-1, LONG_MIN, true); - CHECK_SUM (-1, UINT_MAX, false); - CHECK_SUM (-1L, INT_MIN, INT_MIN == LONG_MIN); - CHECK_SUM (0u, -1, true); - CHECK_SUM (0u, 0, false); - CHECK_SUM (0u, 1, false); - CHECK_SUM (1, LONG_MAX, true); - CHECK_SUM (1, UINT_MAX, true); - CHECK_SUM (1L, INT_MAX, INT_MAX == LONG_MAX); - CHECK_SUM (1u, INT_MAX, INT_MAX == UINT_MAX); - CHECK_SUM (1u, INT_MIN, true); - - VERIFY (! INT_SUBTRACT_OVERFLOW (INT_MAX, 1u)); - VERIFY (! INT_SUBTRACT_OVERFLOW (UINT_MAX, 1)); - VERIFY (! INT_SUBTRACT_OVERFLOW (0u, -1)); - VERIFY (INT_SUBTRACT_OVERFLOW (UINT_MAX, -1)); - VERIFY (INT_SUBTRACT_OVERFLOW (INT_MIN, 1u)); - VERIFY (INT_SUBTRACT_OVERFLOW (-1, 0u)); - - #define CHECK_PRODUCT(a, b, overflow) \ - VERIFY (INT_MULTIPLY_OVERFLOW (a, b) == (overflow)); \ - VERIFY (INT_MULTIPLY_OVERFLOW (b, a) == (overflow)) - - CHECK_PRODUCT (-1, 1u, true); - CHECK_PRODUCT (-1, INT_MIN, INT_NEGATE_OVERFLOW (INT_MIN)); - CHECK_PRODUCT (-1, UINT_MAX, true); - CHECK_PRODUCT (-12345, LONG_MAX / -12345 - 1, true); - CHECK_PRODUCT (-12345, LONG_MAX / -12345, false); - CHECK_PRODUCT (0, -1, false); - CHECK_PRODUCT (0, 0, false); - CHECK_PRODUCT (0, 0u, false); - CHECK_PRODUCT (0, 1, false); - CHECK_PRODUCT (0, INT_MAX, false); - CHECK_PRODUCT (0, INT_MIN, false); - CHECK_PRODUCT (0, UINT_MAX, false); - CHECK_PRODUCT (0u, -1, false); - CHECK_PRODUCT (0u, 0, false); - CHECK_PRODUCT (0u, 0u, false); - CHECK_PRODUCT (0u, 1, false); - CHECK_PRODUCT (0u, INT_MAX, false); - CHECK_PRODUCT (0u, INT_MIN, false); - CHECK_PRODUCT (0u, UINT_MAX, false); - CHECK_PRODUCT (1, INT_MAX, false); - CHECK_PRODUCT (1, INT_MIN, false); - CHECK_PRODUCT (1, UINT_MAX, false); - CHECK_PRODUCT (1u, INT_MIN, true); - CHECK_PRODUCT (1u, INT_MAX, UINT_MAX < INT_MAX); - CHECK_PRODUCT (INT_MAX, UINT_MAX, true); - CHECK_PRODUCT (INT_MAX, ULONG_MAX, true); - CHECK_PRODUCT (INT_MIN, LONG_MAX / INT_MIN - 1, true); - CHECK_PRODUCT (INT_MIN, LONG_MAX / INT_MIN, false); - CHECK_PRODUCT (INT_MIN, UINT_MAX, true); - CHECK_PRODUCT (INT_MIN, ULONG_MAX, true); - - VERIFY (INT_DIVIDE_OVERFLOW (INT_MIN, -1L) - == (TYPE_TWOS_COMPLEMENT (long int) && INT_MIN == LONG_MIN)); - VERIFY (! INT_DIVIDE_OVERFLOW (INT_MIN, UINT_MAX)); - VERIFY (! INT_DIVIDE_OVERFLOW (INTMAX_MIN, UINTMAX_MAX)); - VERIFY (! INT_DIVIDE_OVERFLOW (INTMAX_MIN, UINT_MAX)); - VERIFY (INT_DIVIDE_OVERFLOW (-11, 10u)); - VERIFY (INT_DIVIDE_OVERFLOW (-10, 10u)); - VERIFY (! INT_DIVIDE_OVERFLOW (-9, 10u)); - VERIFY (INT_DIVIDE_OVERFLOW (11u, -10)); - VERIFY (INT_DIVIDE_OVERFLOW (10u, -10)); - VERIFY (! INT_DIVIDE_OVERFLOW (9u, -10)); - - VERIFY (INT_REMAINDER_OVERFLOW (INT_MIN, -1L) - == (TYPE_TWOS_COMPLEMENT (long int) && INT_MIN == LONG_MIN)); - VERIFY (INT_REMAINDER_OVERFLOW (-1, UINT_MAX)); - VERIFY (INT_REMAINDER_OVERFLOW ((intmax_t) -1, UINTMAX_MAX)); - VERIFY (INT_REMAINDER_OVERFLOW (INTMAX_MIN, UINT_MAX) - == (INTMAX_MAX < UINT_MAX - && - (unsigned int) INTMAX_MIN % UINT_MAX != 0)); - VERIFY (INT_REMAINDER_OVERFLOW (INT_MIN, ULONG_MAX) - == (INT_MIN % ULONG_MAX != 1)); - VERIFY (! INT_REMAINDER_OVERFLOW (1u, -1)); - VERIFY (! INT_REMAINDER_OVERFLOW (37*39u, -39)); - VERIFY (INT_REMAINDER_OVERFLOW (37*39u + 1, -39)); - VERIFY (INT_REMAINDER_OVERFLOW (37*39u - 1, -39)); - VERIFY (! INT_REMAINDER_OVERFLOW (LONG_MAX, -INT_MAX)); - return 0; } diff --git a/gl/tests/test-lock.c b/gl/tests/test-lock.c deleted file mode 100644 index 04ce0767ff..0000000000 --- a/gl/tests/test-lock.c +++ /dev/null @@ -1,601 +0,0 @@ -/* Test of locking in multithreaded situations. - Copyright (C) 2005, 2008-2011 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 <http://www.gnu.org/licenses/>. */ - -/* Written by Bruno Haible <bruno@clisp.org>, 2005. */ - -#include <config.h> - -#if USE_POSIX_THREADS || USE_SOLARIS_THREADS || USE_PTH_THREADS || USE_WIN32_THREADS - -#if USE_POSIX_THREADS -# define TEST_POSIX_THREADS 1 -#endif -#if USE_SOLARIS_THREADS -# define TEST_SOLARIS_THREADS 1 -#endif -#if USE_PTH_THREADS -# define TEST_PTH_THREADS 1 -#endif -#if USE_WIN32_THREADS -# define TEST_WIN32_THREADS 1 -#endif - -/* 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_RWLOCK 1 -#define DO_TEST_RECURSIVE_LOCK 1 -#define DO_TEST_ONCE 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 - -/* 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 <stdio.h> -#include <stdlib.h> -#include <string.h> - -#if !ENABLE_LOCKING -# undef USE_POSIX_THREADS -# undef USE_SOLARIS_THREADS -# undef USE_PTH_THREADS -# undef USE_WIN32_THREADS -#endif -#include "glthread/lock.h" - -#if !ENABLE_LOCKING -# if TEST_POSIX_THREADS -# define USE_POSIX_THREADS 1 -# endif -# if TEST_SOLARIS_THREADS -# define USE_SOLARIS_THREADS 1 -# endif -# if TEST_PTH_THREADS -# define USE_PTH_THREADS 1 -# endif -# if TEST_WIN32_THREADS -# define USE_WIN32_THREADS 1 -# endif -#endif - -#include "glthread/thread.h" -#include "glthread/yield.h" - -#if ENABLE_DEBUGGING -# define dbgprintf printf -#else -# define dbgprintf if (0) printf -#endif - -#if EXPLICIT_YIELD -# define yield() gl_thread_yield () -#else -# define yield() -#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. */ - -gl_lock_define_initialized(static, my_lock) - -static void * -lock_mutator_thread (void *arg) -{ - int repeat; - - for (repeat = REPEAT_COUNT; repeat > 0; repeat--) - { - int i1, i2, value; - - dbgprintf ("Mutator %p before lock\n", gl_thread_self ()); - gl_lock_lock (my_lock); - dbgprintf ("Mutator %p after lock\n", gl_thread_self ()); - - i1 = random_account (); - i2 = random_account (); - value = ((unsigned int) rand () >> 3) % 10; - account[i1] += value; - account[i2] -= value; - - dbgprintf ("Mutator %p before unlock\n", gl_thread_self ()); - gl_lock_unlock (my_lock); - dbgprintf ("Mutator %p after unlock\n", gl_thread_self ()); - - dbgprintf ("Mutator %p before check lock\n", gl_thread_self ()); - gl_lock_lock (my_lock); - check_accounts (); - gl_lock_unlock (my_lock); - dbgprintf ("Mutator %p after check unlock\n", gl_thread_self ()); - - yield (); - } - - dbgprintf ("Mutator %p dying.\n", gl_thread_self ()); - return NULL; -} - -static volatile int lock_checker_done; - -static void * -lock_checker_thread (void *arg) -{ - while (!lock_checker_done) - { - dbgprintf ("Checker %p before check lock\n", gl_thread_self ()); - gl_lock_lock (my_lock); - check_accounts (); - gl_lock_unlock (my_lock); - dbgprintf ("Checker %p after check unlock\n", gl_thread_self ()); - - yield (); - } - - dbgprintf ("Checker %p dying.\n", gl_thread_self ()); - return NULL; -} - -static void -test_lock (void) -{ - int i; - gl_thread_t checkerthread; - gl_thread_t threads[THREAD_COUNT]; - - /* Initialization. */ - for (i = 0; i < ACCOUNT_COUNT; i++) - account[i] = 1000; - lock_checker_done = 0; - - /* Spawn the threads. */ - checkerthread = gl_thread_create (lock_checker_thread, NULL); - for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (lock_mutator_thread, NULL); - - /* Wait for the threads to terminate. */ - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (threads[i], NULL); - lock_checker_done = 1; - gl_thread_join (checkerthread, NULL); - check_accounts (); -} - - -/* ----------------- Test read-write (non-recursive) locks ----------------- */ - -/* Test read-write locks by having several bank accounts and several threads - which shuffle around money between the accounts and several other threads - that check that all the money is still there. */ - -gl_rwlock_define_initialized(static, my_rwlock) - -static void * -rwlock_mutator_thread (void *arg) -{ - int repeat; - - for (repeat = REPEAT_COUNT; repeat > 0; repeat--) - { - int i1, i2, value; - - dbgprintf ("Mutator %p before wrlock\n", gl_thread_self ()); - gl_rwlock_wrlock (my_rwlock); - dbgprintf ("Mutator %p after wrlock\n", gl_thread_self ()); - - i1 = random_account (); - i2 = random_account (); - value = ((unsigned int) rand () >> 3) % 10; - account[i1] += value; - account[i2] -= value; - - dbgprintf ("Mutator %p before unlock\n", gl_thread_self ()); - gl_rwlock_unlock (my_rwlock); - dbgprintf ("Mutator %p after unlock\n", gl_thread_self ()); - - yield (); - } - - dbgprintf ("Mutator %p dying.\n", gl_thread_self ()); - return NULL; -} - -static volatile int rwlock_checker_done; - -static void * -rwlock_checker_thread (void *arg) -{ - while (!rwlock_checker_done) - { - dbgprintf ("Checker %p before check rdlock\n", gl_thread_self ()); - gl_rwlock_rdlock (my_rwlock); - check_accounts (); - gl_rwlock_unlock (my_rwlock); - dbgprintf ("Checker %p after check unlock\n", gl_thread_self ()); - - yield (); - } - - dbgprintf ("Checker %p dying.\n", gl_thread_self ()); - return NULL; -} - -static void -test_rwlock (void) -{ - int i; - gl_thread_t checkerthreads[THREAD_COUNT]; - gl_thread_t threads[THREAD_COUNT]; - - /* Initialization. */ - for (i = 0; i < ACCOUNT_COUNT; i++) - account[i] = 1000; - rwlock_checker_done = 0; - - /* Spawn the threads. */ - for (i = 0; i < THREAD_COUNT; i++) - checkerthreads[i] = gl_thread_create (rwlock_checker_thread, NULL); - for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (rwlock_mutator_thread, NULL); - - /* Wait for the threads to terminate. */ - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (threads[i], NULL); - rwlock_checker_done = 1; - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (checkerthreads[i], NULL); - 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. */ - -gl_recursive_lock_define_initialized(static, my_reclock) - -static void -recshuffle (void) -{ - int i1, i2, value; - - dbgprintf ("Mutator %p before lock\n", gl_thread_self ()); - gl_recursive_lock_lock (my_reclock); - dbgprintf ("Mutator %p after lock\n", gl_thread_self ()); - - 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", gl_thread_self ()); - gl_recursive_lock_unlock (my_reclock); - dbgprintf ("Mutator %p after unlock\n", gl_thread_self ()); -} - -static void * -reclock_mutator_thread (void *arg) -{ - int repeat; - - for (repeat = REPEAT_COUNT; repeat > 0; repeat--) - { - recshuffle (); - - dbgprintf ("Mutator %p before check lock\n", gl_thread_self ()); - gl_recursive_lock_lock (my_reclock); - check_accounts (); - gl_recursive_lock_unlock (my_reclock); - dbgprintf ("Mutator %p after check unlock\n", gl_thread_self ()); - - yield (); - } - - dbgprintf ("Mutator %p dying.\n", gl_thread_self ()); - return NULL; -} - -static volatile int reclock_checker_done; - -static void * -reclock_checker_thread (void *arg) -{ - while (!reclock_checker_done) - { - dbgprintf ("Checker %p before check lock\n", gl_thread_self ()); - gl_recursive_lock_lock (my_reclock); - check_accounts (); - gl_recursive_lock_unlock (my_reclock); - dbgprintf ("Checker %p after check unlock\n", gl_thread_self ()); - - yield (); - } - - dbgprintf ("Checker %p dying.\n", gl_thread_self ()); - return NULL; -} - -static void -test_recursive_lock (void) -{ - int i; - gl_thread_t checkerthread; - gl_thread_t threads[THREAD_COUNT]; - - /* Initialization. */ - for (i = 0; i < ACCOUNT_COUNT; i++) - account[i] = 1000; - reclock_checker_done = 0; - - /* Spawn the threads. */ - checkerthread = gl_thread_create (reclock_checker_thread, NULL); - for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (reclock_mutator_thread, NULL); - - /* Wait for the threads to terminate. */ - for (i = 0; i < THREAD_COUNT; i++) - gl_thread_join (threads[i], NULL); - reclock_checker_done = 1; - gl_thread_join (checkerthread, NULL); - 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). */ - -gl_once_define(static, fresh_once) -static int ready[THREAD_COUNT]; -static gl_lock_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 gl_once_t once_control; -static int performed; -gl_lock_define_initialized(static, performed_lock) - -static void -once_execute (void) -{ - gl_lock_lock (performed_lock); - performed++; - gl_lock_unlock (performed_lock); -} - -static void * -once_contender_thread (void *arg) -{ - int id = (int) (long) arg; - int repeat; - - for (repeat = 0; repeat <= REPEAT_COUNT; repeat++) - { - /* Tell the main thread that we're ready. */ - gl_lock_lock (ready_lock[id]); - ready[id] = 1; - gl_lock_unlock (ready_lock[id]); - - if (repeat == REPEAT_COUNT) - break; - - dbgprintf ("Contender %p waiting for signal for round %d\n", - gl_thread_self (), 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", - gl_thread_self (), repeat); - - /* Contend for execution. */ - gl_once (once_control, once_execute); - } - - return NULL; -} - -static void -test_once (void) -{ - int i, repeat; - gl_thread_t threads[THREAD_COUNT]; - - /* Initialize all variables. */ - for (i = 0; i < THREAD_COUNT; i++) - { - ready[i] = 0; - gl_lock_init (ready_lock[i]); - } -#if ENABLE_LOCKING - for (i = 0; i < REPEAT_COUNT; i++) - gl_rwlock_init (fire_signal[i]); -#else - fire_signal_state = 0; -#endif - - /* Block all fire_signals. */ - for (i = REPEAT_COUNT-1; i >= 0; i--) - gl_rwlock_wrlock (fire_signal[i]); - - /* Spawn the threads. */ - for (i = 0; i < THREAD_COUNT; i++) - threads[i] = gl_thread_create (once_contender_thread, (void *) (long) i); - - for (repeat = 0; repeat <= REPEAT_COUNT; repeat++) - { - /* Wait until every thread is ready. */ - dbgprintf ("Main thread before synchonizing for round %d\n", repeat); - for (;;) - { - int ready_count = 0; - for (i = 0; i < THREAD_COUNT; i++) - { - gl_lock_lock (ready_lock[i]); - ready_count += ready[i]; - gl_lock_unlock (ready_lock[i]); - } - if (ready_count == THREAD_COUNT) - break; - yield (); - } - dbgprintf ("Main thread after synchonizing 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 (gl_once_t)); - - /* 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++) - { - gl_lock_lock (ready_lock[i]); - ready[i] = 0; - gl_lock_unlock (ready_lock[i]); - } - - /* 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++) - gl_thread_join (threads[i], NULL); -} - - -/* -------------------------------------------------------------------------- */ - -int -main () -{ -#if TEST_PTH_THREADS - if (!pth_init ()) - abort (); -#endif - -#if DO_TEST_LOCK - printf ("Starting test_lock ..."); fflush (stdout); - test_lock (); - printf (" OK\n"); fflush (stdout); -#endif -#if DO_TEST_RWLOCK - printf ("Starting test_rwlock ..."); fflush (stdout); - test_rwlock (); - printf (" OK\n"); fflush (stdout); -#endif -#if DO_TEST_RECURSIVE_LOCK - printf ("Starting test_recursive_lock ..."); fflush (stdout); - test_recursive_lock (); - 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; -} - -#else - -/* No multithreading available. */ - -#include <stdio.h> - -int -main () -{ - fputs ("Skipping test: multithreading not enabled\n", stderr); - return 77; -} - -#endif diff --git a/gl/tests/test-strerror.c b/gl/tests/test-strerror.c index 03637d7850..66dbe823d1 100644 --- a/gl/tests/test-strerror.c +++ b/gl/tests/test-strerror.c @@ -33,43 +33,25 @@ main (void) { char *str; - errno = 0; str = strerror (EACCES); ASSERT (str); ASSERT (*str); - ASSERT (errno == 0); - errno = 0; str = strerror (ETIMEDOUT); ASSERT (str); ASSERT (*str); - ASSERT (errno == 0); - errno = 0; str = strerror (EOVERFLOW); ASSERT (str); ASSERT (*str); - ASSERT (errno == 0); - /* POSIX requires strerror (0) to succeed. Reject use of "Unknown - error", but allow "Success", "No error", or even Solaris' "Error - 0" which are distinct patterns from true out-of-range strings. - http://austingroupbugs.net/view.php?id=382 */ - errno = 0; str = strerror (0); ASSERT (str); ASSERT (*str); - ASSERT (errno == 0); - ASSERT (strstr (str, "nknown") == NULL); - /* POSIX requires strerror to produce a non-NULL result for all - inputs; as an extension, we also guarantee a non-empty reseult. - Reporting EINVAL is optional. */ - errno = 0; str = strerror (-3); ASSERT (str); ASSERT (*str); - ASSERT (errno == 0 || errno == EINVAL); return 0; } diff --git a/gl/tests/test-strerror_r.c b/gl/tests/test-strerror_r.c deleted file mode 100644 index 48287678bd..0000000000 --- a/gl/tests/test-strerror_r.c +++ /dev/null @@ -1,112 +0,0 @@ -/* Test of strerror_r() function. - Copyright (C) 2007-2011 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, 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include <config.h> - -#include <string.h> - -#include "signature.h" -SIGNATURE_CHECK (strerror_r, int, (int, char *, size_t)); - -#include <errno.h> - -#include "macros.h" - -int -main (void) -{ - char buf[100]; - int ret; - - /* Test results with valid errnum and enough room. */ - - errno = 0; - buf[0] = '\0'; - ASSERT (strerror_r (EACCES, buf, sizeof (buf)) == 0); - ASSERT (buf[0] != '\0'); - ASSERT (errno == 0); - - errno = 0; - buf[0] = '\0'; - ASSERT (strerror_r (ETIMEDOUT, buf, sizeof (buf)) == 0); - ASSERT (buf[0] != '\0'); - ASSERT (errno == 0); - - errno = 0; - buf[0] = '\0'; - ASSERT (strerror_r (EOVERFLOW, buf, sizeof (buf)) == 0); - ASSERT (buf[0] != '\0'); - ASSERT (errno == 0); - - /* POSIX requires strerror (0) to succeed. Reject use of "Unknown - error", but allow "Success", "No error", or even Solaris' "Error - 0" which are distinct patterns from true out-of-range strings. - http://austingroupbugs.net/view.php?id=382 */ - errno = 0; - buf[0] = '\0'; - ret = strerror_r (0, buf, sizeof (buf)); - ASSERT (ret == 0); - ASSERT (buf[0]); - ASSERT (errno == 0); - ASSERT (strstr (buf, "nknown") == NULL); - - /* Test results with out-of-range errnum and enough room. */ - - errno = 0; - buf[0] = '^'; - ret = strerror_r (-3, buf, sizeof (buf)); - ASSERT (ret == 0 || ret == EINVAL); - if (ret == 0) - ASSERT (buf[0] != '^'); - ASSERT (errno == 0); - - /* Test results with a too small buffer. */ - - ASSERT (strerror_r (EACCES, buf, sizeof (buf)) == 0); - { - size_t len = strlen (buf); - size_t i; - - for (i = 0; i <= len; i++) - { - strcpy (buf, "BADFACE"); - errno = 0; - ret = strerror_r (EACCES, buf, i); - ASSERT (errno == 0); - if (ret == 0) - { - /* Truncated result. POSIX allows this, and it actually - happens on AIX 6.1 and Cygwin. */ - ASSERT ((strcmp (buf, "BADFACE") == 0) == (i == 0)); - } - else - { - /* Failure. */ - ASSERT (ret == ERANGE); - /* buf is clobbered nevertheless, on FreeBSD and MacOS X. */ - } - } - - strcpy (buf, "BADFACE"); - errno = 0; - ret = strerror_r (EACCES, buf, len + 1); - ASSERT (ret == 0); - ASSERT (errno == 0); - } - - return 0; -} |