1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_LOCAL_LOCK_H 3 # error "Do not include directly, include linux/local_lock.h" 4 #endif 5 6 #include <linux/percpu-defs.h> 7 #include <linux/lockdep.h> 8 9 #ifndef CONFIG_PREEMPT_RT 10 11 typedef struct { 12 #ifdef CONFIG_DEBUG_LOCK_ALLOC 13 struct lockdep_map dep_map; 14 struct task_struct *owner; 15 #endif 16 } local_lock_t; 17 18 #ifdef CONFIG_DEBUG_LOCK_ALLOC 19 # define LOCAL_LOCK_DEBUG_INIT(lockname) \ 20 .dep_map = { \ 21 .name = #lockname, \ 22 .wait_type_inner = LD_WAIT_CONFIG, \ 23 .lock_type = LD_LOCK_PERCPU, \ 24 }, \ 25 .owner = NULL, 26 27 static inline void local_lock_acquire(local_lock_t *l) 28 { 29 lock_map_acquire(&l->dep_map); 30 DEBUG_LOCKS_WARN_ON(l->owner); 31 l->owner = current; 32 } 33 34 static inline void local_lock_release(local_lock_t *l) 35 { 36 DEBUG_LOCKS_WARN_ON(l->owner != current); 37 l->owner = NULL; 38 lock_map_release(&l->dep_map); 39 } 40 41 static inline void local_lock_debug_init(local_lock_t *l) 42 { 43 l->owner = NULL; 44 } 45 #else /* CONFIG_DEBUG_LOCK_ALLOC */ 46 # define LOCAL_LOCK_DEBUG_INIT(lockname) 47 static inline void local_lock_acquire(local_lock_t *l) { } 48 static inline void local_lock_release(local_lock_t *l) { } 49 static inline void local_lock_debug_init(local_lock_t *l) { } 50 #endif /* !CONFIG_DEBUG_LOCK_ALLOC */ 51 52 #define INIT_LOCAL_LOCK(lockname) { LOCAL_LOCK_DEBUG_INIT(lockname) } 53 54 #define __local_lock_init(lock) \ 55 do { \ 56 static struct lock_class_key __key; \ 57 \ 58 debug_check_no_locks_freed((void *)lock, sizeof(*lock));\ 59 lockdep_init_map_type(&(lock)->dep_map, #lock, &__key, \ 60 0, LD_WAIT_CONFIG, LD_WAIT_INV, \ 61 LD_LOCK_PERCPU); \ 62 local_lock_debug_init(lock); \ 63 } while (0) 64 65 #define __local_lock(lock) \ 66 do { \ 67 preempt_disable(); \ 68 local_lock_acquire(this_cpu_ptr(lock)); \ 69 } while (0) 70 71 #define __local_lock_irq(lock) \ 72 do { \ 73 local_irq_disable(); \ 74 local_lock_acquire(this_cpu_ptr(lock)); \ 75 } while (0) 76 77 #define __local_lock_irqsave(lock, flags) \ 78 do { \ 79 local_irq_save(flags); \ 80 local_lock_acquire(this_cpu_ptr(lock)); \ 81 } while (0) 82 83 #define __local_unlock(lock) \ 84 do { \ 85 local_lock_release(this_cpu_ptr(lock)); \ 86 preempt_enable(); \ 87 } while (0) 88 89 #define __local_unlock_irq(lock) \ 90 do { \ 91 local_lock_release(this_cpu_ptr(lock)); \ 92 local_irq_enable(); \ 93 } while (0) 94 95 #define __local_unlock_irqrestore(lock, flags) \ 96 do { \ 97 local_lock_release(this_cpu_ptr(lock)); \ 98 local_irq_restore(flags); \ 99 } while (0) 100 101 #else /* !CONFIG_PREEMPT_RT */ 102 103 /* 104 * On PREEMPT_RT local_lock maps to a per CPU spinlock, which protects the 105 * critical section while staying preemptible. 106 */ 107 typedef spinlock_t local_lock_t; 108 109 #define INIT_LOCAL_LOCK(lockname) __LOCAL_SPIN_LOCK_UNLOCKED((lockname)) 110 111 #define __local_lock_init(l) \ 112 do { \ 113 local_spin_lock_init((l)); \ 114 } while (0) 115 116 #define __local_lock(__lock) \ 117 do { \ 118 migrate_disable(); \ 119 spin_lock(this_cpu_ptr((__lock))); \ 120 } while (0) 121 122 #define __local_lock_irq(lock) __local_lock(lock) 123 124 #define __local_lock_irqsave(lock, flags) \ 125 do { \ 126 typecheck(unsigned long, flags); \ 127 flags = 0; \ 128 __local_lock(lock); \ 129 } while (0) 130 131 #define __local_unlock(__lock) \ 132 do { \ 133 spin_unlock(this_cpu_ptr((__lock))); \ 134 migrate_enable(); \ 135 } while (0) 136 137 #define __local_unlock_irq(lock) __local_unlock(lock) 138 139 #define __local_unlock_irqrestore(lock, flags) __local_unlock(lock) 140 141 #endif /* CONFIG_PREEMPT_RT */ 142