Loading include/asm-parisc/spinlock.h +61 −37 Original line number Diff line number Diff line Loading @@ -56,50 +56,70 @@ static inline int __raw_spin_trylock(raw_spinlock_t *x) } /* * Read-write spinlocks, allowing multiple readers * but only one writer. * Read-write spinlocks, allowing multiple readers but only one writer. * The spinlock is held by the writer, preventing any readers or other * writers from grabbing the rwlock. Readers use the lock to serialise their * access to the counter (which records how many readers currently hold the * lock). Linux rwlocks are unfair to writers; they can be starved for * an indefinite time by readers. They can also be taken in interrupt context, * so we have to disable interrupts when acquiring the spin lock to be sure * that an interrupting reader doesn't get an inconsistent view of the lock. */ #define __raw_read_trylock(lock) generic__raw_read_trylock(lock) /* read_lock, read_unlock are pretty straightforward. Of course it somehow * sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */ static __inline__ void __raw_read_lock(raw_rwlock_t *rw) { unsigned long flags; local_irq_save(flags); __raw_spin_lock(&rw->lock); rw->counter++; __raw_spin_unlock(&rw->lock); local_irq_restore(flags); } static __inline__ void __raw_read_unlock(raw_rwlock_t *rw) { unsigned long flags; local_irq_save(flags); __raw_spin_lock(&rw->lock); rw->counter--; __raw_spin_unlock(&rw->lock); local_irq_restore(flags); } static __inline__ int __raw_read_trylock(raw_rwlock_t *rw) { unsigned long flags; retry: local_irq_save(flags); if (__raw_spin_trylock(&rw->lock)) { rw->counter++; __raw_spin_unlock(&rw->lock); local_irq_restore(flags); return 1; } /* write_lock is less trivial. We optimistically grab the lock and check * if we surprised any readers. If so we release the lock and wait till * they're all gone before trying again * * Also note that we don't use the _irqsave / _irqrestore suffixes here. * If we're called with interrupts enabled and we've got readers (or other * writers) in interrupt handlers someone fucked up and we'd dead-lock * sooner or later anyway. prumpf */ local_irq_restore(flags); /* If write-locked, we fail to acquire the lock */ if (rw->counter < 0) return 0; /* Wait until we have a realistic chance at the lock */ while (__raw_spin_is_locked(&rw->lock) && rw->counter >= 0) cpu_relax(); goto retry; } static __inline__ void __raw_write_lock(raw_rwlock_t *rw) { unsigned long flags; retry: local_irq_save(flags); __raw_spin_lock(&rw->lock); if (rw->counter != 0) { /* this basically never happens */ __raw_spin_unlock(&rw->lock); local_irq_restore(flags); while (rw->counter != 0) cpu_relax(); Loading @@ -107,12 +127,11 @@ static __inline__ void __raw_write_lock(raw_rwlock_t *rw) goto retry; } /* got it. now leave without unlocking */ rw->counter = -1; /* remember we are locked */ rw->counter = -1; /* mark as write-locked */ mb(); local_irq_restore(flags); } /* write_unlock is absolutely trivial - we don't have to wait for anything */ static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) { rw->counter = 0; Loading @@ -121,17 +140,22 @@ static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) static __inline__ int __raw_write_trylock(raw_rwlock_t *rw) { __raw_spin_lock(&rw->lock); if (rw->counter != 0) { /* this basically never happens */ unsigned long flags; int result = 0; local_irq_save(flags); if (__raw_spin_trylock(&rw->lock)) { if (rw->counter == 0) { rw->counter = -1; result = 1; } else { /* Read-locked. Oh well. */ __raw_spin_unlock(&rw->lock); return 0; } } local_irq_restore(flags); /* got it. now leave without unlocking */ rw->counter = -1; /* remember we are locked */ return 1; return result; } /* Loading Loading
include/asm-parisc/spinlock.h +61 −37 Original line number Diff line number Diff line Loading @@ -56,50 +56,70 @@ static inline int __raw_spin_trylock(raw_spinlock_t *x) } /* * Read-write spinlocks, allowing multiple readers * but only one writer. * Read-write spinlocks, allowing multiple readers but only one writer. * The spinlock is held by the writer, preventing any readers or other * writers from grabbing the rwlock. Readers use the lock to serialise their * access to the counter (which records how many readers currently hold the * lock). Linux rwlocks are unfair to writers; they can be starved for * an indefinite time by readers. They can also be taken in interrupt context, * so we have to disable interrupts when acquiring the spin lock to be sure * that an interrupting reader doesn't get an inconsistent view of the lock. */ #define __raw_read_trylock(lock) generic__raw_read_trylock(lock) /* read_lock, read_unlock are pretty straightforward. Of course it somehow * sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */ static __inline__ void __raw_read_lock(raw_rwlock_t *rw) { unsigned long flags; local_irq_save(flags); __raw_spin_lock(&rw->lock); rw->counter++; __raw_spin_unlock(&rw->lock); local_irq_restore(flags); } static __inline__ void __raw_read_unlock(raw_rwlock_t *rw) { unsigned long flags; local_irq_save(flags); __raw_spin_lock(&rw->lock); rw->counter--; __raw_spin_unlock(&rw->lock); local_irq_restore(flags); } static __inline__ int __raw_read_trylock(raw_rwlock_t *rw) { unsigned long flags; retry: local_irq_save(flags); if (__raw_spin_trylock(&rw->lock)) { rw->counter++; __raw_spin_unlock(&rw->lock); local_irq_restore(flags); return 1; } /* write_lock is less trivial. We optimistically grab the lock and check * if we surprised any readers. If so we release the lock and wait till * they're all gone before trying again * * Also note that we don't use the _irqsave / _irqrestore suffixes here. * If we're called with interrupts enabled and we've got readers (or other * writers) in interrupt handlers someone fucked up and we'd dead-lock * sooner or later anyway. prumpf */ local_irq_restore(flags); /* If write-locked, we fail to acquire the lock */ if (rw->counter < 0) return 0; /* Wait until we have a realistic chance at the lock */ while (__raw_spin_is_locked(&rw->lock) && rw->counter >= 0) cpu_relax(); goto retry; } static __inline__ void __raw_write_lock(raw_rwlock_t *rw) { unsigned long flags; retry: local_irq_save(flags); __raw_spin_lock(&rw->lock); if (rw->counter != 0) { /* this basically never happens */ __raw_spin_unlock(&rw->lock); local_irq_restore(flags); while (rw->counter != 0) cpu_relax(); Loading @@ -107,12 +127,11 @@ static __inline__ void __raw_write_lock(raw_rwlock_t *rw) goto retry; } /* got it. now leave without unlocking */ rw->counter = -1; /* remember we are locked */ rw->counter = -1; /* mark as write-locked */ mb(); local_irq_restore(flags); } /* write_unlock is absolutely trivial - we don't have to wait for anything */ static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) { rw->counter = 0; Loading @@ -121,17 +140,22 @@ static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) static __inline__ int __raw_write_trylock(raw_rwlock_t *rw) { __raw_spin_lock(&rw->lock); if (rw->counter != 0) { /* this basically never happens */ unsigned long flags; int result = 0; local_irq_save(flags); if (__raw_spin_trylock(&rw->lock)) { if (rw->counter == 0) { rw->counter = -1; result = 1; } else { /* Read-locked. Oh well. */ __raw_spin_unlock(&rw->lock); return 0; } } local_irq_restore(flags); /* got it. now leave without unlocking */ rw->counter = -1; /* remember we are locked */ return 1; return result; } /* Loading