26# define SERENE_DEBUG 0
37# include <emmintrin.h>
43#define UNUSED(x) (void)(x)
51#define PANIC(msg) srn_panic(msg, __FILE__, __LINE__, __func__)
52#define TODO(msg) PANIC(msg)
53#define PANIC_WITH_CTX(ctx, msg) \
54 srn_context_release(ctx); \
57#define PANIC_IF(cond, msg) \
64#define PANIC_IF_NULL(ptr) PANIC_IF((ptr) == nullptr, "Null pointer")
66#define SNPRINTF(buf, s, f, ...) \
68 int i = snprintf(buf, (s) + 1, f, __VA_ARGS__); \
70 PANIC("[snprintf] A negative return value"); \
72 if (i >= (int)(s)) { \
73 PANIC("[snprintf] Written bytes are more than expected"); \
77#define SHOULD_NOT_HAPPEN PANIC("This should not happen")
78#define PANIC_ON_ERR(interr) \
99#if defined(__clang__) || defined(__GNUC__)
100# define SRN_ATTR_COLD [[gnu::cold]]
101# define SRN_ATTR_FMT(a, b) [[gnu::format(__printf__, a, b)]]
103# define SRN_ATTR_COLD
104# define SRN_ATTR_FMT(a, b)
111# define SRN_DBG_OUT stdout
113SRN_ATTR_COLD static inline void srn_dbg_prefix(FILE *out,
const char *prefix,
117 int res = fprintf(out,
"[%s]%s:%d:(%s): ", prefix ==
nullptr ?
"SRN" : prefix,
124SRN_ATTR_COLD static inline void srn_dbg_vlog(FILE *out,
const char *prefix,
126 const char *func,
const char *
fmt,
129 srn_dbg_prefix(out, prefix,
file,
line, func);
135 FILE *out, const
char *prefix, const
char *
file,
int line, const
char *func,
136 const
char *
fmt, ...) {
140 srn_dbg_vlog(out, prefix,
file,
line, func,
fmt, ap);
145srn_dbg_hexdump_here(FILE *out,
const char *
file,
int line,
const char *func,
146 const void *data,
size_t len) {
147 const unsigned char *p = (
const unsigned char *)data;
148 srn_dbg_prefix(out,
"Hexdump",
file,
line, func);
149 UNUSED(fprintf(out,
"hexdump %zu bytes\n", len));
150 for (
size_t i = 0; i < len; i += 16) {
151 UNUSED(fprintf(out,
" %08zx ", i));
152 for (
size_t j = 0; j < 16; ++j) {
154 UNUSED(fprintf(out,
"%02x ", p[i + j]));
161 for (
size_t j = 0; j < 16 && i + j < len; ++j) {
162 unsigned char c = p[i + j];
163 UNUSED(fputc((c >= 32 && c < 127) ? c :
'.', out));
169# define DBG(PREFIX, FMT, ...) \
170 srn_dbg_log(SRN_DBG_OUT, PREFIX, __FILE__, __LINE__, __func__, \
171 FMT __VA_OPT__(, ) __VA_ARGS__)
172# define DBG_HEX(PTR, LEN) \
173 srn_dbg_hexdump_here(SRN_DBG_OUT, __FILE__, __LINE__, __func__, (PTR), \
180# define DBG_HEX(...) \
183# define DBG_ASSERT(x) \
193#if defined(__clang__) || defined(__GNUC__)
194 return (uint32_t)__builtin_popcount(x);
196 x = x - ((x >> 1) & 0x55555555u);
197 x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u);
198 return (((x + (x >> 4)) & 0x0F0F0F0Fu) * 0x01010101u) >> 24;
203#if defined(__GNUC__) || defined(__clang__)
204 return (uint64_t)__builtin_popcountll(x);
222#if defined(_M_IX86) || defined(__I86__) || defined(i686) || \
223 defined(__i686) || defined(__i686__) || defined(i586) || \
224 defined(__i586) || defined(__i586__) || defined(i486) || \
225 defined(__i486) || defined(__i486__) || defined(i386) || \
226 defined(__i386) || defined(__i386__) || defined(_X86_) || \
227 defined(__X86__) || defined(__THW_INTEL__)
228# if defined(__SSE2__)
230# elif defined(_MSC_VER)
233 __asm__ __volatile__(
"pause");
235#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || \
236 defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
237# if defined(__SSE2__)
240#elif defined(__aarch64__) || defined(_M_ARM64)
241# if defined(_MSC_VER)
242 __isb(_ARM64_BARRIER_SY);
244 __asm__ __volatile__(
"isb\n");
246#elif defined(__ARM_ARCH) || defined(_M_ARM) || defined(__arm__) || \
247 defined(__thumb__) || defined(__TARGET_ARCH_ARM) || defined(_ARM)
248# if defined(_MSC_VER)
251 __asm__ __volatile__(
"yield");
253#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || \
254 defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC) || \
256 __asm__ __volatile__(
"or 27,27,27" :::
"memory");
257#elif defined(__riscv) || defined(__riscv__)
258# if defined(__riscv_pause)
259 __builtin_riscv_pause();
261 __asm__ __volatile__(
"nop");
263#elif defined(__loongarch32) || defined(__loongarch64)
264 __asm__ __volatile__(
"nop");
265#elif defined(__wasm__)
266 __asm__ __volatile__(
"nop");
278 atomic_flag_clear_explicit(&lock->
flag, memory_order_release);
282 lock->
flag = (atomic_flag)ATOMIC_FLAG_INIT;
287 while (atomic_flag_test_and_set_explicit(&lock->
flag, memory_order_acquire)) {
static int const char * fmt
Main memory manager structure that will own all the allocated blocks and data.
static void srn_spinlock_lock(srn_spinlock_t *lock)
#define SRN_ATTR_FMT(a, b)
char * srn_copy_bytes(srn_context_t *ctx, const char *src, size_t len, size_t alignment)
#define SHOULD_NOT_HAPPEN
static void srn_spinlock_unlock(srn_spinlock_t *lock)
static uint32_t srn_popcnt32(uint32_t x)
static void srn_spinlock_init(srn_spinlock_t *lock)
static uint64_t srn_popcnt64(uint64_t x)
static void cpu_relax(void)
A portable way to use pasue instructions.
char * srn_dup_str(srn_mm_t *mm, const char *s)
Copy a null terminated C string into a fresh allocation made through mm.
void srn_panic(const char *msg, const char *file, size_t line, const char *fn)
TODO(lxsameer): unwind the stack.
#define PANIC_ON_ERR(interr)