1 /* ISO C 11 locking in multithreaded situations.
2 Copyright (C) 2005-2020 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)
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. */
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 call_once (once_flag
*flagp
, void (*func
) (void))
193 glwthread_once (flagp
, func
);
197 /* Use POSIX threads. */
200 mtx_init (mtx_t
*mutex
, int type
)
206 case mtx_plain
| mtx_recursive
:
207 case mtx_timed
| mtx_recursive
:
213 if ((type
& mtx_recursive
) != 0)
215 pthread_mutexattr_t attributes
;
218 err
= pthread_mutexattr_init (&attributes
);
221 err
= pthread_mutexattr_settype (&attributes
, PTHREAD_MUTEX_RECURSIVE
);
224 pthread_mutexattr_destroy (&attributes
);
227 err
= pthread_mutex_init (mutex
, &attributes
);
230 pthread_mutexattr_destroy (&attributes
);
233 err
= pthread_mutexattr_destroy (&attributes
);
239 int err
= pthread_mutex_init (mutex
, NULL
);
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
:
270 mtx_unlock (mtx_t
*mutex
)
272 int err
= pthread_mutex_unlock (mutex
);
273 return (err
== 0 ? thrd_success
: thrd_error
);
277 mtx_destroy (mtx_t
*mutex
)
279 pthread_mutex_destroy (mutex
);
283 call_once (once_flag
*flagp
, void (*func
) (void))
285 pthread_once (flagp
, func
);