/* * Macros shared by spinlock.c and rwlock.c */ /* * This could be a long-held lock. We both prepare to spin for a long * time (making _this_ CPU preemptable if possible), and we also signal * towards that other CPU that it should break the lock ASAP. * * (We do this in a function because inlining it would be excessive.) */ #define BUILD_LOCK_OPS(prefix, op, locktype) \ void __lockfunc _##prefix##_lock(locktype##_t *lock) \ { \ for (;;) { \ preempt_disable(); \ if (likely(_raw_##op##_trylock(lock))) \ break; \ preempt_enable(); \ \ if (!(lock)->break_lock) \ (lock)->break_lock = 1; \ while (!prefix##_can_lock(lock) && (lock)->break_lock) \ _raw_##op##_relax(&lock->raw_lock); \ } \ (lock)->break_lock = 0; \ } \ \ EXPORT_SYMBOL(_##prefix##_lock); \ \ unsigned long __lockfunc _##prefix##_lock_irqsave(locktype##_t *lock) \ { \ unsigned long flags; \ \ for (;;) { \ preempt_disable(); \ local_irq_save(flags); \ if (likely(_raw_##op##_trylock(lock))) \ break; \ local_irq_restore(flags); \ preempt_enable(); \ \ if (!(lock)->break_lock) \ (lock)->break_lock = 1; \ while (!prefix##_can_lock(lock) && (lock)->break_lock) \ _raw_##op##_relax(&lock->raw_lock); \ } \ (lock)->break_lock = 0; \ return flags; \ } \ \ EXPORT_SYMBOL(_##prefix##_lock_irqsave); \ \ void __lockfunc _##prefix##_lock_irq(locktype##_t *lock) \ { \ _##prefix##_lock_irqsave(lock); \ } \ \ EXPORT_SYMBOL(_##prefix##_lock_irq); \ \ void __lockfunc _##prefix##_lock_bh(locktype##_t *lock) \ { \ unsigned long flags; \ \ /* */ \ /* Careful: we must exclude softirqs too, hence the */ \ /* irq-disabling. We use the generic preemption-aware */ \ /* function: */ \ /**/ \ flags = _##prefix##_lock_irqsave(lock); \ local_bh_disable(); \ local_irq_restore(flags); \ } \ \ EXPORT_SYMBOL(_##prefix##_lock_bh)