Today I came across a bug in the kernel cpufreq code where we were missing a bunch of up_write() calls in error paths of a function. I've been trying to get sparse's context checking to pick up on the errors and failing. The kernel patch below is what I have so far, but it seems to report no output whatsoever. What am I missing ? Dave diff --git a/include/asm-x86/rwsem.h b/include/asm-x86/rwsem.h index 041906f..3111853 100644 --- a/include/asm-x86/rwsem.h +++ b/include/asm-x86/rwsem.h @@ -106,6 +106,7 @@ LOCK_PREFIX " incl (%%eax)\n\t" /* adds 0x00000001, returns the old value : "+m" (sem->count) : "a" (sem) : "memory", "cc"); + __acquire(sem); } /* @@ -128,6 +129,7 @@ LOCK_PREFIX " cmpxchgl %2,%0\n\t" : "+m" (sem->count), "=&a" (result), "=&r" (tmp) : "i" (RWSEM_ACTIVE_READ_BIAS) : "memory", "cc"); + __acquire(sem); return result>=0 ? 1 : 0; } @@ -167,6 +169,7 @@ static inline int __down_write_trylock(struct rw_semaphore *sem) RWSEM_ACTIVE_WRITE_BIAS); if (ret == RWSEM_UNLOCKED_VALUE) return 1; + __acquire(sem); return 0; } @@ -186,6 +189,7 @@ LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" /* subtracts 1, returns the old valu : "+m" (sem->count), "=d" (tmp) : "a" (sem), "1" (tmp) : "memory", "cc"); + __release(sem); } /* @@ -204,6 +208,7 @@ LOCK_PREFIX " xaddl %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> : "+m" (sem->count) : "a" (sem), "i" (-RWSEM_ACTIVE_WRITE_BIAS) : "memory", "cc", "edx"); + __release(sem); } /* diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index c4e0016..cf110b0 100644 diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h index 813cee1..90a4b2b 100644 --- a/include/linux/rwsem-spinlock.h +++ b/include/linux/rwsem-spinlock.h @@ -60,13 +60,13 @@ do { \ __init_rwsem((sem), #sem, &__key); \ } while (0) -extern void FASTCALL(__down_read(struct rw_semaphore *sem)); -extern int FASTCALL(__down_read_trylock(struct rw_semaphore *sem)); -extern void FASTCALL(__down_write(struct rw_semaphore *sem)); +extern void FASTCALL(__down_read(struct rw_semaphore *sem)) __acquires(sem); +extern int FASTCALL(__down_read_trylock(struct rw_semaphore *sem)) __acquires(sem); +extern void FASTCALL(__down_write(struct rw_semaphore *sem)) __acquires(sem); extern void FASTCALL(__down_write_nested(struct rw_semaphore *sem, int subclass)); -extern int FASTCALL(__down_write_trylock(struct rw_semaphore *sem)); -extern void FASTCALL(__up_read(struct rw_semaphore *sem)); -extern void FASTCALL(__up_write(struct rw_semaphore *sem)); +extern int FASTCALL(__down_write_trylock(struct rw_semaphore *sem) __acquires(sem)); +extern void FASTCALL(__up_read(struct rw_semaphore *sem)) __releases(sem); +extern void FASTCALL(__up_write(struct rw_semaphore *sem)) __releases(sem); extern void FASTCALL(__downgrade_write(struct rw_semaphore *sem)); static inline int rwsem_is_locked(struct rw_semaphore *sem) diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c index c4cfd6c..c13d112 100644 --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c @@ -162,6 +162,7 @@ void fastcall __sched __down_read(struct rw_semaphore *sem) tsk->state = TASK_RUNNING; out: + __acquire(sem); ; } @@ -184,6 +185,7 @@ int fastcall __down_read_trylock(struct rw_semaphore *sem) spin_unlock_irqrestore(&sem->wait_lock, flags); + __acquire(sem); return ret; } @@ -228,6 +230,7 @@ void fastcall __sched __down_write_nested(struct rw_semaphore *sem, int subclass tsk->state = TASK_RUNNING; out: + __acquire(sem); ; } @@ -253,6 +256,7 @@ int fastcall __down_write_trylock(struct rw_semaphore *sem) } spin_unlock_irqrestore(&sem->wait_lock, flags); + __acquire(sem); return ret; } @@ -270,6 +274,7 @@ void fastcall __up_read(struct rw_semaphore *sem) sem = __rwsem_wake_one_writer(sem); spin_unlock_irqrestore(&sem->wait_lock, flags); + __release(sem); } /* @@ -286,6 +291,7 @@ void fastcall __up_write(struct rw_semaphore *sem) sem = __rwsem_do_wake(sem, 1); spin_unlock_irqrestore(&sem->wait_lock, flags); + __release(sem); } /* -- http://www.codemonkey.org.uk - To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html