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