source: mainline/kernel/generic/include/synch/spinlock.h@ 1433ecda

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1433ecda was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
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.
27 */
28
29/** @addtogroup sync
30 * @{
31 */
32/** @file
33 */
34
35#ifndef KERN_SPINLOCK_H_
36#define KERN_SPINLOCK_H_
37
38#include <stdbool.h>
39#include <arch/barrier.h>
40#include <assert.h>
41#include <preemption.h>
42#include <atomic.h>
43#include <arch/asm.h>
44
45#ifdef CONFIG_SMP
46
47typedef struct spinlock {
48 atomic_t val;
49
50#ifdef CONFIG_DEBUG_SPINLOCK
51 const char *name;
52#endif /* CONFIG_DEBUG_SPINLOCK */
53} spinlock_t;
54
55/*
56 * SPINLOCK_DECLARE is to be used for dynamically allocated spinlocks,
57 * where the lock gets initialized in run time.
58 */
59#define SPINLOCK_DECLARE(lock_name) spinlock_t lock_name
60#define SPINLOCK_EXTERN(lock_name) extern spinlock_t lock_name
61
62/*
63 * SPINLOCK_INITIALIZE and SPINLOCK_STATIC_INITIALIZE are to be used
64 * for statically allocated spinlocks. They declare (either as global
65 * or static) symbol and initialize the lock.
66 */
67#ifdef CONFIG_DEBUG_SPINLOCK
68
69#define SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \
70 spinlock_t lock_name = { \
71 .name = desc_name, \
72 .val = { 0 } \
73 }
74
75#define SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \
76 static spinlock_t lock_name = { \
77 .name = desc_name, \
78 .val = { 0 } \
79 }
80
81#define ASSERT_SPINLOCK(expr, lock) \
82 assert_verbose(expr, (lock)->name)
83
84#define spinlock_lock(lock) spinlock_lock_debug((lock))
85#define spinlock_unlock(lock) spinlock_unlock_debug((lock))
86
87#else /* CONFIG_DEBUG_SPINLOCK */
88
89#define SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \
90 spinlock_t lock_name = { \
91 .val = { 0 } \
92 }
93
94#define SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \
95 static spinlock_t lock_name = { \
96 .val = { 0 } \
97 }
98
99#define ASSERT_SPINLOCK(expr, lock) \
100 assert(expr)
101
102#define spinlock_lock(lock) atomic_lock_arch(&(lock)->val)
103#define spinlock_unlock(lock) spinlock_unlock_nondebug((lock))
104
105#endif /* CONFIG_DEBUG_SPINLOCK */
106
107#define SPINLOCK_INITIALIZE(lock_name) \
108 SPINLOCK_INITIALIZE_NAME(lock_name, #lock_name)
109
110#define SPINLOCK_STATIC_INITIALIZE(lock_name) \
111 SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, #lock_name)
112
113extern void spinlock_initialize(spinlock_t *, const char *);
114extern bool spinlock_trylock(spinlock_t *);
115extern void spinlock_lock_debug(spinlock_t *);
116extern void spinlock_unlock_debug(spinlock_t *);
117extern bool spinlock_locked(spinlock_t *);
118
119/** Unlock spinlock
120 *
121 * Unlock spinlock for non-debug kernels.
122 *
123 * @param sl Pointer to spinlock_t structure.
124 *
125 */
126NO_TRACE static inline void spinlock_unlock_nondebug(spinlock_t *lock)
127{
128 /*
129 * Prevent critical section code from bleeding out this way down.
130 */
131 CS_LEAVE_BARRIER();
132
133 atomic_set(&lock->val, 0);
134 preemption_enable();
135}
136
137#ifdef CONFIG_DEBUG_SPINLOCK
138
139#include <log.h>
140
141#define DEADLOCK_THRESHOLD 100000000
142
143#define DEADLOCK_PROBE_INIT(pname) size_t pname = 0
144
145#define DEADLOCK_PROBE(pname, value) \
146 if ((pname)++ > (value)) { \
147 (pname) = 0; \
148 log(LF_OTHER, LVL_WARN, \
149 "Deadlock probe %s: exceeded threshold %u\n" \
150 "cpu%u: function=%s, line=%u\n", \
151 #pname, (value), CPU->id, __func__, __LINE__); \
152 }
153
154#else /* CONFIG_DEBUG_SPINLOCK */
155
156#define DEADLOCK_PROBE_INIT(pname)
157#define DEADLOCK_PROBE(pname, value)
158
159#endif /* CONFIG_DEBUG_SPINLOCK */
160
161#else /* CONFIG_SMP */
162
163/* On UP systems, spinlocks are effectively left out. */
164
165/* Allow the use of spinlock_t as an incomplete type. */
166typedef struct spinlock spinlock_t;
167
168#define SPINLOCK_DECLARE(name)
169#define SPINLOCK_EXTERN(name)
170
171#define SPINLOCK_INITIALIZE(name)
172#define SPINLOCK_STATIC_INITIALIZE(name)
173
174#define SPINLOCK_INITIALIZE_NAME(name, desc_name)
175#define SPINLOCK_STATIC_INITIALIZE_NAME(name, desc_name)
176
177#define ASSERT_SPINLOCK(expr, lock) assert(expr)
178
179#define spinlock_initialize(lock, name)
180
181#define spinlock_lock(lock) preemption_disable()
182#define spinlock_trylock(lock) ({ preemption_disable(); 1; })
183#define spinlock_unlock(lock) preemption_enable()
184#define spinlock_locked(lock) 1
185#define spinlock_unlocked(lock) 1
186
187#define DEADLOCK_PROBE_INIT(pname)
188#define DEADLOCK_PROBE(pname, value)
189
190#endif /* CONFIG_SMP */
191
192typedef struct {
193 SPINLOCK_DECLARE(lock); /**< Spinlock */
194 bool guard; /**< Flag whether ipl is valid */
195 ipl_t ipl; /**< Original interrupt level */
196} irq_spinlock_t;
197
198#define IRQ_SPINLOCK_DECLARE(lock_name) irq_spinlock_t lock_name
199#define IRQ_SPINLOCK_EXTERN(lock_name) extern irq_spinlock_t lock_name
200
201#ifdef CONFIG_SMP
202
203#define ASSERT_IRQ_SPINLOCK(expr, irq_lock) \
204 ASSERT_SPINLOCK(expr, &((irq_lock)->lock))
205
206/*
207 * IRQ_SPINLOCK_INITIALIZE and IRQ_SPINLOCK_STATIC_INITIALIZE are to be used
208 * for statically allocated interrupts-disabled spinlocks. They declare (either
209 * as global or static symbol) and initialize the lock.
210 */
211#ifdef CONFIG_DEBUG_SPINLOCK
212
213#define IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \
214 irq_spinlock_t lock_name = { \
215 .lock = { \
216 .name = desc_name, \
217 .val = { 0 } \
218 }, \
219 .guard = false, \
220 .ipl = 0 \
221 }
222
223#define IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \
224 static irq_spinlock_t lock_name = { \
225 .lock = { \
226 .name = desc_name, \
227 .val = { 0 } \
228 }, \
229 .guard = false, \
230 .ipl = 0 \
231 }
232
233#else /* CONFIG_DEBUG_SPINLOCK */
234
235#define IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \
236 irq_spinlock_t lock_name = { \
237 .lock = { \
238 .val = { 0 } \
239 }, \
240 .guard = false, \
241 .ipl = 0 \
242 }
243
244#define IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \
245 static irq_spinlock_t lock_name = { \
246 .lock = { \
247 .val = { 0 } \
248 }, \
249 .guard = false, \
250 .ipl = 0 \
251 }
252
253#endif /* CONFIG_DEBUG_SPINLOCK */
254
255#else /* CONFIG_SMP */
256
257/*
258 * Since the spinlocks are void on UP systems, we also need
259 * to have a special variant of interrupts-disabled spinlock
260 * macros which take this into account.
261 */
262
263#define ASSERT_IRQ_SPINLOCK(expr, irq_lock) \
264 ASSERT_SPINLOCK(expr, NULL)
265
266#define IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \
267 irq_spinlock_t lock_name = { \
268 .guard = false, \
269 .ipl = 0 \
270 }
271
272#define IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \
273 static irq_spinlock_t lock_name = { \
274 .guard = false, \
275 .ipl = 0 \
276 }
277
278#endif /* CONFIG_SMP */
279
280#define IRQ_SPINLOCK_INITIALIZE(lock_name) \
281 IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, #lock_name)
282
283#define IRQ_SPINLOCK_STATIC_INITIALIZE(lock_name) \
284 IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, #lock_name)
285
286extern void irq_spinlock_initialize(irq_spinlock_t *, const char *);
287extern void irq_spinlock_lock(irq_spinlock_t *, bool);
288extern void irq_spinlock_unlock(irq_spinlock_t *, bool);
289extern bool irq_spinlock_trylock(irq_spinlock_t *);
290extern void irq_spinlock_pass(irq_spinlock_t *, irq_spinlock_t *);
291extern void irq_spinlock_exchange(irq_spinlock_t *, irq_spinlock_t *);
292extern bool irq_spinlock_locked(irq_spinlock_t *);
293
294#endif
295
296/** @}
297 */
Note: See TracBrowser for help on using the repository browser.