博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
菜鸟nginx源代码剖析数据结构篇(十) 自旋锁ngx_spinlock
阅读量:6292 次
发布时间:2019-06-22

本文共 2392 字,大约阅读时间需要 7 分钟。

 

菜鸟nginx源代码剖析数据结构篇(十) 自旋锁ngx_spinlock

 

Author:Echo Chen(陈斌)

Email:chenb19870707@gmail.com

Blog:

Date:Nov 11th, 2014

          自旋锁(Spinlock)是一种 Linux 内核中广泛运用的底层同步机制。

自旋锁是一种工作于多处理器环境的特殊的锁,在单处理环境中自旋锁的操作被替换为空操作。

当某个处理器上的内核运行线程申请自旋锁时,假设锁可用。则获得锁。然后运行临界区操作,最后释放锁。假设锁已被占用。线程并不会转入睡眠状态,而是忙等待该锁,一旦锁被释放。则第一个感知此信息的线程将获得锁。

1.源码位置

 

源文件:

 

2.相关结构定义

原子锁结构 ngx_atomic_t:

1: typedef unsigned long               ngx_atomic_uint_t;
2: typedef volatile ngx_atomic_uint_t  ngx_atomic_t;

原子锁值类型 ngx_atomic_int_t:

1: typedef long                        ngx_atomic_int_t;

原子的比較和交换,假设lock和old相等,则set写入lock

1: #define ngx_atomic_cmp_set(lock, old, set)                                    \
2:     __sync_bool_compare_and_swap(lock, old, set)

说明:

bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)

       type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

这两个函数是GCC提供原子的比較和交换,假设*ptr == oldval,就将newval写入*ptr。

进程主动让出运行权。ngx_sched_yeld

1: #define ngx_sched_yield()  sched_yield()

3.源码剖析

1: void
2: ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin)
3: {
4: 
5: #if (NGX_HAVE_ATOMIC_OPS)
6: 
7:     ngx_uint_t  i, n;
8: 
9: 
10:     for ( ;; ) {
11: 
12:         //*lock == 0,没有上锁则上锁,则调用ngx_atomic_cmp_set上锁,设置*lock=value,然后返回
13:         if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {
14:             return;
15:         }
16:        
17:         // 多核
18:         if (ngx_ncpu > 1) {
19:            
20:             //假设 spin 为 80,则第一次等待 1 个 ngx_cpu_pause() 操作,然后再次查看锁是否可用。

接下来每轮分别等待 2个、4 个、8 个、16 个、32 个、64 个 ngx_cpu_pause() 操作后再试。

21:               //这中间过程中假设出现锁被释放从而能够使用的情况,则循环会被中止,spinlock 函数会返回值。假设重试仍没有成功。则运行 ngx_sched_yield。然后再反复上面的操作。

22:             for (n = 1; n < spin; n <<= 1) {
23: 
24:                 for (i = 0; i < n; i++) {
25:                     ngx_cpu_pause();
26:                 }
27:                
28:                 //检查是否上锁,假设 *lock == 0,则迅速上锁返回
29:                 if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {
30:                     return;
31:                 }
32:             }
33:         }
34:        
35:         //让出CPU运行权
36:         ngx_sched_yield();
37:     }
38: 
39: #else
40: 
41: #if (NGX_THREADS)
42: 
43: #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined !
44: 
45: #endif
46: 
47: #endif
48: 
49: }

 

4.參考资料

 

1.

2.《深入理解Nginx》

 

-Echo Chen

-

转载于:https://www.cnblogs.com/clnchanpin/p/7105299.html

你可能感兴趣的文章
C语言 · 计算时间
查看>>
JavaEE开发之Spring中的依赖注入与AOP编程
查看>>
spi flash偶尔出现写入错误的情况
查看>>
Native SBS for Android
查看>>
vue过渡和animate.css结合使用
查看>>
C#编程(七十四)----------释放非托管资源
查看>>
如何在Java 环境下使用 HTTP 协议收发 MQ 消息
查看>>
java-容器-ArrayList
查看>>
集合体系
查看>>
RocketMQ与Kafka对比(18项差异)
查看>>
Android学习--------实现增删改查数据库操作以及实现相似微信好友对话管理操作...
查看>>
兔子--eclipse设置编码格式
查看>>
[转]程序集之GAC---Global Assembly Cache
查看>>
英语词汇(5)followed by / sung by / written by
查看>>
HDFS Namenode启动过程
查看>>
SQL Server查询某个字段存在哪些表中
查看>>
web实现QQ第三方登录 开放平台-web实现QQ第三方登录
查看>>
【划分树+二分】HDU 4417 Super Mario
查看>>
WPF 基础到企业应用系列1——开篇故意
查看>>
Android - TextureView, SurfaceView和GLSurfaceView 以及 SurfaceTexture
查看>>