From a1c8b96abddf7a4759ab80043df6e75be35f7023 Mon Sep 17 00:00:00 2001 From: Avril Date: Fri, 4 Jun 2021 17:35:31 +0100 Subject: [PATCH] API for cow struct done --- .gitignore | 3 +- Makefile | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/cow.h | 19 +++++++++++++ src/cow.c | 69 +++++++++++++++++++++++---------------------- src/main.c | 24 ++++++++++++++++ 5 files changed, 159 insertions(+), 34 deletions(-) create mode 100644 Makefile create mode 100644 include/cow.h create mode 100644 src/main.c diff --git a/.gitignore b/.gitignore index cab3a22..aa7b7a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -cow +cow-* +obj/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2a56b78 --- /dev/null +++ b/Makefile @@ -0,0 +1,78 @@ +# Generic C and C++ Makefile project template +# Contains targets for `release', `debug', and `clean'. + +PROJECT=cow +AUTHOR=Avril (Flanchan) + +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} + diff --git a/include/cow.h b/include/cow.h new file mode 100644 index 0000000..3adde60 --- /dev/null +++ b/include/cow.h @@ -0,0 +1,19 @@ +#ifndef _COW_H +#define _COW_H + +#include + +// 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 */ diff --git a/src/cow.c b/src/cow.c index d1a6024..b3b87dc 100644 --- a/src/cow.c +++ b/src/cow.c @@ -8,15 +8,20 @@ #include #include -#define SIZE 4096 +#include -// Copy-on-write mapped memory. -typedef struct cow { +#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; 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_t, *cow 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); } +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) { - _Thread_local static char buffer[12] = {}; + _Thread_local static char buffer[12] = {0}; snprintf(buffer, 11, "0x%08lx", size); //fprintf(stderr, "shm_fd_name: '%s'\n", buffer); int fd = memfd_create(buffer, 0); @@ -45,7 +57,12 @@ int cow_is_fake(const cow_t* cow) 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; 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); 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); - if(!cow_is_fake(&cow)) - close(cow.fd); + munmap(cow->origin, cow->size); + if(!cow_is_fake(cow)) + close(cow->fd); + free(cow); } -cow_t cow_clone(cow_t cow) +cow_t* cow_clone(const cow_t* cow) { 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"); - clone.fd = (~INT_MAX) | cow.fd; - clone.size = cow.size; + clone.fd = (~INT_MAX) | cow->fd; + clone.size = cow->size; - return clone; + return box_value(clone); } - +/* void* cow_ptr(cow_t* restrict cow) { return cow->origin; @@ -84,22 +102,7 @@ const void* cow_ptr_const(const cow_t* cow) { 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 void alter(void* map_ptr) diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..5d7577a --- /dev/null +++ b/src/main.c @@ -0,0 +1,24 @@ +#include +#include +#include + +#include + +#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; +}