linux 内核同步,Linux内核同步机制【rwlock】

读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑CPU数。写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。

数据结构

rwlock_t1

2

3

4

5

6

7

8

9

10

11

12

13typedef struct {

arch_rwlock_t raw_lock;

#ifdef CONFIG_GENERIC_LOCKBREAK

unsigned int break_lock;

#endif

#ifdef CONFIG_DEBUG_SPINLOCK

unsigned int magic, owner_cpu;

void *owner;

#endif

#ifdef CONFIG_DEBUG_LOCK_ALLOC

struct lockdep_map dep_map;

#endif

} rwlock_t;file: include/linux/rwlock_types.h

arch_rwlock_t

MIPS1

2

3typedef struct {

volatile unsigned int lock;

} arch_rwlock_t;file: arch/mips/include/asm/spinlock_types.h

通用接口APIrwlock_init1

2

3

4

5

6

7

8

9#define __ARCH_RW_LOCK_UNLOCKED { 0 }

#define __RW_LOCK_UNLOCKED(lockname) \

(rwlock_t) { .raw_lock = __ARCH_RW_LOCK_UNLOCKED, \

RW_DEP_MAP_INIT(lockname) }

# define rwlock_init(lock) \

do { *(lock) = __RW_LOCK_UNLOCKED(lock); } while (0)

初始化rwlock_t->raw_lock->lock=0R/W lock1

2#define write_lock(lock) _raw_write_lock(lock)

#define read_lock(lock) _raw_read_lock(lock)file: include/linux/rwlock.h

实现

读写锁包括读取锁和写入锁,多个读线程可以同时访问共享数据;写线程必须等待所有读线程都释放锁以后,才能取得锁;同样的,读线程必须等待写线程释放锁后,才能取得锁;

也就是说读写锁要确保的是如下互斥关系:可以同时读,但是读-写,写-写都是互斥的;读锁1

2

3

4

5

6read_lock

|->_raw_read_lock

|->__raw_read_lock

|->preempt_disable();

|->rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);

|->LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);

在读锁上锁时与spinlock的流程基本相同,都会关闭内核抢占,因此读写锁中也不能睡眠1

2# define do_raw_read_trylock(rwlock) arch_read_trylock(&(rwlock)->raw_lock)

# define do_raw_read_lock(rwlock) do {__acquire(lock); arch_read_lock(&(rwlock)->raw_lock); } while (0)file: include/linux/rwlock.h

MIPS

不同架构的实现:

arch_read_lock1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17static inline void arch_read_lock(arch_rwlock_t *rw)

{

unsigned int tmp;

do {

__asm__ __volatile__(

"1: ll %1, %2 # arch_read_lock \n"

" bltz %1, 1b \n"

" addu %1, 1 \n"

"2: sc %1, %0 \n"

: "=m" (rw->lock), "=&r" (tmp)

: "m" (rw->lock)

: "memory");

} while (unlikely(!tmp));

smp_llsc_mb();

}bltz $s,offset <==> if($s< 0) jump(offset « 2); 小于0,跳转

内嵌汇编源码:1

2

3

4

5

6c2020000 ll v0,0(s0)

0440fffe bltz v0,8021c8f8

00000000 nop

24420001 addiu v0,v0,1

e2020000 sc v0,0(s0)

1040fffa beqz v0,8021c8f8

上读锁是通过原子操作对rwlock_t->raw_lock->lock += 1

arch_read_unlock1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16static inline void arch_read_unlock(arch_rwlock_t *rw)

{

unsigned int tmp;

smp_mb__before_llsc();

do {

__asm__ __volatile__(

"1: ll %1, %2 # arch_read_unlock \n"

" sub %1, 1 \n"

" sc %1, %0 \n"

: "=m" (rw->lock), "=&r" (tmp)

: "m" (rw->lock)

: "memory");

} while (unlikely(!tmp));

}

解读锁是通过原子操作对rwlock_t->raw_lock->lock -= 1

arch_write_lock1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17static inline void arch_write_lock(arch_rwlock_t *rw)

{

unsigned int tmp;

do {

__asm__ __volatile__(

"1: ll %1, %2 # arch_write_lock \n"

" bnez %1, 1b \n"

" lui %1, 0x8000 \n"

"2: sc %1, %0 \n"

: "=m" (rw->lock), "=&r" (tmp)

: "m" (rw->lock)

: "memory");

} while (unlikely(!tmp));

smp_llsc_mb();

}lui $t,imm <==> $t=(imm « 16)

将立即数左移16位,低16位补零

内嵌汇编反汇编源码:1

2

3

4

5

6c2020000 ll v0,0(s0)

1440fffe bnez v0,8021ca08

00000000 nop

3c028000 lui v0,0x8000

e2020000 sc v0,0(s0)

1040fffa beqz v0,8021ca08

arch_write_unlock1

2

3

4

5

6

7

8

9

10

11static inline void arch_write_unlock(arch_rwlock_t *rw)

{

smp_mb();

__asm__ __volatile__(

" # arch_write_unlock \n"

" sw $0, %0 \n"

: "=m" (rw->lock)

: "m" (rw->lock)

: "memory");

}

Q&A读锁怎么实现可以存在多个读者进行处理??读写锁与SMP多核之间的线程处理关系??

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值