1 定义ngx_shmtx_wakeup 函数 定义在 ./nginx-1.24.0/src/core/ngx_shmtx.cstaticvoidngx_shmtx_wakeup(ngx_shmtx_t*mtx){#if(NGX_HAVE_POSIX_SEM)ngx_atomic_uint_twait;if(!mtx-semaphore){return;}for(;;){wait*mtx-wait;if((ngx_atomic_int_t)wait0){return;}if(ngx_atomic_cmp_set(mtx-wait,wait,wait-1)){break;}}ngx_log_debug1(NGX_LOG_DEBUG_CORE,ngx_cycle-log,0,shmtx wake %uA,wait);if(sem_post(mtx-sem)-1){ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,ngx_errno,sem_post() failed while wake shmtx);}#endif}ngx_shmtx_wakeup 的核心作用是 在进程释放共享互斥锁后安全地唤醒一个正在等待该锁的阻塞者。2 详解1 函数签名staticvoidngx_shmtx_wakeup(ngx_shmtx_t*mtx)返回值 该函数无返回值 参数 ngx_shmtx_t *mtx 传入一个指向共享内存互斥锁对象 ngx_shmtx_t 的指针2 逻辑流程1 局部变量 2 获取唤醒权利 3 唤醒一个等待进程1 局部变量{#if(NGX_HAVE_POSIX_SEM)ngx_atomic_uint_twait;#1 条件编译预处理指令。 如果系统支持 POSIX 信号量则编译 #if 到 #endif 之间的代码 #2 声明一个局部变量 wait 该变量用于在 CASCompare-And-Swap循环中暂存从共享内存读取到的 *mtx-wait 的当前值2 获取唤醒权利if(!mtx-semaphore){return;}检查锁是否启用信号量机制 读取 ngx_shmtx_t 结构体中的 semaphore 布尔标志位 若为0表示仅靠自旋不使用信号量 提前退出函数for(;;){wait*mtx-wait;if((ngx_atomic_int_t)wait0){return;}if(ngx_atomic_cmp_set(mtx-wait,wait,wait-1)){break;}}#1 开始一个无限循环 进入重试机制直到满足 break 条件才退出 #2 读取共享内存中等待计数的当前值 mtx-wait 是一个指向共享内存地址的指针指向一个 ngx_atomic_t 变量。 *mtx-wait 解引用指针取出当前等待该锁的进程数量。 将值赋给局部变量 wait。 #3 判断是否有进程正在等待 如果 wait 0说明当前没有进程在等待 直接退出函数。 因为没有等待者唤醒操作没有目标函数任务提前结束。 #4 原子操作 尝试将 *mtx-wait 从 wait 更新为 wait - 1 比较 *mtx-wait 是否仍然等于 old即局部变量 wait。 如果相等 说明在此期间没有其他进程修改过计数器。 原子地将 *mtx-wait 设置为 new即 wait - 1并返回 1成功。 如果不相等 说明有其他进程例如另一个刚释放锁的 worker抢先修改了计数器。 原子操作失败内存值不变返回 0。 成功时执行 break退出 for 循环。 跳出 for ( ;; ) 循环。 CAS 操作成功意味着当前进程赢得了唤醒等待者的权利。无需继续循环尝试。3 唤醒一个等待进程ngx_log_debug1(NGX_LOG_DEBUG_CORE,ngx_cycle-log,0,shmtx wake %uA,wait);记录日志if(sem_post(mtx-sem)-1){ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,ngx_errno,sem_post() failed while wake shmtx);}#endif}#1 调用 POSIX 信号量函数 sem_post 来唤醒一个等待进程 sem_post 会将信号量 mtx-sem 的值原子地加 1 如果有进程正阻塞在 sem_wait(mtx-sem) 上系统会唤醒其中一个。 如果函数返回 -1表示系统调用失败。 #2 失败 记录严重错误日志