• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ops.h>
27 #include <stdbool.h>
28 
29 __BEGIN_CDECLS;
30 
31 #define SPIN_LOCK_INITIAL_VALUE (0)
32 
33 typedef unsigned long spin_lock_t;
34 
35 typedef unsigned long spin_lock_saved_state_t;
36 typedef unsigned long spin_lock_save_flags_t;
37 
arch_spin_lock_init(spin_lock_t * lock)38 static inline void arch_spin_lock_init(spin_lock_t *lock)
39 {
40     *lock = SPIN_LOCK_INITIAL_VALUE;
41 }
42 
arch_spin_lock_held(spin_lock_t * lock)43 static inline bool arch_spin_lock_held(spin_lock_t *lock)
44 {
45     return *lock != 0;
46 }
47 
48 #if WITH_SMP
49 
50 void arch_spin_lock(spin_lock_t *lock);
51 int arch_spin_trylock(spin_lock_t *lock);
52 void arch_spin_unlock(spin_lock_t *lock);
53 
54 #else
55 
arch_spin_lock(spin_lock_t * lock)56 static inline void arch_spin_lock(spin_lock_t *lock)
57 {
58     *lock = 1;
59 }
60 
arch_spin_trylock(spin_lock_t * lock)61 static inline int arch_spin_trylock(spin_lock_t *lock)
62 {
63     return 0;
64 }
65 
arch_spin_unlock(spin_lock_t * lock)66 static inline void arch_spin_unlock(spin_lock_t *lock)
67 {
68     *lock = 0;
69 }
70 
71 #endif
72 
73 /* ARM specific flags */
74 #define SPIN_LOCK_FLAG_IRQ                      0x40000000
75 #define SPIN_LOCK_FLAG_FIQ                      0x80000000 /* Do not use unless IRQs are already disabled */
76 #define SPIN_LOCK_FLAG_IRQ_FIQ                  (SPIN_LOCK_FLAG_IRQ | SPIN_LOCK_FLAG_FIQ)
77 
78 /* default arm flag is to just disable plain irqs */
79 #define ARCH_DEFAULT_SPIN_LOCK_FLAG_INTERRUPTS  SPIN_LOCK_FLAG_IRQ
80 
81 enum {
82     /* private */
83     SPIN_LOCK_STATE_RESTORE_IRQ = 1,
84     SPIN_LOCK_STATE_RESTORE_FIQ = 2,
85 };
86 
87 static inline void
arch_interrupt_save(spin_lock_saved_state_t * statep,spin_lock_save_flags_t flags)88 arch_interrupt_save(spin_lock_saved_state_t *statep, spin_lock_save_flags_t flags)
89 {
90     spin_lock_saved_state_t state = 0;
91     if ((flags & SPIN_LOCK_FLAG_IRQ) && !arch_ints_disabled()) {
92         state |= SPIN_LOCK_STATE_RESTORE_IRQ;
93         arch_disable_ints();
94     }
95     if ((flags & SPIN_LOCK_FLAG_FIQ) && !arch_fiqs_disabled()) {
96         state |= SPIN_LOCK_STATE_RESTORE_FIQ;
97         arch_disable_fiqs();
98     }
99     *statep = state;
100 }
101 
102 static inline void
arch_interrupt_restore(spin_lock_saved_state_t old_state,spin_lock_save_flags_t flags)103 arch_interrupt_restore(spin_lock_saved_state_t old_state, spin_lock_save_flags_t flags)
104 {
105     if ((flags & SPIN_LOCK_FLAG_FIQ) && (old_state & SPIN_LOCK_STATE_RESTORE_FIQ))
106         arch_enable_fiqs();
107     if ((flags & SPIN_LOCK_FLAG_IRQ) && (old_state & SPIN_LOCK_STATE_RESTORE_IRQ))
108         arch_enable_ints();
109 }
110 
111 __END_CDECLS;
112