API for cow struct done

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

3
.gitignore vendored

@ -1 +1,2 @@
cow cow-*
obj/

@ -0,0 +1,78 @@
# Generic C and C++ Makefile project template
# Contains targets for `release', `debug', and `clean'.
PROJECT=cow
AUTHOR=Avril (Flanchan) <flanchan@cumallover.me>
SRC_C = $(wildcard src/*.c)
SRC_CXX = $(wildcard src/*.cpp)
INCLUDE=include
COMMON_FLAGS= -W -Wall -pedantic -fno-strict-aliasing $(addprefix -I,$(INCLUDE))
MARCH?=native
OPT_FLAGS?= $(addprefix -march=,$(MARCH)) -fgraphite -fopenmp -floop-parallelize-all -ftree-parallelize-loops=4 \
-floop-interchange -ftree-loop-distribution -floop-strip-mine -floop-block \
-fno-stack-check
CXX_OPT_FLAGS?= $(OPT_FLAGS) -felide-constructors
CFLAGS += $(COMMON_FLAGS) --std=gnu11
CXXFLAGS += $(COMMON_FLAGS) --std=gnu++20 -fno-exceptions
LDFLAGS +=
STRIP=strip
RELEASE_CFLAGS?= -O3 -flto $(OPT_FLAGS)
RELEASE_CXXFLAGS?= -O3 -flto $(CXX_OPT_FLAGS)
RELEASE_LDFLAGS?= -O3 -flto
DEBUG_CFLAGS?= -O0 -g -DDEBUG
DEBUG_CXXFLAGS?= $(DEBUG_CFLAGS)
DEBUG_LDFLAGS?=
# Objects
OBJ_C = $(addprefix obj/c/,$(SRC_C:.c=.o))
OBJ_CXX = $(addprefix obj/cxx/,$(SRC_CXX:.cpp=.o))
OBJ = $(OBJ_C) $(OBJ_CXX)
# Phonies
.PHONY: release
release: | dirs $(PROJECT)-release
.PHONY: debug
debug: | dirs $(PROJECT)-debug
# Targets
dirs:
@mkdir -p obj/c{,xx}/src
obj/c/%.o: %.c
$(CC) -c $< $(CFLAGS) -o $@ $(LDFLAGS)
obj/cxx/%.o: %.cpp
$(CXX) -c $< $(CXXFLAGS) -o $@ $(LDFLAGS)
$(PROJECT)-release: CFLAGS+= $(RELEASE_CFLAGS)
$(PROJECT)-release: CXXFLAGS += $(RELEASE_CXXFLAGS)
$(PROJECT)-release: LDFLAGS += $(RELEASE_LDFLAGS)
$(PROJECT)-release: $(OBJ)
$(CXX) $^ $(CXXFLAGS) -o $@ $(LDFLAGS)
$(STRIP) $@
$(PROJECT)-debug: CFLAGS+= $(DEBUG_CFLAGS)
$(PROJECT)-debug: CXXFLAGS += $(DEBUG_CXXFLAGS)
$(PROJECT)-debug: LDFLAGS += $(DEBUG_LDFLAGS)
$(PROJECT)-debug: $(OBJ)
$(CXX) $^ $(CXXFLAGS) -o $@ $(LDFLAGS)
clean-rebuild:
rm -rf obj
clean: clean-rebuild
rm -f $(PROJECT)-{release,debug,pgo}

@ -0,0 +1,19 @@
#ifndef _COW_H
#define _COW_H
#include <stdlib.h>
// Copy-on-write mapped memory.
typedef struct cow cow_t, *cow;
cow_t* cow_create(size_t size);
void cow_free(cow_t* restrict cow);
cow_t* cow_clone(const cow_t* cow);
int cow_is_fake(const cow_t* cow);
size_t cow_size(const cow_t* cow);
#define cow_ptr(v) (*((void**)(v)))
#define cow_ptr_of(t, v) (*((t **)(v)))
#endif /* _COW_H */

@ -8,15 +8,20 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <limits.h> #include <limits.h>
#define SIZE 4096 #include <cow.h>
// Copy-on-write mapped memory. #define box(t) aligned_alloc(_Alignof(t), sizeof(t))
typedef struct cow { #define box_value_any(v) ({ __typeof(v)* _boxed = box(__typeof(v)); \
*_boxed = (v); \
_boxed; })
struct cow {
void* origin; void* origin;
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_t, *cow
static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold)) void die(const char* error) static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold)) void die(const char* error)
{ {
@ -24,9 +29,16 @@ static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold))
exit(1); exit(1);
} }
static inline cow_t* box_value(cow_t v)
{
cow_t* boxed = box(cow_t);
*boxed = v;
return boxed;
}
static inline int shm_fd(size_t size) static inline int shm_fd(size_t size)
{ {
_Thread_local static char buffer[12] = {}; _Thread_local static char buffer[12] = {0};
snprintf(buffer, 11, "0x%08lx", size); snprintf(buffer, 11, "0x%08lx", size);
//fprintf(stderr, "shm_fd_name: '%s'\n", buffer); //fprintf(stderr, "shm_fd_name: '%s'\n", buffer);
int fd = memfd_create(buffer, 0); int fd = memfd_create(buffer, 0);
@ -45,7 +57,12 @@ int cow_is_fake(const cow_t* cow)
return cow->fd<0; return cow->fd<0;
} }
cow_t cow_create(size_t size) size_t cow_size(const cow_t* cow)
{
return cow->size;
}
cow_t* cow_create(size_t size)
{ {
cow_t ret; cow_t ret;
ret.size = size; ret.size = size;
@ -53,28 +70,29 @@ cow_t cow_create(size_t 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);
if(ret.origin == MAP_FAILED) die("cow_create:mmap"); if(ret.origin == MAP_FAILED) die("cow_create:mmap");
return ret; return box_value(ret);
} }
void cow_free(cow_t cow) void cow_free(cow_t* restrict cow)
{ {
munmap(cow.origin, cow.size); munmap(cow->origin, cow->size);
if(!cow_is_fake(&cow)) if(!cow_is_fake(cow))
close(cow.fd); close(cow->fd);
free(cow);
} }
cow_t cow_clone(cow_t cow) cow_t* cow_clone(const cow_t* cow)
{ {
cow_t clone; cow_t clone;
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;
clone.size = cow.size; clone.size = cow->size;
return clone; return box_value(clone);
} }
/*
void* cow_ptr(cow_t* restrict cow) void* cow_ptr(cow_t* restrict cow)
{ {
return cow->origin; return cow->origin;
@ -84,22 +102,7 @@ const void* cow_ptr_const(const cow_t* cow)
{ {
return cow->origin; return cow->origin;
} }
*/
int main()
{
cow_t origin = cow_create(SIZE);
strcpy(cow_ptr(&origin), "Hello world");
cow_t fake = cow_clone(origin);
printf("Fake (pre write): %s\n", (const char*)cow_ptr(&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));
cow_free(fake);
cow_free(origin);
return 0;
}
#ifdef DEMO // This code works #ifdef DEMO // This code works
void alter(void* map_ptr) void alter(void* map_ptr)

@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cow.h>
#define SIZE 4096
int main()
{
cow_t* origin = cow_create(SIZE);
strcpy(cow_ptr(origin), "Hello world");
cow_t* fake = cow_clone(origin);
printf("Fake (pre write): %s\n", (const char*)cow_ptr(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));
cow_free(fake);
cow_free(origin);
return 0;
}
Loading…
Cancel
Save