Loading...
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
9typedef 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 }
22#else
23# define LL_DEP_MAP_INIT(lockname)
24#endif
25
26#define INIT_LOCAL_LOCK(lockname) { LL_DEP_MAP_INIT(lockname) }
27
28#define __local_lock_init(lock) \
29do { \
30 static struct lock_class_key __key; \
31 \
32 debug_check_no_locks_freed((void *)lock, sizeof(*lock));\
33 lockdep_init_map_wait(&(lock)->dep_map, #lock, &__key, 0, LD_WAIT_CONFIG);\
34} while (0)
35
36#ifdef CONFIG_DEBUG_LOCK_ALLOC
37static inline void local_lock_acquire(local_lock_t *l)
38{
39 lock_map_acquire(&l->dep_map);
40 DEBUG_LOCKS_WARN_ON(l->owner);
41 l->owner = current;
42}
43
44static inline void local_lock_release(local_lock_t *l)
45{
46 DEBUG_LOCKS_WARN_ON(l->owner != current);
47 l->owner = NULL;
48 lock_map_release(&l->dep_map);
49}
50
51#else /* CONFIG_DEBUG_LOCK_ALLOC */
52static inline void local_lock_acquire(local_lock_t *l) { }
53static inline void local_lock_release(local_lock_t *l) { }
54#endif /* !CONFIG_DEBUG_LOCK_ALLOC */
55
56#define __local_lock(lock) \
57 do { \
58 preempt_disable(); \
59 local_lock_acquire(this_cpu_ptr(lock)); \
60 } while (0)
61
62#define __local_lock_irq(lock) \
63 do { \
64 local_irq_disable(); \
65 local_lock_acquire(this_cpu_ptr(lock)); \
66 } while (0)
67
68#define __local_lock_irqsave(lock, flags) \
69 do { \
70 local_irq_save(flags); \
71 local_lock_acquire(this_cpu_ptr(lock)); \
72 } while (0)
73
74#define __local_unlock(lock) \
75 do { \
76 local_lock_release(this_cpu_ptr(lock)); \
77 preempt_enable(); \
78 } while (0)
79
80#define __local_unlock_irq(lock) \
81 do { \
82 local_lock_release(this_cpu_ptr(lock)); \
83 local_irq_enable(); \
84 } while (0)
85
86#define __local_unlock_irqrestore(lock, flags) \
87 do { \
88 local_lock_release(this_cpu_ptr(lock)); \
89 local_irq_restore(flags); \
90 } while (0)
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
11typedef 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
27static 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
34static 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
41static 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)
47static inline void local_lock_acquire(local_lock_t *l) { }
48static inline void local_lock_release(local_lock_t *l) { }
49static 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) \
55do { \
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 */
107typedef 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 */