测试pthread_rwlock_rdlock_2-1.c用例失败。log如下:
[83#yuchen@ubuntu ltp]# gcc 2-1.c -o 21 -pthread [84#yuchen@ubuntu ltp]# ./21 main: has priority: 3 main: attempt read lock main: acquired read lock main: create wr_thread, with priority: 2 wr_thread: attempt write lock main: create rd_thread, with priority: 1 rd_thread: attempt read lock rd_thread: acquired read lock rd_thread: unlock read lock Test FAILED: rd_thread did not block on read lock, when a reader owns the lock, and a higher priority writer is waiting for the lock [85#yuchen@ubuntu ltp]# |
这个测试用例的流程:
Steps:
* We have three threads, main(also a reader), writer, reader
*
* 1. Main thread set its shcedule policy as "SCHED_FIFO", with highest priority
* the three: sched_get_priority_min()+2.
* 2. Main thread read lock 'rwlock'
* 3. Create a writer thread, with schedule policy as "SCHED_FIFO", and priority
* using sched_get_priority_min()+1.
* 4. The thread write lock 'rwlock', should block.
* 5. Main thread create a reader thread, with schedule policy as "SCHED_FIFO", and
* priority sched_get_priority_min()
* 6. Reader thread read lock 'rwlock', should block, since there is a higher priority
* writer blocked on 'rwlock'
* 7. Main thread release the 'rwlock', the writer should get the lock first
*/
用例失败的原因:
rwlock是读写锁,读者是可以递归调用的,因为多个读者不存在竞争问题,如果写者先拿到了锁,则后面来的读者必须阻塞。读和写之间必然会造成竞争,但是读和读之间没有竞争。读写锁的实现比较复杂,基于futex实现(用户态和内核态混合同步机制)。在glibc库有很多分支判断,如果对futex机制不了解的话,是比较难理解的。针对这个用例,简单说下流程:
默认情况下,如果没有写者持有锁,并且锁的属性设置了读优先(默认情况下rwlock就是读优先的),那么读者可以重复占用锁(读和读没有竞争)。代码见nptl/pthread_rwlock_rdlock.c,注意140行。那么在该测试用例中有2个读者,读者1先拿到了锁,读者2在去拿锁,是不会被阻塞的,因为写者并没有持有锁。持有锁的是一个读者(main主程序)。
但是测试用例期望,在有高优先级写者竞争锁的时候,读者要阻塞。从c库代码上看,要想让读者阻塞,必须设置rwlock写者优先属性,也就是让pthread_rwlock_rdlock.c的140行的条件判断为假。从而让代码走到slowfast,在pthread_rwlock_rdlock_slow函数中会挂起当前线程,等待其他任务unlock时才有可能被唤醒。
119 __pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
120 {
121 int result = 0;
122 bool wake = false;
123 int futex_shared =
124 rwlock->__data.__shared == LLL_PRI