blob: dd698cbc846073d6483ba4073c001fc5d20b6e14 [file]
/*
* Copyright © 2025, Niklas Haas
* Copyright © 2018, VideoLAN and dav1d authors
* Copyright © 2018, Two Orioles, LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CHECKASM_INTERNAL_H
#define CHECKASM_INTERNAL_H
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "checkasm/attributes.h"
#include "checkasm/test.h"
#include "longjmp.h"
#include "stats.h"
#ifdef __GNUC__
#define COLD __attribute__((cold))
#else
#define COLD
#endif
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#ifdef _MSC_VER
#define NOINLINE __declspec(noinline)
#elif __has_attribute(noclone)
#define NOINLINE __attribute__((noinline, noclone))
#else
#define NOINLINE __attribute__((noinline))
#endif
#ifdef _MSC_VER
#define NORETURN __declspec(noreturn)
#else
#include <stdnoreturn.h>
#define NORETURN noreturn
#endif
#ifdef _MSC_VER
#define ALWAYS_INLINE __forceinline
#else
#define ALWAYS_INLINE inline __attribute__((always_inline))
#endif
#ifdef __GNUC__
#define THREAD_LOCAL __thread
#else
#define THREAD_LOCAL _Thread_local
#endif
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#ifdef _MSC_VER
#define PACKED(...) __pragma(pack(push, 1)) __VA_ARGS__ __pragma(pack(pop))
#else
#define PACKED(...) __VA_ARGS__ __attribute__((__packed__))
#endif
#if __has_attribute(fallthrough)
#define FALLTHROUGH __attribute__((fallthrough))
#else
#define FALLTHROUGH do {} while (0)
#endif
void checkasm_srand(unsigned seed);
/* Internal variant of checkasm_fail_func() that also jumps back to the signal
* handler */
NORETURN void checkasm_fail_abort(const char *msg, ...) CHECKASM_PRINTF(1, 2);
#define COLOR_DEFAULT -1
#define COLOR_RED 31
#define COLOR_GREEN 32
#define COLOR_YELLOW 33
#define COLOR_BLUE 34
#define COLOR_MAGENTA 35
#define COLOR_CYAN 36
#define COLOR_WHITE 37
/* Colored variant of fprintf for terminals that support it */
void checkasm_setup_fprintf(void);
void checkasm_fprintf(FILE *const f, const int color, const char *const fmt, ...)
CHECKASM_PRINTF(3, 4);
/* Light-weight helper for printing nested JSON objects */
typedef struct CheckasmJson {
FILE *file;
int level;
int nonempty;
} CheckasmJson;
void checkasm_json(CheckasmJson *json, const char *key, const char *fmt, ...)
CHECKASM_PRINTF(3, 4);
void checkasm_json_str(CheckasmJson *json, const char *key, const char *str);
void checkasm_json_push(CheckasmJson *json, const char *const key, char type);
void checkasm_json_pop(CheckasmJson *json, char type);
/* Platform specific signal handling */
void checkasm_set_signal_handlers(void);
const char *checkasm_get_last_signal_desc(void);
/* Set to 1 if the process should terminate. The current test will continue
* executing until the next report() call, then the process will exit. */
extern volatile sig_atomic_t checkasm_interrupted;
extern checkasm_jmp_buf checkasm_context;
/* Platform specific timing code */
extern CheckasmPerf checkasm_perf;
int checkasm_perf_init(void);
int checkasm_perf_init_linux(CheckasmPerf *perf);
int checkasm_perf_init_macos(CheckasmPerf *perf);
int checkasm_perf_init_arm(CheckasmPerf *perf);
int checkasm_perf_validate_start(const CheckasmPerf *perf);
int checkasm_perf_validate_start_stop(const CheckasmPerf *perf);
int checkasm_run_on_all_cores(void (*func)(void));
uint64_t checkasm_gettime_nsec(void);
uint64_t checkasm_gettime_nsec_diff(uint64_t t); /* subtracts t */
unsigned checkasm_seed(void);
void checkasm_noop(void *);
/* These functions update the measurements in `meas` directly; must be initialized */
void checkasm_measure_nop_cycles(CheckasmMeasurement *meas, uint64_t target_cycles);
void checkasm_measure_perf_scale(CheckasmMeasurement *meas); /* ns per cycle */
/* Miscellaneous helpers */
static inline int imax(const int a, const int b)
{
return a > b ? a : b;
}
static inline int imin(const int a, const int b)
{
return a < b ? a : b;
}
static inline void *checkasm_handle_oom(void *ptr)
{
if (!ptr) {
fprintf(stderr, "checkasm: out of memory\n");
exit(1);
}
return ptr;
}
/* Allocate a zero-initialized block, clean up and exit on failure */
static inline void *checkasm_mallocz(const size_t size)
{
return checkasm_handle_oom(calloc(1, size));
}
static inline char *checkasm_strdup(const char *str)
{
return checkasm_handle_oom(strdup(str));
}
char *checkasm_vasprintf(const char *fmt, va_list arg);
#endif /* CHECKASM_INTERNAL_H */