gnu: Disable gnulib's test-lock test in packages.

* gnu/packages/base.scm (findutils)[source]: Disable test-lock.
* gnu/packages/gettext.scm (gettext-minimal)[source]: Ditto.
* gnu/packages/libidn.scm (libidn)[source]: Ditto.
* gnu/packages/libunistring.scm (libunistring)[source]: Ditto.
* gnu/packages/augeas.scm (augeas)[source]: Ditto.
* gnu/packages/gsasl.scm (gsasl)[source]: Ditto.
* gnu/packages/patches/findutils-gnulib-multi-core.patch,
gnu/packages/patches/gettext-gnulib-multi-core.patch,
gnu/packages/patches/gettext-multi-core.patch,
gnu/packages/patches/libunistring-gnulib-multi-core.patch: Delete patches.
* gnu/local.mk (DIST_PATCH_DATA): Remove them.
This commit is contained in:
Eric Bavier 2017-10-30 11:23:46 -05:00 committed by Eric Bavier
parent a7c7d5ab8b
commit acc2dab7f2
No known key found for this signature in database
GPG key ID: FD73CAC719D32566
11 changed files with 72 additions and 857 deletions

View file

@ -615,7 +615,6 @@ dist_patch_DATA = \
%D%/packages/patches/fcgi-2.4.0-poll.patch \
%D%/packages/patches/file-CVE-2017-1000249.patch \
%D%/packages/patches/findutils-localstatedir.patch \
%D%/packages/patches/findutils-gnulib-multi-core.patch \
%D%/packages/patches/findutils-test-xargs.patch \
%D%/packages/patches/flint-ldconfig.patch \
%D%/packages/patches/fltk-shared-lib-defines.patch \
@ -647,8 +646,6 @@ dist_patch_DATA = \
%D%/packages/patches/gegl-CVE-2012-4433.patch \
%D%/packages/patches/gemma-intel-compat.patch \
%D%/packages/patches/geoclue-config.patch \
%D%/packages/patches/gettext-multi-core.patch \
%D%/packages/patches/gettext-gnulib-multi-core.patch \
%D%/packages/patches/ghc-dont-pass-linker-flags-via-response-files.patch \
%D%/packages/patches/ghostscript-no-header-id.patch \
%D%/packages/patches/ghostscript-no-header-uuid.patch \
@ -811,7 +808,6 @@ dist_patch_DATA = \
%D%/packages/patches/libtirpc-CVE-2017-8779.patch \
%D%/packages/patches/libtorrent-rasterbar-boost-compat.patch \
%D%/packages/patches/libtool-skip-tests2.patch \
%D%/packages/patches/libunistring-gnulib-multi-core.patch \
%D%/packages/patches/libusb-0.1-disable-tests.patch \
%D%/packages/patches/libusb-for-axoloti.patch \
%D%/packages/patches/libvirt-CVE-2017-1000256.patch \

View file

@ -1,6 +1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016, 2017 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2017 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2017 Eric Bavier <bavier@member.fsf.org>
;;;
;;; This file is part of GNU Guix.
;;;
@ -38,7 +39,17 @@ (define-public augeas
version ".tar.gz"))
(sha256
(base32
"1yf93fqwav1zsl8dpyfkf0g11w05mmfckqy6qsjy5zkklnspbkv5"))))
"1yf93fqwav1zsl8dpyfkf0g11w05mmfckqy6qsjy5zkklnspbkv5"))
(modules '((guix build utils)))
(snippet
'(begin
;; The gnulib test-lock test is prone to writer starvation
;; with our glibc@2.25, which prefers readers, so disable it.
;; The gnulib commit b20e8afb0b2 should fix this once
;; incorporated here.
(substitute* "gnulib/tests/Makefile.in"
(("test-lock\\$\\(EXEEXT\\) ") ""))
#t))))
(build-system gnu-build-system)
;; Marked as "required" in augeas.pc
(propagated-inputs

View file

@ -10,6 +10,7 @@
;;; Copyright © 2017 Rene Saavedra <rennes@openmailbox.org>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2017 Eric Bavier <bavier@member.fsf.org>
;;;
;;; This file is part of GNU Guix.
;;;
@ -262,11 +263,17 @@ (define-public findutils
"178nn4dl7wbcw499czikirnkniwnx36argdnqgz4ik9i6zvwkm6y"))
(patches (search-patches
"findutils-localstatedir.patch"
"findutils-test-xargs.patch"
;; test-lock has performance issues on multi-core
;; machines, it hangs or takes a long time to complete.
;; This is a commit from gnulib to fix this issue.
"findutils-gnulib-multi-core.patch"))))
"findutils-test-xargs.patch"))
(modules '((guix build utils)))
(snippet
'(begin
;; The gnulib test-lock test is prone to writer starvation
;; with our glibc@2.25, which prefers readers, so disable it.
;; The gnulib commit b20e8afb0b2 should fix this once
;; incorporated here.
(substitute* "tests/Makefile.in"
(("test-lock\\$\\(EXEEXT\\) ") ""))
#t))))
(build-system gnu-build-system)
(arguments
`(#:configure-flags (list

View file

@ -6,6 +6,7 @@
;;; Copyright © 2016 Alex Kost <alezost@gmail.com>
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2017 Eric Bavier <bavier@member.fsf.org>
;;;
;;; This file is part of GNU Guix.
;;;
@ -47,12 +48,18 @@ (define-public gettext-minimal
(sha256
(base32
"0hsw28f9q9xaggjlsdp2qmbp2rbd1mp0njzan2ld9kiqwkq2m57z"))
;; test-lock has performance issues on multi-core machines,
;; it hangs or takes a long time to complete.
;; There is one commit in gettext and one commit
;; in gettext's embedded gnulib to fix this issue.
(patches (search-patches "gettext-multi-core.patch"
"gettext-gnulib-multi-core.patch"))))
(modules '((guix build utils)))
(snippet
'(begin
;; The gnulib test-lock test is prone to writer starvation
;; with our glibc@2.25, which prefers readers, so disable it.
;; The gnulib commit b20e8afb0b2 should fix this once
;; incorporated here.
(substitute* "gettext-runtime/tests/Makefile.in"
(("TESTS = test-lock\\$\\(EXEEXT\\)") "TESTS ="))
(substitute* "gettext-tools/gnulib-tests/Makefile.in"
(("test-lock\\$\\(EXEEXT\\) ") ""))
#t))))
(build-system gnu-build-system)
(outputs '("out"
"doc")) ;8 MiB of HTML

View file

@ -1,6 +1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2017 Eric Bavier <bavier@member.fsf.org>
;;;
;;; This file is part of GNU Guix.
;;;
@ -81,7 +82,17 @@ (define-public gsasl
(uri (string-append "mirror://gnu/gsasl/gsasl-" version
".tar.gz"))
(sha256 (base32
"1rci64cxvcfr8xcjpqc4inpfq7aw4snnsbf5xz7d30nhvv8n40ii"))))
"1rci64cxvcfr8xcjpqc4inpfq7aw4snnsbf5xz7d30nhvv8n40ii"))
(modules '((guix build utils)))
(snippet
'(begin
;; The gnulib test-lock test is prone to writer starvation
;; with our glibc@2.25, which prefers readers, so disable it.
;; The gnulib commit b20e8afb0b2 should fix this once
;; incorporated here.
(substitute* "tests/Makefile.in"
(("test-lock\\$\\(EXEEXT\\) ") ""))
#t))))
(build-system gnu-build-system)
(inputs `(("libidn" ,libidn)
("libntlm" ,libntlm)

View file

@ -3,6 +3,7 @@
;;; Copyright © 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2017 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2017 Eric Bavier <bavier@member.fsf.org>
;;;
;;; This file is part of GNU Guix.
;;;
@ -38,7 +39,17 @@ (define-public libidn
".tar.gz"))
(sha256
(base32
"068fjg2arlppjqqpzd714n1lf6gxkpac9v5yyvp1qwmv6nvam9s4"))))
"068fjg2arlppjqqpzd714n1lf6gxkpac9v5yyvp1qwmv6nvam9s4"))
(modules '((guix build utils)))
(snippet
'(begin
;; The gnulib test-lock test is prone to writer starvation
;; with our glibc@2.25, which prefers readers, so disable it.
;; The gnulib commit b20e8afb0b2 should fix this once
;; incorporated here.
(substitute* "lib/gltests/Makefile.in"
(("test-lock\\$\\(EXEEXT\\) ") ""))
#t))))
(build-system gnu-build-system)
;; FIXME: No Java and C# libraries are currently built.
(synopsis "Internationalized string processing library")

View file

@ -4,6 +4,7 @@
;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2017 Eric Bavier <bavier@member.fsf.org>
;;;
;;; This file is part of GNU Guix.
;;;
@ -40,10 +41,16 @@ (define-public libunistring
(sha256
(base32
"15z76qrmrvkc3c6hfq2lzzqysgd21s682f2smycfab5g598n8drf"))
;; test-lock has performance issues on multi-core machines,
;; it hangs or takes a long time to complete.
;; This is a commit from gnulib to fix this issue.
(patches (search-patches "libunistring-gnulib-multi-core.patch"))))
(modules '((guix build utils)))
(snippet
'(begin
;; The gnulib test-lock test is prone to writer starvation
;; with our glibc@2.25, which prefers readers, so disable it.
;; The gnulib commit b20e8afb0b2 should fix this once
;; incorporated here.
(substitute* "tests/Makefile.in"
(("test-lock\\$\\(EXEEXT\\) ") ""))
#t))))
(propagated-inputs (libiconv-if-needed))
(build-system gnu-build-system)
(arguments

View file

@ -1,294 +0,0 @@
This patch fixes performance problems on multi-core machines
as reported at <https://bugs.gnu.org/26441>.
See commit 480d374e596a0ee3fed168ab42cd84c313ad3c89 in Gnulib
by Bruno Haible <bruno@clisp.org>.
diff --git a/tests/test-lock.c b/tests/test-lock.c
index a992f64..fb18dee 100644
--- a/tests/test-lock.c
+++ b/tests/test-lock.c
@@ -1,5 +1,5 @@
/* Test of locking in multithreaded situations.
- Copyright (C) 2005, 2008-2015 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2008-2017 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
@@ -50,6 +50,28 @@
Uncomment this to see if the operating system has a fair scheduler. */
#define EXPLICIT_YIELD 1
+/* Whether to use 'volatile' on some variables that communicate information
+ between threads. If set to 0, a semaphore or a lock is used to protect
+ these variables. If set to 1, 'volatile' is used; this is theoretically
+ equivalent but can lead to much slower execution (e.g. 30x slower total
+ run time on a 40-core machine), because 'volatile' does not imply any
+ synchronization/communication between different CPUs. */
+#define USE_VOLATILE 0
+
+#if USE_POSIX_THREADS && HAVE_SEMAPHORE_H
+/* Whether to use a semaphore to communicate information between threads.
+ If set to 0, a lock is used. If set to 1, a semaphore is used.
+ Uncomment this to reduce the dependencies of this test. */
+# define USE_SEMAPHORE 1
+/* Mac OS X provides only named semaphores (sem_open); its facility for
+ unnamed semaphores (sem_init) does not work. */
+# if defined __APPLE__ && defined __MACH__
+# define USE_NAMED_SEMAPHORE 1
+# else
+# define USE_UNNAMED_SEMAPHORE 1
+# endif
+#endif
+
/* Whether to print debugging messages. */
#define ENABLE_DEBUGGING 0
@@ -90,6 +112,12 @@
#include "glthread/thread.h"
#include "glthread/yield.h"
+#if USE_SEMAPHORE
+# include <errno.h>
+# include <fcntl.h>
+# include <semaphore.h>
+# include <unistd.h>
+#endif
#if ENABLE_DEBUGGING
# define dbgprintf printf
@@ -103,6 +131,132 @@
# define yield()
#endif
+#if USE_VOLATILE
+struct atomic_int {
+ volatile int value;
+};
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+}
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ return ai->value;
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ ai->value = new_value;
+}
+#elif USE_SEMAPHORE
+/* This atomic_int implementation can only support the values 0 and 1.
+ It is initially 0 and can be set to 1 only once. */
+# if USE_UNNAMED_SEMAPHORE
+struct atomic_int {
+ sem_t semaphore;
+};
+#define atomic_int_semaphore(ai) (&(ai)->semaphore)
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+ sem_init (&ai->semaphore, 0, 0);
+}
+# endif
+# if USE_NAMED_SEMAPHORE
+struct atomic_int {
+ sem_t *semaphore;
+};
+#define atomic_int_semaphore(ai) ((ai)->semaphore)
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+ sem_t *s;
+ unsigned int count;
+ for (count = 0; ; count++)
+ {
+ char name[80];
+ /* Use getpid() in the name, so that different processes running at the
+ same time will not interfere. Use ai in the name, so that different
+ atomic_int in the same process will not interfere. Use a count in
+ the name, so that even in the (unlikely) case that a semaphore with
+ the specified name already exists, we can try a different name. */
+ sprintf (name, "test-lock-%lu-%p-%u",
+ (unsigned long) getpid (), ai, count);
+ s = sem_open (name, O_CREAT | O_EXCL, 0600, 0);
+ if (s == SEM_FAILED)
+ {
+ if (errno == EEXIST)
+ /* Retry with a different name. */
+ continue;
+ else
+ {
+ perror ("sem_open failed");
+ abort ();
+ }
+ }
+ else
+ {
+ /* Try not to leave a semaphore hanging around on the file system
+ eternally, if we can avoid it. */
+ sem_unlink (name);
+ break;
+ }
+ }
+ ai->semaphore = s;
+}
+# endif
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ if (sem_trywait (atomic_int_semaphore (ai)) == 0)
+ {
+ if (sem_post (atomic_int_semaphore (ai)))
+ abort ();
+ return 1;
+ }
+ else if (errno == EAGAIN)
+ return 0;
+ else
+ abort ();
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ if (new_value == 0)
+ /* It's already initialized with 0. */
+ return;
+ /* To set the value 1: */
+ if (sem_post (atomic_int_semaphore (ai)))
+ abort ();
+}
+#else
+struct atomic_int {
+ gl_lock_define (, lock)
+ int value;
+};
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+ gl_lock_init (ai->lock);
+}
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ gl_lock_lock (ai->lock);
+ int ret = ai->value;
+ gl_lock_unlock (ai->lock);
+ return ret;
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ gl_lock_lock (ai->lock);
+ ai->value = new_value;
+ gl_lock_unlock (ai->lock);
+}
+#endif
+
#define ACCOUNT_COUNT 4
static int account[ACCOUNT_COUNT];
@@ -170,12 +324,12 @@ lock_mutator_thread (void *arg)
return NULL;
}
-static volatile int lock_checker_done;
+static struct atomic_int lock_checker_done;
static void *
lock_checker_thread (void *arg)
{
- while (!lock_checker_done)
+ while (get_atomic_int_value (&lock_checker_done) == 0)
{
dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
gl_lock_lock (my_lock);
@@ -200,7 +354,8 @@ test_lock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- lock_checker_done = 0;
+ init_atomic_int (&lock_checker_done);
+ set_atomic_int_value (&lock_checker_done, 0);
/* Spawn the threads. */
checkerthread = gl_thread_create (lock_checker_thread, NULL);
@@ -210,7 +365,7 @@ test_lock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- lock_checker_done = 1;
+ set_atomic_int_value (&lock_checker_done, 1);
gl_thread_join (checkerthread, NULL);
check_accounts ();
}
@@ -254,12 +409,12 @@ rwlock_mutator_thread (void *arg)
return NULL;
}
-static volatile int rwlock_checker_done;
+static struct atomic_int rwlock_checker_done;
static void *
rwlock_checker_thread (void *arg)
{
- while (!rwlock_checker_done)
+ while (get_atomic_int_value (&rwlock_checker_done) == 0)
{
dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
gl_rwlock_rdlock (my_rwlock);
@@ -284,7 +439,8 @@ test_rwlock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- rwlock_checker_done = 0;
+ init_atomic_int (&rwlock_checker_done);
+ set_atomic_int_value (&rwlock_checker_done, 0);
/* Spawn the threads. */
for (i = 0; i < THREAD_COUNT; i++)
@@ -295,7 +451,7 @@ test_rwlock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- rwlock_checker_done = 1;
+ set_atomic_int_value (&rwlock_checker_done, 1);
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (checkerthreads[i], NULL);
check_accounts ();
@@ -356,12 +512,12 @@ reclock_mutator_thread (void *arg)
return NULL;
}
-static volatile int reclock_checker_done;
+static struct atomic_int reclock_checker_done;
static void *
reclock_checker_thread (void *arg)
{
- while (!reclock_checker_done)
+ while (get_atomic_int_value (&reclock_checker_done) == 0)
{
dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
gl_recursive_lock_lock (my_reclock);
@@ -386,7 +542,8 @@ test_recursive_lock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- reclock_checker_done = 0;
+ init_atomic_int (&reclock_checker_done);
+ set_atomic_int_value (&reclock_checker_done, 0);
/* Spawn the threads. */
checkerthread = gl_thread_create (reclock_checker_thread, NULL);
@@ -396,7 +553,7 @@ test_recursive_lock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- reclock_checker_done = 1;
+ set_atomic_int_value (&reclock_checker_done, 1);
gl_thread_join (checkerthread, NULL);
check_accounts ();
}

View file

@ -1,178 +0,0 @@
This patch fixes performance problems on multi-core machines
as reported at <https://bugs.gnu.org/26441>.
See commit 480d374e596a0ee3fed168ab42cd84c313ad3c89 in Gnulib
by Bruno Haible <bruno@clisp.org>.
diff --git a/gettext-tools/gnulib-tests/test-lock.c b/gettext-tools/gnulib-tests/test-lock.c
index cb734b4e6..aa6de2739 100644
--- a/gettext-tools/gnulib-tests/test-lock.c
+++ b/gettext-tools/gnulib-tests/test-lock.c
@@ -50,6 +50,13 @@
Uncomment this to see if the operating system has a fair scheduler. */
#define EXPLICIT_YIELD 1
+/* Whether to use 'volatile' on some variables that communicate information
+ between threads. If set to 0, a lock is used to protect these variables.
+ If set to 1, 'volatile' is used; this is theoretically equivalent but can
+ lead to much slower execution (e.g. 30x slower total run time on a 40-core
+ machine. */
+#define USE_VOLATILE 0
+
/* Whether to print debugging messages. */
#define ENABLE_DEBUGGING 0
@@ -103,6 +110,51 @@
# define yield()
#endif
+#if USE_VOLATILE
+struct atomic_int {
+ volatile int value;
+};
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+}
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ return ai->value;
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ ai->value = new_value;
+}
+#else
+struct atomic_int {
+ gl_lock_define (, lock)
+ int value;
+};
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+ gl_lock_init (ai->lock);
+}
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ gl_lock_lock (ai->lock);
+ int ret = ai->value;
+ gl_lock_unlock (ai->lock);
+ return ret;
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ gl_lock_lock (ai->lock);
+ ai->value = new_value;
+ gl_lock_unlock (ai->lock);
+}
+#endif
+
#define ACCOUNT_COUNT 4
static int account[ACCOUNT_COUNT];
@@ -170,12 +222,12 @@ lock_mutator_thread (void *arg)
return NULL;
}
-static volatile int lock_checker_done;
+static struct atomic_int lock_checker_done;
static void *
lock_checker_thread (void *arg)
{
- while (!lock_checker_done)
+ while (get_atomic_int_value (&lock_checker_done) == 0)
{
dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
gl_lock_lock (my_lock);
@@ -200,7 +252,8 @@ test_lock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- lock_checker_done = 0;
+ init_atomic_int (&lock_checker_done);
+ set_atomic_int_value (&lock_checker_done, 0);
/* Spawn the threads. */
checkerthread = gl_thread_create (lock_checker_thread, NULL);
@@ -210,7 +263,7 @@ test_lock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- lock_checker_done = 1;
+ set_atomic_int_value (&lock_checker_done, 1);
gl_thread_join (checkerthread, NULL);
check_accounts ();
}
@@ -254,12 +307,12 @@ rwlock_mutator_thread (void *arg)
return NULL;
}
-static volatile int rwlock_checker_done;
+static struct atomic_int rwlock_checker_done;
static void *
rwlock_checker_thread (void *arg)
{
- while (!rwlock_checker_done)
+ while (get_atomic_int_value (&rwlock_checker_done) == 0)
{
dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
gl_rwlock_rdlock (my_rwlock);
@@ -284,7 +337,8 @@ test_rwlock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- rwlock_checker_done = 0;
+ init_atomic_int (&rwlock_checker_done);
+ set_atomic_int_value (&rwlock_checker_done, 0);
/* Spawn the threads. */
for (i = 0; i < THREAD_COUNT; i++)
@@ -295,7 +349,7 @@ test_rwlock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- rwlock_checker_done = 1;
+ set_atomic_int_value (&rwlock_checker_done, 1);
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (checkerthreads[i], NULL);
check_accounts ();
@@ -356,12 +410,12 @@ reclock_mutator_thread (void *arg)
return NULL;
}
-static volatile int reclock_checker_done;
+static struct atomic_int reclock_checker_done;
static void *
reclock_checker_thread (void *arg)
{
- while (!reclock_checker_done)
+ while (get_atomic_int_value (&reclock_checker_done) == 0)
{
dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
gl_recursive_lock_lock (my_reclock);
@@ -386,7 +440,8 @@ test_recursive_lock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- reclock_checker_done = 0;
+ init_atomic_int (&reclock_checker_done);
+ set_atomic_int_value (&reclock_checker_done, 0);
/* Spawn the threads. */
checkerthread = gl_thread_create (reclock_checker_thread, NULL);
@@ -396,7 +451,7 @@ test_recursive_lock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- reclock_checker_done = 1;
+ set_atomic_int_value (&reclock_checker_done, 1);
gl_thread_join (checkerthread, NULL);
check_accounts ();
}

View file

@ -1,185 +0,0 @@
This patch fixes performance problems on multi-core machines
as reported at <https://bugs.gnu.org/26441>.
See commit 1afbcb06fded2a427b761dd1615b1e48e1e853cc in Gettext
by Bruno Haible <bruno@clisp.org>.
diff --git a/gettext-runtime/tests/test-lock.c b/gettext-runtime/tests/test-lock.c
index d279d1d60..51cec3d6b 100644
--- a/gettext-runtime/tests/test-lock.c
+++ b/gettext-runtime/tests/test-lock.c
@@ -1,5 +1,5 @@
/* Test of locking in multithreaded situations.
- Copyright (C) 2005, 2008-2016 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2008-2017 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -50,6 +50,13 @@
Uncomment this to see if the operating system has a fair scheduler. */
#define EXPLICIT_YIELD 1
+/* Whether to use 'volatile' on some variables that communicate information
+ between threads. If set to 0, a lock is used to protect these variables.
+ If set to 1, 'volatile' is used; this is theoretically equivalent but can
+ lead to much slower execution (e.g. 30x slower total run time on a 40-core
+ machine. */
+#define USE_VOLATILE 0
+
/* Whether to print debugging messages. */
#define ENABLE_DEBUGGING 0
@@ -214,6 +221,51 @@ static inline void * gl_thread_self_pointer (void)
# define yield()
#endif
+#if USE_VOLATILE
+struct atomic_int {
+ volatile int value;
+};
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+}
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ return ai->value;
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ ai->value = new_value;
+}
+#else
+struct atomic_int {
+ gl_lock_define (, lock)
+ int value;
+};
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+ gl_lock_init (ai->lock);
+}
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ gl_lock_lock (ai->lock);
+ int ret = ai->value;
+ gl_lock_unlock (ai->lock);
+ return ret;
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ gl_lock_lock (ai->lock);
+ ai->value = new_value;
+ gl_lock_unlock (ai->lock);
+}
+#endif
+
#define ACCOUNT_COUNT 4
static int account[ACCOUNT_COUNT];
@@ -281,12 +333,12 @@ lock_mutator_thread (void *arg)
return NULL;
}
-static volatile int lock_checker_done;
+static struct atomic_int lock_checker_done;
static void *
lock_checker_thread (void *arg)
{
- while (!lock_checker_done)
+ while (get_atomic_int_value (&lock_checker_done) == 0)
{
dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
gl_lock_lock (my_lock);
@@ -311,7 +363,8 @@ test_lock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- lock_checker_done = 0;
+ init_atomic_int (&lock_checker_done);
+ set_atomic_int_value (&lock_checker_done, 0);
/* Spawn the threads. */
checkerthread = gl_thread_create (lock_checker_thread, NULL);
@@ -321,7 +374,7 @@ test_lock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- lock_checker_done = 1;
+ set_atomic_int_value (&lock_checker_done, 1);
gl_thread_join (checkerthread, NULL);
check_accounts ();
}
@@ -365,12 +418,12 @@ rwlock_mutator_thread (void *arg)
return NULL;
}
-static volatile int rwlock_checker_done;
+static struct atomic_int rwlock_checker_done;
static void *
rwlock_checker_thread (void *arg)
{
- while (!rwlock_checker_done)
+ while (get_atomic_int_value (&rwlock_checker_done) == 0)
{
dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
gl_rwlock_rdlock (my_rwlock);
@@ -395,7 +448,8 @@ test_rwlock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- rwlock_checker_done = 0;
+ init_atomic_int (&rwlock_checker_done);
+ set_atomic_int_value (&rwlock_checker_done, 0);
/* Spawn the threads. */
for (i = 0; i < THREAD_COUNT; i++)
@@ -406,7 +460,7 @@ test_rwlock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- rwlock_checker_done = 1;
+ set_atomic_int_value (&rwlock_checker_done, 1);
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (checkerthreads[i], NULL);
check_accounts ();
@@ -467,12 +521,12 @@ reclock_mutator_thread (void *arg)
return NULL;
}
-static volatile int reclock_checker_done;
+static struct atomic_int reclock_checker_done;
static void *
reclock_checker_thread (void *arg)
{
- while (!reclock_checker_done)
+ while (get_atomic_int_value (&reclock_checker_done) == 0)
{
dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
gl_recursive_lock_lock (my_reclock);
@@ -497,7 +551,8 @@ test_recursive_lock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- reclock_checker_done = 0;
+ init_atomic_int (&reclock_checker_done);
+ set_atomic_int_value (&reclock_checker_done, 0);
/* Spawn the threads. */
checkerthread = gl_thread_create (reclock_checker_thread, NULL);
@@ -507,7 +562,7 @@ test_recursive_lock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- reclock_checker_done = 1;
+ set_atomic_int_value (&reclock_checker_done, 1);
gl_thread_join (checkerthread, NULL);
check_accounts ();
}

View file

@ -1,178 +0,0 @@
This patch fixes performance problems on multi-core machines
as reported at <https://bugs.gnu.org/26441>.
See commit 480d374e596a0ee3fed168ab42cd84c313ad3c89 in Gnulib
by Bruno Haible <bruno@clisp.org>.
diff --git a/tests/test-lock.c b/tests/test-lock.c
index cb734b4e6..aa6de2739 100644
--- a/tests/test-lock.c
+++ b/tests/test-lock.c
@@ -50,6 +50,13 @@
Uncomment this to see if the operating system has a fair scheduler. */
#define EXPLICIT_YIELD 1
+/* Whether to use 'volatile' on some variables that communicate information
+ between threads. If set to 0, a lock is used to protect these variables.
+ If set to 1, 'volatile' is used; this is theoretically equivalent but can
+ lead to much slower execution (e.g. 30x slower total run time on a 40-core
+ machine. */
+#define USE_VOLATILE 0
+
/* Whether to print debugging messages. */
#define ENABLE_DEBUGGING 0
@@ -103,6 +110,51 @@
# define yield()
#endif
+#if USE_VOLATILE
+struct atomic_int {
+ volatile int value;
+};
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+}
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ return ai->value;
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ ai->value = new_value;
+}
+#else
+struct atomic_int {
+ gl_lock_define (, lock)
+ int value;
+};
+static void
+init_atomic_int (struct atomic_int *ai)
+{
+ gl_lock_init (ai->lock);
+}
+static int
+get_atomic_int_value (struct atomic_int *ai)
+{
+ gl_lock_lock (ai->lock);
+ int ret = ai->value;
+ gl_lock_unlock (ai->lock);
+ return ret;
+}
+static void
+set_atomic_int_value (struct atomic_int *ai, int new_value)
+{
+ gl_lock_lock (ai->lock);
+ ai->value = new_value;
+ gl_lock_unlock (ai->lock);
+}
+#endif
+
#define ACCOUNT_COUNT 4
static int account[ACCOUNT_COUNT];
@@ -170,12 +222,12 @@ lock_mutator_thread (void *arg)
return NULL;
}
-static volatile int lock_checker_done;
+static struct atomic_int lock_checker_done;
static void *
lock_checker_thread (void *arg)
{
- while (!lock_checker_done)
+ while (get_atomic_int_value (&lock_checker_done) == 0)
{
dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
gl_lock_lock (my_lock);
@@ -200,7 +252,8 @@ test_lock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- lock_checker_done = 0;
+ init_atomic_int (&lock_checker_done);
+ set_atomic_int_value (&lock_checker_done, 0);
/* Spawn the threads. */
checkerthread = gl_thread_create (lock_checker_thread, NULL);
@@ -210,7 +263,7 @@ test_lock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- lock_checker_done = 1;
+ set_atomic_int_value (&lock_checker_done, 1);
gl_thread_join (checkerthread, NULL);
check_accounts ();
}
@@ -254,12 +307,12 @@ rwlock_mutator_thread (void *arg)
return NULL;
}
-static volatile int rwlock_checker_done;
+static struct atomic_int rwlock_checker_done;
static void *
rwlock_checker_thread (void *arg)
{
- while (!rwlock_checker_done)
+ while (get_atomic_int_value (&rwlock_checker_done) == 0)
{
dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
gl_rwlock_rdlock (my_rwlock);
@@ -284,7 +337,8 @@ test_rwlock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- rwlock_checker_done = 0;
+ init_atomic_int (&rwlock_checker_done);
+ set_atomic_int_value (&rwlock_checker_done, 0);
/* Spawn the threads. */
for (i = 0; i < THREAD_COUNT; i++)
@@ -295,7 +349,7 @@ test_rwlock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- rwlock_checker_done = 1;
+ set_atomic_int_value (&rwlock_checker_done, 1);
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (checkerthreads[i], NULL);
check_accounts ();
@@ -356,12 +410,12 @@ reclock_mutator_thread (void *arg)
return NULL;
}
-static volatile int reclock_checker_done;
+static struct atomic_int reclock_checker_done;
static void *
reclock_checker_thread (void *arg)
{
- while (!reclock_checker_done)
+ while (get_atomic_int_value (&reclock_checker_done) == 0)
{
dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
gl_recursive_lock_lock (my_reclock);
@@ -386,7 +440,8 @@ test_recursive_lock (void)
/* Initialization. */
for (i = 0; i < ACCOUNT_COUNT; i++)
account[i] = 1000;
- reclock_checker_done = 0;
+ init_atomic_int (&reclock_checker_done);
+ set_atomic_int_value (&reclock_checker_done, 0);
/* Spawn the threads. */
checkerthread = gl_thread_create (reclock_checker_thread, NULL);
@@ -396,7 +451,7 @@ test_recursive_lock (void)
/* Wait for the threads to terminate. */
for (i = 0; i < THREAD_COUNT; i++)
gl_thread_join (threads[i], NULL);
- reclock_checker_done = 1;
+ set_atomic_int_value (&reclock_checker_done, 1);
gl_thread_join (checkerthread, NULL);
check_accounts ();
}