Day24 read-write lock

前言

昨天讲完了 mutex, semaphore ,今天仍要继续朝着各种不同的 lock前进,昨天讲的semaphore,有个明显的缺点,没办法知道在 C.S里的行程究竟是读还是写。 rwlock 可以有效的提高并行性,rwlock可以允许多个执行绪存取c.s 但是写入就只能有一个行程。

rwlock

rwlock 具有以下的特性

  • 允许多个读取行程,但同时刻不能有写入行程
  • 同一个时刻只能有一个写入行程
  • 写入行程与读取行程不能同时进入C.S

rwlock 有两种,分别是 spinlock型与 semaphore型。

以下是 spinlock型的定义

// <include/linux/rwlock_types.h >
typedef struct{
    arch_rwlock_t raw_lock;
}rwlock_t

// <arch/arm/include/asm/spinlock_types.h>
typedef sturct{
    u32 lock;
}arch_rwlock_t;

以下是常见的函数:

  • rwlock_init() : 初始化rwlock。
  • write_lock() : 申请写入锁。
  • write_unlock() : 释放写入锁。
  • read_lock() : 申请读取锁。
  • read_unlock() :释放读取锁。
  • read_lock_irq() : 关闭中断并且申请读取锁。
  • write_lock_irq() :关闭中断并且申请写入锁。
  • write_unlock_irq() :打开中断并且释放写者锁。

read-write semaphore

//<include/linux/rwsem.h>

struct rw_semaphore {
	atomic_long_t count;
	struct list_head wait_list;
	raw_spinlock_t wait_lock;
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
	struct optimistic_spin_queue osq; /* spinner MCS lock */
	/*
	 * Write owner. Used as a speculative check to see
	 * if the owner is running on the cpu.
	 */
	struct task_struct *owner;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	struct lockdep_map	dep_map;
#endif
};

wait_lock : 是一个 spinlock变量,用以保护 rw_semaphore 资料结构中的 count 成员。
count :用来保护 read-write semaphore 的计数。
wait_list :管理所有在 semaphore上的睡眠行程,没有获取锁的行程会睡眠在这个链表。
osq : 表示MCS锁。
owner : 写者获取锁的时候, owner 指向锁持有者的 task_struct 资料结构。

其中将 count 拿出来看

/*
 * the semaphore definition
 */
#ifdef CONFIG_64BIT
# define RWSEM_ACTIVE_MASK		0xffffffffL
#else
# define RWSEM_ACTIVE_MASK		0x0000ffffL
#endif

#define RWSEM_UNLOCKED_VALUE		0x00000000L
#define RWSEM_ACTIVE_BIAS		0x00000001L
#define RWSEM_WAITING_BIAS		(-RWSEM_ACTIVE_MASK-1)
#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)

count 应该要看成两段,分别为低位的 [15:0]位元,代表了正在持有锁的读取者或是写入者的个数; [31:16]为元,通常是一个负数,代表有一个正在持有锁或是处於等待状态的写入者,以及睡眠等待队列有人在等待。
例子如下

  • RWSEM_ACTIVE_READ_BIAS = 0x00000001 ,即二元[0,1]表示只有一个读取者。
  • RWSEM_ACTIVE_WRITE_BIAS = 0xffff0001, 二元数[-1,1],表示当前只有一个活跃的写入者。
  • RWSEM_WAITING_BIAS = 0xffff0000 即[-1, 0]代表睡眠等待队列中有人在睡眠等待 。

rw-lock 在kernel中应用广泛,特别是在内存管理经常会使用到除了前面的 mm->mmap_sem 的rw semaphore以外, RMAP系统中的 anon_vma->rwsem 、 address space 资料结构中的 i_mmap_rwsem 等。

最後再整理几个rw lock的重要特性:

  • down_read() : 如果行程有了read lock,允许行程继续申请更多的 read lock,但是申请 write lock则需要睡眠等待
  • down_write() :如果一个行程有了 write lock ,另一个行程想申请 write lock 时,需要用 spinlock等待,申请 read lock 则需要睡眠等待。
  • up_write() / up_read() :若等待列上第一个成员是写入者,则只唤醒他; 若为读取行程,则唤醒等待列最前面几个连续的读取者。

<<:  Day 24 快速启动个 JSON Server

>>:  Day 25 : Linux - 如何在windows使用scp去传送档案至Linux上?

Day12 X Writing High Performance CSS

CSS 是前端开发者不可不学的技术之一,没有了它就好像你做出来的网页都没有穿衣服一样,有点羞於见人...

[Tableau Public] day 10:试试长条图&地图,抓不到地图资讯怎麽办?

第10天,打完疫苗已经48小时,目前只有接种处抬手不会酸痛,昨天短暂晕完几分钟,就没感受到其他副作用...

比起懂最新的知识,工程师更应该懂这些.......

有些公司永远在徵人(人员一直在流动),实际去应徵过後,会深刻理解到为什麽。 前几天提到GitHub时...

开源网路钓鱼框架-Gophish(补充)

今天下班後去学校上课 回到家後就11点多了...... 就简单说明关於Gophish操作可能遇到的几...

虎你发财啦!自己的新年图自己做 (React+Fabric.js) -下

前情提要 为了不浪费我白白画的春联,做了一个新年图制造机 还没有新年图的可以到下面玩玩看~(快收假了...