LWLock in postgres

一 相关结构体说明

1
2
3
4
5
6
7
8
9
10
typedef struct LWLock
{
uint16 tranche; /* tranche ID */
pg_atomic_uint32 state; /* state of exclusive/nonexclusive lockers */
proclist_head waiters; /* list of waiting PGPROCs */
#ifdef LOCK_DEBUG
pg_atomic_uint32 nwaiters; /* number of waiters */
struct PGPROC *owner; /* last exclusive owner of the lock */
#endif
} LWLock;
  • tranche
    每个 LWLock 都属于某个 tranche,tranche 是一个 int 类型的 ID,代表这把锁的用途

  • state
    bit0~23:共享锁状态,实际最多用bit0~17,因为backend最多18位
    bit24: 排他锁状态
    bit28:用于锁定等待队列:waiters
    bit29: 是否允许唤醒等待队列里面的进程,初始状态:LW_FLAG_RELEASE_OK
    bit30: LW_FLAG_HAS_WAITERS :是否有waiter

  • waiters
    等待队列

二 Interface说明

2.1 LWLockAcquire

加锁,失败进入等待队列,直接加上锁的情况,可能会造成等待队列无效唤醒

acquire a lightweight lock in the specified mode
Side effect: cancel/die interrupts are held off until lock release.

1
2
3
4
5
6
7
8
9
10
11
12
if (mode == LW_EXCLUSIVE)
{
lock_free = (old_state & LW_LOCK_MASK) == 0;
if (lock_free)
desired_state += LW_VAL_EXCLUSIVE;
}
else
{
lock_free = (old_state & LW_VAL_EXCLUSIVE) == 0;
if (lock_free)
desired_state += LW_VAL_SHARED;
}

按位判断前25位即可知道此LWLock是否被进程所占

2.2 LWLockRelease

进行唤醒条件:

  • oldstate & LW_FLAG_HAS_WAITERS:等待队列非空。这个条件确认有进程在等待锁。
  • oldstate & LW_FLAG_RELEASE_OK: 允许唤醒。这个标志表示系统在上次唤醒后,已经将再次唤醒其他等待者的权限交给了被唤醒的进程。
  • (oldstate & LW_LOCK_MASK) == 0:锁已空闲。这个条件确认锁当前没有被任何进程占用(无论是独占模式还是共享模式,计数都为零)