diff -urN rwsem/include/linux/rwsem.h rwsem-rec/include/linux/rwsem.h --- rwsem/include/linux/rwsem.h Wed Mar 6 05:03:56 2002 +++ rwsem-rec/include/linux/rwsem.h Wed Mar 6 05:05:36 2002 @@ -18,6 +18,11 @@ #endif }; +struct rw_sem_recursor +{ + int counter; +}; + #if RWSEM_DEBUG #define __SEM_DEBUG_INIT(name) \ , (long)&(name).__magic @@ -42,6 +47,7 @@ __SEM_DEBUG_INIT(name) \ } #define RWSEM_INITIALIZER(name) __RWSEM_INITIALIZER(name, 0) +#define RWSEM_RECURSOR_INITIALIZER ((struct rw_sem_recursor) { 0, }) #define __DECLARE_RWSEM(name, count) \ struct rw_semaphore name = __RWSEM_INITIALIZER(name, count) @@ -112,6 +118,35 @@ spin_lock(&sem->lock); sem->count -= RWSEM_WRITE_BIAS; if (unlikely(sem->count)) + rwsem_wake(sem); + spin_unlock(&sem->lock); +} + +static inline void down_read_recursive(struct rw_semaphore *sem, + struct rw_sem_recursor * recursor) +{ + long count; + int counter; + CHECK_MAGIC(sem->__magic); + + spin_lock(&sem->lock); + count = sem->count; + sem->count += RWSEM_READ_BIAS; + counter = recursor->counter++; + if (unlikely(count < 0 && !counter && !(count & RWSEM_READ_MASK))) + rwsem_down_failed(sem, RWSEM_READ_BLOCKING_BIAS); + spin_unlock(&sem->lock); +} + +static inline void up_read_recursive(struct rw_semaphore *sem, + struct rw_sem_recursor * recursor) +{ + CHECK_MAGIC(sem->__magic); + + spin_lock(&sem->lock); + sem->count -= RWSEM_READ_BIAS; + recursor->counter--; + if (unlikely(sem->count < 0 && !(sem->count & RWSEM_READ_MASK))) rwsem_wake(sem); spin_unlock(&sem->lock); }