1 This patch fixes performance problems on multi-core machines
2 as reported at <https://bugs.gnu.org/26441>.
4 See commit 480d374e596a0ee3fed168ab42cd84c313ad3c89 in Gnulib
5 by Bruno Haible <bruno@clisp.org>.
7 diff --git a/tests/test-lock.c b/tests/test-lock.c
8 index cb734b4e6..aa6de2739 100644
9 --- a/tests/test-lock.c
10 +++ b/tests/test-lock.c
12 Uncomment this to see if the operating system has a fair scheduler. */
13 #define EXPLICIT_YIELD 1
15 +/* Whether to use 'volatile' on some variables that communicate information
16 + between threads. If set to 0, a lock is used to protect these variables.
17 + If set to 1, 'volatile' is used; this is theoretically equivalent but can
18 + lead to much slower execution (e.g. 30x slower total run time on a 40-core
20 +#define USE_VOLATILE 0
22 /* Whether to print debugging messages. */
23 #define ENABLE_DEBUGGING 0
34 +init_atomic_int (struct atomic_int *ai)
38 +get_atomic_int_value (struct atomic_int *ai)
43 +set_atomic_int_value (struct atomic_int *ai, int new_value)
45 + ai->value = new_value;
49 + gl_lock_define (, lock)
53 +init_atomic_int (struct atomic_int *ai)
55 + gl_lock_init (ai->lock);
58 +get_atomic_int_value (struct atomic_int *ai)
60 + gl_lock_lock (ai->lock);
61 + int ret = ai->value;
62 + gl_lock_unlock (ai->lock);
66 +set_atomic_int_value (struct atomic_int *ai, int new_value)
68 + gl_lock_lock (ai->lock);
69 + ai->value = new_value;
70 + gl_lock_unlock (ai->lock);
74 #define ACCOUNT_COUNT 4
76 static int account[ACCOUNT_COUNT];
77 @@ -170,12 +222,12 @@ lock_mutator_thread (void *arg)
81 -static volatile int lock_checker_done;
82 +static struct atomic_int lock_checker_done;
85 lock_checker_thread (void *arg)
87 - while (!lock_checker_done)
88 + while (get_atomic_int_value (&lock_checker_done) == 0)
90 dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
91 gl_lock_lock (my_lock);
92 @@ -200,7 +252,8 @@ test_lock (void)
94 for (i = 0; i < ACCOUNT_COUNT; i++)
96 - lock_checker_done = 0;
97 + init_atomic_int (&lock_checker_done);
98 + set_atomic_int_value (&lock_checker_done, 0);
100 /* Spawn the threads. */
101 checkerthread = gl_thread_create (lock_checker_thread, NULL);
102 @@ -210,7 +263,7 @@ test_lock (void)
103 /* Wait for the threads to terminate. */
104 for (i = 0; i < THREAD_COUNT; i++)
105 gl_thread_join (threads[i], NULL);
106 - lock_checker_done = 1;
107 + set_atomic_int_value (&lock_checker_done, 1);
108 gl_thread_join (checkerthread, NULL);
111 @@ -254,12 +307,12 @@ rwlock_mutator_thread (void *arg)
115 -static volatile int rwlock_checker_done;
116 +static struct atomic_int rwlock_checker_done;
119 rwlock_checker_thread (void *arg)
121 - while (!rwlock_checker_done)
122 + while (get_atomic_int_value (&rwlock_checker_done) == 0)
124 dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
125 gl_rwlock_rdlock (my_rwlock);
126 @@ -284,7 +337,8 @@ test_rwlock (void)
127 /* Initialization. */
128 for (i = 0; i < ACCOUNT_COUNT; i++)
130 - rwlock_checker_done = 0;
131 + init_atomic_int (&rwlock_checker_done);
132 + set_atomic_int_value (&rwlock_checker_done, 0);
134 /* Spawn the threads. */
135 for (i = 0; i < THREAD_COUNT; i++)
136 @@ -295,7 +349,7 @@ test_rwlock (void)
137 /* Wait for the threads to terminate. */
138 for (i = 0; i < THREAD_COUNT; i++)
139 gl_thread_join (threads[i], NULL);
140 - rwlock_checker_done = 1;
141 + set_atomic_int_value (&rwlock_checker_done, 1);
142 for (i = 0; i < THREAD_COUNT; i++)
143 gl_thread_join (checkerthreads[i], NULL);
145 @@ -356,12 +410,12 @@ reclock_mutator_thread (void *arg)
149 -static volatile int reclock_checker_done;
150 +static struct atomic_int reclock_checker_done;
153 reclock_checker_thread (void *arg)
155 - while (!reclock_checker_done)
156 + while (get_atomic_int_value (&reclock_checker_done) == 0)
158 dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
159 gl_recursive_lock_lock (my_reclock);
160 @@ -386,7 +440,8 @@ test_recursive_lock (void)
161 /* Initialization. */
162 for (i = 0; i < ACCOUNT_COUNT; i++)
164 - reclock_checker_done = 0;
165 + init_atomic_int (&reclock_checker_done);
166 + set_atomic_int_value (&reclock_checker_done, 0);
168 /* Spawn the threads. */
169 checkerthread = gl_thread_create (reclock_checker_thread, NULL);
170 @@ -396,7 +451,7 @@ test_recursive_lock (void)
171 /* Wait for the threads to terminate. */
172 for (i = 0; i < THREAD_COUNT; i++)
173 gl_thread_join (threads[i], NULL);
174 - reclock_checker_done = 1;
175 + set_atomic_int_value (&reclock_checker_done, 1);
176 gl_thread_join (checkerthread, NULL);