PostgreSQL V9.6 LWLock实现分析(五)

时间:2020-12-02 05:56:09

LWLock实现的技术

    上一节,我们介绍了LWLock的数据结构,其中LWLock锁的“state”上的锁标志可以有两种模式,如下:

typedef enum LWLockMode

{

    LW_EXCLUSIVE,  //排他模式

    LW_SHARED,     //共享模式

    LW_WAIT_UNTIL_FREE    /* A special mode used inPGPROC->lwlockMode,

                           * when waiting forlock to become free. Not

                           * to be used asLWLockAcquire argument */

} LWLockMode;

    LWLock结构体定义了state标志位(LWLock的数据结构参见上一节),此标志位是通过LWLockAcquire ()LWLockAttemptLock()函数调用完成标志位设置的。

LWLockAttemptLock(LWLock *lock, LWLockMode mode)

{...

   old_state = pg_atomic_read_u32(&lock->state);  //读出锁的原始值

    while(true)

    {...

       desired_state = old_state; //desired_state上先保持旧值

        if(mode == LW_EXCLUSIVE)

        {

           lock_free = (old_state & LW_LOCK_MASK) == 0;

           if (lock_free)

               desired_state += LW_VAL_EXCLUSIVE;  //desired_state上先保持旧值后,根据锁的模式加排它锁的标识

        }

       else

        {

           lock_free = (old_state & LW_VAL_EXCLUSIVE) == 0;

           if (lock_free)

               desired_state += LW_VAL_SHARED; //desired_state上先保持旧值后,根据锁的模式加共享锁的标识

        }

        //desired_state成为在锁标志位上将被设置的值。pg_atomic_compare_exchange_u32()完成设置标志位(不同硬件平台,设置方式不同)

        if(pg_atomic_compare_exchange_u32(&lock->state,&old_state, desired_state))   

        {

...

        }

    }

...

}

    pg_atomic_compare_exchange_u32()函数调用的其它函数,因硬件平台而异,如Windows下,调用栈如下,最终使用了InterlockedCompareExchange()函数完成锁标志位的置位工作,state标志位被设置为“LW_VAL_SHARED”或“LW_VAL_EXCLUSIVE”。

LWLockAcquire()

 LWLockAttemptLock()

   pg_atomic_compare_exchange_u32()

     pg_atomic_compare_exchange_u32_impl()   

       InterlockedCompareExchange() //把目标操作数(第1参数所指向的内存中的数)与一个值(第3参数)比较,如果相等,则用另一个值(第2参数)与目标操作数(第1参数所指向的内存中的数)交换

    另外,释放锁时也需要对锁标志位置位为“LW_FLAG_RELEASE_OK”,且无“LW_VAL_SHARED”也无“LW_VAL_EXCLUSIVE”,置位操作通过pg_atomic_sub_fetch_u32()函数完成,如下是在Windows下的调用栈示例。

LWLockRelease()

 pg_atomic_sub_fetch_u32()

   pg_atomic_sub_fetch_u32_impl()

     pg_atomic_fetch_sub_u32_impl()

       pg_atomic_fetch_add_u32_impl()

          InterlockedExchangeAdd() //用于对一个32位数值执行加法的原子操作