# RwLock Read-Write Lock — DragonOS dev 文档

备注

AI Translation Notice

This document was automatically translated by `Qwen/Qwen3-8B` model, for reference only.

- Source document: kernel/locking/rwlock.md

- Translation time: 2025-05-19 01:41:57

- Translation model: `Qwen/Qwen3-8B`

Please report issues via Community Channel

# RwLock Read-Write Lock

备注

Author: sujintao

Email: sujintao@dragonos.org

## 1. Introduction

A read-write lock is a mechanism used in a concurrent environment to protect shared data among multiple processes. Compared to a regular spinlock, a read-write lock divides access to shared data into two types: read access and write access. Read access to shared data is controlled by a read lock, while write access to shared data is controlled by a write lock. The design of a read-write lock allows for multiple “readers” (read-only access) and a single “writer” (write access) to coexist simultaneously. For shared data that is mostly read-only, using a read-write lock to control access can improve performance to some extent.

## 2. Implementation of Read-Write Lock in DragonOS

### 2.1 Mechanism of Read-Write Lock

The purpose of a read-write lock is to maintain the consistency of shared variables in a multi-threaded system. Data is wrapped in an RwLock data structure, and all access and modification must be done through this structure. Each process that accesses shared data will obtain a guard. A read-only process obtains a READER (reader guard), while a process that needs to modify a shared variable obtains a WRITER (writer guard). As a “shadow” of the RwLock, threads perform access and modification operations based on the guard.

In practice, in addition to READER and WRITER, a read-write lock also introduces an UPGRADER. This is a guard that lies between READER and WRITER. The role of the UPGRADER is to prevent WRITER starvation. When a process obtains an UPGRADER, it treats it as a READER. However, the UPGRADER can be upgraded, and after upgrading, it becomes a WRITER guard, allowing write operations on shared data.

All guards satisfy the RAII mechanism native to Rust. When the scope of a guard ends, the guard will automatically release.

### 2.2 Relationship Between Read-Write Lock Guards

At any given time, multiple READERS can exist, meaning that multiple processes can access shared data simultaneously. However, only one WRITER can exist at a time, and when a process obtains a WRITER, no READERS or UPGRADERS can exist. A process can obtain an UPGRADER only if there are no existing UPGRADERS or WRITERS. However, once a process obtains an UPGRADER, it cannot successfully apply for a READER.

### 2.3 Design Details

#### 2.3.1 RwLock Data Structure

    pub struct RwLock<T> {
        lock: AtomicU32,//原子变量
        data: UnsafeCell<T>,
    }

#### 2.3.2 READER Guard Data Structure

    pub struct RwLockReadGuard<'a, T: 'a> {
        data: *const T,
        lock: &'a AtomicU32,
    }

#### 2.3.3 UPGRADER Guard Data Structure

    pub struct RwLockUpgradableGuard<'a, T: 'a> {
        data: *const T,
        inner: &'a RwLock<T>,
    }

#### 2.3.4 WRITER Guard Data Structure

    pub struct RwLockWriteGuard<'a, T: 'a> {
        data: *mut T,
        inner: &'a RwLock<T>,
    }

#### 2.3.5 Introduction to the lock Structure in RwLock

The lock is a 32-bit atomic variable AtomicU32, and its bit allocation is as follows:

                                                           UPGRADER_BIT     WRITER_BIT
                                                             ^                   ^
    OVERFLOW_BIT                                             +------+    +-------+
      ^                                                             |    |
      |                                                             |    |
    +-+--+--------------------------------------------------------+-+--+-+--+
    |    |                                                        |    |    |
    |    |                                                        |    |    |
    |    |             The number of the readers                  |    |    |
    |    |                                                        |    |    |
    +----+--------------------------------------------------------+----+----+
      31  30                                                    2   1    0

(From right to left) The 0th bit represents whether WRITER is valid. If WRITER_BIT = 1, it indicates that a process has obtained a WRITER guard. If UPGRADER_BIT = 1, it indicates that a process has obtained an UPGRADER guard. Bits 2 to 30 are used to represent the number of processes that have obtained READER guards in binary form. The 31st bit is an overflow detection bit. If OVERFLOW_BIT = 1, new requests for obtaining READER guards will be rejected.

## 3. Main APIs of Read-Write Lock

### 3.1 Main APIs of RwLock

    ///功能:  输入需要保护的数据类型data,返回一个新的RwLock类型.
    pub const fn new(data: T) -> Self

    ///功能: 获得READER守卫
    pub fn read(&self) -> RwLockReadGuard<T>

    ///功能: 尝试获得READER守卫
    pub fn try_read(&self) -> Option<RwLockReadGuard<T>>

    ///功能: 获得WRITER守卫
    pub fn write(&self) -> RwLockWriteGuard<T>

    ///功能: 尝试获得WRITER守卫
    pub fn try_write(&self) -> Option<RwLockWriteGuard<T>>

    ///功能: 获得UPGRADER守卫
    pub fn upgradeable_read(&self) -> RwLockUpgradableGuard<T>

    ///功能: 尝试获得UPGRADER守卫
    pub fn try_upgradeable_read(&self) -> Option<RwLockUpgradableGuard<T>>

### 3.2 Main APIs of the WRITER Guard RwLockWriteGuard

    ///功能: 将WRITER降级为READER
    pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T>

    ///功能: 将WRITER降级为UPGRADER
    pub fn downgrade_to_upgradeable(self) -> RwLockUpgradableGuard<'rwlock, T>

### 3.3 Main APIs of the UPGRADER Guard RwLockUpgradableGuard

    ///功能: 将UPGRADER升级为WRITER
    pub fn upgrade(mut self) -> RwLockWriteGuard<'rwlock, T>

    ///功能: 将UPGRADER降级为READER
    pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T>

## 4. Usage Examples

    static LOCK: RwLock<u32> = RwLock::new(100 as u32);

    fn t_read1() {
        let guard = LOCK.read();
        let value = *guard;
        let readers_current = LOCK.reader_count();
        let writers_current = LOCK.writer_count();
        println!(
            "Reader1: the value is {value}
        There are totally {writers_current} writers, {readers_current} readers"
        );
    }

    fn t_read2() {
        let guard = LOCK.read();
        let value = *guard;
        let readers_current = LOCK.reader_count();
        let writers_current = LOCK.writer_count();
        println!(
            "Reader2: the value is {value}
        There are totally {writers_current} writers, {readers_current} readers"
        );
    }

    fn t_write() {
        let mut guard = LOCK.write();
        *guard += 100;
        let writers_current = LOCK.writer_count();
        let readers_current = LOCK.reader_count();
        println!(
            "Writers: the value is {guard}
        There are totally {writers_current} writers, {readers_current} readers",
            guard = *guard
        );
        let read_guard=guard.downgrade();
        let value=*read_guard;
        println!("After downgraded to read_guard: {value}");
    }

    fn t_upgrade() {
        let guard = LOCK.upgradeable_read();
        let value = *guard;
        let readers_current = LOCK.reader_count();
        let writers_current = LOCK.writer_count();
        println!(
            "Upgrader1 before upgrade: the value is {value}
        There are totally {writers_current} writers, {readers_current} readers"
        );
        let mut upgraded_guard = guard.upgrade();
        *upgraded_guard += 100;
        let writers_current = LOCK.writer_count();
        let readers_current = LOCK.reader_count();
        println!(
            "Upgrader1 after upgrade: the value is {temp}
        There are totally {writers_current} writers, {readers_current} readers",
            temp = *upgraded_guard
        );
        let downgraded_guard=upgraded_guard.downgrade_to_upgradeable();
        let value=*downgraded_guard;
        println!("value after downgraded: {value}");
        let read_guard=downgraded_guard.downgrade();
        let value_=*read_guard;
        println!("value after downgraded to read_guard: {value_}");
    }

    fn main() {
        let r2=thread::spawn(t_read2);
        let r1 = thread::spawn(t_read1);
        let t1 = thread::spawn(t_write);
        let g1 = thread::spawn(t_upgrade);
        r1.join().expect("r1");
        t1.join().expect("t1");
        g1.join().expect("g1");
        r2.join().expect("r2");
    }

Other Versions v: V0.2.0

Tags
  V0.1.0
  V0.1.1
  V0.1.10
  V0.1.2
  V0.1.3
  V0.1.4
  V0.1.5
  V0.1.6
  V0.1.7
  V0.1.8
  V0.1.9
  V0.2.0
  V0.3.0
  V0.4.0

Branches
  master