Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / ep / ep_thr.c @ master

History | View | Annotate | Download (24.2 KB)

1 49c87bd9 Eric Allman
/* vim: set ai sw=8 sts=8 ts=8 :*/
2
3
/***********************************************************************
4 055d3009 Eric Allman
**  ----- BEGIN LICENSE BLOCK -----
5
**        LIBEP: Enhanced Portability Library (Reduced Edition)
6
**
7 c87dd166 Eric Allman
**        Copyright (c) 2008-2019, Eric P. Allman.  All rights reserved.
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9 6bd5476b Eric Allman
**        All rights reserved.
10 055d3009 Eric Allman
**
11 6bd5476b Eric Allman
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16 055d3009 Eric Allman
**
17 6bd5476b Eric Allman
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 055d3009 Eric Allman
**
22 6bd5476b Eric Allman
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23 055d3009 Eric Allman
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 6bd5476b Eric Allman
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28 055d3009 Eric Allman
**  ----- END LICENSE BLOCK -----
29 49c87bd9 Eric Allman
***********************************************************************/
30
31
#include <ep.h>
32
#include <ep_dbg.h>
33
#include <ep_thr.h>
34
#include <stdio.h>
35
#include <string.h>
36 416d60f4 Eric Allman
#include <strings.h>
37 a6f08b8d Eric Allman
#include <sys/errno.h>
38 49c87bd9 Eric Allman
39 9f5d76d6 Eric Allman
#if EP_OSCF_USE_PTHREADS
40
41 d16b1437 Eric Allman
static EP_DBG        Dbg = EP_DBG_INIT("libep.thr", "Threading support");
42 49c87bd9 Eric Allman
43 837e94b0 Eric Allman
bool        _EpThrUsePthreads = false;        // also used by ep_dbg_*
44 49c87bd9 Eric Allman
45 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
46 47d57c57 Eric Allman
# include <ep_string.h>
47 84fbdde9 Eric Allman
#endif
48
49
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
50
pthread_key_t        lorder_key;
51
pthread_once_t        lorder_once = PTHREAD_ONCE_INIT;
52
struct lorder
53
{
54
        uint64_t        lorder_used;
55
};
56
57
#  define GETMTX(m)                                                        \
58
        pthread_mutex_t *pmtx;                                                \
59 89035e50 Eric Allman
        int mtxorder EP_ATTR_UNUSED;                                        \
60 84fbdde9 Eric Allman
        if (m->magic != _EP_THR_MUTEX_MAGIC)                                \
61
        {                                                                \
62
            ep_assert_print(file, line,                                        \
63
                    "passing non-debug mutex %p to debug library", m);        \
64
            pmtx = (pthread_mutex_t *) m;                                \
65
            mtxorder = 0;                                                \
66
        }                                                                \
67
        else                                                                \
68
        {                                                                \
69
            pmtx = (pthread_mutex_t *) &m->pthr_mtx;                        \
70
            mtxorder = m->order;                                        \
71
        }
72 67fa395f Eric Allman
73
// This extern is needed because GNU insists that _GNU_SOURCE be defined
74
// to get the declaration.  But that pulls in a non-Posix strerror_r.
75
// Damned if you do, damned if you don't.
76
extern int        ffsl(long);
77
78 84fbdde9 Eric Allman
#else
79
#  define GETMTX(m)                                                        \
80
        pthread_mutex_t *pmtx = m;
81
#endif // EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
82
83
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x10
84 47d57c57 Eric Allman
#  define CHECKMTX(m, e) \
85 74e5f511 Eric Allman
    do        \
86
    {                                                                \
87 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__lock,                \
88
                        sizeof pmtx->__data.__lock);                \
89
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__owner,                \
90
                        sizeof pmtx->__data.__owner);                \
91
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__nusers,        \
92
                        sizeof pmtx->__data.__nusers);                \
93 2dec1b62 Eric Allman
        if (ep_dbg_test(Dbg, 98) &&                                \
94
            ((m)->__data.__lock > 1 ||                                \
95
             (m)->__data.__nusers > 1))                                \
96
        {                                                        \
97 74e5f511 Eric Allman
                fprintf(stderr,                                        \
98 3e98a709 Eric Allman
                    "%smutex_%s(%p): __lock=%x, __owner=%d, __nusers=%u%s\n", \
99 74e5f511 Eric Allman
                    EpVid->vidfgred, e, m,                        \
100 2dec1b62 Eric Allman
                    (m)->__data.__lock, (m)->__data.__owner,        \
101
                    (m)->__data.__nusers, EpVid->vidnorm);        \
102
        }                                                        \
103 14e720aa Eric Allman
    } while (false)
104 84fbdde9 Eric Allman
#endif // EP_OPT_EXTENDED_MUTEX_CHECK & 0x10
105 74e5f511 Eric Allman
106
#ifndef CHECKMTX
107
# define CHECKMTX(m, e)
108 2dec1b62 Eric Allman
#endif
109
110
#ifndef CHECKCOND
111 14e720aa Eric Allman
# define CHECKCOND(c, e)
112 74e5f511 Eric Allman
#endif
113
114 49c87bd9 Eric Allman
/*
115
**  Helper routines
116
*/
117
118
static void
119 fbb88f4c Eric Allman
diagnose_thr_err(int err,
120
                const char *where,
121
                const char *file,
122
                int line,
123 47d57c57 Eric Allman
                const char *name,
124
                void *p)
125 49c87bd9 Eric Allman
{
126 a6f08b8d Eric Allman
        // timed out is not unexpected, so put it at a high debug level
127
        if (ep_dbg_test(Dbg, err == ETIMEDOUT ? 90 : 4))
128
        {
129
                char nbuf[40];
130 5bc1cdfb Eric Allman
131 bfecf573 Eric Allman
                (void) (0 == strerror_r(err, nbuf, sizeof nbuf));
132 fbb88f4c Eric Allman
                if (name == NULL)
133
                        name = "???";
134 3e98a709 Eric Allman
                ep_dbg_printf("ep_thr_%-13s: %s:%d %s (%p): %s\n",
135
                                where, file, line, name, p, nbuf);
136 4a8ff91d Eric Allman
                ep_dbg_backtrace(NULL);
137 a6f08b8d Eric Allman
        }
138 19efef53 Eric Allman
        if (ep_dbg_test(Dbg, 101))
139 84fbdde9 Eric Allman
                ep_assert_failure(file, line,
140
                                "exiting on thread error in %s",
141
                                where);
142 49c87bd9 Eric Allman
}
143
144 84fbdde9 Eric Allman
# if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
145 2dec1b62 Eric Allman
static void
146 84fbdde9 Eric Allman
mtx_printtrace(EP_THR_MUTEX *m, const char *where,
147 2dec1b62 Eric Allman
                const char *file, int line, const char *name)
148
{
149 95e9c871 Eric Allman
        EP_THR_ID my_tid = ep_thr_gettid();
150 2dec1b62 Eric Allman
151 84fbdde9 Eric Allman
        GETMTX(m);
152 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__lock, sizeof pmtx->__data.__lock);
153
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__owner, sizeof pmtx->__data.__owner);
154 3e98a709 Eric Allman
        ep_dbg_printf("ep_thr_%-13s %s:%d %p (%s) [%d] __lock=%x __owner=%d%s\n",
155 2dec1b62 Eric Allman
                        where, file, line, m, name, my_tid,
156 84fbdde9 Eric Allman
                        pmtx->__data.__lock, pmtx->__data.__owner,
157 2dec1b62 Eric Allman
                        _EpThrUsePthreads ? "" : " (ignored)");
158
}
159
160 837e94b0 Eric Allman
static void
161 2dec1b62 Eric Allman
lock_printtrace(void *lock, const char *where,
162
                const char *file, int line, const char *name)
163
{
164 95e9c871 Eric Allman
        EP_THR_ID my_tid = ep_thr_gettid();
165 2dec1b62 Eric Allman
166 95e9c871 Eric Allman
        ep_dbg_printf("ep_thr_%-13s %s:%d %p (%s) [%" EP_THR_PRItid "]%s\n",
167 2dec1b62 Eric Allman
                        where, file, line, lock, name, my_tid,
168
                        _EpThrUsePthreads ? "" : " (ignored)");
169
}
170
171
#define TRACEMTX(m, where)        \
172
                if (ep_dbg_test(Dbg, 99))        \
173
                        mtx_printtrace(m, where, file, line, name)
174
175
#else
176
177
static void
178
lock_printtrace(void *lock, const char *where,
179 b22be946 Eric Allman
                const char *file, int line, const char *name)
180 837e94b0 Eric Allman
{
181
        pthread_t self = pthread_self();
182
183 3e98a709 Eric Allman
        ep_dbg_printf("ep_thr_%-13s %s:%d %p (%s) [%p]%s\n",
184 47d57c57 Eric Allman
                        where, file, line, lock, name, (void *) self,
185 74e5f511 Eric Allman
                        _EpThrUsePthreads ? "" : " (ignored)");
186 837e94b0 Eric Allman
}
187 2dec1b62 Eric Allman
#define TRACEMTX        TRACE
188
189 84fbdde9 Eric Allman
#endif // EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
190 837e94b0 Eric Allman
191 51775f02 Eric Allman
#define TRACE(lock, where)        \
192 b22be946 Eric Allman
                if (ep_dbg_test(Dbg, 99))        \
193 2dec1b62 Eric Allman
                        lock_printtrace(lock, where, file, line, name)
194 837e94b0 Eric Allman
195 49c87bd9 Eric Allman
void
196
_ep_thr_init(void)
197
{
198
        _EpThrUsePthreads = true;
199
}
200
201
202
/*
203 546805c8 Eric Allman
**  Basics
204
*/
205
206 b22be946 Eric Allman
int
207 fbb88f4c Eric Allman
_ep_thr_spawn(EP_THR *thidp,
208
                void *(*thfunc)(void *),
209
                void *arg,
210
                const char *file,
211
                int line)
212 b22be946 Eric Allman
{
213 e17a232e Eric Allman
int r;
214 b22be946 Eric Allman
215 fbb88f4c Eric Allman
        // to make the TRACE call compile
216 b22be946 Eric Allman
        const char *name = NULL;
217
218
        TRACE(NULL, "spawn");
219
        if (!_EpThrUsePthreads)
220
                return EPERM;
221
        r = pthread_create(thidp, NULL, thfunc, arg);
222
        if (r != 0)
223 47d57c57 Eric Allman
                diagnose_thr_err(errno, "spawn", file, line, NULL, NULL);
224 b22be946 Eric Allman
        return r;
225
}
226
227
228 546805c8 Eric Allman
void
229 fbb88f4c Eric Allman
_ep_thr_yield(const char *file, int line)
230 546805c8 Eric Allman
{
231 fbb88f4c Eric Allman
        // to make the TRACE call compile
232 b22be946 Eric Allman
        const char *name = NULL;
233
234 546805c8 Eric Allman
        TRACE(NULL, "yield");
235
        if (!_EpThrUsePthreads)
236
                return;
237
        if (sched_yield() < 0)
238 47d57c57 Eric Allman
                diagnose_thr_err(errno, "yield", file, line, NULL, NULL);
239 546805c8 Eric Allman
}
240
241
242 522991b2 Eric Allman
EP_THR
243 95e9c871 Eric Allman
ep_thr_getself(void)
244
{
245
        return pthread_self();
246
}
247
248
249
EP_THR_ID
250 522991b2 Eric Allman
ep_thr_gettid(void)
251
{
252 95e9c871 Eric Allman
#if EP_OSCF_HAS_SYS_GETTID
253
        return syscall(SYS_gettid);
254
#else
255 522991b2 Eric Allman
        return pthread_self();
256 95e9c871 Eric Allman
#endif
257 522991b2 Eric Allman
}
258
259
260 546805c8 Eric Allman
/*
261 49c87bd9 Eric Allman
**  Mutex implementation
262
*/
263
264
int
265 b22be946 Eric Allman
_ep_thr_mutex_init(EP_THR_MUTEX *mtx, int type,
266
                const char *file, int line, const char *name)
267 49c87bd9 Eric Allman
{
268
        int err;
269 837e94b0 Eric Allman
        pthread_mutexattr_t attr;
270 49c87bd9 Eric Allman
271
        if (!_EpThrUsePthreads)
272
                return 0;
273 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
274
        mtx->magic = _EP_THR_MUTEX_MAGIC;
275 e17a232e Eric Allman
        mtx->locker = 0;
276 84fbdde9 Eric Allman
        mtx->order = 0;
277 e17a232e Eric Allman
        mtx->l_file = NULL;
278
        mtx->l_line = 0;
279 84fbdde9 Eric Allman
        pthread_mutex_t *pmtx = &mtx->pthr_mtx;
280
#else
281
        pthread_mutex_t *pmtx = mtx;
282
#endif
283 837e94b0 Eric Allman
        pthread_mutexattr_init(&attr);
284 74e5f511 Eric Allman
        if (type == EP_THR_MUTEX_DEFAULT)
285
        {
286
                const char *mtype;
287
288
                mtype = ep_adm_getstrparam("libep.thr.mutex.type", "default");
289
                if (strcasecmp(mtype, "normal") == 0)
290
                        type = PTHREAD_MUTEX_NORMAL;
291
                else if (strcasecmp(mtype, "errorcheck") == 0)
292
                        type = PTHREAD_MUTEX_ERRORCHECK;
293
                else if (strcasecmp(mtype, "recursive") == 0)
294
                        type = PTHREAD_MUTEX_RECURSIVE;
295
                else
296
                        type = PTHREAD_MUTEX_DEFAULT;
297
        }
298 51775f02 Eric Allman
        pthread_mutexattr_settype(&attr, type);
299 84fbdde9 Eric Allman
        if ((err = pthread_mutex_init(pmtx, &attr)) != 0)
300 47d57c57 Eric Allman
                diagnose_thr_err(err, "mutex_init", file, line, name, mtx);
301 51775f02 Eric Allman
        pthread_mutexattr_destroy(&attr);
302 2dec1b62 Eric Allman
        TRACEMTX(mtx, "mutex_init");
303 14e720aa Eric Allman
        CHECKMTX(mtx, "init <<<");
304 49c87bd9 Eric Allman
        return err;
305
}
306
307
int
308 b22be946 Eric Allman
_ep_thr_mutex_destroy(EP_THR_MUTEX *mtx,
309
                const char *file, int line, const char *name)
310 49c87bd9 Eric Allman
{
311
        int err;
312
313 2dec1b62 Eric Allman
        TRACEMTX(mtx, "mutex_destroy");
314 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
315
                return 0;
316 84fbdde9 Eric Allman
        GETMTX(mtx);
317 14e720aa Eric Allman
        CHECKMTX(mtx, "destroy >>>");
318 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
319 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__lock, sizeof pmtx->__data.__lock);
320 84fbdde9 Eric Allman
        if (pmtx->__data.__lock != 0)
321 c975e6e5 Eric Allman
        {
322 95e9c871 Eric Allman
                if (pmtx->__data.__lock == ep_thr_gettid())
323 c975e6e5 Eric Allman
                        ep_assert_print(file, line,
324 84fbdde9 Eric Allman
                                "_ep_thr_mutex_destroy: destroying self-locked"
325
                                " mutex %p (%s)",
326
                                pmtx, name);
327 c975e6e5 Eric Allman
                else
328
                        ep_assert_print(file, line,
329 84fbdde9 Eric Allman
                                "_ep_thr_mutex_destroy: destroying mutex "
330 95e9c871 Eric Allman
                                "%p (%s) locked by %d "
331
                                "(I am %" EP_THR_PRItid ")",
332
                                pmtx, name, pmtx->__data.__lock,
333
                                ep_thr_gettid());
334 c975e6e5 Eric Allman
        }
335 84fbdde9 Eric Allman
#endif // EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
336 5e58af7b Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
337
        if (mtx->magic != _EP_THR_MUTEX_MAGIC)
338
                ep_assert_print(file, line, "mutex %s bad magic %x",
339
                                name, mtx->magic);
340
        mtx->magic = 0xDEADBEEF;
341
#endif // EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
342 84fbdde9 Eric Allman
        if ((err = pthread_mutex_destroy(pmtx)) != 0)
343 47d57c57 Eric Allman
                diagnose_thr_err(err, "mutex_destroy", file, line, name, mtx);
344 49c87bd9 Eric Allman
        return err;
345
}
346
347 84fbdde9 Eric Allman
348
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
349
static void
350
lorder_free(void *lorder_)
351
{
352
        ep_mem_free(lorder_);
353
}
354
355
static void
356
lorder_init(void)
357
{
358
        int istat;
359 fc0cbc23 Eric Allman
        struct lorder *lorder =
360
                        (struct lorder *) ep_mem_zalloc(sizeof *lorder);
361 84fbdde9 Eric Allman
362
        lorder->lorder_used = 0;
363
        istat = pthread_key_create(&lorder_key, lorder_free);
364
        if (istat != 0)
365
                diagnose_thr_err(istat, "lorder_init", __FILE__, __LINE__,
366
                                "pthread_key_create", NULL);
367
        istat = pthread_setspecific(lorder_key, lorder);
368
        if (istat != 0)
369
                diagnose_thr_err(istat, "lorder_init", __FILE__, __LINE__,
370
                                "pthread_setspecific", NULL);
371
}
372
373
void
374
_ep_thr_mutex_setorder(EP_THR_MUTEX *mtx, int order,
375
                const char *file, int line, const char *name)
376
{
377
        if (mtx->order != 0 && mtx->order != order)
378
        {
379
                ep_dbg_cprintf(Dbg, 1,
380
                                "_ep_thr_mutex_setorder: changing order from %d to %d\n",
381
                                mtx->order, order);
382
        }
383
        mtx->order = order;
384
}
385
386
#endif // EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
387
388 49c87bd9 Eric Allman
int
389 b22be946 Eric Allman
_ep_thr_mutex_lock(EP_THR_MUTEX *mtx,
390
                const char *file, int line, const char *name)
391 49c87bd9 Eric Allman
{
392
        int err;
393
394 2dec1b62 Eric Allman
        TRACEMTX(mtx, "mutex_lock");
395 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
396
                return 0;
397 84fbdde9 Eric Allman
        GETMTX(mtx);
398 14e720aa Eric Allman
        CHECKMTX(mtx, "lock >>>");
399 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
400 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__lock, sizeof pmtx->__data.__lock);
401
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__owner, sizeof pmtx->__data.__owner);
402
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__kind, sizeof pmtx->__data.__kind);
403 84fbdde9 Eric Allman
        if (pmtx->__data.__lock != 0 &&
404 95e9c871 Eric Allman
            pmtx->__data.__owner == ep_thr_gettid() &&
405 84fbdde9 Eric Allman
            pmtx->__data.__kind != PTHREAD_MUTEX_RECURSIVE_NP)
406 c975e6e5 Eric Allman
        {
407
                ep_assert_print(file, line,
408 8834a9d7 Eric Allman
                        "ep_thr_mutex_lock: mutex %p (%s) already self-locked",
409 c975e6e5 Eric Allman
                        mtx, name);
410
        }
411 e17a232e Eric Allman
#elif EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
412 5e58af7b Eric Allman
        if (mtx->magic != _EP_THR_MUTEX_MAGIC)
413
                ep_assert_print(file, line, "mutex %s bad magic %x",
414
                                name, mtx->magic);
415 e17a232e Eric Allman
        if (mtx->locker == ep_thr_gettid())
416
        {
417 8834a9d7 Eric Allman
                ep_dbg_cprintf(Dbg, 1,
418
                        "ep_thr_mutex_lock at %s:%d: mutex %p (%s) already self-locked"
419
                        " (%s:%d)\n",
420
                        file, line,
421 e17a232e Eric Allman
                        mtx, name, mtx->l_file, mtx->l_line);
422
        }
423 ffd16cbe Eric Allman
#endif
424 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
425
        struct lorder *lorder;
426
        if (mtxorder > 0)
427
        {
428
                uint64_t mask;
429
430
                mask = ~((1 << (mtxorder - 1)) - 1) << 1;
431 416d60f4 Eric Allman
                pthread_once(&lorder_once, lorder_init);
432 fc0cbc23 Eric Allman
                lorder = (struct lorder *) pthread_getspecific(lorder_key);
433 84fbdde9 Eric Allman
                if (lorder != NULL)
434
                {
435
                        int llu = ffsl(lorder->lorder_used & mask);
436
                        if (llu > mtxorder)
437
                        {
438 728482c6 Eric Allman
                                ep_dbg_cprintf(Dbg, 1,
439 8834a9d7 Eric Allman
                                        "ep_thr_mutex_lock at %s:%d:"
440
                                        " mutex %p (%s) has order %d,"
441
                                        " but %d is already locked\n",
442
                                        file, line,
443
                                        mtx, name, mtxorder, llu);
444 84fbdde9 Eric Allman
                        }
445
                }
446
        }
447
#endif // EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
448
        if ((err = pthread_mutex_lock(pmtx)) != 0)
449 47d57c57 Eric Allman
                diagnose_thr_err(err, "mutex_lock", file, line, name, mtx);
450 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
451 e17a232e Eric Allman
        if (err == 0)
452
        {
453
                if (mtxorder > 0 && lorder != NULL)
454
                        lorder->lorder_used |= 1 << (mtxorder - 1);
455
                mtx->locker = ep_thr_gettid();
456
                mtx->l_file = file;
457
                mtx->l_line = line;
458
        }
459 84fbdde9 Eric Allman
#endif
460 14e720aa Eric Allman
        CHECKMTX(mtx, "lock <<<");
461 49c87bd9 Eric Allman
        return err;
462
}
463
464
int
465 b22be946 Eric Allman
_ep_thr_mutex_trylock(EP_THR_MUTEX *mtx,
466
                const char *file, int line, const char *name)
467 49c87bd9 Eric Allman
{
468
        int err;
469
470 2dec1b62 Eric Allman
        TRACEMTX(mtx, "mutex_trylock");
471 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
472
                return 0;
473 84fbdde9 Eric Allman
        GETMTX(mtx);
474
        CHECKMTX(pmtx, "trylock >>>");
475
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
476 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__lock, sizeof pmtx->__data.__lock);
477
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__owner, sizeof pmtx->__data.__owner);
478
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__kind, sizeof pmtx->__data.__kind);
479 84fbdde9 Eric Allman
        if (pmtx->__data.__lock != 0 &&
480 95e9c871 Eric Allman
            pmtx->__data.__owner == ep_thr_gettid() &&
481 84fbdde9 Eric Allman
            pmtx->__data.__kind != PTHREAD_MUTEX_RECURSIVE_NP)
482 4a863be9 Eric Allman
        {
483 b8f93c05 Eric Allman
                // this is not necessarily an error
484
                ep_dbg_cprintf(Dbg, 1,
485 95e9c871 Eric Allman
                        "_ep_thr_mutex_lock: mutex %p (%s) "
486
                        "already self-locked (%s:%d)\n",
487 b8f93c05 Eric Allman
                        mtx, name, file, line);
488 4a863be9 Eric Allman
        }
489 e17a232e Eric Allman
#elif EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
490 5e58af7b Eric Allman
        if (mtx->magic != _EP_THR_MUTEX_MAGIC)
491
                ep_assert_print(file, line, "mutex %s bad magic %x",
492
                                name, mtx->magic);
493 e17a232e Eric Allman
        if (mtx->locker == ep_thr_gettid())
494
        {
495
                // this is not necessarily an error
496
                ep_dbg_cprintf(Dbg, 1,
497 8834a9d7 Eric Allman
                        "ep_thr_mutex_lock: mutex %p (%s) already self-locked\n"
498 e17a232e Eric Allman
                        "    (error at %s:%d, previous lock %s:%d)\n",
499
                        mtx, name, file, line, mtx->l_file, mtx->l_line);
500
        }
501 4a863be9 Eric Allman
#endif
502 06416042 Eric Allman
        // EBUSY => mutex was already locked
503 84fbdde9 Eric Allman
        if ((err = pthread_mutex_trylock(pmtx)) != 0 && err != EBUSY)
504 47d57c57 Eric Allman
                diagnose_thr_err(err, "mutex_trylock", file, line, name, mtx);
505 416d60f4 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
506
        struct lorder *lorder;
507
        pthread_once(&lorder_once, lorder_init);
508 fc0cbc23 Eric Allman
        lorder = (struct lorder *) pthread_getspecific(lorder_key);
509 e17a232e Eric Allman
        if (err == 0)
510
        {
511
                if (mtxorder > 0 && lorder != NULL)
512
                        lorder->lorder_used |= 1 << (mtxorder - 1);
513
                mtx->locker = ep_thr_gettid();
514
                mtx->l_file = file;
515
                mtx->l_line = line;
516
        }
517 416d60f4 Eric Allman
#endif
518 14e720aa Eric Allman
        CHECKMTX(mtx, "trylock <<<");
519 49c87bd9 Eric Allman
        return err;
520
}
521
522
int
523 b22be946 Eric Allman
_ep_thr_mutex_unlock(EP_THR_MUTEX *mtx,
524
                const char *file, int line, const char *name)
525 49c87bd9 Eric Allman
{
526
        int err;
527
528 2dec1b62 Eric Allman
        TRACEMTX(mtx, "mutex_unlock");
529 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
530
                return 0;
531 84fbdde9 Eric Allman
        GETMTX(mtx);
532
        CHECKMTX(pmtx, "unlock >>>");
533
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
534 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__owner, sizeof pmtx->__data.__owner);
535 95e9c871 Eric Allman
        if (pmtx->__data.__owner != ep_thr_gettid())
536 8834a9d7 Eric Allman
                ep_dbg_cprintf(Dbg, 1,
537
                                "ep_thr_mutex_unlock at %s:%d:"
538
                                " mtx owner = %d, I am %"EP_THR_PRItid "\n",
539
                                file, line,
540 95e9c871 Eric Allman
                                pmtx->__data.__owner, ep_thr_gettid());
541 e17a232e Eric Allman
#elif EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
542 5e58af7b Eric Allman
        if (mtx->magic != _EP_THR_MUTEX_MAGIC)
543
                ep_assert_print(file, line, "mutex %s bad magic %x",
544
                                name, mtx->magic);
545 e17a232e Eric Allman
        if (mtx->locker != ep_thr_gettid())
546 a1e67be4 Eric Allman
        {
547 8834a9d7 Eric Allman
                ep_dbg_cprintf(Dbg, 1,
548
                                "ep_thr_mutex_unlock at %s:%d:"
549
                                " mtx owner = %"EP_THR_PRItid " at %s:%d;"
550
                                " I am %"EP_THR_PRItid "\n",
551
                                file, line,
552 e17a232e Eric Allman
                                mtx->locker, mtx->l_file, mtx->l_line,
553
                                ep_thr_gettid());
554 a1e67be4 Eric Allman
        }
555
        else
556
        {
557
                mtx->locker = 0;        // presumptuous
558
        }
559 ffd16cbe Eric Allman
#endif
560 84fbdde9 Eric Allman
        if ((err = pthread_mutex_unlock(pmtx)) != 0)
561 47d57c57 Eric Allman
                diagnose_thr_err(err, "mutex_unlock", file, line, name, mtx);
562 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
563 a1e67be4 Eric Allman
        if (err == 0 && mtxorder > 0)
564 84fbdde9 Eric Allman
        {
565 a1e67be4 Eric Allman
                struct lorder *lorder;
566
                pthread_once(&lorder_once, lorder_init);
567
                lorder = (struct lorder *) pthread_getspecific(lorder_key);
568
                if (lorder != NULL)
569
                        lorder->lorder_used &= ~(1 << (mtxorder - 1));
570 84fbdde9 Eric Allman
        }
571
#endif // EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
572
        CHECKMTX(pmtx, "unlock <<<");
573 49c87bd9 Eric Allman
        return err;
574
}
575
576 74e5f511 Eric Allman
int
577 06416042 Eric Allman
_ep_thr_mutex_tryunlock(EP_THR_MUTEX *mtx,
578
                const char *file, int line, const char *name)
579
{
580
        int err;
581
582
        TRACE(mtx, "mutex_tryunlock");
583
        if (!_EpThrUsePthreads)
584
                return 0;
585 84fbdde9 Eric Allman
        GETMTX(mtx);
586
        CHECKMTX(pmtx, "tryunlock >>>");
587
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
588 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__owner, sizeof pmtx->__data.__owner);
589 95e9c871 Eric Allman
        if (pmtx->__data.__owner != ep_thr_gettid())
590 8834a9d7 Eric Allman
                ep_dbg_cprintf(Dbg, 1,
591
                                "_ep_thr_mutex_unlock at %s:%d:"
592
                                " mtx owner = %"EP_THR_PRItid ","
593
                                " I am %" EP_THR_PRItid "\n",
594
                                file, line,
595 95e9c871 Eric Allman
                                pmtx->__data.__owner, ep_thr_gettid());
596 e17a232e Eric Allman
#elif EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
597
        if (mtx->locker != ep_thr_gettid())
598 a1e67be4 Eric Allman
        {
599 8834a9d7 Eric Allman
                ep_dbg_cprintf(Dbg, 1,
600
                                "_ep_thr_mutex_unlock at %s:%d:"
601
                                " mtx owner = %"EP_THR_PRItid " at %s:%d,"
602
                                " I am %" EP_THR_PRItid "\n",
603
                                file, line,
604 e17a232e Eric Allman
                                mtx->locker, mtx->l_file, mtx->l_line,
605
                                ep_thr_gettid());
606 a1e67be4 Eric Allman
        }
607
        else
608
        {
609
                mtx->locker = 0;        // presumptuous
610
        }
611 ffd16cbe Eric Allman
#endif
612 06416042 Eric Allman
        // EAGAIN => mutex was not locked
613 7bc0e2cf Eric Allman
        // EPERM  => mutex held by a different thread
614 84fbdde9 Eric Allman
        if ((err = pthread_mutex_unlock(pmtx)) != 0 &&
615 7bc0e2cf Eric Allman
                        err != EAGAIN && err != EPERM)
616 47d57c57 Eric Allman
                diagnose_thr_err(err, "mutex_unlock", file, line, name, mtx);
617 84fbdde9 Eric Allman
        CHECKMTX(pmtx, "tryunlock <<<");
618 06416042 Eric Allman
        return err;
619
}
620
621 ffd16cbe Eric Allman
622 06416042 Eric Allman
int
623 5e58af7b Eric Allman
_ep_thr_mutex_check(
624
                EP_THR_MUTEX *mtx,
625
                const char *file,
626
                int line,
627
                const char *mstr)
628 74e5f511 Eric Allman
{
629 14e720aa Eric Allman
        CHECKMTX(mtx, "check ===");
630 5e58af7b Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
631
        if (mtx->magic != _EP_THR_MUTEX_MAGIC)
632
                ep_assert_print(file, line, "mutex %s bad magic %x",
633
                                mstr, mtx->magic);
634
#endif
635 74e5f511 Eric Allman
        return 0;
636
}
637
638 ffd16cbe Eric Allman
639 b9c4d7c8 Eric Allman
#undef ep_thr_mutex_assert_islocked
640
641 47d57c57 Eric Allman
bool
642 ffd16cbe Eric Allman
ep_thr_mutex_assert_islocked(
643 47d57c57 Eric Allman
                        EP_THR_MUTEX *m,
644
                        const char *mstr,
645
                        const char *file,
646
                        int line)
647
{
648 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
649
        GETMTX(m);
650 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__lock, sizeof pmtx->__data.__lock);
651
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__owner, sizeof pmtx->__data.__owner);
652 95e9c871 Eric Allman
        if (pmtx->__data.__lock != 0 && pmtx->__data.__owner == ep_thr_gettid())
653 47d57c57 Eric Allman
        {
654
                // OK, this is locked (by me)
655
                return true;
656
        }
657
658
        // oops, not locked or not locked by me
659 84fbdde9 Eric Allman
        if (pmtx->__data.__lock == 0)
660 8834a9d7 Eric Allman
                ep_assert_print(file, line,
661
                                "mutex %s (%p) is not locked "
662 95e9c871 Eric Allman
                                "(should be %" EP_THR_PRItid ")",
663
                                mstr, m, ep_thr_gettid());
664 47d57c57 Eric Allman
        else
665 e17a232e Eric Allman
                ep_assert_print(file, line,
666
                                "mutex %s (%p) locked by %d "
667 95e9c871 Eric Allman
                                "(should be %" EP_THR_PRItid ")",
668
                                mstr, m, pmtx->__data.__owner, ep_thr_gettid());
669 47d57c57 Eric Allman
        return false;
670 e17a232e Eric Allman
#elif EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
671 5e58af7b Eric Allman
        if (m->magic != _EP_THR_MUTEX_MAGIC)
672
                ep_assert_print(file, line, "mutex %s bad magic %x",
673
                                mstr, m->magic);
674 e17a232e Eric Allman
        if (m->locker == 0)
675
                ep_assert_print(file, line, "mutex %s (%p) is not locked "
676
                                "(should be %" EP_THR_PRItid ")",
677
                                mstr, m, ep_thr_gettid());
678
        else if (m->locker != ep_thr_gettid())
679
                ep_assert_print(file, line,
680
                                "mutex %s (%p) is locked by %" EP_THR_PRItid
681
                                " (%s:%d), should be %" EP_THR_PRItid,
682
                                mstr, m, m->locker, m->l_file, m->l_line,
683
                                ep_thr_gettid());
684
        else
685
                return true;
686
        return false;
687 84fbdde9 Eric Allman
#else
688
        return true;
689 47d57c57 Eric Allman
#endif
690
}
691
692
693 b9c4d7c8 Eric Allman
#undef ep_thr_mutex_assert_isunlocked
694
695 47d57c57 Eric Allman
bool
696 ffd16cbe Eric Allman
ep_thr_mutex_assert_isunlocked(
697 47d57c57 Eric Allman
                        EP_THR_MUTEX *m,
698
                        const char *mstr,
699
                        const char *file,
700
                        int line)
701
{
702 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
703
        GETMTX(m);
704 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__lock, sizeof pmtx->__data.__lock);
705 84fbdde9 Eric Allman
        if (pmtx->__data.__lock == 0)
706 66f6c374 Eric Allman
        {
707 47d57c57 Eric Allman
                return true;
708 66f6c374 Eric Allman
        }
709 47d57c57 Eric Allman
        ep_assert_print(file, line,
710 95e9c871 Eric Allman
                        "mutex %s (%p) is locked by %d "
711
                        "(should be unlocked; I am %" EP_THR_PRItid ")",
712
                        mstr, m, pmtx->__data.__owner, ep_thr_gettid());
713 47d57c57 Eric Allman
        return false;
714 e17a232e Eric Allman
#elif EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
715 5e58af7b Eric Allman
        if (m->magic != _EP_THR_MUTEX_MAGIC)
716
                ep_assert_print(file, line, "mutex %s bad magic %x",
717
                                mstr, m->magic);
718 e17a232e Eric Allman
        if (m->locker == 0)
719
                return true;
720
        ep_assert_print(file, line,
721
                        "mutex %s (%p) is locked by %" EP_THR_PRItid
722
                        " (%s:%d), should be %" EP_THR_PRItid,
723
                        mstr, m, m->locker, m->l_file, m->l_line,
724
                        ep_thr_gettid());
725
        return false;
726 84fbdde9 Eric Allman
#else
727
        return true;
728 47d57c57 Eric Allman
#endif
729
}
730
731 49c87bd9 Eric Allman
732 b9c4d7c8 Eric Allman
#undef ep_thr_mutex_assert_i_own
733
734 ffd16cbe Eric Allman
bool
735
ep_thr_mutex_assert_i_own(
736
                        EP_THR_MUTEX *m,
737
                        const char *mstr,
738
                        const char *file,
739
                        int line)
740
{
741 84fbdde9 Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x01
742
        GETMTX(m);
743 66f6c374 Eric Allman
        VALGRIND_HG_CLEAN_MEMORY(&pmtx->__data.__owner, sizeof pmtx->__data.__owner);
744 95e9c871 Eric Allman
        if (pmtx->__data.__owner == ep_thr_gettid())
745 66f6c374 Eric Allman
        {
746 ffd16cbe Eric Allman
                return true;
747 66f6c374 Eric Allman
        }
748 ffd16cbe Eric Allman
        ep_assert_print(file, line,
749 95e9c871 Eric Allman
                        "mutex %s (%p) is locked by %d "
750
                        "(should be %" EP_THR_PRItid ")",
751
                        mstr, m, pmtx->__data.__owner, ep_thr_gettid());
752 ffd16cbe Eric Allman
        return false;
753 e17a232e Eric Allman
#elif EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
754 5e58af7b Eric Allman
        if (m->magic != _EP_THR_MUTEX_MAGIC)
755
                ep_assert_print(file, line, "mutex %s bad magic %x",
756
                                mstr, m->magic);
757 e17a232e Eric Allman
        if (m->locker == ep_thr_gettid())
758
                return true;
759
        ep_assert_print(file, line,
760
                        "mutex %s (%p) is locked by %" EP_THR_PRItid
761 8834a9d7 Eric Allman
                        " at %s:%d, should be %" EP_THR_PRItid,
762 e17a232e Eric Allman
                        mstr, m, m->locker, m->l_file, m->l_line,
763
                        ep_thr_gettid());
764
        return false;
765 84fbdde9 Eric Allman
#else
766
        return true;
767 ffd16cbe Eric Allman
#endif
768
}
769
770
771 49c87bd9 Eric Allman
/*
772
**  Condition Variable implementation
773
*/
774
775
int
776 b22be946 Eric Allman
_ep_thr_cond_init(EP_THR_COND *cv,
777
                const char *file, int line, const char *name)
778 49c87bd9 Eric Allman
{
779
        int err;
780
781 51775f02 Eric Allman
        TRACE(cv, "cond_init");
782 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
783
                return 0;
784
        if ((err = pthread_cond_init(cv, NULL)) != 0)
785 47d57c57 Eric Allman
                diagnose_thr_err(err, "cond_init", file, line, name, cv);
786 14e720aa Eric Allman
        CHECKCOND(cv, "init <<<");
787 49c87bd9 Eric Allman
        return err;
788
}
789
790
int
791 b22be946 Eric Allman
_ep_thr_cond_destroy(EP_THR_COND *cv,
792
                const char *file, int line, const char *name)
793 49c87bd9 Eric Allman
{
794
        int err;
795
796 51775f02 Eric Allman
        TRACE(cv, "cond_destroy");
797 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
798
                return 0;
799 14e720aa Eric Allman
        CHECKCOND(cv, "destroy >>>");
800 49c87bd9 Eric Allman
        if ((err = pthread_cond_destroy(cv)) != 0)
801 47d57c57 Eric Allman
                diagnose_thr_err(err, "cond_destroy", file, line, name, cv);
802 49c87bd9 Eric Allman
        return err;
803
}
804
805
int
806 b22be946 Eric Allman
_ep_thr_cond_signal(EP_THR_COND *cv,
807
                const char *file, int line, const char *name)
808 49c87bd9 Eric Allman
{
809
        int err;
810
811 51775f02 Eric Allman
        TRACE(cv, "cond_signal");
812 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
813
                return 0;
814 14e720aa Eric Allman
        CHECKCOND(cv, "signal >>>");
815 49c87bd9 Eric Allman
        if ((err = pthread_cond_signal(cv)) != 0)
816 47d57c57 Eric Allman
                diagnose_thr_err(err, "cond_signal", file, line, name, cv);
817 14e720aa Eric Allman
        CHECKCOND(cv, "signal <<<");
818 49c87bd9 Eric Allman
        return err;
819
}
820
821
int
822 b22be946 Eric Allman
_ep_thr_cond_wait(EP_THR_COND *cv, EP_THR_MUTEX *mtx, EP_TIME_SPEC *timeout,
823
                const char *file, int line, const char *name)
824 49c87bd9 Eric Allman
{
825
        int err;
826
827 4dcf6f56 Eric Allman
        TRACE(cv, "cond_wait-cv");
828 2dec1b62 Eric Allman
        TRACEMTX(mtx, "cond-wait-mtx");
829 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
830
                return 0;
831 84fbdde9 Eric Allman
        GETMTX(mtx);
832 14e720aa Eric Allman
        CHECKMTX(mtx, "wait >>>");
833
        CHECKCOND(cv, "wait >>>");
834 e17a232e Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
835
        EP_THR_ID save_locker = mtx->locker;
836
        const char *save_l_file = mtx->l_file;
837
        int save_l_line = mtx->l_line;
838
#endif
839 686e4579 Eric Allman
        if (timeout == NULL)
840
        {
841 84fbdde9 Eric Allman
                err = pthread_cond_wait(cv, pmtx);
842 686e4579 Eric Allman
        }
843
        else
844
        {
845
                struct timespec ts;
846 ce3c250b Eric Allman
                ts.tv_sec = timeout->tv_sec;
847
                ts.tv_nsec = timeout->tv_nsec;
848 84fbdde9 Eric Allman
                err = pthread_cond_timedwait(cv, pmtx, &ts);
849 686e4579 Eric Allman
        }
850
        if (err != 0)
851 47d57c57 Eric Allman
                diagnose_thr_err(err, "cond_wait", file, line, name, cv);
852 e17a232e Eric Allman
#if EP_OPT_EXTENDED_MUTEX_CHECK & 0x02
853
        mtx->locker = save_locker;
854
        mtx->l_file = save_l_file;
855
        mtx->l_line = save_l_line;
856
#endif
857 14e720aa Eric Allman
        CHECKMTX(mtx, "wait <<<");
858
        CHECKCOND(cv, "wait <<<");
859 49c87bd9 Eric Allman
        return err;
860
}
861
862
int
863 b22be946 Eric Allman
_ep_thr_cond_broadcast(EP_THR_COND *cv,
864
                const char *file, int line, const char *name)
865 49c87bd9 Eric Allman
{
866
        int err;
867
868 51775f02 Eric Allman
        TRACE(cv, "cond_broadcast");
869 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
870
                return 0;
871 14e720aa Eric Allman
        CHECKCOND(cv, "broadcast >>>");
872 49c87bd9 Eric Allman
        if ((err = pthread_cond_broadcast(cv)) != 0)
873 47d57c57 Eric Allman
                diagnose_thr_err(err, "cond_broadcast", file, line, name, cv);
874 14e720aa Eric Allman
        CHECKCOND(cv, "broadcast <<<");
875 49c87bd9 Eric Allman
        return err;
876
}
877
878
879
/*
880
**  Read/Write Lock implementation
881
*/
882
883
int
884 b22be946 Eric Allman
_ep_thr_rwlock_init(EP_THR_RWLOCK *rwl,
885
                const char *file, int line, const char *name)
886 49c87bd9 Eric Allman
{
887
        int err;
888
889 51775f02 Eric Allman
        TRACE(rwl, "rwlock_init");
890 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
891
                return 0;
892
        if ((err = pthread_rwlock_init(rwl, NULL)) != 0)
893 47d57c57 Eric Allman
                diagnose_thr_err(err, "rwlock_init", file, line, name, rwl);
894 49c87bd9 Eric Allman
        return err;
895
}
896
897
int
898 b22be946 Eric Allman
_ep_thr_rwlock_destroy(EP_THR_RWLOCK *rwl,
899
                const char *file, int line, const char *name)
900 49c87bd9 Eric Allman
{
901
        int err;
902
903 51775f02 Eric Allman
        TRACE(rwl, "rwlock_destroy");
904 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
905
                return 0;
906
        if ((err = pthread_rwlock_destroy(rwl)) != 0)
907 47d57c57 Eric Allman
                diagnose_thr_err(err, "rwlock_destroy", file, line, name, rwl);
908 49c87bd9 Eric Allman
        return err;
909
}
910
911
int
912 b22be946 Eric Allman
_ep_thr_rwlock_rdlock(EP_THR_RWLOCK *rwl,
913
                const char *file, int line, const char *name)
914 49c87bd9 Eric Allman
{
915
        int err;
916
917 51775f02 Eric Allman
        TRACE(rwl, "rwlock_rdlock");
918 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
919
                return 0;
920
        if ((err = pthread_rwlock_rdlock(rwl)) != 0)
921 47d57c57 Eric Allman
                diagnose_thr_err(err, "rwlock_rdlock", file, line, name, rwl);
922 49c87bd9 Eric Allman
        return err;
923
}
924
925
int
926 b22be946 Eric Allman
_ep_thr_rwlock_tryrdlock(EP_THR_RWLOCK *rwl,
927
                const char *file, int line, const char *name)
928 49c87bd9 Eric Allman
{
929
        int err;
930
931 51775f02 Eric Allman
        TRACE(rwl, "rwlock_tryrdlock");
932 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
933
                return 0;
934
        if ((err = pthread_rwlock_tryrdlock(rwl)) != 0)
935 47d57c57 Eric Allman
                diagnose_thr_err(err, "rwlock_tryrdlock", file, line, name, rwl);
936 49c87bd9 Eric Allman
        return err;
937
}
938
939
int
940 b22be946 Eric Allman
_ep_thr_rwlock_wrlock(EP_THR_RWLOCK *rwl,
941
                const char *file, int line, const char *name)
942 49c87bd9 Eric Allman
{
943
        int err;
944
945 51775f02 Eric Allman
        TRACE(rwl, "rwlock_wrlock");
946 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
947
                return 0;
948
        if ((err = pthread_rwlock_wrlock(rwl)) != 0)
949 47d57c57 Eric Allman
                diagnose_thr_err(err, "rwlock_wrlock", file, line, name, rwl);
950 49c87bd9 Eric Allman
        return err;
951
}
952
953
int
954 b22be946 Eric Allman
_ep_thr_rwlock_trywrlock(EP_THR_RWLOCK *rwl,
955
                const char *file, int line, const char *name)
956 49c87bd9 Eric Allman
{
957
        int err;
958
959 51775f02 Eric Allman
        TRACE(rwl, "rwlock_tryrwlock");
960 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
961
                return 0;
962
        if ((err = pthread_rwlock_trywrlock(rwl)) != 0)
963 47d57c57 Eric Allman
                diagnose_thr_err(err, "rwlock_trywrlock", file, line, name, rwl);
964 49c87bd9 Eric Allman
        return err;
965
}
966
967
int
968 b22be946 Eric Allman
_ep_thr_rwlock_unlock(EP_THR_RWLOCK *rwl,
969
                const char *file, int line, const char *name)
970 49c87bd9 Eric Allman
{
971
        int err;
972
973 51775f02 Eric Allman
        TRACE(rwl, "rwlock_unlock");
974 49c87bd9 Eric Allman
        if (!_EpThrUsePthreads)
975
                return 0;
976
        if ((err = pthread_rwlock_unlock(rwl)) != 0)
977 47d57c57 Eric Allman
                diagnose_thr_err(err, "rwlock_unlock", file, line, name, rwl);
978 49c87bd9 Eric Allman
        return err;
979
}
980 9f5d76d6 Eric Allman
981
#else // !EP_OSCF_USE_PTHREADS
982
983
void
984
_ep_thr_init(void)
985
{
986
        ep_dbg_printf("WARNING: initializing pthreads, "
987
                        "but pthreads compiled out\n");
988
}
989
990
#endif // EP_OSCF_USE_PTHREADS