diff --git a/include/cow.h b/include/cow.h index a6180f4..9472a66 100644 --- a/include/cow.h +++ b/include/cow.h @@ -8,6 +8,18 @@ extern "C" { #include +enum cow_err { + COW_ERR_UNKNOWN =0, + COW_ERR_NONE =1, // Success + + /// `memfd_create()` failed. + COW_ERR_FDCREATE, + /// `ftruncate()` (set size) failed. + COW_ERR_SIZE, + /// `mmap()` failed. + COW_ERR_MAP, +}; + // Copy-on-write mapped memory. typedef struct cow_mapped_slice cow_t; diff --git a/src/cow.c b/src/cow.c index 02a2eb5..b9c0f56 100644 --- a/src/cow.c +++ b/src/cow.c @@ -33,6 +33,7 @@ // struct cow { ... } #include "cow_t.h" +#include "error.h" static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold)) void die(const char* error) { @@ -48,6 +49,8 @@ static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold)) static inline cow_t* box_value(cow_t v) { cow_t* boxed = box(cow_t); + LASSERT(boxed != NULL, "aligned_alloc() returned `NULL` for `cow_t`"); + TRACE("boxing cow_t { origin = %p, fd = 0x%x, size = %lu } -> %p (%lu bytes)", v.origin, v.fd, v.size, (const void*)boxed, sizeof(cow_t)); *boxed = v; @@ -89,6 +92,7 @@ size_t cow_size(const cow_t* cow) inline internal cow_t _cow_create_unboxed(size_t size) { cow_t ret; + ret.error = COW_POISON_NONE; ret.size = size; ret.fd = shm_fd(size); ret.origin = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, ret.fd, 0); @@ -120,6 +124,7 @@ cow_t* cow_clone(const cow_t* cow) { cow_t clone; + clone.error = COW_POISON_NONE; clone.origin = mmap(cow->origin, cow->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, cow_real_fd(cow), 0); if(clone.origin == MAP_FAILED) die("cow_clone:mmap"); clone.fd = (~INT_MAX) | cow->fd; diff --git a/src/cow_t.h b/src/cow_t.h index 3719982..f16f715 100644 --- a/src/cow_t.h +++ b/src/cow_t.h @@ -2,7 +2,6 @@ #ifndef _COW_T_H #define _COW_T_H -#define internal __attribute__((visibility("internal"))) #ifdef __cplusplus #define restrict __restrict__ @@ -11,13 +10,19 @@ extern "C" { #include +#include "macros.h" #include +#include "error.h" + struct cow_mapped_slice { void* origin; // ptr to mapped memory. This *MUST* be the first field and have an offset of 0. size_t size; // Should be at this offset. int fd; // Will be ORd with ~INT_MAX if it's a clone. Will be >0 if it's the original. + + // Error status + union poison error; }; // cow_t, *cow #ifdef __cplusplus diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..7ec51d3 --- /dev/null +++ b/src/error.c @@ -0,0 +1,13 @@ +#include "error.h" + +internal void _cow_poison(cow_t* restrict cow, enum cow_err kind, const char *msg) +{ + if(cow->error.e_global) { + + } +} + +internal void _cow_poison_ref(cow_t* restrict cow, cow_error* globl) +{ + +} diff --git a/src/error.h b/src/error.h new file mode 100644 index 0000000..da700fc --- /dev/null +++ b/src/error.h @@ -0,0 +1,40 @@ +#ifndef _COW_ERROR_H +#define _COW_ERROR_H + +#include + +#include + +#include "macros.h" + +#ifdef __cplusplus +extern "C" { +#define restrict __restrict__ +#endif + +typedef struct cow_error cow_error; +union poison { + struct cow_error { + cow_error* prev; + + const char* message; + + enum cow_err kind : 31; + /// Should we free this instance? + unsigned char owned : 1; + } e_static; + cow_error* e_global; +}; + +#define COW_ERROR_NONE ((struct cow_error){ .prev = NULL, .message = NULL, .kind = COW_ERR_SUCCESS, .owned = 0 }) +#define COW_POISON_NONE ((union poison){ .e_static = COW_ERROR_NONE}) + +void _cow_poison(cow_t* restrict cow, enum cow_err kind, const char *msg) internal; +void _cow_poison_ref(cow_t* restrict cow, cow_error* globl) internal; + +#ifdef __cplusplus +} +#undef restrict +#endif + +#endif /* _COW_ERROR_H */ diff --git a/src/macros.h b/src/macros.h new file mode 100644 index 0000000..fdfeac3 --- /dev/null +++ b/src/macros.h @@ -0,0 +1,5 @@ + +#ifndef internal +#define internal __attribute__((visibility("internal"))) +#endif /* internal */ +