1 /*
2 * Copyright (c) 2014 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23 #pragma once
24
25 #include <compiler.h>
26 #include <arch/spinlock.h>
27
28 __BEGIN_CDECLS
29
30 /* interrupts should already be disabled */
spin_lock(spin_lock_t * lock)31 static inline void spin_lock(spin_lock_t *lock)
32 {
33 arch_spin_lock(lock);
34 }
35
36 /* Returns 0 on success, non-0 on failure */
spin_trylock(spin_lock_t * lock)37 static inline int spin_trylock(spin_lock_t *lock)
38 {
39 return arch_spin_trylock(lock);
40 }
41
42 /* interrupts should already be disabled */
spin_unlock(spin_lock_t * lock)43 static inline void spin_unlock(spin_lock_t *lock)
44 {
45 arch_spin_unlock(lock);
46 }
47
spin_lock_init(spin_lock_t * lock)48 static inline void spin_lock_init(spin_lock_t *lock)
49 {
50 arch_spin_lock_init(lock);
51 }
52
spin_lock_held(spin_lock_t * lock)53 static inline bool spin_lock_held(spin_lock_t *lock)
54 {
55 return arch_spin_lock_held(lock);
56 }
57
58 /* spin lock irq save flags: */
59
60 /* Possible future flags:
61 * SPIN_LOCK_FLAG_PMR_MASK = 0x000000ff
62 * SPIN_LOCK_FLAG_PREEMPTION = 0x00000100
63 * SPIN_LOCK_FLAG_SET_PMR = 0x00000200
64 */
65
66 /* Generic flags */
67 #define SPIN_LOCK_FLAG_INTERRUPTS ARCH_DEFAULT_SPIN_LOCK_FLAG_INTERRUPTS
68
69 /* same as spin lock, but save disable and save interrupt state first */
spin_lock_save(spin_lock_t * lock,spin_lock_saved_state_t * statep,spin_lock_save_flags_t flags)70 static inline void spin_lock_save(
71 spin_lock_t *lock,
72 spin_lock_saved_state_t *statep,
73 spin_lock_save_flags_t flags)
74 {
75 arch_interrupt_save(statep, flags);
76 spin_lock(lock);
77 }
78
79 /* restore interrupt state before unlocking */
spin_unlock_restore(spin_lock_t * lock,spin_lock_saved_state_t old_state,spin_lock_save_flags_t flags)80 static inline void spin_unlock_restore(
81 spin_lock_t *lock,
82 spin_lock_saved_state_t old_state,
83 spin_lock_save_flags_t flags)
84 {
85 spin_unlock(lock);
86 arch_interrupt_restore(old_state, flags);
87 }
88
89 /* hand(ier) routines */
90 #define spin_lock_irqsave(lock, statep) spin_lock_save(lock, &(statep), SPIN_LOCK_FLAG_INTERRUPTS)
91 #define spin_unlock_irqrestore(lock, statep) spin_unlock_restore(lock, statep, SPIN_LOCK_FLAG_INTERRUPTS)
92
93 __END_CDECLS
94