source: rtems-libbsd/freebsd/sys/sys/sx.h @ 0389b30

5
Last change on this file since 0389b30 was 0389b30, checked in by Sebastian Huber <sebastian.huber@…>, on 01/15/19 at 14:35:11

Fix INVARIANTS support

  • Property mode set to 100644
File size: 11.8 KB
Line 
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2007 Attilio Rao <attilio@freebsd.org>
5 * Copyright (c) 2001 Jason Evans <jasone@freebsd.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice(s), this list of conditions and the following disclaimer as
13 *    the first lines of this file unmodified other than the possible
14 *    addition of one or more copyright notices.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice(s), 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 COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 * DAMAGE.
30 *
31 * $FreeBSD$
32 */
33
34#ifndef _SYS_SX_H_
35#define _SYS_SX_H_
36
37#include <sys/_lock.h>
38#include <sys/_sx.h>
39
40#ifdef  _KERNEL
41#include <sys/pcpu.h>
42#include <sys/lock_profile.h>
43#include <sys/lockstat.h>
44#include <machine/atomic.h>
45#endif
46
47#ifdef __rtems__
48#define SX_NOINLINE 1
49#define sx_try_xlock_ _bsd_sx_try_slock_int
50#define sx_try_xlock_int _bsd_sx_try_slock_int
51#define _sx_sunlock _bsd__sx_sunlock_int
52#endif /* __rtems__ */
53/*
54 * In general, the sx locks and rwlocks use very similar algorithms.
55 * The main difference in the implementations is how threads are
56 * blocked when a lock is unavailable.  For this, sx locks use sleep
57 * queues which do not support priority propagation, and rwlocks use
58 * turnstiles which do.
59 *
60 * The sx_lock field consists of several fields.  The low bit
61 * indicates if the lock is locked with a shared or exclusive lock.  A
62 * value of 0 indicates an exclusive lock, and a value of 1 indicates
63 * a shared lock.  Bit 1 is a boolean indicating if there are any
64 * threads waiting for a shared lock.  Bit 2 is a boolean indicating
65 * if there are any threads waiting for an exclusive lock.  Bit 3 is a
66 * boolean indicating if an exclusive lock is recursively held.  The
67 * rest of the variable's definition is dependent on the value of the
68 * first bit.  For an exclusive lock, it is a pointer to the thread
69 * holding the lock, similar to the mtx_lock field of mutexes.  For
70 * shared locks, it is a count of read locks that are held.
71 *
72 * When the lock is not locked by any thread, it is encoded as a
73 * shared lock with zero waiters.
74 */
75
76#define SX_LOCK_SHARED                  0x01
77#define SX_LOCK_SHARED_WAITERS          0x02
78#define SX_LOCK_EXCLUSIVE_WAITERS       0x04
79#define SX_LOCK_WRITE_SPINNER           0x08
80#define SX_LOCK_RECURSED                0x10
81#define SX_LOCK_FLAGMASK                                                \
82        (SX_LOCK_SHARED | SX_LOCK_SHARED_WAITERS |                      \
83        SX_LOCK_EXCLUSIVE_WAITERS | SX_LOCK_RECURSED | SX_LOCK_WRITE_SPINNER)
84#define SX_LOCK_WAITERS                 (SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS)
85
86#define SX_OWNER(x)                     ((x) & ~SX_LOCK_FLAGMASK)
87#define SX_SHARERS_SHIFT                5
88#define SX_SHARERS(x)                   (SX_OWNER(x) >> SX_SHARERS_SHIFT)
89#define SX_SHARERS_LOCK(x)                                              \
90        ((x) << SX_SHARERS_SHIFT | SX_LOCK_SHARED)
91#define SX_ONE_SHARER                   (1 << SX_SHARERS_SHIFT)
92
93#define SX_LOCK_UNLOCKED                SX_SHARERS_LOCK(0)
94#define SX_LOCK_DESTROYED                                               \
95        (SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS)
96
97#ifdef _KERNEL
98
99#define sx_recurse      lock_object.lo_data
100
101#define SX_READ_VALUE(sx)       ((sx)->sx_lock)
102
103#define lv_sx_owner(v) \
104        ((v & SX_LOCK_SHARED) ? NULL : (struct thread *)SX_OWNER(v))
105
106/*
107 * Function prototipes.  Routines that start with an underscore are not part
108 * of the public interface and are wrappered with a macro.
109 */
110void    sx_sysinit(void *arg);
111#define sx_init(sx, desc)       sx_init_flags((sx), (desc), 0)
112void    sx_init_flags(struct sx *sx, const char *description, int opts);
113void    sx_destroy(struct sx *sx);
114int     sx_try_slock_int(struct sx *sx LOCK_FILE_LINE_ARG_DEF);
115#ifndef __rtems__
116int     sx_try_slock_(struct sx *sx, const char *file, int line);
117int     sx_try_xlock_int(struct sx *sx LOCK_FILE_LINE_ARG_DEF);
118int     sx_try_xlock_(struct sx *sx, const char *file, int line);
119#endif /* __rtems__ */
120int     sx_try_upgrade_int(struct sx *sx LOCK_FILE_LINE_ARG_DEF);
121#ifndef __rtems__
122int     sx_try_upgrade_(struct sx *sx, const char *file, int line);
123#endif /* __rtems__ */
124void    sx_downgrade_int(struct sx *sx LOCK_FILE_LINE_ARG_DEF);
125#ifndef __rtems__
126void    sx_downgrade_(struct sx *sx, const char *file, int line);
127#endif /* __rtems__ */
128int     _sx_slock_int(struct sx *sx, int opts LOCK_FILE_LINE_ARG_DEF);
129#ifndef __rtems__
130int     _sx_slock(struct sx *sx, int opts, const char *file, int line);
131int     _sx_xlock(struct sx *sx, int opts, const char *file, int line);
132#else /* __rtems__ */
133#if     (LOCK_DEBUG > 0)
134#define _sx_xlock(sx, opts, file, line) \
135    _bsd__sx_slock_int(sx, opts, file, line)
136#else
137#define _sx_xlock(sx, opts, file, line) _bsd__sx_slock_int(sx, opts)
138#endif
139#endif /* __rtems__ */
140void    _sx_sunlock_int(struct sx *sx LOCK_FILE_LINE_ARG_DEF);
141#ifndef __rtems__
142void    _sx_sunlock(struct sx *sx, const char *file, int line);
143void    _sx_xunlock(struct sx *sx, const char *file, int line);
144int     _sx_xlock_hard(struct sx *sx, uintptr_t x, int opts LOCK_FILE_LINE_ARG_DEF);
145void    _sx_xunlock_hard(struct sx *sx, uintptr_t x LOCK_FILE_LINE_ARG_DEF);
146#else /* __rtems__ */
147#if     (LOCK_DEBUG > 0)
148#define _sx_xunlock(sx, file, line) _bsd__sx_sunlock_int(sx, file, line)
149#else
150#define _sx_xunlock(sx, file, line) _bsd__sx_sunlock_int(sx)
151#endif
152#endif /* __rtems__ */
153#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
154void    _sx_assert(const struct sx *sx, int what, const char *file, int line);
155#endif
156#ifdef DDB
157int     sx_chain(struct thread *td, struct thread **ownerp);
158#endif
159
160struct sx_args {
161        struct sx       *sa_sx;
162        const char      *sa_desc;
163        int             sa_flags;
164};
165
166#define SX_SYSINIT_FLAGS(name, sxa, desc, flags)                        \
167        static struct sx_args name##_args = {                           \
168                (sxa),                                                  \
169                (desc),                                                 \
170                (flags)                                                 \
171        };                                                              \
172        SYSINIT(name##_sx_sysinit, SI_SUB_LOCK, SI_ORDER_MIDDLE,        \
173            sx_sysinit, &name##_args);                                  \
174        SYSUNINIT(name##_sx_sysuninit, SI_SUB_LOCK, SI_ORDER_MIDDLE,    \
175            sx_destroy, (sxa))
176
177#define SX_SYSINIT(name, sxa, desc)     SX_SYSINIT_FLAGS(name, sxa, desc, 0)
178
179#ifndef __rtems__
180/*
181 * Full lock operations that are suitable to be inlined in non-debug kernels.
182 * If the lock can't be acquired or released trivially then the work is
183 * deferred to 'tougher' functions.
184 */
185
186#if     (LOCK_DEBUG == 0)
187/* Acquire an exclusive lock. */
188static __inline int
189__sx_xlock(struct sx *sx, struct thread *td, int opts, const char *file,
190    int line)
191{
192        uintptr_t tid = (uintptr_t)td;
193        uintptr_t v = SX_LOCK_UNLOCKED;
194        int error = 0;
195
196        if (__predict_false(LOCKSTAT_PROFILE_ENABLED(sx__acquire) ||
197            !atomic_fcmpset_acq_ptr(&sx->sx_lock, &v, tid)))
198                error = _sx_xlock_hard(sx, v, opts);
199
200        return (error);
201}
202
203/* Release an exclusive lock. */
204static __inline void
205__sx_xunlock(struct sx *sx, struct thread *td, const char *file, int line)
206{
207        uintptr_t x = (uintptr_t)td;
208
209        if (__predict_false(LOCKSTAT_PROFILE_ENABLED(sx__release) ||
210            !atomic_fcmpset_rel_ptr(&sx->sx_lock, &x, SX_LOCK_UNLOCKED)))
211                _sx_xunlock_hard(sx, x);
212}
213#endif
214#endif /* __rtems__ */
215
216/*
217 * Public interface for lock operations.
218 */
219#ifndef LOCK_DEBUG
220#error  "LOCK_DEBUG not defined, include <sys/lock.h> before <sys/sx.h>"
221#endif
222#if     (LOCK_DEBUG > 0) || defined(SX_NOINLINE)
223#define sx_xlock_(sx, file, line)                                       \
224        (void)_sx_xlock((sx), 0, (file), (line))
225#define sx_xlock_sig_(sx, file, line)                                   \
226        _sx_xlock((sx), SX_INTERRUPTIBLE, (file), (line))
227#define sx_xunlock_(sx, file, line)                                     \
228        _sx_xunlock((sx), (file), (line))
229#else
230#define sx_xlock_(sx, file, line)                                       \
231        (void)__sx_xlock((sx), curthread, 0, (file), (line))
232#define sx_xlock_sig_(sx, file, line)                                   \
233        __sx_xlock((sx), curthread, SX_INTERRUPTIBLE, (file), (line))
234#define sx_xunlock_(sx, file, line)                                     \
235        __sx_xunlock((sx), curthread, (file), (line))
236#endif  /* LOCK_DEBUG > 0 || SX_NOINLINE */
237#if     (LOCK_DEBUG > 0)
238#ifndef __rtems__
239#define sx_slock_(sx, file, line)                                       \
240        (void)_sx_slock((sx), 0, (file), (line))
241#else /* __rtems__ */
242#define sx_slock_(sx, file, line)                                       \
243        (void)_sx_xlock((sx), 0, (file), (line))
244#endif /* __rtems__ */
245#define sx_slock_sig_(sx, file, line)                                   \
246        _sx_slock((sx), SX_INTERRUPTIBLE, (file) , (line))
247#define sx_sunlock_(sx, file, line)                                     \
248        _sx_sunlock((sx), (file), (line))
249#define sx_try_slock(sx)        sx_try_slock_((sx), LOCK_FILE, LOCK_LINE)
250#define sx_try_xlock(sx)        sx_try_xlock_((sx), LOCK_FILE, LOCK_LINE)
251#define sx_try_upgrade(sx)      sx_try_upgrade_((sx), LOCK_FILE, LOCK_LINE)
252#define sx_downgrade(sx)        sx_downgrade_((sx), LOCK_FILE, LOCK_LINE)
253#else
254#define sx_slock_(sx, file, line)                                       \
255        (void)_sx_slock_int((sx), 0)
256#define sx_slock_sig_(sx, file, line)                                   \
257        _sx_slock_int((sx), SX_INTERRUPTIBLE)
258#define sx_sunlock_(sx, file, line)                                     \
259        _sx_sunlock_int((sx))
260#define sx_try_slock(sx)        sx_try_slock_int((sx))
261#define sx_try_xlock(sx)        sx_try_xlock_int((sx))
262#define sx_try_upgrade(sx)      sx_try_upgrade_int((sx))
263#define sx_downgrade(sx)        sx_downgrade_int((sx))
264#endif
265#ifdef INVARIANTS
266#define sx_assert_(sx, what, file, line)                                \
267        _sx_assert((sx), (what), (file), (line))
268#else
269#define sx_assert_(sx, what, file, line)        (void)0
270#endif
271
272#define sx_xlock(sx)            sx_xlock_((sx), LOCK_FILE, LOCK_LINE)
273#define sx_xlock_sig(sx)        sx_xlock_sig_((sx), LOCK_FILE, LOCK_LINE)
274#define sx_xunlock(sx)          sx_xunlock_((sx), LOCK_FILE, LOCK_LINE)
275#define sx_slock(sx)            sx_slock_((sx), LOCK_FILE, LOCK_LINE)
276#define sx_slock_sig(sx)        sx_slock_sig_((sx), LOCK_FILE, LOCK_LINE)
277#define sx_sunlock(sx)          sx_sunlock_((sx), LOCK_FILE, LOCK_LINE)
278#define sx_assert(sx, what)     sx_assert_((sx), (what), __FILE__, __LINE__)
279
280/*
281 * Return a pointer to the owning thread if the lock is exclusively
282 * locked.
283 */
284#ifndef __rtems__
285#define sx_xholder(sx)                                                  \
286        ((sx)->sx_lock & SX_LOCK_SHARED ? NULL :                        \
287        (struct thread *)SX_OWNER((sx)->sx_lock))
288
289#define sx_xlocked(sx)                                                  \
290        (((sx)->sx_lock & ~(SX_LOCK_FLAGMASK & ~SX_LOCK_SHARED)) ==     \
291            (uintptr_t)curthread)
292
293#define sx_unlock_(sx, file, line) do {                                 \
294        if (sx_xlocked(sx))                                             \
295                sx_xunlock_(sx, file, line);                            \
296        else                                                            \
297                sx_sunlock_(sx, file, line);                            \
298} while (0)
299
300#define sx_unlock(sx)   sx_unlock_((sx), LOCK_FILE, LOCK_LINE)
301#else /* __rtems__ */
302int sx_xlocked(struct sx *sx);
303#if     (LOCK_DEBUG > 0)
304#define sx_unlock(sx)   _sx_sunlock_int((sx), LOCK_FILE, LOCK_LINE)
305#else
306#define sx_unlock(sx)   _sx_sunlock_int((sx))
307#endif
308#endif /* __rtems__ */
309
310#define sx_sleep(chan, sx, pri, wmesg, timo)                            \
311        _sleep((chan), &(sx)->lock_object, (pri), (wmesg),              \
312            tick_sbt * (timo), 0,  C_HARDCLOCK)
313
314/*
315 * Options passed to sx_init_flags().
316 */
317#define SX_DUPOK                0x01
318#define SX_NOPROFILE            0x02
319#define SX_NOWITNESS            0x04
320#define SX_QUIET                0x08
321#define SX_RECURSE              0x20
322#define SX_NEW                  0x40
323
324/*
325 * Options passed to sx_*lock_hard().
326 */
327#define SX_INTERRUPTIBLE        0x40
328
329#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
330#define SA_LOCKED               LA_LOCKED
331#define SA_SLOCKED              LA_SLOCKED
332#define SA_XLOCKED              LA_XLOCKED
333#define SA_UNLOCKED             LA_UNLOCKED
334#define SA_RECURSED             LA_RECURSED
335#define SA_NOTRECURSED          LA_NOTRECURSED
336
337/* Backwards compatibility. */
338#define SX_LOCKED               LA_LOCKED
339#define SX_SLOCKED              LA_SLOCKED
340#define SX_XLOCKED              LA_XLOCKED
341#define SX_UNLOCKED             LA_UNLOCKED
342#define SX_RECURSED             LA_RECURSED
343#define SX_NOTRECURSED          LA_NOTRECURSED
344#endif
345
346#endif /* _KERNEL */
347
348#endif /* !_SYS_SX_H_ */
Note: See TracBrowser for help on using the repository browser.