171b3fa15SDavid Xu /*
271b3fa15SDavid Xu * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
3d3b15642Szrj * Copyright (c) 2006 David Xu <davidxu@freebsd.org>.
471b3fa15SDavid Xu * All rights reserved.
571b3fa15SDavid Xu *
671b3fa15SDavid Xu * Redistribution and use in source and binary forms, with or without
771b3fa15SDavid Xu * modification, are permitted provided that the following conditions
871b3fa15SDavid Xu * are met:
971b3fa15SDavid Xu * 1. Redistributions of source code must retain the above copyright
1071b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer.
1171b3fa15SDavid Xu * 2. Redistributions in binary form must reproduce the above copyright
1271b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer in the
1371b3fa15SDavid Xu * documentation and/or other materials provided with the distribution.
1471b3fa15SDavid Xu * 3. All advertising materials mentioning features or use of this software
1571b3fa15SDavid Xu * must display the following acknowledgement:
1671b3fa15SDavid Xu * This product includes software developed by John Birrell.
1771b3fa15SDavid Xu * 4. Neither the name of the author nor the names of any co-contributors
1871b3fa15SDavid Xu * may be used to endorse or promote products derived from this software
1971b3fa15SDavid Xu * without specific prior written permission.
2071b3fa15SDavid Xu *
2171b3fa15SDavid Xu * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
2271b3fa15SDavid Xu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2371b3fa15SDavid Xu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2471b3fa15SDavid Xu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2571b3fa15SDavid Xu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2671b3fa15SDavid Xu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2771b3fa15SDavid Xu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2871b3fa15SDavid Xu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2971b3fa15SDavid Xu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3071b3fa15SDavid Xu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3171b3fa15SDavid Xu * SUCH DAMAGE.
3271b3fa15SDavid Xu *
3371b3fa15SDavid Xu */
349e2ee207SJoerg Sonnenberger
35fc71f871SDavid Xu #include "namespace.h"
369e2ee207SJoerg Sonnenberger #include <machine/tls.h>
3771b3fa15SDavid Xu #include <errno.h>
38fc71f871SDavid Xu #include <stdlib.h>
3971b3fa15SDavid Xu #include <string.h>
4071b3fa15SDavid Xu #include <sys/queue.h>
4171b3fa15SDavid Xu #include <pthread.h>
42fc71f871SDavid Xu #include "un-namespace.h"
43fc71f871SDavid Xu
4471b3fa15SDavid Xu #include "thr_private.h"
4571b3fa15SDavid Xu
46fcaa7a3aSMatthew Dillon #ifdef _PTHREADS_DEBUGGING
47fcaa7a3aSMatthew Dillon
48fcaa7a3aSMatthew Dillon #include <stdio.h>
49fcaa7a3aSMatthew Dillon #include <stdarg.h>
50fcaa7a3aSMatthew Dillon #include <sys/file.h>
51fcaa7a3aSMatthew Dillon
52fcaa7a3aSMatthew Dillon #endif
53fcaa7a3aSMatthew Dillon
5471b3fa15SDavid Xu #if defined(_PTHREADS_INVARIANTS)
5571b3fa15SDavid Xu #define MUTEX_INIT_LINK(m) do { \
5671b3fa15SDavid Xu (m)->m_qe.tqe_prev = NULL; \
5771b3fa15SDavid Xu (m)->m_qe.tqe_next = NULL; \
5871b3fa15SDavid Xu } while (0)
5971b3fa15SDavid Xu #define MUTEX_ASSERT_IS_OWNED(m) do { \
6071b3fa15SDavid Xu if ((m)->m_qe.tqe_prev == NULL) \
6171b3fa15SDavid Xu PANIC("mutex is not on list"); \
6271b3fa15SDavid Xu } while (0)
6371b3fa15SDavid Xu #define MUTEX_ASSERT_NOT_OWNED(m) do { \
6471b3fa15SDavid Xu if (((m)->m_qe.tqe_prev != NULL) || \
6571b3fa15SDavid Xu ((m)->m_qe.tqe_next != NULL)) \
6671b3fa15SDavid Xu PANIC("mutex is on list"); \
6771b3fa15SDavid Xu } while (0)
6871b3fa15SDavid Xu #define THR_ASSERT_NOT_IN_SYNCQ(thr) do { \
6971b3fa15SDavid Xu THR_ASSERT(((thr)->sflags & THR_FLAGS_IN_SYNCQ) == 0, \
7071b3fa15SDavid Xu "thread in syncq when it shouldn't be."); \
7171b3fa15SDavid Xu } while (0);
7271b3fa15SDavid Xu #else
7371b3fa15SDavid Xu #define MUTEX_INIT_LINK(m)
7471b3fa15SDavid Xu #define MUTEX_ASSERT_IS_OWNED(m)
7571b3fa15SDavid Xu #define MUTEX_ASSERT_NOT_OWNED(m)
7671b3fa15SDavid Xu #define THR_ASSERT_NOT_IN_SYNCQ(thr)
7771b3fa15SDavid Xu #endif
7871b3fa15SDavid Xu
7971b3fa15SDavid Xu #define THR_IN_MUTEXQ(thr) (((thr)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
8071b3fa15SDavid Xu #define MUTEX_DESTROY(m) do { \
81e7bf3f77SMatthew Dillon __free(m); \
8271b3fa15SDavid Xu } while (0)
8371b3fa15SDavid Xu
84e8382b15SDavid Xu umtx_t _mutex_static_lock;
8571b3fa15SDavid Xu
86fcaa7a3aSMatthew Dillon #ifdef _PTHREADS_DEBUGGING
87fcaa7a3aSMatthew Dillon
88fcaa7a3aSMatthew Dillon static
89fcaa7a3aSMatthew Dillon void
mutex_log(const char * ctl,...)90fcaa7a3aSMatthew Dillon mutex_log(const char *ctl, ...)
91fcaa7a3aSMatthew Dillon {
92fcaa7a3aSMatthew Dillon char buf[256];
93fcaa7a3aSMatthew Dillon va_list va;
94fcaa7a3aSMatthew Dillon size_t len;
95fcaa7a3aSMatthew Dillon
96fcaa7a3aSMatthew Dillon va_start(va, ctl);
97fcaa7a3aSMatthew Dillon len = vsnprintf(buf, sizeof(buf), ctl, va);
98fcaa7a3aSMatthew Dillon va_end(va);
99fcaa7a3aSMatthew Dillon _thr_log(buf, len);
100fcaa7a3aSMatthew Dillon }
101fcaa7a3aSMatthew Dillon
102fcaa7a3aSMatthew Dillon #else
103fcaa7a3aSMatthew Dillon
104fcaa7a3aSMatthew Dillon static __inline
105fcaa7a3aSMatthew Dillon void
mutex_log(const char * ctl __unused,...)106fcaa7a3aSMatthew Dillon mutex_log(const char *ctl __unused, ...)
107fcaa7a3aSMatthew Dillon {
108fcaa7a3aSMatthew Dillon }
109fcaa7a3aSMatthew Dillon
110fcaa7a3aSMatthew Dillon #endif
111fcaa7a3aSMatthew Dillon
112fcaa7a3aSMatthew Dillon #ifdef _PTHREADS_DEBUGGING2
113fcaa7a3aSMatthew Dillon
114fcaa7a3aSMatthew Dillon static void
mutex_log2(pthread_t curthread,pthread_mutex_t m,int op)115940be950Szrj mutex_log2(pthread_t curthread, pthread_mutex_t m, int op)
116fcaa7a3aSMatthew Dillon {
117fcaa7a3aSMatthew Dillon if (curthread) {
118fcaa7a3aSMatthew Dillon if (curthread->tid < 32)
119fcaa7a3aSMatthew Dillon m->m_lastop[curthread->tid] =
120fcaa7a3aSMatthew Dillon (__sys_getpid() << 16) | op;
121fcaa7a3aSMatthew Dillon } else {
122fcaa7a3aSMatthew Dillon m->m_lastop[0] =
123fcaa7a3aSMatthew Dillon (__sys_getpid() << 16) | op;
124fcaa7a3aSMatthew Dillon }
125fcaa7a3aSMatthew Dillon }
126fcaa7a3aSMatthew Dillon
127fcaa7a3aSMatthew Dillon #else
128fcaa7a3aSMatthew Dillon
129fcaa7a3aSMatthew Dillon static __inline
130fcaa7a3aSMatthew Dillon void
mutex_log2(pthread_t curthread __unused,pthread_mutex_t m __unused,int op __unused)131940be950Szrj mutex_log2(pthread_t curthread __unused,
132940be950Szrj pthread_mutex_t m __unused, int op __unused)
133fcaa7a3aSMatthew Dillon {
134fcaa7a3aSMatthew Dillon }
135fcaa7a3aSMatthew Dillon
136fcaa7a3aSMatthew Dillon #endif
137fcaa7a3aSMatthew Dillon
13871b3fa15SDavid Xu /*
13971b3fa15SDavid Xu * Prototypes
14071b3fa15SDavid Xu */
141fc71f871SDavid Xu static int mutex_self_trylock(pthread_mutex_t);
142fc71f871SDavid Xu static int mutex_self_lock(pthread_mutex_t,
14371b3fa15SDavid Xu const struct timespec *abstime);
144f84e38f4SDavid Xu static int mutex_unlock_common(pthread_mutex_t *);
14571b3fa15SDavid Xu
146fc71f871SDavid Xu int __pthread_mutex_init(pthread_mutex_t *mutex,
147fc71f871SDavid Xu const pthread_mutexattr_t *mutex_attr);
148fc71f871SDavid Xu int __pthread_mutex_trylock(pthread_mutex_t *mutex);
149fc71f871SDavid Xu int __pthread_mutex_lock(pthread_mutex_t *mutex);
150fc71f871SDavid Xu int __pthread_mutex_timedlock(pthread_mutex_t *mutex,
151fc71f871SDavid Xu const struct timespec *abs_timeout);
152fc71f871SDavid Xu
15371b3fa15SDavid Xu static int
mutex_check_attr(const struct __pthread_mutexattr_s * attr)154*cf8046a9Szrj mutex_check_attr(const struct __pthread_mutexattr_s *attr)
15571b3fa15SDavid Xu {
156113768d8SDavid Xu if (attr->m_type < PTHREAD_MUTEX_ERRORCHECK ||
157b8ee06c5Szrj attr->m_type >= PTHREAD_MUTEX_TYPE_MAX)
158113768d8SDavid Xu return (EINVAL);
159113768d8SDavid Xu if (attr->m_protocol < PTHREAD_PRIO_NONE ||
160113768d8SDavid Xu attr->m_protocol > PTHREAD_PRIO_PROTECT)
161113768d8SDavid Xu return (EINVAL);
162a1f9998fSzrj return (0);
16371b3fa15SDavid Xu }
164113768d8SDavid Xu
165a1f9998fSzrj static void
mutex_init_body(pthread_mutex_t pmutex,const struct __pthread_mutexattr_s * attr,int private)166*cf8046a9Szrj mutex_init_body(pthread_mutex_t pmutex,
167*cf8046a9Szrj const struct __pthread_mutexattr_s *attr, int private)
168a1f9998fSzrj {
169113768d8SDavid Xu _thr_umtx_init(&pmutex->m_lock);
170113768d8SDavid Xu pmutex->m_type = attr->m_type;
171113768d8SDavid Xu pmutex->m_protocol = attr->m_protocol;
17271b3fa15SDavid Xu TAILQ_INIT(&pmutex->m_queue);
173fcaa7a3aSMatthew Dillon mutex_log2(tls_get_curthread(), pmutex, 32);
174113768d8SDavid Xu pmutex->m_owner = NULL;
175113768d8SDavid Xu pmutex->m_flags = attr->m_flags | MUTEX_FLAGS_INITED;
17671b3fa15SDavid Xu if (private)
17771b3fa15SDavid Xu pmutex->m_flags |= MUTEX_FLAGS_PRIVATE;
178113768d8SDavid Xu pmutex->m_count = 0;
17971b3fa15SDavid Xu pmutex->m_refcount = 0;
180113768d8SDavid Xu if (attr->m_protocol == PTHREAD_PRIO_PROTECT)
181113768d8SDavid Xu pmutex->m_prio = attr->m_ceiling;
18271b3fa15SDavid Xu else
18371b3fa15SDavid Xu pmutex->m_prio = -1;
18471b3fa15SDavid Xu pmutex->m_saved_prio = 0;
18571b3fa15SDavid Xu MUTEX_INIT_LINK(pmutex);
186a1f9998fSzrj }
187a1f9998fSzrj
188a1f9998fSzrj static int
mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t * mutex_attr,int private)189a1f9998fSzrj mutex_init(pthread_mutex_t *mutex,
190a1f9998fSzrj const pthread_mutexattr_t *mutex_attr, int private)
191a1f9998fSzrj {
192*cf8046a9Szrj const struct __pthread_mutexattr_s *attr;
193*cf8046a9Szrj pthread_mutex_t pmutex;
194a1f9998fSzrj int error;
195a1f9998fSzrj
196a1f9998fSzrj if (mutex_attr == NULL) {
197a1f9998fSzrj attr = &_pthread_mutexattr_default;
198a1f9998fSzrj } else {
199a1f9998fSzrj attr = *mutex_attr;
200a1f9998fSzrj error = mutex_check_attr(attr);
201a1f9998fSzrj if (error != 0)
202a1f9998fSzrj return (error);
203a1f9998fSzrj }
204e7bf3f77SMatthew Dillon
205*cf8046a9Szrj pmutex = __malloc(sizeof(struct __pthread_mutex_s));
206e7bf3f77SMatthew Dillon if (pmutex == NULL)
207a1f9998fSzrj return (ENOMEM);
208a1f9998fSzrj mutex_init_body(pmutex, attr, private);
20971b3fa15SDavid Xu *mutex = pmutex;
210113768d8SDavid Xu return (0);
21171b3fa15SDavid Xu }
21271b3fa15SDavid Xu
21371b3fa15SDavid Xu static int
init_static(pthread_t thread,pthread_mutex_t * mutex)214940be950Szrj init_static(pthread_t thread, pthread_mutex_t *mutex)
21571b3fa15SDavid Xu {
21671b3fa15SDavid Xu int ret;
21771b3fa15SDavid Xu
21871b3fa15SDavid Xu THR_LOCK_ACQUIRE(thread, &_mutex_static_lock);
21971b3fa15SDavid Xu
22071b3fa15SDavid Xu if (*mutex == NULL)
22171b3fa15SDavid Xu ret = mutex_init(mutex, NULL, 0);
22271b3fa15SDavid Xu else
22371b3fa15SDavid Xu ret = 0;
22471b3fa15SDavid Xu THR_LOCK_RELEASE(thread, &_mutex_static_lock);
22571b3fa15SDavid Xu
22671b3fa15SDavid Xu return (ret);
22771b3fa15SDavid Xu }
22871b3fa15SDavid Xu
22971b3fa15SDavid Xu static int
init_static_private(pthread_t thread,pthread_mutex_t * mutex)230940be950Szrj init_static_private(pthread_t thread, pthread_mutex_t *mutex)
23171b3fa15SDavid Xu {
23271b3fa15SDavid Xu int ret;
23371b3fa15SDavid Xu
23471b3fa15SDavid Xu THR_LOCK_ACQUIRE(thread, &_mutex_static_lock);
23571b3fa15SDavid Xu
23671b3fa15SDavid Xu if (*mutex == NULL)
23771b3fa15SDavid Xu ret = mutex_init(mutex, NULL, 1);
23871b3fa15SDavid Xu else
23971b3fa15SDavid Xu ret = 0;
24071b3fa15SDavid Xu
24171b3fa15SDavid Xu THR_LOCK_RELEASE(thread, &_mutex_static_lock);
24271b3fa15SDavid Xu
24371b3fa15SDavid Xu return (ret);
24471b3fa15SDavid Xu }
24571b3fa15SDavid Xu
24671b3fa15SDavid Xu int
_pthread_mutex_init(pthread_mutex_t * __restrict mutex,const pthread_mutexattr_t * __restrict mutex_attr)247d33005aaSSascha Wildner _pthread_mutex_init(pthread_mutex_t * __restrict mutex,
248d33005aaSSascha Wildner const pthread_mutexattr_t * __restrict mutex_attr)
24971b3fa15SDavid Xu {
25071b3fa15SDavid Xu return mutex_init(mutex, mutex_attr, 1);
25171b3fa15SDavid Xu }
25271b3fa15SDavid Xu
25371b3fa15SDavid Xu int
__pthread_mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t * mutex_attr)25471b3fa15SDavid Xu __pthread_mutex_init(pthread_mutex_t *mutex,
25571b3fa15SDavid Xu const pthread_mutexattr_t *mutex_attr)
25671b3fa15SDavid Xu {
25771b3fa15SDavid Xu return mutex_init(mutex, mutex_attr, 0);
25871b3fa15SDavid Xu }
25971b3fa15SDavid Xu
260fcaa7a3aSMatthew Dillon #if 0
26171b3fa15SDavid Xu int
262fcaa7a3aSMatthew Dillon _mutex_reinit(pthread_mutex_t *mutexp)
26371b3fa15SDavid Xu {
264fcaa7a3aSMatthew Dillon pthread_mutex_t mutex = *mutexp;
265fcaa7a3aSMatthew Dillon
266fcaa7a3aSMatthew Dillon _thr_umtx_init(&mutex->m_lock);
267fcaa7a3aSMatthew Dillon TAILQ_INIT(&mutex->m_queue);
268fcaa7a3aSMatthew Dillon MUTEX_INIT_LINK(mutex);
269fcaa7a3aSMatthew Dillon mutex_log2(tls_get_curthread(), mutex, 33);
270fcaa7a3aSMatthew Dillon mutex->m_owner = NULL;
271fcaa7a3aSMatthew Dillon mutex->m_count = 0;
272fcaa7a3aSMatthew Dillon mutex->m_refcount = 0;
273fcaa7a3aSMatthew Dillon mutex->m_prio = 0;
274fcaa7a3aSMatthew Dillon mutex->m_saved_prio = 0;
275fcaa7a3aSMatthew Dillon
27671b3fa15SDavid Xu return (0);
27771b3fa15SDavid Xu }
278fcaa7a3aSMatthew Dillon #endif
27971b3fa15SDavid Xu
28071b3fa15SDavid Xu void
_mutex_fork(pthread_t curthread,lwpid_t tid)281940be950Szrj _mutex_fork(pthread_t curthread, lwpid_t tid)
28271b3fa15SDavid Xu {
283940be950Szrj pthread_mutex_t m;
28471b3fa15SDavid Xu
28571b3fa15SDavid Xu TAILQ_FOREACH(m, &curthread->mutexq, m_qe)
2864cc8110fSMatthew Dillon m->m_lock = tid;
28771b3fa15SDavid Xu }
28871b3fa15SDavid Xu
28971b3fa15SDavid Xu int
_pthread_mutex_destroy(pthread_mutex_t * mutex)29071b3fa15SDavid Xu _pthread_mutex_destroy(pthread_mutex_t *mutex)
29171b3fa15SDavid Xu {
292940be950Szrj pthread_t curthread = tls_get_curthread();
29371b3fa15SDavid Xu pthread_mutex_t m;
29471b3fa15SDavid Xu int ret = 0;
29571b3fa15SDavid Xu
296fcaa7a3aSMatthew Dillon if (mutex == NULL) {
29771b3fa15SDavid Xu ret = EINVAL;
298fcaa7a3aSMatthew Dillon } else if (*mutex == NULL) {
299146da5fcSMichael Neumann ret = 0;
300fcaa7a3aSMatthew Dillon } else {
30171b3fa15SDavid Xu /*
30271b3fa15SDavid Xu * Try to lock the mutex structure, we only need to
303fcaa7a3aSMatthew Dillon * try once, if failed, the mutex is in use.
30471b3fa15SDavid Xu */
305721505deSMatthew Dillon ret = THR_UMTX_TRYLOCK_PERSIST(curthread, &(*mutex)->m_lock);
30671b3fa15SDavid Xu if (ret)
30771b3fa15SDavid Xu return (ret);
30871b3fa15SDavid Xu
30971b3fa15SDavid Xu /*
31071b3fa15SDavid Xu * Check mutex other fields to see if this mutex is
31171b3fa15SDavid Xu * in use. Mostly for prority mutex types, or there
31271b3fa15SDavid Xu * are condition variables referencing it.
31371b3fa15SDavid Xu */
31471b3fa15SDavid Xu if (((*mutex)->m_owner != NULL) ||
31571b3fa15SDavid Xu (TAILQ_FIRST(&(*mutex)->m_queue) != NULL) ||
31671b3fa15SDavid Xu ((*mutex)->m_refcount != 0)) {
317721505deSMatthew Dillon THR_UMTX_UNLOCK_PERSIST(curthread, &(*mutex)->m_lock);
31871b3fa15SDavid Xu ret = EBUSY;
31971b3fa15SDavid Xu } else {
32071b3fa15SDavid Xu /*
32171b3fa15SDavid Xu * Save a pointer to the mutex so it can be free'd
32271b3fa15SDavid Xu * and set the caller's pointer to NULL:
32371b3fa15SDavid Xu */
32471b3fa15SDavid Xu m = *mutex;
32571b3fa15SDavid Xu *mutex = NULL;
32671b3fa15SDavid Xu
32771b3fa15SDavid Xu /* Unlock the mutex structure: */
328721505deSMatthew Dillon THR_UMTX_UNLOCK_PERSIST(curthread, &m->m_lock);
32971b3fa15SDavid Xu
33071b3fa15SDavid Xu /*
33171b3fa15SDavid Xu * Free the memory allocated for the mutex
33271b3fa15SDavid Xu * structure:
33371b3fa15SDavid Xu */
33471b3fa15SDavid Xu MUTEX_ASSERT_NOT_OWNED(m);
33571b3fa15SDavid Xu MUTEX_DESTROY(m);
33671b3fa15SDavid Xu }
33771b3fa15SDavid Xu }
33871b3fa15SDavid Xu
33971b3fa15SDavid Xu /* Return the completion status: */
34071b3fa15SDavid Xu return (ret);
34171b3fa15SDavid Xu }
34271b3fa15SDavid Xu
34371b3fa15SDavid Xu static int
mutex_trylock_common(pthread_t curthread,pthread_mutex_t * mutex)344940be950Szrj mutex_trylock_common(pthread_t curthread, pthread_mutex_t *mutex)
34571b3fa15SDavid Xu {
346940be950Szrj pthread_mutex_t m;
347a4472baeSDavid Xu int ret;
34871b3fa15SDavid Xu
349a4472baeSDavid Xu m = *mutex;
350fcaa7a3aSMatthew Dillon mutex_log("mutex_lock_trylock_common %p\n", m);
351721505deSMatthew Dillon ret = THR_UMTX_TRYLOCK_PERSIST(curthread, &m->m_lock);
35271b3fa15SDavid Xu if (ret == 0) {
353fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 1);
354a4472baeSDavid Xu m->m_owner = curthread;
35571b3fa15SDavid Xu /* Add to the list of owned mutexes: */
356a4472baeSDavid Xu MUTEX_ASSERT_NOT_OWNED(m);
357fcaa7a3aSMatthew Dillon TAILQ_INSERT_TAIL(&curthread->mutexq, m, m_qe);
358a4472baeSDavid Xu } else if (m->m_owner == curthread) {
359fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 2);
360a4472baeSDavid Xu ret = mutex_self_trylock(m);
36171b3fa15SDavid Xu } /* else {} */
362fcaa7a3aSMatthew Dillon mutex_log("mutex_lock_trylock_common %p (returns %d)\n", m, ret);
36371b3fa15SDavid Xu
36471b3fa15SDavid Xu return (ret);
36571b3fa15SDavid Xu }
36671b3fa15SDavid Xu
36771b3fa15SDavid Xu int
__pthread_mutex_trylock(pthread_mutex_t * m)368a4472baeSDavid Xu __pthread_mutex_trylock(pthread_mutex_t *m)
36971b3fa15SDavid Xu {
370940be950Szrj pthread_t curthread = tls_get_curthread();
371a4472baeSDavid Xu int ret;
37271b3fa15SDavid Xu
3738db03831SMatthew Dillon if (__predict_false(m == NULL))
3748db03831SMatthew Dillon return(EINVAL);
37571b3fa15SDavid Xu /*
37671b3fa15SDavid Xu * If the mutex is statically initialized, perform the dynamic
37771b3fa15SDavid Xu * initialization:
37871b3fa15SDavid Xu */
379a4472baeSDavid Xu if (__predict_false(*m == NULL)) {
380a4472baeSDavid Xu ret = init_static(curthread, m);
381f84e38f4SDavid Xu if (__predict_false(ret != 0))
38271b3fa15SDavid Xu return (ret);
38371b3fa15SDavid Xu }
384a4472baeSDavid Xu return (mutex_trylock_common(curthread, m));
385a4472baeSDavid Xu }
38671b3fa15SDavid Xu
38771b3fa15SDavid Xu int
_pthread_mutex_trylock(pthread_mutex_t * m)388a4472baeSDavid Xu _pthread_mutex_trylock(pthread_mutex_t *m)
38971b3fa15SDavid Xu {
390940be950Szrj pthread_t curthread = tls_get_curthread();
39171b3fa15SDavid Xu int ret = 0;
39271b3fa15SDavid Xu
39371b3fa15SDavid Xu /*
39471b3fa15SDavid Xu * If the mutex is statically initialized, perform the dynamic
39571b3fa15SDavid Xu * initialization marking the mutex private (delete safe):
39671b3fa15SDavid Xu */
397a4472baeSDavid Xu if (__predict_false(*m == NULL)) {
398a4472baeSDavid Xu ret = init_static_private(curthread, m);
399f84e38f4SDavid Xu if (__predict_false(ret != 0))
40071b3fa15SDavid Xu return (ret);
40171b3fa15SDavid Xu }
402a4472baeSDavid Xu return (mutex_trylock_common(curthread, m));
403a4472baeSDavid Xu }
40471b3fa15SDavid Xu
40571b3fa15SDavid Xu static int
mutex_lock_common(pthread_t curthread,pthread_mutex_t * mutex,const struct timespec * abstime)406940be950Szrj mutex_lock_common(pthread_t curthread, pthread_mutex_t *mutex,
40771b3fa15SDavid Xu const struct timespec * abstime)
40871b3fa15SDavid Xu {
40971b3fa15SDavid Xu struct timespec ts, ts2;
410940be950Szrj pthread_mutex_t m;
41171b3fa15SDavid Xu int ret = 0;
41271b3fa15SDavid Xu
413a4472baeSDavid Xu m = *mutex;
414fcaa7a3aSMatthew Dillon mutex_log("mutex_lock_common %p\n", m);
415721505deSMatthew Dillon ret = THR_UMTX_TRYLOCK_PERSIST(curthread, &m->m_lock);
41671b3fa15SDavid Xu if (ret == 0) {
417fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 3);
418a4472baeSDavid Xu m->m_owner = curthread;
41971b3fa15SDavid Xu /* Add to the list of owned mutexes: */
420a4472baeSDavid Xu MUTEX_ASSERT_NOT_OWNED(m);
421fcaa7a3aSMatthew Dillon TAILQ_INSERT_TAIL(&curthread->mutexq, m, m_qe);
422a4472baeSDavid Xu } else if (m->m_owner == curthread) {
423a4472baeSDavid Xu ret = mutex_self_lock(m, abstime);
42471b3fa15SDavid Xu } else {
42571b3fa15SDavid Xu if (abstime == NULL) {
426721505deSMatthew Dillon THR_UMTX_LOCK_PERSIST(curthread, &m->m_lock);
42771b3fa15SDavid Xu ret = 0;
428a4472baeSDavid Xu } else if (__predict_false(
429a4472baeSDavid Xu abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
430a4472baeSDavid Xu abstime->tv_nsec >= 1000000000)) {
431a4472baeSDavid Xu ret = EINVAL;
43271b3fa15SDavid Xu } else {
43371b3fa15SDavid Xu clock_gettime(CLOCK_REALTIME, &ts);
434ce96aca2SSascha Wildner timespecsub(abstime, &ts, &ts2);
435721505deSMatthew Dillon ret = THR_UMTX_TIMEDLOCK_PERSIST(curthread,
436721505deSMatthew Dillon &m->m_lock, &ts2);
43771b3fa15SDavid Xu }
43871b3fa15SDavid Xu if (ret == 0) {
439fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 4);
440a4472baeSDavid Xu m->m_owner = curthread;
44171b3fa15SDavid Xu /* Add to the list of owned mutexes: */
442a4472baeSDavid Xu MUTEX_ASSERT_NOT_OWNED(m);
443fcaa7a3aSMatthew Dillon TAILQ_INSERT_TAIL(&curthread->mutexq, m, m_qe);
44471b3fa15SDavid Xu }
44571b3fa15SDavid Xu }
446fcaa7a3aSMatthew Dillon mutex_log("mutex_lock_common %p (returns %d) lock %d,%d\n",
447fcaa7a3aSMatthew Dillon m, ret, m->m_lock, m->m_count);
44871b3fa15SDavid Xu return (ret);
44971b3fa15SDavid Xu }
45071b3fa15SDavid Xu
45171b3fa15SDavid Xu int
__pthread_mutex_lock(pthread_mutex_t * m)45271b3fa15SDavid Xu __pthread_mutex_lock(pthread_mutex_t *m)
45371b3fa15SDavid Xu {
454940be950Szrj pthread_t curthread;
455a4472baeSDavid Xu int ret;
45671b3fa15SDavid Xu
4578db03831SMatthew Dillon if (__predict_false(m == NULL))
4588db03831SMatthew Dillon return(EINVAL);
45971b3fa15SDavid Xu
46071b3fa15SDavid Xu /*
46171b3fa15SDavid Xu * If the mutex is statically initialized, perform the dynamic
46271b3fa15SDavid Xu * initialization:
46371b3fa15SDavid Xu */
4648db03831SMatthew Dillon curthread = tls_get_curthread();
465a4472baeSDavid Xu if (__predict_false(*m == NULL)) {
466a4472baeSDavid Xu ret = init_static(curthread, m);
467a4472baeSDavid Xu if (__predict_false(ret))
46871b3fa15SDavid Xu return (ret);
46971b3fa15SDavid Xu }
470a4472baeSDavid Xu return (mutex_lock_common(curthread, m, NULL));
471a4472baeSDavid Xu }
47271b3fa15SDavid Xu
47371b3fa15SDavid Xu int
_pthread_mutex_lock(pthread_mutex_t * m)47471b3fa15SDavid Xu _pthread_mutex_lock(pthread_mutex_t *m)
47571b3fa15SDavid Xu {
476940be950Szrj pthread_t curthread;
477a4472baeSDavid Xu int ret;
47871b3fa15SDavid Xu
4798b03c2a2Szrj _thr_check_init();
4808b03c2a2Szrj
4818db03831SMatthew Dillon if (__predict_false(m == NULL))
4828db03831SMatthew Dillon return(EINVAL);
48371b3fa15SDavid Xu
48471b3fa15SDavid Xu /*
48571b3fa15SDavid Xu * If the mutex is statically initialized, perform the dynamic
48671b3fa15SDavid Xu * initialization marking it private (delete safe):
48771b3fa15SDavid Xu */
4888db03831SMatthew Dillon curthread = tls_get_curthread();
489a4472baeSDavid Xu if (__predict_false(*m == NULL)) {
490a4472baeSDavid Xu ret = init_static_private(curthread, m);
491a4472baeSDavid Xu if (__predict_false(ret))
49271b3fa15SDavid Xu return (ret);
49371b3fa15SDavid Xu }
494a4472baeSDavid Xu return (mutex_lock_common(curthread, m, NULL));
495a4472baeSDavid Xu }
49671b3fa15SDavid Xu
49771b3fa15SDavid Xu int
__pthread_mutex_timedlock(pthread_mutex_t * __restrict m,const struct timespec * __restrict abs_timeout)498d33005aaSSascha Wildner __pthread_mutex_timedlock(pthread_mutex_t * __restrict m,
499d33005aaSSascha Wildner const struct timespec * __restrict abs_timeout)
50071b3fa15SDavid Xu {
501940be950Szrj pthread_t curthread;
502a4472baeSDavid Xu int ret;
50371b3fa15SDavid Xu
5048b03c2a2Szrj _thr_check_init();
5058b03c2a2Szrj
5068db03831SMatthew Dillon if (__predict_false(m == NULL))
5078db03831SMatthew Dillon return(EINVAL);
50871b3fa15SDavid Xu
50971b3fa15SDavid Xu /*
51071b3fa15SDavid Xu * If the mutex is statically initialized, perform the dynamic
51171b3fa15SDavid Xu * initialization:
51271b3fa15SDavid Xu */
5138db03831SMatthew Dillon curthread = tls_get_curthread();
514a4472baeSDavid Xu if (__predict_false(*m == NULL)) {
515a4472baeSDavid Xu ret = init_static(curthread, m);
516a4472baeSDavid Xu if (__predict_false(ret))
51771b3fa15SDavid Xu return (ret);
51871b3fa15SDavid Xu }
519a4472baeSDavid Xu return (mutex_lock_common(curthread, m, abs_timeout));
520a4472baeSDavid Xu }
52171b3fa15SDavid Xu
52271b3fa15SDavid Xu int
_pthread_mutex_timedlock(pthread_mutex_t * m,const struct timespec * abs_timeout)52371b3fa15SDavid Xu _pthread_mutex_timedlock(pthread_mutex_t *m,
52471b3fa15SDavid Xu const struct timespec *abs_timeout)
52571b3fa15SDavid Xu {
526940be950Szrj pthread_t curthread;
527a4472baeSDavid Xu int ret;
52871b3fa15SDavid Xu
5298db03831SMatthew Dillon if (__predict_false(m == NULL))
5308db03831SMatthew Dillon return(EINVAL);
5318db03831SMatthew Dillon
5329e2ee207SJoerg Sonnenberger curthread = tls_get_curthread();
53371b3fa15SDavid Xu
53471b3fa15SDavid Xu /*
53571b3fa15SDavid Xu * If the mutex is statically initialized, perform the dynamic
53671b3fa15SDavid Xu * initialization marking it private (delete safe):
53771b3fa15SDavid Xu */
538a4472baeSDavid Xu if (__predict_false(*m == NULL)) {
539a4472baeSDavid Xu ret = init_static_private(curthread, m);
540a4472baeSDavid Xu if (__predict_false(ret))
54171b3fa15SDavid Xu return (ret);
54271b3fa15SDavid Xu }
543a4472baeSDavid Xu return (mutex_lock_common(curthread, m, abs_timeout));
544a4472baeSDavid Xu }
54571b3fa15SDavid Xu
54671b3fa15SDavid Xu int
_pthread_mutex_unlock(pthread_mutex_t * m)54771b3fa15SDavid Xu _pthread_mutex_unlock(pthread_mutex_t *m)
54871b3fa15SDavid Xu {
5498db03831SMatthew Dillon if (__predict_false(m == NULL))
5508db03831SMatthew Dillon return(EINVAL);
551f84e38f4SDavid Xu return (mutex_unlock_common(m));
55271b3fa15SDavid Xu }
55371b3fa15SDavid Xu
55471b3fa15SDavid Xu static int
mutex_self_trylock(pthread_mutex_t m)555fc71f871SDavid Xu mutex_self_trylock(pthread_mutex_t m)
55671b3fa15SDavid Xu {
55771b3fa15SDavid Xu int ret;
55871b3fa15SDavid Xu
55971b3fa15SDavid Xu switch (m->m_type) {
56071b3fa15SDavid Xu /* case PTHREAD_MUTEX_DEFAULT: */
56171b3fa15SDavid Xu case PTHREAD_MUTEX_ERRORCHECK:
56271b3fa15SDavid Xu case PTHREAD_MUTEX_NORMAL:
56371b3fa15SDavid Xu ret = EBUSY;
56471b3fa15SDavid Xu break;
56571b3fa15SDavid Xu
56671b3fa15SDavid Xu case PTHREAD_MUTEX_RECURSIVE:
56771b3fa15SDavid Xu /* Increment the lock count: */
56871b3fa15SDavid Xu if (m->m_count + 1 > 0) {
56971b3fa15SDavid Xu m->m_count++;
57071b3fa15SDavid Xu ret = 0;
57171b3fa15SDavid Xu } else
57271b3fa15SDavid Xu ret = EAGAIN;
57371b3fa15SDavid Xu break;
57471b3fa15SDavid Xu
57571b3fa15SDavid Xu default:
57671b3fa15SDavid Xu /* Trap invalid mutex types; */
57771b3fa15SDavid Xu ret = EINVAL;
57871b3fa15SDavid Xu }
57971b3fa15SDavid Xu
58071b3fa15SDavid Xu return (ret);
58171b3fa15SDavid Xu }
58271b3fa15SDavid Xu
58371b3fa15SDavid Xu static int
mutex_self_lock(pthread_mutex_t m,const struct timespec * abstime)584fc71f871SDavid Xu mutex_self_lock(pthread_mutex_t m, const struct timespec *abstime)
58571b3fa15SDavid Xu {
58671b3fa15SDavid Xu struct timespec ts1, ts2;
58771b3fa15SDavid Xu int ret;
58871b3fa15SDavid Xu
58971b3fa15SDavid Xu switch (m->m_type) {
59071b3fa15SDavid Xu /* case PTHREAD_MUTEX_DEFAULT: */
59171b3fa15SDavid Xu case PTHREAD_MUTEX_ERRORCHECK:
59271b3fa15SDavid Xu if (abstime) {
59371b3fa15SDavid Xu clock_gettime(CLOCK_REALTIME, &ts1);
594ce96aca2SSascha Wildner timespecsub(abstime, &ts1, &ts2);
59571b3fa15SDavid Xu __sys_nanosleep(&ts2, NULL);
59671b3fa15SDavid Xu ret = ETIMEDOUT;
59771b3fa15SDavid Xu } else {
59871b3fa15SDavid Xu /*
59971b3fa15SDavid Xu * POSIX specifies that mutexes should return
60071b3fa15SDavid Xu * EDEADLK if a recursive lock is detected.
60171b3fa15SDavid Xu */
60271b3fa15SDavid Xu ret = EDEADLK;
60371b3fa15SDavid Xu }
60471b3fa15SDavid Xu break;
60571b3fa15SDavid Xu
60671b3fa15SDavid Xu case PTHREAD_MUTEX_NORMAL:
60771b3fa15SDavid Xu /*
60871b3fa15SDavid Xu * What SS2 define as a 'normal' mutex. Intentionally
60971b3fa15SDavid Xu * deadlock on attempts to get a lock you already own.
61071b3fa15SDavid Xu */
61171b3fa15SDavid Xu ret = 0;
61271b3fa15SDavid Xu if (abstime) {
61371b3fa15SDavid Xu clock_gettime(CLOCK_REALTIME, &ts1);
614ce96aca2SSascha Wildner timespecsub(abstime, &ts1, &ts2);
61571b3fa15SDavid Xu __sys_nanosleep(&ts2, NULL);
61671b3fa15SDavid Xu ret = ETIMEDOUT;
61771b3fa15SDavid Xu } else {
61871b3fa15SDavid Xu ts1.tv_sec = 30;
61971b3fa15SDavid Xu ts1.tv_nsec = 0;
62071b3fa15SDavid Xu for (;;)
62171b3fa15SDavid Xu __sys_nanosleep(&ts1, NULL);
62271b3fa15SDavid Xu }
62371b3fa15SDavid Xu break;
62471b3fa15SDavid Xu
62571b3fa15SDavid Xu case PTHREAD_MUTEX_RECURSIVE:
62671b3fa15SDavid Xu /* Increment the lock count: */
62771b3fa15SDavid Xu if (m->m_count + 1 > 0) {
62871b3fa15SDavid Xu m->m_count++;
62971b3fa15SDavid Xu ret = 0;
63071b3fa15SDavid Xu } else
63171b3fa15SDavid Xu ret = EAGAIN;
63271b3fa15SDavid Xu break;
63371b3fa15SDavid Xu
63471b3fa15SDavid Xu default:
63571b3fa15SDavid Xu /* Trap invalid mutex types; */
63671b3fa15SDavid Xu ret = EINVAL;
63771b3fa15SDavid Xu }
63871b3fa15SDavid Xu
63971b3fa15SDavid Xu return (ret);
64071b3fa15SDavid Xu }
64171b3fa15SDavid Xu
64271b3fa15SDavid Xu static int
mutex_unlock_common(pthread_mutex_t * mutex)643f84e38f4SDavid Xu mutex_unlock_common(pthread_mutex_t *mutex)
64471b3fa15SDavid Xu {
645940be950Szrj pthread_t curthread = tls_get_curthread();
646940be950Szrj pthread_mutex_t m;
64771b3fa15SDavid Xu
648fcaa7a3aSMatthew Dillon if (__predict_false((m = *mutex) == NULL)) {
649fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 252);
650a8851a0fSDavid Xu return (EINVAL);
651fcaa7a3aSMatthew Dillon }
652fcaa7a3aSMatthew Dillon mutex_log("mutex_unlock_common %p\n", m);
653fcaa7a3aSMatthew Dillon if (__predict_false(m->m_owner != curthread)) {
654fcaa7a3aSMatthew Dillon mutex_log("mutex_unlock_common %p (failedA)\n", m);
655fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 253);
656a8851a0fSDavid Xu return (EPERM);
657fcaa7a3aSMatthew Dillon }
658a8851a0fSDavid Xu
659fcaa7a3aSMatthew Dillon if (__predict_false(m->m_type == PTHREAD_MUTEX_RECURSIVE &&
660a8851a0fSDavid Xu m->m_count > 0)) {
661a8851a0fSDavid Xu m->m_count--;
662fcaa7a3aSMatthew Dillon mutex_log("mutex_unlock_common %p (returns 0, partial)\n", m);
663fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 254);
66471b3fa15SDavid Xu } else {
66571b3fa15SDavid Xu /*
666a8851a0fSDavid Xu * Clear the count in case this is a recursive mutex.
66771b3fa15SDavid Xu */
668a8851a0fSDavid Xu m->m_count = 0;
669a8851a0fSDavid Xu m->m_owner = NULL;
67071b3fa15SDavid Xu /* Remove the mutex from the threads queue. */
671a8851a0fSDavid Xu MUTEX_ASSERT_IS_OWNED(m);
672a8851a0fSDavid Xu TAILQ_REMOVE(&curthread->mutexq, m, m_qe);
673fcaa7a3aSMatthew Dillon mutex_log2(tls_get_curthread(), m, 35);
674a8851a0fSDavid Xu MUTEX_INIT_LINK(m);
675fcaa7a3aSMatthew Dillon mutex_log2(tls_get_curthread(), m, 36);
67671b3fa15SDavid Xu /*
677a8851a0fSDavid Xu * Hand off the mutex to the next waiting thread.
67871b3fa15SDavid Xu */
679fcaa7a3aSMatthew Dillon mutex_log("mutex_unlock_common %p (returns 0) lock %d\n",
680fcaa7a3aSMatthew Dillon m, m->m_lock);
681721505deSMatthew Dillon THR_UMTX_UNLOCK_PERSIST(curthread, &m->m_lock);
682fcaa7a3aSMatthew Dillon mutex_log2(tls_get_curthread(), m, 37);
683fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 255);
684e8382b15SDavid Xu }
685f84e38f4SDavid Xu return (0);
686f84e38f4SDavid Xu }
687f84e38f4SDavid Xu
688f84e38f4SDavid Xu int
_pthread_mutex_getprioceiling(const pthread_mutex_t * __restrict mutex,int * __restrict prioceiling)6893337d96bSSascha Wildner _pthread_mutex_getprioceiling(const pthread_mutex_t * __restrict mutex,
690d33005aaSSascha Wildner int * __restrict prioceiling)
691808e48a1Szrj {
692808e48a1Szrj if ((mutex == NULL) || (*mutex == NULL))
6938979fd9cSzrj return (EINVAL);
6948979fd9cSzrj if ((*mutex)->m_protocol != PTHREAD_PRIO_PROTECT)
6958979fd9cSzrj return (EINVAL);
696808e48a1Szrj *prioceiling = (*mutex)->m_prio;
6978979fd9cSzrj return (0);
698808e48a1Szrj }
699808e48a1Szrj
700808e48a1Szrj int
_pthread_mutex_setprioceiling(pthread_mutex_t * __restrict mutex,int prioceiling,int * __restrict old_ceiling)701d33005aaSSascha Wildner _pthread_mutex_setprioceiling(pthread_mutex_t * __restrict mutex,
702d33005aaSSascha Wildner int prioceiling, int * __restrict old_ceiling)
703808e48a1Szrj {
704808e48a1Szrj int ret = 0;
705808e48a1Szrj int tmp;
706808e48a1Szrj
707808e48a1Szrj if ((mutex == NULL) || (*mutex == NULL))
708808e48a1Szrj ret = EINVAL;
709808e48a1Szrj else if ((*mutex)->m_protocol != PTHREAD_PRIO_PROTECT)
710808e48a1Szrj ret = EINVAL;
711808e48a1Szrj else if ((ret = _pthread_mutex_lock(mutex)) == 0) {
712808e48a1Szrj tmp = (*mutex)->m_prio;
713808e48a1Szrj (*mutex)->m_prio = prioceiling;
714808e48a1Szrj ret = _pthread_mutex_unlock(mutex);
715808e48a1Szrj *old_ceiling = tmp;
716808e48a1Szrj }
717808e48a1Szrj return(ret);
718808e48a1Szrj }
719808e48a1Szrj
720808e48a1Szrj int
_mutex_cv_lock(pthread_mutex_t * m,int count)721f84e38f4SDavid Xu _mutex_cv_lock(pthread_mutex_t *m, int count)
722f84e38f4SDavid Xu {
723f84e38f4SDavid Xu int ret;
724f84e38f4SDavid Xu
725f84e38f4SDavid Xu if ((ret = _pthread_mutex_lock(m)) == 0) {
726f84e38f4SDavid Xu (*m)->m_refcount--;
727f84e38f4SDavid Xu (*m)->m_count += count;
728f84e38f4SDavid Xu }
72971b3fa15SDavid Xu return (ret);
73071b3fa15SDavid Xu }
73171b3fa15SDavid Xu
732f84e38f4SDavid Xu int
_mutex_cv_unlock(pthread_mutex_t * mutex,int * count)733f84e38f4SDavid Xu _mutex_cv_unlock(pthread_mutex_t *mutex, int *count)
734f84e38f4SDavid Xu {
735940be950Szrj pthread_t curthread = tls_get_curthread();
736940be950Szrj pthread_mutex_t m;
737f84e38f4SDavid Xu
7388db03831SMatthew Dillon if (__predict_false(mutex == NULL))
7398db03831SMatthew Dillon return (EINVAL);
740f84e38f4SDavid Xu if (__predict_false((m = *mutex) == NULL))
741f84e38f4SDavid Xu return (EINVAL);
742f84e38f4SDavid Xu if (__predict_false(m->m_owner != curthread))
743f84e38f4SDavid Xu return (EPERM);
744f84e38f4SDavid Xu
745f84e38f4SDavid Xu *count = m->m_count;
746f84e38f4SDavid Xu m->m_count = 0;
747f84e38f4SDavid Xu m->m_refcount++;
748fcaa7a3aSMatthew Dillon mutex_log2(tls_get_curthread(), m, 45);
749f84e38f4SDavid Xu m->m_owner = NULL;
750f84e38f4SDavid Xu /* Remove the mutex from the threads queue. */
751f84e38f4SDavid Xu MUTEX_ASSERT_IS_OWNED(m);
752f84e38f4SDavid Xu TAILQ_REMOVE(&curthread->mutexq, m, m_qe);
753f84e38f4SDavid Xu MUTEX_INIT_LINK(m);
754721505deSMatthew Dillon THR_UMTX_UNLOCK_PERSIST(curthread, &m->m_lock);
755fcaa7a3aSMatthew Dillon mutex_log2(curthread, m, 250);
756f84e38f4SDavid Xu return (0);
757f84e38f4SDavid Xu }
758f84e38f4SDavid Xu
75971b3fa15SDavid Xu void
_mutex_unlock_private(pthread_t pthread)76071b3fa15SDavid Xu _mutex_unlock_private(pthread_t pthread)
76171b3fa15SDavid Xu {
762940be950Szrj pthread_mutex_t m, m_next;
76371b3fa15SDavid Xu
764e8382b15SDavid Xu for (m = TAILQ_FIRST(&pthread->mutexq); m != NULL; m = m_next) {
76571b3fa15SDavid Xu m_next = TAILQ_NEXT(m, m_qe);
76671b3fa15SDavid Xu if ((m->m_flags & MUTEX_FLAGS_PRIVATE) != 0)
767fc71f871SDavid Xu _pthread_mutex_unlock(&m);
76871b3fa15SDavid Xu }
76971b3fa15SDavid Xu }
77071b3fa15SDavid Xu
7715a1048c8SDavid Xu __strong_reference(__pthread_mutex_init, pthread_mutex_init);
7725a1048c8SDavid Xu __strong_reference(__pthread_mutex_lock, pthread_mutex_lock);
7735a1048c8SDavid Xu __strong_reference(__pthread_mutex_timedlock, pthread_mutex_timedlock);
7745a1048c8SDavid Xu __strong_reference(__pthread_mutex_trylock, pthread_mutex_trylock);
7755a1048c8SDavid Xu
7765a1048c8SDavid Xu /* Single underscore versions provided for libc internal usage: */
7775a1048c8SDavid Xu /* No difference between libc and application usage of these: */
7785a1048c8SDavid Xu __strong_reference(_pthread_mutex_destroy, pthread_mutex_destroy);
7795a1048c8SDavid Xu __strong_reference(_pthread_mutex_unlock, pthread_mutex_unlock);
780808e48a1Szrj __strong_reference(_pthread_mutex_getprioceiling, pthread_mutex_getprioceiling);
781808e48a1Szrj __strong_reference(_pthread_mutex_setprioceiling, pthread_mutex_setprioceiling);
782