atoll: Assume that the compiler supports 'long long'.
[gnulib.git] / lib / mtx.c
blob6acb8ae44ca92e9bf2d3b0346aac1ce9d2e84e17
1 /* ISO C 11 locking in multithreaded situations.
2 Copyright (C) 2005-2019 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 2, or (at your option)
7 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/>. */
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 void
191 call_once (once_flag *flagp, void (*func) (void))
193 glwthread_once (flagp, func);
196 #else
197 /* Use POSIX threads. */
200 mtx_init (mtx_t *mutex, int type)
202 switch (type)
204 case mtx_plain:
205 case mtx_timed:
206 case mtx_plain | mtx_recursive:
207 case mtx_timed | mtx_recursive:
208 break;
209 default:
210 return thrd_error;
213 if ((type & mtx_recursive) != 0)
215 pthread_mutexattr_t attributes;
216 int err;
218 err = pthread_mutexattr_init (&attributes);
219 if (err != 0)
220 return thrd_error;
221 err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
222 if (err != 0)
224 pthread_mutexattr_destroy (&attributes);
225 return thrd_error;
227 err = pthread_mutex_init (mutex, &attributes);
228 if (err != 0)
230 pthread_mutexattr_destroy (&attributes);
231 return thrd_error;
233 err = pthread_mutexattr_destroy (&attributes);
234 if (err != 0)
235 return thrd_error;
237 else
239 int err = pthread_mutex_init (mutex, NULL);
240 if (err != 0)
241 return thrd_error;
243 return thrd_success;
247 mtx_lock (mtx_t *mutex)
249 int err = pthread_mutex_lock (mutex);
250 return (err == 0 ? thrd_success : thrd_error);
254 mtx_trylock (mtx_t *mutex)
256 int err = pthread_mutex_trylock (mutex);
257 return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error);
261 mtx_timedlock (mtx_t *mutex, const struct timespec *abstime)
263 int err = pthread_mutex_timedlock (mutex, abstime);
264 return (err == 0 ? thrd_success :
265 err == ETIMEDOUT ? thrd_timedout :
266 thrd_error);
270 mtx_unlock (mtx_t *mutex)
272 int err = pthread_mutex_unlock (mutex);
273 return (err == 0 ? thrd_success : thrd_error);
276 void
277 mtx_destroy (mtx_t *mutex)
279 pthread_mutex_destroy (mutex);
282 void
283 call_once (once_flag *flagp, void (*func) (void))
285 pthread_once (flagp, func);
288 #endif