16b6b4792SThomas Gleixner #ifndef __LINUX_RWLOCK_API_SMP_H
26b6b4792SThomas Gleixner #define __LINUX_RWLOCK_API_SMP_H
36b6b4792SThomas Gleixner
46b6b4792SThomas Gleixner #ifndef __LINUX_SPINLOCK_API_SMP_H
5*a7306f3cSNataniel Farzan # error "Please do not include this file directly."
66b6b4792SThomas Gleixner #endif
76b6b4792SThomas Gleixner
86b6b4792SThomas Gleixner /*
96b6b4792SThomas Gleixner * include/linux/rwlock_api_smp.h
106b6b4792SThomas Gleixner *
116b6b4792SThomas Gleixner * spinlock API declarations on SMP (and debug)
126b6b4792SThomas Gleixner * (implemented in kernel/spinlock.c)
136b6b4792SThomas Gleixner *
146b6b4792SThomas Gleixner * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
156b6b4792SThomas Gleixner * Released under the General Public License (GPL).
166b6b4792SThomas Gleixner */
176b6b4792SThomas Gleixner
189c1721aaSThomas Gleixner void __lockfunc _raw_read_lock(rwlock_t *lock) __acquires(lock);
199c1721aaSThomas Gleixner void __lockfunc _raw_write_lock(rwlock_t *lock) __acquires(lock);
204a57d6bbSMinchan Kim void __lockfunc _raw_write_lock_nested(rwlock_t *lock, int subclass) __acquires(lock);
219c1721aaSThomas Gleixner void __lockfunc _raw_read_lock_bh(rwlock_t *lock) __acquires(lock);
229c1721aaSThomas Gleixner void __lockfunc _raw_write_lock_bh(rwlock_t *lock) __acquires(lock);
239c1721aaSThomas Gleixner void __lockfunc _raw_read_lock_irq(rwlock_t *lock) __acquires(lock);
249c1721aaSThomas Gleixner void __lockfunc _raw_write_lock_irq(rwlock_t *lock) __acquires(lock);
259c1721aaSThomas Gleixner unsigned long __lockfunc _raw_read_lock_irqsave(rwlock_t *lock)
266b6b4792SThomas Gleixner __acquires(lock);
279c1721aaSThomas Gleixner unsigned long __lockfunc _raw_write_lock_irqsave(rwlock_t *lock)
286b6b4792SThomas Gleixner __acquires(lock);
299c1721aaSThomas Gleixner int __lockfunc _raw_read_trylock(rwlock_t *lock);
309c1721aaSThomas Gleixner int __lockfunc _raw_write_trylock(rwlock_t *lock);
319c1721aaSThomas Gleixner void __lockfunc _raw_read_unlock(rwlock_t *lock) __releases(lock);
329c1721aaSThomas Gleixner void __lockfunc _raw_write_unlock(rwlock_t *lock) __releases(lock);
339c1721aaSThomas Gleixner void __lockfunc _raw_read_unlock_bh(rwlock_t *lock) __releases(lock);
349c1721aaSThomas Gleixner void __lockfunc _raw_write_unlock_bh(rwlock_t *lock) __releases(lock);
359c1721aaSThomas Gleixner void __lockfunc _raw_read_unlock_irq(rwlock_t *lock) __releases(lock);
369c1721aaSThomas Gleixner void __lockfunc _raw_write_unlock_irq(rwlock_t *lock) __releases(lock);
379c1721aaSThomas Gleixner void __lockfunc
389c1721aaSThomas Gleixner _raw_read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
396b6b4792SThomas Gleixner __releases(lock);
409c1721aaSThomas Gleixner void __lockfunc
419c1721aaSThomas Gleixner _raw_write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
426b6b4792SThomas Gleixner __releases(lock);
436b6b4792SThomas Gleixner
446b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_LOCK
459c1721aaSThomas Gleixner #define _raw_read_lock(lock) __raw_read_lock(lock)
466b6b4792SThomas Gleixner #endif
476b6b4792SThomas Gleixner
486b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_LOCK
499c1721aaSThomas Gleixner #define _raw_write_lock(lock) __raw_write_lock(lock)
506b6b4792SThomas Gleixner #endif
516b6b4792SThomas Gleixner
526b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_LOCK_BH
539c1721aaSThomas Gleixner #define _raw_read_lock_bh(lock) __raw_read_lock_bh(lock)
546b6b4792SThomas Gleixner #endif
556b6b4792SThomas Gleixner
566b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_LOCK_BH
579c1721aaSThomas Gleixner #define _raw_write_lock_bh(lock) __raw_write_lock_bh(lock)
586b6b4792SThomas Gleixner #endif
596b6b4792SThomas Gleixner
606b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_LOCK_IRQ
619c1721aaSThomas Gleixner #define _raw_read_lock_irq(lock) __raw_read_lock_irq(lock)
626b6b4792SThomas Gleixner #endif
636b6b4792SThomas Gleixner
646b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_LOCK_IRQ
659c1721aaSThomas Gleixner #define _raw_write_lock_irq(lock) __raw_write_lock_irq(lock)
666b6b4792SThomas Gleixner #endif
676b6b4792SThomas Gleixner
686b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_LOCK_IRQSAVE
699c1721aaSThomas Gleixner #define _raw_read_lock_irqsave(lock) __raw_read_lock_irqsave(lock)
706b6b4792SThomas Gleixner #endif
716b6b4792SThomas Gleixner
726b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_LOCK_IRQSAVE
739c1721aaSThomas Gleixner #define _raw_write_lock_irqsave(lock) __raw_write_lock_irqsave(lock)
746b6b4792SThomas Gleixner #endif
756b6b4792SThomas Gleixner
766b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_TRYLOCK
779c1721aaSThomas Gleixner #define _raw_read_trylock(lock) __raw_read_trylock(lock)
786b6b4792SThomas Gleixner #endif
796b6b4792SThomas Gleixner
806b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_TRYLOCK
819c1721aaSThomas Gleixner #define _raw_write_trylock(lock) __raw_write_trylock(lock)
826b6b4792SThomas Gleixner #endif
836b6b4792SThomas Gleixner
846b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_UNLOCK
859c1721aaSThomas Gleixner #define _raw_read_unlock(lock) __raw_read_unlock(lock)
866b6b4792SThomas Gleixner #endif
876b6b4792SThomas Gleixner
886b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_UNLOCK
899c1721aaSThomas Gleixner #define _raw_write_unlock(lock) __raw_write_unlock(lock)
906b6b4792SThomas Gleixner #endif
916b6b4792SThomas Gleixner
926b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_UNLOCK_BH
939c1721aaSThomas Gleixner #define _raw_read_unlock_bh(lock) __raw_read_unlock_bh(lock)
946b6b4792SThomas Gleixner #endif
956b6b4792SThomas Gleixner
966b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_UNLOCK_BH
979c1721aaSThomas Gleixner #define _raw_write_unlock_bh(lock) __raw_write_unlock_bh(lock)
986b6b4792SThomas Gleixner #endif
996b6b4792SThomas Gleixner
1006b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_UNLOCK_IRQ
1019c1721aaSThomas Gleixner #define _raw_read_unlock_irq(lock) __raw_read_unlock_irq(lock)
1026b6b4792SThomas Gleixner #endif
1036b6b4792SThomas Gleixner
1046b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_UNLOCK_IRQ
1059c1721aaSThomas Gleixner #define _raw_write_unlock_irq(lock) __raw_write_unlock_irq(lock)
1066b6b4792SThomas Gleixner #endif
1076b6b4792SThomas Gleixner
1086b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_READ_UNLOCK_IRQRESTORE
1099c1721aaSThomas Gleixner #define _raw_read_unlock_irqrestore(lock, flags) \
1109c1721aaSThomas Gleixner __raw_read_unlock_irqrestore(lock, flags)
1116b6b4792SThomas Gleixner #endif
1126b6b4792SThomas Gleixner
1136b6b4792SThomas Gleixner #ifdef CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE
1149c1721aaSThomas Gleixner #define _raw_write_unlock_irqrestore(lock, flags) \
1159c1721aaSThomas Gleixner __raw_write_unlock_irqrestore(lock, flags)
1166b6b4792SThomas Gleixner #endif
1176b6b4792SThomas Gleixner
__raw_read_trylock(rwlock_t * lock)1189c1721aaSThomas Gleixner static inline int __raw_read_trylock(rwlock_t *lock)
1196b6b4792SThomas Gleixner {
1206b6b4792SThomas Gleixner preempt_disable();
1219828ea9dSThomas Gleixner if (do_raw_read_trylock(lock)) {
1226b6b4792SThomas Gleixner rwlock_acquire_read(&lock->dep_map, 0, 1, _RET_IP_);
1236b6b4792SThomas Gleixner return 1;
1246b6b4792SThomas Gleixner }
1256b6b4792SThomas Gleixner preempt_enable();
1266b6b4792SThomas Gleixner return 0;
1276b6b4792SThomas Gleixner }
1286b6b4792SThomas Gleixner
__raw_write_trylock(rwlock_t * lock)1299c1721aaSThomas Gleixner static inline int __raw_write_trylock(rwlock_t *lock)
1306b6b4792SThomas Gleixner {
1316b6b4792SThomas Gleixner preempt_disable();
1329828ea9dSThomas Gleixner if (do_raw_write_trylock(lock)) {
1336b6b4792SThomas Gleixner rwlock_acquire(&lock->dep_map, 0, 1, _RET_IP_);
1346b6b4792SThomas Gleixner return 1;
1356b6b4792SThomas Gleixner }
1366b6b4792SThomas Gleixner preempt_enable();
1376b6b4792SThomas Gleixner return 0;
1386b6b4792SThomas Gleixner }
1396b6b4792SThomas Gleixner
1406b6b4792SThomas Gleixner /*
1416b6b4792SThomas Gleixner * If lockdep is enabled then we use the non-preemption spin-ops
1426b6b4792SThomas Gleixner * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are
1436b6b4792SThomas Gleixner * not re-enabled during lock-acquire (which the preempt-spin-ops do):
1446b6b4792SThomas Gleixner */
1456b6b4792SThomas Gleixner #if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC)
1466b6b4792SThomas Gleixner
__raw_read_lock(rwlock_t * lock)1479c1721aaSThomas Gleixner static inline void __raw_read_lock(rwlock_t *lock)
1486b6b4792SThomas Gleixner {
1496b6b4792SThomas Gleixner preempt_disable();
1506b6b4792SThomas Gleixner rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
1519828ea9dSThomas Gleixner LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
1526b6b4792SThomas Gleixner }
1536b6b4792SThomas Gleixner
__raw_read_lock_irqsave(rwlock_t * lock)1549c1721aaSThomas Gleixner static inline unsigned long __raw_read_lock_irqsave(rwlock_t *lock)
1556b6b4792SThomas Gleixner {
1566b6b4792SThomas Gleixner unsigned long flags;
1576b6b4792SThomas Gleixner
1586b6b4792SThomas Gleixner local_irq_save(flags);
1596b6b4792SThomas Gleixner preempt_disable();
1606b6b4792SThomas Gleixner rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
161f98a3dccSArnd Bergmann LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
1626b6b4792SThomas Gleixner return flags;
1636b6b4792SThomas Gleixner }
1646b6b4792SThomas Gleixner
__raw_read_lock_irq(rwlock_t * lock)1659c1721aaSThomas Gleixner static inline void __raw_read_lock_irq(rwlock_t *lock)
1666b6b4792SThomas Gleixner {
1676b6b4792SThomas Gleixner local_irq_disable();
1686b6b4792SThomas Gleixner preempt_disable();
1696b6b4792SThomas Gleixner rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
1709828ea9dSThomas Gleixner LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
1716b6b4792SThomas Gleixner }
1726b6b4792SThomas Gleixner
__raw_read_lock_bh(rwlock_t * lock)1739c1721aaSThomas Gleixner static inline void __raw_read_lock_bh(rwlock_t *lock)
1746b6b4792SThomas Gleixner {
1759ea4c380SPeter Zijlstra __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
1766b6b4792SThomas Gleixner rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
1779828ea9dSThomas Gleixner LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
1786b6b4792SThomas Gleixner }
1796b6b4792SThomas Gleixner
__raw_write_lock_irqsave(rwlock_t * lock)1809c1721aaSThomas Gleixner static inline unsigned long __raw_write_lock_irqsave(rwlock_t *lock)
1816b6b4792SThomas Gleixner {
1826b6b4792SThomas Gleixner unsigned long flags;
1836b6b4792SThomas Gleixner
1846b6b4792SThomas Gleixner local_irq_save(flags);
1856b6b4792SThomas Gleixner preempt_disable();
1866b6b4792SThomas Gleixner rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
187f98a3dccSArnd Bergmann LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
1886b6b4792SThomas Gleixner return flags;
1896b6b4792SThomas Gleixner }
1906b6b4792SThomas Gleixner
__raw_write_lock_irq(rwlock_t * lock)1919c1721aaSThomas Gleixner static inline void __raw_write_lock_irq(rwlock_t *lock)
1926b6b4792SThomas Gleixner {
1936b6b4792SThomas Gleixner local_irq_disable();
1946b6b4792SThomas Gleixner preempt_disable();
1956b6b4792SThomas Gleixner rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
1969828ea9dSThomas Gleixner LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
1976b6b4792SThomas Gleixner }
1986b6b4792SThomas Gleixner
__raw_write_lock_bh(rwlock_t * lock)1999c1721aaSThomas Gleixner static inline void __raw_write_lock_bh(rwlock_t *lock)
2006b6b4792SThomas Gleixner {
2019ea4c380SPeter Zijlstra __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
2026b6b4792SThomas Gleixner rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
2039828ea9dSThomas Gleixner LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
2046b6b4792SThomas Gleixner }
2056b6b4792SThomas Gleixner
__raw_write_lock(rwlock_t * lock)2069c1721aaSThomas Gleixner static inline void __raw_write_lock(rwlock_t *lock)
2076b6b4792SThomas Gleixner {
2086b6b4792SThomas Gleixner preempt_disable();
2096b6b4792SThomas Gleixner rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
2109828ea9dSThomas Gleixner LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
2116b6b4792SThomas Gleixner }
2126b6b4792SThomas Gleixner
__raw_write_lock_nested(rwlock_t * lock,int subclass)2134a57d6bbSMinchan Kim static inline void __raw_write_lock_nested(rwlock_t *lock, int subclass)
2144a57d6bbSMinchan Kim {
2154a57d6bbSMinchan Kim preempt_disable();
2164a57d6bbSMinchan Kim rwlock_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
2174a57d6bbSMinchan Kim LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
2184a57d6bbSMinchan Kim }
2194a57d6bbSMinchan Kim
220f791dd25SCheng Jian #endif /* !CONFIG_GENERIC_LOCKBREAK || CONFIG_DEBUG_LOCK_ALLOC */
2216b6b4792SThomas Gleixner
__raw_write_unlock(rwlock_t * lock)2229c1721aaSThomas Gleixner static inline void __raw_write_unlock(rwlock_t *lock)
2236b6b4792SThomas Gleixner {
2245facae4fSQian Cai rwlock_release(&lock->dep_map, _RET_IP_);
2259828ea9dSThomas Gleixner do_raw_write_unlock(lock);
2266b6b4792SThomas Gleixner preempt_enable();
2276b6b4792SThomas Gleixner }
2286b6b4792SThomas Gleixner
__raw_read_unlock(rwlock_t * lock)2299c1721aaSThomas Gleixner static inline void __raw_read_unlock(rwlock_t *lock)
2306b6b4792SThomas Gleixner {
2315facae4fSQian Cai rwlock_release(&lock->dep_map, _RET_IP_);
2329828ea9dSThomas Gleixner do_raw_read_unlock(lock);
2336b6b4792SThomas Gleixner preempt_enable();
2346b6b4792SThomas Gleixner }
2356b6b4792SThomas Gleixner
2369c1721aaSThomas Gleixner static inline void
__raw_read_unlock_irqrestore(rwlock_t * lock,unsigned long flags)2379c1721aaSThomas Gleixner __raw_read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
2386b6b4792SThomas Gleixner {
2395facae4fSQian Cai rwlock_release(&lock->dep_map, _RET_IP_);
2409828ea9dSThomas Gleixner do_raw_read_unlock(lock);
2416b6b4792SThomas Gleixner local_irq_restore(flags);
2426b6b4792SThomas Gleixner preempt_enable();
2436b6b4792SThomas Gleixner }
2446b6b4792SThomas Gleixner
__raw_read_unlock_irq(rwlock_t * lock)2459c1721aaSThomas Gleixner static inline void __raw_read_unlock_irq(rwlock_t *lock)
2466b6b4792SThomas Gleixner {
2475facae4fSQian Cai rwlock_release(&lock->dep_map, _RET_IP_);
2489828ea9dSThomas Gleixner do_raw_read_unlock(lock);
2496b6b4792SThomas Gleixner local_irq_enable();
2506b6b4792SThomas Gleixner preempt_enable();
2516b6b4792SThomas Gleixner }
2526b6b4792SThomas Gleixner
__raw_read_unlock_bh(rwlock_t * lock)2539c1721aaSThomas Gleixner static inline void __raw_read_unlock_bh(rwlock_t *lock)
2546b6b4792SThomas Gleixner {
2555facae4fSQian Cai rwlock_release(&lock->dep_map, _RET_IP_);
2569828ea9dSThomas Gleixner do_raw_read_unlock(lock);
2579ea4c380SPeter Zijlstra __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
2586b6b4792SThomas Gleixner }
2596b6b4792SThomas Gleixner
__raw_write_unlock_irqrestore(rwlock_t * lock,unsigned long flags)2609c1721aaSThomas Gleixner static inline void __raw_write_unlock_irqrestore(rwlock_t *lock,
2616b6b4792SThomas Gleixner unsigned long flags)
2626b6b4792SThomas Gleixner {
2635facae4fSQian Cai rwlock_release(&lock->dep_map, _RET_IP_);
2649828ea9dSThomas Gleixner do_raw_write_unlock(lock);
2656b6b4792SThomas Gleixner local_irq_restore(flags);
2666b6b4792SThomas Gleixner preempt_enable();
2676b6b4792SThomas Gleixner }
2686b6b4792SThomas Gleixner
__raw_write_unlock_irq(rwlock_t * lock)2699c1721aaSThomas Gleixner static inline void __raw_write_unlock_irq(rwlock_t *lock)
2706b6b4792SThomas Gleixner {
2715facae4fSQian Cai rwlock_release(&lock->dep_map, _RET_IP_);
2729828ea9dSThomas Gleixner do_raw_write_unlock(lock);
2736b6b4792SThomas Gleixner local_irq_enable();
2746b6b4792SThomas Gleixner preempt_enable();
2756b6b4792SThomas Gleixner }
2766b6b4792SThomas Gleixner
__raw_write_unlock_bh(rwlock_t * lock)2779c1721aaSThomas Gleixner static inline void __raw_write_unlock_bh(rwlock_t *lock)
2786b6b4792SThomas Gleixner {
2795facae4fSQian Cai rwlock_release(&lock->dep_map, _RET_IP_);
2809828ea9dSThomas Gleixner do_raw_write_unlock(lock);
2819ea4c380SPeter Zijlstra __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
2826b6b4792SThomas Gleixner }
2836b6b4792SThomas Gleixner
2846b6b4792SThomas Gleixner #endif /* __LINUX_RWLOCK_API_SMP_H */
285