diff --git a/include/cow.h b/include/cow.h index 3adde60..ac7ccb7 100644 --- a/include/cow.h +++ b/include/cow.h @@ -6,14 +6,23 @@ // Copy-on-write mapped memory. typedef struct cow cow_t, *cow; +/// Create a new copy-on-write area of `size` bytes. +/// Writes to this instance pointer (`cow_ptr()`) are written to the allocated memory. +/// Writes to any cloned instances do not propagate to this instance. cow_t* cow_create(size_t size); +/// Free a cow area. This should be called on all clones before the parent of those clones is freed. void cow_free(cow_t* restrict cow); +/// Create a clone of this instance. Any writes to the returned pointer will not be propagated to the input one. cow_t* cow_clone(const cow_t* cow); +/// Returns 1 if this instance is a clone. 0 if it is not. int cow_is_fake(const cow_t* cow); +/// Get the size of this cow area. size_t cow_size(const cow_t* cow); +/// Get the `void*` pointer to the start of the area. #define cow_ptr(v) (*((void**)(v))) -#define cow_ptr_of(t, v) (*((t **)(v))) +/// Get the `T*` pointer to the start of the area. +#define cow_ptr_of(T, v) (*((T **)(v))) #endif /* _COW_H */ diff --git a/src/cow.c b/src/cow.c index b3b87dc..7a16a80 100644 --- a/src/cow.c +++ b/src/cow.c @@ -7,22 +7,21 @@ #include #include #include +#include #include #define box(t) aligned_alloc(_Alignof(t), sizeof(t)) -#define box_value_any(v) ({ __typeof(v)* _boxed = box(__typeof(v)); \ - *_boxed = (v); \ - _boxed; }) - struct cow { - void* origin; + void* origin; // ptr to mapped memory. This *MUST* be the first field and have an offset of 0. int fd; // Will be ORd with ~INT_MAX if it's a clone. Will be >0 if it's the original. size_t size; }; // cow_t, *cow +_Static_assert(offsetof(cow_t, origin) == 0, "`cow_t.origin` must have an offset of 0."); + static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold)) void die(const char* error) { perror(error); @@ -92,74 +91,3 @@ cow_t* cow_clone(const cow_t* cow) return box_value(clone); } -/* -void* cow_ptr(cow_t* restrict cow) -{ - return cow->origin; -} - -const void* cow_ptr_const(const cow_t* cow) -{ - return cow->origin; -} -*/ - -#ifdef DEMO // This code works -void alter(void* map_ptr) -{ - strcpy(map_ptr, "Hello two"); -} - -int main() -{ - // This works! - int graph = shm_fd(); - void* map_ptr = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, graph, 0); - if(map_ptr == MAP_FAILED) die("map_ptr"); - strcpy(map_ptr, "Hello world"); - printf("Ptr begins: %s\n", (const char*)map_ptr); - { - void* map_alter = mmap(map_ptr, SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE, graph, 0); - if(map_alter == MAP_FAILED) die("map_alter"); - printf("Alter begins: %s\n", (const char*)map_alter); - alter(map_alter); - printf("Alter ends: %s\n", (const char*)map_alter); - munmap(map_alter, SIZE); - } - printf("Ptr ends: %s\n", (const char*) map_ptr); - munmap(map_ptr, SIZE); - close(graph); - return 0; -} -#endif -// Doesn't work... -#if 0 -int main() -{ - void* map_ptr = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0); - if(map_ptr == MAP_FAILED) die("map_ptr"); - printf("First ptr is: %p\n - '", map_ptr); - strcpy(map_ptr, "Hello world"); - printf("%s'\n", (const char*)map_ptr); - -#ifdef USE_FORK - if(fork()>0) { // Eh... This is ugly. - printf("Forked...\n"); - void* map_alter = mmap(map_ptr, SIZE, PROT_READ|PROT_WRITE, MAP_ANON | MAP_FIXED |MAP_PRIVATE, 0, 0); -#else - //doesnt' work.... - void* map_alter = mmap(map_ptr, SIZE, PROT_READ|PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0); -#endif - if(map_alter == MAP_FAILED) die("map_alter"); - printf("Second ptr is: %p\n - '", map_alter); - printf("%s' - '", (const char*)map_alter); - strcpy(map_alter, "Hello two"); - printf("%s'\n", (const char*)map_alter); -#ifdef USE_FORK - } else -#endif - printf("First is still? '%s'\n", (volatile const char*)map_ptr); - - return 0; -} -#endif diff --git a/src/main.c b/src/main.c index 5d7577a..dd6a303 100644 --- a/src/main.c +++ b/src/main.c @@ -12,11 +12,11 @@ int main() strcpy(cow_ptr(origin), "Hello world"); cow_t* fake = cow_clone(origin); - printf("Fake (pre write): %s\n", (const char*)cow_ptr(fake)); + printf("Fake (pre write): %s\n", cow_ptr_of(const char, fake)); strcpy(cow_ptr(fake), "Hello fake!"); - printf("Real: %s\n", (const char*)cow_ptr(origin)); - printf("Fake: %s\n", (const char*)cow_ptr(fake)); + printf("Real: %s\n", cow_ptr_of(const char, origin)); + printf("Fake: %s\n", cow_ptr_of(const char, fake)); cow_free(fake); cow_free(origin);