原子量操作

更新时间:
2024-01-10
下载文档

原子量操作

原子量操作 是不可被打断的一个或一系列操作。

当我们的程序存在较多对变量的互斥访问时,我们的程序必然存在较多的锁和锁操作,一方面这使得我们的程序难以编写和维护,另一方面不合理的锁操作可能会发生死锁。

为了避免这些问题,SylixOS 提供了原子量类型 atomic_t 及其 API,原子量类型可储存一个整型 INT 类型的值,同时使用原子量 API 对原子量进行的操作是一个原子操作,因为原子操作不可打断,这样在设备驱动的并发操作中也就不会存在混乱风险。

SylixOS 原子量的类型为 atomic_t。使用时需定义一个 atomic_t 类型的变量,如:

atomic_t    atomic;

原子量

原子量的设置和获取

#include <SylixOS.h> 
VOID  API_AtomicSet (INT  iVal, atomic_t  *patomic);

函数 API_AtomicSet 原型分析:

  • 参数 iVal 是需要设置的值。
  • 参数 patomic 是原子量的指针。
#include <SylixOS.h> 
INT  API_AtomicGet (atomic_t  *patomic);

函数 API_ AtomicGet 原型分析:

  • 此函数成功时返回原子量的值,失败时返回 PX_ERROR 并设置错误号。
  • 参数 patomic 是原子量的指针。

原子量的加和减

#include <SylixOS.h> 
INT  API_AtomicAdd (INT  iVal, atomic_t  *patomic);

函数 API_ AtomicAdd 原型分析:

  • 此函数成功时返回原子量的新值,失败时返回 PX_ERROR 并设置错误号。
  • 参数 iVal 是需要加上的值。
  • 参数 patomic 是原子量的指针。
#include <SylixOS.h> 
INT  API_AtomicSub (INT  iVal, atomic_t  *patomic);

函数 API_ AtomicSub 原型分析:

  • 此函数成功时返回原子量的新值,失败时返回 PX_ERROR 并设置错误号。
  • 参数 iVal 是需要减去的值。
  • 参数 patomic 是原子量的指针。

原子量的自增和自减

#include <SylixOS.h> 
INT  API_AtomicInc (atomic_t  *patomic); 
INT  API_AtomicDec (atomic_t  *patomic);

以上两个函数原型分析:

  • 此函数成功时返回原子量的新值,失败时返回 PX_ERROR 并设置错误号。
  • 参数 patomic 是原子量的指针。

原子量的逻辑位操作

#include <SylixOS.h> 
INT  API_AtomicAnd (INT  iVal, atomic_t  *patomic);

函数 API_ AtomicAnd 原型分析:

  • 此函数成功时返回原子量的新值,失败时返回 PX_ERROR 并设置错误号。
  • 参数 iVal 是需要进行逻辑位与操作的值。
  • 参数 patomic 是原子量的指针。
#include <SylixOS.h> 
INT  API_AtomicNand (INT  iVal, atomic_t  *patomic);

函数 API_ AtomicNand 原型分析:

  • 此函数成功时返回原子量的新值,失败时返回 PX_ERROR 并设置错误号。
  • 参数 iVal 是需要进行逻辑位与非操作的值。
  • 参数 patomic 是原子量的指针。
#include <SylixOS.h> 
INT  API_AtomicOr (INT  iVal, atomic_t  *patomic);

函数 API_ AtomicOr 原型分析:

  • 此函数成功时返回原子量的新值,失败时返回 PX_ERROR 并设置错误号。
  • 参数 iVal 是需要进行逻辑位或操作的值。
  • 参数 patomic 是原子量的指针。
#include <SylixOS.h> 
INT  API_AtomicXor (INT  iVal, atomic_t  *patomic);

函数 API_ AtomicXor 原型分析:

  • 此函数成功时返回原子量的新值,失败时返回 PX_ERROR 并设置错误号。
  • 参数 iVal 是需要进行逻辑位异或操作的值。
  • 参数 patomic 是原子量的指针。

原子量的交换操作

#include <SylixOS.h> 
INT  API_AtomicSwp (INT  iVal, atomic_t  *patomic);

函数 API_ AtomicSwp 原型分析:

  • 此函数成功时返回原子量的旧值(进行操作前的值),失败时返回 PX_ERROR 并设置错误号。
  • 参数 iVal 是需要设置的值。
  • 参数 patomic 是原子量的指针。

以下程序展示了 SylixOS 原子量的使用,内核模块在装载时创建两个线程,两个线程分别对原子量 _G_atomicCount 进行自增操作和打印,内核模块在卸载时删除两个线程。

#define  __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <module.h>
LW_HANDLE         _G_hThreadAId = LW_OBJECT_HANDLE_INVALID;
LW_HANDLE         _G_hThreadBId = LW_OBJECT_HANDLE_INVALID;
static atomic_t   _G_atomicCount;
static PVOID  tTestA (PVOID pvArg)
{
    while (1) {
        printk("tTestA(): count = %d\n", API_AtomicGet(&_G_atomicCount));
        API_TimeSSleep(1);
    }
    return  (LW_NULL);
}
static PVOID  tTestB (PVOID pvArg)
{
    while (1) {
        API_AtomicInc(&_G_atomicCount);
        API_TimeSSleep(1);
    }
    return  (LW_NULL);
}
VOID  module_init (VOID)
{
    printk("atomic_module init!\n");
    _G_hThreadAId = API_ThreadCreate("t_testa", tTestA, LW_NULL, LW_NULL);
    if (_G_hThreadAId == LW_OBJECT_HANDLE_INVALID) {
        printk("t_testa create failed.\n");
        return;
    }
    _G_hThreadBId = API_ThreadCreate("t_testb", tTestB, LW_NULL, LW_NULL);
    if (_G_hThreadBId == LW_OBJECT_HANDLE_INVALID) {
        printk("t_testb create failed.\n");
        return;
    }
}
VOID  module_exit (VOID)
{
    if (_G_hThreadAId != LW_OBJECT_HANDLE_INVALID) {
        API_ThreadDelete(&_G_hThreadAId, LW_NULL);
    }
    if (_G_hThreadBId != LW_OBJECT_HANDLE_INVALID) {
        API_ThreadDelete(&_G_hThreadBId, LW_NULL);
    }
    printk("atomic_module exit!\n");
}

在 SylixOS Shell 下装载模块:

#insmod ./atomic.ko
atomic_module init!
module atomic.ko register ok, handle: 0x13338f0
tTestA(): count = 0
tTestA(): count = 1
tTestA(): count = 2
tTestA(): count = 3
tTestA(): count = 4

在 SylixOS Shell 下卸载模块:

#rmmod atomic.ko
atomic_module exit!
module /lib/modules/atomic.ko unregister ok.
文档内容是否对您有所帮助?
有帮助
没帮助