Linux 6.9-rc6
[sfrench/cifs-2.6.git] / include / linux / local_lock_internal.h
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 typedef struct {
10 #ifdef CONFIG_DEBUG_LOCK_ALLOC
11         struct lockdep_map      dep_map;
12         struct task_struct      *owner;
13 #endif
14 } local_lock_t;
15
16 #ifdef CONFIG_DEBUG_LOCK_ALLOC
17 # define LL_DEP_MAP_INIT(lockname)                      \
18         .dep_map = {                                    \
19                 .name = #lockname,                      \
20                 .wait_type_inner = LD_WAIT_CONFIG,      \
21                 .lock_type = LD_LOCK_PERCPU,                    \
22         }
23 #else
24 # define LL_DEP_MAP_INIT(lockname)
25 #endif
26
27 #define INIT_LOCAL_LOCK(lockname)       { LL_DEP_MAP_INIT(lockname) }
28
29 #define __local_lock_init(lock)                                 \
30 do {                                                            \
31         static struct lock_class_key __key;                     \
32                                                                 \
33         debug_check_no_locks_freed((void *)lock, sizeof(*lock));\
34         lockdep_init_map_type(&(lock)->dep_map, #lock, &__key, 0, \
35                               LD_WAIT_CONFIG, LD_WAIT_INV,      \
36                               LD_LOCK_PERCPU);                  \
37 } while (0)
38
39 #ifdef CONFIG_DEBUG_LOCK_ALLOC
40 static inline void local_lock_acquire(local_lock_t *l)
41 {
42         lock_map_acquire(&l->dep_map);
43         DEBUG_LOCKS_WARN_ON(l->owner);
44         l->owner = current;
45 }
46
47 static inline void local_lock_release(local_lock_t *l)
48 {
49         DEBUG_LOCKS_WARN_ON(l->owner != current);
50         l->owner = NULL;
51         lock_map_release(&l->dep_map);
52 }
53
54 #else /* CONFIG_DEBUG_LOCK_ALLOC */
55 static inline void local_lock_acquire(local_lock_t *l) { }
56 static inline void local_lock_release(local_lock_t *l) { }
57 #endif /* !CONFIG_DEBUG_LOCK_ALLOC */
58
59 #define __local_lock(lock)                                      \
60         do {                                                    \
61                 preempt_disable();                              \
62                 local_lock_acquire(this_cpu_ptr(lock));         \
63         } while (0)
64
65 #define __local_lock_irq(lock)                                  \
66         do {                                                    \
67                 local_irq_disable();                            \
68                 local_lock_acquire(this_cpu_ptr(lock));         \
69         } while (0)
70
71 #define __local_lock_irqsave(lock, flags)                       \
72         do {                                                    \
73                 local_irq_save(flags);                          \
74                 local_lock_acquire(this_cpu_ptr(lock));         \
75         } while (0)
76
77 #define __local_unlock(lock)                                    \
78         do {                                                    \
79                 local_lock_release(this_cpu_ptr(lock));         \
80                 preempt_enable();                               \
81         } while (0)
82
83 #define __local_unlock_irq(lock)                                \
84         do {                                                    \
85                 local_lock_release(this_cpu_ptr(lock));         \
86                 local_irq_enable();                             \
87         } while (0)
88
89 #define __local_unlock_irqrestore(lock, flags)                  \
90         do {                                                    \
91                 local_lock_release(this_cpu_ptr(lock));         \
92                 local_irq_restore(flags);                       \
93         } while (0)