nginx源代码分析 - nginx自旋锁实现

本文介绍AMD64架构下Linux系统的原子操作实现方法,包括ngx_atomic_cmp_set和ngx_atomic_fetch_add函数的具体实现细节,以及如何使用这些原子操作来实现锁机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

架构系统相关的代码(amd64, Linux)
相关定义
typedef int64_t                     ngx_atomic_int_t;
typedef uint64_t                    ngx_atomic_uint_t;
typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
#define NGX_HAVE_ATOMIC_OPS  1

#include "ngx_gcc_atomic_amd64.h"

ngx_gcc_atomic_amd64.h
#define NGX_SMP_LOCK  "lock;"
嵌入式汇编函数
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 lock指令
    "    cmpxchgq  %3, %1;   " cmpxchg的意思是比较ax寄存器的值(old的值)和lock的值,如果相等(0 = 0),set的值(1)覆盖lock,zf置1
                                ax=1,返回1,加锁成功
                                如果不等(ax 1 != 0 lock),old = 1的情况,lock的值(0)覆盖ax寄存器,zf清0,cmpxchgq是64位
                                lock == 0,才会调这个函数,cmpxchgq可理解为相等交换并返回1
    "    sete      %0;       " 设置ax寄存器的值为zf

    : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
    ax寄存器的值赋给res返回,输入内存变量lock,old放入寄存器ax中,set放在任意寄存器
    可能改变的值,cc(CPU标志寄存器 ),memory

    return res;
}

static ngx_inline ngx_atomic_int_t
ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
{
    __asm__ volatile (

         NGX_SMP_LOCK
    "    xaddq  %0, %1;   " add + value的值放到add存放的寄存器中

    : "+r" (add) : "m" (*value) : "cc", "memory");
    add可以放到任意寄存器,输出add,输入内存变量value,

    return add;
}

#define ngx_memory_barrier()    __asm__ volatile ("" ::: "memory")空
#define ngx_cpu_pause()         __asm__ ("pause")

公用的宏
#define ngx_trylock(lock)  (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1)) 只尝试获取一次锁
#define ngx_unlock(lock)    *(lock) = 0

函数void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin);得不到锁就等待
ngx_uint_t  i, n;

for ( ;; ) {
    if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) { ax的值和lock的值相同,都是0,value覆盖lock,并返回1
        return;
    }

    if (ngx_ncpu > 1) {多核
        for (n = 1; n < spin; n <<= 1) {n = 1, 2, 4...

            for (i = 0; i < n; i++) {
                ngx_cpu_pause();
            }

            if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {
                return;
            }
        }
    }
    
    ngx_sched_yield(); //sched_yield()放弃当前的执行机会,等待下次调度
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值