当前位置: 首页> 文旅> 酒店 > 企业展厅设计公司的资质是什么_东莞网站建设专业品牌_东莞网站建设最牛_搜狗seo快速排名公司

企业展厅设计公司的资质是什么_东莞网站建设专业品牌_东莞网站建设最牛_搜狗seo快速排名公司

时间:2025/7/11 0:17:55来源:https://blog.csdn.net/shaohui973/article/details/146373049 浏览次数:0次
企业展厅设计公司的资质是什么_东莞网站建设专业品牌_东莞网站建设最牛_搜狗seo快速排名公司

本文基于arm linux 5.10来介绍内核中使用的读写信号量rw remphore的实现代码。

内核中信号量结构体struct rw_semaphore的定义在include/linux/rwsem.h

32位architectures下,结构体struct rw_semaphore中的count的使用如下:

先来看信号量的定义和初始化函数和宏:

宏DECLARE_RWSEM()定义了一个读写信号量,并初始化count为0.

如果我们已经定义了信号量变量,要初始化它,可以使用init_rwsem()或直接使用__init_rwsem(), 它们的定义如下:

init_rwsem()和__init_rwsem()他们初始化信号量计数count也是为0.

读写信号量,运行多个读,读与写互斥,写只能有一个。

先看读信号量获取: down_read().

down_read()先调用__down_read_trylock()去上锁, 如果trylock()上锁失败(返回0), 再调用__down_read()去上锁。

先来看__down_read_trylock().

__down_read_trylock() -> atomic_long_try_cmpxchg_acquire() -> atomic_try_cmpxchg_acquire()

这个atomic_try_cmpxchg_acquire()在include/linux/atomic-fallback.h中定义,它有两个定义处,用哪个依赖于对应architecture的atomic.h中定义。

我们来看armv7下的atomic.h中是否定义了atomic_try_cmpxchg_relaxed.

所以,在armv7下,atomic_try_cmpxchg_relaxed没有#define.故,__down_read_trylock() -> atomic_long_try_cmpxchg_acquire() -> atomic_try_cmpxchg_acquire()

这个atomic_try_cmpxchg_acquire()在include/linux/atomic-fallback.h中926行定义,如下:

故,atomic_try_cmpxchg_acquire() -> atomic_cmpxchg_acquire()。

atomic_cmpxchg_acquire() 定义如下:

故, atomic_cmpxchg_acquire() -> atomic_cmpxchg_relaxed().

所以,__down_read_trylock() -> atomic_long_try_cmpxchg_acquire() ->

atomic_try_cmpxchg_acquire() -> atomic_cmpxchg_acquire() -> atomic_cmpxchg_relaxed(),

atomic_cmpxchg_relaxed()定义在arch/arm/include/asm/atomic.h, 如下:

117行:加载信号量计数 sem->count.counter.

118行:清零res.

119行:比较信号量计数值和参数old的大小.

120行:信号量计数值和参数old相等,则将参数new更新到信号量计数。

126行:返回信号量计数更新前的值。

从实现代码看出,__down_read_trylock()是判断信号量计数是否为初值RWSEM_UNLOCKED_VALUE(0), 是的话,则将read计数设置为1(就是1<<8)。

当__down_read_trylock()失败时,则调用__down_read().

__down_read()先调用rwsem_read_trylock().

__down_read() -> rwsem_read_trylock() -> atomic_long_add_return_acquire() ->

atomic_add_return_acquire() -> atomic_add_return_relaxed().

atomic_add_return_relaxed()定义如下:

65行:加载信号量计数sem->count.counter

66行:sem->count.counter + (1 << 8)

67行:新值更新到sem->count.counter

74行:返回sem->count.counter新值。

所以,__down_read()-> rwsem_read_trylock()就是将信号量读计数+1.

rwsem_read_try_lock()拿到更新read计数后的新值时,判断锁是否存在写者或者等待者waiter(279行),存在写者或者等待者waiter时,返回0;否则返回1.

当信号量有写者时,__down_read() –> rwsem_down_read_slowpath().

rwsem_down_read_slowpath()将当前task放入信号量等待队列sem->wait_list中,并设置为TASK_UNINTERRUPTIBLE状态,同时,将信号量计数sem->count减1.

好了,读信号量获取介绍完了,下面介绍读信号量释放: up_read().

up_read() -> __up_read() -> atomic_long_add_return_release() -> atomic_add_return_release() ->

atomic_add_return_relaxed()

atomic_add_return_relaxed() 定义如下:

可见,up_read() -> __up_read()就是将读计数-1。

__up_read()将读计数减1后,判断是等待队列是否有等待者wait_list,有则调用rwsem_wake()将去唤醒。如果等待队列中第一个是写占有请求,则唤醒这个写占有请求者去占有信号量;如果等待队列中第一个不是写等待者,则优先将等待队列中读请求者全部唤醒(最多0x100个)

信号量读操作介绍完了,来看看信号量写。

写信号量获取: down_write().

down_write()先调用__down_write_trylock()获取信号量,如果失败(返回0),则再调用__down_write().

atomic_cmpxchg_acquire() 定义如下:

所以,down_write() -> __down_write_trylock() -> atomic_long_try_cmpxchg_acquire() ->

atomic_try_cmpxchg_acquire() -> atomic_cmpxchg_acquire() -> atomic_cmpxchg_relaxed().

atomic_cmpxchg_relaxed()定义在arch/arm/include/asm/atomic.h,

如下:

117行:加载信号量计数 sem->count.counter.

118行:清零res.

119行:比较信号量计数值和参数old的大小.

120行:信号量计数值和参数old相等,则将参数new更新到信号量计数。

126行:返回信号量计数更新前的值。

down_write() -> __down_write_trylock()就是先判断信号量是否为初值RWSEM_UNLOCKED_VALUE(0)。是的话,则设置信号量count为RWSEM_WRITER_LOCKED (1<<0). 否则__down_write_trylock()就是获取信号量失败,down_write()则调用__down_write()去获取写信号量。

__down_write()先调用atomic_long_try_cmpxchg_acquire(), 这个操作和

__down_write_trylock()一样。

atomic_cmpxchg_acquire() 定义如下:

down_write() -> __down_write() -> atomic_long_try_cmpxchg_acquire() ->

atomic_try_cmpxchg_acquire() -> atomic_cmpxchg_acquire() -> atomic_cmpxchg_relaxed().

atomic_cmpxchg_relaxed()定义在arch/arm/include/asm/atomic.h, 如下:

117行:加载信号量计数 sem->count.counter.

118行:清零res.

119行:比较信号量计数值和参数old的大小.

120行:信号量计数值和参数old相等,则将参数new更新到信号量计数。

126行:返回信号量计数更新前的值。

down_write() -> __down_write()就是判断信号量是否为初值RWSEM_UNLOCKED_VALUE(0)。是的话,则设置信号量count为RWSEM_WRITER_LOCKED (1<<0),否则就是获取信号量失败,则进入rwsem_down_write_slowpath().

1166-1175行:将当前写信号量请求者添加到等待队列sem->wait_list.

1178-1196行:如果当前写信号量请求者不是第一个等待者,则唤醒等待队列前面的task,

读等待者优先。

1207行:设置当前有等待者flag: RWSEM_FLAG_WAITERS

1212行:设置当前进程状态为不可中断休眠状态TASK_UNINTERRUPTILE。

1214行:调用rwsem_try_write_lock(), 尝试去lock信号量。

1238行:重新调度,让出cpu。

好了,写信号量获取down_write()介绍完了,来介绍最后一个写信号量释放: up_write().

up_write() -> __up_write() -> atomic_long_fetch_add_release()

up_write() -> __up_write() -> atomic_long_fetch_add_release() -> atomic_fetch_add_release() ->

atomic_featch_add_relaxed()

atomic_featch_add_relaxed()的定义如下:

86行:加载sem->count.counter

87行:sem->count.counter + i

88行:保存sem->count.counter + i到sem->count.counter。

95行:返回值result为sem->count.counter更新前的值。

故,up_write() -> __up_write()就是删除write_lock, 即写者不再占有信号量。

当写者释放信号量时,如果该信号量有等待者waiters, 则调用rwsem_wake()去唤醒第一个写等待者;如果第一个不是写等待者,则优先唤醒等待队列中所有读等待者(最多0x100个)。

这里的唤醒没有reader优先,和rwsem_down_write_slowpath()不一样。

好了,我们讲解完了读写信号量。现在总结一下:

  1. 当信号量当前被读者占有时,允许其他task读lock, 每lock一次,读计数+1,读lock次数不限制(当然在计数器不溢出范围内),也就是允许多个读存在。此时写占有请求被阻止,写占有请求者task将被放入等待队列sem->wait_list. 这之后来的读请求,都将被放入等待队列(因为被设置了waiters flag)。当信号量所有读占有者释放信号量时,写占有请求者task将被唤醒,去占有信号量。

  1. 当信号量当前被写者占有时,任何其他读请求者或写请求者,都将被组织,请求者被放入等待队列sem->wait_list.当信号量写占有者释放信号量时,如果有信号量占有请求,则去做唤醒动作。如果等待队列第一个是写占有请求,则将其唤醒去占有信号量。如果等待队列第一个不是写占有请求,则优先将所有读占有请求者(最多0x100个)唤醒去占有信号量。

关键字:企业展厅设计公司的资质是什么_东莞网站建设专业品牌_东莞网站建设最牛_搜狗seo快速排名公司

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: