FreeBSD/Linux Kernel Cross Reference
sys/sys/mutex.h
1 /* $NetBSD: mutex.h,v 1.26 2022/10/26 23:21:20 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2002, 2006, 2007, 2008, 2009, 2019 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe and Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef _SYS_MUTEX_H_
33 #define _SYS_MUTEX_H_
34
35 /*
36 * There are 2 types of mutexes:
37 *
38 * * Adaptive -- If the lock is already held, the thread attempting
39 * to acquire the lock determines if the thread that holds it is
40 * currently running. If so, it spins, else it sleeps.
41 *
42 * * Spin -- If the lock is already held, the thread attempting to
43 * acquire the lock spins. The IPL will be raised on entry.
44 *
45 * Machine dependent code must provide the following:
46 *
47 * struct mutex
48 * The actual mutex structure. This structure is mostly
49 * opaque to machine-independent code; most access are done
50 * through macros. However, machine-independent code must
51 * be able to access the following members:
52 *
53 * uintptr_t mtx_owner
54 * ipl_cookie_t mtx_ipl
55 * __cpu_simple_lock_t mtx_lock
56 *
57 * If an architecture can be considered 'simple' (no interlock required in
58 * the MP case, or no MP) it need only define __HAVE_SIMPLE_MUTEXES and
59 * provide the following:
60 *
61 * struct mutex
62 *
63 * [additionally:]
64 * volatile integer mtx_id
65 *
66 * MUTEX_CAS(ptr, old, new)
67 * Perform an atomic "compare and swap" operation and
68 * evaluate to true or false according to the success
69 *
70 * Otherwise, the following must be defined:
71 *
72 * MUTEX_INITIALIZE_SPIN(mtx, dodebug, minipl)
73 * Initialize a spin mutex.
74 *
75 * MUTEX_INITIALIZE_ADAPTIVE(mtx, dodebug)
76 * Initialize an adaptive mutex.
77 *
78 * MUTEX_DESTROY(mtx)
79 * Tear down a mutex.
80 *
81 * MUTEX_ADAPTIVE_P(mtx)
82 * Evaluates to true if the mutex is an adaptive mutex.
83 *
84 * MUTEX_SPIN_P(mtx)
85 * Evaluates to true if the mutex is a spin mutex.
86 *
87 * MUTEX_OWNER(owner)
88 * Returns the owner of the adaptive mutex (LWP address).
89 *
90 * MUTEX_OWNED(owner)
91 * Returns non-zero if an adaptive mutex is currently
92 * held by an LWP.
93 *
94 * MUTEX_HAS_WAITERS(mtx)
95 * Returns true if the mutex has waiters.
96 *
97 * MUTEX_SET_WAITERS(mtx)
98 * Mark the mutex has having waiters.
99 *
100 * MUTEX_ACQUIRE(mtx, owner)
101 * Try to acquire an adaptive mutex such that:
102 * if (lock held OR waiters)
103 * return 0;
104 * else
105 * return 1;
106 * Must be MP/interrupt atomic.
107 *
108 * MUTEX_RELEASE(mtx)
109 * Release the lock and clear the "has waiters" indication.
110 * Must be interrupt atomic, need not be MP safe.
111 *
112 * MUTEX_DEBUG_P(mtx)
113 * Evaluates to true if the mutex is initialized with
114 * dodebug==true. Only used in the LOCKDEBUG case.
115 *
116 * Machine dependent code may optionally provide stubs for the following
117 * functions to implement the easy (unlocked / no waiters) cases. If
118 * these stubs are provided, __HAVE_MUTEX_STUBS should be defined.
119 *
120 * mutex_enter()
121 * mutex_exit()
122 *
123 * Two additional stubs may be implemented that handle only the spinlock
124 * case, primarily for the scheduler. __HAVE_SPIN_MUTEX_STUBS should be
125 * defined if these are provided:
126 *
127 * mutex_spin_enter()
128 * mutex_spin_exit()
129 */
130
131 #if defined(_KERNEL_OPT)
132 #include "opt_lockdebug.h"
133 #endif
134
135 #if !defined(_KERNEL)
136 #include <sys/types.h>
137 #include <sys/inttypes.h>
138 #endif
139
140 typedef enum kmutex_type_t {
141 MUTEX_SPIN = 0, /* To get a spin mutex at IPL_NONE */
142 MUTEX_ADAPTIVE = 1, /* For porting code written for Solaris */
143 MUTEX_DEFAULT = 2, /* The only native, endorsed type */
144 MUTEX_DRIVER = 3, /* For porting code written for Solaris */
145 MUTEX_NODEBUG = 4 /* Disables LOCKDEBUG; use with care */
146 } kmutex_type_t;
147
148 typedef struct kmutex kmutex_t;
149
150 #if defined(__MUTEX_PRIVATE)
151
152 #define MUTEX_THREAD ((uintptr_t)-16L)
153
154 #define MUTEX_BIT_SPIN 0x01
155 #define MUTEX_BIT_WAITERS 0x02
156
157 #if defined(LOCKDEBUG)
158 #define MUTEX_BIT_NODEBUG 0x04 /* LOCKDEBUG disabled */
159 #else
160 #define MUTEX_BIT_NODEBUG 0x00 /* do nothing */
161 #endif /* LOCKDEBUG */
162
163 #define MUTEX_SPIN_IPL(mtx) ((mtx)->mtx_ipl)
164 #define MUTEX_SPIN_OLDSPL(ci) ((ci)->ci_mtx_oldspl)
165
166 void mutex_vector_enter(kmutex_t *);
167 void mutex_vector_exit(kmutex_t *);
168 void mutex_spin_retry(kmutex_t *);
169 void mutex_wakeup(kmutex_t *);
170
171 #endif /* __MUTEX_PRIVATE */
172
173 #ifdef _KERNEL
174 #include <sys/intr.h>
175 #endif
176
177 #include <machine/mutex.h>
178
179 /*
180 * Return true if no spin mutexes are held by the current CPU.
181 */
182 #ifndef MUTEX_NO_SPIN_ACTIVE_P
183 #define MUTEX_NO_SPIN_ACTIVE_P(ci) ((ci)->ci_mtx_count == 0)
184 #endif
185
186 #ifdef _KERNEL
187
188 void _mutex_init(kmutex_t *, kmutex_type_t, int, uintptr_t);
189 void mutex_init(kmutex_t *, kmutex_type_t, int);
190 void mutex_destroy(kmutex_t *);
191
192 void mutex_enter(kmutex_t *);
193 void mutex_exit(kmutex_t *);
194
195 void mutex_spin_enter(kmutex_t *);
196 void mutex_spin_exit(kmutex_t *);
197
198 int mutex_tryenter(kmutex_t *);
199
200 int mutex_owned(const kmutex_t *);
201 int mutex_ownable(const kmutex_t *);
202 lwp_t *mutex_owner(const kmutex_t *);
203 bool mutex_owner_running(const kmutex_t *);
204
205 void mutex_obj_init(void);
206 kmutex_t *mutex_obj_alloc(kmutex_type_t, int);
207 void mutex_obj_hold(kmutex_t *);
208 bool mutex_obj_free(kmutex_t *);
209 u_int mutex_obj_refcnt(kmutex_t *);
210 kmutex_t *mutex_obj_tryalloc(kmutex_type_t, int);
211
212 #endif /* _KERNEL */
213
214 #endif /* _SYS_MUTEX_H_ */
Cache object: 7d3dadb358f76246ca9c8d227d5d1399
|