Ubuntu 下 nginx-1.24.0 源码分析 - ngx_atomic_cmp_set 函数

目录

修正 


执行 

./configure

 命令时,输出:

 checking for OS
 + Linux 6.8.0-52-generic x86_64
checking for C compiler ... found
 + using GNU C compiler
 + gcc version: 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) 

 所以当前环境是 x86_64

于是在 src\os\unix\ngx_atomic.h 中

#include "ngx_gcc_atomic_x86.h"

被包含 

src/os/unix/ngx_gcc_atomic_x86.h 中:

static ngx_inline ngx_atomic_uint_t
ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,ngx_atomic_uint_t set)
{u_char  res;__asm__ volatile (NGX_SMP_LOCK"    cmpxchgl  %3, %1;   ""    sete      %0;       ": "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");return res;
}

函数功能:

原子地比较 *lock 的值是否等于 old

若相等:将 *lock 设置为 set,并返回 1(成功)

若不相等:不修改 *lock,返回 0(失败)


内联汇编实现

NGX_SMP_LOCK

宏定义,在多核(SMP)系统中扩展为 lock 前缀,确保指令的原子性;单核系统中可能为空

cmpxchgl %3, %1

x86 的原子比较并交换指令:

  • 比较 %1(即 *lock)与 eax 寄存器(隐含使用,值为 old
  • 若相等,将 %3(即 set)写入 *lock;否则,将 *lock 的值加载到 eax

sete %0

根据 cmpxchgl 结果(ZF 标志位)设置 res 为 0 或 1

输入输出约束

输出 "=a" (res):结果 res 通过 eax 寄存器返回

输入 "m" (*lock), "a" (old), "r" (set)

*lock 作为内存操作数

old 存入 eax(隐含用于 cmpxchgl 的比较)

set 存入通用寄存器

"cc", "memory":告知编译器条件寄存器和内存可能被修改


内联汇编语法

操作数占位符

  • %0, %1, %2, %3:按操作数出现顺序编号:
    • %0 → "=a" (res)(输出)
    • %1 → "m" (*lock)(输入)
    • %2 → "a" (old)(输入)
    • %3 → "r" (set)(输入)

操作数约束(Constraints)

输出操作数 "=a" (res)

  • =:表示只写(输出)。
  • a:使用 eax 寄存器。
  • res:C变量,接收结果(0或1)

"m" (*lock) 

 m:内存操作数,直接操作 *lock 的内存地址

"a" (old)

 a:将 old 的值存入 eax 寄存器(cmpxchgl 隐式使用 eax 进行比较)。

"r" (set)

 r:将 set 的值存入任意通用寄存器(如 ebxecx 等)。

Clobber列表

  • "cc":表示指令修改了标志寄存器(如 ZF、CF)。
  • "memory":表示指令可能修改内存,强制编译器刷新内存缓存。

cmpxchgl 源操作数, 目标操作数

比较 目标操作数(即 *lock)与 eax 的值(old)。

若相等:

将 源操作数(即 set)写入 目标操作数*lock)。

设置 ZF(Zero Flag)为 1。

若不相等:

将 目标操作数*lock)的值加载到 eax

设置 ZF 为 0。

sete %0

  • sete:若 ZF=1(即比较成功),将目标(%0,即 res)设为 1,否则设为 0。
  • 由于 %0 约束为 "=a",结果通过 eax 写入 res

执行流程

将 old 加载到 eax

原子比较 *lock 与 eax

相等 → 将 set 写入 *lock,ZF=1。

不等 → 将 *lock 值加载到 eax,ZF=0。

根据 ZF 设置 res(1 或 0)。

返回 res


意图

  1. 实现原子操作
    通过 cmpxchgl 指令和 lock 前缀,确保在多核环境下的原子性,避免竞态条件。

  2. 跨平台兼容性

        使用 NGX_SMP_LOCK 宏适配不同平台(如单核无需 lock 前缀)

NGX_SMP_LOCK

在 src\os\unix\ngx_gcc_atomic_x86.h

#if (NGX_SMP)
#define NGX_SMP_LOCK  "lock;"
#else
#define NGX_SMP_LOCK
#endif

objs/ngx_auto_config.h 中

#ifndef NGX_SMP
#define NGX_SMP  1
#endif

所以 NGX_SMP_LOCK 是 "lock;"

  • 无 lockcmpxchgl 本身是原子的,但仅限单核环境。
  • 有 lock:确保多核环境下的原子性,完整执行“比较-交换”操作。

修正 

以上部分 可能是错误的

在 src\os\unix\ngx_atomic.h 中:

#define ngx_trylock(lock)  (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1))

这样定义了 ngx_trylock

但对于 ngx_atomic_cmp_set 的定义可能判断错了

在 我的Ubuntu 环境中 

objs/ngx_auto_config.h:9:#define NGX_HAVE_GCC_ATOMIC  1

也就是在 objs/ngx_auto_config.h 中

定义了 

#ifndef NGX_HAVE_GCC_ATOMIC
#define NGX_HAVE_GCC_ATOMIC  1
#endif

在 ngx_atomic.h 中

#if (NGX_HAVE_LIBATOMIC)
省略
#elif (NGX_HAVE_GCC_ATOMIC)
省略
#define ngx_atomic_cmp_set(lock, old, set)                                    \__sync_bool_compare_and_swap(lock, old, set)

#elif (NGX_HAVE_GCC_ATOMIC) 条件成立

所以 ngx_atomic_cmp_set 的定义应该是:

#define ngx_atomic_cmp_set(lock, old, set)                                    \__sync_bool_compare_and_swap(lock, old, set)

在Ubuntu的x86_64架构下,NGX_HAVE_GCC_ATOMIC会被定义

ngx_atomic_cmp_set 在支持GCC原子内置函数的情况下,这个函数应该会被定义为上述情况

__sync_bool_compare_and_swap 

是 GCC 提供的一个内置原子操作函数,用于实现多线程环境下的无锁同步。其作用是在原子操作中比较并交换(Compare-and-Swap, CAS)一个值,常用于实现线程安全的操作。

函数原型

bool __sync_bool_compare_and_swap(type *ptr, type oldval, type newval);
  • 参数
    • ptr:指向需要操作的内存地址的指针。
    • oldval:期望的旧值。
    • newval:要设置的新值。
  • 返回值
    • 如果 *ptr 的当前值等于 oldval,则将 *ptr 设置为 newval,并返回 true
    • 否则不修改内存,返回 false

底层原理

该函数依赖硬件级别的原子指令(如 x86 的 CMPXCHG 指令)实现,确保多线程环境下操作的原子性

函数由 GCC 编译器直接提供,无需像标准库函数(如 printf)那样通过 #include 引入头文件。

直接在代码中调用即可

gcc -E

鉴于有时预编译指令较多且嵌套,难以判断具体使用的哪一个定义

于是改用 gcc -E 的方法

  • 作用:运行 GCC 的 预处理阶段,处理以下内容:
    • 展开 #include 引入的头文件。
    • 替换 #define 定义的宏。
    • 处理 #ifdef/#if 等条件编译指令。
    • 删除注释。
  • 输出:预处理后的纯 C 代码(未编译)。
gcc -E src/core/ngx_times.c \-I src/core \-I src/event \-I src/event/modules \-I src/os/unix \-I objs \> ngx_times_preprocessed.c

-I 添加头文件搜索路径

> ngx_times_preprocessed.c

  • 作用:将预处理结果重定向到文件 ngx_times_preprocessed.c
  • 文件内容:展开后的完整代码

找到原本 ngx_times.c中

void
ngx_time_update(void)
{u_char          *p0, *p1, *p2, *p3, *p4;ngx_tm_t         tm, gmt;time_t           sec;ngx_uint_t       msec;ngx_time_t      *tp;struct timeval   tv;if (!ngx_trylock(&ngx_time_lock)) {return;}

ngx_time_update 函数中,struct timeval   tv; 后,ngx_trylock 调用的地方

在 ngx_times_preprocessed.c 中的位置

 if (!(*(&ngx_time_lock) == 0 && __sync_bool_compare_and_swap(&ngx_time_lock, 0, 1))) {return;}

这里是展开后的样子

所以 确认是 调用了

__sync_bool_compare_and_swap

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/895371.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在 Go 中实现事件溯源:构建高效且可扩展的系统

事件溯源(Event Sourcing)是一种强大的架构模式,它通过记录系统状态的变化(事件)来重建系统的历史状态。这种模式特别适合需要高可扩展性、可追溯性和解耦的系统。在 Go 语言中,事件溯源可以通过一些简单的…

大数据Orc文件生成与读取

ORC(Optimized Row Columnar)是Hadoop生态系统中一种高效的列式存储文件格式,其主要特性包括高效压缩、快速读取、以及能够存储结构化数据。本文将展示如何使用Java编写代码来生成和读取ORC文件。 一、ORC文件介绍 ORC是一种为Hadoop生态系统优化的列式存储格式,具有以下…

解读 Flink Source 接口重构后的 KafkaSource

前言 Apache Kafka 和 Apache Flink 的结合,为构建实时流处理应用提供了一套强大的解决方案[1]。Kafka 作为高吞吐量、低延迟的分布式消息队列,负责数据的采集、缓冲和分发;而 Flink 则是功能强大的流处理引擎,负责对数据进行实时…

【推理llm论文精读】DeepSeek V3技术论文_精工见效果

先附上原始论文和效果对比https://arxiv.org/pdf/2412.19437 摘要 (Abstract) DeepSeek-V3是DeepSeek-AI团队推出的最新力作,一个强大的混合专家(Mixture-of-Experts,MoE)语言模型。它拥有671B的总参数量,但每个tok…

如何使用Java语言在Idea和Android中分别建立服务端和客户端实现局域网聊天

手把手教你用Java语言在Idea和Android中分别建立服务端和客户端实现局域网聊天 目录 文章目录 手把手教你用**Java**语言在**Idea**和**Android**中分别建立**服务端**和**客户端**实现局域网聊天**目录**[toc]**基本实现****问题分析****服务端**Idea:结构预览Server类代码解…

java韩顺平最新教程,Java工程师进阶

简介 HikariCP 是用于创建和管理连接,利用“池”的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制、连接可靠性测试、连接泄露控制、缓存语句等功能,另外,和 druid 一样,HikariCP 也支持监控…

如何在 IDE 里使用 DeepSeek?

近期,阿里云百炼平台重磅推出 DeepSeek-V3、DeepSeek-R1、DeepSeek-R1-Distill-Qwen-32B 等 6 款模型,进一步丰富其 AI 模型矩阵。与此同时,通义灵码也紧跟步伐,全新上线模型选择功能,支持基于百炼的 DeepSeek-V3 和 D…

vue中附件下载及打印功能

1.附件dom 注&#xff1a;fileList是由后台返回的附件数组&#xff0c;数组中包含附件名称fileName,附件地址url&#xff0c;附件id等信息 <el-form-item label"附件" style"width: 100% !important;" v-if"modelTypeborrowDetail"><d…

chromium-mojo

https://chromium.googlesource.com/chromium/src//refs/heads/main/mojo/README.md 相关类&#xff1a;https://zhuanlan.zhihu.com/p/426069459 Core:https://source.chromium.org/chromium/chromium/src//main:mojo/core/README.md;bpv1;bpt0 embedder:https://source.chr…

网络安全技术复习总结

1|0第一章 概论 1.网络安全发展阶段包括四个阶段&#xff1a;通信安全、计算机安全、网络安全、网络空间安全。 2.2017年6月1日&#xff0c;我国第一部全面规范网络空间安全的基础性法律《中华人民共和国网络安全法》正式实施。 3.2021年 6月10日&#xff0c;《中华人民共和…

基于华为云镜像加速器的Docker环境搭建与项目部署指南

基于华为云镜像加速器的Docker环境搭建与项目部署指南 一、安装Docker1.1 更新系统包1.2 安装必要的依赖包1.3 移除原有的Docker仓库配置(如果存在)1.4 添加华为云Docker仓库1.5 安装Docker CE1.6 启动Docker服务1.7 验证Docker是否安装成功1.8 添加华为云镜像加速器地址二、…

在SpringBoot服务器端采购上,如何选择操作系统、Cpu、内存和带宽、流量套餐

在Spring Boot服务器端采购时&#xff0c;选择操作系统、CPU、内存、带宽和流量套餐需根据应用需求、预算和性能要求综合考虑。以下是具体建议&#xff1a; 1. 操作系统 Linux发行版&#xff08;如Ubuntu、CentOS&#xff09;&#xff1a;适合大多数Spring Boot应用&#xff…

DedeBIZ系统审计小结

之前简单审计过DedeBIZ系统&#xff0c;网上还没有对这个系统的漏洞有过详尽的分析&#xff0c;于是重新审计并总结文章&#xff0c;记录下自己审计的过程。 https://github.com/DedeBIZ/DedeV6/archive/refs/tags/6.2.10.zip &#x1f4cc;DedeBIZ 系统并非基于 MVC 框架&…

业务开发 | 基础知识 | Maven 快速入门

Maven 快速入门 1.Maven 全面概述 Apache Maven 是一种软件项目管理和理解工具。基于项目对象模型的概念&#xff08;POM&#xff09;&#xff0c;Maven 可以从中央信息中管理项目的构建&#xff0c;报告和文档。 2.Maven 基本功能 因此实际上 Maven 的基本功能就是作为 Ja…

人工智能之推荐系统实战系列(协同过滤,矩阵分解,FM与DeepFM算法)

一.推荐系统介绍和应用 (1)推荐系统通俗解读 推荐系统就是来了就别想走了。例如在大数据时代中京东越买越想买&#xff0c;抖音越刷越是自己喜欢的东西&#xff0c;微博越刷越过瘾。 (2).推荐系统发展简介 1)推荐系统无处不在&#xff0c;它是根据用户的行为决定推荐的内容…

2.11 sqlite3数据库【数据库的相关操作指令、函数】

练习&#xff1a; 将 epoll 服务器 客户端拿来用 客户端&#xff1a;写一个界面&#xff0c;里面有注册登录 服务器&#xff1a;处理注册和登录逻辑&#xff0c;注册的话将注册的账号密码写入数据库&#xff0c;登录的话查询数据库中是否存在账号&#xff0c;并验证密码是否正确…

Python(十九)实现各大跨境船公司物流查询数据处理优化

一、前言 之前已经实现了常用 跨境物流船司 基础信息查询功能&#xff0c;如下所示 实现各大跨境船公司[COSCO/ZIM/MSK/MSC/ONE/PIL]的物流信息查询&#xff1a;https://blog.csdn.net/Makasa/article/details/145484999?spm1001.2014.3001.5501 然后本章在其基础上做了一些…

CentOS开机自启动服务内容设置

CentOS开机自启动服务内容设置 1. 开机后自动配置时钟同步2. 开机自启动服务脚本3. 配置开机自动添加路由 1. 开机后自动配置时钟同步 # cat /etc/rc.local /usr/sbin/ntpdate pool.ntp.org >> /var/log/ntpdate.log需要设置/etc/rc.local的一个权限&#xff1a; # ll …

基于微信小程序的博物馆预约系统的设计与实现

hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生…

深度学习框架TensorFlow怎么用?

大家好呀&#xff0c;以下是使用 TensorFlow 的详细步骤&#xff0c;从安装到构建和训练模型&#xff1a; 一、安装 TensorFlow 安装 Python&#xff1a;TensorFlow 基于 Python&#xff0c;确保已安装 Python&#xff08;推荐 Python 3.8 及以上版本&#xff09;。可通过 Pyt…