1
1
Static Keys
2
2
-----------
3
3
4
- By: Jason Baron <
[email protected] >
4
+ DEPRECATED API:
5
+
6
+ The use of 'struct static_key' directly, is now DEPRECATED. In addition
7
+ static_key_{true,false}() is also DEPRECATED. IE DO NOT use the following:
8
+
9
+ struct static_key false = STATIC_KEY_INIT_FALSE;
10
+ struct static_key true = STATIC_KEY_INIT_TRUE;
11
+ static_key_true()
12
+ static_key_false()
13
+
14
+ The updated API replacements are:
15
+
16
+ DEFINE_STATIC_KEY_TRUE(key);
17
+ DEFINE_STATIC_KEY_FALSE(key);
18
+ static_key_likely()
19
+ statick_key_unlikely()
5
20
6
21
0) Abstract
7
22
8
23
Static keys allows the inclusion of seldom used features in
9
24
performance-sensitive fast-path kernel code, via a GCC feature and a code
10
25
patching technique. A quick example:
11
26
12
- struct static_key key = STATIC_KEY_INIT_FALSE ;
27
+ DEFINE_STATIC_KEY_FALSE( key) ;
13
28
14
29
...
15
30
16
- if (static_key_false (&key))
31
+ if (static_branch_unlikely (&key))
17
32
do unlikely code
18
33
else
19
34
do likely code
20
35
21
36
...
22
- static_key_slow_inc( );
37
+ static_branch_enable(&key );
23
38
...
24
- static_key_slow_inc( );
39
+ static_branch_disable(&key );
25
40
...
26
41
27
- The static_key_false () branch will be generated into the code with as little
42
+ The static_branch_unlikely () branch will be generated into the code with as little
28
43
impact to the likely code path as possible.
29
44
30
45
@@ -56,7 +71,7 @@ the branch site to change the branch direction.
56
71
57
72
For example, if we have a simple branch that is disabled by default:
58
73
59
- if (static_key_false (&key))
74
+ if (static_branch_unlikely (&key))
60
75
printk("I am the true branch\n");
61
76
62
77
Thus, by default the 'printk' will not be emitted. And the code generated will
@@ -75,68 +90,55 @@ the basis for the static keys facility.
75
90
76
91
In order to make use of this optimization you must first define a key:
77
92
78
- struct static_key key;
79
-
80
- Which is initialized as:
81
-
82
- struct static_key key = STATIC_KEY_INIT_TRUE;
93
+ DEFINE_STATIC_KEY_TRUE(key);
83
94
84
95
or:
85
96
86
- struct static_key key = STATIC_KEY_INIT_FALSE;
97
+ DEFINE_STATIC_KEY_FALSE(key);
98
+
87
99
88
- If the key is not initialized, it is default false. The 'struct static_key',
89
- must be a 'global'. That is, it can't be allocated on the stack or dynamically
100
+ The key must be global, that is, it can't be allocated on the stack or dynamically
90
101
allocated at run-time.
91
102
92
103
The key is then used in code as:
93
104
94
- if (static_key_false (&key))
105
+ if (static_branch_unlikely (&key))
95
106
do unlikely code
96
107
else
97
108
do likely code
98
109
99
110
Or:
100
111
101
- if (static_key_true (&key))
112
+ if (static_branch_likely (&key))
102
113
do likely code
103
114
else
104
115
do unlikely code
105
116
106
- A key that is initialized via 'STATIC_KEY_INIT_FALSE', must be used in a
107
- 'static_key_false()' construct. Likewise, a key initialized via
108
- 'STATIC_KEY_INIT_TRUE' must be used in a 'static_key_true()' construct. A
109
- single key can be used in many branches, but all the branches must match the
110
- way that the key has been initialized.
117
+ Keys defined via DEFINE_STATIC_KEY_TRUE(), or DEFINE_STATIC_KEY_FALSE, may
118
+ be used in either static_branch_likely() or static_branch_unlikely()
119
+ statemnts.
111
120
112
- The branch (es) can then be switched via:
121
+ Branch (es) can be set true via:
113
122
114
- static_key_slow_inc(&key);
115
- ...
116
- static_key_slow_dec(&key);
123
+ static_branch_enable(&key);
117
124
118
- Thus, 'static_key_slow_inc()' means 'make the branch true', and
119
- 'static_key_slow_dec()' means 'make the branch false' with appropriate
120
- reference counting. For example, if the key is initialized true, a
121
- static_key_slow_dec(), will switch the branch to false. And a subsequent
122
- static_key_slow_inc(), will change the branch back to true. Likewise, if the
123
- key is initialized false, a 'static_key_slow_inc()', will change the branch to
124
- true. And then a 'static_key_slow_dec()', will again make the branch false.
125
+ or false via:
126
+
127
+ static_branch_disable(&key);
125
128
126
- An example usage in the kernel is the implementation of tracepoints :
129
+ The branch(es) can then be switched via reference counts :
127
130
128
- static inline void trace_##name(proto) \
129
- { \
130
- if (static_key_false(&__tracepoint_##name.key)) \
131
- __DO_TRACE(&__tracepoint_##name, \
132
- TP_PROTO(data_proto), \
133
- TP_ARGS(data_args), \
134
- TP_CONDITION(cond)); \
135
- }
131
+ static_branch_inc(&key);
132
+ ...
133
+ static_branch_dec(&key);
136
134
137
- Tracepoints are disabled by default, and can be placed in performance critical
138
- pieces of the kernel. Thus, by using a static key, the tracepoints can have
139
- absolutely minimal impact when not in use.
135
+ Thus, 'static_branch_inc()' means 'make the branch true', and
136
+ 'static_branch_dec()' means 'make the branch false' with appropriate
137
+ reference counting. For example, if the key is initialized true, a
138
+ static_branch_dec(), will switch the branch to false. And a subsequent
139
+ static_branch_inc(), will change the branch back to true. Likewise, if the
140
+ key is initialized false, a 'static_branch_inc()', will change the branch to
141
+ true. And then a 'static_branch_dec()', will again make the branch false.
140
142
141
143
142
144
4) Architecture level code patching interface, 'jump labels'
@@ -150,9 +152,12 @@ simply fall back to a traditional, load, test, and jump sequence.
150
152
151
153
* #define JUMP_LABEL_NOP_SIZE, see: arch/x86/include/asm/jump_label.h
152
154
153
- * __always_inline bool arch_static_branch(struct static_key *key), see:
155
+ * __always_inline bool arch_static_branch(struct static_key *key, bool branch ), see:
154
156
arch/x86/include/asm/jump_label.h
155
157
158
+ * __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch),
159
+ see: arch/x86/include/asm/jump_label.h
160
+
156
161
* void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type),
157
162
see: arch/x86/kernel/jump_label.c
158
163
@@ -173,7 +178,7 @@ SYSCALL_DEFINE0(getppid)
173
178
{
174
179
int pid;
175
180
176
- + if (static_key_false (&key))
181
+ + if (static_branch_unlikely (&key))
177
182
+ printk("I am the true branch\n");
178
183
179
184
rcu_read_lock();
0 commit comments