news 2026/6/13 15:09:20

[Linux]学习笔记系列 -- 底层CPU与体系结构宏

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[Linux]学习笔记系列 -- 底层CPU与体系结构宏

title: 底层CPU与体系结构宏
categories:

  • linux
  • include
    tags:
  • linux
  • include
    abbrlink: febaf417
    date: 2025-10-03 09:01:49

https://github.com/wdfk-prog/linux-study

文章目录

  • include/asm-generic/rwonce.h: 提供 READ_ONCE() 和 WRITE_ONCE() 宏,防止编译器优化,保证单次读写的原子性
    • compiletime_assert_rwonce_type
    • READ_ONCE 保证原子性读取
  • include/asm-generic/irqflags.h 提供中断标志位的通用操作函数
    • arch_irqs_disabled_flags 判断中断是否被禁用
    • arch_irqs_disabled
  • include/linux/irqflags.h 包含特定于体系结构的 irqflags.h,提供中断开关等操作
    • kernel/locking/irqflag-debug.c
    • raw_check_bogus_irq_restore 检查中断恢复
    • local_irq_save 返回当前中断状态并禁用中断
    • local_irq_restore 恢复中断状态
  • include/linux/instruction_pointer.h: 提供获取当前指令指针(IP)的宏
    • _RET_IP_ 返回地址
    • _THIS_IP_ 当前指令地址
  • include/asm-generic/topology.h 提供描述CPU拓扑结构(如节点、核心)的通用定义
    • cpu_to_node
  • include/linux/topology.h 包含特定于体系结构的CPU拓扑信息
    • numa_node_id
  • arch/arm/include/asm/word-at-a-time.h: ARM架构下用于一次性处理一个字(word)数据的优化函数
    • WORD_AT_A_TIME_CONSTANTS 一次单词常量
    • has_zero 检查一个无符号长整数 a 是否包含零字节,并返回一个掩码表示零字节的位置
    • prep_zero_mask zero_bytemask
    • create_zero_mask

include/asm-generic/rwonce.h: 提供 READ_ONCE() 和 WRITE_ONCE() 宏,防止编译器优化,保证单次读写的原子性

/* * 阻止编译器合并或重新获取读取或写入。还禁止编译器对 READ_ONCE 和 WRITE_ONCE 的连续实例重新排序,但前提是编译器知道某些特定排序。使编译器了解 Sequences 的一种方法是将 READ_ONCE 或 WRITE_ONCE 的两次调用放在不同的 C 语句中。 * * 这两个宏也适用于聚合数据类型,如结构体或联合体。 * * 它们的两个主要用例是:(1) 调解进程级代码和 irq/NMI 处理程序之间的通信,所有处理程序都运行在同一个 CPU 上,以及 (2) 确保编译器不会折叠、纺锤或以其他方式破坏不需要排序或与提供所需排序的显式内存屏障或原子指令交互的访问。 */

compiletime_assert_rwonce_type

  • __native_word是一个宏,用于检查给定类型是否是本机字长(通常是 32 位或 64 位)。如果类型不是本机字长,则检查它的大小是否为sizeof(long long),即 64 位。这个宏通常用于确保在进行原子操作时,数据类型的大小与系统架构相匹配。
/* 是的,这允许在 32 位架构上进行 64 位访问。在某些情况下,这些实际上是原子的(即 Armv7 + LPAE),但对于其他情况,我们依赖于将访问分成 2x32 位访问,以获得 32 位数量(例如虚拟地址)和强大的盛行风。 */#definecompiletime_assert_rwonce_type(t)\compiletime_assert(__native_word(t)||sizeof(t)==sizeof(longlong),\"Unsupported access size for {READ,WRITE}_ONCE().")

READ_ONCE 保证原子性读取

  • READ_ONCE是一个宏,用于在多线程环境中安全地读取变量的值。它确保读取操作是原子的,即不会被其他线程的写入操作打断。这对于避免数据竞争和确保数据一致性非常重要。
  • compiletime_assert_rwonce_type是一个编译时断言,用于检查传入的变量类型是否符合要求。它确保变量是原子类型或具有与长整型相同的大小。这有助于在编译时捕获潜在的错误,确保代码的正确性和安全性。
  • __READ_ONCE是一个底层实现,用于执行实际的读取操作。它使用了__unqual_scalar_typeof来获取变量的类型,并将其转换为const volatile指针,以确保读取操作是原子的。
/* * 如果不需要任何原子性,请使用 __READ_ONCE() 而不是 READ_ONCE()。请注意,这可能会导致编译错误! */#ifndef__READ_ONCE#define__READ_ONCE(x)(*(constvolatile__unqual_scalar_typeof(x)*)&(x))#endif#defineREAD_ONCE(x)\({\compiletime_assert_rwonce_type(x);\__READ_ONCE(x);\})

include/asm-generic/irqflags.h 提供中断标志位的通用操作函数

arch_irqs_disabled_flags 判断中断是否被禁用

/* test flags */#ifndefarch_irqs_disabled_flagsstaticinlineintarch_irqs_disabled_flags(unsignedlongflags){returnflags==ARCH_IRQ_DISABLED;}#endif

arch_irqs_disabled

/* test hardware interrupt enable bit */#ifndefarch_irqs_disabledstaticinlineintarch_irqs_disabled(void){//arch_local_save_flags 返回当前的中断状态returnarch_irqs_disabled_flags(arch_local_save_flags());}#endif

include/linux/irqflags.h 包含特定于体系结构的 irqflags.h,提供中断开关等操作

kernel/locking/irqflag-debug.c

noinstr//禁止内联插桩的段voidwarn_bogus_irq_restore(void){instrumentation_begin();WARN_ONCE(1,"raw_local_irq_restore() called with IRQs enabled\n");instrumentation_end();}EXPORT_SYMBOL(warn_bogus_irq_restore);

raw_check_bogus_irq_restore 检查中断恢复

#ifdefCONFIG_DEBUG_IRQFLAGSexternvoidwarn_bogus_irq_restore(void);#defineraw_check_bogus_irq_restore()\do{\if(unlikely(!arch_irqs_disabled()))\warn_bogus_irq_restore();\}while(0)#else#defineraw_check_bogus_irq_restore()do{}while(0)#endif

local_irq_save 返回当前中断状态并禁用中断

  1. 返回当前的中断状态,并将其保存到 flags 变量中。
  2. 执行中断禁止操作

local_irq_restore 恢复中断状态

  • 恢复之前保存的中断状态,允许中断再次发生。

include/linux/instruction_pointer.h: 提供获取当前指令指针(IP)的宏

RET_IP返回地址

/* * _RET_IP_ 是一个宏,用于获取当前函数的返回地址。 * 它通常用于调试和错误处理,以便在发生异常或错误时 * 记录函数的返回地址。 */#define_RET_IP_(unsignedlong)__builtin_return_address(0)

THIS_IP当前指令地址

  • _THIS_IP_是一个宏,用于获取当前指令的地址。它通常用于调试和错误处理,以便在发生异常或错误时记录当前指令的地址。
  • 具体来说,THIS_IP被定义为一个复合语句表达式({ __label__ __here; __here: (unsigned long)&&__here; })。复合语句表达式是 GCC 的一种扩展语法,允许在表达式中包含多个语句。
  • 在这个复合语句表达式中,首先定义了一个局部标签__here,这是通过__label__关键字实现的。局部标签是一种特殊的标签,只在当前复合语句表达式的作用域内有效。
  • 接下来,表达式使用了标签__here,并通过&&__here获取该标签的地址。标签地址运算符&&GCC的一个扩展,用于获取标签的地址。然后,将这个地址强制转换为unsigned long类型。
  • 最终,这个宏_THIS_IP_提供了一种方法来获取当前代码位置的地址,并将其转换为unsigned long类型。这在调试和分析代码执行路径时可能非常有用,因为它允许程序员获取当前执行点的地址。
#ifndef_THIS_IP_#define_THIS_IP_({__label__ __here;__here:(unsignedlong)&&__here;})#endif

include/asm-generic/topology.h 提供描述CPU拓扑结构(如节点、核心)的通用定义

cpu_to_node

#ifndefcpu_to_node// 逗号运算符的作用 在 C 语言中,逗号运算符(,)会依次计算其左侧和右侧的表达式,并返回右侧表达式的值。#definecpu_to_node(cpu)((void)(cpu),0)#endif

include/linux/topology.h 包含特定于体系结构的CPU拓扑信息

numa_node_id

staticinlineintnuma_node_id(void){returncpu_to_node(raw_smp_processor_id());}

arch/arm/include/asm/word-at-a-time.h: ARM架构下用于一次性处理一个字(word)数据的优化函数

WORD_AT_A_TIME_CONSTANTS 一次单词常量

#defineWORD_AT_A_TIME_CONSTANTS{REPEAT_BYTE(0x01),REPEAT_BYTE(0x80)}

has_zero 检查一个无符号长整数 a 是否包含零字节,并返回一个掩码表示零字节的位置

staticinlineunsignedlonghas_zero(unsignedlonga,unsignedlong*bits,conststructword_at_a_time*c){/* one_bits表示每个字节的最低位为 1 high_bits表示每个字节的最高位为 1*//* 如果某个字节为零,则 (a - c->one_bits) 的该字节会产生一个进位 *//* ~a 的该字节会为全 1 *//* 结合 c->high_bits,最终生成一个掩码,标记零字节的位置 */unsignedlongmask=((a-c->one_bits)&~a)&c->high_bits;*bits=mask;returnmask;}

prep_zero_mask zero_bytemask

#defineprep_zero_mask(a,bits,c)(bits)#definezero_bytemask(mask)(mask)

create_zero_mask

staticinlineunsignedlongcreate_zero_mask(unsignedlongbits){bits=(bits-1)&~bits;returnbits>>7;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 22:34:39

Switch终极音乐播放方案:TriPlayer完整使用教程与技巧

Switch终极音乐播放方案:TriPlayer完整使用教程与技巧 【免费下载链接】TriPlayer A feature-rich background audio player for Nintendo Switch (requires Atmosphere) 项目地址: https://gitcode.com/gh_mirrors/tr/TriPlayer 还在为Switch无法后台播放音…

作者头像 李华
网站建设 2026/6/10 9:17:50

如何快速掌握Anki记忆工具:从零开始的完整学习指南

如何快速掌握Anki记忆工具:从零开始的完整学习指南 【免费下载链接】anki Ankis shared backend and web components, and the Qt frontend 项目地址: https://gitcode.com/GitHub_Trending/an/anki 在信息爆炸的数字化时代,高效记忆成为现代人必…

作者头像 李华
网站建设 2026/6/11 23:38:40

基于Python的动漫数据可视化分析系统(源码+数据库+文档)

动漫数据可视化分析系统 目录 基于PythonFlask动漫数据可视化分析系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取: 基于PythonFlask动漫数据可视化分析系统 一、前言…

作者头像 李华
网站建设 2026/6/5 21:50:30

SDXL VAE FP16精度修复:释放显卡性能的智能优化方案

SDXL VAE FP16精度修复:释放显卡性能的智能优化方案 【免费下载链接】sdxl-vae-fp16-fix 项目地址: https://ai.gitcode.com/hf_mirrors/madebyollin/sdxl-vae-fp16-fix 在人工智能图像生成领域,SDXL模型以其卓越的生成质量赢得了广泛赞誉&#…

作者头像 李华
网站建设 2026/6/1 19:23:18

CSANMT模型性能优化:让CPU推理速度提升3倍

CSANMT模型性能优化:让CPU推理速度提升3倍 🌐 AI 智能中英翻译服务 (WebUI API) 项目背景与业务需求 随着全球化进程加速,高质量的中英翻译需求持续增长。尤其在中小企业、开发者工具链和轻量级应用中,对低延迟、高精度、低成本的…

作者头像 李华
网站建设 2026/6/13 2:12:41

基于Python 招聘大数据可视化分析系统(源码+数据库+文档)

招聘大数据可视化分析系统 目录 基于PythonFlask招聘大数据可视化分析系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取: 基于PythonFlask招聘大数据可视化分析系统 一…

作者头像 李华