当前位置: 技术问答>linux和unix
linux 关于rw_semaphore 结构体内的count,到底是如何记录信息的?
来源: 互联网 发布时间:2017-05-24
本文导语: linux 3.10 在include/linux/Rwsem.h中有关于rw_semaphore结构体的定义: #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK #include /* use a generic implementation */ #else /* All arch specific implementations share the same struct */ struct rw_semaphore { long coun...
linux 3.10
在include/linux/Rwsem.h中有关于rw_semaphore结构体的定义:
Understanding the Linux Kernel, 3rd Edition 里面对 count 的定义是:
count
Stores two 16-bit counters. The counter in the most significant word encodes in two's complement form the sum of the number of nonwaiting writers (either 0 or 1) and the number of waiting kernel control paths. The counter in the less significant word encodes the total number of nonwaiting readers and writers.
我对应了lib/rwsem.c的实现函数:rwsem_down_read_failed,rwsem_down_write_failed 还是看不懂count的意义。
我的理解是比如有1个read占有信号,而一个write阻塞,这样的话count应该是0xffff 0001 ;而1个write占有信号,1个read被阻塞应该是0x fffe 0001
实际情况不是这样的,有没有谁可以帮忙解释下,谢谢了
另外x86 下,arch/x86/include/asm/Rwsem.h中的几个宏为什么这样定义?
在include/linux/Rwsem.h中有关于rw_semaphore结构体的定义:
#ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
#include /* use a generic implementation */
#else
/* All arch specific implementations share the same struct */
struct rw_semaphore {
long count;
raw_spinlock_t wait_lock;
struct list_head wait_list;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
};
Understanding the Linux Kernel, 3rd Edition 里面对 count 的定义是:
count
Stores two 16-bit counters. The counter in the most significant word encodes in two's complement form the sum of the number of nonwaiting writers (either 0 or 1) and the number of waiting kernel control paths. The counter in the less significant word encodes the total number of nonwaiting readers and writers.
我对应了lib/rwsem.c的实现函数:rwsem_down_read_failed,rwsem_down_write_failed 还是看不懂count的意义。
我的理解是比如有1个read占有信号,而一个write阻塞,这样的话count应该是0xffff 0001 ;而1个write占有信号,1个read被阻塞应该是0x fffe 0001
实际情况不是这样的,有没有谁可以帮忙解释下,谢谢了
另外x86 下,arch/x86/include/asm/Rwsem.h中的几个宏为什么这样定义?
#ifdef CONFIG_X86_64
# define RWSEM_ACTIVE_MASK 0xffffffffL
#else
# define RWSEM_ACTIVE_MASK 0x0000ffffL
#endif
#define RWSEM_UNLOCKED_VALUE 0x00000000L
#define RWSEM_ACTIVE_BIAS 0x00000001L
#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1)
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
|
我用如下的模块试了一下,根据log推断,count的变化应该和之前想的一样。
[ 6312.206759] Hello, world
[ 6312.208982] reader_1 is running
[ 6312.209347] reader_2 is running
[ 6312.209724] writer is running
[ 6312.222916] writer is waiting for write
[ 6312.222924] writer got write lock
[ 6312.222926] sem.count=0xffffffff00000001
[ 6312.222928] writer is sleeping 200
[ 6312.313546] reader_1 is waiting for read
[ 6312.313559] reader_2 is waiting for read
[ 6312.314651] writer_2 is running
[ 6312.327622] writer_2 is waiting for write
[ 6312.424645] sem.count=0xfffffffe00000001
[ 6312.424651] writer releses write lock
[ 6312.424697] reader_1 got read lock
[ 6312.424700] sem.count=0xffffffff00000002
[ 6312.424701] reader_1 is sleeping 200
[ 6312.424705] reader_2 got read lock
[ 6312.424707] sem.count=0xffffffff00000002
[ 6312.424708] reader_2 is sleeping 200
[ 6312.627648] reader_2 releses read lock
[ 6312.627747] reader_1 releses read lock
[ 6312.627867] writer_2 got write lock
[ 6312.627872] sem.count=0xffffffff00000001
[ 6312.627874] writer_2 is sleeping 200
[ 6312.831732] sem.count=0xffffffff00000001
[ 6312.831739] writer_2 releses write lock
[ 6312.206759] Hello, world
[ 6312.208982] reader_1 is running
[ 6312.209347] reader_2 is running
[ 6312.209724] writer is running
[ 6312.222916] writer is waiting for write
[ 6312.222924] writer got write lock
[ 6312.222926] sem.count=0xffffffff00000001
[ 6312.222928] writer is sleeping 200
[ 6312.313546] reader_1 is waiting for read
[ 6312.313559] reader_2 is waiting for read
[ 6312.314651] writer_2 is running
[ 6312.327622] writer_2 is waiting for write
[ 6312.424645] sem.count=0xfffffffe00000001
[ 6312.424651] writer releses write lock
[ 6312.424697] reader_1 got read lock
[ 6312.424700] sem.count=0xffffffff00000002
[ 6312.424701] reader_1 is sleeping 200
[ 6312.424705] reader_2 got read lock
[ 6312.424707] sem.count=0xffffffff00000002
[ 6312.424708] reader_2 is sleeping 200
[ 6312.627648] reader_2 releses read lock
[ 6312.627747] reader_1 releses read lock
[ 6312.627867] writer_2 got write lock
[ 6312.627872] sem.count=0xffffffff00000001
[ 6312.627874] writer_2 is sleeping 200
[ 6312.831732] sem.count=0xffffffff00000001
[ 6312.831739] writer_2 releses write lock
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("Dual BSD/GPL");
static struct rw_semaphore sem;
static void print_sem(struct rw_semaphore *sem)
{
printk(KERN_DEBUG "sem.count=0x%016lxn", sem->count);
}
static void get_read_lock(struct rw_semaphore *sem, char *name)
{
printk(KERN_DEBUG "%s is waiting for readn", name);
down_read(sem);
printk(KERN_DEBUG "%s got read lockn", name);
}
static void release_read_lock(struct rw_semaphore *sem, char *name)
{
printk(KERN_DEBUG "%s releses read lockn", name);
up_read(sem);
}
static void get_write_lock(struct rw_semaphore *sem, char *name)
{
printk(KERN_DEBUG "%s is waiting for writen", name);
down_write(sem);
printk(KERN_DEBUG "%s got write lockn", name);
}
static void release_write_lock(struct rw_semaphore *sem, char *name)
{
printk(KERN_DEBUG "%s releses write lockn", name);
up_write(sem);
}
int reader(void *data)
{
char *name = (char *)data;
printk(KERN_DEBUG "%s is runningn", name);
msleep(100);
get_read_lock(&sem, name);
print_sem(&sem);
printk(KERN_DEBUG "%s is sleeping 200n", name);
msleep(200);
release_read_lock(&sem, name);
do_exit(0);
}
int writer(void *data)
{
char *name = (char *)data;
printk(KERN_DEBUG "%s is runningn", name);
msleep(10);
get_write_lock(&sem, name);
print_sem(&sem);
printk(KERN_DEBUG "%s is sleeping 200n", name);
msleep(200);
print_sem(&sem);
release_write_lock(&sem, name);
do_exit(0);
}
static int hello_init(void)
{
struct task_struct *task = NULL;
printk(KERN_ALERT "Hello, worldn");
init_rwsem(&sem);
task = kthread_create(reader, "reader_1", "reader");
if (IS_ERR(task)) {
printk(KERN_DEBUG "failed to create taskn");
return 1;
}
wake_up_process(task);
task = kthread_create(reader, "reader_2", "reader");
if (IS_ERR(task)) {
printk(KERN_DEBUG "failed to create taskn");
return 1;
}
wake_up_process(task);
task = kthread_create(writer, "writer", "reader");
if (IS_ERR(task)) {
printk(KERN_DEBUG "failed to create taskn");
return 1;
}
wake_up_process(task);
msleep(100);
task = kthread_create(writer, "writer_2", "reader");
if (IS_ERR(task)) {
printk(KERN_DEBUG "failed to create taskn");
return 1;
}
wake_up_process(task);
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT"Goodbye, cruel worldn");
}
module_init(hello_init);
module_exit(hello_exit);
|
我的理解基本和楼主一样。区别就是count的上半部分等于当前获得锁的写者数目(0或1)加上等待列表是否为空(0或1)的补码。
例如:
1. 当前有一个获得锁的写者且等待链表为空,则count=0xffff0001
2. 当前有一个获得锁的写者且等待链表非空,则count=0xfffe0001
3. 当前有多个获得锁的读者且等待链表为空,则count=0x0000000X
4. 当前有多个获得锁的读者且等待链表非空,则count=0xffff000X
楼主实际测试过并且发现不是这样?
例如:
1. 当前有一个获得锁的写者且等待链表为空,则count=0xffff0001
2. 当前有一个获得锁的写者且等待链表非空,则count=0xfffe0001
3. 当前有多个获得锁的读者且等待链表为空,则count=0x0000000X
4. 当前有多个获得锁的读者且等待链表非空,则count=0xffff000X
楼主实际测试过并且发现不是这样?