exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / mtx.c
blobd72eebd5d3beda91e26acf709dd6f5fb928d6284
1 /* ISO C 11 locking in multithreaded situations.
2 Copyright (C) 2005-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2005, 2019.
18 Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */
20 #include <config.h>
22 #include <threads.h>
24 #include <errno.h>
26 #if defined _WIN32 && ! defined __CYGWIN__
27 /* Use Windows threads. */
29 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
30 # include <windows.h>
32 # include <stdlib.h>
34 #else
35 /* Use POSIX threads. */
37 # include <pthread.h>
39 #endif
41 #if defined _WIN32 && ! defined __CYGWIN__
42 /* Use Windows threads. */
44 int
45 mtx_init (mtx_t *mutex, int type)
47 switch (type)
49 case mtx_plain:
50 glwthread_mutex_init (&mutex->u.u_mutex);
51 break;
52 case mtx_plain | mtx_recursive:
53 glwthread_recmutex_init (&mutex->u.u_recmutex);
54 break;
55 case mtx_timed:
56 if (glwthread_timedmutex_init (&mutex->u.u_timedmutex) != 0)
57 return thrd_error;
58 break;
59 case mtx_timed | mtx_recursive:
60 if (glwthread_timedrecmutex_init (&mutex->u.u_timedrecmutex) != 0)
61 return thrd_error;
62 break;
63 default:
64 return thrd_error;
66 mutex->type = type;
67 return thrd_success;
70 int
71 mtx_lock (mtx_t *mutex)
73 int err;
75 switch (mutex->type)
77 case mtx_plain:
78 err = glwthread_mutex_lock (&mutex->u.u_mutex);
79 break;
80 case mtx_plain | mtx_recursive:
81 err = glwthread_recmutex_lock (&mutex->u.u_recmutex);
82 break;
83 case mtx_timed:
84 err = glwthread_timedmutex_lock (&mutex->u.u_timedmutex);
85 break;
86 case mtx_timed | mtx_recursive:
87 err = glwthread_timedrecmutex_lock (&mutex->u.u_timedrecmutex);
88 break;
89 default:
90 abort ();
92 return (err == 0 ? thrd_success : thrd_error);
95 int
96 mtx_trylock (mtx_t *mutex)
98 int err;
100 switch (mutex->type)
102 case mtx_plain:
103 err = glwthread_mutex_trylock (&mutex->u.u_mutex);
104 break;
105 case mtx_plain | mtx_recursive:
106 err = glwthread_recmutex_trylock (&mutex->u.u_recmutex);
107 break;
108 case mtx_timed:
109 err = glwthread_timedmutex_trylock (&mutex->u.u_timedmutex);
110 break;
111 case mtx_timed | mtx_recursive:
112 err = glwthread_timedrecmutex_trylock (&mutex->u.u_timedrecmutex);
113 break;
114 default:
115 abort ();
117 return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error);
121 mtx_timedlock (mtx_t *mutex, const struct timespec *abstime)
123 int err;
125 switch (mutex->type)
127 case mtx_plain:
128 case mtx_plain | mtx_recursive:
129 return thrd_error;
130 case mtx_timed:
131 err = glwthread_timedmutex_timedlock (&mutex->u.u_timedmutex, abstime);
132 break;
133 case mtx_timed | mtx_recursive:
134 err =
135 glwthread_timedrecmutex_timedlock (&mutex->u.u_timedrecmutex, abstime);
136 break;
137 default:
138 abort ();
140 return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error);
144 mtx_unlock (mtx_t *mutex)
146 int err;
148 switch (mutex->type)
150 case mtx_plain:
151 err = glwthread_mutex_unlock (&mutex->u.u_mutex);
152 break;
153 case mtx_plain | mtx_recursive:
154 err = glwthread_recmutex_unlock (&mutex->u.u_recmutex);
155 break;
156 case mtx_timed:
157 err = glwthread_timedmutex_unlock (&mutex->u.u_timedmutex);
158 break;
159 case mtx_timed | mtx_recursive:
160 err = glwthread_timedrecmutex_unlock (&mutex->u.u_timedrecmutex);
161 break;
162 default:
163 abort ();
165 return (err == 0 ? thrd_success : thrd_error);
168 void
169 mtx_destroy (mtx_t *mutex)
171 switch (mutex->type)
173 case mtx_plain:
174 glwthread_mutex_destroy (&mutex->u.u_mutex);
175 break;
176 case mtx_plain | mtx_recursive:
177 glwthread_recmutex_destroy (&mutex->u.u_recmutex);
178 break;
179 case mtx_timed:
180 glwthread_timedmutex_destroy (&mutex->u.u_timedmutex);
181 break;
182 case mtx_timed | mtx_recursive:
183 glwthread_timedrecmutex_destroy (&mutex->u.u_timedrecmutex);
184 break;
185 default:
186 abort ();
190 #else
191 /* Use POSIX threads. */
194 mtx_init (mtx_t *mutex, int type)
196 switch (type)
198 case mtx_plain:
199 case mtx_timed:
200 case mtx_plain | mtx_recursive:
201 case mtx_timed | mtx_recursive:
202 break;
203 default:
204 return thrd_error;
207 if ((type & mtx_recursive) != 0)
209 pthread_mutexattr_t attributes;
210 int err;
212 err = pthread_mutexattr_init (&attributes);
213 if (err != 0)
214 return thrd_error;
215 err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
216 if (err != 0)
218 pthread_mutexattr_destroy (&attributes);
219 return thrd_error;
221 err = pthread_mutex_init (mutex, &attributes);
222 if (err != 0)
224 pthread_mutexattr_destroy (&attributes);
225 return thrd_error;
227 err = pthread_mutexattr_destroy (&attributes);
228 if (err != 0)
229 return thrd_error;
231 else
233 int err = pthread_mutex_init (mutex, NULL);
234 if (err != 0)
235 return thrd_error;
237 return thrd_success;
241 mtx_lock (mtx_t *mutex)
243 int err = pthread_mutex_lock (mutex);
244 return (err == 0 ? thrd_success : thrd_error);
248 mtx_trylock (mtx_t *mutex)
250 int err = pthread_mutex_trylock (mutex);
251 return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error);
255 mtx_timedlock (mtx_t *mutex, const struct timespec *abstime)
257 int err = pthread_mutex_timedlock (mutex, abstime);
258 return (err == 0 ? thrd_success :
259 err == ETIMEDOUT ? thrd_timedout :
260 thrd_error);
264 mtx_unlock (mtx_t *mutex)
266 int err = pthread_mutex_unlock (mutex);
267 return (err == 0 ? thrd_success : thrd_error);
270 void
271 mtx_destroy (mtx_t *mutex)
273 pthread_mutex_destroy (mutex);
276 #endif