diff -Naur rwsem/include/asm-i386/rwsem.h rwsem-test/include/asm-i386/rwsem.h --- rwsem/include/asm-i386/rwsem.h Mon Feb 18 18:46:18 2002 +++ rwsem-test/include/asm-i386/rwsem.h Mon Feb 18 18:18:02 2002 @@ -120,9 +120,30 @@ : "memory", "cc"); } +void rst_debug_print(signed long ctr); + /* * trylock for reading -- returns 1 if successful, 0 if contention */ +#if 0 +static inline int __down_read_trylock(struct rw_semaphore *sem) +{ + signed long old, new, result; + +repeat: + old = (volatile signed long)sem->count; + if (old < RWSEM_UNLOCKED_VALUE) + return 0; + new = old + RWSEM_ACTIVE_READ_BIAS; + result = cmpxchg(&sem->count, old, new); + rst_debug_print(result); + if (result == old) + return 1; + else + goto repeat; +} +#endif + static inline int __down_read_trylock(struct rw_semaphore *sem) { __s32 result, tmp; @@ -140,6 +161,7 @@ : "+m"(sem->count), "=&a"(result), "+&r"(tmp) : "i"(RWSEM_ACTIVE_READ_BIAS) : "memory", "cc"); + rst_debug_print(result); return result>=0 ? 1 : 0; } @@ -181,6 +203,7 @@ signed long ret = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS); + rst_debug_print(ret); if (ret == RWSEM_UNLOCKED_VALUE) return 1; return 0; diff -Naur rwsem/include/linux/rwsem.h rwsem-test/include/linux/rwsem.h --- rwsem/include/linux/rwsem.h Mon Feb 18 18:44:36 2002 +++ rwsem-test/include/linux/rwsem.h Mon Feb 18 18:18:07 2002 @@ -9,7 +9,7 @@ #include -#define RWSEM_DEBUG 0 +#define RWSEM_DEBUG 1 #ifdef __KERNEL__ diff -Naur rwsem/include/rwsem_test.h rwsem-test/include/rwsem_test.h --- rwsem/include/rwsem_test.h Wed Dec 31 16:00:00 1969 +++ rwsem-test/include/rwsem_test.h Mon Feb 18 15:36:44 2002 @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include + +DECLARE_RWSEM(rst_lock); + +spinlock_t rst_ctrlock = SPIN_LOCK_UNLOCKED; +unsigned int rst_ctr = 1000; +unsigned int getctr(void) +{ + unsigned long ret; + spin_lock(&rst_ctrlock); + ret = ++rst_ctr; + spin_unlock(&rst_ctrlock); + return ret; +} + +void rst_debug_print(signed long ctr) +{ + printk("[rst %d:%d] rwsem counter: %x\n", current->pid, getctr(), (unsigned int)ctr); +} + +int +rst_daemon(void *ignore) +{ + while (1) { + unsigned char sleep, style, ctr = 0; + + get_random_bytes(&sleep, 1); + __set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((signed long)sleep); + + for (; ctr < 20; ++ctr) { + get_random_bytes(&style, 1); + + if (style > 191) { + down_write(&rst_lock); + printk("[rst %d:%d] down_write\n", current->pid, getctr()); + } else if (style > 127) { + if (!down_write_trylock(&rst_lock)) { + printk("[rst %d:%d] down_write_trylock " + "failed\n", + current->pid, getctr()); + break; + } + printk("[rst %d:%d] down_write_trylock " + "succeeded\n", current->pid, getctr()); + } else if (style > 63) { + down_read(&rst_lock); + printk("[rst %d:%d] down_read\n", current->pid, getctr()); + } else { + if (!down_read_trylock(&rst_lock)) { + printk("[rst %d:%d] down_read_trylock " + "failed\n", + current->pid, getctr()); + break; + } + printk("[rst %d:%d] down_read_trylock " + "succeeded\n", current->pid, getctr()); + } + + if (style > 127) + printk("[rst %d:%d] writing... [1]\n", + current->pid, getctr()); + else + printk("[rst %d:%d] reading... [1]\n", + current->pid, getctr()); + + __set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(5); + + if (style > 127) + printk("[rst %d:%d] writing... [2]\n", + current->pid, getctr()); + else + printk("[rst %d:%d] reading... [2]\n", + current->pid, getctr()); + + if (style > 127) { + printk("[rst %d:%d] up_write\n", current->pid, getctr()); + up_write(&rst_lock); + } else { + printk("[rst %d:%d] up_read\n", current->pid, getctr()); + up_read(&rst_lock); + } + } + } + return 0; +} + +void +rst_init(void) +{ + int ctr = 0; + rst_lock.debug = 1; + for (; ctr < 10; ++ctr) + kernel_thread(rst_daemon, NULL, 0); +} diff -Naur rwsem/init/main.c rwsem-test/init/main.c --- rwsem/init/main.c Mon Feb 18 18:45:30 2002 +++ rwsem-test/init/main.c Mon Feb 18 14:11:23 2002 @@ -31,6 +31,8 @@ #include #include +#include + #if defined(CONFIG_ARCH_S390) #include #include @@ -829,6 +831,8 @@ * The Bourne shell can be used instead of init if we are * trying to recover a really broken machine. */ + + rst_init(); if (execute_command) execve(execute_command,argv_init,envp_init);