documented the API

error_handling
Avril 4 years ago
parent a1c8b96abd
commit 3f4c59fa83
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -6,14 +6,23 @@
// Copy-on-write mapped memory. // Copy-on-write mapped memory.
typedef struct cow cow_t, *cow; 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); 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); 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); 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); int cow_is_fake(const cow_t* cow);
/// Get the size of this cow area.
size_t cow_size(const cow_t* cow); 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(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 */ #endif /* _COW_H */

@ -7,22 +7,21 @@
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <limits.h> #include <limits.h>
#include <stddef.h>
#include <cow.h> #include <cow.h>
#define box(t) aligned_alloc(_Alignof(t), sizeof(t)) #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 { 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. int fd; // Will be ORd with ~INT_MAX if it's a clone. Will be >0 if it's the original.
size_t size; size_t size;
}; // cow_t, *cow }; // 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) static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold)) void die(const char* error)
{ {
perror(error); perror(error);
@ -92,74 +91,3 @@ cow_t* cow_clone(const cow_t* cow)
return box_value(clone); 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

@ -12,11 +12,11 @@ int main()
strcpy(cow_ptr(origin), "Hello world"); strcpy(cow_ptr(origin), "Hello world");
cow_t* fake = cow_clone(origin); 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!"); strcpy(cow_ptr(fake), "Hello fake!");
printf("Real: %s\n", (const char*)cow_ptr(origin)); printf("Real: %s\n", cow_ptr_of(const char, origin));
printf("Fake: %s\n", (const char*)cow_ptr(fake)); printf("Fake: %s\n", cow_ptr_of(const char, fake));
cow_free(fake); cow_free(fake);
cow_free(origin); cow_free(origin);

Loading…
Cancel
Save