Re: 64-bit ppc rwsem
On Tuesday 24 August 2010, Benjamin Herrenschmidt wrote: > On Mon, 2010-08-23 at 15:18 -0700, David Miller wrote: > > > I've seen drivers in the past do trylocks at interrupt time ... tho > > I > > > agree it sucks. > > > > Recently there was a thread where this was declared absolutely > > illegal. > > > > Maybe it was allowed, or sort-of worked before, and that's why it's > > accounted for with IRQ disables in some implementations. I don't > > know. > > Ok, I'm happy to say it's a big no-no then. > > Arnd, do you want to take over the moving to asm-generic and take care > of the spinlock case as well ? I can send Linus the first patch that > changes powerpc to use atomic_long now along with a few other things I > have pending, then you can pickup from there. Or do you want me to > continue pushing my patch as-is and we can look at cleaning up the > spinlock case separately ? I'm currently doing too many things at once, please push in your existing patch for now, we can continue from there. For the asm-generic patch: Acked-by: Arnd Bergmann ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
On Mon, 2010-08-23 at 15:18 -0700, David Miller wrote: > > I've seen drivers in the past do trylocks at interrupt time ... tho > I > > agree it sucks. > > Recently there was a thread where this was declared absolutely > illegal. > > Maybe it was allowed, or sort-of worked before, and that's why it's > accounted for with IRQ disables in some implementations. I don't > know. Ok, I'm happy to say it's a big no-no then. Arnd, do you want to take over the moving to asm-generic and take care of the spinlock case as well ? I can send Linus the first patch that changes powerpc to use atomic_long now along with a few other things I have pending, then you can pickup from there. Or do you want me to continue pushing my patch as-is and we can look at cleaning up the spinlock case separately ? Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
From: Benjamin Herrenschmidt Date: Tue, 24 Aug 2010 08:01:25 +1000 > On Mon, 2010-08-23 at 15:44 +0200, Arnd Bergmann wrote: >> >> * Alpha has an optimization for the uniprocessor case, where the atomic >> instructions get turned into nonatomic additions. The spinlock based >> version uses no locks on UP but disables interrupts for reasons I don't >> understand (nothing running at interrupt time should try to access an rwsem). >> Should the generic version do the same as Alpha? > > I've seen drivers in the past do trylocks at interrupt time ... tho I > agree it sucks. Recently there was a thread where this was declared absolutely illegal. Maybe it was allowed, or sort-of worked before, and that's why it's accounted for with IRQ disables in some implementations. I don't know. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
On Mon, 2010-08-23 at 15:44 +0200, Arnd Bergmann wrote: > > * Alpha has an optimization for the uniprocessor case, where the atomic > instructions get turned into nonatomic additions. The spinlock based > version uses no locks on UP but disables interrupts for reasons I don't > understand (nothing running at interrupt time should try to access an rwsem). > Should the generic version do the same as Alpha? I've seen drivers in the past do trylocks at interrupt time ... tho I agree it sucks. > * Is there any architecture that would still benefit from having a separate > rwsem implementation? AFAICT all the remaining ones are just variations of > the same concept of using cmpxchg (or xadd in case of x86), which is what > atomics typically end up doing anyway. It depends how sensitive rwsems are. The "generic" variant based on atomic's and cmpxchg on powerpc is sub-optimal in the sense that it has stronger memory barriers that would be necessary (atomic_inc_return for example has both acquire and release). But that vs. one more pile of inline asm, we decided it wasn't hot enough a spot for us to care back then. Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
On Thursday 19 August 2010, David Miller wrote: > From: Benjamin Herrenschmidt > Date: Thu, 19 Aug 2010 15:23:23 +1000 > > > Similar here, but using atomic_long_t instead so it works for 32-bit too > > for me. I suppose we could make that part common indeed. > > > > What about asm-generic/rwsem-atomic.h or rwsem-cmpxchg.h ? > > Using rwsem-cmpxchg.h sounds best I guess. The implementation looks good for asm-generic, but there is now an asymmetry between the spinlock and the atomic_long_t based version. Maybe we can make them both do the same thing, either of 1. create include/linux/rwsem-cmpxchg.h and add an #elif defined(CONFIG_RWSEM_GENERIC_ATOMIC) to include/linux/rwsem.h 2. move include/linux/rwsem-spinlock.h to include/asm-generic/ and include that from all architectures that want the spinlock based version. Further comments: * Alpha has an optimization for the uniprocessor case, where the atomic instructions get turned into nonatomic additions. The spinlock based version uses no locks on UP but disables interrupts for reasons I don't understand (nothing running at interrupt time should try to access an rwsem). Should the generic version do the same as Alpha? * Is there any architecture that would still benefit from having a separate rwsem implementation? AFAICT all the remaining ones are just variations of the same concept of using cmpxchg (or xadd in case of x86), which is what atomics typically end up doing anyway. Arnd ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
On Wed, 2010-08-18 at 22:29 -0700, David Miller wrote: > From: Benjamin Herrenschmidt > Date: Thu, 19 Aug 2010 15:23:23 +1000 > > > Similar here, but using atomic_long_t instead so it works for 32-bit too > > for me. I suppose we could make that part common indeed. > > > > What about asm-generic/rwsem-atomic.h or rwsem-cmpxchg.h ? > > Using rwsem-cmpxchg.h sounds best I guess. Ok, I'll send a new patch tomorrow that does that. Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
From: Benjamin Herrenschmidt Date: Thu, 19 Aug 2010 15:23:23 +1000 > Similar here, but using atomic_long_t instead so it works for 32-bit too > for me. I suppose we could make that part common indeed. > > What about asm-generic/rwsem-atomic.h or rwsem-cmpxchg.h ? Using rwsem-cmpxchg.h sounds best I guess. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
On Tue, 2010-08-17 at 22:28 -0700, David Miller wrote: > From: Benjamin Herrenschmidt > Date: Wed, 18 Aug 2010 15:03:23 +1000 > > > I tried various tricks but so far they didn't work. I'll have another > > look tomorrow, but I may end up having to keep all the crap typecasts. > > The casts are pretty much unavoidable. > > Here's what I'm going to end up using on sparc64: Similar here, but using atomic_long_t instead so it works for 32-bit too for me. I suppose we could make that part common indeed. What about asm-generic/rwsem-atomic.h or rwsem-cmpxchg.h ? Below is my current patch, seems to boot fine here so far. Cheers, Ben Subject: [PATCH] powerpc: Make rwsem use "long" type This makes the 64-bit kernel use 64-bit signed integers for the counter (effectively supporting 32-bit of active count in the semaphore), thus avoiding things like overflow of the mmap_sem if you use a really crazy number of threads Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/rwsem.h | 64 ++ 1 files changed, 37 insertions(+), 27 deletions(-) diff --git a/arch/powerpc/include/asm/rwsem.h b/arch/powerpc/include/asm/rwsem.h index 24cd928..8447d89 100644 --- a/arch/powerpc/include/asm/rwsem.h +++ b/arch/powerpc/include/asm/rwsem.h @@ -21,15 +21,20 @@ /* * the semaphore definition */ -struct rw_semaphore { - /* XXX this should be able to be an atomic_t -- paulus */ - signed int count; -#define RWSEM_UNLOCKED_VALUE 0x -#define RWSEM_ACTIVE_BIAS 0x0001 -#define RWSEM_ACTIVE_MASK 0x -#define RWSEM_WAITING_BIAS (-0x0001) +#ifdef CONFIG_PPC64 +# define RWSEM_ACTIVE_MASK 0xL +#else +# define RWSEM_ACTIVE_MASK 0xL +#endif + +#define RWSEM_UNLOCKED_VALUE 0xL +#define RWSEM_ACTIVE_BIAS 0x0001L +#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) + +struct rw_semaphore { + longcount; spinlock_t wait_lock; struct list_headwait_list; #ifdef CONFIG_DEBUG_LOCK_ALLOC @@ -43,9 +48,13 @@ struct rw_semaphore { # define __RWSEM_DEP_MAP_INIT(lockname) #endif -#define __RWSEM_INITIALIZER(name) \ - { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \ - LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) } +#define __RWSEM_INITIALIZER(name) \ +{ \ + RWSEM_UNLOCKED_VALUE, \ + __SPIN_LOCK_UNLOCKED((name).wait_lock), \ + LIST_HEAD_INIT((name).wait_list)\ + __RWSEM_DEP_MAP_INIT(name) \ +} #define DECLARE_RWSEM(name)\ struct rw_semaphore name = __RWSEM_INITIALIZER(name) @@ -70,13 +79,13 @@ extern void __init_rwsem(struct rw_semaphore *sem, const char *name, */ static inline void __down_read(struct rw_semaphore *sem) { - if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0)) + if (unlikely(atomic_long_inc_return((atomic_long_t *)&sem->count) <= 0)) rwsem_down_read_failed(sem); } static inline int __down_read_trylock(struct rw_semaphore *sem) { - int tmp; + long tmp; while ((tmp = sem->count) >= 0) { if (tmp == cmpxchg(&sem->count, tmp, @@ -92,10 +101,10 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) */ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) { - int tmp; + long tmp; - tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)); + tmp = atomic_long_add_return(RWSEM_ACTIVE_WRITE_BIAS, +(atomic_long_t *)&sem->count); if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) rwsem_down_write_failed(sem); } @@ -107,7 +116,7 @@ static inline void __down_write(struct rw_semaphore *sem) static inline int __down_write_trylock(struct rw_semaphore *sem) { - int tmp; + long tmp; tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS); @@ -119,9 +128,9 @@ static inline int __down_write_trylock(struct rw_semaphore *sem) */ static inline void __up_read(struct rw_semaphore *sem) { - int tmp; + long tmp; - tmp = atomic_dec_return((atomic_t *)(&sem->count)); + tmp = atomic_long_dec_return((atomic_long_t *)&sem->count); if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)) rwsem_wake(sem); } @@ -131,17 +140,17 @@ static inline void __up_read(struct rw_
Re: 64-bit ppc rwsem
From: Sam Ravnborg Date: Wed, 18 Aug 2010 07:39:55 +0200 >> @@ -15,7 +15,7 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o >> lib-$(CONFIG_SPARC32) += copy_user.o locks.o >> lib-y += atomic_$(BITS).o >> lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o >> -lib-y += rwsem_$(BITS).o >> +lib-$(CONFIG_SPARC32) += rwsem_$(BITS).o > > You could write this explicit as: > >> +lib-$(CONFIG_SPARC32) += rwsem_32.o > > As rwsem_64 is gone now. Sure, I'll make that change, thanks Sam. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
> diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile > index c4b5e03..fa4c3ea 100644 > --- a/arch/sparc/lib/Makefile > +++ b/arch/sparc/lib/Makefile > @@ -15,7 +15,7 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o > lib-$(CONFIG_SPARC32) += copy_user.o locks.o > lib-y += atomic_$(BITS).o > lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o > -lib-y += rwsem_$(BITS).o > +lib-$(CONFIG_SPARC32) += rwsem_$(BITS).o You could write this explicit as: > +lib-$(CONFIG_SPARC32) += rwsem_32.o As rwsem_64 is gone now. Sam ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: 64-bit ppc rwsem
From: Benjamin Herrenschmidt Date: Wed, 18 Aug 2010 15:03:23 +1000 > I tried various tricks but so far they didn't work. I'll have another > look tomorrow, but I may end up having to keep all the crap typecasts. The casts are pretty much unavoidable. Here's what I'm going to end up using on sparc64: sparc64: Make rwsems 64-bit. Basically tip-off the powerpc code, use a 64-bit type and atomic64_t interfaces for the implementation. This gets us off of the by-hand asm code I wrote, which frankly I think probably ruins I-cache hit rates. The idea was the keep the call chains less deep, but anything taking the rw-semaphores probably is also calling other stuff and therefore already has allocated a stack-frame. So no real stack frame savings ever. Ben H. has posted patches to make powerpc use 64-bit too and with some abstractions we can probably use a shared header file somewhere. Signed-off-by: David S. Miller --- arch/sparc/include/asm/rwsem-const.h | 12 --- arch/sparc/include/asm/rwsem.h | 120 + arch/sparc/lib/Makefile |2 +- arch/sparc/lib/rwsem_64.S| 163 -- 4 files changed, 104 insertions(+), 193 deletions(-) delete mode 100644 arch/sparc/include/asm/rwsem-const.h delete mode 100644 arch/sparc/lib/rwsem_64.S diff --git a/arch/sparc/include/asm/rwsem-const.h b/arch/sparc/include/asm/rwsem-const.h deleted file mode 100644 index e4c61a1..000 --- a/arch/sparc/include/asm/rwsem-const.h +++ /dev/null @@ -1,12 +0,0 @@ -/* rwsem-const.h: RW semaphore counter constants. */ -#ifndef _SPARC64_RWSEM_CONST_H -#define _SPARC64_RWSEM_CONST_H - -#define RWSEM_UNLOCKED_VALUE 0x -#define RWSEM_ACTIVE_BIAS 0x0001 -#define RWSEM_ACTIVE_MASK 0x -#define RWSEM_WAITING_BIAS (-0x0001) -#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) - -#endif /* _SPARC64_RWSEM_CONST_H */ diff --git a/arch/sparc/include/asm/rwsem.h b/arch/sparc/include/asm/rwsem.h index 6e56210..a2b4302 100644 --- a/arch/sparc/include/asm/rwsem.h +++ b/arch/sparc/include/asm/rwsem.h @@ -15,16 +15,21 @@ #include #include -#include struct rwsem_waiter; struct rw_semaphore { - signed int count; - spinlock_t wait_lock; - struct list_headwait_list; + signed long count; +#define RWSEM_UNLOCKED_VALUE 0xL +#define RWSEM_ACTIVE_BIAS 0x0001L +#define RWSEM_ACTIVE_MASK 0xL +#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) + spinlock_t wait_lock; + struct list_headwait_list; #ifdef CONFIG_DEBUG_LOCK_ALLOC - struct lockdep_map dep_map; + struct lockdep_map dep_map; #endif }; @@ -41,6 +46,11 @@ struct rw_semaphore { #define DECLARE_RWSEM(name) \ struct rw_semaphore name = __RWSEM_INITIALIZER(name) +extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); + extern void __init_rwsem(struct rw_semaphore *sem, const char *name, struct lock_class_key *key); @@ -51,27 +61,103 @@ do { \ __init_rwsem((sem), #sem, &__key); \ } while (0) -extern void __down_read(struct rw_semaphore *sem); -extern int __down_read_trylock(struct rw_semaphore *sem); -extern void __down_write(struct rw_semaphore *sem); -extern int __down_write_trylock(struct rw_semaphore *sem); -extern void __up_read(struct rw_semaphore *sem); -extern void __up_write(struct rw_semaphore *sem); -extern void __downgrade_write(struct rw_semaphore *sem); +/* + * lock for reading + */ +static inline void __down_read(struct rw_semaphore *sem) +{ + if (unlikely(atomic64_inc_return((atomic64_t *)(&sem->count)) <= 0L)) + rwsem_down_read_failed(sem); +} + +static inline int __down_read_trylock(struct rw_semaphore *sem) +{ + long tmp; + + while ((tmp = sem->count) >= 0L) { + if (tmp == cmpxchg(&sem->count, tmp, + tmp + RWSEM_ACTIVE_READ_BIAS)) { + return 1; + } + } + return 0; +} +/* + * lock for writing + */ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) { - __down_write(sem); + long tmp; + + tmp = atomic64_a
Re: 64-bit ppc rwsem (was: Re: [GIT] Sparc)
On Wed, 2010-08-18 at 14:38 +1000, Benjamin Herrenschmidt wrote: > > Here's an untested patch for the folks on linuxppc-dev to look at, > I'll > review my own stuff & test tomorrow. Allright, gcc's being a pain, and atomics are a struct so we can't that easily assign. I tried various tricks but so far they didn't work. I'll have another look tomorrow, but I may end up having to keep all the crap typecasts. Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
64-bit ppc rwsem (was: Re: [GIT] Sparc)
On Tue, 2010-08-17 at 19:14 -0700, David Miller wrote: > > I merged your pull request, but you've got some fixing up to do, > > methinks. I also really think you need to make your rwsem's use 64-bit > > values on sparc64, because otherwise you can overflow the mmap_sem by > > having more than 65536 threads doing page-faults (on 32-bit, having > > more than 2**16 threads in one process is unlikely to work for other > > reasons, like just pure stack usage, so we don't really care about the > > 32-bit case) > > I have a patch to do this already, just need to test it. > > You should bug the powerpc folks too :-) 32K threads :-) you guys are nuts ! Here's an untested patch for the folks on linuxppc-dev to look at, I'll review my own stuff & test tomorrow. Cheers, Ben. powerpc: Make rwsem use "long" types on 64-bit platforms This should avoid overflow of the mmap_sem when playing with insane number of threads. Not-signed-off-by-yet. diff --git a/arch/powerpc/include/asm/rwsem.h b/arch/powerpc/include/asm/rwsem.h index 24cd928..ca64a98 100644 --- a/arch/powerpc/include/asm/rwsem.h +++ b/arch/powerpc/include/asm/rwsem.h @@ -21,15 +21,20 @@ /* * the semaphore definition */ -struct rw_semaphore { - /* XXX this should be able to be an atomic_t -- paulus */ - signed int count; -#define RWSEM_UNLOCKED_VALUE 0x -#define RWSEM_ACTIVE_BIAS 0x0001 -#define RWSEM_ACTIVE_MASK 0x -#define RWSEM_WAITING_BIAS (-0x0001) +#ifdef CONFIG_PPC64 +# define RWSEM_ACTIVE_MASK 0xL +#else +# define RWSEM_ACTIVE_MASK 0xL +#endif + +#define RWSEM_UNLOCKED_VALUE 0xL +#define RWSEM_ACTIVE_BIAS 0x0001L +#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) + +struct rw_semaphore { + atomic_long_t count; spinlock_t wait_lock; struct list_headwait_list; #ifdef CONFIG_DEBUG_LOCK_ALLOC @@ -43,9 +48,13 @@ struct rw_semaphore { # define __RWSEM_DEP_MAP_INIT(lockname) #endif -#define __RWSEM_INITIALIZER(name) \ - { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \ - LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) } +#define __RWSEM_INITIALIZER(name) \ +{ \ + ATOMIC_LONG_INIT(RWSEM_UNLOCKED_VALUE), \ + __SPIN_LOCK_UNLOCKED((name).wait_lock), \ + LIST_HEAD_INIT((name).wait_list)\ + __RWSEM_DEP_MAP_INIT(name) \ +} #define DECLARE_RWSEM(name)\ struct rw_semaphore name = __RWSEM_INITIALIZER(name) @@ -70,16 +79,16 @@ extern void __init_rwsem(struct rw_semaphore *sem, const char *name, */ static inline void __down_read(struct rw_semaphore *sem) { - if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0)) + if (unlikely(atomic_long_inc_return(&sem->count) <= 0)) rwsem_down_read_failed(sem); } static inline int __down_read_trylock(struct rw_semaphore *sem) { - int tmp; + long tmp; - while ((tmp = sem->count) >= 0) { - if (tmp == cmpxchg(&sem->count, tmp, + while ((tmp = atomic_long_read(&sem->count)) >= 0) { + if (tmp == cmpxchg((long *)&sem->count, tmp, tmp + RWSEM_ACTIVE_READ_BIAS)) { return 1; } @@ -92,10 +101,10 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) */ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) { - int tmp; + long tmp; - tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)); + tmp = atomic_long_add_return(RWSEM_ACTIVE_WRITE_BIAS, +&sem->count); if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) rwsem_down_write_failed(sem); } @@ -107,9 +116,9 @@ static inline void __down_write(struct rw_semaphore *sem) static inline int __down_write_trylock(struct rw_semaphore *sem) { - int tmp; + long tmp; - tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, + tmp = cmpxchg((long *)&sem->count, RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS); return tmp == RWSEM_UNLOCKED_VALUE; } @@ -119,9 +128,9 @@ static inline int __down_write_trylock(struct rw_semaphore *sem) */ static inline void __up_read(struct rw_semaphore *sem) { - int tmp; + long tmp; - tmp = atomic_dec_return((atomic_t *)(&sem->count)); + tmp = atomic_long_dec_return(&sem->count); if (unlik