This commit is contained in:
2026-08-11 17:48:20 +02:00
committed by Marvin Friedrich
parent cf33867e68
commit 0e2d4ed8c6
55 changed files with 279 additions and 346 deletions
@@ -3,7 +3,8 @@
#include <common/compiler.h>
#include <kernel/panic.h>
#define ASSERT(expr, msg, ...) \
// Like the standard C assert, but also active in debug builds.
#define assert(expr, msg, ...) \
({ \
if (__unlikely(!(expr))) { \
panic( \
@@ -19,7 +20,7 @@
})
#ifndef NDEBUG
#define DEBUG_ASSERT(...) ASSERT(__VA_ARGS__)
#define debug_assert(...) assert(__VA_ARGS__)
#else
#define DEBUG_ASSERT(...) ((void)0)
#define debug_assert(...) ((void)0)
#endif
+2 -2
View File
@@ -13,13 +13,13 @@ struct channel_msg {
size_t num_bytes;
struct namespace_desc* descs;
size_t num_handles;
TAILQ_LINK(struct channel_msg) next;
tailq_link(struct channel_msg) next;
};
struct channel {
struct channel* peer;
struct spinlock lock;
TAILQ_HEAD(struct channel_msg) messages;
tailq_head(struct channel_msg) messages;
struct wait_queue waiters;
};
+11 -11
View File
@@ -25,7 +25,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
// Ensure a hash is never zero (zero is the empty sentinel).
#define _HASHMAP_FIXHASH(h) ((h) == 0 ? (uint64_t)1 : (h))
#define HASHMAP(K, V) \
#define hashmap(K, V) \
struct { \
K* keys; \
V* values; \
@@ -34,7 +34,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
size_t count; \
}
#define HASHMAP_INIT(map) \
#define hashmap_init(map) \
do { \
(map)->keys = nullptr; \
(map)->values = nullptr; \
@@ -43,7 +43,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
(map)->count = 0; \
} while (0)
#define HASHMAP_DESTROY(map) \
#define hashmap_destroy(map) \
do { \
mem_free((map)->keys); \
mem_free((map)->values); \
@@ -55,7 +55,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
(map)->count = 0; \
} while (0)
#define HASHMAP_COUNT(map) ((map)->count)
#define hashmap_count(map) ((map)->count)
// Internal: probe distance from ideal position.
#define _HASHMAP_PROBE_DIST(hash, pos, cap) (((pos) - ((hash) & ((cap) - 1))) & ((cap) - 1))
@@ -116,10 +116,10 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
} \
} while (0)
// Insert or update a key-value pair. Returns ZN_OK or ZN_ERR_NO_MEMORY.
#define HASHMAP_INSERT(map, key, val, hash_fn, eq_fn) \
// Insert or update a key-value pair. Returns 0 or ZN_ERR_NO_MEMORY.
#define hashmap_insert(map, key, val, hash_fn, eq_fn) \
({ \
zn_status_t _status = ZN_OK; \
zn_status_t _status = 0; \
typeof(*(map)->keys) _k = (key); \
uint64_t _h = _HASHMAP_FIXHASH((hash_fn)(&_k, sizeof(_k))); \
/* Check for existing key first. */ \
@@ -147,7 +147,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
_status = ZN_ERR_NO_MEMORY; \
} \
} \
if (_status == ZN_OK) { \
if (_status == 0) { \
_HASHMAP_INSERT_INNER(map, _k, (val), _h); \
} \
} \
@@ -155,7 +155,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
})
// Look up a key. Returns a pointer to the value, or nullptr if not found.
#define HASHMAP_GET(map, key, hash_fn, eq_fn) \
#define hashmap_get(map, key, hash_fn, eq_fn) \
({ \
typeof(*(map)->values)* _result = nullptr; \
if ((map)->capacity > 0) { \
@@ -180,7 +180,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
// Remove a key. Returns true if the key was found and removed.
// Uses backward-shift deletion to avoid tombstones.
#define HASHMAP_REMOVE(map, key, hash_fn, eq_fn) \
#define hashmap_remove(map, key, hash_fn, eq_fn) \
({ \
bool _removed = false; \
if ((map)->capacity > 0) { \
@@ -218,6 +218,6 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len)
// Iterate over all occupied entries. `idx` is a size_t loop variable.
// Access keys and values via (map)->keys[idx] and (map)->values[idx].
#define HASHMAP_FOREACH(map, idx) \
#define hashmap_foreach(map, idx) \
for (size_t idx = 0; idx < (map)->capacity; idx++) \
if ((map)->hashes[idx] != 0)
+2 -2
View File
@@ -22,7 +22,7 @@ enum irq_trigger_mode : uint8_t {
struct irq_handler {
enum irq_status (*handler)(void* self);
SLIST_LINK(struct irq_handler*) next;
list_link(struct irq_handler*) next;
};
struct irq_line {
@@ -31,7 +31,7 @@ struct irq_line {
void (*unmask)(struct irq_line* self);
void (*eoi)(struct irq_line* self);
SLIST_HEAD(struct irq_handler*) handlers;
list_head(struct irq_handler*) handlers;
bool is_busy;
};
+14 -14
View File
@@ -1,29 +1,29 @@
#pragma once
#define SLIST_HEAD(type) \
#define list_head(type) \
struct { \
type sl_head; \
type _sl_head; \
}
#define SLIST_LINK(type) \
#define list_link(type) \
struct { \
type sl_link; \
type _sl_link; \
}
#define SLIST_EMPTY(head) ((head)->sl_head == NULL)
#define SLIST_FIRST(head) ((head)->sl_head)
#define SLIST_NEXT(elm, field) ((elm)->field.sl_link)
#define list_is_empty(head) ((head)->_sl_head == NULL)
#define list_first(head) ((head)->_sl_head)
#define list_next(elm, field) ((elm)->field._sl_link)
#define SLIST_INSERT_END(slistelm, elm, field) \
#define list_insert_end(slistelm, elm, field) \
do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
list_next((elm), field) = list_next((slistelm), field); \
list_next((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) \
#define list_insert_head(head, elm, field) \
do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
list_next((elm), field) = list_first((head)); \
list_first((head)) = (elm); \
} while (0)
#define SLIST_FOREACH(var, head, field) for ((var) = SLIST_FIRST((head)); (var); (var) = SLIST_NEXT((var), field))
#define list_foreach(var, head, field) for ((var) = list_first((head)); (var); (var) = list_next((var), field))
+1 -1
View File
@@ -32,7 +32,7 @@ struct namespace_desc {
struct namespace {
zn_handle_t next_handle;
struct mutex mutex;
HASHMAP(zn_handle_t, struct namespace_desc) descriptors;
hashmap(zn_handle_t, struct namespace_desc) descriptors;
};
// Creates a new namespace with no contents.
+2 -2
View File
@@ -38,7 +38,7 @@ struct task {
size_t time_slice;
int8_t priority;
TAILQ_LINK(struct task) next;
tailq_link(struct task) next;
};
// Per-CPU data for scheduling.
@@ -46,7 +46,7 @@ struct sched_percpu {
struct task* current;
struct task* idle_task;
size_t preempt_level;
TAILQ_HEAD(struct task) run_queue;
tailq_head(struct task) run_queue;
};
// Blocks the current task on the given wait queue.
+4 -1
View File
@@ -1,9 +1,12 @@
#pragma once
#include <stdint.h>
// Busy-waits in a loop until the lock is freed.
// Does not put the CPU to sleep.
struct spinlock {
bool locked;
uint32_t owner;
uint32_t next;
};
// Attempts to lock a spinlock. If it's already locked, waits until it's freed.
+9 -9
View File
@@ -1,30 +1,30 @@
#pragma once
#define TAILQ_HEAD(type) \
#define tailq_head(type) \
struct { \
type* tqh_first; \
type** tqh_last; \
}
#define TAILQ_LINK(type) \
#define tailq_link(type) \
struct { \
type* tqe_next; \
type** tqe_prev; \
}
#define TAILQ_INIT(head) \
#define tailq_init(head) \
do { \
(head)->tqh_first = nullptr; \
(head)->tqh_last = &(head)->tqh_first; \
} while (0)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define tailq_first(head) ((head)->tqh_first)
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define tailq_next(elm, field) ((elm)->field.tqe_next)
#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == nullptr)
#define tailq_empty(head) (tailq_first(head) == nullptr)
#define TAILQ_INSERT_TAIL(head, elm, field) \
#define tailq_insert_tail(head, elm, field) \
do { \
(elm)->field.tqe_next = nullptr; \
(elm)->field.tqe_prev = (head)->tqh_last; \
@@ -32,7 +32,7 @@
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) \
#define tailq_insert_head(head, elm, field) \
do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != nullptr) \
(head)->tqh_first->field.tqe_prev = &(elm)->field.tqe_next; \
@@ -42,7 +42,7 @@
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (0)
#define TAILQ_REMOVE(head, elm, field) \
#define tailq_remove(head, elm, field) \
do { \
if (((elm)->field.tqe_next) != nullptr) \
(elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev; \
+25 -26
View File
@@ -1,25 +1,24 @@
#pragma once
#include <zinnia/status.h>
#include <kernel/alloc.h>
#include <stddef.h>
#include <string.h>
#include <stddef.h> // IWYU pragma: keep
#include <string.h> // IWYU pragma: keep
#define VEC(T) \
#define vec(T) \
struct { \
T* data; \
size_t length; \
size_t capacity; \
}
#define VEC_INIT(vec) \
#define vec_init(vec) \
do { \
(vec)->data = nullptr; \
(vec)->length = 0; \
(vec)->capacity = 0; \
} while (0)
#define VEC_DESTROY(vec) \
#define vec_destroy(vec) \
do { \
mem_free((vec)->data); \
(vec)->data = nullptr; \
@@ -27,13 +26,13 @@
(vec)->capacity = 0; \
} while (0)
#define VEC_LENGTH(vec) ((vec)->length)
#define VEC_CAPACITY(vec) ((vec)->capacity)
#define VEC_EMPTY(vec) ((vec)->length == 0)
#define VEC_AT(vec, i) ((vec)->data[i])
#define vec_length(vec) ((vec)->length)
#define vec_capacity(vec) ((vec)->capacity)
#define vec_empty(vec) ((vec)->length == 0)
#define vec_at(vec, i) ((vec)->data[i])
// Internal: grow to at least `needed` capacity.
#define _VEC_GROW(vec, needed) \
#define _vec_grow(vec, needed) \
do { \
size_t _new_cap = (vec)->capacity == 0 ? 8 : (vec)->capacity; \
while (_new_cap < (needed)) \
@@ -46,34 +45,34 @@
(vec)->capacity = _new_cap; \
} while (0)
// Append an element. Returns ZN_OK or ZN_ERR_NO_MEMORY.
#define VEC_PUSH(vec, val) \
// Append an element. Returns 0 or ZN_ERR_NO_MEMORY.
#define vec_push(vec, val) \
({ \
zn_status_t _status = ZN_OK; \
zn_status_t _status = 0; \
if ((vec)->length >= (vec)->capacity) { \
_VEC_GROW(vec, (vec)->length + 1); \
_vec_grow(vec, (vec)->length + 1); \
if ((vec)->data == nullptr) \
_status = ZN_ERR_NO_MEMORY; \
} \
if (_status == ZN_OK) \
if (_status == 0) \
(vec)->data[(vec)->length++] = (val); \
_status; \
})
// Remove and return the last element. Undefined if empty.
#define VEC_POP(vec) ((vec)->data[--(vec)->length])
#define vec_pop(vec) ((vec)->data[--(vec)->length])
// Insert at index, shifting subsequent elements right. Returns ZN_OK or ZN_ERR_NO_MEMORY.
#define VEC_INSERT(vec, i, val) \
// Insert at index, shifting subsequent elements right. Returns 0 or ZN_ERR_NO_MEMORY.
#define vec_insert(vec, i, val) \
({ \
zn_status_t _status = ZN_OK; \
zn_status_t _status = 0; \
size_t _idx = (i); \
if ((vec)->length >= (vec)->capacity) { \
_VEC_GROW(vec, (vec)->length + 1); \
_vec_grow(vec, (vec)->length + 1); \
if ((vec)->data == nullptr) \
_status = ZN_ERR_NO_MEMORY; \
} \
if (_status == ZN_OK) { \
if (_status == 0) { \
memmove(&(vec)->data[_idx + 1], &(vec)->data[_idx], ((vec)->length - _idx) * sizeof(*(vec)->data)); \
(vec)->data[_idx] = (val); \
(vec)->length++; \
@@ -82,7 +81,7 @@
})
// Remove element at index, shifting subsequent elements left.
#define VEC_REMOVE(vec, i) \
#define vec_remove(vec, i) \
do { \
size_t _idx = (i); \
(vec)->length--; \
@@ -91,7 +90,7 @@
} while (0)
// Remove element at index by swapping with the last element (O(1), unordered).
#define VEC_SWAP_REMOVE(vec, i) \
#define vec_swap_remove(vec, i) \
do { \
size_t _idx = (i); \
(vec)->length--; \
@@ -100,6 +99,6 @@
} while (0)
// Clear all elements without freeing memory.
#define VEC_CLEAR(vec) ((vec)->length = 0)
#define vec_clear(vec) ((vec)->length = 0)
#define VEC_FOREACH(vec, idx) for (size_t idx = 0; idx < (vec)->length; idx++)
#define vec_foreach(vec, idx) for (size_t idx = 0; idx < (vec)->length; idx++)
+2 -2
View File
@@ -30,13 +30,13 @@ struct pager_ops {
struct page_list {
uintptr_t offset;
struct page* value;
SLIST_LINK(struct page_list*) next;
list_link(struct page_list*) next;
};
struct paged_vmo {
struct vmo object;
struct pager_ops source;
SLIST_HEAD(struct page_list*) cache;
list_head(struct page_list*) cache;
struct spinlock lock;
};
+1 -1
View File
@@ -7,7 +7,7 @@ struct task;
// A queue of tasks waiting for an event.
struct wait_queue {
TAILQ_HEAD(struct task) waiters;
tailq_head(struct task) waiters;
struct spinlock lock;
};
+1 -4
View File
@@ -1,10 +1,7 @@
#ifndef ZINNIA_STDARG_H
#define ZINNIA_STDARG_H
#pragma once
typedef __builtin_va_list va_list;
#define va_start(v, l) __builtin_va_start(v, l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v, T) __builtin_va_arg(v, T)
#define va_copy(d, s) __builtin_va_copy(d, s)
#endif
+1 -4
View File
@@ -1,5 +1,4 @@
#ifndef ZINNIA_STDATOMIC_H
#define ZINNIA_STDATOMIC_H
#pragma once
typedef enum memory_order {
memory_order_relaxed = __ATOMIC_RELAXED,
@@ -35,5 +34,3 @@ typedef enum memory_order {
#define atomic_fetch_and(ptr, op) atomic_fetch_and_explicit(ptr, op, __ATOMIC_SEQ_CST)
#define atomic_thread_fence(ord) __atomic_thread_fence(ord)
#endif
+2 -4
View File
@@ -1,9 +1,7 @@
#ifndef ZINNIA_STDDEF_H
#define ZINNIA_STDDEF_H
#pragma once
typedef unsigned long size_t;
typedef signed long ssize_t;
#define offsetof(type, member) __builtin_offsetof(type, member)
#endif
#define unreachable() __builtin_unreachable()
+1 -4
View File
@@ -1,5 +1,4 @@
#ifndef ZINNIA_STDINT_H
#define ZINNIA_STDINT_H
#pragma once
typedef __INT8_TYPE__ int8_t;
typedef __UINT8_TYPE__ uint8_t;
@@ -25,5 +24,3 @@ typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
#define INTPTR_MAX __INTPTR_MAX__
#define UINTPTR_MAX __UINTPTR_MAX__
#endif
+1 -4
View File
@@ -1,7 +1,4 @@
#ifndef ZINNIA_STDLIB_H
#define ZINNIA_STDLIB_H
#pragma once
long atol(const char* str, int base);
unsigned long atolu(const char* str, int base);
#endif
+1 -4
View File
@@ -1,5 +1,4 @@
#ifndef ZINNIA_STRING_H
#define ZINNIA_STRING_H
#pragma once
#include <stddef.h>
@@ -13,5 +12,3 @@ char* strncpy(char* restrict dst, const char* restrict src, size_t len);
int strcmp(const char* str1, const char* str2);
int strncmp(const char* str1, const char* str2, size_t len);
char* strchr(const char* c, int s);
#endif