1 /* Atomic integers. Useful for testing multithreaded locking primitives.
2 Copyright (C) 2005, 2008-2021 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Whether to use 'volatile' on some variables that communicate information
19 between threads. If set to 0, a semaphore or a lock is used to protect
20 these variables. If set to 1, 'volatile' is used; this is theoretically
21 equivalent but can lead to much slower execution (e.g. 30x slower total
22 run time on a 40-core machine), because 'volatile' does not imply any
23 synchronization/communication between different CPUs. */
24 #define USE_VOLATILE 0
26 #if USE_POSIX_THREADS && HAVE_SEMAPHORE_H
27 /* Whether to use a semaphore to communicate information between threads.
28 If set to 0, a lock is used. If set to 1, a semaphore is used.
29 Uncomment this to reduce the dependencies of this test. */
30 # define USE_SEMAPHORE 1
31 /* Mac OS X provides only named semaphores (sem_open); its facility for
32 unnamed semaphores (sem_init) does not work. */
33 # if defined __APPLE__ && defined __MACH__
34 # define USE_NAMED_SEMAPHORE 1
36 # define USE_UNNAMED_SEMAPHORE 1
44 # include <semaphore.h>
54 init_atomic_int (struct atomic_int *ai)
58 get_atomic_int_value (struct atomic_int *ai)
63 set_atomic_int_value (struct atomic_int *ai, int new_value)
65 ai->value = new_value;
68 /* This atomic_int implementation can only support the values 0 and 1.
69 It is initially 0 and can be set to 1 only once. */
70 # if USE_UNNAMED_SEMAPHORE
74 #define atomic_int_semaphore(ai) (&(ai)->semaphore)
76 init_atomic_int (struct atomic_int *ai)
78 sem_init (&ai->semaphore, 0, 0);
81 # if USE_NAMED_SEMAPHORE
85 #define atomic_int_semaphore(ai) ((ai)->semaphore)
87 init_atomic_int (struct atomic_int *ai)
91 for (count = 0; ; count++)
94 /* Use getpid() in the name, so that different processes running at the
95 same time will not interfere. Use ai in the name, so that different
96 atomic_int in the same process will not interfere. Use a count in
97 the name, so that even in the (unlikely) case that a semaphore with
98 the specified name already exists, we can try a different name. */
99 sprintf (name, "test-lock-%lu-%p-%u",
100 (unsigned long) getpid (), ai, count);
101 s = sem_open (name, O_CREAT | O_EXCL, 0600, 0);
105 /* Retry with a different name. */
109 perror ("sem_open failed");
115 /* Try not to leave a semaphore hanging around on the file system
116 eternally, if we can avoid it. */
125 get_atomic_int_value (struct atomic_int *ai)
127 if (sem_trywait (atomic_int_semaphore (ai)) == 0)
129 if (sem_post (atomic_int_semaphore (ai)))
133 else if (errno == EAGAIN)
139 set_atomic_int_value (struct atomic_int *ai, int new_value)
142 /* It's already initialized with 0. */
144 /* To set the value 1: */
145 if (sem_post (atomic_int_semaphore (ai)))
150 gl_lock_define (, lock)
154 init_atomic_int (struct atomic_int *ai)
156 gl_lock_init (ai->lock);
159 get_atomic_int_value (struct atomic_int *ai)
161 gl_lock_lock (ai->lock);
163 gl_lock_unlock (ai->lock);
167 set_atomic_int_value (struct atomic_int *ai, int new_value)
169 gl_lock_lock (ai->lock);
170 ai->value = new_value;
171 gl_lock_unlock (ai->lock);