start recoverable error handle: failed design

error_handling
Avril 4 years ago
parent 8d5e587333
commit aeb3f528d4
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -8,6 +8,18 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
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. // Copy-on-write mapped memory.
typedef struct cow_mapped_slice cow_t; typedef struct cow_mapped_slice cow_t;

@ -33,6 +33,7 @@
// struct cow { ... } // struct cow { ... }
#include "cow_t.h" #include "cow_t.h"
#include "error.h"
static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold)) void die(const char* error) 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) static inline cow_t* box_value(cow_t v)
{ {
cow_t* boxed = box(cow_t); 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)); 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; *boxed = v;
@ -89,6 +92,7 @@ size_t cow_size(const cow_t* cow)
inline internal cow_t _cow_create_unboxed(size_t size) inline internal cow_t _cow_create_unboxed(size_t size)
{ {
cow_t ret; cow_t ret;
ret.error = COW_POISON_NONE;
ret.size = size; ret.size = size;
ret.fd = shm_fd(size); ret.fd = shm_fd(size);
ret.origin = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, ret.fd, 0); 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; 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); 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"); if(clone.origin == MAP_FAILED) die("cow_clone:mmap");
clone.fd = (~INT_MAX) | cow->fd; clone.fd = (~INT_MAX) | cow->fd;

@ -2,7 +2,6 @@
#ifndef _COW_T_H #ifndef _COW_T_H
#define _COW_T_H #define _COW_T_H
#define internal __attribute__((visibility("internal")))
#ifdef __cplusplus #ifdef __cplusplus
#define restrict __restrict__ #define restrict __restrict__
@ -11,13 +10,19 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
#include "macros.h"
#include <cow.h> #include <cow.h>
#include "error.h"
struct cow_mapped_slice { struct cow_mapped_slice {
void* origin; // ptr to mapped memory. This *MUST* be the first field and have an offset of 0. 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. 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. 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 }; // cow_t, *cow
#ifdef __cplusplus #ifdef __cplusplus

@ -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)
{
}

@ -0,0 +1,40 @@
#ifndef _COW_ERROR_H
#define _COW_ERROR_H
#include <stdlib.h>
#include <cow.h>
#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 */

@ -0,0 +1,5 @@
#ifndef internal
#define internal __attribute__((visibility("internal")))
#endif /* internal */
Loading…
Cancel
Save