FFmpeg
Loading...
Searching...
No Matches
checkasm.h
Go to the documentation of this file.
1/*
2 * Copyright © 2025, Niklas Haas
3 * Copyright © 2018, VideoLAN and dav1d authors
4 * Copyright © 2018, Two Orioles, LLC
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @file checkasm.h
31 * @brief Main checkasm API for test suite configuration and execution
32 *
33 * This header provides the primary checkasm API for setting up and running
34 * assembly test suites, including configuration structures, test registration,
35 * and benchmark execution. It defines the main entry points and configuration
36 * options for checkasm-based test programs.
37 */
38
39#ifndef CHECKASM_CHECKASM_H
40#define CHECKASM_CHECKASM_H
41
42#include <stdint.h>
43
44#include "checkasm/attributes.h"
45
46/**
47 * @defgroup config User-provided Configuration
48 * @{
49 *
50 * User-provided preprocessor definitions for configuring the behavior of
51 * the checkasm header files. These macros should be defined before including
52 * checkasm.h, based on the availability of compiler features in the target
53 * project.
54 */
55
56/**
57 * @def CHECKASM_HAVE_GENERIC
58 * @brief Enable C11 _Generic support
59 *
60 * When enabled (defined to a nonzero value), checkasm uses C11's _Generic
61 * keyword to enable extra checks that rely on type information. This enables
62 * register width checking and floating point state checks on supported
63 * platforms. When disabled (defined to 0), these features are silently
64 * disabled.
65 *
66 * By default (when not defined), this is automatically enabled for C11 and
67 * later, and disabled for older C standards. Define this macro before
68 * including checkasm.h to explicitly control the behavior.
69 *
70 * @note This is not needed when compiling with `-std=c11` or later.
71 */
72#ifndef CHECKASM_HAVE_GENERIC
73 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
74 #define CHECKASM_HAVE_GENERIC 1
75 #else
76 #define CHECKASM_HAVE_GENERIC 0
77 #endif
78#endif
79
80/** @} */ /* end of config group */
81
82/**
83 * @brief Opaque type representing a set of CPU feature flags
84 *
85 * Bitfield type used to represent CPU capabilities and SIMD instruction set
86 * support. The specific bit values are defined by the implementation.
87 */
88typedef uint64_t CheckasmCpu;
89
90/**
91 * @brief Opaque type used to identify function implementations
92 *
93 * Used internally by checkasm to track and match different variants of
94 * functions being tested.
95 */
96typedef uintptr_t CheckasmKey;
97
98/**
99 * @brief Describes a CPU feature flag/capability
100 *
101 * Used to define the CPU features that the test suite should test against.
102 * Tests will be run incrementally for each CPU feature set, with each test
103 * inheriting flags from previously tested CPUs.
104 */
105typedef struct CheckasmCpuInfo {
106 const char *name; /**< Human-readable name (e.g., "SSE2", "AVX2") */
107 const char *suffix; /**< Short suffix for function names (e.g., "sse2", "avx2") */
108 CheckasmCpu flag; /**< Bitmask flag value for this CPU feature */
109
110 /** @brief Bitmask of prior CPU flags to disable again
111 *
112 * Any CPU flags in this mask will be removed from the active CPU flag set
113 * when testing this and any subsequent CPU configurations. This is
114 * effectively the opposite of `flag`.
115 *
116 * @since v1.3.0
117 */
120
121/**
122 * @brief Describes a single test function
123 *
124 * Represents one test function that will be invoked by the test suite.
125 * Each test function typically tests a specific component or subsystem.
126 */
127typedef struct CheckasmTest {
128 const char *name; /**< Name of the test (used for filtering and reporting) */
129 void (*func)(void); /**< Test function to invoke */
130
131 /**
132 * @brief Optional initialization function
133 *
134 * These functions, if set, are invoked before testing any CPU flags
135 * and after testing all CPU flags, respectively.
136 *
137 * @note If CheckasmConfig.repeat > 1, they will be called for every
138 * iteration.
139 *
140 * @warning These are called even when running checkasm_list_functions().
141 */
142 void (*init)(void);
143 void (*uninit)(void);
145
146/**
147 * @brief Output format for benchmark results
148 *
149 * Specifies how benchmark results should be formatted.
150 *
151 * @note In all cases, output is written to `stdout` by default.
152 */
153typedef enum CheckasmFormat {
154 CHECKASM_FORMAT_PRETTY, /**< Pretty-printed (colored) text output (default) */
155 CHECKASM_FORMAT_CSV, /**< Comma-separated values with optional header */
156 CHECKASM_FORMAT_TSV, /**< Tab-separated values with optional header */
157 CHECKASM_FORMAT_JSON, /**< JSON structured output with all measurement data */
158 CHECKASM_FORMAT_HTML, /**< Interactive HTML report for web viewing */
160
161/**
162 * @brief Configuration structure for the checkasm test suite
163 *
164 * This structure contains all configuration options for running checkasm tests,
165 * including test selection, CPU feature flags, benchmarking options, and output
166 * formatting. Initialize this structure with your project's tests and CPU flags
167 * before calling checkasm_main() or checkasm_run().
168 *
169 * @code
170 * CheckasmConfig config = {
171 * .cpu_flags = my_cpu_flags,
172 * .tests = my_tests,
173 * .cpu = my_get_cpu_flags(),
174 * .set_cpu_flags = my_set_cpu_flags,
175 * };
176 *
177 * return checkasm_main(&config, argc, argv);
178 * @endcode
179 *
180 * @see checkasm_main(), checkasm_run()
181 */
182typedef struct CheckasmConfig {
183 /**
184 * @brief List of CPU flags understood by the implementation
185 *
186 * Array of CPU features that will be tested in incremental order,
187 * terminated by an entry with `CheckasmCpuInfo.flag == 0` (i.e. `{0}`).
188 *
189 * Each test run inherits any active flags from previously tested CPUs.
190 * This allows testing progressively more advanced instruction sets.
191 */
193
194 /**
195 * @brief Array of test functions to execute
196 *
197 * Array of test functions to execute, terminated by an entry with
198 * `CheckasmTest.func == NULL` (i.e. `{0}`.
199 */
201
202 /**
203 * @brief Detected CPU flags for the current system
204 *
205 * Set this to the detected CPU capabilities of the system. Any extra flags
206 * not included in cpu_flags will also be transparently included in
207 * checkasm_get_cpu_flags(), and can be used to signal flags that should
208 * be assumed to always be enabled (e.g., CPU_FLAG_FAST_* modifiers).
209 */
211
212 /**
213 * @brief Callback invoked when active CPU flags change
214 *
215 * If provided, this function will be called whenever the active set of
216 * CPU flags changes, with the new set of flags as argument. This includes
217 * once at the start of the program with the baseline set of flags.
218 *
219 * Use this to update global function pointers, internal static variables,
220 * or dispatch tables.
221 */
222 void (*set_cpu_flags)(CheckasmCpu new_flags);
223
224 /**
225 * @brief Pattern for filtering which tests to run
226 *
227 * Shell-style wildcard pattern (e.g., "video_*") to select tests.
228 * NULL means run all tests.
229 */
230 const char *test_pattern;
231
232 /**
233 * @brief Pattern for filtering which functions within tests to run
234 *
235 * Shell-style wildcard pattern to select specific functions. Matched
236 * against the names passed to checkasm_check_func(). NULL means run all
237 * functions.
238 */
239 const char *function_pattern;
240
241 /**
242 * @brief Enable benchmarking
243 *
244 * When nonzero, enables performance benchmarking of tested functions.
245 * Set to 1 to enable with default settings.
246 */
247 int bench;
248
249 /**
250 * @brief Target benchmark duration in microseconds
251 *
252 * Target time (in µs) to spend benchmarking each function.
253 * Defaults to 1000 µs if left unset when bench is enabled.
254 *
255 * @note Very slow functions may execute for a longer duration to ensure
256 * enough samples are collected for accurate measurement.
257 */
258 unsigned bench_usec;
259
260 /** @brief Output format for benchmark results */
262
263 /**
264 * @brief Enable verbose output
265 *
266 * When nonzero, prints detailed timing information, failure diagnostics,
267 * and extra terminal output (including table headers and extra information
268 * about the active configuration).
269 */
271
272 /** @brief Enable using the seed value
273 *
274 * If nonzero, the value in the seed field will be used even if it may be
275 * zero.
276 */
278
279 /**
280 * @brief Random number generator seed
281 *
282 * If nonzero or if seed_set is nonzero, use this seed for deterministic
283 * random number generation. If zero and seed_set is zero, a seed will
284 * be chosen based on the current time.
285 */
286 unsigned seed;
287
288 /**
289 * @brief Number of times to repeat tests
290 *
291 * Repeat the test (and benchmark, if enabled) this many times using
292 * successive seeds. Setting to -1 effectively tests every possible seed
293 * (useful for exhaustive testing).
294 */
295 unsigned repeat;
296
297 /** @brief Enable process pinning via cpu_affinity
298 *
299 * If nonzero, the test process will be pinned to the CPU core specified
300 * in cpu_affinity.
301 *
302 * @warning This will override the CPU affinity of the calling process, and
303 * will persist even after checkasm_run() returns.
304 */
306
307 /**
308 * @brief CPU core ID for process pinning
309 *
310 * If cpu_affinity_set is nonzero, pin the test process to this CPU core.
311 */
312 unsigned cpu_affinity;
314
315/**
316 * @brief Get the current active set of CPU flags
317 *
318 * Returns the currently active (masked) set of CPU flags. During test execution,
319 * this reflects which CPU features are currently being tested. May be called
320 * from within test functions to choose an implementation to test.
321 *
322 * @return Current CPU feature flags as a bitmask
323 *
324 * @note The returned value changes as checkasm iterates through different CPU
325 * feature sets during testing.
326 */
328
329/**
330 * @brief Get the CPU flag currently being tested
331 *
332 * Returns the CheckasmCpuInfo structure for the CPU flag currently being
333 * tested, or NULL if testing the baseline configuration with no additional
334 * CPU flags.
335 *
336 * @return Currently active CPU flag info, or NULL
337 *
338 * @note Unlike checkasm_get_cpu_flags(), this only reflects the currently
339 * running test, and does not include any information about previously
340 * tested CPU flags.
341 *
342 * @since v1.2.0
343 */
345
346/**
347 * @brief Get the suffix for the current CPU flag, or "c" if none
348 * @since v1.2.0
349 */
350static inline const char *checkasm_get_cpu_suffix(void)
351{
353 return info ? info->suffix : "c";
354}
355
356/**
357 * @brief Print available CPU flags to stdout.
358 *
359 * Prints a list of all CPU flags/features that are available for testing
360 * based on the configuration, as well as CPU flags which are defined but
361 * unsupported on the system.
362 *
363 * @param[in] config Configuration containing CPU flag definitions
364 */
366
367/**
368 * @brief Print available tests
369 *
370 * Prints a list of all test functions registered in the configuration.
371 * Useful for discovering what tests are available and for use with
372 * test pattern filtering.
373 *
374 * @param[in] config Configuration containing test definitions
375 */
377
378/**
379 * @brief Print available functions within tests
380 *
381 * Prints a detailed list of all functions being tested across all registered
382 * tests. Useful for discovering what can be filtered with function patterns.
383 *
384 * @param[in] config Configuration containing test definitions
385 *
386 * @note This requires executing all tests to gather information about the
387 * available functions. During this process, checkasm_check_func() always
388 * returns 0 to skip the actual testing. However, any side effects from
389 * test functions will still occur, unless properly guarded. In
390 * particular, CheckasmTest.init() and CheckasmTest.uninit() will still
391 * be executed.
392 */
394
395/**
396 * @brief Run all tests and benchmarks matching the specified patterns
397 *
398 * Executes the checkasm test suite according to the configuration. Tests
399 * and functions are filtered according to test_pattern and function_pattern
400 * if specified. Benchmarks are run if bench is enabled.
401 *
402 * @param[in] config Configuration structure with all test parameters
403 * @return 0 on success (all tests passed), negative error code on failure
404 *
405 * @note This is the lower-level entry point. Most users should use
406 * checkasm_main() instead, which handles argument parsing.
407 *
408 * @warning This function may override the processor state in subtle ways,
409 * including enabling high-precision performance timers, installing
410 * signal handlers and configuring the terminal output.
411 *
412 * @see checkasm_main()
413 */
414CHECKASM_API int checkasm_run(const CheckasmConfig *config);
415
416/**
417 * @brief Main entry point for checkasm test programs
418 *
419 * Convenience wrapper around checkasm_run() that parses command-line arguments
420 * and updates the config accordingly. This is the recommended entry point for
421 * most checkasm test programs. Call this from your main() function.
422 *
423 * Before calling this function, initialize config with the minimum set of
424 * project-specific fields:
425 * - config.cpu_flags: Array of CPU features to test
426 * - config.tests: Array of test functions
427 * - config.cpu: Detected CPU capabilities
428 *
429 * Command-line arguments like --bench, --test, --function, --seed, etc. are
430 * automatically parsed and applied to the config.
431 *
432 * @param[in,out] config Configuration structure (will be modified by argument parsing)
433 * @param[in] argc Argument count from main()
434 * @param[in] argv Argument vector from main()
435 * @return 0 on success, non-zero on failure (suitable for return from main())
436 *
437 * @code
438 * int main(int argc, const char *argv[]) {
439 * CheckasmConfig config = {
440 * .cpu_flags = my_cpu_flags,
441 * .tests = my_tests,
442 * .cpu = my_get_cpu_flags(),
443 * .set_cpu_flags = my_set_cpu_flags,
444 * };
445 * return checkasm_main(&config, argc, argv);
446 * }
447 * @endcode
448 *
449 * @see checkasm_run()
450 */
451CHECKASM_API int checkasm_main(CheckasmConfig *config, int argc, const char *argv[]);
452
453#endif /* CHECKASM_CHECKASM_H */
uint64_t CheckasmCpu
Opaque type representing a set of CPU feature flags.
Definition checkasm.h:88
CHECKASM_API void checkasm_list_tests(const CheckasmConfig *config)
Print available tests.
Definition checkasm.c:705
uintptr_t CheckasmKey
Opaque type used to identify function implementations.
Definition checkasm.h:96
CHECKASM_API void checkasm_list_functions(const CheckasmConfig *config)
Print available functions within tests.
Definition checkasm.c:743
static const char * checkasm_get_cpu_suffix(void)
Get the suffix for the current CPU flag, or "c" if none.
Definition checkasm.h:350
CheckasmFormat
Output format for benchmark results.
Definition checkasm.h:153
@ CHECKASM_FORMAT_PRETTY
Pretty-printed (colored) text output (default)
Definition checkasm.h:154
@ CHECKASM_FORMAT_TSV
Tab-separated values with optional header.
Definition checkasm.h:156
@ CHECKASM_FORMAT_HTML
Interactive HTML report for web viewing.
Definition checkasm.h:158
@ CHECKASM_FORMAT_CSV
Comma-separated values with optional header.
Definition checkasm.h:155
@ CHECKASM_FORMAT_JSON
JSON structured output with all measurement data.
Definition checkasm.h:157
CHECKASM_API int checkasm_run(const CheckasmConfig *config)
Run all tests and benchmarks matching the specified patterns.
Definition checkasm.c:857
CHECKASM_API void checkasm_list_cpu_flags(const CheckasmConfig *config)
Print available CPU flags to stdout.
Definition checkasm.c:692
CHECKASM_API const CheckasmCpuInfo * checkasm_get_cpu_info(void)
Get the CPU flag currently being tested.
Definition checkasm.c:127
CHECKASM_API CheckasmCpu checkasm_get_cpu_flags(void)
Get the current active set of CPU flags.
Definition checkasm.c:122
CHECKASM_API int checkasm_main(CheckasmConfig *config, int argc, const char *argv[])
Main entry point for checkasm test programs.
Definition checkasm.c:1209
Configuration structure for the checkasm test suite.
Definition checkasm.h:182
int cpu_affinity_set
Enable process pinning via cpu_affinity.
Definition checkasm.h:305
int verbose
Enable verbose output.
Definition checkasm.h:270
const char * test_pattern
Pattern for filtering which tests to run.
Definition checkasm.h:230
unsigned cpu_affinity
CPU core ID for process pinning.
Definition checkasm.h:312
unsigned repeat
Number of times to repeat tests.
Definition checkasm.h:295
unsigned bench_usec
Target benchmark duration in microseconds.
Definition checkasm.h:258
CheckasmFormat format
Output format for benchmark results.
Definition checkasm.h:261
int bench
Enable benchmarking.
Definition checkasm.h:247
void(* set_cpu_flags)(CheckasmCpu new_flags)
Callback invoked when active CPU flags change.
Definition checkasm.h:222
int seed_set
Enable using the seed value.
Definition checkasm.h:277
const CheckasmCpuInfo * cpu_flags
List of CPU flags understood by the implementation.
Definition checkasm.h:192
const char * function_pattern
Pattern for filtering which functions within tests to run.
Definition checkasm.h:239
unsigned seed
Random number generator seed.
Definition checkasm.h:286
CheckasmCpu cpu
Detected CPU flags for the current system.
Definition checkasm.h:210
const CheckasmTest * tests
Array of test functions to execute.
Definition checkasm.h:200
Describes a CPU feature flag/capability.
Definition checkasm.h:105
CheckasmCpu mask
Bitmask of prior CPU flags to disable again.
Definition checkasm.h:118
CheckasmCpu flag
Bitmask flag value for this CPU feature.
Definition checkasm.h:108
const char * suffix
Short suffix for function names (e.g., "sse2", "avx2")
Definition checkasm.h:107
const char * name
Human-readable name (e.g., "SSE2", "AVX2")
Definition checkasm.h:106
Describes a single test function.
Definition checkasm.h:127
void(* func)(void)
Test function to invoke.
Definition checkasm.h:129
const char * name
Name of the test (used for filtering and reporting)
Definition checkasm.h:128
void(* uninit)(void)
Definition checkasm.h:143
void(* init)(void)
Optional initialization function.
Definition checkasm.h:142
Platform and compiler attribute macros.
#define CHECKASM_API
Symbol visibility attribute for public API functions.
Definition attributes.h:90