linux 内核接口atomic_long_try_cmpxchg_acquire/release详解

这篇具有很好参考价值的文章主要介绍了linux 内核接口atomic_long_try_cmpxchg_acquire/release详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 atomic_long_try_cmpxchg_acquire/release

1.1 atomic_long_try_cmpxchg_acquire

static __always_inline bool
atomic_long_try_cmpxchg_acquire(atomic_long_t *v, long *old, long new)
{
        return atomic64_try_cmpxchg_acquire(v, (s64 *)old, new);
}

1.2 atomic_long_try_cmpxchg_release

static __always_inline bool
atomic_long_try_cmpxchg_release(atomic_long_t *v, long *old, long new)
{
        return atomic64_try_cmpxchg_release(v, (s64 *)old, new);
}

2 arch_atomic64_cmpxchg_acquire/release

2.1 arch_atomic64_cmpxchg_acquire/release定义

#define arch_atomic64_cmpxchg_acquire atomic64_cmpxchg_acquire
#define arch_atomic64_cmpxchg_release atomic64_cmpxchg_release

2.2 atomic64_cmpxchg_acquire/release

#if defined(arch_atomic64_cmpxchg_acquire)
static __always_inline s64
atomic64_cmpxchg_acquire(atomic64_t *v, s64 old, s64 new)
{
        instrument_atomic_read_write(v, sizeof(*v));
        return arch_atomic64_cmpxchg_acquire(v, old, new);
}
#define atomic64_cmpxchg_acquire atomic64_cmpxchg_acquire
#endif

#if defined(arch_atomic64_cmpxchg_release)
static __always_inline s64
atomic64_cmpxchg_release(atomic64_t *v, s64 old, s64 new)
{
        instrument_atomic_read_write(v, sizeof(*v));
        return arch_atomic64_cmpxchg_release(v, old, new);
}
#define atomic64_cmpxchg_release atomic64_cmpxchg_release
#endif

2.3 instrument_atomic_read_write

原子读写访问

/**
 * instrument_atomic_read_write - instrument atomic read-write access
 *
 * Instrument an atomic read-write access. The instrumentation should be
 * inserted before the actual write happens.
 *
 * @ptr address of access
 * @size size of access
 */
static __always_inline void instrument_atomic_read_write(const volatile void *v, size_t size)
{
        kasan_check_write(v, size);
        kcsan_check_atomic_read_write(v, size);
}

2.4 arch_atomic64_cmpxchg_acquire/release

#define arch_atomic64_cmpxchg_acquire           arch_atomic_cmpxchg_acquire
#define arch_atomic64_cmpxchg_release           arch_atomic_cmpxchg_release

2.5 arch_atomic_cmpxchg_acquire/release

#define arch_atomic_cmpxchg_acquire(v, old, new) \
        arch_cmpxchg_acquire(&((v)->counter), (old), (new))
#define arch_atomic_cmpxchg_release(v, old, new) \
        arch_cmpxchg_release(&((v)->counter), (old), (new))

2.6 arch_cmpxchg_acquire/release

#define arch_cmpxchg_acquire(...)       __cmpxchg_wrapper(_acq, __VA_ARGS__)
#define arch_cmpxchg_release(...)       __cmpxchg_wrapper(_rel, __VA_ARGS__)

2.7 __cmpxchg_wrapper

  • 对于arch_cmpxchg_acquire来说,sfx指代的是_acq
  • 对于arch_cmpxchg_release来说,sfx指代的是_rel
  • sizeof(*(ptr))表示要访问地址对应的数据宽度
#define __cmpxchg_wrapper(sfx, ptr, o, n)                               \
({                                                                      \
        __typeof__(*(ptr)) __ret;                                       \
        __ret = (__typeof__(*(ptr)))                                    \
                __cmpxchg##sfx((ptr), (unsigned long)(o),               \
                                (unsigned long)(n), sizeof(*(ptr)));    \
        __ret;                                                          \
})

2.8 __cmpxchg##sfx

  • __CMPXCHG_GEN()表示为__cmpxchg
  • __CMPXCHG_GEN(_acq)表示为__cmpxchg_acq
  • __CMPXCHG_GEN(_rel)表示为__cmpxchg_rel
  • __CMPXCHG_GEN(_mb)表示为__cmpxchg_mb
#define __CMPXCHG_GEN(sfx)                                              \
static __always_inline unsigned long __cmpxchg##sfx(volatile void *ptr, \
                                           unsigned long old,           \
                                           unsigned long new,           \
                                           int size)                    \
{                                                                       \
        switch (size) {                                                 \
        case 1:                                                         \
                return __cmpxchg_case##sfx##_8(ptr, old, new);          \
        case 2:                                                         \
                return __cmpxchg_case##sfx##_16(ptr, old, new);         \
        case 4:                                                         \
                return __cmpxchg_case##sfx##_32(ptr, old, new);         \
        case 8:                                                         \
                return __cmpxchg_case##sfx##_64(ptr, old, new);         \
        default:                                                        \
                BUILD_BUG();                                            \
        }                                                               \
                                                                        \
        unreachable();                                                  \
}

__CMPXCHG_GEN()
__CMPXCHG_GEN(_acq)
__CMPXCHG_GEN(_rel)
__CMPXCHG_GEN(_mb)

2.9 _xchg_case##name##sz

  • __XCHG_CASE(w, b, , 8, , , , , , )对应着__xchg_case_8,其所对应的ld" #acq "xr" #sfx "\t%" #w "0, %2ldxrb "\t%" #w "0, %2;所对应的st" #rel "xr" #sfx "\t%w1, %" #w "3, %2stxrb "\t%w1, %" #w "3, %2;相对应的arm64汇编指令为ldxrbstxrb
  • __XCHG_CASE(w, b, acq_, 8, , , a, a, , "memory")对应着__xchg_case_acq_8,其所对应的ld" #acq "xr" #sfx "\t%" #w "0, %2ldaxrb "\t%" #w "0, %2;所对应的st" #rel "xr" #sfx "\t%w1, %" #w "3, %2stxrb "\t%w1, %" #w "3, %2;相对应的arm64汇编指令为ldaxrbstxrb
/*
 * We need separate acquire parameters for ll/sc and lse, since the full
 * barrier case is generated as release+dmb for the former and
 * acquire+release for the latter.
 */
#define __XCHG_CASE(w, sfx, name, sz, mb, nop_lse, acq, acq_lse, rel, cl)       \
static inline u##sz __xchg_case_##name##sz(u##sz x, volatile void *ptr)         \
{                                                                               \
        u##sz ret;                                                              \
        unsigned long tmp;                                                      \
                                                                                \
        asm volatile(ARM64_LSE_ATOMIC_INSN(                                     \
        /* LL/SC */                                                             \
        "       prfm    pstl1strm, %2\n"                                        \
        "1:     ld" #acq "xr" #sfx "\t%" #w "0, %2\n"                           \
        "       st" #rel "xr" #sfx "\t%w1, %" #w "3, %2\n"                      \
        "       cbnz    %w1, 1b\n"                                              \
        "       " #mb,                                                          \
        /* LSE atomics */                                                       \
        "       swp" #acq_lse #rel #sfx "\t%" #w "3, %" #w "0, %2\n"            \
                __nops(3)                                                       \
        "       " #nop_lse)                                                     \
        : "=&r" (ret), "=&r" (tmp), "+Q" (*(u##sz *)ptr)                        \
        : "r" (x)                                                               \
        : cl);                                                                  \
                                                                                \
        return ret;                                                             \
}

__XCHG_CASE(w, b,     ,  8,        ,    ,  ,  ,  ,         )
__XCHG_CASE(w, h,     , 16,        ,    ,  ,  ,  ,         )
__XCHG_CASE(w,  ,     , 32,        ,    ,  ,  ,  ,         )
__XCHG_CASE( ,  ,     , 64,        ,    ,  ,  ,  ,         )
__XCHG_CASE(w, b, acq_,  8,        ,    , a, a,  , "memory")
__XCHG_CASE(w, h, acq_, 16,        ,    , a, a,  , "memory")
__XCHG_CASE(w,  , acq_, 32,        ,    , a, a,  , "memory")
__XCHG_CASE( ,  , acq_, 64,        ,    , a, a,  , "memory")
__XCHG_CASE(w, b, rel_,  8,        ,    ,  ,  , l, "memory")
__XCHG_CASE(w, h, rel_, 16,        ,    ,  ,  , l, "memory")
__XCHG_CASE(w,  , rel_, 32,        ,    ,  ,  , l, "memory")
__XCHG_CASE( ,  , rel_, 64,        ,    ,  ,  , l, "memory")
__XCHG_CASE(w, b,  mb_,  8, dmb ish, nop,  , a, l, "memory")
__XCHG_CASE(w, h,  mb_, 16, dmb ish, nop,  , a, l, "memory")
__XCHG_CASE(w,  ,  mb_, 32, dmb ish, nop,  , a, l, "memory")
__XCHG_CASE( ,  ,  mb_, 64, dmb ish, nop,  , a, l, "memory")

2.10 ldxr

2.10.1 ldxr

加载排他寄存器从基本寄存器值获取地址,从内存中加载32位字或64位双字,并将其写入寄存器。内存访问是原子式的。PE将被访问的物理地址标记为独家访问。此独家访问标记是由独占存储指令检查的。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release

2.10.2 ldxrb

加载排他寄存器字节从一个基本寄存器值派生一个地址,从内存加载一个字节,零扩展它,并将其写入一个寄存器。内存访问是原子式的。PE将被访问的物理地址标记为独家访问。此独家访问标记是由独占存储指令检查的。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release

2.10.3 LDXRH

加载排他寄存器半字从基本寄存器值获得地址,从内存加载半字,零扩展它并将其写入寄存器。内存访问是原子式的。PE将被访问的物理地址标记为独家访问。此独家访问标记是由独占存储指令检查的。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release

2.11 ldaxr

2.11.1 ldaxr

加载-获取独占寄存器从基本寄存器值获取地址,从内存中加载32位字或64位双字,并将其写入寄存器。内存访问是原子式的。PE将被访问的物理地址标记为独家访问。此独家访问标记是由独占存储指令检查的。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release

2.11.2 ldaxb

加载-获取独占寄存器字节从一个基本寄存器值派生一个地址,从内存加载一个字节,零扩展它,并将其写入一个寄存器。内存访问是原子式的。PE将被访问的物理地址标记为独家访问。此独家访问标记是由存储独占指令检查的。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release

2.11.3 LDAXRH

加载获取独占寄存器半字从基本寄存器值获得地址,从内存加载半字,零扩展它并将其写入寄存器。内存访问是原子式的。PE将被访问的物理地址标记为独家访问。此独家访问标记是由存储独占指令检查的。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release

2.12 stxr

2.12.1 STXR

如果PE对内存地址具有独占访问权限,则独家存储器从寄存器存储32位字或64位双字,如果存储成功,返回状态值为0,如果没有执行存储,则返回状态值为1。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release

2.12.2 STXRB

存储独占寄存器字节如果PE只访问内存地址,则存储从寄存器到内存的字节,如果存储成功,则返回状态值为0,如果没有执行存储,则返回状态值为1。内存访问是原子式的。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release

2.12.3 stxrh

如果PE对内存地址有独占访问,则存储寄存器存储到内存,如果存储成功,返回状态值为0,如果没有执行存储,返回状态值为1。内存访问是原子式的。
linux 内核接口atomic_long_try_cmpxchg_acquire/release详解,锁相关专题,atomic_acquire,atomic_release,cmpxchg_acquire,cmpxchg_release文章来源地址https://www.toymoban.com/news/detail-569332.html

到了这里,关于linux 内核接口atomic_long_try_cmpxchg_acquire/release详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第七天-内核函数接口(物联技术666)

    链接:https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd=1688 提取码:1688 //************************************************** #include linux/module.h    /*module_init()*/ #include linux/kernel.h        /* printk() */ #include linux/init.h            /* __init __exit */ #include linux/fs.h              /* file_opera

    2024年02月22日
    浏览(69)
  • 【Linux】Argument list too long参数列表过长的办法-四种

    Linux下使用cp,mv,rm,chmod等命令时经常会碰到“Argument list too long”错误,这主要是因为这些命令的参数太长,即文件个数过多。 方案一:将文件群手动划分为比较小的组合 [user@localhost ubuntu]$ mv [a-l]* ../foo2 [user@localhost ubuntu]$ mv [m-z]* ../foo2 注:应用范围有限,只适用于文件列

    2024年02月10日
    浏览(39)
  • postgresql15 内核源码分析-buffer查找接口

        专栏内容:postgresql内核源码分析 个人主页:我的主页 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 目录 前言 概述 接口介绍 调用场景分析 详细分解 结尾 本文是基于postgresql 15的代码进行分析解读,演示是在centos8系统上进行。   在postgresql中,SQL引擎

    2023年04月09日
    浏览(57)
  • linux C函数之strdup函数分析和getopt_long()的使用

    函数介绍:        strdup()函数主要是拷贝字符串s的一个副本,有函数返回值返回,这个副本有自己的内存空间,和s没有关联。strdup函数复制一个字符串,使用完后,要使用free函数删除在函数中动态申请的内存,strdup函数的参数不能为NULL,一旦为NULL就会段错误,因为该函数

    2024年01月23日
    浏览(36)
  • FPGA纯verilog实现UDP协议栈 AXIS用户接口,可替代Tri Mode Ethernet MAC,提供三套工程源码和技术支持

    FPGA高端项目:纯verilog的 UDP 协议栈,提供11套工程源码和技术支持 目前网上的fpga实现udp基本生态如下: 1:verilog编写的udp收发器,但中间的FIFO或者RAM等调用了IP,或者不带ping功能,这样的代码功能正常也能用,但不带ping功能基本就是废物,在实际项目中不会用这样的代码,

    2024年02月13日
    浏览(50)
  • FPGA平台以太网学习:涉及1G/2.5G Ethernet 和Tri Mode Ethernet MAC两个IP核的学习记录(三)——接口与框架

    学习不能稀里糊涂,要学会多思考,发散式学习以及总结:   FPGA作为一种器件,只是实现目的的一种方法,过度追求实现的技术细节(用hdl还是hls,用啥芯片,用啥接口)容易只见树木不见森林。工具软件的用法也好,器件的架构也好,语言孰优孰劣的争论也罢。工程应用里

    2024年02月09日
    浏览(76)
  • Linux下通过 rm -f 删除大量文件时报错:Argument list too long

    Linux下通过 rm -f 删除大量的小文件时出现类似如下错误信息:   -bash: /bin/rm: Argument list too long 如下图所示: 如果待删除文件中包含的小文件数量过多,通常是由于受到 shell 参数个数限制所致。 这个是Linux系统存在的限制,可以通过如下指令查看该参数值的配置: 注: 删除

    2024年02月13日
    浏览(47)
  • /bin/rm Argument list too long – Linux 删除海量文件报错的解决方法

    这种情况主要在大批量删除居多文件的情况下发生,也是因为删除的命令参数超过了shell参数的个数导致的,可以通过 getconf ARG_MAX 来确认,解决方法好几种 配合find与xargs完成删除海量文件 可以通过find和xargs命令配合的方式,比如删除当前目录所有的png文件, 上面的这个命令

    2024年01月21日
    浏览(49)
  • Windows内核和Linux内核比较(附Linux内核各版本历史纪年表)

    我是荔园微风,作为一名在IT界整整25年的老兵,最近受邀给年轻人讲了一场Windows内核和Linux内核相关的讲座。大家听得非常认真。 计算机操作系统的功能角色:作为用户和计算机硬件资源之间的交互,管理调度硬件资源,为应用软件提供运行环境。操作系统属于基础软件,

    2024年02月10日
    浏览(57)
  • Linux内核8. Linux内核的经典调试方式

    内核总是那么捉摸不透, 内核也会犯错, 但是调试却不能像用户空间程序那样, 为此内核开发者为我们提供了一系列的工具和系统来支持内核的调试. 内核的调试, 其本质是内核空间与用户空间的数据交换, 内核开发者们提供了多样的形式来完成这一功能. 内核中有三个常用的伪

    2024年02月07日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包