thr_umtx.c revision 178647
1144518Sdavidxu/*
2144518Sdavidxu * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3144518Sdavidxu * All rights reserved.
4144518Sdavidxu *
5144518Sdavidxu * Redistribution and use in source and binary forms, with or without
6144518Sdavidxu * modification, are permitted provided that the following conditions
7144518Sdavidxu * are met:
8144518Sdavidxu * 1. Redistributions of source code must retain the above copyright
9144518Sdavidxu *    notice unmodified, this list of conditions, and the following
10144518Sdavidxu *    disclaimer.
11144518Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright
12144518Sdavidxu *    notice, this list of conditions and the following disclaimer in the
13144518Sdavidxu *    documentation and/or other materials provided with the distribution.
14144518Sdavidxu *
15144518Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16144518Sdavidxu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17144518Sdavidxu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18144518Sdavidxu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19144518Sdavidxu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20144518Sdavidxu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21144518Sdavidxu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22144518Sdavidxu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23144518Sdavidxu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24144518Sdavidxu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25144518Sdavidxu *
26144518Sdavidxu * $FreeBSD: head/lib/libthr/thread/thr_umtx.c 178647 2008-04-29 03:58:18Z davidxu $
27144518Sdavidxu *
28144518Sdavidxu */
29144518Sdavidxu
30144518Sdavidxu#include "thr_private.h"
31144518Sdavidxu#include "thr_umtx.h"
32144518Sdavidxu
33177853Sdavidxu#ifndef HAS__UMTX_OP_ERR
34177853Sdavidxuint _umtx_op_err(void *obj, int op, u_long val, void *uaddr, void *uaddr2)
35177853Sdavidxu{
36177853Sdavidxu	if (_umtx_op(obj, op, val, uaddr, uaddr2) == -1)
37177853Sdavidxu		return (errno);
38177853Sdavidxu	return (0);
39177853Sdavidxu}
40177853Sdavidxu#endif
41177853Sdavidxu
42163334Sdavidxuvoid
43163334Sdavidxu_thr_umutex_init(struct umutex *mtx)
44163334Sdavidxu{
45163334Sdavidxu	static struct umutex default_mtx = DEFAULT_UMUTEX;
46163334Sdavidxu
47163334Sdavidxu	*mtx = default_mtx;
48163334Sdavidxu}
49163334Sdavidxu
50144518Sdavidxuint
51163334Sdavidxu__thr_umutex_lock(struct umutex *mtx)
52161680Sdavidxu{
53177853Sdavidxu	return _umtx_op_err(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 0);
54161680Sdavidxu}
55161680Sdavidxu
56161680Sdavidxuint
57163334Sdavidxu__thr_umutex_timedlock(struct umutex *mtx,
58161680Sdavidxu	const struct timespec *timeout)
59161680Sdavidxu{
60161680Sdavidxu	if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
61161680Sdavidxu		timeout->tv_nsec <= 0)))
62161680Sdavidxu		return (ETIMEDOUT);
63177853Sdavidxu	return _umtx_op_err(mtx, UMTX_OP_MUTEX_LOCK, 0, 0,
64177853Sdavidxu		__DECONST(void *, timeout));
65161680Sdavidxu}
66161680Sdavidxu
67161680Sdavidxuint
68163334Sdavidxu__thr_umutex_unlock(struct umutex *mtx)
69161680Sdavidxu{
70177853Sdavidxu	return _umtx_op_err(mtx, UMTX_OP_MUTEX_UNLOCK, 0, 0, 0);
71161680Sdavidxu}
72161680Sdavidxu
73161680Sdavidxuint
74163334Sdavidxu__thr_umutex_trylock(struct umutex *mtx)
75161680Sdavidxu{
76177853Sdavidxu	return _umtx_op_err(mtx, UMTX_OP_MUTEX_TRYLOCK, 0, 0, 0);
77161680Sdavidxu}
78161680Sdavidxu
79161680Sdavidxuint
80161680Sdavidxu__thr_umutex_set_ceiling(struct umutex *mtx, uint32_t ceiling,
81161680Sdavidxu	uint32_t *oldceiling)
82161680Sdavidxu{
83177853Sdavidxu	return _umtx_op_err(mtx, UMTX_OP_SET_CEILING, ceiling, oldceiling, 0);
84161680Sdavidxu}
85161680Sdavidxu
86161680Sdavidxuint
87173801Sdavidxu_thr_umtx_wait(volatile long *mtx, long id, const struct timespec *timeout)
88144518Sdavidxu{
89144518Sdavidxu	if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
90144518Sdavidxu		timeout->tv_nsec <= 0)))
91144518Sdavidxu		return (ETIMEDOUT);
92177853Sdavidxu	return _umtx_op_err(__DEVOLATILE(void *, mtx), UMTX_OP_WAIT, id, 0,
93177853Sdavidxu		__DECONST(void*, timeout));
94144518Sdavidxu}
95144518Sdavidxu
96144518Sdavidxuint
97178647Sdavidxu_thr_umtx_wait_uint(volatile u_int *mtx, u_int id, const struct timespec *timeout, int shared)
98144518Sdavidxu{
99173801Sdavidxu	if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
100173801Sdavidxu		timeout->tv_nsec <= 0)))
101173801Sdavidxu		return (ETIMEDOUT);
102178647Sdavidxu	return _umtx_op_err(__DEVOLATILE(void *, mtx),
103178647Sdavidxu			shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id, 0,
104178647Sdavidxu			__DECONST(void*, timeout));
105173801Sdavidxu}
106173801Sdavidxu
107173801Sdavidxuint
108178647Sdavidxu_thr_umtx_wake(volatile void *mtx, int nr_wakeup, int shared)
109173801Sdavidxu{
110178647Sdavidxu	return _umtx_op_err(__DEVOLATILE(void *, mtx), shared ? UMTX_OP_WAKE : UMTX_OP_WAKE_PRIVATE,
111177853Sdavidxu		nr_wakeup, 0, 0);
112144518Sdavidxu}
113164877Sdavidxu
114164902Sdavidxuvoid
115164902Sdavidxu_thr_ucond_init(struct ucond *cv)
116164902Sdavidxu{
117164902Sdavidxu	bzero(cv, sizeof(struct ucond));
118164902Sdavidxu}
119164902Sdavidxu
120164877Sdavidxuint
121164877Sdavidxu_thr_ucond_wait(struct ucond *cv, struct umutex *m,
122164877Sdavidxu	const struct timespec *timeout, int check_unparking)
123164877Sdavidxu{
124164877Sdavidxu	if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
125164877Sdavidxu	    timeout->tv_nsec <= 0))) {
126164877Sdavidxu		__thr_umutex_unlock(m);
127164877Sdavidxu                return (ETIMEDOUT);
128164877Sdavidxu	}
129177853Sdavidxu	return _umtx_op_err(cv, UMTX_OP_CV_WAIT,
130164878Sdavidxu		     check_unparking ? UMTX_CHECK_UNPARKING : 0,
131177853Sdavidxu		     m, __DECONST(void*, timeout));
132164877Sdavidxu}
133164877Sdavidxu
134164877Sdavidxuint
135164877Sdavidxu_thr_ucond_signal(struct ucond *cv)
136164877Sdavidxu{
137165110Sdavidxu	if (!cv->c_has_waiters)
138165110Sdavidxu		return (0);
139177853Sdavidxu	return _umtx_op_err(cv, UMTX_OP_CV_SIGNAL, 0, NULL, NULL);
140164877Sdavidxu}
141164877Sdavidxu
142164877Sdavidxuint
143164877Sdavidxu_thr_ucond_broadcast(struct ucond *cv)
144164877Sdavidxu{
145165110Sdavidxu	if (!cv->c_has_waiters)
146165110Sdavidxu		return (0);
147177853Sdavidxu	return _umtx_op_err(cv, UMTX_OP_CV_BROADCAST, 0, NULL, NULL);
148164877Sdavidxu}
149177850Sdavidxu
150177850Sdavidxuint
151177850Sdavidxu__thr_rwlock_rdlock(struct urwlock *rwlock, int flags, struct timespec *tsp)
152177850Sdavidxu{
153177853Sdavidxu	return _umtx_op_err(rwlock, UMTX_OP_RW_RDLOCK, flags, NULL, tsp);
154177850Sdavidxu}
155177850Sdavidxu
156177850Sdavidxuint
157177850Sdavidxu__thr_rwlock_wrlock(struct urwlock *rwlock, struct timespec *tsp)
158177850Sdavidxu{
159177853Sdavidxu	return _umtx_op_err(rwlock, UMTX_OP_RW_WRLOCK, 0, NULL, tsp);
160177850Sdavidxu}
161177850Sdavidxu
162177850Sdavidxuint
163177850Sdavidxu__thr_rwlock_unlock(struct urwlock *rwlock)
164177850Sdavidxu{
165177853Sdavidxu	return _umtx_op_err(rwlock, UMTX_OP_RW_UNLOCK, 0, NULL, NULL);
166177850Sdavidxu}
167