aboutsummaryrefslogtreecommitdiff
path: root/gnu/packages
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages')
-rw-r--r--gnu/packages/libunistring.scm8
-rw-r--r--gnu/packages/patches/libunistring-gnulib-multi-core.patch178
2 files changed, 185 insertions, 1 deletions
diff --git a/gnu/packages/libunistring.scm b/gnu/packages/libunistring.scm
index 212bec4b49..df02f68cea 100644
--- a/gnu/packages/libunistring.scm
+++ b/gnu/packages/libunistring.scm
@@ -3,6 +3,7 @@
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
+;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -24,6 +25,7 @@
#:use-module (guix packages)
#:use-module (guix download)
#:use-module (guix build-system gnu)
+ #:use-module (gnu packages)
#:use-module (gnu packages base))
(define-public libunistring
@@ -37,7 +39,11 @@
version ".tar.xz"))
(sha256
(base32
- "15z76qrmrvkc3c6hfq2lzzqysgd21s682f2smycfab5g598n8drf"))))
+ "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"))))
(propagated-inputs (libiconv-if-needed))
(build-system gnu-build-system)
(arguments
diff --git a/gnu/packages/patches/libunistring-gnulib-multi-core.patch b/gnu/packages/patches/libunistring-gnulib-multi-core.patch
new file mode 100644
index 0000000000..709b20c6d2
--- /dev/null
+++ b/gnu/packages/patches/libunistring-gnulib-multi-core.patch
@@ -0,0 +1,178 @@
+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 ();
+ }