You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LiteOS-Reading/src/kernel/include/arch_generic/atomic.h

330 lines
8.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2013-2020. All rights reserved.
* Description: Aarch32 Atomic HeadFile
* Author: Huawei LiteOS Team
* Create: 2013-01-01
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
/**
* @defgroup los_atomic Atomic
* @ingroup kernel
*/
//在LiteOS操作系统中atomic.h头文件通常用于提供原子操作的支持。原子操作是不可中断的操作它可以确保在多线程环境中对共享资源进行安全的访问和修改。
#ifndef _ARCH_GENERIC_ATOMIC_H
#define _ARCH_GENERIC_ATOMIC_H
#include "los_typedef.h"
#include "los_hwi.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifndef LOSCFG_KERNEL_SMP
/*ArchAtomicRead 函数用于原子读取一个整数变量的值。
它将一个指向原子变量的指针 v 强制转换为 volatile INT32 类型的指针,
并返回该指针所指向的值。*/
STATIC INLINE INT32 ArchAtomicRead(const Atomic *v)
{
return *(volatile INT32 *)v;
}
/*ArchAtomicSet 函数用于原子设置一个整数变量的值。
它将一个指向原子变量的指针 v 强制转换为 volatile INT32 类型的指针,
并将 setVal 的值赋给该指针所指向的变量。*/
STATIC INLINE VOID ArchAtomicSet(Atomic *v, INT32 setVal)
{
*(volatile INT32 *)v = setVal;
}
/*ArchAtomicAdd 函数用于原子增加一个整数变量的值。
它先保存当前中断状态,然后在关闭中断的情况下,将 addVal 加到指针 v 所指向的变量上,
并返回增加后的值。
最后,恢复之前保存的中断状态。*/
STATIC INLINE INT32 ArchAtomicAdd(Atomic *v, INT32 addVal)
{
UINT32 intSave;
intSave = LOS_IntLock();
*v += addVal;
LOS_IntRestore(intSave);
return *v;
}
/*ArchAtomicSub 函数用于原子减少一个整数变量的值。
它的实现与 ArchAtomicAdd 类似,
只是将 subVal 减去指针 v 所指向的变量。*/
STATIC INLINE INT32 ArchAtomicSub(Atomic *v, INT32 subVal)
{
UINT32 intSave;
intSave = LOS_IntLock();
*v -= subVal;
LOS_IntRestore(intSave);
return *v;
}
/*ArchAtomicInc 函数用于原子增加一个整数变量的值。
它首先保存当前中断状态 intSave然后在关闭中断的情况下
将指针 addr 指向的变量加 1
最后恢复之前保存的中断状态。*/
STATIC INLINE VOID ArchAtomicInc(Atomic *addr)
{
UINT32 intSave;
intSave = LOS_IntLock();
*addr += 1;
LOS_IntRestore(intSave);
}
//ArchAtomicIncRet 函数与 ArchAtomicInc 类似,但它还返回增加后的变量值。
STATIC INLINE INT32 ArchAtomicIncRet(Atomic *addr)
{
UINT32 intSave;
intSave = LOS_IntLock();
*addr += 1;
LOS_IntRestore(intSave);
return *addr;
}
//ArchAtomicDec 函数用于原子减少一个整数变量的值。它的实现类似于 ArchAtomicInc只是将指针 addr 指向的变量减 1。
STATIC INLINE VOID ArchAtomicDec(Atomic *addr)
{
UINT32 intSave;
intSave = LOS_IntLock();
*addr -= 1;
LOS_IntRestore(intSave);
}
//ArchAtomicDecRet 函数与 ArchAtomicDec 类似,但它还返回减少后的变量值。
STATIC INLINE INT32 ArchAtomicDecRet(Atomic *addr)
{
UINT32 intSave;
intSave = LOS_IntLock();
*addr -= 1;
LOS_IntRestore(intSave);
return *addr;
}
/*ArchAtomic64Read 函数用于原子读取一个 64 位整数变量的值。
它首先保存当前中断状态 intSave然后在关闭中断的情况下
读取指针 v 指向的 64 位整数变量的值,
最后恢复之前保存的中断状态,并返回读取的值。*/
STATIC INLINE INT64 ArchAtomic64Read(const Atomic64 *v)
{
UINT32 intSave;
INT64 val;
intSave = LOS_IntLock();
val = *v;
LOS_IntRestore(intSave);
return val;
}
/*ArchAtomic64Set 函数用于原子设置一个 64 位整数变量的值为 setVal。
它首先保存当前中断状态 intSave然后在关闭中断的情况下
将指针 v 指向的变量设置为 setVal
最后恢复之前保存的中断状态。*/
STATIC INLINE VOID ArchAtomic64Set(Atomic64 *v, INT64 setVal)
{
UINT32 intSave;
intSave = LOS_IntLock();
*v = setVal;
LOS_IntRestore(intSave);
}
/*ArchAtomic64Add 函数用于原子增加一个 64 位整数变量的值。
它首先保存当前中断状态 intSave然后在关闭中断的情况下
将指针 v 指向的变量增加 addVal然后将增加后的值赋给变量 val
最后恢复之前保存的中断状态,并返回 val。*/
STATIC INLINE INT64 ArchAtomic64Add(Atomic64 *v, INT64 addVal)
{
UINT32 intSave;
INT64 val;
intSave = LOS_IntLock();
*v += addVal;
val = *v;
LOS_IntRestore(intSave);
return val;
}
/*ArchAtomic64Sub 函数用于原子减少一个 64 位整数变量的值。
它的实现类似于 ArchAtomic64Add
只是将指针 v 指向的变量减去 subVal。*/
STATIC INLINE INT64 ArchAtomic64Sub(Atomic64 *v, INT64 subVal)
{
UINT32 intSave;
INT64 val;
intSave = LOS_IntLock();
*v -= subVal;
val = *v;
LOS_IntRestore(intSave);
return val;
}
/*ArchAtomic64Inc 函数用于原子增加一个 64 位整数变量的值。
它的实现类似于 ArchAtomic64Add只是将增加的值固定为 1。*/
STATIC INLINE VOID ArchAtomic64Inc(Atomic64 *v)
{
UINT32 intSave;
intSave = LOS_IntLock();
*v += 1;
LOS_IntRestore(intSave);
}
//ArchAtomic64IncRet 函数与 ArchAtomic64Inc 类似,但它还返回增加后的变量值。
STATIC INLINE INT64 ArchAtomic64IncRet(Atomic64 *v)
{
UINT32 intSave;
INT64 val;
intSave = LOS_IntLock();
*v += 1;
val = *v;
LOS_IntRestore(intSave);
return val;
}
/*ArchAtomic64Dec 函数用于原子减少一个 64 位整数变量的值。
它首先保存当前中断状态 intSave然后在关闭中断的情况下将指针 v 指向的变量减去 1
最后恢复之前保存的中断状态。*/
STATIC INLINE VOID ArchAtomic64Dec(Atomic64 *v)
{
UINT32 intSave;
intSave = LOS_IntLock();
*v -= 1;
LOS_IntRestore(intSave);
}
//ArchAtomic64DecRet 函数与 ArchAtomic64Dec 类似,但它还返回减少后的变量值。
STATIC INLINE INT64 ArchAtomic64DecRet(Atomic64 *v)
{
UINT32 intSave;
INT64 val;
intSave = LOS_IntLock();
*v -= 1;
val = *v;
LOS_IntRestore(intSave);
return val;
}
/*ArchAtomicXchg32bits 函数用于原子交换一个 32 位整数变量的值。
它首先保存当前中断状态 intSave然后在关闭中断的情况下
将指针 v 指向的变量的值赋给 prevVal再将变量 v 的值设置为 val
最后恢复之前保存的中断状态,并返回原先的值 prevVal。*/
STATIC INLINE INT32 ArchAtomicXchg32bits(Atomic *v, INT32 val)
{
UINT32 intSave;
INT32 prevVal;
intSave = LOS_IntLock();
prevVal = *v;
*v = val;
LOS_IntRestore(intSave);
return prevVal;
}
//ArchAtomicXchg64bits 函数类似于 ArchAtomicXchg32bits但它用于原子交换一个 64 位整数变量的值。
STATIC INLINE INT64 ArchAtomicXchg64bits(Atomic64 *v, INT64 val)
{
UINT32 intSave;
INT64 prevVal;
intSave = LOS_IntLock();
prevVal = *v;
*v = val;
LOS_IntRestore(intSave);
return prevVal;
}
/*ArchAtomicCmpXchg32bits 函数用于原子比较和交换一个 32 位整数变量的值。
它首先保存当前中断状态 intSave然后在关闭中断的情况下
将指针 v 指向的变量的值赋给 prevVal接着判断 prevVal 是否等于 oldVal
如果相等,则将变量 v 的值设置为 val最后恢复之前保存的中断状态
并返回是否执行了交换操作的布尔值。*/
STATIC INLINE BOOL ArchAtomicCmpXchg32bits(Atomic *v, INT32 val, INT32 oldVal)
{
UINT32 intSave;
INT32 prevVal;
intSave = LOS_IntLock();
prevVal = *v;
if (prevVal == oldVal) {
*v = val;
}
LOS_IntRestore(intSave);
return (prevVal != oldVal);
}
//ArchAtomicCmpXchg64bits 函数类似于 ArchAtomicCmpXchg32bits但它用于原子比较和交换一个 64 位整数变量的值。
STATIC INLINE BOOL ArchAtomicCmpXchg64bits(Atomic64 *v, INT64 val, INT64 oldVal)
{
UINT32 intSave;
INT64 prevVal;
intSave = LOS_IntLock();
prevVal = *v;
if (prevVal == oldVal) {
*v = val;
}
LOS_IntRestore(intSave);
return (prevVal != oldVal);
}
#else
#error "Generic atomic implementation is not supported on SMP!"
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _ARCH_GENERIC_ATOMIC_H */