Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
utils.h File Reference
#include <limits.h>
#include <stdarg.h>
#include <stdatomic.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
Include dependency graph for utils.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  srn_spinlock_t

Macros

#define SERENE_DEBUG   0
#define UNUSED(x)
#define PANIC(msg)
#define TODO(msg)
#define PANIC_WITH_CTX(ctx, msg)
#define PANIC_IF(cond, msg)
#define PANIC_IF_NULL(ptr)
#define RETURN_IF_NULL(ptr)
#define SNPRINTF(buf, s, f, ...)
#define SHOULD_NOT_HAPPEN   PANIC("This should not happen")
#define PANIC_ON_ERR(interr)
#define SRN_ATTR_COLD
#define SRN_ATTR_FMT(a, b)
#define DBG(...)
#define DBG_HEX(...)
#define DBG_ASSERT(x)
#define SRN_NS_PER_SEC   1000000000ULL
 nanoseconds in one second
#define SRN_NS_PER_MS   1000000ULL
 nanoseconds in one millisecond
#define TYPE_BITS(T)
#define MAX_POW2_EXP_FOR_UNSIGNED(T)

Typedefs

typedef struct srn_spinlock_t srn_spinlock_t

Functions

void srn_panic (const char *msg, const char *file, size_t line, const char *fn)
 TODO(lxsameer): unwind the stack.
static uint32_t srn_popcnt32 (uint32_t x)
static uint64_t srn_popcnt64 (uint64_t x)
static void cpu_relax (void)
 A portable way to use pasue instructions.
static void srn_spinlock_unlock (srn_spinlock_t *lock)
static void srn_spinlock_init (srn_spinlock_t *lock)
static void srn_spinlock_lock (srn_spinlock_t *lock)
char * srn_copy_bytes (const srn_context_t *ctx, const char *src, size_t len, size_t alignment)
char * srn_dup_str (srn_mm_t *mm, const char *s)
 Copy a null terminated C string into a fresh allocation made through mm.
uint64_t srn_now_ns (void)
 The current time on the monotonic clock, in nanoseconds.

Macro Definition Documentation

◆ DBG

#define DBG ( ...)
Value:
do { \
} while (0)

Definition at line 179 of file utils.h.

179# define DBG(...) \
180 do { \
181 } while (0)

◆ DBG_ASSERT

#define DBG_ASSERT ( x)
Value:
do { \
(void)sizeof(x); \
} while (0)

Definition at line 185 of file utils.h.

185# define DBG_ASSERT(x) \
186 do { \
187 (void)sizeof(x); \
188 } while (0)

◆ DBG_HEX

#define DBG_HEX ( ...)
Value:
do { \
} while (0)

Definition at line 182 of file utils.h.

182# define DBG_HEX(...) \
183 do { \
184 } while (0)

◆ MAX_POW2_EXP_FOR_UNSIGNED

#define MAX_POW2_EXP_FOR_UNSIGNED ( T)
Value:
(TYPE_BITS(T) - 1)
#define TYPE_BITS(T)
Definition utils.h:319

Definition at line 320 of file utils.h.

◆ PANIC

#define PANIC ( msg)
Value:
srn_panic(msg, __FILE__, __LINE__, __func__)
void srn_panic(const char *msg, const char *file, size_t line, const char *fn)
TODO(lxsameer): unwind the stack.
Definition utils.c:31

Definition at line 53 of file utils.h.

◆ PANIC_IF

#define PANIC_IF ( cond,
msg )
Value:
do { \
if (cond) { \
PANIC(msg); \
} \
} while (0)

Definition at line 59 of file utils.h.

59#define PANIC_IF(cond, msg) \
60 do { \
61 if (cond) { \
62 PANIC(msg); \
63 } \
64 } while (0)

◆ PANIC_IF_NULL

#define PANIC_IF_NULL ( ptr)
Value:
PANIC_IF((ptr) == nullptr, "Null pointer")
#define PANIC_IF(cond, msg)
Definition utils.h:59

Definition at line 66 of file utils.h.

◆ PANIC_ON_ERR

#define PANIC_ON_ERR ( interr)
Value:
if ((interr) < 0) { \
}
#define SHOULD_NOT_HAPPEN
Definition utils.h:83

Definition at line 84 of file utils.h.

84#define PANIC_ON_ERR(interr) \
85 if ((interr) < 0) { \
86 SHOULD_NOT_HAPPEN; \
87 }

◆ PANIC_WITH_CTX

#define PANIC_WITH_CTX ( ctx,
msg )
Value:
PANIC(msg)
int srn_context_release(srn_context_t *ctx)
Definition context.c:64

Definition at line 55 of file utils.h.

55#define PANIC_WITH_CTX(ctx, msg) \
56 srn_context_release(ctx); \
57 PANIC(msg)

◆ RETURN_IF_NULL

#define RETURN_IF_NULL ( ptr)
Value:
if ((ptr) == nullptr) { \
return; \
}

Definition at line 67 of file utils.h.

67#define RETURN_IF_NULL(ptr) \
68 if ((ptr) == nullptr) { \
69 return; \
70 }

◆ SERENE_DEBUG

#define SERENE_DEBUG   0

Definition at line 32 of file utils.h.

◆ SHOULD_NOT_HAPPEN

#define SHOULD_NOT_HAPPEN   PANIC("This should not happen")

Definition at line 83 of file utils.h.

◆ SNPRINTF

#define SNPRINTF ( buf,
s,
f,
... )
Value:
do { \
int i = snprintf(buf, (s) + 1, f, __VA_ARGS__); \
if (i < 0) { \
PANIC("[snprintf] A negative return value"); \
} \
if (i >= (int)(s)) { \
PANIC("[snprintf] Written bytes are more than expected"); \
} \
} while (0)

Definition at line 72 of file utils.h.

72#define SNPRINTF(buf, s, f, ...) \
73 do { \
74 int i = snprintf(buf, (s) + 1, f, __VA_ARGS__); \
75 if (i < 0) { \
76 PANIC("[snprintf] A negative return value"); \
77 } \
78 if (i >= (int)(s)) { \
79 PANIC("[snprintf] Written bytes are more than expected"); \
80 } \
81 } while (0)

◆ SRN_ATTR_COLD

#define SRN_ATTR_COLD

Definition at line 109 of file utils.h.

◆ SRN_ATTR_FMT

#define SRN_ATTR_FMT ( a,
b )

Definition at line 110 of file utils.h.

◆ SRN_NS_PER_MS

#define SRN_NS_PER_MS   1000000ULL

nanoseconds in one millisecond

Definition at line 308 of file utils.h.

◆ SRN_NS_PER_SEC

#define SRN_NS_PER_SEC   1000000000ULL

nanoseconds in one second

Definition at line 306 of file utils.h.

◆ TODO

#define TODO ( msg)
Value:
PANIC(msg)
#define PANIC(msg)
Definition utils.h:53

Definition at line 54 of file utils.h.

◆ TYPE_BITS

#define TYPE_BITS ( T)
Value:
(sizeof(T) * CHAR_BIT)

Definition at line 319 of file utils.h.

◆ UNUSED

#define UNUSED ( x)
Value:
(void)(x)

Definition at line 45 of file utils.h.

Typedef Documentation

◆ srn_spinlock_t

typedef struct srn_spinlock_t srn_spinlock_t

Function Documentation

◆ cpu_relax()

void cpu_relax ( void )
inlinestatic

A portable way to use pasue instructions.

The long list of preprocessors is there thanks to: https://github.com/goodcleanfun/cpu_relax

Definition at line 223 of file utils.h.

223 {
224#if defined(_M_IX86) || defined(__I86__) || defined(i686) || defined(__i686) || \
225 defined(__i686__) || defined(i586) || defined(__i586) || defined(__i586__) || defined(i486) || \
226 defined(__i486) || defined(__i486__) || defined(i386) || defined(__i386) || defined(__i386__) || \
227 defined(_X86_) || defined(__X86__) || defined(__THW_INTEL__)
228# if defined(__SSE2__)
229 _mm_pause();
230# elif defined(_MSC_VER)
231 __asm pause;
232# else
233 __asm__ __volatile__("pause");
234# endif
235#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
236 defined(_M_X64) || defined(_M_AMD64)
237# if defined(__SSE2__)
238 _mm_pause();
239# endif
240#elif defined(__aarch64__) || defined(_M_ARM64)
241# if defined(_MSC_VER)
242 __isb(_ARM64_BARRIER_SY);
243# else
244 __asm__ __volatile__("isb\n");
245# endif
246#elif defined(__ARM_ARCH) || defined(_M_ARM) || defined(__arm__) || defined(__thumb__) || \
247 defined(__TARGET_ARCH_ARM) || defined(_ARM)
248# if defined(_MSC_VER)
249 __yield();
250# else
251 __asm__ __volatile__("yield");
252# endif
253#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || \
254 defined(__PPC__) || defined(_ARCH_PPC) || defined(__ppc)
255 __asm__ __volatile__("or 27,27,27" ::: "memory");
256#elif defined(__riscv) || defined(__riscv__)
257# if defined(__riscv_pause)
258 __builtin_riscv_pause();
259# else
260 __asm__ __volatile__("nop");
261# endif
262#elif defined(__loongarch32) || defined(__loongarch64)
263 __asm__ __volatile__("nop");
264#elif defined(__wasm__)
265 __asm__ __volatile__("nop");
266#endif
267}
Here is the caller graph for this function:

◆ srn_copy_bytes()

char * srn_copy_bytes ( const srn_context_t * ctx,
const char * src,
size_t len,
size_t alignment )

Definition at line 56 of file utils.c.

56 {
57 PANIC_IF_NULL(ctx);
58
59 char *dst = srn_allocate(ctx, len, alignment);
60
61 // It will panic earlier anyway.
62 if (dst == nullptr) {
63 return nullptr;
64 }
65
66 memcpy(dst, src, len);
67 return dst;
68}
void * srn_allocate(const srn_context_t *ctx, size_t size, size_t alignment)
Definition context.c:73
#define PANIC_IF_NULL(ptr)
Definition utils.h:66
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_dup_str()

char * srn_dup_str ( srn_mm_t * mm,
const char * s )

Copy a null terminated C string into a fresh allocation made through mm.

Returns nullptr on allocation failure.

Definition at line 70 of file utils.c.

70 {
71 PANIC_IF_NULL(mm);
73 size_t n = strlen(s);
74 char *copy = srn_mm_malloc(mm, n + 1);
75 if (copy == nullptr) {
76 return nullptr;
77 }
78 memcpy(copy, s, n + 1);
79 return copy;
80}
int n
Definition acutest.h:525
void * srn_mm_malloc(srn_mm_t *mm, size_t size)
Generic allocations that do not participate in the block based pools.
Definition default.c:155
Here is the call graph for this function:

◆ srn_now_ns()

uint64_t srn_now_ns ( void )

The current time on the monotonic clock, in nanoseconds.

Panics if the clock read fails – CLOCK_MONOTONIC with a valid buffer cannot fail on supported targets, so a failure means something is deeply wrong.

Definition at line 46 of file utils.c.

46 {
47 struct timespec ts;
48 // CLOCK_MONOTONIC with a valid buffer can only fail EINVAL (clock
49 // unsupported) or EFAULT (bad pointer), neither possible here -- so a failure
50 // should never happen.
51 int rc = clock_gettime(CLOCK_MONOTONIC, &ts);
52 PANIC_IF(rc != 0, "clock_gettime(CLOCK_MONOTONIC) failed");
53 return ((uint64_t)ts.tv_sec * SRN_NS_PER_SEC) + (uint64_t)ts.tv_nsec;
54}
#define SRN_NS_PER_SEC
nanoseconds in one second
Definition utils.h:306
Here is the caller graph for this function:

◆ srn_panic()

void srn_panic ( const char * msg,
const char * file,
size_t line,
const char * fn )

TODO(lxsameer): unwind the stack.

Definition at line 31 of file utils.c.

31 {
32 (void)fprintf(stderr, "PANIC: %s %s:%zu (%s)\n", msg, file, line, fn);
33 (void)fflush(nullptr);
34#if SERENE_DEBUG
35# if defined(__has_builtin) && __has_builtin(__builtin_debugtrap)
36 __builtin_debugtrap();
37# else
38 __builtin_trap(); // gcc: SIGILL into the debugger; no resumable trap
39# endif
40 __builtin_unreachable();
41#else
42 abort();
43#endif
44}
int const char * file
Definition acutest.h:779
void int line
Definition acutest.h:732

◆ srn_popcnt32()

uint32_t srn_popcnt32 ( uint32_t x)
inlinestatic

Definition at line 194 of file utils.h.

194 {
195#if defined(__clang__) || defined(__GNUC__)
196 return (uint32_t)__builtin_popcount(x);
197#else
198 x = x - ((x >> 1) & 0x55555555u);
199 x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u);
200 return (((x + (x >> 4)) & 0x0F0F0F0Fu) * 0x01010101u) >> 24;
201#endif
202}
Here is the caller graph for this function:

◆ srn_popcnt64()

uint64_t srn_popcnt64 ( uint64_t x)
inlinestatic

Definition at line 204 of file utils.h.

204 {
205#if defined(__GNUC__) || defined(__clang__)
206 return (uint64_t)__builtin_popcountll(x);
207#else
208 unsigned c = 0;
209 while (x) {
210 x &= x - 1;
211 ++c;
212 }
213 return c;
214#endif
215}

◆ srn_spinlock_init()

void srn_spinlock_init ( srn_spinlock_t * lock)
inlinestatic

Definition at line 280 of file utils.h.

280 {
281 lock->flag = (atomic_flag)ATOMIC_FLAG_INIT;
283}
atomic_flag flag
Definition utils.h:273
static void srn_spinlock_unlock(srn_spinlock_t *lock)
Definition utils.h:276
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_spinlock_lock()

void srn_spinlock_lock ( srn_spinlock_t * lock)
inlinestatic

Definition at line 285 of file utils.h.

285 {
286 while (atomic_flag_test_and_set_explicit(&lock->flag, memory_order_acquire)) {
287 // Keep busy for the lock to get unlocked
288 cpu_relax();
289 }
290}
static void cpu_relax(void)
A portable way to use pasue instructions.
Definition utils.h:223
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_spinlock_unlock()

void srn_spinlock_unlock ( srn_spinlock_t * lock)
inlinestatic

Definition at line 276 of file utils.h.

276 {
277 atomic_flag_clear_explicit(&lock->flag, memory_order_release);
278}
Here is the caller graph for this function: