XenevaOS
Loading...
Searching...
No Matches
spinlock.h
Go to the documentation of this file.
1#ifndef __LINUX_SPINLOCK_H__
2#define __LINUX_SPINLOCK_H__
3
4/*
5 * DCL <linux/spinlock.h> -- the lock words tty/serial code wraps in guards.
6 *
7 * The primitives themselves are already in <linux/kernel.h> and they are
8 * no-ops:
9 *
10 * #define spin_lock_init(l) do{} while(0)
11 * #define spin_lock_irqsave(l,f) do{(f) = 0;}while(0)
12 * #define spin_unlock_irqrestore(l, f) do{}while(0)
13 *
14 * That is DCL's pre-existing contract -- driver work runs in one kernel
15 * context and Xeneva serialises at the process level -- and it is not a
16 * shortcut taken here. What this header adds is the rest of the *shape*
17 * mainline's code is written in: plain spin_lock/spin_unlock, the _irq and
18 * _bh variants (kernel.h carries only init and the irqsave pair), and the
19 * three guard classes <linux/cleanup.h> needs in order for
20 * `scoped_guard(spinlock_irq, &lock) { ... }` to mean anything.
21 *
22 * If real locking ever lands, the two places to change are kernel.h's macros
23 * and this header's guards -- nothing in between depends on the details.
24 *
25 * The irqsave guard deserves one honest note: because spin_lock_irqsave()
26 * sets flags to 0 and never touches the interrupt state, the guard has no
27 * interrupt state to carry across its scope, so it restores from a zero. If
28 * spin_lock_irqsave() ever becomes real, this guard must grow a flags field
29 * (DCL_LOCK_GUARD's struct is otherwise unchanged) -- otherwise it would
30 * silently re-enable interrupts that the acquire disabled.
31 */
32
33#include <linux/kernel.h> /* spinlock_t, spin_lock_init, irqsave pair */
34#include <linux/cleanup.h>
35
36#define spin_lock(l) do {} while (0)
37#define spin_unlock(l) do {} while (0)
38#define spin_lock_irq(l) do {} while (0)
39#define spin_unlock_irq(l) do {} while (0)
40#define spin_lock_bh(l) do {} while (0)
41#define spin_unlock_bh(l) do {} while (0)
42#define spin_unlock_irq_bh(l) do {} while (0)
43#define spin_trylock(l) (1)
44#define spin_is_locked(l) (1)
45#define spin_lock_irqsave_flags(l, f) do { (f) = 0; } while (0)
46
47/*
48 * The raw-spinlock spelling -- DEFINE_RAW_SPINLOCK(), raw_spin_lock_irqsave(),
49 * raw_spin_unlock_irqrestore(). Only tty_ldisc.c uses it (:45, :112, :114),
50 * to guard the tty_ldiscs[] table, and the reason mainline distinguishes raw
51 * locks has no referent here: DCL's spinlock_t *is* an int with every
52 * operation a no-op (kernel.h:43), so there is no raw lock underneath the
53 * non-raw one for the distinction to point at. tty_ldisc.h's own note says
54 * the same thing about ld_semaphore's wait_lock.
55 *
56 * The type is `spinlock_t`, which the file-scope definition at :45 needs to
57 * be a complete type -- `int` -- and the flags assignment mirrors
58 * spin_lock_irqsave() in kernel.h: this never reads interrupt state, so the
59 * matching restore is a no-op rather than a re-enable of something that was
60 * never disabled.
61 */
62/*
63 * raw_spin_lock_init() -- tty_ldsem.c:69, inside __init_ldsem. Deliberately
64 * the same no-op as kernel.h's spin_lock_init() rather than a store to 0:
65 * the two spellings differ only in mainline's raw/non-raw split, which this
66 * header has already established has no referent here (see the block above),
67 * and two macros that initialised the same word differently would be a
68 * difference nobody could explain from the source that calls them. The word
69 * is never read -- spin_lock() is `do {} while (0)` -- so a value it does not
70 * have cannot matter.
71 */
72/*
73 * raw_spin_lock_irq() / raw_spin_unlock_irq() -- tty_ldsem.c's contended
74 * paths (:162, :175, :184, :190, :211 and the write-side twins), which drop
75 * the flags argument the _irqsave pair takes because they never saved any.
76 * Same body as spin_lock_irq()/spin_unlock_irq() three blocks up, and for the
77 * same reason: interrupts are never disabled by a lock here, so there is
78 * nothing for the unlock to re-enable. mainline distinguishes them by
79 * whether flags travel with the call; that is the whole difference.
80 */
81#define raw_spin_lock_irq(l) do {} while (0)
82#define raw_spin_unlock_irq(l) do {} while (0)
83#define raw_spin_lock_init(l) do {} while (0)
84#define DEFINE_RAW_SPINLOCK(name) spinlock_t name = 0
85/*
86 * DEFINE_SPINLOCK(name) -- a file-scope `spinlock_t name = 0`, which is what
87 * DEFINE_RAW_SPINLOCK above already spells. virtio_console.c:60 and :361
88 * declare two of them (`static DEFINE_SPINLOCK(pdrvdata_lock);`); without a
89 * macro the line parses as a function *declaration* with an untyped parameter
90 * list and reports "type specifier missing, defaults to int" plus "a parameter
91 * list without types is only allowed in a function definition" -- two errors
92 * for one missing name, neither of which mentions the name that is missing.
93 *
94 * spinlock_t is an int here (kernel.h:43) and every lock operation is a
95 * no-op, so the initial value is not read by anything; it is written as 0
96 * rather than left uninitialised only because a file-scope object with no
97 * initialiser is already zero and spelling it out says so.
98 */
99#define DEFINE_SPINLOCK(name) spinlock_t name = 0
100
101/*
102 * __SPIN_LOCK_UNLOCKED(lockname) -- the static initialiser, the spelling a
103 * file-scope struct field needs where DEFINE_SPINLOCK's `name = 0` cannot be
104 * used. Two consumers, both struct members rather than objects:
105 *
106 * xarray.h:308 .xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock)
107 * seqlock.h:809 .lock = __SPIN_LOCK_UNLOCKED(lockname)
108 *
109 * Neither existed here until drm_drv.c:65 expanded DEFINE_XARRAY_ALLOC()
110 * (drm_minors_xa, the minor-number allocator). Undeclared, the token reads as
111 * an implicit int function call inside a static initialiser, and clang reports
112 * "initializer element is not a compile-time constant" at the *declaration* --
113 * a message that never mentions __SPIN_LOCK_UNLOCKED, so the missing name is
114 * only findable by expanding the macro by hand.
115 *
116 * mainline's is a typeof() cast over a brace initialiser carrying the arch
117 * unlock value, lockdep maps and debug fields. None of that has a referent:
118 * spinlock_t is an int (kernel.h:43) and every lock operation is a no-op, so
119 * the lock starts unlocked by having no other state to start in. `{ 0 }`
120 * rather than `0` because the context is an initialiser for a struct member
121 * and braced is what the other two initialisers in XARRAY_INIT spell.
122 *
123 * The argument is dropped, not expanded -- callers pass an lvalue (an
124 * existing lock, or a field of the object being defined) and evaluating it
125 * during its own initialisation would be a read of an object not yet
126 * complete.
127 */
128#ifndef __SPIN_LOCK_UNLOCKED
129#define __SPIN_LOCK_UNLOCKED(lockname) { 0 }
130#endif
131
132/*
133 * cpu_relax() -- the "I am spinning, back off" hint. virtio_console.c:563 and
134 * :638 sit in loops that poll a virtqueue for a reply.
135 *
136 * mainline puts it in <asm/processor.h> as a `yield`/`wfe`; DCL has no
137 * sleeping scheduler to yield to (schedule() is mdelay(1), kernel.h) and no
138 * WFE to issue against a hypervisor that may never signal, so there is no
139 * instruction for the hint to map onto. The macro discards its (absent)
140 * argument the way spin_lock() discards its lock above: the loop still reads
141 * as a spin, and the busy-wait is unchanged from what the code does today.
142 */
143#define cpu_relax() ((void)0)
144#define raw_spin_lock_irqsave(l, f) do { (f) = 0; } while (0)
145#define raw_spin_unlock_irqrestore(l, f) do {} while (0)
146
147/*
148 * spin_trylock_irqsave(lock, flags) -- try the lock, and set flags either way.
149 *
150 * It has to be a macro, not a function: the call site is
151 * `spin_trylock_irqsave(&up->lock, *flags)` (serial_core.h:1005), where
152 * `flags` arrives as a *value* that the macro is expected to assign into the
153 * caller's lvalue and whose success boolean is the macro's value. A function
154 * could take a pointer and return the boolean, but it could not reproduce
155 * that spelling -- and the spelling is mainline's, not DCL's to change.
156 *
157 * Statement expression, so it can both assign and yield. mainline's
158 * implementation saves the interrupt flags first and restores them on
159 * failure; DCL's spin_lock_irqsave() sets flags to 0 and does not touch
160 * interrupt state at all (the header's own note), so saving means recording
161 * 0, and the matching restore in uart_port_trylock_irqsave()'s failure arm is
162 * a no-op too. Returning spin_trylock(l) -- which is `(1)` -- keeps the
163 * "lock acquired" answer true, which is the only thing the caller branches on.
164 */
165#define spin_trylock_irqsave(l, f)\
166 ({ (f) = 0; spin_trylock(l); })
167
168/* Half of the irqsave pair, as a callable (see the note above). The (void)
169 * casts are because kernel.h's macros discard both arguments -- with -Wextra
170 * that would warn on every file that includes this header. */
171static inline void dcl_spin_lock_irqsave(spinlock_t* l)
172{
173 unsigned long flags = 0;
174 (void)l;
176 (void)flags;
177}
178
179static inline void dcl_spin_unlock_irqrestore(spinlock_t* l)
180{
181 unsigned long flags = 0;
182 (void)l;
184 (void)flags;
185}
186
187/* The three classes 8250_port.c, serial_core.c, n_tty.c and tty_io.c name. */
190DCL_LOCK_GUARD(spinlock_irqsave, spinlock_t,
191 dcl_spin_lock_irqsave(_T), dcl_spin_unlock_irqrestore(_T))
192
193/*
194 * seqlock.h instantiates seqcount variants named over raw_spinlock_t,
195 * spinlock_t, rwlock_t and struct mutex. DCL has exactly one lock flavour
196 * (an int), so the other three spellings alias it; the seqcount bodies only
197 * ever store the pointer, they never take the lock.
198 */
199typedef spinlock_t raw_spinlock_t;
201
202/*
203 * struct raw_spinlock -- the *type*, which drm_mode_config.h:501 embeds by
204 * value in `panic_lock`. mainline's holds an arch spinlock, a magic, a
205 * waiter list and lockdep state; here the type exists to be a field, and
206 * nothing locks through it (raw_spin_lock_* above are macros that never look
207 * at their argument). One int, so a `struct raw_spinlock` costs what the
208 * int it stands in for does.
209 */
211 unsigned int rlock;
212};
213
214#endif /* __LINUX_SPINLOCK_H__ */
uint8_t flags
Definition virtio.h:0
#define DCL_LOCK_GUARD(name, type, acquire, release)
Definition cleanup.h:168
#define spin_unlock_irqrestore(l, f)
Definition kernel.h:227
#define spin_lock_irqsave(l, f)
Definition kernel.h:226
int spinlock_t
Definition kernel.h:44
#define spin_lock(l)
Definition spinlock.h:36
#define spin_unlock(l)
Definition spinlock.h:37
spinlock_t rwlock_t
Definition spinlock.h:200
#define spin_lock_irq(l)
Definition spinlock.h:38
#define spin_unlock_irq(l)
Definition spinlock.h:39
Definition spinlock.h:210
unsigned int rlock
Definition spinlock.h:211