Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1/*
  2 * Kernel module for testing static keys.
  3 *
  4 * Copyright 2015 Akamai Technologies Inc. All Rights Reserved
  5 *
  6 * Authors:
  7 *      Jason Baron       <jbaron@akamai.com>
  8 *
  9 * This software is licensed under the terms of the GNU General Public
 10 * License version 2, as published by the Free Software Foundation, and
 11 * may be copied, distributed, and modified under those terms.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 */
 18
 19#include <linux/module.h>
 20#include <linux/jump_label.h>
 21
 22/* old keys */
 23struct static_key old_true_key	= STATIC_KEY_INIT_TRUE;
 24struct static_key old_false_key	= STATIC_KEY_INIT_FALSE;
 25
 26/* new api */
 27DEFINE_STATIC_KEY_TRUE(true_key);
 28DEFINE_STATIC_KEY_FALSE(false_key);
 29
 30/* external */
 31extern struct static_key base_old_true_key;
 32extern struct static_key base_inv_old_true_key;
 33extern struct static_key base_old_false_key;
 34extern struct static_key base_inv_old_false_key;
 35
 36/* new api */
 37extern struct static_key_true base_true_key;
 38extern struct static_key_true base_inv_true_key;
 39extern struct static_key_false base_false_key;
 40extern struct static_key_false base_inv_false_key;
 41
 42
 43struct test_key {
 44	bool			init_state;
 45	struct static_key	*key;
 46	bool			(*test_key)(void);
 47};
 48
 49#define test_key_func(key, branch)	\
 50static bool key ## _ ## branch(void)	\
 51{					\
 52	return branch(&key);		\
 53}
 54
 55static void invert_key(struct static_key *key)
 56{
 57	if (static_key_enabled(key))
 58		static_key_disable(key);
 59	else
 60		static_key_enable(key);
 61}
 62
 63static void invert_keys(struct test_key *keys, int size)
 64{
 65	struct static_key *previous = NULL;
 66	int i;
 67
 68	for (i = 0; i < size; i++) {
 69		if (previous != keys[i].key) {
 70			invert_key(keys[i].key);
 71			previous = keys[i].key;
 72		}
 73	}
 74}
 75
 76static int verify_keys(struct test_key *keys, int size, bool invert)
 77{
 78	int i;
 79	bool ret, init;
 80
 81	for (i = 0; i < size; i++) {
 82		ret = static_key_enabled(keys[i].key);
 83		init = keys[i].init_state;
 84		if (ret != (invert ? !init : init))
 85			return -EINVAL;
 86		ret = keys[i].test_key();
 87		if (static_key_enabled(keys[i].key)) {
 88			if (!ret)
 89				return -EINVAL;
 90		} else {
 91			if (ret)
 92				return -EINVAL;
 93		}
 94	}
 95	return 0;
 96}
 97
 98test_key_func(old_true_key, static_key_true)
 99test_key_func(old_false_key, static_key_false)
100test_key_func(true_key, static_branch_likely)
101test_key_func(true_key, static_branch_unlikely)
102test_key_func(false_key, static_branch_likely)
103test_key_func(false_key, static_branch_unlikely)
104test_key_func(base_old_true_key, static_key_true)
105test_key_func(base_inv_old_true_key, static_key_true)
106test_key_func(base_old_false_key, static_key_false)
107test_key_func(base_inv_old_false_key, static_key_false)
108test_key_func(base_true_key, static_branch_likely)
109test_key_func(base_true_key, static_branch_unlikely)
110test_key_func(base_inv_true_key, static_branch_likely)
111test_key_func(base_inv_true_key, static_branch_unlikely)
112test_key_func(base_false_key, static_branch_likely)
113test_key_func(base_false_key, static_branch_unlikely)
114test_key_func(base_inv_false_key, static_branch_likely)
115test_key_func(base_inv_false_key, static_branch_unlikely)
116
117static int __init test_static_key_init(void)
118{
119	int ret;
120	int size;
121
122	struct test_key static_key_tests[] = {
123		/* internal keys - old keys */
124		{
125			.init_state	= true,
126			.key		= &old_true_key,
127			.test_key	= &old_true_key_static_key_true,
128		},
129		{
130			.init_state	= false,
131			.key		= &old_false_key,
132			.test_key	= &old_false_key_static_key_false,
133		},
134		/* internal keys - new keys */
135		{
136			.init_state	= true,
137			.key		= &true_key.key,
138			.test_key	= &true_key_static_branch_likely,
139		},
140		{
141			.init_state	= true,
142			.key		= &true_key.key,
143			.test_key	= &true_key_static_branch_unlikely,
144		},
145		{
146			.init_state	= false,
147			.key		= &false_key.key,
148			.test_key	= &false_key_static_branch_likely,
149		},
150		{
151			.init_state	= false,
152			.key		= &false_key.key,
153			.test_key	= &false_key_static_branch_unlikely,
154		},
155		/* external keys - old keys */
156		{
157			.init_state	= true,
158			.key		= &base_old_true_key,
159			.test_key	= &base_old_true_key_static_key_true,
160		},
161		{
162			.init_state	= false,
163			.key		= &base_inv_old_true_key,
164			.test_key	= &base_inv_old_true_key_static_key_true,
165		},
166		{
167			.init_state	= false,
168			.key		= &base_old_false_key,
169			.test_key	= &base_old_false_key_static_key_false,
170		},
171		{
172			.init_state	= true,
173			.key		= &base_inv_old_false_key,
174			.test_key	= &base_inv_old_false_key_static_key_false,
175		},
176		/* external keys - new keys */
177		{
178			.init_state	= true,
179			.key		= &base_true_key.key,
180			.test_key	= &base_true_key_static_branch_likely,
181		},
182		{
183			.init_state	= true,
184			.key		= &base_true_key.key,
185			.test_key	= &base_true_key_static_branch_unlikely,
186		},
187		{
188			.init_state	= false,
189			.key		= &base_inv_true_key.key,
190			.test_key	= &base_inv_true_key_static_branch_likely,
191		},
192		{
193			.init_state	= false,
194			.key		= &base_inv_true_key.key,
195			.test_key	= &base_inv_true_key_static_branch_unlikely,
196		},
197		{
198			.init_state	= false,
199			.key		= &base_false_key.key,
200			.test_key	= &base_false_key_static_branch_likely,
201		},
202		{
203			.init_state	= false,
204			.key		= &base_false_key.key,
205			.test_key	= &base_false_key_static_branch_unlikely,
206		},
207		{
208			.init_state	= true,
209			.key		= &base_inv_false_key.key,
210			.test_key	= &base_inv_false_key_static_branch_likely,
211		},
212		{
213			.init_state	= true,
214			.key		= &base_inv_false_key.key,
215			.test_key	= &base_inv_false_key_static_branch_unlikely,
216		},
217	};
218
219	size = ARRAY_SIZE(static_key_tests);
220
221	ret = verify_keys(static_key_tests, size, false);
222	if (ret)
223		goto out;
224
225	invert_keys(static_key_tests, size);
226	ret = verify_keys(static_key_tests, size, true);
227	if (ret)
228		goto out;
229
230	invert_keys(static_key_tests, size);
231	ret = verify_keys(static_key_tests, size, false);
232	if (ret)
233		goto out;
234	return 0;
235out:
236	return ret;
237}
238
239static void __exit test_static_key_exit(void)
240{
241}
242
243module_init(test_static_key_init);
244module_exit(test_static_key_exit);
245
246MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
247MODULE_LICENSE("GPL");