2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2002, Jeffrey Roberson <jeff@freebsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice unmodified, this list of conditions, and the following
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #ifndef _SYS_UMTXVAR_H_
33 #define _SYS_UMTXVAR_H_
38 * The umtx_key structure is used by both the Linux futex code and the
39 * umtx implementation to map userland addresses to unique keys.
52 TYPE_PI_ROBUST_UMUTEX,
53 TYPE_PP_ROBUST_UMUTEX,
57 /* Key to represent a unique userland synchronous object */
64 struct vm_object *object;
78 #define THREAD_SHARE 0
79 #define PROCESS_SHARE 1
82 struct umtx_abs_timeout {
84 bool is_abs_real; /* TIMER_ABSTIME && CLOCK_REALTIME* */
91 /* Priority inheritance mutex info. */
94 struct thread *pi_owner;
99 /* List entry to link umtx holding by thread */
100 TAILQ_ENTRY(umtx_pi) pi_link;
102 /* List entry in hash */
103 TAILQ_ENTRY(umtx_pi) pi_hashlink;
105 /* List for waiters */
106 TAILQ_HEAD(,umtx_q) pi_blocked;
108 /* Identify a userland lock object */
109 struct umtx_key pi_key;
112 /* A userland synchronous object user. */
114 /* Linked list for the hash. */
115 TAILQ_ENTRY(umtx_q) uq_link;
118 struct umtx_key uq_key;
122 #define UQF_UMTXQ 0x0001
124 /* Futex bitset mask */
127 /* The thread waits on. */
128 struct thread *uq_thread;
131 * Blocked on PI mutex. read can use chain lock
132 * or umtx_lock, write must have both chain lock and
133 * umtx_lock being hold.
135 struct umtx_pi *uq_pi_blocked;
137 /* On blocked list */
138 TAILQ_ENTRY(umtx_q) uq_lockq;
140 /* Thread contending with us */
141 TAILQ_HEAD(,umtx_pi) uq_pi_contested;
143 /* Inherited priority from PP mutex */
144 u_char uq_inherited_pri;
146 /* Spare queue ready to be reused */
147 struct umtxq_queue *uq_spare_queue;
149 /* The queue we on */
150 struct umtxq_queue *uq_cur_queue;
153 TAILQ_HEAD(umtxq_head, umtx_q);
155 /* Per-key wait-queue */
157 struct umtxq_head head;
159 LIST_ENTRY(umtxq_queue) link;
163 LIST_HEAD(umtxq_list, umtxq_queue);
165 /* Userland lock object's wait-queue chain */
167 /* Lock for this chain. */
170 /* List of sleep queues. */
171 struct umtxq_list uc_queue[2];
172 #define UMTX_SHARED_QUEUE 0
173 #define UMTX_EXCLUSIVE_QUEUE 1
175 LIST_HEAD(, umtxq_queue) uc_spare_queue;
180 /* Chain lock waiters */
183 /* All PI in the list */
184 TAILQ_HEAD(,umtx_pi) uc_pi_list;
186 #ifdef UMTX_PROFILING
193 umtx_key_match(const struct umtx_key *k1, const struct umtx_key *k2)
196 return (k1->type == k2->type &&
197 k1->info.both.a == k2->info.both.a &&
198 k1->info.both.b == k2->info.both.b);
201 void umtx_abs_timeout_init(struct umtx_abs_timeout *, int, int,
202 const struct timespec *);
203 int umtx_copyin_timeout(const void *, struct timespec *);
204 void umtx_exec(struct proc *p);
205 int umtx_key_get(const void *, int, int, struct umtx_key *);
206 void umtx_key_release(struct umtx_key *);
207 struct umtx_q *umtxq_alloc(void);
208 void umtxq_busy(struct umtx_key *);
209 int umtxq_count(struct umtx_key *);
210 void umtxq_free(struct umtx_q *);
211 struct umtxq_chain *umtxq_getchain(struct umtx_key *);
212 void umtxq_insert_queue(struct umtx_q *, int);
213 void umtxq_remove_queue(struct umtx_q *, int);
214 int umtxq_requeue(struct umtx_key *, int, struct umtx_key *, int);
215 int umtxq_signal_mask(struct umtx_key *, int, u_int);
216 int umtxq_sleep(struct umtx_q *, const char *,
217 struct umtx_abs_timeout *);
218 int umtxq_sleep_pi(struct umtx_q *, struct umtx_pi *, uint32_t,
219 const char *, struct umtx_abs_timeout *, bool);
220 void umtxq_unbusy(struct umtx_key *);
221 void umtxq_unbusy_unlocked(struct umtx_key *);
222 int kern_umtx_wake(struct thread *, void *, int, int);
223 void umtx_pi_adjust(struct thread *, u_char);
224 struct umtx_pi *umtx_pi_alloc(int);
225 int umtx_pi_claim(struct umtx_pi *, struct thread *);
226 int umtx_pi_drop(struct thread *, struct umtx_key *, bool, int *);
227 void umtx_pi_free(struct umtx_pi *);
228 void umtx_pi_insert(struct umtx_pi *);
229 struct umtx_pi *umtx_pi_lookup(struct umtx_key *);
230 void umtx_pi_ref(struct umtx_pi *);
231 void umtx_pi_unref(struct umtx_pi *);
232 void umtx_thread_init(struct thread *);
233 void umtx_thread_fini(struct thread *);
234 void umtx_thread_alloc(struct thread *);
235 void umtx_thread_exit(struct thread *);
237 #define umtxq_insert(uq) umtxq_insert_queue((uq), UMTX_SHARED_QUEUE)
238 #define umtxq_remove(uq) umtxq_remove_queue((uq), UMTX_SHARED_QUEUE)
243 * The code is a macro so that file/line information is taken from the caller.
245 #define umtxq_lock(key) do { \
246 struct umtx_key *_key = (key); \
247 struct umtxq_chain *_uc; \
249 _uc = umtxq_getchain(_key); \
250 mtx_lock(&_uc->uc_lock); \
257 umtxq_unlock(struct umtx_key *key)
259 struct umtxq_chain *uc;
261 uc = umtxq_getchain(key);
262 mtx_unlock(&uc->uc_lock);
266 #endif /* !_SYS_UMTXVAR_H_ */