经典的读者写者问题

/*
 * read_write_lock.h
 *
 *  Created on: July 29, 2016  09:55:16
 *      Author: [email protected]
 */

#ifndef __READ_WRITE_LOCK_H__
#define __READ_WRITE_LOCK_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include 
#include 
#include 


/******************************************************************************/
enum read_write_priority_mode_e
{
    RD_PRI_MODE = 0,
    WR_PRI_MODE,
};

/******************************************************************************/
struct read_write_lock_s;
typedef void (*read_write_lock_r_lock_func)(struct read_write_lock_s *);
typedef void (*read_write_lock_r_unlock_func)(struct read_write_lock_s *);
typedef void (*read_write_lock_w_lock_func)(struct read_write_lock_s *);
typedef void (*read_write_lock_w_unlock_func)(struct read_write_lock_s *);

/******************************************************************************/
typedef struct read_write_lock_s
{
    uint32_t priority_mode;

    uint32_t reader_cnt;
    pthread_mutex_t reader_cnt_mutex;

    uint32_t writer_cnt;
    pthread_mutex_t writer_cnt_mutex;

    pthread_mutex_t reader_writer_writer_mutex;     /**< 读写互斥, 写写互斥 */

    pthread_mutex_t first_reader_mutex;
    pthread_mutex_t wait_reader_mutex;

    read_write_lock_r_lock_func rwl_read_lock;
    read_write_lock_r_unlock_func rwl_read_unlock;
    read_write_lock_w_lock_func rwl_write_lock;
    read_write_lock_w_unlock_func rwl_write_unlock;
}read_write_lock_t;

/******************************************************************************/
/*
 * 读者优先: 根据读写问题的基本特性: 读读同步, 读写互斥, 写写互斥,
 * 必须待所有读者完成读取后, 写者才可进行写入, 极端情况存在写者饥饿现象
 */
/******************************************************************************/
static inline void
read_write_lock_r_lock_read_first(read_write_lock_t *rwl)
{
    pthread_mutex_lock(&rwl->reader_cnt_mutex);
    if (rwl->reader_cnt++ == 0)
        pthread_mutex_lock(&rwl->reader_writer_writer_mutex);
    pthread_mutex_unlock(&rwl->reader_cnt_mutex);
}

/******************************************************************************/
static inline void
read_write_lock_r_unlock_read_first(read_write_lock_t *rwl)
{
    pthread_mutex_lock(&rwl->reader_cnt_mutex);
    if (--rwl->reader_cnt == 0)
        pthread_mutex_unlock(&rwl->reader_writer_writer_mutex);
    pthread_mutex_unlock(&rwl->reader_cnt_mutex);
}

/******************************************************************************/
static inline void
read_write_lock_w_lock_read_first(read_write_lock_t *rwl)
{
    pthread_mutex_lock(&rwl->reader_writer_writer_mutex);
}

/******************************************************************************/
static inline void
read_write_lock_w_unlock_read_first(read_write_lock_t *rwl)
{
    pthread_mutex_unlock(&rwl->reader_writer_writer_mutex);
}

/*
 * 写者优先: 根据读写问题的基本特性: 读读同步, 读写互斥, 写写互斥,
 * 且避免"读者问题带来可能的饥饿情况, 考虑这样的情况: 存在多个读者工作的同时, 有
 * 新的写者进入等待, 则让当前进行的读者读完后让写者插队进入写操作, 第二个读者暂
 * 时进入等待状态, 待写者完成时方可进行读取;
 */
/******************************************************************************/
static inline void
read_write_lock_r_lock_write_first(read_write_lock_t *rwl)
{
    pthread_mutex_lock(&rwl->wait_reader_mutex);
    pthread_mutex_lock(&rwl->first_reader_mutex);

    pthread_mutex_lock(&rwl->reader_cnt_mutex);
    if (++rwl->reader_cnt == 1)
        pthread_mutex_lock(&rwl->reader_writer_writer_mutex);
    pthread_mutex_unlock(&rwl->reader_cnt_mutex);

    pthread_mutex_unlock(&rwl->first_reader_mutex);
    pthread_mutex_unlock(&rwl->wait_reader_mutex);
}
static inline void
read_write_lock_r_unlock_write_first(read_write_lock_t *rwl)
{
    pthread_mutex_lock(&rwl->reader_cnt_mutex);
    if (--rwl->reader_cnt == 0)
        pthread_mutex_unlock(&rwl->reader_writer_writer_mutex);
    pthread_mutex_unlock(&rwl->reader_cnt_mutex);
}

static inline void
read_write_lock_w_lock_write_first(read_write_lock_t *rwl)
{
    pthread_mutex_lock(&rwl->writer_cnt_mutex);
    if (++rwl->writer_cnt == 1)
        pthread_mutex_lock(&rwl->first_reader_mutex);
    pthread_mutex_unlock(&rwl->writer_cnt_mutex);
    pthread_mutex_lock(&rwl->reader_writer_writer_mutex);
}
static inline void
read_write_lock_w_unlock_write_first(read_write_lock_t *rwl)
{
    pthread_mutex_unlock(&rwl->reader_writer_writer_mutex);
    pthread_mutex_lock(&rwl->writer_cnt_mutex);
    if (--rwl->writer_cnt == 0)
        pthread_mutex_unlock(&rwl->first_reader_mutex);
    pthread_mutex_unlock(&rwl->writer_cnt_mutex);
}

/******************************************************************************/
/******************************************************************************/
static inline void
read_write_lock_init(read_write_lock_t *rwl,
    enum read_write_priority_mode_e mode)
{
    int ret = 0;
    rwl->priority_mode = mode;

    switch (mode)
    {
        case RD_PRI_MODE:
        {
            pthread_mutex_init(&rwl->reader_cnt_mutex, NULL);
            rwl->reader_cnt = 0;
            pthread_mutex_init(&rwl->reader_writer_writer_mutex, NULL);
            rwl->rwl_read_lock = read_write_lock_r_lock_read_first;
            rwl->rwl_read_unlock = read_write_lock_r_unlock_read_first;
            rwl->rwl_write_lock = read_write_lock_w_lock_read_first;
            rwl->rwl_write_unlock = read_write_lock_w_unlock_read_first;
        }
        break;
        case WR_PRI_MODE:
        {
            pthread_mutex_init(&rwl->writer_cnt_mutex, NULL);
            rwl->writer_cnt = 0;
            pthread_mutex_init(&rwl->reader_writer_writer_mutex, NULL);

            pthread_mutex_init(&rwl->reader_cnt_mutex, NULL);
            rwl->reader_cnt = 0;
            pthread_mutex_init(&rwl->first_reader_mutex, NULL);
            pthread_mutex_init(&rwl->wait_reader_mutex, NULL);
            rwl->rwl_read_lock = read_write_lock_r_lock_write_first;
            rwl->rwl_read_unlock = read_write_lock_r_unlock_write_first;
            rwl->rwl_write_lock = read_write_lock_w_lock_write_first;
            rwl->rwl_write_unlock = read_write_lock_w_unlock_write_first;
        }
        break;
        default:
            break;
    }
}

/******************************************************************************/
static inline void
read_lock_r_lock(read_write_lock_t *rwl)
{
    rwl->rwl_read_lock(rwl);
}

/******************************************************************************/
static inline void
read_lock_r_unlock(read_write_lock_t *rwl)
{
    rwl->rwl_read_unlock(rwl);
}

static inline void
read_lock_w_lock(read_write_lock_t *rwl)
{
    rwl->rwl_write_lock(rwl);
}

static inline void
read_lock_w_unlock(read_write_lock_t *rwl)
{
    rwl->rwl_write_unlock(rwl);
}

/******************************************************************************/
/******************************************************************************/
/*
 * dpdk的读写锁实现, 显然采用了读者优先的方法, 但其加锁的粒度已经非常的小了
 */
/******************************************************************************/
/******************************************************************************/
#ifdef __DPDK__
typedef struct
{
    volatile int32_t cnt; /**< -1 when W lock held, > 0 when R locks held. */
} rte_rwlock_t;

/******************************************************************************/
static inline void
rte_rwlock_init(rte_rwlock_t *rwl)
{
    rwl->cnt = 0;
}

/******************************************************************************/
static void inline
rte_rwlock_read_lock(rte_rwlock_t *rwl)
{
    int32_t x;
    int success = 0;

    while (success == 0)
    {
        x = rwl->cnt;
        if (x < 0)
        {
            _mm_pause;//节能减排
            continue;
        }
        success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt, x, x+1);
    }
}

static void inline
rte_rwlock_read_unlock(rte_rwlock_t *rwl)
{
    rte_atomic32_dec((rte_atomic32_t *)&rwl->cnt);
}

/******************************************************************************/
static void inline
rte_rwlock_write_lock(rte_rwlock_t *rwl)
{
    int32_t x;
    int success = 0;

    while (success == 0)
    {
        x = rwl->cnt;
        if (x != 0)
        {
            _mm_pause;
            continue;
        }
        success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt, 0, -1);
    }
}
static void inline
rte_rwlock_write_unlock(rte_rwlock_t *rwl)
{
    rte_atomic32_inc((rte_atomic32_t *)&rwl->cnt);
}
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __READ_WRITE_LOCK_H__ */


你可能感兴趣的:(操纵系统,读写锁,同步与互斥)