Skip to main content

Common Macros (xdef)

libx/xdef.h provides the global, foundational macro definitions and helper utilities used throughout XSTAR, including common size constants, boolean/null pointer definitions, container and offset calculations, branch prediction hints, static assertions, math helpers, and bit-scanning inline functions. The header is platform-independent and may be included by any source file.

Size Constants

Predefined memory size constants in hexadecimal form, convenient for buffer sizes, page alignment, heap/stack sizing, etc.

MacroValueMeaning
SZ_160x0000001016 bytes
SZ_2560x00000100256 bytes
SZ_5120x00000200512 bytes
SZ_1K0x000004001 KiB
SZ_4K0x000010004 KiB
SZ_8K0x000020008 KiB
SZ_16K0x0000400016 KiB
SZ_32K0x0000800032 KiB
SZ_64K0x0001000064 KiB
SZ_128K0x00020000128 KiB
SZ_256K0x00040000256 KiB
SZ_512K0x00080000512 KiB
SZ_1M0x001000001 MiB
SZ_2M0x002000002 MiB
SZ_4M0x004000004 MiB
SZ_8M0x008000008 MiB
SZ_16M0x0100000016 MiB
SZ_32M0x0200000032 MiB
SZ_64M0x0400000064 MiB
SZ_128M0x08000000128 MiB
SZ_256M0x10000000256 MiB
SZ_512M0x20000000512 MiB
SZ_1G0x400000001 GiB
SZ_2G0x800000002 GiB

Example:

char buf[SZ_4K];
void * heap = xos_mem_malloc(SZ_1M);

Basic Constants

NULL

Null pointer constant. Defined as 0 under C++ and ((void *)0) under C. Only defined when not already provided by the compiler.

TRUE / FALSE

Boolean true/false constants, with values 1 and 0 respectively. XSTAR uses these macros uniformly to represent boolean results, avoiding the <stdbool.h> dependency.

if(register_driver(&drv) == FALSE)
return FALSE;
return TRUE;

Struct and Pointer Operations

offsetof(type, member)

Computes the byte offset of a struct member relative to the start of the struct. Uses the compiler built-in __builtin_offsetof under GCC 4 and above, falling back to the classic macro otherwise.

struct foo_t {
int a;
char b;
void * c;
};

size_t off = offsetof(struct foo_t, c);

container_of(ptr, type, member)

Given the address of a struct member, recovers the address of the containing struct. This Linux-kernel-style macro is the foundation of intrusive data structures in XSTAR, such as list_head_t, hlist_node_t, and rb_node_t.

struct list_head_t * pos;
struct my_node_t * node = container_of(pos, struct my_node_t, list);

Branch Prediction

likely(expr) / unlikely(expr)

Provides the compiler with the expected result of a conditional expression to optimize instruction layout. Uses __builtin_expect on GCC 3+ and degrades to a plain boolean expression on other compilers.

if(unlikely(ptr == NULL))
return FALSE;

if(likely(count > 0))
do_work();

Only use these on performance-sensitive hot paths with a clearly skewed branch direction; avoid them in ordinary code.

Static Assertion

STATIC_ASSERT(cond)

Compile-time assertion. Emits no code when the condition is true; when false, it defines an array of size -1 to trigger a compilation error. Commonly used to constrain struct sizes, enum ranges, etc.

STATIC_ASSERT(sizeof(uint32_t) == 4);
STATIC_ASSERT(DEVICE_TYPE_MAX_COUNT < 256);

Math and Numeric Helpers

XMAP(x, ia, ib, oa, ob)

Linearly maps x from the input range [ia, ib] to the output range [oa, ob]. Useful for ADC sampling, brightness/volume normalization, etc.

int duty = XMAP(adc_value, 0, 4095, 0, 100);

XMIN(a, b) / XMAX(a, b)

Type-safe minimum/maximum macros. Implemented with GCC statement expressions and typeof, avoiding argument side effects and producing a compile warning when the operand types disagree.

int m = XMIN(a, b);
int n = XMAX(x + 1, y - 1);

XCLAMP(v, a, b)

Clamps v to the closed range [a, b]. Equivalent to XMIN(XMAX(a, v), b).

int volume = XCLAMP(user_input, 0, 100);

XFLOOR(x) / XROUND(x) / XCEIL(x)

Floating-point to int rounding macros for floor, round-half-up, and ceiling respectively. They avoid the <math.h> dependency and handle negative numbers symmetrically.

int a = XFLOOR(1.7); /* 1 */
int b = XROUND(1.5); /* 2 */
int c = XCEIL(-1.2); /* -1 */

XDIV255(x)

Fast integer division by 255, equivalent to (x + 1) * 257 >> 16. Commonly used in alpha blending for 8-bit color channels; faster than a regular division.

uint8_t blended = XDIV255((uint32_t)src * alpha);

XBYTEMUL(x, a)

Simultaneously multiplies the two interleaved groups of 8-bit byte channels in a 32-bit integer (such as the R/B and G/A channels of RGBA) by an 8-bit constant a and normalizes back to 8-bit. This is the core optimization macro for color multiplication in the graphics subsystem.

Arrays and Strings

ARRAY_SIZE(array)

Returns the number of elements in a static array. Only valid for true array objects (not pointers).

static const char * names[] = { "a", "b", "c" };
for(int i = 0; i < ARRAY_SIZE(names); i++)
use(names[i]);

X(...)

Converts variadic arguments verbatim into a string literal. Useful for embedding JSON, device-tree fragments, or other multi-line text without extra escaping.

const char * json = X({
"name": "demo",
"value": 42
});

Bit-Scanning Inline Functions

All of the following inline functions are implemented with GCC built-ins and have zero overhead.

int xffs(int x)

Returns the position of the lowest set bit in x (1-based). Returns 0 when x is 0.

int xfls(int x)

Returns the position of the highest set bit in x (1-based). Returns 0 when x is 0. Commonly used to compute base-2 logarithms or round up to the next power of two.

int order = xfls(size - 1); /* smallest 2^order >= size */

unsigned long __xffs(unsigned long x)

Returns the index (0-based) of the lowest set bit in x, equivalent to __builtin_ctzl. x must not be 0.

unsigned long __xfls(unsigned long x)

Returns the index (0-based) of the highest set bit in x, equivalent to (sizeof(long) * 8) - 1 - __builtin_clzl(x). x must not be 0.

unsigned long bit = __xffs(mask); /* lowest set bit index */
mask &= ~(1UL << bit); /* clear that bit */

Usage Guidelines

  • Source files should bring these definitions in via #include <xstar.h> or directly via #include <libx/xdef.h>.
  • Prefer XMIN / XMAX / XCLAMP over hand-written ternary expressions to avoid side-effect bugs caused by repeated argument evaluation.
  • Do not overuse likely / unlikely; reserve them for hot paths where instruction layout actually matters.
  • STATIC_ASSERT may be placed at file scope in headers and is equally valid inside functions.
  • Together with the XOS abstraction layer and libx/xtypes.h, this header forms the minimal foundation required by all XSTAR source code.