1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #ifndef __OAL_LINUX_SPINLOCK_H__
20 #define __OAL_LINUX_SPINLOCK_H__
21
22 /* ****************************************************************************
23 1 其他头文件包含
24 **************************************************************************** */
25 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
26 #include <linux/spinlock.h>
27 #endif
28 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
29 #include <los_task.h>
30 #include <los_spinlock.h>
31 #endif
32
33 #ifdef __cplusplus
34 #if __cplusplus
35 extern "C" {
36 #endif
37 #endif
38
39 /* ****************************************************************************
40 2 宏定义
41 **************************************************************************** */
42 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
43 typedef spinlock_t oal_spinlock;
44
45 #define OAL_SPIN_LOCK_MAGIC_TAG (0xdead4ead)
46 typedef struct _oal_spin_lock_stru_ {
47 #ifdef CONFIG_SPIN_LOCK_MAGIC_DEBUG
48 hi_u32 magic;
49 hi_u32 reserved;
50 #endif
51 spinlock_t lock;
52 } oal_spin_lock_stru;
53
54 #ifdef CONFIG_SPIN_LOCK_MAGIC_DEBUG
55 #define OAL_DEFINE_SPINLOCK(x) oal_spin_lock_stru x = { \
56 .magic = OAL_SPIN_LOCK_MAGIC_TAG, \
57 .lock = __SPIN_LOCK_UNLOCKED(x) \
58 }
59 #else
60 #define OAL_DEFINE_SPINLOCK(x) oal_spin_lock_stru x = { \
61 .lock = __SPIN_LOCK_UNLOCKED(x) \
62 }
63 #endif
64
65 /* 函数指针,用来指向需要自旋锁保护的的函数 */
66 typedef hi_u32 (*oal_irqlocked_func)(hi_void *);
67 #endif
68
69 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
70 typedef struct _oal_spin_lock_stru_ {
71 SPIN_LOCK_S lock;
72 } oal_spin_lock_stru;
73
74
oal_spin_lock_init(oal_spin_lock_stru * pst_lock)75 static inline hi_void oal_spin_lock_init(oal_spin_lock_stru *pst_lock)
76 {
77 #ifdef LOSCFG_KERNEL_SMP
78 LOS_SpinInit(&pst_lock->lock);
79 #else
80 (void)pst_lock;
81 #endif
82 }
83
84 /*
85 锁线程调度,支持嵌套
86 */
oal_spin_lock(oal_spin_lock_stru * pst_lock)87 static inline hi_void oal_spin_lock(oal_spin_lock_stru *pst_lock)
88 {
89 #ifdef LOSCFG_KERNEL_SMP
90 LOS_SpinLock(&pst_lock->lock);
91 #else
92 (void)pst_lock;
93 LOS_TaskLock();
94 #endif
95 }
oal_spin_unlock(oal_spin_lock_stru * pst_lock)96 static inline hi_void oal_spin_unlock(oal_spin_lock_stru *pst_lock)
97 {
98 #ifdef LOSCFG_KERNEL_SMP
99 LOS_SpinUnlock(&pst_lock->lock);
100 #else
101 (void)pst_lock;
102 LOS_TaskUnlock();
103 #endif
104 }
105
106 /*
107 锁线程调度,支持嵌套
108 */
oal_spin_lock_bh(oal_spin_lock_stru * pst_lock)109 static inline hi_void oal_spin_lock_bh(oal_spin_lock_stru *pst_lock)
110 {
111 #ifdef LOSCFG_KERNEL_SMP
112 LOS_SpinLock(&pst_lock->lock);
113 #else
114 (void)pst_lock;
115 LOS_TaskLock();
116 #endif
117 }
oal_spin_unlock_bh(oal_spin_lock_stru * pst_lock)118 static inline hi_void oal_spin_unlock_bh(oal_spin_lock_stru *pst_lock)
119 {
120 #ifdef LOSCFG_KERNEL_SMP
121 LOS_SpinUnlock(&pst_lock->lock);
122 #else
123 (void)pst_lock;
124 LOS_TaskUnlock();
125 #endif
126 }
127
128 /*
129 锁硬件中断,支持嵌套
130 */
oal_spin_lock_irq_save(oal_spin_lock_stru * pst_lock,unsigned long * flags)131 static inline hi_void oal_spin_lock_irq_save(oal_spin_lock_stru *pst_lock, unsigned long *flags)
132 {
133 #ifdef LOSCFG_KERNEL_SMP
134 LOS_SpinLockSave(&pst_lock->lock, (UINT32 *)flags);
135 #else
136 (void)pst_lock;
137 *flags = LOS_IntLock();
138 #endif
139 }
oal_spin_unlock_irq_restore(oal_spin_lock_stru * pst_lock,unsigned long * flags)140 static inline hi_void oal_spin_unlock_irq_restore(oal_spin_lock_stru *pst_lock, unsigned long *flags)
141 {
142 #ifdef LOSCFG_KERNEL_SMP
143 LOS_SpinUnlockRestore(&pst_lock->lock, (UINT32)*flags);
144 #else
145 (void)pst_lock;
146 LOS_IntRestore(*flags);
147 #endif
148 }
149 #endif
150
151 /* ****************************************************************************
152 3 枚举定义
153 **************************************************************************** */
154 /* ****************************************************************************
155 4 全局变量声明
156 **************************************************************************** */
157 /* ****************************************************************************
158 5 消息头定义
159 **************************************************************************** */
160 /* ****************************************************************************
161 6 消息定义
162 **************************************************************************** */
163 /* ****************************************************************************
164 7 STRUCT定义
165 **************************************************************************** */
166 /* ****************************************************************************
167 8 UNION定义
168 **************************************************************************** */
169 /* ****************************************************************************
170 9 OTHERS定义
171 **************************************************************************** */
172 /* ****************************************************************************
173 10 函数声明
174 **************************************************************************** */
175 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
176 /* ****************************************************************************
177 功能描述 : 自旋锁初始化,把自旋锁设置为1(未锁状态)。
178 输入参数 : *pst_lock: 锁的地址
179 输出参数 : 无
180 返 回 值 : 无
181 **************************************************************************** */
oal_spin_lock_init(oal_spin_lock_stru * pst_lock)182 static inline hi_void oal_spin_lock_init(oal_spin_lock_stru *pst_lock)
183 {
184 spin_lock_init(&pst_lock->lock);
185 #ifdef CONFIG_SPIN_LOCK_MAGIC_DEBUG
186 pst_lock->magic = OAL_SPIN_LOCK_MAGIC_TAG;
187 #endif
188 }
189 #define SPIN_LOCK_CONSTANT (32)
oal_spin_lock_magic_bug(oal_spin_lock_stru * pst_lock)190 static inline hi_void oal_spin_lock_magic_bug(oal_spin_lock_stru *pst_lock)
191 {
192 #ifdef CONFIG_SPIN_LOCK_MAGIC_DEBUG
193 if (oal_unlikely((hi_u32)OAL_SPIN_LOCK_MAGIC_TAG != pst_lock->magic)) {
194 #ifdef CONFIG_PRINTK
195 /* spinlock never init or memory overwrite */
196 printk(KERN_EMERG "[E]SPIN_LOCK_BUG: spinlock:%p on CPU#%d, %s,magic:%08x should be %08x\n", pst_lock,
197 raw_smp_processor_id(), current->comm, pst_lock->magic, OAL_SPIN_LOCK_MAGIC_TAG);
198 print_hex_dump(KERN_EMERG, "spinlock_magic: ", DUMP_PREFIX_ADDRESS, 16, 1, /* 16:hex */
199 (hi_u8 *)((uintptr_t)pst_lock - SPIN_LOCK_CONSTANT),
200 SPIN_LOCK_CONSTANT + sizeof(oal_spin_lock_stru) + SPIN_LOCK_CONSTANT, true);
201 printk(KERN_EMERG "\n");
202 #endif
203 }
204 #else
205 hi_unref_param(pst_lock);
206 #endif
207 }
208
209 /* ****************************************************************************
210 功能描述 : 自旋锁在软中断以及内核线程等核心态上下文环境下的加锁操作。如果
211 能够立即获得锁,它就马上返回,否则,它将自旋在那里,直到该自旋
212 锁的保持者释放,这时,它获得锁并返回。
213 输入参数 : *pst_lock:自旋锁地址
214 输出参数 : 无
215 返 回 值 : 无
216 **************************************************************************** */
oal_spin_lock(oal_spin_lock_stru * pst_lock)217 static inline hi_void oal_spin_lock(oal_spin_lock_stru *pst_lock)
218 {
219 oal_spin_lock_magic_bug(pst_lock);
220 spin_lock(&pst_lock->lock);
221 }
222
223 /* ****************************************************************************
224 功能描述 : Spinlock在内核线程等核心态上下文环境下的解锁操作。
225 输入参数 : *pst_lock:自旋锁地址
226 输出参数 : 无
227 返 回 值 : 无
228 **************************************************************************** */
oal_spin_unlock(oal_spin_lock_stru * pst_lock)229 static inline hi_void oal_spin_unlock(oal_spin_lock_stru *pst_lock)
230 {
231 oal_spin_lock_magic_bug(pst_lock);
232 spin_unlock(&pst_lock->lock);
233 }
234
235 /* ****************************************************************************
236 功能描述 : 自旋锁在软中断以及内核线程等核心态上下文环境下的加锁操作。如果
237 能够立即获得锁,它就马上返回,否则,它将自旋在那里,直到该自旋
238 锁的保持者释放,这时,它获得锁并返回。
239 输入参数 : pst_lock:自旋锁地址
240 输出参数 : 无
241 返 回 值 : 无
242 **************************************************************************** */
oal_spin_lock_bh(oal_spin_lock_stru * pst_lock)243 static inline hi_void oal_spin_lock_bh(oal_spin_lock_stru *pst_lock)
244 {
245 oal_spin_lock_magic_bug(pst_lock);
246 spin_lock_bh(&pst_lock->lock);
247 }
248
249 /* ****************************************************************************
250 功能描述 : Spinlock在软中断以及内核线程等核心态上下文环境下的解锁操作。
251 输入参数 : 无
252 输出参数 : 无
253 返 回 值 : hi_void
254 **************************************************************************** */
oal_spin_unlock_bh(oal_spin_lock_stru * pst_lock)255 static inline hi_void oal_spin_unlock_bh(oal_spin_lock_stru *pst_lock)
256 {
257 oal_spin_lock_magic_bug(pst_lock);
258 spin_unlock_bh(&pst_lock->lock);
259 }
260
261 /* ****************************************************************************
262 功能描述 : 获得自旋锁的同时获得保存标志寄存器的值,并且失效本地中断。
263 输入参数 : *pst_lock:自旋锁地址
264 pui_flags:标志寄存器
265 输出参数 : 无
266 返 回 值 : 无
267 **************************************************************************** */
oal_spin_lock_irq_save(oal_spin_lock_stru * pst_lock,unsigned long * pui_flags)268 static inline hi_void oal_spin_lock_irq_save(oal_spin_lock_stru *pst_lock, unsigned long *pui_flags)
269 {
270 oal_spin_lock_magic_bug(pst_lock);
271 spin_lock_irqsave(&pst_lock->lock, *pui_flags);
272 }
273
274 /* ****************************************************************************
275 功能描述 : 释放自旋锁的同时,恢复标志寄存器的值,恢复本地中断。它与oal_sp-
276 in_lock_irq配对使用
277 输入参数 : *pst_lock:自旋锁地址
278 pui_flags:标志寄存器
279 输出参数 : 无
280 返 回 值 : 无
281 **************************************************************************** */
oal_spin_unlock_irq_restore(oal_spin_lock_stru * pst_lock,unsigned long * pui_flags)282 static inline hi_void oal_spin_unlock_irq_restore(oal_spin_lock_stru *pst_lock, unsigned long *pui_flags)
283 {
284 oal_spin_lock_magic_bug(pst_lock);
285 spin_unlock_irqrestore(&pst_lock->lock, *pui_flags);
286 }
287
288 /* ****************************************************************************
289 功能描述 : 获取自旋锁,关闭中断,执行某个函数,完了之后再打开中断,释放自
290 旋锁。
291 输入参数 : *pst_lock:自旋锁地址
292 func:函数指针地址
293 *p_arg:函数参数
294 *pui_flags: 中断标志寄存器
295 输出参数 : 无
296 返 回 值 :
297 **************************************************************************** */
oal_spin_lock_irq_exec(oal_spin_lock_stru * pst_lock,oal_irqlocked_func func,hi_void * p_arg,unsigned long * pui_flags)298 static inline hi_u32 oal_spin_lock_irq_exec(oal_spin_lock_stru *pst_lock, oal_irqlocked_func func, hi_void *p_arg,
299 unsigned long *pui_flags)
300 {
301 hi_u32 ul_rslt;
302
303 spin_lock_irqsave(&pst_lock->lock, *pui_flags);
304 ul_rslt = func(p_arg);
305 spin_unlock_irqrestore(&pst_lock->lock, *pui_flags);
306
307 return ul_rslt;
308 }
309 #endif
310
311 #ifdef __cplusplus
312 #if __cplusplus
313 }
314 #endif
315 #endif
316
317 #endif /* end of oal_spinlock.h */
318