更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_atomic.h
浏览该文件的文档.
1/*!
2 * @file los_atomic.h
3 * @brief 原子操作
4 * @link atomic http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-basic-atomic.html @endlink
5 @verbatim
6 基本概念
7 在支持多任务的操作系统中,修改一块内存区域的数据需要“读取-修改-写入”三个步骤。
8 然而同一内存区域的数据可能同时被多个任务访问,如果在修改数据的过程中被其他任务打断,
9 就会造成该操作的执行结果无法预知。
10 使用开关中断的方法固然可以保证多任务执行结果符合预期,但这种方法显然会影响系统性能。
11 ARMv6架构引入了LDREX和STREX指令,以支持对共享存储器更缜密的非阻塞同步。由此实现的
12 原子操作能确保对同一数据的“读取-修改-写入”操作在它的执行期间不会被打断,即操作的原子性。
13
14 使用场景
15 有多个任务对同一个内存数据进行加减或交换操作时,使用原子操作保证结果的可预知性。
16
17 汇编指令
18 LDREX Rx, [Ry]
19 读取内存中的值,并标记对该段内存为独占访问:
20 读取寄存器Ry指向的4字节内存数据,保存到Rx寄存器中。
21 对Ry指向的内存区域添加独占访问标记。
22
23 STREX Rf, Rx, [Ry]
24 检查内存是否有独占访问标记,如果有则更新内存值并清空标记,否则不更新内存:
25 有独占访问标记
26 将寄存器Rx中的值更新到寄存器Ry指向的内存。
27 标志寄存器Rf置为0。
28 没有独占访问标记
29 不更新内存。
30 标志寄存器Rf置为1。
31
32 判断标志寄存器
33 标志寄存器为0时,退出循环,原子操作结束。
34 标志寄存器为1时,继续循环,重新进行原子操作。
35
36 有多个任务对同一个内存数据进行加减或交换等操作时,使用原子操作保证结果的可预知性。
37
38 volatile关键字在用C语言编写嵌入式软件里面用得很多,不使用volatile关键字的代码比使用volatile关键字的代码效率要高一些,
39 但就无法保证数据的一致性。volatile的本意是告诉编译器,此变量的值是易变的,每次读写该变量的值时务必从该变量的内存地址中读取或写入,
40 不能为了效率使用对一个“临时”变量的读写来代替对该变量的直接读写。编译器看到了volatile关键字,就一定会生成内存访问指令,
41 每次读写该变量就一定会执行内存访问指令直接读写该变量。若是没有volatile关键字,编译器为了效率,
42 只会在循环开始前使用读内存指令将该变量读到寄存器中,之后在循环内都是用寄存器访问指令来操作这个“临时”变量,
43 在循环结束后再使用内存写指令将这个寄存器中的“临时”变量写回内存。在这个过程中,如果内存中的这个变量被别的因素
44 (其他线程、中断函数、信号处理函数、DMA控制器、其他硬件设备)所改变了,就产生数据不一致的问题。另外,
45 寄存器访问指令的速度要比内存访问指令的速度快,这里说的内存也包括缓存,也就是说内存访问指令实际上也有可能访问的是缓存里的数据,
46 但即便如此,还是不如访问寄存器快的。缓存对于编译器也是透明的,编译器使用内存读写指令时只会认为是在读写内存,
47 内存和缓存间的数据同步由CPU保证。
48
49 @endverbatim
50 * @attention 原子操作中,操作数及其结果不能超过函数所支持位数的最大值。目前原子操作接口只支持整型数据。
51 * @version
52 * @author weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
53 * @date 2021-11-26
54 */
55/*
56 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
57 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
58 *
59 * Redistribution and use in source and binary forms, with or without modification,
60 * are permitted provided that the following conditions are met:
61 *
62 * 1. Redistributions of source code must retain the above copyright notice, this list of
63 * conditions and the following disclaimer.
64 *
65 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
66 * of conditions and the following disclaimer in the documentation and/or other materials
67 * provided with the distribution.
68 *
69 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
70 * to endorse or promote products derived from this software without specific prior written
71 * permission.
72 *
73 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
74 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
75 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
76 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
78 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
79 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
80 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
81 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
82 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
83 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
84 */
85
86/**
87 * @defgroup los_atomic Atomic
88 * @ingroup kernel
89 */
90
91#ifndef __LOS_ATOMIC_H__
92#define __LOS_ATOMIC_H__
93
94#include "los_typedef.h"
95
96#ifdef __cplusplus
97#if __cplusplus
98extern "C" {
99#endif /* __cplusplus */
100#endif /* __cplusplus */
101
102typedef volatile INT32 Atomic; //原子数据包含两种类型Atomic(有符号32位数)与 Atomic64(有符号64位数)
103typedef volatile INT64 Atomic64;
104
105/**
106 * @ingroup los_atomic
107 * @brief Atomic read. | 读取32bit原子数据
108 *
109 * @par Description:
110 * This API is used to implement the atomic read and return the result value of the read.
111 * @attention
112 * <ul>
113 * <li>The pointer v must not be NULL.</li>
114 * </ul>
115 *
116 * @param v [IN] The reading pointer.
117 *
118 * @retval #INT32 The result value of the read.
119 * @par Dependency:
120 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
121 * @see
122 */
123STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)
124{
125 return *(volatile INT32 *)v; //读取内存数据
126}
127
128/**
129 * @ingroup los_atomic
130 * @brief Atomic setting.
131 *
132 * @par Description:
133 * This API is used to implement the atomic setting operation.
134 * @attention
135 * <ul>
136 * <li>The pointer v must not be NULL.</li>
137 * </ul>
138 *
139 * @param v [IN] The variable pointer to be setting.
140 * @param setVal [IN] The value to be setting.
141 *
142 * @retval none.
143 * @par Dependency:
144 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
145 * @see
146 */ //写入内存数据
147STATIC INLINE VOID LOS_AtomicSet(Atomic *v, INT32 setVal)
148{
149 *(volatile INT32 *)v = setVal;
150}
151
152/**
153 * @ingroup los_atomic
154 * @brief Atomic addition.
155 *
156 * @par Description:
157 * This API is used to implement the atomic addition and return the result value of the augend.
158 * @attention
159 * <ul>
160 * <li>The pointer v must not be NULL.</li>
161 * <li>If the addtion result is not in the range of representable values for 32-bit signed integer,
162 * an int integer overflow may occur to the return value</li>
163 * </ul>
164 *
165 * @param v [IN] The augend pointer.
166 * @param addVal [IN] The addend.
167 *
168 * @retval #INT32 The result value of the augend.
169 * @par Dependency:
170 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
171 * @see
172 */ //对内存数据做加法
173STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal)
174{
175 INT32 val;
176 UINT32 status;
177
178 do {
179 __asm__ __volatile__("ldrex %1, [%2]\n"
180 "add %1, %1, %3\n"
181 "strex %0, %1, [%2]"
182 : "=&r"(status), "=&r"(val)
183 : "r"(v), "r"(addVal)
184 : "cc");
185 } while (__builtin_expect(status != 0, 0));
186 /****************************************************
187 __builtin_expect是结束循环的判断语句,将最有可能执行的分支告诉编译器。
188 这个指令的写法为:__builtin_expect(EXP, N)。
189 意思是:EXP==N 的概率很大。
190 综合理解__builtin_expect(status != 0, 0)
191 说的是status = 0 的可能性很大,不成功就会重新来一遍,直到strex更新成(status == 0)为止.
192 ****************************************************/
193 return val;
194}
195
196/**
197 * @ingroup los_atomic
198 * @brief Atomic subtraction.
199 *
200 * @par Description:
201 * This API is used to implement the atomic subtraction and return the result value of the minuend.
202 * @attention
203 * <ul>
204 * <li>The pointer v must not be NULL.</li>
205 * <li>If the subtraction result is not in the range of representable values for 32-bit signed integer,
206 * an int integer overflow may occur to the return value</li>
207 * </ul>
208 *
209 * @param v [IN] The minuend pointer.
210 * @param subVal [IN] The subtrahend.
211 *
212 * @retval #INT32 The result value of the minuend.
213 * @par Dependency:
214 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
215 * @see
216 */ //对内存数据做减法
217STATIC INLINE INT32 LOS_AtomicSub(Atomic *v, INT32 subVal)
218{
219 INT32 val;
220 UINT32 status;
221
222 do {
223 __asm__ __volatile__("ldrex %1, [%2]\n"
224 "sub %1, %1, %3\n"
225 "strex %0, %1, [%2]"
226 : "=&r"(status), "=&r"(val)
227 : "r"(v), "r"(subVal)
228 : "cc");
229 } while (__builtin_expect(status != 0, 0));
230
231 return val;
232}
233
234/**
235 * @ingroup los_atomic
236 * @brief Atomic addSelf.
237 *
238 * @par Description:
239 * This API is used to implement the atomic addSelf.
240 * @attention
241 * <ul>
242 * <li>The pointer v must not be NULL.</li>
243 * <li>The value which v point to must not be INT_MAX to avoid integer overflow after adding 1.</li>
244 * </ul>
245 *
246 * @param v [IN] The addSelf variable pointer.
247 *
248 * @retval none.
249 * @par Dependency:
250 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
251 * @see
252 */ //对内存数据加1
253STATIC INLINE VOID LOS_AtomicInc(Atomic *v)
254{
255 INT32 val;
256 UINT32 status;
257
258 do {
259 __asm__ __volatile__("ldrex %0, [%3]\n"
260 "add %0, %0, #1\n"
261 "strex %1, %0, [%3]"
262 : "=&r"(val), "=&r"(status), "+m"(*v)
263 : "r"(v)
264 : "cc");
265 } while (__builtin_expect(status != 0, 0));
266}
267
268/**
269 * @ingroup los_atomic
270 * @brief Atomic addSelf. | 对内存数据加1并返回运算结果
271 *
272 * @par Description:
273 * This API is used to implement the atomic addSelf and return the result of addSelf.
274 * @attention
275 * <ul>
276 * <li>The pointer v must not be NULL.</li>
277 * <li>The value which v point to must not be INT_MAX to avoid integer overflow after adding 1.</li>
278 * </ul>
279 *
280 * @param v [IN] The addSelf variable pointer.
281 *
282 * @retval #INT32 The return value of variable addSelf.
283 * @par Dependency:
284 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
285 * @see
286 */
287STATIC INLINE INT32 LOS_AtomicIncRet(Atomic *v)
288{
289 INT32 val;
290 UINT32 status;
291
292 do {
293 __asm__ __volatile__("ldrex %0, [%3]\n"
294 "add %0, %0, #1\n"
295 "strex %1, %0, [%3]"
296 : "=&r"(val), "=&r"(status), "+m"(*v)
297 : "r"(v)
298 : "cc");
299 } while (__builtin_expect(status != 0, 0));
300
301 return val;
302}
303
304/**
305 * @ingroup los_atomic
306 * @brief Atomic auto-decrement. | 对32bit原子数据做减1
307 *
308 * @par Description:
309 * This API is used to implementating the atomic auto-decrement.
310 * @attention
311 * <ul>
312 * <li>The pointer v must not be NULL.</li>
313 * <li>The value which v point to must not be INT_MIN to avoid overflow after reducing 1.</li>
314 * </ul>
315 *
316 * @param v [IN] The auto-decrement variable pointer.
317 *
318 * @retval none.
319 * @par Dependency:
320 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
321 * @see
322 */
323STATIC INLINE VOID LOS_AtomicDec(Atomic *v)
324{
325 INT32 val;
326 UINT32 status;
327
328 do {
329 __asm__ __volatile__("ldrex %0, [%3]\n"
330 "sub %0, %0, #1\n"
331 "strex %1, %0, [%3]"
332 : "=&r"(val), "=&r"(status), "+m"(*v)
333 : "r"(v)
334 : "cc");
335 } while (__builtin_expect(status != 0, 0));
336}
337
338/**
339 * @ingroup los_atomic
340 * @brief Atomic auto-decrement. | 对内存数据减1并返回运算结果
341 *
342 * @par Description:
343 * This API is used to implementating the atomic auto-decrement and return the result of auto-decrement.
344 * @attention
345 * <ul>
346 * <li>The pointer v must not be NULL.</li>
347 * <li>The value which v point to must not be INT_MIN to avoid overflow after reducing 1.</li>
348 * </ul>
349 *
350 * @param v [IN] The auto-decrement variable pointer.
351 *
352 * @retval #INT32 The return value of variable auto-decrement.
353 * @par Dependency:
354 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
355 * @see
356 */
357STATIC INLINE INT32 LOS_AtomicDecRet(Atomic *v)
358{
359 INT32 val;
360 UINT32 status;
361
362 do {
363 __asm__ __volatile__("ldrex %0, [%3]\n"
364 "sub %0, %0, #1\n"
365 "strex %1, %0, [%3]"
366 : "=&r"(val), "=&r"(status), "+m"(*v)
367 : "r"(v)
368 : "cc");
369 } while (__builtin_expect(status != 0, 0));
370
371 return val;
372}
373
374/**
375 * @ingroup los_atomic
376 * @brief Atomic64 read. | 读取64bit原子数据
377 *
378 * @par Description:
379 * This API is used to implement the atomic64 read and return the result value of the read.
380 * @attention
381 * <ul>
382 * <li>The pointer v must not be NULL.</li>
383 * </ul>
384 *
385 * @param v [IN] The reading pointer.
386 *
387 * @retval #INT64 The result value of the read.
388 * @par Dependency:
389 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
390 * @see
391 */
392STATIC INLINE INT64 LOS_Atomic64Read(const Atomic64 *v)
393{
394 INT64 val;
395
396 do {
397 __asm__ __volatile__("ldrexd %0, %H0, [%1]"
398 : "=&r"(val)
399 : "r"(v)
400 : "cc");
401 } while (0);
402
403 return val;
404}
405
406/**
407 * @ingroup los_atomic
408 * @brief Atomic64 setting. | 写入64位内存数据
409 *
410 * @par Description:
411 * This API is used to implement the atomic64 setting operation.
412 * @attention
413 * <ul>
414 * <li>The pointer v must not be NULL.</li>
415 * </ul>
416 *
417 * @param v [IN] The variable pointer to be setting.
418 * @param setVal [IN] The value to be setting.
419 *
420 * @retval none.
421 * @par Dependency:
422 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
423 * @see
424 */
425STATIC INLINE VOID LOS_Atomic64Set(Atomic64 *v, INT64 setVal)
426{
427 INT64 tmp;
428 UINT32 status;
429
430 do {
431 __asm__ __volatile__("ldrexd %1, %H1, [%2]\n"
432 "strexd %0, %3, %H3, [%2]"
433 : "=&r"(status), "=&r"(tmp)
434 : "r"(v), "r"(setVal)
435 : "cc");
436 } while (__builtin_expect(status != 0, 0));
437}
438
439/**
440 * @ingroup los_atomic
441 * @brief Atomic64 addition. | 对64位内存数据做加法
442 *
443 * @par Description:
444 * This API is used to implement the atomic64 addition and return the result value of the augend.
445 * @attention
446 * <ul>
447 * <li>The pointer v must not be NULL.</li>
448 * <li>If the addtion result is not in the range of representable values for 64-bit signed integer,
449 * an int integer overflow may occur to the return value</li>
450 * </ul>
451 *
452 * @param v [IN] The augend pointer.
453 * @param addVal [IN] The addend.
454 *
455 * @retval #INT64 The result value of the augend.
456 * @par Dependency:
457 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
458 * @see
459 */
460STATIC INLINE INT64 LOS_Atomic64Add(Atomic64 *v, INT64 addVal)
461{
462 INT64 val;
463 UINT32 status;
464
465 do {
466 __asm__ __volatile__("ldrexd %1, %H1, [%2]\n"
467 "adds %Q1, %Q1, %Q3\n"
468 "adc %R1, %R1, %R3\n"
469 "strexd %0, %1, %H1, [%2]"
470 : "=&r"(status), "=&r"(val)
471 : "r"(v), "r"(addVal)
472 : "cc");
473 } while (__builtin_expect(status != 0, 0));
474
475 return val;
476}
477
478/**
479 * @ingroup los_atomic
480 * @brief Atomic64 subtraction. | 对64位原子数据做减法
481 *
482 * @par Description:
483 * This API is used to implement the atomic64 subtraction and return the result value of the minuend.
484 * @attention
485 * <ul>
486 * <li>The pointer v must not be NULL.</li>
487 * <li>If the subtraction result is not in the range of representable values for 64-bit signed integer,
488 * an int integer overflow may occur to the return value</li>
489 * </ul>
490 *
491 * @param v [IN] The minuend pointer.
492 * @param subVal [IN] The subtrahend.
493 *
494 * @retval #INT64 The result value of the minuend.
495 * @par Dependency:
496 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
497 * @see
498 */
499STATIC INLINE INT64 LOS_Atomic64Sub(Atomic64 *v, INT64 subVal)
500{
501 INT64 val;
502 UINT32 status;
503
504 do {
505 __asm__ __volatile__("ldrexd %1, %H1, [%2]\n"
506 "subs %Q1, %Q1, %Q3\n"
507 "sbc %R1, %R1, %R3\n"
508 "strexd %0, %1, %H1, [%2]"
509 : "=&r"(status), "=&r"(val)
510 : "r"(v), "r"(subVal)
511 : "cc");
512 } while (__builtin_expect(status != 0, 0));
513
514 return val;
515}
516
517/**
518 * @ingroup los_atomic
519 * @brief Atomic64 addSelf. | 对64位原子数据加1
520 *
521 * @par Description:
522 * This API is used to implement the atomic64 addSelf .
523 * @attention
524 * <ul>
525 * <li>The pointer v must not be NULL.</li>
526 * <li>The value which v point to must not be INT64_MAX to avoid integer overflow after adding 1.</li>
527 * </ul>
528 *
529 * @param v [IN] The addSelf variable pointer.
530 *
531 * @retval none.
532 * @par Dependency:
533 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
534 * @see
535 */
536STATIC INLINE VOID LOS_Atomic64Inc(Atomic64 *v)
537{
538 INT64 val;
539 UINT32 status;
540
541 do {
542 __asm__ __volatile__("ldrexd %0, %H0, [%3]\n"
543 "adds %Q0, %Q0, #1\n"
544 "adc %R0, %R0, #0\n"
545 "strexd %1, %0, %H0, [%3]"
546 : "=&r"(val), "=&r"(status), "+m"(*v)
547 : "r"(v)
548 : "cc");
549 } while (__builtin_expect(status != 0, 0));
550}
551
552/**
553 * @ingroup los_atomic
554 * @brief Atomic64 addSelf. | 对64位原子数据加1并返回运算结果
555 *
556 * @par Description:
557 * This API is used to implement the atomic64 addSelf and return the result of addSelf.
558 * @attention
559 * <ul>
560 * <li>The pointer v must not be NULL.</li>
561 * <li>The value which v point to must not be INT64_MAX to avoid integer overflow after adding 1.</li>
562 * </ul>
563 *
564 * @param v [IN] The addSelf variable pointer.
565 *
566 * @retval #INT64 The return value of variable addSelf.
567 * @par Dependency:
568 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
569 * @see
570 */
572{
573 INT64 val;
574 UINT32 status;
575
576 do {
577 __asm__ __volatile__("ldrexd %0, %H0, [%3]\n"
578 "adds %Q0, %Q0, #1\n"
579 "adc %R0, %R0, #0\n"
580 "strexd %1, %0, %H0, [%3]"
581 : "=&r"(val), "=&r"(status), "+m"(*v)
582 : "r"(v)
583 : "cc");
584 } while (__builtin_expect(status != 0, 0));
585
586 return val;
587}
588
589/**
590 * @ingroup los_atomic
591 * @brief Atomic64 auto-decrement. | 对64位原子数据减1
592 *
593 * @par Description:
594 * This API is used to implementating the atomic64 auto-decrement.
595 * @attention
596 * <ul>
597 * <li>The pointer v must not be NULL.</li>
598 * <li>The value which v point to must not be INT64_MIN to avoid overflow after reducing 1.</li>
599 * </ul>
600 *
601 * @param v [IN] The auto-decrement variable pointer.
602 *
603 * @retval none.
604 * @par Dependency:
605 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
606 * @see
607 */
608STATIC INLINE VOID LOS_Atomic64Dec(Atomic64 *v)
609{
610 INT64 val;
611 UINT32 status;
612
613 do {
614 __asm__ __volatile__("ldrexd %0, %H0, [%3]\n"
615 "subs %Q0, %Q0, #1\n"
616 "sbc %R0, %R0, #0\n"
617 "strexd %1, %0, %H0, [%3]"
618 : "=&r"(val), "=&r"(status), "+m"(*v)
619 : "r"(v)
620 : "cc");
621 } while (__builtin_expect(status != 0, 0));
622}
623
624/**
625 * @ingroup los_atomic
626 * @brief Atomic64 auto-decrement. | 对64位原子数据减1并返回运算结果
627 *
628 * @par Description:
629 * This API is used to implementating the atomic64 auto-decrement and return the result of auto-decrement.
630 * @attention
631 * <ul>
632 * <li>The pointer v must not be NULL.</li>
633 * <li>The value which v point to must not be INT64_MIN to avoid overflow after reducing 1.</li>
634 * </ul>
635 *
636 * @param v [IN] The auto-decrement variable pointer.
637 *
638 * @retval #INT64 The return value of variable auto-decrement.
639 * @par Dependency:
640 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
641 * @see
642 */
644{
645 INT64 val;
646 UINT32 status;
647
648 do {
649 __asm__ __volatile__("ldrexd %0, %H0, [%3]\n"
650 "subs %Q0, %Q0, #1\n"
651 "sbc %R0, %R0, #0\n"
652 "strexd %1, %0, %H0, [%3]"
653 : "=&r"(val), "=&r"(status), "+m"(*v)
654 : "r"(v)
655 : "cc");
656 } while (__builtin_expect(status != 0, 0));
657
658 return val;
659}
660
661/**
662 * @ingroup los_atomic
663 * @brief Atomic exchange for 8-bit variable. | 交换8位原子数据,原内存中的值以返回值的方式返回
664 *
665 * @par Description:
666 * This API is used to implement the atomic exchange for 8-bit variable and
667 * return the previous value of the atomic variable.
668 * @attention
669 * <ul>The pointer v must not be NULL.</ul>
670 *
671 * @param v [IN] The variable pointer.
672 * @param val [IN] The exchange value.
673 *
674 * @retval #INT32 The previous value of the atomic variable
675 * @par Dependency:
676 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
677 * @see
678 */
679STATIC INLINE INT32 LOS_AtomicXchgByte(volatile INT8 *v, INT32 val)
680{
681 INT32 prevVal;
682 UINT32 status;
683
684 do {
685 __asm__ __volatile__("ldrexb %0, [%3]\n"
686 "strexb %1, %4, [%3]"
687 : "=&r"(prevVal), "=&r"(status), "+m"(*v)
688 : "r"(v), "r"(val)
689 : "cc");
690 } while (__builtin_expect(status != 0, 0));
691
692 return prevVal;
693}
694
695/**
696 * @ingroup los_atomic
697 * @brief Atomic exchange for 16-bit variable. | 交换16位原子数据,原内存中的值以返回值的方式返回
698 *
699 * @par Description:
700 * This API is used to implement the atomic exchange for 16-bit variable and
701 * return the previous value of the atomic variable.
702 * @attention
703 * <ul>The pointer v must not be NULL.</ul>
704 *
705 * @param v [IN] The variable pointer.
706 * @param val [IN] The exchange value.
707 *
708 * @retval #INT32 The previous value of the atomic variable
709 * @par Dependency:
710 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
711 * @see
712 */
713STATIC INLINE INT32 LOS_AtomicXchg16bits(volatile INT16 *v, INT32 val)
714{
715 INT32 prevVal;
716 UINT32 status;
717
718 do {
719 __asm__ __volatile__("ldrexh %0, [%3]\n"
720 "strexh %1, %4, [%3]"
721 : "=&r"(prevVal), "=&r"(status), "+m"(*v)
722 : "r"(v), "r"(val)
723 : "cc");
724 } while (__builtin_expect(status != 0, 0));
725
726 return prevVal;
727}
728
729/**
730 * @ingroup los_atomic
731 * @brief Atomic exchange for 32-bit variable. | 交换32位原子数据,原内存中的值以返回值的方式返回
732 *
733 * @par Description:
734 * This API is used to implement the atomic exchange for 32-bit variable
735 * and return the previous value of the atomic variable.
736 * @attention
737 * <ul>The pointer v must not be NULL.</ul>
738 *
739 * @param v [IN] The variable pointer.
740 * @param val [IN] The exchange value.
741 *
742 * @retval #INT32 The previous value of the atomic variable
743 * @par Dependency:
744 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
745 * @see
746 */
747STATIC INLINE INT32 LOS_AtomicXchg32bits(Atomic *v, INT32 val)
748{
749 INT32 prevVal;
750 UINT32 status;
751
752 do {
753 __asm__ __volatile__("ldrex %0, [%3]\n"
754 "strex %1, %4, [%3]"
755 : "=&r"(prevVal), "=&r"(status), "+m"(*v)
756 : "r"(v), "r"(val)
757 : "cc");
758 } while (__builtin_expect(status != 0, 0));
759
760 return prevVal;
761}
762
763/**
764 * @ingroup los_atomic
765 * @brief Atomic exchange for 64-bit variable. | 交换64位原子数据,原内存中的值以返回值的方式返回
766 *
767 * @par Description:
768 * This API is used to implement the atomic exchange for 64-bit variable
769 * and return the previous value of the atomic variable.
770 * @attention
771 * <ul>The pointer v must not be NULL.</ul>
772 *
773 * @param v [IN] The variable pointer.
774 * @param val [IN] The exchange value.
775 *
776 * @retval #INT64 The previous value of the atomic variable
777 * @par Dependency:
778 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
779 * @see
780 */
782{
783 INT64 prevVal;
784 UINT32 status;
785
786 do {
787 __asm__ __volatile__("ldrexd %0, %H0, [%3]\n"
788 "strexd %1, %4, %H4, [%3]"
789 : "=&r"(prevVal), "=&r"(status), "+m"(*v)
790 : "r"(v), "r"(val)
791 : "cc");
792 } while (__builtin_expect(status != 0, 0));
793
794 return prevVal;
795}
796
797/**
798 * @ingroup los_atomic
799 * @brief Atomic exchange for 8-bit variable with compare. | 比较并交换8位原子数据,返回比较结果
800 *
801 * @par Description:
802 * This API is used to implement the atomic exchange for 8-bit variable, if the value of variable is equal to oldVal.
803 * @attention
804 * <ul>The pointer v must not be NULL.</ul>
805 *
806 * @param v [IN] The variable pointer.
807 * @param val [IN] The new value.
808 * @param oldVal [IN] The old value.
809 *
810 * @retval TRUE The previous value of the atomic variable is not equal to oldVal.
811 * @retval FALSE The previous value of the atomic variable is equal to oldVal.
812 * @par Dependency:
813 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
814 * @see
815 */
816STATIC INLINE BOOL LOS_AtomicCmpXchgByte(volatile INT8 *v, INT32 val, INT32 oldVal)
817{
818 INT32 prevVal;
819 UINT32 status;
820
821 do {
822 __asm__ __volatile__("ldrexb %0, [%3]\n"
823 "mov %1, #0\n"
824 "teq %0, %4\n"
825 "strexbeq %1, %5, [%3]"
826 : "=&r"(prevVal), "=&r"(status), "+m"(*v)
827 : "r"(v), "r"(oldVal), "r"(val)
828 : "cc");
829 } while (__builtin_expect(status != 0, 0));
830
831 return prevVal != oldVal;
832}
833
834/**
835 * @ingroup los_atomic
836 * @brief Atomic exchange for 16-bit variable with compare. | 比较并交换16位原子数据,返回比较结果
837 *
838 * @par Description:
839 * This API is used to implement the atomic exchange for 16-bit variable, if the value of variable is equal to oldVal.
840 * @attention
841 * <ul>The pointer v must not be NULL.</ul>
842 *
843 * @param v [IN] The variable pointer.
844 * @param val [IN] The new value.
845 * @param oldVal [IN] The old value.
846 *
847 * @retval TRUE The previous value of the atomic variable is not equal to oldVal.
848 * @retval FALSE The previous value of the atomic variable is equal to oldVal.
849 * @par Dependency:
850 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
851 * @see
852 */
853STATIC INLINE BOOL LOS_AtomicCmpXchg16bits(volatile INT16 *v, INT32 val, INT32 oldVal)
854{
855 INT32 prevVal;
856 UINT32 status;
857
858 do {
859 __asm__ __volatile__("ldrexh %0, [%3]\n"
860 "mov %1, #0\n"
861 "teq %0, %4\n"
862 "strexheq %1, %5, [%3]"
863 : "=&r"(prevVal), "=&r"(status), "+m"(*v)
864 : "r"(v), "r"(oldVal), "r"(val)
865 : "cc");
866 } while (__builtin_expect(status != 0, 0));
867
868 return prevVal != oldVal;
869}
870
871/**
872 * @ingroup los_atomic
873 * @brief Atomic exchange for 32-bit variable with compare. | 比较并交换32位原子数据,返回比较结果
874 *
875 * @par Description:
876 * This API is used to implement the atomic exchange for 32-bit variable, if the value of variable is equal to oldVal.
877 * @attention
878 * <ul>The pointer v must not be NULL.</ul>
879 *
880 * @param v [IN] The variable pointer.
881 * @param val [IN] The new value.
882 * @param oldVal [IN] The old value.
883 *
884 * @retval TRUE The previous value of the atomic variable is not equal to oldVal.
885 * @retval FALSE The previous value of the atomic variable is equal to oldVal.
886 * @par Dependency:
887 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
888 * @see
889 */
890STATIC INLINE BOOL LOS_AtomicCmpXchg32bits(Atomic *v, INT32 val, INT32 oldVal)
891{
892 INT32 prevVal;
893 UINT32 status;
894
895 do {
896 __asm__ __volatile__("ldrex %0, [%3]\n"
897 "mov %1, #0\n"
898 "teq %0, %4\n"
899 "strexeq %1, %5, [%3]"
900 : "=&r"(prevVal), "=&r"(status), "+m"(*v)
901 : "r"(v), "r"(oldVal), "r"(val)
902 : "cc");
903 } while (__builtin_expect(status != 0, 0));
904
905 return prevVal != oldVal;
906}
907
908/**
909 * @ingroup los_atomic
910 * @brief Atomic exchange for 64-bit variable with compare. | 比较并交换64位原子数据,返回比较结果
911 *
912 * @par Description:
913 * This API is used to implement the atomic exchange for 64-bit variable, if the value of variable is equal to oldVal.
914 * @attention
915 * <ul>The pointer v must not be NULL.</ul>
916 *
917 * @param v [IN] The variable pointer.
918 * @param val [IN] The new value.
919 * @param oldVal [IN] The old value.
920 *
921 * @retval TRUE The previous value of the atomic variable is not equal to oldVal.
922 * @retval FALSE The previous value of the atomic variable is equal to oldVal.
923 * @par Dependency:
924 * <ul><li>los_atomic.h: the header file that contains the API declaration.</li></ul>
925 * @see
926 */
927STATIC INLINE BOOL LOS_AtomicCmpXchg64bits(Atomic64 *v, INT64 val, INT64 oldVal)
928{
929 INT64 prevVal;
930 UINT32 status;
931
932 do {
933 __asm__ __volatile__("ldrexd %0, %H0, [%3]\n"
934 "mov %1, #0\n"
935 "teq %0, %4\n"
936 "teqeq %H0, %H4\n"
937 "strexdeq %1, %5, %H5, [%3]"
938 : "=&r"(prevVal), "=&r"(status), "+m"(*v)
939 : "r"(v), "r"(oldVal), "r"(val)
940 : "cc");
941 } while (__builtin_expect(status != 0, 0));
942
943 return prevVal != oldVal;
944}
945
946#ifdef __cplusplus
947#if __cplusplus
948}
949#endif /* __cplusplus */
950#endif /* __cplusplus */
951
952#endif /* __LOS_ATOMIC_H__ */
STATIC INLINE INT32 LOS_AtomicXchg32bits(Atomic *v, INT32 val)
Atomic exchange for 32-bit variable. | 交换32位原子数据,原内存中的值以返回值的方式返回
Definition: los_atomic.h:747
STATIC INLINE VOID LOS_AtomicInc(Atomic *v)
Atomic addSelf.
Definition: los_atomic.h:253
STATIC INLINE VOID LOS_Atomic64Inc(Atomic64 *v)
Atomic64 addSelf. | 对64位原子数据加1
Definition: los_atomic.h:536
STATIC INLINE INT64 LOS_Atomic64Sub(Atomic64 *v, INT64 subVal)
Atomic64 subtraction. | 对64位原子数据做减法
Definition: los_atomic.h:499
STATIC INLINE INT64 LOS_Atomic64DecRet(Atomic64 *v)
Atomic64 auto-decrement. | 对64位原子数据减1并返回运算结果
Definition: los_atomic.h:643
STATIC INLINE INT64 LOS_Atomic64Add(Atomic64 *v, INT64 addVal)
Atomic64 addition. | 对64位内存数据做加法
Definition: los_atomic.h:460
STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)
Atomic read. | 读取32bit原子数据
Definition: los_atomic.h:123
STATIC INLINE INT64 LOS_Atomic64IncRet(Atomic64 *v)
Atomic64 addSelf. | 对64位原子数据加1并返回运算结果
Definition: los_atomic.h:571
STATIC INLINE VOID LOS_Atomic64Set(Atomic64 *v, INT64 setVal)
Atomic64 setting. | 写入64位内存数据
Definition: los_atomic.h:425
STATIC INLINE BOOL LOS_AtomicCmpXchg32bits(Atomic *v, INT32 val, INT32 oldVal)
Atomic exchange for 32-bit variable with compare. | 比较并交换32位原子数据,返回比较结果
Definition: los_atomic.h:890
STATIC INLINE INT64 LOS_AtomicXchg64bits(Atomic64 *v, INT64 val)
Atomic exchange for 64-bit variable. | 交换64位原子数据,原内存中的值以返回值的方式返回
Definition: los_atomic.h:781
STATIC INLINE VOID LOS_AtomicSet(Atomic *v, INT32 setVal)
Atomic setting.
Definition: los_atomic.h:147
STATIC INLINE VOID LOS_AtomicDec(Atomic *v)
Atomic auto-decrement. | 对32bit原子数据做减1
Definition: los_atomic.h:323
STATIC INLINE INT32 LOS_AtomicDecRet(Atomic *v)
Atomic auto-decrement. | 对内存数据减1并返回运算结果
Definition: los_atomic.h:357
STATIC INLINE BOOL LOS_AtomicCmpXchg16bits(volatile INT16 *v, INT32 val, INT32 oldVal)
Atomic exchange for 16-bit variable with compare. | 比较并交换16位原子数据,返回比较结果
Definition: los_atomic.h:853
STATIC INLINE INT32 LOS_AtomicXchg16bits(volatile INT16 *v, INT32 val)
Atomic exchange for 16-bit variable. | 交换16位原子数据,原内存中的值以返回值的方式返回
Definition: los_atomic.h:713
STATIC INLINE INT32 LOS_AtomicIncRet(Atomic *v)
Atomic addSelf. | 对内存数据加1并返回运算结果
Definition: los_atomic.h:287
STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal)
Atomic addition.
Definition: los_atomic.h:173
STATIC INLINE INT32 LOS_AtomicSub(Atomic *v, INT32 subVal)
Atomic subtraction.
Definition: los_atomic.h:217
STATIC INLINE INT32 LOS_AtomicXchgByte(volatile INT8 *v, INT32 val)
Atomic exchange for 8-bit variable. | 交换8位原子数据,原内存中的值以返回值的方式返回
Definition: los_atomic.h:679
STATIC INLINE INT64 LOS_Atomic64Read(const Atomic64 *v)
Atomic64 read. | 读取64bit原子数据
Definition: los_atomic.h:392
STATIC INLINE VOID LOS_Atomic64Dec(Atomic64 *v)
Atomic64 auto-decrement. | 对64位原子数据减1
Definition: los_atomic.h:608
STATIC INLINE BOOL LOS_AtomicCmpXchgByte(volatile INT8 *v, INT32 val, INT32 oldVal)
Atomic exchange for 8-bit variable with compare. | 比较并交换8位原子数据,返回比较结果
Definition: los_atomic.h:816
STATIC INLINE BOOL LOS_AtomicCmpXchg64bits(Atomic64 *v, INT64 val, INT64 oldVal)
Atomic exchange for 64-bit variable with compare. | 比较并交换64位原子数据,返回比较结果
Definition: los_atomic.h:927
volatile INT64 Atomic64
Definition: los_atomic.h:103
volatile INT32 Atomic
Definition: los_atomic.h:102
signed int INT32
Definition: los_typedef.h:60
signed short INT16
Definition: los_typedef.h:59
signed char INT8
Definition: los_typedef.h:58
unsigned int UINT32
Definition: los_typedef.h:57
size_t BOOL
Definition: los_typedef.h:88
long signed int INT64
Definition: los_typedef.h:67