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. */
26 #if defined _WIN32 && ! defined __CYGWIN__
27 /* Use Windows threads. */
29 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
35 /* Use POSIX threads. */
41 #if defined _WIN32 && ! defined __CYGWIN__
42 /* Use Windows threads. */
45 mtx_init (mtx_t
*mutex
, int type
)
50 glwthread_mutex_init (&mutex
->u
.u_mutex
);
52 case mtx_plain
| mtx_recursive
:
53 glwthread_recmutex_init (&mutex
->u
.u_recmutex
);
56 if (glwthread_timedmutex_init (&mutex
->u
.u_timedmutex
) != 0)
59 case mtx_timed
| mtx_recursive
:
60 if (glwthread_timedrecmutex_init (&mutex
->u
.u_timedrecmutex
) != 0)
71 mtx_lock (mtx_t
*mutex
)
78 err
= glwthread_mutex_lock (&mutex
->u
.u_mutex
);
80 case mtx_plain
| mtx_recursive
:
81 err
= glwthread_recmutex_lock (&mutex
->u
.u_recmutex
);
84 err
= glwthread_timedmutex_lock (&mutex
->u
.u_timedmutex
);
86 case mtx_timed
| mtx_recursive
:
87 err
= glwthread_timedrecmutex_lock (&mutex
->u
.u_timedrecmutex
);
92 return (err
== 0 ? thrd_success
: thrd_error
);
96 mtx_trylock (mtx_t
*mutex
)
103 err
= glwthread_mutex_trylock (&mutex
->u
.u_mutex
);
105 case mtx_plain
| mtx_recursive
:
106 err
= glwthread_recmutex_trylock (&mutex
->u
.u_recmutex
);
109 err
= glwthread_timedmutex_trylock (&mutex
->u
.u_timedmutex
);
111 case mtx_timed
| mtx_recursive
:
112 err
= glwthread_timedrecmutex_trylock (&mutex
->u
.u_timedrecmutex
);
117 return (err
== 0 ? thrd_success
: err
== EBUSY
? thrd_busy
: thrd_error
);
121 mtx_timedlock (mtx_t
*mutex
, const struct timespec
*abstime
)
128 case mtx_plain
| mtx_recursive
:
131 err
= glwthread_timedmutex_timedlock (&mutex
->u
.u_timedmutex
, abstime
);
133 case mtx_timed
| mtx_recursive
:
135 glwthread_timedrecmutex_timedlock (&mutex
->u
.u_timedrecmutex
, abstime
);
140 return (err
== 0 ? thrd_success
: err
== EBUSY
? thrd_busy
: thrd_error
);
144 mtx_unlock (mtx_t
*mutex
)
151 err
= glwthread_mutex_unlock (&mutex
->u
.u_mutex
);
153 case mtx_plain
| mtx_recursive
:
154 err
= glwthread_recmutex_unlock (&mutex
->u
.u_recmutex
);
157 err
= glwthread_timedmutex_unlock (&mutex
->u
.u_timedmutex
);
159 case mtx_timed
| mtx_recursive
:
160 err
= glwthread_timedrecmutex_unlock (&mutex
->u
.u_timedrecmutex
);
165 return (err
== 0 ? thrd_success
: thrd_error
);
169 mtx_destroy (mtx_t
*mutex
)
174 glwthread_mutex_destroy (&mutex
->u
.u_mutex
);
176 case mtx_plain
| mtx_recursive
:
177 glwthread_recmutex_destroy (&mutex
->u
.u_recmutex
);
180 glwthread_timedmutex_destroy (&mutex
->u
.u_timedmutex
);
182 case mtx_timed
| mtx_recursive
:
183 glwthread_timedrecmutex_destroy (&mutex
->u
.u_timedrecmutex
);
191 /* Use POSIX threads. */
194 mtx_init (mtx_t
*mutex
, int type
)
200 case mtx_plain
| mtx_recursive
:
201 case mtx_timed
| mtx_recursive
:
207 if ((type
& mtx_recursive
) != 0)
209 pthread_mutexattr_t attributes
;
212 err
= pthread_mutexattr_init (&attributes
);
215 err
= pthread_mutexattr_settype (&attributes
, PTHREAD_MUTEX_RECURSIVE
);
218 pthread_mutexattr_destroy (&attributes
);
221 err
= pthread_mutex_init (mutex
, &attributes
);
224 pthread_mutexattr_destroy (&attributes
);
227 err
= pthread_mutexattr_destroy (&attributes
);
233 int err
= pthread_mutex_init (mutex
, NULL
);
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
:
264 mtx_unlock (mtx_t
*mutex
)
266 int err
= pthread_mutex_unlock (mutex
);
267 return (err
== 0 ? thrd_success
: thrd_error
);
271 mtx_destroy (mtx_t
*mutex
)
273 pthread_mutex_destroy (mutex
);