Merge branch 'core-updates'
[jackhill/guix/guix.git] / gnu / packages / patches / libunistring-gnulib-multi-core.patch
1 This patch fixes performance problems on multi-core machines
2 as reported at <https://bugs.gnu.org/26441>.
3
4 See commit 480d374e596a0ee3fed168ab42cd84c313ad3c89 in Gnulib
5 by Bruno Haible <bruno@clisp.org>.
6
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
11 @@ -50,6 +50,13 @@
12 Uncomment this to see if the operating system has a fair scheduler. */
13 #define EXPLICIT_YIELD 1
14
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
19 + machine. */
20 +#define USE_VOLATILE 0
21 +
22 /* Whether to print debugging messages. */
23 #define ENABLE_DEBUGGING 0
24
25 @@ -103,6 +110,51 @@
26 # define yield()
27 #endif
28
29 +#if USE_VOLATILE
30 +struct atomic_int {
31 + volatile int value;
32 +};
33 +static void
34 +init_atomic_int (struct atomic_int *ai)
35 +{
36 +}
37 +static int
38 +get_atomic_int_value (struct atomic_int *ai)
39 +{
40 + return ai->value;
41 +}
42 +static void
43 +set_atomic_int_value (struct atomic_int *ai, int new_value)
44 +{
45 + ai->value = new_value;
46 +}
47 +#else
48 +struct atomic_int {
49 + gl_lock_define (, lock)
50 + int value;
51 +};
52 +static void
53 +init_atomic_int (struct atomic_int *ai)
54 +{
55 + gl_lock_init (ai->lock);
56 +}
57 +static int
58 +get_atomic_int_value (struct atomic_int *ai)
59 +{
60 + gl_lock_lock (ai->lock);
61 + int ret = ai->value;
62 + gl_lock_unlock (ai->lock);
63 + return ret;
64 +}
65 +static void
66 +set_atomic_int_value (struct atomic_int *ai, int new_value)
67 +{
68 + gl_lock_lock (ai->lock);
69 + ai->value = new_value;
70 + gl_lock_unlock (ai->lock);
71 +}
72 +#endif
73 +
74 #define ACCOUNT_COUNT 4
75
76 static int account[ACCOUNT_COUNT];
77 @@ -170,12 +222,12 @@ lock_mutator_thread (void *arg)
78 return NULL;
79 }
80
81 -static volatile int lock_checker_done;
82 +static struct atomic_int lock_checker_done;
83
84 static void *
85 lock_checker_thread (void *arg)
86 {
87 - while (!lock_checker_done)
88 + while (get_atomic_int_value (&lock_checker_done) == 0)
89 {
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)
93 /* Initialization. */
94 for (i = 0; i < ACCOUNT_COUNT; i++)
95 account[i] = 1000;
96 - lock_checker_done = 0;
97 + init_atomic_int (&lock_checker_done);
98 + set_atomic_int_value (&lock_checker_done, 0);
99
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);
109 check_accounts ();
110 }
111 @@ -254,12 +307,12 @@ rwlock_mutator_thread (void *arg)
112 return NULL;
113 }
114
115 -static volatile int rwlock_checker_done;
116 +static struct atomic_int rwlock_checker_done;
117
118 static void *
119 rwlock_checker_thread (void *arg)
120 {
121 - while (!rwlock_checker_done)
122 + while (get_atomic_int_value (&rwlock_checker_done) == 0)
123 {
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++)
129 account[i] = 1000;
130 - rwlock_checker_done = 0;
131 + init_atomic_int (&rwlock_checker_done);
132 + set_atomic_int_value (&rwlock_checker_done, 0);
133
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);
144 check_accounts ();
145 @@ -356,12 +410,12 @@ reclock_mutator_thread (void *arg)
146 return NULL;
147 }
148
149 -static volatile int reclock_checker_done;
150 +static struct atomic_int reclock_checker_done;
151
152 static void *
153 reclock_checker_thread (void *arg)
154 {
155 - while (!reclock_checker_done)
156 + while (get_atomic_int_value (&reclock_checker_done) == 0)
157 {
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++)
163 account[i] = 1000;
164 - reclock_checker_done = 0;
165 + init_atomic_int (&reclock_checker_done);
166 + set_atomic_int_value (&reclock_checker_done, 0);
167
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);
177 check_accounts ();
178 }