<span style="font-size:14px;">/*
* read_write_lock.h
*
* Created on: July 29, 2016 09:55:16
* Author: xtank.nie@gmail.com
*/
#ifndef __READ_WRITE_LOCK_H__
#define __READ_WRITE_LOCK_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stdint.h>
#include <pthread.h>
#include <emmintrin.h>
/******************************************************************************/
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__ */
</span>
经典的读者写者问题
最新推荐文章于 2022-01-15 15:56:55 发布