From 1d35956aad0a1a4907185ce039bcb0ab4385c06e Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Mon, 11 Apr 2016 23:25:49 -0400 Subject: [PATCH 01/37] synchronize bop_msg --- bop_ppr.c | 2 +- utils.c | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/bop_ppr.c b/bop_ppr.c index 984484e..a2887f1 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -467,7 +467,7 @@ void ErrorKillAll(int signo){ //don't need to reap children. We know that it's an erroring-exit, //intecept the call, allert monitor process, execute def behavior /**Horrible things are happening. Go to SEQ mode so malloc won't have issues*/ - bop_msg(1, "ERROR CAUGHT %d", signo); + bop_msg(1, "ERROR CAUGHT %s (%d)", strsignal(signo), signo); int om = bop_mode; malloc_panic = true; print_backtrace(); diff --git a/utils.c b/utils.c index 8bb1d10..9dbfd8f 100644 --- a/utils.c +++ b/utils.c @@ -5,7 +5,9 @@ #include #include #include +#include #include +#include #include "bop_api.h" #include "utils.h" @@ -15,7 +17,7 @@ extern int ppr_index; extern int spec_order; extern bop_mode_t bop_mode; -sem_t *bopmsg_sem = NULL; +static pthread_mutex_t * msg_lock; task_status_t BOP_task_status(void) { return task_status; @@ -62,8 +64,9 @@ char *strerror(int errnum); void bop_msg(int level, const char * msg, ...) { if(bop_verbose >= level) { - //msg_init(); - sem_wait(bopmsg_sem); + msg_init(); + if(msg_lock != NULL) + pthread_mutex_lock(msg_lock); va_list v; va_start(v,msg); fprintf(stderr, "%d-", getpid()); @@ -98,23 +101,23 @@ void bop_msg(int level, const char * msg, ...) { vfprintf(stderr,msg,v); fprintf(stderr,"\n"); fflush(stderr); - sem_post(bopmsg_sem); + if(msg_lock != NULL) + pthread_mutex_unlock(msg_lock); } } void msg_init(){ - if (!bopmsg_sem){ - bopmsg_sem = sem_open("/bopmsg.sem", (O_CREAT), S_IRWXO|S_IRWXU|S_IRWXG, 0); - if(bopmsg_sem == SEM_FAILED){ - printf("Error in BOP_Init: %s\n", strerror(errno)); - } - assert(bopmsg_sem != NULL); - assert(bopmsg_sem != SEM_FAILED); - sem_post(bopmsg_sem); + if (!msg_lock){ + msg_lock = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); + pthread_mutexattr_t mutexAttr; + if(pthread_mutexattr_init(&mutexAttr)) perror("Couldn't create mutex attr"); + if(pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED)) perror("Error sharing mutex"); + if(pthread_mutex_init(msg_lock, &mutexAttr)) perror("Error creating shared msg mutex"); } } void msg_destroy(){ - sem_close(bopmsg_sem); + munmap(msg_lock, 0); + pthread_mutex_destroy(msg_lock); } /* read the environment variable env, and returns it's integer value. From 9e32f2df54ca717d0ae4cbb0a696b01bfefa051a Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Mon, 11 Apr 2016 23:32:54 -0400 Subject: [PATCH 02/37] Revert "synchronize bop_msg" This reverts commit 1d35956aad0a1a4907185ce039bcb0ab4385c06e. --- bop_ppr.c | 2 +- utils.c | 29 +++++++++++++---------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/bop_ppr.c b/bop_ppr.c index a2887f1..984484e 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -467,7 +467,7 @@ void ErrorKillAll(int signo){ //don't need to reap children. We know that it's an erroring-exit, //intecept the call, allert monitor process, execute def behavior /**Horrible things are happening. Go to SEQ mode so malloc won't have issues*/ - bop_msg(1, "ERROR CAUGHT %s (%d)", strsignal(signo), signo); + bop_msg(1, "ERROR CAUGHT %d", signo); int om = bop_mode; malloc_panic = true; print_backtrace(); diff --git a/utils.c b/utils.c index 9dbfd8f..8bb1d10 100644 --- a/utils.c +++ b/utils.c @@ -5,9 +5,7 @@ #include #include #include -#include #include -#include #include "bop_api.h" #include "utils.h" @@ -17,7 +15,7 @@ extern int ppr_index; extern int spec_order; extern bop_mode_t bop_mode; -static pthread_mutex_t * msg_lock; +sem_t *bopmsg_sem = NULL; task_status_t BOP_task_status(void) { return task_status; @@ -64,9 +62,8 @@ char *strerror(int errnum); void bop_msg(int level, const char * msg, ...) { if(bop_verbose >= level) { - msg_init(); - if(msg_lock != NULL) - pthread_mutex_lock(msg_lock); + //msg_init(); + sem_wait(bopmsg_sem); va_list v; va_start(v,msg); fprintf(stderr, "%d-", getpid()); @@ -101,23 +98,23 @@ void bop_msg(int level, const char * msg, ...) { vfprintf(stderr,msg,v); fprintf(stderr,"\n"); fflush(stderr); - if(msg_lock != NULL) - pthread_mutex_unlock(msg_lock); + sem_post(bopmsg_sem); } } void msg_init(){ - if (!msg_lock){ - msg_lock = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); - pthread_mutexattr_t mutexAttr; - if(pthread_mutexattr_init(&mutexAttr)) perror("Couldn't create mutex attr"); - if(pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED)) perror("Error sharing mutex"); - if(pthread_mutex_init(msg_lock, &mutexAttr)) perror("Error creating shared msg mutex"); + if (!bopmsg_sem){ + bopmsg_sem = sem_open("/bopmsg.sem", (O_CREAT), S_IRWXO|S_IRWXU|S_IRWXG, 0); + if(bopmsg_sem == SEM_FAILED){ + printf("Error in BOP_Init: %s\n", strerror(errno)); + } + assert(bopmsg_sem != NULL); + assert(bopmsg_sem != SEM_FAILED); + sem_post(bopmsg_sem); } } void msg_destroy(){ - munmap(msg_lock, 0); - pthread_mutex_destroy(msg_lock); + sem_close(bopmsg_sem); } /* read the environment variable env, and returns it's integer value. From f9375cb155fa77024689cf97acb120a06aec378a Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Tue, 12 Apr 2016 12:21:06 -0400 Subject: [PATCH 03/37] format for abort spec --- bop_api.h | 4 ++-- bop_ppr.c | 21 +++++++-------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/bop_api.h b/bop_api.h index da5bd7f..4d20cca 100644 --- a/bop_api.h +++ b/bop_api.h @@ -85,7 +85,7 @@ void BOP_record_write(void* addr, size_t size); typedef void monitor_t (void *, size_t); /* Called by a speculation process in case of error. */ -void BOP_abort_spec( const char* msg ); +void BOP_abort_spec( const char* msg, ...) __attribute__ ((format (printf, 1, 2))); void BOP_abort_next_spec( char* msg ); /* FILE I/O */ @@ -175,7 +175,7 @@ size_t max_ppr_request; #define bop_msg(ignored, ...) printf( __VA_ARGS__ ) -#define BOP_abort_spec( msg ) +#define BOP_abort_spec( msg, ... ) #define BOP_abort_next_spec( msg ) #define BOP_abort_spec_group( msg ) #define bop_assert(x) assert(x) diff --git a/bop_ppr.c b/bop_ppr.c index 984484e..009a1b6 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -44,7 +44,6 @@ int monitor_group = 0; //the process group that PPR tasks are using static bool is_monitoring = false; static bool errored = false; -void BOP_abort_spec_2(bool, const char*); //only for in this function static void __attribute__((noreturn)) wait_process(void); static void __attribute__((noreturn)) end_clean(void); //exit if children errored or call abort static int cleanup_children(void); //returns the value that end_clean would call with _exit (or 0 if would have aborted) @@ -202,30 +201,24 @@ void BOP_malloc_rescue(char * msg, size_t size){ } _exit(0); //my sanity } -void BOP_abort_spec_2(bool really_abort, const char* msg){ +void __attribute__ ((format (printf, 1, 2))) BOP_abort_spec(const char* msg, ...){ if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) return; - + va_list argptr; + va_start(argptr,msg); if (task_status == MAIN) { /* non-mergeable actions have happened */ if ( partial_group_get_size() > 1 ) { - bop_msg(2, "Abort main speculation because %s", msg); + bop_msg(2, "Abort main speculation because %s", msg, argptr); partial_group_set_size( 1 ); } }else{ - bop_msg(2, "Abort alt speculation because %s", msg); + bop_msg(2, "Abort alt speculation because %s", msg, argptr); partial_group_set_size( spec_order ); signal_commit_done( ); - if(really_abort) - end_clean(); //_exit(0); /* die silently, but reap children*/ - else - bop_msg(2, "WARNING: Not calling abort to preserve exit values"); + end_clean(); //_exit(0); /* die silently, but reap children*/ } } -void BOP_abort_spec( const char *msg ) { - BOP_abort_spec_2(true, msg); //original behavior -} - void BOP_abort_next_spec( char *msg ) { if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) @@ -770,7 +763,7 @@ static void BOP_fini(void) { bop_msg(3, "An exit is reached in %s mode", status_name()); switch (task_status) { case SPEC: - BOP_abort_spec_2(true, "SPEC reached an exit"); /* will abort */ + BOP_abort_spec("SPEC reached an exit"); /* will abort */ signal(SIGUSR2, SIG_IGN); kill(0, SIGUSR2); //send SIGUSR to spec group but not ourself-> own group //everything is termininating From 870dce5a13162a0547120edbc8b224d73f3156b2 Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Tue, 12 Apr 2016 17:12:57 -0400 Subject: [PATCH 04/37] remove old semaphore --- utils.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/utils.c b/utils.c index 8bb1d10..e4c1c15 100644 --- a/utils.c +++ b/utils.c @@ -15,8 +15,6 @@ extern int ppr_index; extern int spec_order; extern bop_mode_t bop_mode; -sem_t *bopmsg_sem = NULL; - task_status_t BOP_task_status(void) { return task_status; } @@ -63,7 +61,6 @@ void bop_msg(int level, const char * msg, ...) { if(bop_verbose >= level) { //msg_init(); - sem_wait(bopmsg_sem); va_list v; va_start(v,msg); fprintf(stderr, "%d-", getpid()); @@ -98,23 +95,13 @@ void bop_msg(int level, const char * msg, ...) { vfprintf(stderr,msg,v); fprintf(stderr,"\n"); fflush(stderr); - sem_post(bopmsg_sem); } } void msg_init(){ - if (!bopmsg_sem){ - bopmsg_sem = sem_open("/bopmsg.sem", (O_CREAT), S_IRWXO|S_IRWXU|S_IRWXG, 0); - if(bopmsg_sem == SEM_FAILED){ - printf("Error in BOP_Init: %s\n", strerror(errno)); - } - assert(bopmsg_sem != NULL); - assert(bopmsg_sem != SEM_FAILED); - sem_post(bopmsg_sem); - } + } void msg_destroy(){ - sem_close(bopmsg_sem); } /* read the environment variable env, and returns it's integer value. From f4a63b9efe07cc179b08a933cf9c7713376bea90 Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Tue, 19 Apr 2016 11:23:34 -0400 Subject: [PATCH 05/37] Add BOP_ordered ports Close #21 Add a port called when entering ordered region and another for exiting the region --- bop_api.h | 2 +- bop_ordered.c | 8 ++++++-- bop_ports.c | 16 ++++++++++++++++ bop_ports.h | 2 ++ bop_ppr_sync.h | 2 ++ dmmalloc.c | 2 +- 6 files changed, 28 insertions(+), 4 deletions(-) diff --git a/bop_api.h b/bop_api.h index 4d20cca..28b7f6e 100644 --- a/bop_api.h +++ b/bop_api.h @@ -7,7 +7,7 @@ #ifndef NDEBUG /* We want the task status while debugging->bop_msg **/ -#define bop_debug(x, ...) bop_msg(1, "%s:%d " x "\n" , __FILE__, __LINE__, ##__VA_ARGS__); +#define bop_debug(x, ...) bop_msg(1, "%s:%d " x "" , __FILE__, __LINE__, ##__VA_ARGS__); #else #define bop_debug(...) #endif diff --git a/bop_ordered.c b/bop_ordered.c index 24585df..3e344dd 100644 --- a/bop_ordered.c +++ b/bop_ordered.c @@ -5,6 +5,7 @@ #include "bop_ports.h" #include "external/malloc.h" #include "postwait.h" +#include "bop_ppr_sync.h" extern mspace metacow_space; @@ -29,6 +30,7 @@ void BOP_ordered_begin( addr_t id ) { bop_msg( 2, "Entering ordered region "PRIdPTR, id ); addr_t my_ch = channel_for_region( id ); channel_wait( my_ch - 1 ); + on_enter_ordered(); } else bop_msg( 2, "Currently in ordered region "PRIdPTR". BOP_ordered_region( "PRIdPTR" ) ignored.", ordered_region_id, id ); @@ -47,19 +49,21 @@ static void fill_range( void *sum, mem_range_t *range ) { void BOP_ordered_end( addr_t id ) { if ( in_ordered_region && ordered_region_id == id ) { - bop_msg( 2, "Leaving ordered region "PRIdPTR, id ); + bop_msg( 2, "Leaving ordered region %"PRIdPTR, id ); addr_t my_ch = channel_for_region( id ); map_inject( & ordered_writes, (void *) my_ch, fill_range ); channel_post( my_ch ); + on_exit_ordered(); map_clear( & ordered_writes ); in_ordered_region = 0; + } else bop_msg( 2, "No matching ordered region (%d "PRIdPTR"). BOP_ordered_end( "PRIdPTR" ) ignored.", in_ordered_region, ordered_region_id, id ); } static void ppr_reset( void ) { - if ( ordered_writes.residence == NULL ) + if ( ordered_writes.residence == NULL ) init_empty_map( & ordered_writes, metacow_space, "ordered_writes" ); else map_clear( & ordered_writes ); diff --git a/bop_ports.c b/bop_ports.c index bfc57b6..30f6390 100644 --- a/bop_ports.c +++ b/bop_ports.c @@ -96,6 +96,22 @@ void undy_succ_fini( void ) { } } +void on_exit_ordered( void ) { + int i; + for (i = 0; i < num_ports; i ++) { + if (bop_ports[i]->on_exit_ordered!=NULL) + port_call( bop_ports[i]->on_exit_ordered ); + } +} + +void on_enter_ordered( void ) { + int i; + for (i = 0; i < num_ports; i ++) { + if (bop_ports[i]->on_enter_ordered!=NULL) + port_call( bop_ports[i]->on_enter_ordered ); + } +} + /* Port code gen. See [compiler repos]/tools/scripts/codegen.rb methods = ["ppr_group_init", "ppr_task_init", "spec_check", "data_commit", "task_group_commit", "task_group_succ_fini", "undy_init", "undy_succ_fini"] diff --git a/bop_ports.h b/bop_ports.h index 98067cb..557ee54 100644 --- a/bop_ports.h +++ b/bop_ports.h @@ -13,6 +13,8 @@ typedef struct { void (*task_group_succ_fini)( void ); void (*undy_init)( void ); void (*undy_succ_fini)( void ); + void (*on_enter_ordered) (void); + void (*on_exit_ordered) (void); } bop_port_t; void register_port( bop_port_t *port, char * desc ); diff --git a/bop_ppr_sync.h b/bop_ppr_sync.h index b244079..eee19c4 100644 --- a/bop_ppr_sync.h +++ b/bop_ppr_sync.h @@ -24,6 +24,8 @@ void undy_succ_fini( void ); void ppr_group_init( void ); void ppr_task_init( void ); int ppr_check_correctness( void ); +void on_exit_ordered(void); +void on_enter_ordered(void); /* void report_conflict( void ); Name conflicts with something in utils.h */ void data_commit( void ); void task_group_commit( void ); diff --git a/dmmalloc.c b/dmmalloc.c index d69cd95..784967a 100644 --- a/dmmalloc.c +++ b/dmmalloc.c @@ -375,7 +375,7 @@ static inline header * get_header (size_t size, int *which) { if ( !SEQUENTIAL() && found != NULL){ //this will be useless in sequential mode, and useless if found == NULL if(ends[temp] != NULL && CAST_UH(found) == ends[temp]->free.next) { - bop_msg(3, "Something may have gone wrong:\n value of ends[which]: %p\t value of which: %d", ends[temp], temp); + bop_msg(3, "Something may have gone wrong: value of ends[which]: %p\t value of which: %d", ends[temp], temp); found = NULL; } } From ae61a0bad9247bf5a63e0dc06565cbf7503f57b3 Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Sat, 30 Apr 2016 13:57:38 -0400 Subject: [PATCH 06/37] Allow for external error reporter --- bop_ppr.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/bop_ppr.c b/bop_ppr.c index 009a1b6..c9f7c43 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -55,6 +55,8 @@ static void unblock_wait(void); //Semaphore msg init extern void msg_init(); +void (*external_reporter)(const char *, ...); + static void _ppr_group_init( void ) { bop_msg( 3, "task group starts (gs %d)", BOP_get_group_size() ); @@ -390,7 +392,7 @@ void BOP_this_group_over(){ _BOP_group_over(ppr_static_id); } void _BOP_ppr_end(int id) { - bop_msg(1, "Reached PPR end (pid %d)", getpid()); + bop_msg(2, "Reached PPR end (pid %d)", getpid()); if (ppr_pos == GAP || ppr_static_id != id) { bop_msg(4, "Unmatched end PPR (region %d in/after region %d) ignored", id, ppr_static_id); return; @@ -457,17 +459,19 @@ void print_backtrace(void){ bop_msg(1, "\nEND BACKTRACE"); } void ErrorKillAll(int signo){ + static const char * msg_f = "Error caught signal %d"; //don't need to reap children. We know that it's an erroring-exit, //intecept the call, allert monitor process, execute def behavior /**Horrible things are happening. Go to SEQ mode so malloc won't have issues*/ - bop_msg(1, "ERROR CAUGHT %d", signo); - int om = bop_mode; malloc_panic = true; - print_backtrace(); + if(external_reporter != NULL) + external_reporter(msg_f, signo); + else{ + bop_msg(1, msg_f, signo); + print_backtrace(); + } error_alert_monitor(); - signal(signo, SIG_DFL); - raise(signo); - bop_mode = om; + exit(-1); } void SigUsr1(int signo, siginfo_t *siginfo, ucontext_t *cntxt) { assert( SIGUSR1 == signo ); @@ -544,9 +548,9 @@ int report_child(pid_t child, int status){ // is_monitoring = false; // } if(val != -1) - bop_msg(1, msg, child, val); + bop_msg(2, msg, child, val); else - bop_msg(1, msg, child); + bop_msg(2, msg, child); return rval; } static inline void block_wait(){ @@ -796,7 +800,7 @@ static void BOP_fini(void) { gettimeofday(&tv, NULL); double bop_end_time = tv.tv_sec+(tv.tv_usec/1000000.0); - bop_msg( 1, "\n***BOP Report***\n The total run time is %.2lf seconds. There were %d ppr tasks, %d executed speculatively and %d non-speculatively (%d by main and %d by understudy). pid %d\n", + bop_msg(0, "\n***BOP Report***\n The total run time is %.2lf seconds. There were %d ppr tasks, %d executed speculatively and %d non-speculatively (%d by main and %d by understudy). pid %d\n", bop_end_time - bop_stats.start_time, ppr_index, bop_stats.num_by_spec, bop_stats.num_by_undy + bop_stats.num_by_main, bop_stats.num_by_main, bop_stats.num_by_undy, getpid()); From 94c9e87171b318d4f0dffbff8b1c177ecb788148 Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Sat, 30 Apr 2016 14:54:33 -0400 Subject: [PATCH 07/37] Cleanup makefile, lower ending bop_report msg level --- .gitignore | 2 ++ Makefile | 54 ++++++++++++++++-------------------------------------- bop_ppr.c | 2 +- 3 files changed, 19 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index e2af728..5ace650 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ wrapper_test malloc_test *.o inst.a +*.d +*.d.tmp diff --git a/Makefile b/Makefile index 3c9b1f0..f655824 100644 --- a/Makefile +++ b/Makefile @@ -3,52 +3,32 @@ ifeq ($(CC), cc) CC = gcc endif -CI ?= false -ifeq ($(CI), true) - CI_FLAGS = -D CI_BUILD -else - CI_FLAGS = -U CI_BUILD -endif - -BUILD_DIR ?= . -_OBJS = malloc_wrapper.o dmmalloc.o ary_bitmap.o postwait.o bop_merge.o \ - range_tree/dtree.o bop_ppr.o utils.o external/malloc.o \ - bop_ppr_sync.o bop_io.o bop_ports.o bop_ordered.o libc_overrides.o key_value_checks.o - -CFLAGS_DEF = -Wall -g -fPIC -pthread -I. -Wno-unused-function $(PLATFORM) $(CUSTOMDEF) $(CI_FLAGS) +CFLAGS = -Wall -g -fPIC -pthread -I. -Wno-unused-function $(CUSTOMDEF) CUSTOMDEF = -D USE_DL_PREFIX -D BOP -D USE_LOCKS -D UNSUPPORTED_MALLOC LDFLAGS = -Wl,--no-as-needed -ldl OPITIMIZEFLAGS = -O3 DEBUG_FLAGS = -ggdb3 -g3 -pg -D CHECK_COUNTS -U NDEBUG LIB = inst.a -LIB_SO = $(BUILD_DIR)/inst.a -OBJS = $(patsubst %,$(BUILD_DIR)/%,$(_OBJS)) -_HEADERS = $(wildcard *.h) $(wildcard external/*.h) $(wildcard range_tree/*.h) -HEADERS = $(patsubst %,$(BUILD_DIR)/%,$(_HEADERS)) +SRC := $(wildcard *.c) $(wildcard external/*.c) $(wildcard range_tree/*.c) +OBJS = $(SRC:.c=.o) -DEBUG ?= 1 -ifeq ($(DEBUG), 1) - CFLAGS = $(CFLAGS_DEF) $(DEBUG_FLAGS) -else - CFLAGS = $(CFLAGS_DEF) $(OPITIMIZEFLAGS) -endif TEST_DIRS = add sleep str/BOP_string str/strsub str/strsub2 -library: print_info $(LIB_SO) # $(HEADERS) +library: print_info $(LIB) print_info: - @echo Build info debug build = $(DEBUG) @echo cc = $(CC) @echo CFLAGS = $(CFLAGS) @echo LDFLAGS = $(LDFLAGS) @echo OBJS = $(OBJS) + test: library - for dir in $(TEST_DIRS) ; do \ + @for dir in $(TEST_DIRS) ; do \ echo $$dir ; \ cd tests/$$dir ; \ rake ; \ @@ -56,24 +36,22 @@ test: library cd -; \ done -$(LIB_SO): $(OBJS) - @echo building archive "$(LIB_SO)" - @ar r $(LIB_SO) $(OBJS) - @ranlib $(LIB_SO) +$(LIB): $(OBJS) + @echo building archive "$(LIB)" + @ar r $(LIB) $(OBJS) + @ranlib $(LIB) all: $(OBJS) -$(BUILD_DIR)/%.o: %.c - @mkdir -p $(@D) - @echo compiling $^ - @$(CC) -c -o $@ $^ $(CFLAGS) +-include $(OBJS:.o=.d) -$(BUILD_DIR)/%.h: %.h - @mkdir -p $(@D) - @cp $^ $@ +%.o: %.c + @echo compiling $^ + @gcc -MM $(CFLAGS) $^ > $*.d + @gcc -c -o $@ $^ $(CFLAGS) clean: - rm -f $(OBJS) $(LIB_SO) + rm -f $(OBJS) $(LIB) *.d *.d.tmp for dir in $(TEST_DIRS) ; do \ echo $$dir ; \ cd tests/$$dir ; \ diff --git a/bop_ppr.c b/bop_ppr.c index c9f7c43..1a10cc0 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -800,7 +800,7 @@ static void BOP_fini(void) { gettimeofday(&tv, NULL); double bop_end_time = tv.tv_sec+(tv.tv_usec/1000000.0); - bop_msg(0, "\n***BOP Report***\n The total run time is %.2lf seconds. There were %d ppr tasks, %d executed speculatively and %d non-speculatively (%d by main and %d by understudy). pid %d\n", + bop_msg(1, "\n***BOP Report***\n The total run time is %.2lf seconds. There were %d ppr tasks, %d executed speculatively and %d non-speculatively (%d by main and %d by understudy). pid %d\n", bop_end_time - bop_stats.start_time, ppr_index, bop_stats.num_by_spec, bop_stats.num_by_undy + bop_stats.num_by_main, bop_stats.num_by_main, bop_stats.num_by_undy, getpid()); From 98619b23e97623d16a835efa6fe7559e1c80f554 Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Sat, 30 Apr 2016 15:07:29 -0400 Subject: [PATCH 08/37] Increase DM Block size --- dmmalloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmmalloc.h b/dmmalloc.h index dc8861f..6d4a479 100644 --- a/dmmalloc.h +++ b/dmmalloc.h @@ -48,7 +48,7 @@ void malloc_merge_counts(bool); //counts get updated AFTER abort status is known //malloc config macros #ifndef DM_BLOCK_SIZE -#define DM_BLOCK_SIZE 500 +#define DM_BLOCK_SIZE 750 #endif //alignement/ header macros From 025139fac12ae8d63b67f970196a677b075f97eb Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Sat, 30 Apr 2016 21:51:00 -0400 Subject: [PATCH 09/37] Refactor dmmalloc headers far simpler to read --- Makefile | 4 +- dmmalloc.c | 126 +++++++++++++++++++++++++++++------------------------ dmmalloc.h | 34 ++++++++------- 3 files changed, 90 insertions(+), 74 deletions(-) diff --git a/Makefile b/Makefile index f655824..ed9ba5d 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ endif CFLAGS = -Wall -g -fPIC -pthread -I. -Wno-unused-function $(CUSTOMDEF) -CUSTOMDEF = -D USE_DL_PREFIX -D BOP -D USE_LOCKS -D UNSUPPORTED_MALLOC +CUSTOMDEF = -D USE_DL_PREFIX -D BOP -D USE_LOCKS -D UNSUPPORTED_MALLOC -D DM_DEBUG LDFLAGS = -Wl,--no-as-needed -ldl OPITIMIZEFLAGS = -O3 DEBUG_FLAGS = -ggdb3 -g3 -pg -D CHECK_COUNTS -U NDEBUG @@ -43,7 +43,7 @@ $(LIB): $(OBJS) all: $(OBJS) --include $(OBJS:.o=.d) +# -include $(OBJS:.o=.d) %.o: %.c @echo compiling $^ diff --git a/dmmalloc.c b/dmmalloc.c index 784967a..18c5791 100644 --- a/dmmalloc.c +++ b/dmmalloc.c @@ -160,7 +160,7 @@ static int* count_lists(bool is_locked){ header * head; for(i = 0; i < DM_NUM_CLASSES; i++){ loc_count = 0; - for(head = headers[i]; head; head = CAST_H(head->free.next)) + for(head = headers[i]; head; head = CAST_H(head->next)) loc_count ++; counts[i] = loc_count; } @@ -195,14 +195,14 @@ void carve () { bop_assert(count > 0); for (r = 0; r < tasks; r++) { regions[r].start[index] = current_headers[index]; - temp = CAST_H (current_headers[index]->free.next); + temp = CAST_H (current_headers[index]->next); for (j = 0; j < count && temp; j++) { - temp = CAST_H(temp->free.next); + temp = CAST_H(temp->next); } current_headers[index] = temp; // the last task has no tail, use the same as seq. exectution bop_assert (temp != (header*) -1); - regions[r].end[index] = temp != NULL ? CAST_H (temp->free.prev) : NULL; + regions[r].end[index] = temp != NULL ? CAST_H (temp->prev) : NULL; bop_assert(regions[r].start[index] != regions[r].end[index]); } } @@ -231,7 +231,7 @@ void initialize_group () { #ifndef NDEBUG for(ind = 0; ind < DM_NUM_CLASSES; ind++){ bop_assert(headers[ind] != NULL); - bop_assert(headers[ind]->free.next != NULL); + bop_assert(headers[ind]->next != NULL); } #endif } @@ -246,18 +246,18 @@ void malloc_promise() { int i; int allocs = 0, frees = 0; for(i = 0; i < DM_NUM_CLASSES; i++){ - for(head = allocated_lists[i]; head != NULL; head = CAST_H(head->allocated.next)){ - BOP_promise(head, head->allocated.blocksize); //playload matters + for(head = allocated_lists[i]; head != NULL; head = CAST_H(head->next)){ + BOP_promise(head, head->blocksize); //playload matters allocs++; } } for(i=0; i < DM_NUM_CLASSES; i++){ - for(head = freedlist[i]; head != NULL; head = CAST_H(head->free.next)){ + for(head = freedlist[i]; head != NULL; head = CAST_H(head->next)){ BOP_promise(head, HSIZE); //payload doesn't matter frees++; } } - for(head = large_free_list; head != NULL; head = CAST_H(head->free.next)){ + for(head = large_free_list; head != NULL; head = CAST_H(head->next)){ BOP_promise(head, HSIZE); //payload doesn't matter frees++; } @@ -272,18 +272,18 @@ void dm_malloc_undy_init(){ header * current, * next; int ind; for(ind = 0; ind < DM_NUM_CLASSES; ind++){ - for(current = freedlist[ind]; current != NULL; current = CAST_H(current->free.next)){ + for(current = freedlist[ind]; current != NULL; current = CAST_H(current->next)){ dm_free(PAYLOAD(current)); } freedlist[ind] = NULL; } - for(current = large_free_list; current != NULL; current = CAST_H(current->free.next)){ + for(current = large_free_list; current != NULL; current = CAST_H(current->next)){ dm_free(PAYLOAD(current)); } for(ind = 0; ind < DM_NUM_CLASSES; ind++){ for(current = allocated_lists[ind]; current != NULL; current = next){ - next = CAST_H(current->allocated.next); - current->allocated.next = NULL; + next = CAST_H(current->next); + current->next = NULL; } allocated_lists[ind] = NULL; } @@ -340,11 +340,11 @@ static inline void grow (const int tasks) { // add_next_list( &headers[class_index], head); if(list_top == NULL){ headers[class_index] = head; - head->free.next = head->free.prev = NULL; + head->next = head->prev = NULL; } else{ - head->free.next = CAST_UH(list_top); - list_top->free.prev = CAST_UH(head); + head->next = CAST_UH(list_top); + list_top->prev = CAST_UH(head); headers[class_index] = head; } } @@ -353,9 +353,9 @@ static inline void grow (const int tasks) { if(grow_count > 1){ //ensure that this list is not a giant loop header * current; - for(current = CAST_H(headers[class_index]->free.next); current; current = CAST_H(current->free.next)){ + for(current = CAST_H(headers[class_index]->next); current; current = CAST_H(current->next)){ bop_assert(current != headers[class_index]); - bop_assert(current != CAST_H(current->free.next)); + bop_assert(current != CAST_H(current->next)); } } #endif @@ -374,7 +374,7 @@ static inline header * get_header (size_t size, int *which) { found = headers[temp]; if ( !SEQUENTIAL() && found != NULL){ //this will be useless in sequential mode, and useless if found == NULL - if(ends[temp] != NULL && CAST_UH(found) == ends[temp]->free.next) { + if(ends[temp] != NULL && CAST_UH(found) == ends[temp]->next) { bop_msg(3, "Something may have gone wrong: value of ends[which]: %p\t value of which: %d", ends[temp], temp); found = NULL; } @@ -412,7 +412,7 @@ void *dm_malloc (const size_t size) { return NULL; } //don't need to add to free list, just set information - block->allocated.blocksize = alloc_size; + block->blocksize = alloc_size; goto checks; }else{ //not SEQUENTIAL(), and allocating a too-large block. Might be able to rescue @@ -433,9 +433,10 @@ void *dm_malloc (const size_t size) { //bop_abort } } - block->allocated.blocksize = size_of_klass(which); - bop_assert (headers[which] != CAST_H (block->free.next)); - headers[which] = CAST_H (block->free.next); //remove from free list + block->blocksize = size_of_klass(which); + SET_ALLOCATED(block, true); + bop_assert (headers[which] != CAST_H (block->next)); + headers[which] = CAST_H (block->next); //remove from free list // Write allocated next information if( !SEQUENTIAL()){ bop_assert(which != -1); //valid because -1 == too large, can't do in PPR @@ -482,14 +483,16 @@ static inline header* dm_split (int which, int larger) { //split-specific info sets // headers[which] = split; // was null PPR Safe - headers[larger] = CAST_H (headers[larger]->free.next); //PPR Safe + headers[larger] = CAST_H (headers[larger]->next); //PPR Safe //remove split up block - block->allocated.blocksize = size_of_klass(which); + block->blocksize = size_of_klass(which); + SET_ALLOCATED(block, true); - block->free.next = CAST_UH (split); - split->free.next = split->free.prev = NULL; - bop_assert (block->allocated.blocksize != 0); + block->next = CAST_UH (split); + split->next = split->prev = NULL; + + bop_assert (block->blocksize != 0); which++; #ifndef NDEBUG if (get_header(size_of_klass(which), NULL) == NULL && which != larger) @@ -507,7 +510,8 @@ static inline header* dm_split (int which, int larger) { headers[which] = split; }else{ //go through dm_free - split->allocated.blocksize = size_of_klass(which); + split->blocksize = size_of_klass(which); + SET_ALLOCATED(split, true); release_lock(); //need to let dm_free have the lock dm_free(PAYLOAD(split)); } @@ -521,7 +525,7 @@ void * dm_calloc (size_t n, size_t size) { char *allocd = dm_malloc (size * n); if(allocd != NULL){ head = HEADER(allocd); - assert(head->allocated.blocksize >= (size*n)); + assert(head->blocksize >= (size*n)); memset (allocd, 0, size * n); ASSERTBLK(HEADER(allocd)); } @@ -529,7 +533,7 @@ void * dm_calloc (size_t n, size_t size) { } // Reallocator: use sytem realloc with large->large sizes in SEQUENTIAL() mode. Otherwise use standard realloc implementation -void * dm_realloc (const void *ptr, size_t gsize) { +void * dm_realloc (void *ptr, size_t gsize) { header* old_head, * new_head; size_t new_size = ALIGN(gsize + HSIZE), old_size; if(gsize == 0) @@ -541,26 +545,30 @@ void * dm_realloc (const void *ptr, size_t gsize) { } old_head = HEADER (ptr); - +#ifdef DM_REM_ALLOC + if(old_head->allocated == false) + ErrorKillAll(-1); +#endif ASSERTBLK(old_head); - old_size = old_head->allocated.blocksize; + old_size = old_head->blocksize; int new_index = get_index (new_size); - if (new_index != -1 && size_of_klass(new_index) <= old_head->allocated.blocksize) { - return (void*) ptr; //no need to update - } else if (SEQUENTIAL() && old_head->allocated.blocksize > MAX_SIZE && new_size > MAX_SIZE) { + if (new_index != -1 && size_of_klass(new_index) <= old_head->blocksize) { + return ptr; //no need to update + } else if (SEQUENTIAL() && old_head->blocksize > MAX_SIZE && new_size > MAX_SIZE) { //use system realloc in SEQUENTIAL() mode for large->large blocks new_head = sys_realloc (old_head, new_size); - new_head->allocated.blocksize = new_size; //sytem block - new_head->allocated.next = NULL; + new_head->blocksize = new_size; //sytem block + new_head->next = NULL; + SET_ALLOCATED(new_head, true); ASSERTBLK (new_head); return PAYLOAD (new_head); } else { //build off malloc and free ASSERTBLK(old_head); - size_t size_cache = old_head->allocated.blocksize; + size_t size_cache = old_head->blocksize; //we're reallocating within managed memory void* new_payload = dm_malloc(gsize); //malloc will tweak size again. @@ -571,11 +579,11 @@ void * dm_realloc (const void *ptr, size_t gsize) { //copy the data size_t copy_size = MIN(old_size, new_size) - HSIZE; // block sizes include the header! assert(copy_size != new_size - HSIZE); - bop_assert( HEADER(new_payload)->allocated.blocksize >= (copy_size + HSIZE)); //check dm_malloc gave enough space + bop_assert( HEADER(new_payload)->blocksize >= (copy_size + HSIZE)); //check dm_malloc gave enough space new_payload = memcpy(new_payload, ptr, copy_size); // copy data - bop_assert( ((header *)HEADER(new_payload))->allocated.blocksize >= copy_size); + bop_assert( ((header *)HEADER(new_payload))->blocksize >= copy_size); ASSERTBLK(old_head); - bop_assert(old_head->allocated.blocksize == size_cache); + bop_assert(old_head->blocksize == size_cache); dm_free( (void*) ptr); return new_payload; @@ -592,10 +600,16 @@ void dm_free (void *ptr) { header *free_header = HEADER (ptr); ASSERTBLK(free_header); get_lock(); +#ifdef DM_REM_ALLOC + if(free_header->allocated == false){ + ErrorKillAll(-1); + } +#endif if(SEQUENTIAL() || remove_from_alloc_list (free_header)){ release_lock(); free_now (free_header); } else{ + SET_ALLOCATED(free_header, false); add_freed_list(free_header); } @@ -604,7 +618,7 @@ void dm_free (void *ptr) { //free a (regular or huge) block now. all saftey checks must be done before calling this function static inline void free_now (header * head) { int which; - size_t size = head->allocated.blocksize; + size_t size = head->blocksize; ASSERTBLK(head); bop_assert (size >= HSIZE && size == ALIGN (size)); //size is aligned, ie right value was written //test for system block @@ -627,13 +641,13 @@ static inline void free_now (header * head) { bop_assert (size_of_klass(which) == size); //should exactly align if (free_stack == NULL) { //empty free_stack - head->free.next = head->free.prev = NULL; + head->next = head->prev = NULL; headers[which] = head; release_lock(); return; } - free_stack->free.prev = CAST_UH (head); - head->free.next = CAST_UH (free_stack); + free_stack->prev = CAST_UH (head); + head->next = CAST_UH (free_stack); headers[which] = head; release_lock(); @@ -642,7 +656,7 @@ inline size_t dm_malloc_usable_size(void* ptr) { if(ptr == NULL) return 0; header *free_header = HEADER (ptr); - size_t head_size = free_header->allocated.blocksize; + size_t head_size = free_header->blocksize; if(head_size > MAX_SIZE){ head_size = sys_malloc_usable_size(free_header); } @@ -652,13 +666,13 @@ inline size_t dm_malloc_usable_size(void* ptr) { static bool remove_from_alloc_list (header * val) { //remove val from the list header* current, * prev = NULL; - const int index = get_index(val->allocated.blocksize); - for(current = allocated_lists[index]; current; prev = current, current = CAST_H(current->allocated.next)) { + const int index = get_index(val->blocksize); + for(current = allocated_lists[index]; current; prev = current, current = CAST_H(current->next)) { if(current == val) { if(prev == NULL){ - allocated_lists[index] = CAST_H(current->allocated.next); + allocated_lists[index] = CAST_H(current->next); }else{ - prev->allocated.next = CAST_UH(current->allocated.next); + prev->next = CAST_UH(current->next); } return true; } @@ -670,7 +684,7 @@ static inline bool list_contains (header * list, header * search_value) { if (list == NULL || search_value == NULL) return false; header *current; - for (current = list; current != NULL; current = CAST_H (current->free.next)) { + for (current = list; current != NULL; current = CAST_H (current->next)) { if (current == search_value) return true; } @@ -685,19 +699,19 @@ static inline void add_next_list (header** list_head, header * item) { if(!SEQUENTIAL()) nseq_added_n++; bop_assert(*list_head != item); - item->allocated.next = CAST_UH(*list_head); //works even if *list_head == NULL + item->next = CAST_UH(*list_head); //works even if *list_head == NULL *list_head = item; } static inline void add_freed_list(header* item){ - size_t size = item->allocated.blocksize; + size_t size = item->blocksize; int index = get_index(size); if(index >= DM_NUM_CLASSES){ add_next_list(&large_free_list, item); } - item->free.next = CAST_UH(freedlist[index]); + item->next = CAST_UH(freedlist[index]); if(freedlist[index]){ - freedlist[index]->free.prev = CAST_UH(item); + freedlist[index]->prev = CAST_UH(item); } freedlist[index] = item; } diff --git a/dmmalloc.h b/dmmalloc.h index 6d4a479..beba9be 100644 --- a/dmmalloc.h +++ b/dmmalloc.h @@ -1,28 +1,30 @@ #ifndef DM_MALLOC_H #define DM_MALLOC_H -#define DM_DEBUG #include #include //dm structs, unions etc -typedef union { - //NOTE: the two nexts must be the same address for some utility functions in dmmalloc.c - struct { - union header * next; // ppr-allocated object list - size_t blocksize; // which free list to insert freed items into - } allocated; - struct { - //doubly linked free list for partioning - union header * next; - union header * prev; - - } free; +typedef struct { + struct header * next; +#ifdef DM_REM_ALLOC + bool allocated; +#endif + union{ + size_t blocksize; + struct header * prev; + }; } header; +#ifdef DM_REM_ALLOC +#define SET_ALLOCATED(h,a) (h->allocated = a) +#else +#define SET_ALLOCATED(h,a) +#endif + //prototypes void * dm_malloc(size_t); -void * dm_realloc(const void *, size_t); +void * dm_realloc(void *, size_t); void dm_free(void *); void * dm_calloc(size_t, size_t); void dm_print_info(void); @@ -55,12 +57,12 @@ void malloc_merge_counts(bool); //counts get updated AFTER abort status is known #define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~(ALIGNMENT-1)) #define HSIZE (ALIGN((sizeof(header)))) #define HEADER(vp) ((header *) (((char *) (vp)) - HSIZE)) -#define CAST_UH(h) ((union header *) (h)) +#define CAST_UH(h) ((struct header *) (h)) #define CAST_H(h) ((header*) (h)) #define CHARP(p) (((char*) (p))) #define PAYLOAD(hp) ((header *) (((char *) (hp)) + HSIZE)) #define PTR_MATH(ptr, d) ((CHARP(ptr)) + d) -#define ASSERTBLK(head) bop_assert ((head)->allocated.blocksize > 0); +#define ASSERTBLK(head) bop_assert ((head)->blocksize > 0); //class size macros #define DM_NUM_CLASSES 16 From ec3e05de5ad274d31490be4611fbecb1c59838e9 Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Sun, 1 May 2016 14:52:42 -0400 Subject: [PATCH 10/37] Properly support printf-like message in abort spec --- bop_api.h | 6 ++--- bop_ppr.c | 34 +++++++++++++++++--------- utils.c | 72 ++++++++++++++++++++++++++++++------------------------- 3 files changed, 65 insertions(+), 47 deletions(-) diff --git a/bop_api.h b/bop_api.h index 28b7f6e..b3568e9 100644 --- a/bop_api.h +++ b/bop_api.h @@ -86,7 +86,7 @@ typedef void monitor_t (void *, size_t); /* Called by a speculation process in case of error. */ void BOP_abort_spec( const char* msg, ...) __attribute__ ((format (printf, 1, 2))); -void BOP_abort_next_spec( char* msg ); +void BOP_abort_next_spec( char* msg, ... ) __attribute__ ((format (printf, 1, 2))); /* FILE I/O */ int BOP_printf(const char *format, ...); @@ -176,8 +176,8 @@ size_t max_ppr_request; #define bop_msg(ignored, ...) printf( __VA_ARGS__ ) #define BOP_abort_spec( msg, ... ) -#define BOP_abort_next_spec( msg ) -#define BOP_abort_spec_group( msg ) +#define BOP_abort_next_spec( msg, ...) +#define BOP_abort_spec_group( msg, ... ) #define bop_assert(x) assert(x) #include diff --git a/bop_ppr.c b/bop_ppr.c index 1a10cc0..461e9d1 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -27,6 +27,7 @@ extern bop_port_t bop_merge_port; extern bop_port_t postwait_port; extern bop_port_t bop_ordered_port; extern bop_port_t bop_alloc_port; +extern void bop_msg_va(int level, const char * msg, va_list v); volatile task_status_t task_status = SEQ; volatile ppr_pos_t ppr_pos = GAP; @@ -203,30 +204,41 @@ void BOP_malloc_rescue(char * msg, size_t size){ } _exit(0); //my sanity } +static inline void abort_printf(const char * abrt_msg, const char * usr_msg, + va_list argptr){ + char buffer[strlen(usr_msg) + strlen(abrt_msg) + 2] ; + size_t size = sizeof(buffer); + size_t written = snprintf(buffer, sizeof(buffer), "%s %s", abrt_msg, usr_msg); + assert(written < size); + bop_msg_va(2, buffer, argptr); +} + void __attribute__ ((format (printf, 1, 2))) BOP_abort_spec(const char* msg, ...){ - if (task_status == SEQ - || task_status == UNDY || bop_mode == SERIAL) + if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) return; - va_list argptr; - va_start(argptr,msg); + va_list argptr; + va_start(argptr,msg); if (task_status == MAIN) { /* non-mergeable actions have happened */ if ( partial_group_get_size() > 1 ) { - bop_msg(2, "Abort main speculation because %s", msg, argptr); + abort_printf("Abort main speculation because", msg, argptr); + va_end(argptr); partial_group_set_size( 1 ); } }else{ - bop_msg(2, "Abort alt speculation because %s", msg, argptr); + abort_printf("Abort alt speculation because", msg, argptr); + va_end(argptr); partial_group_set_size( spec_order ); signal_commit_done( ); end_clean(); //_exit(0); /* die silently, but reap children*/ } } -void BOP_abort_next_spec( char *msg ) { - if (task_status == SEQ - || task_status == UNDY || bop_mode == SERIAL) +void __attribute__ ((format (printf, 1, 2))) BOP_abort_next_spec( char *msg, ... ) { + if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) return; - - bop_msg(2, "Abort next speculation because %s", msg); + va_list argptr; + va_start(argptr,msg); + abort_printf("Abort next speculation because", msg, argptr); + va_end(argptr); if (task_status == MAIN) /* non-mergeable actions have happened */ partial_group_set_size( 1 ); else diff --git a/utils.c b/utils.c index e4c1c15..a6f2c0d 100644 --- a/utils.c +++ b/utils.c @@ -57,44 +57,50 @@ extern char in_ordered_region; // bop_ordered.c extern int errno; char *strerror(int errnum); +void bop_msg_va(int level, const char * msg, va_list v){ + if(bop_verbose >= level) { + fprintf(stderr, "%d-", getpid()); + char *pos; + switch (ppr_pos) { + case PPR: + pos = ""; + break; + case GAP: + pos = "g"; + break; + default: + assert(0); + } + if (in_ordered_region) { + assert( ppr_pos == PPR ); + pos = "od"; + } + unsigned pidx = BOP_ppr_index( ); + switch(task_status) { + case UNDY: fprintf(stderr, "Undy-(idx %d%s): ", pidx, pos); break; + case MAIN: fprintf(stderr, "Main-%d(idx %d%s): ", spec_order, pidx, pos); break; + case SEQ: fprintf(stderr, "Seq-(idx %d%s): ", pidx, pos); break; + case SPEC: fprintf(stderr, "Spec-%d(idx %d%s): ", spec_order, pidx, pos); break; + } + struct timeval tv; + gettimeofday(&tv, NULL); + double curr_time = tv.tv_sec + (tv.tv_usec/1000000.0); + if (bop_stats.start_time != 0) + fprintf(stderr, " (%.6lfs) ", curr_time - bop_stats.start_time); + + vfprintf(stderr,msg,v); + fprintf(stderr,"\n"); + fflush(stderr); + } +} + void bop_msg(int level, const char * msg, ...) { if(bop_verbose >= level) { - //msg_init(); va_list v; va_start(v,msg); - fprintf(stderr, "%d-", getpid()); - char *pos; - switch (ppr_pos) { - case PPR: - pos = ""; - break; - case GAP: - pos = "g"; - break; - default: - assert(0); - } - if (in_ordered_region) { - assert( ppr_pos == PPR ); - pos = "od"; - } - unsigned pidx = BOP_ppr_index( ); - switch(task_status) { - case UNDY: fprintf(stderr, "Undy-(idx %d%s): ", pidx, pos); break; - case MAIN: fprintf(stderr, "Main-%d(idx %d%s): ", spec_order, pidx, pos); break; - case SEQ: fprintf(stderr, "Seq-(idx %d%s): ", pidx, pos); break; - case SPEC: fprintf(stderr, "Spec-%d(idx %d%s): ", spec_order, pidx, pos); break; - } - struct timeval tv; - gettimeofday(&tv, NULL); - double curr_time = tv.tv_sec + (tv.tv_usec/1000000.0); - if (bop_stats.start_time != 0) - fprintf(stderr, " (%.6lfs) ", curr_time - bop_stats.start_time); - - vfprintf(stderr,msg,v); - fprintf(stderr,"\n"); - fflush(stderr); + bop_msg_va(level, msg, v); + va_end(v); } } From ec88c1d3cd703fb5ba438292f6d8fc00de1e8fe1 Mon Sep 17 00:00:00 2001 From: Ben O'Halloran Date: Sun, 1 May 2016 23:29:06 -0400 Subject: [PATCH 11/37] Fix deadlock issue --- dmmalloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dmmalloc.c b/dmmalloc.c index 18c5791..bb53af2 100644 --- a/dmmalloc.c +++ b/dmmalloc.c @@ -409,6 +409,7 @@ void *dm_malloc (const size_t size) { block = sys_malloc (alloc_size); if (block == NULL) { //ERROR: ran out of system memory. malloc rescue won't help + release_lock(); return NULL; } //don't need to add to free list, just set information From 2de76f974465c72fb77a92df82d7a4839438ab79 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Fri, 17 Jun 2016 03:48:42 -0400 Subject: [PATCH 12/37] Joel's initial commit --- .gitignore | 2 +- Makefile | 2 +- add.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 add.c diff --git a/.gitignore b/.gitignore index 5ace650..5970676 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ wrapper_test malloc_test *.o -inst.a +libinst.a *.d *.d.tmp diff --git a/Makefile b/Makefile index ed9ba5d..b8a2ff4 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ CUSTOMDEF = -D USE_DL_PREFIX -D BOP -D USE_LOCKS -D UNSUPPORTED_MALLOC -D DM_DEB LDFLAGS = -Wl,--no-as-needed -ldl OPITIMIZEFLAGS = -O3 DEBUG_FLAGS = -ggdb3 -g3 -pg -D CHECK_COUNTS -U NDEBUG -LIB = inst.a +LIB = libinst.a SRC := $(wildcard *.c) $(wildcard external/*.c) $(wildcard range_tree/*.c) diff --git a/add.c b/add.c new file mode 100644 index 0000000..e2af2f7 --- /dev/null +++ b/add.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include + +#include "bop_api.h" + +/* The program makes an array of randomly initialized integers and adds them together. */ + +static double *data; +static int datasize; + +static double sum; + +int main(int argc, char ** argv) +{ + int _blocksize; + int _parallelism; + + /* processing the input */ + if (argc>3 || argc<2) { + printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); + exit(1); + } + datasize = (int) (atof(argv[1])*1000000); + assert(datasize>0); + _parallelism = atoi(argv[2]); + assert(_parallelism>0); + + /* Initialization */ + printf("%d: initializing %d million numbers\n", getpid(), datasize/1000000); + + data = (double *) malloc(datasize*sizeof(double)); + for (int i = 0; i < datasize; i++) + data[i] = i; + + printf("%d: adding %d million numbers\n", getpid(), datasize/1000000); + + _blocksize = ceil((float)datasize/_parallelism); + + + for (int i=0; i datasize? datasize:i+_blocksize; + double sump = 0.0; + BOP_record_read(data + i, (_n - i) * sizeof(*data)); + for (int _j=i; _j<_n; _j++) { + sump += sin(data[_j])*sin(data[_j])+cos(data[_j])*cos(data[_j]); + + } + BOP_ordered_begin(2); + BOP_record_read(&sum, sizeof(sum)); + BOP_record_write(&sum, sizeof(sum)); + sum += sump; + BOP_ordered_end(2); + BOP_ppr_end(1); + } + + printf("%d: %d million numbers added. The sum is %.0f million (%.0f) \n", getpid(), datasize/1000000, sum/1000000, sum); + + return 0; +} From 0287edbb1171c6241292b1a47a4c95e9bd7c3bc9 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Fri, 17 Jun 2016 04:09:05 -0400 Subject: [PATCH 13/37] Undo --- .gitignore | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5970676..5ace650 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ wrapper_test malloc_test *.o -libinst.a +inst.a *.d *.d.tmp diff --git a/Makefile b/Makefile index b8a2ff4..ed9ba5d 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ CUSTOMDEF = -D USE_DL_PREFIX -D BOP -D USE_LOCKS -D UNSUPPORTED_MALLOC -D DM_DEB LDFLAGS = -Wl,--no-as-needed -ldl OPITIMIZEFLAGS = -O3 DEBUG_FLAGS = -ggdb3 -g3 -pg -D CHECK_COUNTS -U NDEBUG -LIB = libinst.a +LIB = inst.a SRC := $(wildcard *.c) $(wildcard external/*.c) $(wildcard range_tree/*.c) From 64de78438f3ab836ded3119f4207f26f0162c8f7 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Fri, 17 Jun 2016 04:09:24 -0400 Subject: [PATCH 14/37] Add test --- tests/parallel_alloc/add_ppr_only.c | 78 +++++++++++++++++++++++++++++ tests/parallel_alloc/rakefile | 8 +++ 2 files changed, 86 insertions(+) create mode 100644 tests/parallel_alloc/add_ppr_only.c create mode 100755 tests/parallel_alloc/rakefile diff --git a/tests/parallel_alloc/add_ppr_only.c b/tests/parallel_alloc/add_ppr_only.c new file mode 100644 index 0000000..bc57ba5 --- /dev/null +++ b/tests/parallel_alloc/add_ppr_only.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +/* The program makes an array of randomly initialized integers and adds them together. */ + +#include "bop_api.h" + +static void +initialize(double *array, size_t len) +{ + for (size_t i = 0; i < len; ++i) { + array[i] = sin(i)*sin(i) + cos(i)*cos(i); + } +} + +static double +get_sum(double *array, size_t len) +{ + double sum = 0; + for (size_t i = 0; i < len; ++i) { + sum += array[i]; + } + return sum; +} + +int +main(int argc, char ** argv) +{ + int data_size, num_blocks; + int block_size; + + /* processing the input */ + if (argc>3 || argc<2) { + printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); + exit(1); + } + data_size = (int) (atof(argv[1])*1000000); + assert(data_size>0); + num_blocks = atoi(argv[2]); + assert(num_blocks>0); + + printf("%d: adding %d million numbers\n", getpid(), data_size/1000000); + block_size = ceil((float)data_size / num_blocks); + + + double sums[num_blocks]; + double *blocks[num_blocks]; + memset(&sums, 0, num_blocks * sizeof(double)); + for (size_t i = 0; i < num_blocks; ++i) { + blocks[i] = malloc(block_size * sizeof(double)); + assert(blocks[i] != NULL); + } + + int index = 0; + while (data_size > 0) { + int block_end = data_size; + data_size -= block_size; + int block_begin = data_size >= 0 ? data_size : 0 ; + double *block = blocks[index]; + assert(block != NULL); + + BOP_ppr_begin(1); /* Begin PPR */ + + initialize(block, block_end - block_begin); + BOP_promise(block, (block_end - block_begin) * sizeof(*block)); + + sums[index] = get_sum(block, block_end - block_begin); + BOP_promise(&sums[index], sizeof(double)); + + BOP_ppr_end(1); /* End PPR */ + index++; + } + + printf("%d: The sum is %.0f million (%.0f) \n", getpid(), sum/1000000, sum); + return 0; +} diff --git a/tests/parallel_alloc/rakefile b/tests/parallel_alloc/rakefile new file mode 100755 index 0000000..0675f18 --- /dev/null +++ b/tests/parallel_alloc/rakefile @@ -0,0 +1,8 @@ +load '../bop_test.rake' + +$c_flags = '-g3' + +$params = '20 4' + +bop_test 'add', nil, false # Orig version fails +bop_test 'add_ppr_only' From 09ecaa66d35e6c177c2de62f309762c7a6e573b7 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Fri, 17 Jun 2016 04:25:41 -0400 Subject: [PATCH 15/37] Add test --- Makefile | 2 +- tests/parallel_alloc/add_ppr_only.c | 6 ++++++ tests/parallel_alloc/rakefile | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ed9ba5d..4f94d48 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ SRC := $(wildcard *.c) $(wildcard external/*.c) $(wildcard range_tree/*.c) OBJS = $(SRC:.c=.o) -TEST_DIRS = add sleep str/BOP_string str/strsub str/strsub2 +TEST_DIRS = add sleep str/BOP_string str/strsub str/strsub2 parallel_alloc library: print_info $(LIB) diff --git a/tests/parallel_alloc/add_ppr_only.c b/tests/parallel_alloc/add_ppr_only.c index bc57ba5..c1a490c 100644 --- a/tests/parallel_alloc/add_ppr_only.c +++ b/tests/parallel_alloc/add_ppr_only.c @@ -2,6 +2,10 @@ #include #include #include +#include + +#include +#include /* The program makes an array of randomly initialized integers and adds them together. */ @@ -73,6 +77,8 @@ main(int argc, char ** argv) index++; } + double sum = get_sum(sums, num_blocks); + printf("%d: The sum is %.0f million (%.0f) \n", getpid(), sum/1000000, sum); return 0; } diff --git a/tests/parallel_alloc/rakefile b/tests/parallel_alloc/rakefile index 0675f18..a5f6d43 100755 --- a/tests/parallel_alloc/rakefile +++ b/tests/parallel_alloc/rakefile @@ -2,7 +2,7 @@ load '../bop_test.rake' $c_flags = '-g3' -$params = '20 4' +$params = '200 2' -bop_test 'add', nil, false # Orig version fails +# bop_test 'add', nil, false # Orig version fails bop_test 'add_ppr_only' From 86588431b2652cd973e4d2a3acefe3c2d66f70d8 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 22 Jun 2016 08:40:57 -0400 Subject: [PATCH 16/37] Update tests --- .gitignore | 1 + add.c | 66 ----------------------------- tests/parallel_alloc/add_ppr_only.c | 12 ++---- 3 files changed, 5 insertions(+), 74 deletions(-) delete mode 100644 add.c diff --git a/.gitignore b/.gitignore index 5ace650..ded91d0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ wrapper_test malloc_test *.o inst.a +libinst.a *.d *.d.tmp diff --git a/add.c b/add.c deleted file mode 100644 index e2af2f7..0000000 --- a/add.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "bop_api.h" - -/* The program makes an array of randomly initialized integers and adds them together. */ - -static double *data; -static int datasize; - -static double sum; - -int main(int argc, char ** argv) -{ - int _blocksize; - int _parallelism; - - /* processing the input */ - if (argc>3 || argc<2) { - printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); - exit(1); - } - datasize = (int) (atof(argv[1])*1000000); - assert(datasize>0); - _parallelism = atoi(argv[2]); - assert(_parallelism>0); - - /* Initialization */ - printf("%d: initializing %d million numbers\n", getpid(), datasize/1000000); - - data = (double *) malloc(datasize*sizeof(double)); - for (int i = 0; i < datasize; i++) - data[i] = i; - - printf("%d: adding %d million numbers\n", getpid(), datasize/1000000); - - _blocksize = ceil((float)datasize/_parallelism); - - - for (int i=0; i datasize? datasize:i+_blocksize; - double sump = 0.0; - BOP_record_read(data + i, (_n - i) * sizeof(*data)); - for (int _j=i; _j<_n; _j++) { - sump += sin(data[_j])*sin(data[_j])+cos(data[_j])*cos(data[_j]); - - } - BOP_ordered_begin(2); - BOP_record_read(&sum, sizeof(sum)); - BOP_record_write(&sum, sizeof(sum)); - sum += sump; - BOP_ordered_end(2); - BOP_ppr_end(1); - } - - printf("%d: %d million numbers added. The sum is %.0f million (%.0f) \n", getpid(), datasize/1000000, sum/1000000, sum); - - return 0; -} diff --git a/tests/parallel_alloc/add_ppr_only.c b/tests/parallel_alloc/add_ppr_only.c index c1a490c..78ea872 100644 --- a/tests/parallel_alloc/add_ppr_only.c +++ b/tests/parallel_alloc/add_ppr_only.c @@ -48,30 +48,26 @@ main(int argc, char ** argv) printf("%d: adding %d million numbers\n", getpid(), data_size/1000000); block_size = ceil((float)data_size / num_blocks); - double sums[num_blocks]; - double *blocks[num_blocks]; memset(&sums, 0, num_blocks * sizeof(double)); - for (size_t i = 0; i < num_blocks; ++i) { - blocks[i] = malloc(block_size * sizeof(double)); - assert(blocks[i] != NULL); - } int index = 0; while (data_size > 0) { int block_end = data_size; data_size -= block_size; int block_begin = data_size >= 0 ? data_size : 0 ; - double *block = blocks[index]; - assert(block != NULL); BOP_ppr_begin(1); /* Begin PPR */ + double *block = malloc((block_end - block_begin) * sizeof(*block)); + assert(block != NULL); initialize(block, block_end - block_begin); BOP_promise(block, (block_end - block_begin) * sizeof(*block)); + BOP_use(block, (block_end - block_begin) * sizeof(*block)); sums[index] = get_sum(block, block_end - block_begin); BOP_promise(&sums[index], sizeof(double)); + free(block); BOP_ppr_end(1); /* End PPR */ index++; From 40b26f912c4b5da30fb4c6f193e117b119614392 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 22 Jun 2016 09:18:21 -0400 Subject: [PATCH 17/37] Fix formatting in dmmalloc.[ch] --- dmmalloc.c | 921 +++++++++++++++++++++++++++-------------------------- dmmalloc.h | 61 ++-- 2 files changed, 496 insertions(+), 486 deletions(-) diff --git a/dmmalloc.c b/dmmalloc.c index bb53af2..12bd024 100644 --- a/dmmalloc.c +++ b/dmmalloc.c @@ -1,13 +1,13 @@ #ifndef NDEBUG -#include //commas numbers (debug information) +#include // Commas numbers(debug information) #endif -#include //print errors -#include //mutex -#include //system malloc & free -#include //memcopy -#include //debug -#include //boolean types -#include //get page size +#include // Print errors +#include // Mutex +#include // System malloc & free +#include // Memcopy +#include // Debug +#include // Boolean types +#include // Get page size #include "dmmalloc.h" #include "malloc_wrapper.h" #include "bop_api.h" @@ -24,9 +24,9 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) -short malloc_panic = 0; //force sequential allocation rules +short malloc_panic = 0; // Force sequential allocation rules -//BOP macros & structures +// BOP macros & structures #define SEQUENTIAL() (malloc_panic || bop_mode == SERIAL || BOP_task_status() == SEQ || BOP_task_status() == UNDY) typedef struct { @@ -35,24 +35,24 @@ typedef struct { } ppr_list; static ppr_list *regions = NULL; -//header info -static header *headers[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; //current heads of free lists -static header* ends[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; //end of lists in PPR region - -static header* freedlist[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; //list of items freed during PPR-mode. -static header* large_free_list = NULL; -static header* allocated_lists[DM_NUM_CLASSES]= {[0 ... DM_NUM_CLASSES - 1] = NULL}; //list of items allocated during PPR-mode NOTE: info of allocated block - -//helper prototypes -static inline int get_index (size_t); -static inline void grow (int); -static inline void free_now (header *); -static inline bool list_contains (header * list, header * item); -static bool remove_from_alloc_list (header *); -static inline void add_next_list (header**, header *); -static inline void add_freed_list (header*); -static inline header *dm_split (int which, int larger); -static inline int index_bigger (int); +// Header info +static header *headers[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; // Current heads of free lists +static header *ends[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; // End of lists in PPR region + +static header *freedlist[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; // List of items freed during PPR-mode. +static header *large_free_list = NULL; +static header *allocated_lists[DM_NUM_CLASSES]= {[0 ... DM_NUM_CLASSES - 1] = NULL}; // List of items allocated during PPR-mode NOTE: info of allocated block + +// Helper prototypes +static inline int get_index(size_t); +static inline void grow(int); +static inline void free_now(header *); +static inline bool list_contains(header *list, header *item); +static bool remove_from_alloc_list(header *); +static inline void add_next_list(header **, header *); +static inline void add_freed_list(header *); +static inline header *dm_split(int which, int larger); +static inline int index_bigger(int); static inline size_t align(size_t size, size_t align); static inline void get_lock(); static inline void release_lock(); @@ -70,69 +70,75 @@ static int split_gave_head[DM_NUM_CLASSES]; #define FORCE_INLINE inline __attribute__((always_inline)) - /** x86 assembly code for computing the log2 of a value. - This is much faster than math.h log2*/ + This is much faster than math.h log2*/ static inline int llog2(const int x) { int y; - __asm__ ( "\tbsr %1, %0\n" + __asm__( "\tbsr %1, %0\n" : "=r"(y) : "r" (x) ); return y; } + /**Note: This is the INDEX of the old array of the class index, ie param 0 * means SIZE class 1. The original implementation had an array that had these values*/ -const FORCE_INLINE size_t size_of_klass(int klass_index){ - return SIZE_C(klass_index + 1); +const FORCE_INLINE size_t size_of_klass(int klass_index) { + return SIZE_C(klass_index + 1); } -const FORCE_INLINE int goal_blocks(int klass){ - switch(klass){ - case 0 ... 3: - return DM_BLOCK_SIZE * 10; - case 4 ... 12: - return DM_BLOCK_SIZE; - case 13 ... 16: - return MAX(DM_BLOCK_SIZE / (klass - 8), 1); - default: - return 1; - } + +const FORCE_INLINE int goal_blocks(int klass) { + switch(klass) { + case 0 ... 3: + return DM_BLOCK_SIZE * 10; + case 4 ... 12: + return DM_BLOCK_SIZE; + case 13 ... 16: + return MAX(DM_BLOCK_SIZE / (klass - 8), 1); + default: + return 1; + } } -static int * goal_counts(){ - static int goal[DM_NUM_CLASSES] = {[0 ... (DM_NUM_CLASSES -1)] = -1}; - int ind; - if( goal[0] == -1) - for(ind = 0; ind < DM_NUM_CLASSES; ind++) - goal[ind] = goal_blocks(ind); + +static int *goal_counts() { + static int goal[DM_NUM_CLASSES] = {[0 ... (DM_NUM_CLASSES - 1)] = -1}; + int ind; + if (goal[0] == -1) + for (ind = 0; ind < DM_NUM_CLASSES; ind++) + goal[ind] = goal_blocks(ind); return goal; } -void dm_check(void* payload) { - if(payload == NULL) - return; - header* head = HEADER (payload); - ASSERTBLK (head); + +void dm_check(void *payload) { + if (payload == NULL) + return; + header *head = HEADER(payload); + ASSERTBLK(head); } + static inline size_t align(size_t size, size_t alignment) { int log = LOG(alignment); bop_assert(alignment == (1 << log)); - return (((size) + (alignment-1)) & ~(alignment-1)); + return(((size) + (alignment-1)) & ~(alignment-1)); } + /**Get the index corresponding to the given size. If size > MAX_SIZE, then return -1*/ -static inline int get_index (size_t size) { - bop_assert (size == ALIGN (size)); - bop_assert (size >= HSIZE); - //Space is too big. +static inline int get_index(size_t size) { + bop_assert(size == ALIGN(size)); + bop_assert(size >= HSIZE); + // Space is too big. if (size > MAX_SIZE) - return -1; //too big + return -1; // Too big int index = LOG(size) - DM_CLASS_OFFSET - 1; if (index == -1 || size_of_klass(index) < size) // this is how it gets rounded up only if needed index++; - bop_assert (index >= 0 && index < DM_NUM_CLASSES); - bop_assert (size_of_klass(index) >= size); //this size class is large enough - bop_assert (index == 0 || size_of_klass(index - 1) < size); //using the minimal valid size class + bop_assert(index >= 0 && index < DM_NUM_CLASSES); + bop_assert(size_of_klass(index) >= size); // This size class is large enough + bop_assert(index == 0 || size_of_klass(index - 1) < size); // Using the minimal valid size class return index; } + /**Locking functions*/ #ifdef USE_LOCKS static pthread_mutex_t lock; @@ -146,142 +152,141 @@ static inline void release_lock() { #warning "Dmmalloc malloc not locking for thread" static inline void get_lock() {/*Do nothing*/} static inline void release_lock() {/*Do nothing*/} -#endif //use locks +#endif // Use locks /** Bop-related functionss*/ /** Divide up the currently allocated groups into regions. - Insures that each task will have a percentage of a SEQUENTIAL() goal*/ - -static int* count_lists(bool is_locked){ - static int counts[DM_NUM_CLASSES]; - int i, loc_count; - if( ! is_locked) - get_lock(); - header * head; - for(i = 0; i < DM_NUM_CLASSES; i++){ - loc_count = 0; - for(head = headers[i]; head; head = CAST_H(head->next)) - loc_count ++; - counts[i] = loc_count; - } - if( ! is_locked ) - release_lock(); - return counts; + Insures that each task will have a percentage of a SEQUENTIAL() goal*/ + +static int *count_lists(bool is_locked) { + static int counts[DM_NUM_CLASSES]; + int i, loc_count; + if (!is_locked) + get_lock(); + header *head; + for (i = 0; i < DM_NUM_CLASSES; i++) { + loc_count = 0; + for (head = headers[i]; head; head = CAST_H(head->next)) + loc_count++; + counts[i] = loc_count; + } + if (!is_locked) + release_lock(); + return counts; } /** BOP Port functions */ -void carve () { - bop_assert(SEQUENTIAL()); - int tasks = BOP_get_group_size(); - if( regions != NULL){ - dm_free(regions); //dm_free -> don't have lock - } - regions = dm_calloc (tasks, sizeof (ppr_list) ); - get_lock(); //now locked - grow(tasks); //need to already have the lock - - int * counts = count_lists(true); // true -> we have the lock - bop_assert (tasks >= 2); - - int index, count, j, r; - header *current_headers[DM_NUM_CLASSES]; - header *temp = (header*) -1; - for (index = 0; index < DM_NUM_CLASSES; index++) - current_headers[index] = CAST_H (headers[index]); - //actually split the lists - for (index = 0; index < DM_NUM_CLASSES; index++) { - bop_assert(counts[index] > 0); - count = counts[index] / tasks; - bop_assert(count > 0); - for (r = 0; r < tasks; r++) { - regions[r].start[index] = current_headers[index]; - temp = CAST_H (current_headers[index]->next); - for (j = 0; j < count && temp; j++) { - temp = CAST_H(temp->next); - } - current_headers[index] = temp; - // the last task has no tail, use the same as seq. exectution - bop_assert (temp != (header*) -1); - regions[r].end[index] = temp != NULL ? CAST_H (temp->prev) : NULL; - bop_assert(regions[r].start[index] != regions[r].end[index]); +void carve() { + bop_assert(SEQUENTIAL()); + int tasks = BOP_get_group_size(); + if (regions != NULL) { + dm_free(regions); // Dm_free -> don't have lock } - } - release_lock(); + regions = dm_calloc(tasks, sizeof(ppr_list)); + get_lock(); // Now locked + grow(tasks); // Need to already have the lock + + int *counts = count_lists(true); // true -> we have the lock + bop_assert(tasks >= 2); + + int index, count, j, r; + header *current_headers[DM_NUM_CLASSES]; + header *temp = (header *)-1; + for (index = 0; index < DM_NUM_CLASSES; index++) + current_headers[index] = CAST_H(headers[index]); + // Actually split the lists + for (index = 0; index < DM_NUM_CLASSES; index++) { + bop_assert(counts[index] > 0); + count = counts[index] / tasks; + bop_assert(count > 0); + for (r = 0; r < tasks; r++) { + regions[r].start[index] = current_headers[index]; + temp = CAST_H(current_headers[index]->next); + for (j = 0; j < count && temp; j++) { + temp = CAST_H(temp->next); + } + current_headers[index] = temp; + // the last task has no tail, use the same as seq. exectution + bop_assert(temp != (header *)-1); + regions[r].end[index] = temp != NULL ? CAST_H(temp->prev) : NULL; + bop_assert(regions[r].start[index] != regions[r].end[index]); + } + } + release_lock(); } /**set the range of values to be used by this PPR task*/ -void initialize_group () { - bop_msg(2,"DM Malloc initializing spec task %d", spec_order); - // bop_assert(! SEQUENTIAL() ); - int group_num = spec_order; - ppr_list my_list = regions[group_num]; - int ind; - for (ind = 0; ind < DM_NUM_CLASSES; ind++) { - ends[ind] = my_list.end[ind]; - if(task_status != MAIN) - headers[ind] = my_list.start[ind]; - if(group_num != 0){ - bop_assert(headers[ind] != NULL); - }else{ - bop_assert(task_status == MAIN); - } - bop_assert(headers[ind] != ends[ind]); - // bop_msg(3, "DM malloc task %d header[%d] = %p", spec_order, ind, headers[ind]); - } +void initialize_group() { + bop_msg(2, "DM Malloc initializing spec task %d", spec_order); + // bop_assert(! SEQUENTIAL() ); + int group_num = spec_order; + ppr_list my_list = regions[group_num]; + int ind; + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { + ends[ind] = my_list.end[ind]; + if (task_status != MAIN) + headers[ind] = my_list.start[ind]; + if (group_num != 0) { + bop_assert(headers[ind] != NULL); + } else { + bop_assert(task_status == MAIN); + } + bop_assert(headers[ind] != ends[ind]); + // bop_msg(3, "DM malloc task %d header[%d] = %p", spec_order, ind, headers[ind]); + } #ifndef NDEBUG - for(ind = 0; ind < DM_NUM_CLASSES; ind++){ - bop_assert(headers[ind] != NULL); - bop_assert(headers[ind]->next != NULL); - } + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { + bop_assert(headers[ind] != NULL); + bop_assert(headers[ind]->next != NULL); + } #endif } - /** Merge 1) Promise everything in both allocated and free list */ -//NOTE: only the heads should be promised. The payloads should be the job of the caller? +// NOTE: only the heads should be promised. The payloads should be the job of the caller? void malloc_promise() { - header* head; + header *head; int i; int allocs = 0, frees = 0; - for(i = 0; i < DM_NUM_CLASSES; i++){ - for(head = allocated_lists[i]; head != NULL; head = CAST_H(head->next)){ - BOP_promise(head, head->blocksize); //playload matters - allocs++; - } - } - for(i=0; i < DM_NUM_CLASSES; i++){ - for(head = freedlist[i]; head != NULL; head = CAST_H(head->next)){ - BOP_promise(head, HSIZE); //payload doesn't matter - frees++; - } + for (i = 0; i < DM_NUM_CLASSES; i++) { + for (head = allocated_lists[i]; head != NULL; head = CAST_H(head->next)) { + BOP_promise(head, head->blocksize); // Playload matters + allocs++; + } + } + for (i = 0; i < DM_NUM_CLASSES; i++) { + for (head = freedlist[i]; head != NULL; head = CAST_H(head->next)) { + BOP_promise(head, HSIZE); // Payload doesn't matter + frees++; + } } - for(head = large_free_list; head != NULL; head = CAST_H(head->next)){ - BOP_promise(head, HSIZE); //payload doesn't matter - frees++; + for (head = large_free_list; head != NULL; head = CAST_H(head->next)) { + BOP_promise(head, HSIZE); // Payload doesn't matter + frees++; } bop_msg(3, "Number of promised frees: \t%d", frees); bop_msg(3, "Number of promised allocs: \t%d", allocs); } -void dm_malloc_undy_init(){ - return; //TODO this method should actually work, but it causes Travis to fail. - //called when the under study begins. Free everything in the freed list +void dm_malloc_undy_init() { + return; // TODO this method should actually work, but it causes Travis to fail. + // Called when the under study begins. Free everything in the freed list bop_assert(SEQUENTIAL()); - header * current, * next; + header *current, *next; int ind; - for(ind = 0; ind < DM_NUM_CLASSES; ind++){ - for(current = freedlist[ind]; current != NULL; current = CAST_H(current->next)){ + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { + for (current = freedlist[ind]; current != NULL; current = CAST_H(current->next)) { dm_free(PAYLOAD(current)); } freedlist[ind] = NULL; } - for(current = large_free_list; current != NULL; current = CAST_H(current->next)){ + for (current = large_free_list; current != NULL; current = CAST_H(current->next)) { dm_free(PAYLOAD(current)); } - for(ind = 0; ind < DM_NUM_CLASSES; ind++){ - for(current = allocated_lists[ind]; current != NULL; current = next){ + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { + for (current = allocated_lists[ind]; current != NULL; current = next) { next = CAST_H(current->next); current->next = NULL; } @@ -289,71 +294,71 @@ void dm_malloc_undy_init(){ } } -static inline void grow (const int tasks) { - //THIS IS THE NEW GROW FUNCTION! +static inline void grow(const int tasks) { + // THIS IS THE NEW GROW FUNCTION! int class_index, blocks_left, size; - if(tasks > 1) + if (tasks > 1) bop_debug("growing tasks = %d", tasks); #ifndef NDEBUG grow_count++; #endif - int * goal_counts_arr = goal_counts(); - //compute the number of blocks to allocate + int *goal_counts_arr = goal_counts(); + // Compute the number of blocks to allocate // size_t growth = HSIZE; int blocks[DM_NUM_CLASSES]; - int * counts = count_lists(true); //we have the lock - for(class_index = 0; class_index < DM_NUM_CLASSES; class_index++) { + int *counts = count_lists(true); // We have the lock + for (class_index = 0; class_index < DM_NUM_CLASSES; class_index++) { blocks_left = tasks * goal_counts_arr[class_index] - counts[class_index]; - blocks[class_index] = blocks_left >= 0 ? blocks_left : 0; + blocks[class_index] = blocks_left >= 0 ? blocks_left : 0; // growth += blocks[class_index] * size_of_klass(class_index); } - header * head, * list_top; + header *head, *list_top; - char* space_head; + char *space_head; int current_block; - char * debug_ptr; + char *debug_ptr; for (class_index = 0; class_index < DM_NUM_CLASSES; class_index++) { size = size_of_klass(class_index); - space_head = sys_calloc (blocks[class_index], size); //system malloc, use byte-sized type - bop_assert (blocks[class_index] == 0 || space_head != NULL); //ran out of sys memory + space_head = sys_calloc(blocks[class_index], size); // system malloc, use byte-sized type + bop_assert(blocks[class_index] == 0 || space_head != NULL); // Ran out of sys memory - for(current_block = 0; current_block < blocks[class_index]; current_block++){ - //set up this space - head = (header *) & (space_head[current_block * size]); - //make sure the last B in the head is writtable + for (current_block = 0; current_block < blocks[class_index]; current_block++) { + // Set up this space + head = (header *)&space_head[current_block * size]; + // Make sure the last B in the head is writtable #ifndef NDEBUG - if(grow_count > 1){ /** Utilization tests */ - debug_ptr = (char*) head; - //check stack is growing correctly - bop_assert(current_block == 0 || - headers[class_index] == (header *) & space_head[(current_block - 1) * size]); - // calloc'd return & seperate from previous head - bop_assert( *debug_ptr == (char) 0); - // last byte is readable - bop_assert(current_block == blocks[class_index] - 1 || debug_ptr[size -1] == (char) 0); - //adjacent in memory to previous block - bop_assert( current_block == 0 || debug_ptr[-1] == 'x'); //previous byte is the last of the previous - debug_ptr[size - 1] = 'x'; //This is an array, so -1 since the highest array index is -1 than length - } + if (grow_count > 1) { /** Utilization tests */ + debug_ptr = (char *)head; + // Check stack is growing correctly + bop_assert(current_block == 0 || + headers[class_index] == (header *)&space_head[(current_block - 1) * size]); + // calloc'd return & seperate from previous head + bop_assert(*debug_ptr == (char)0); + // last byte is readable + bop_assert(current_block == blocks[class_index] - 1 || debug_ptr[size -1] == (char) 0); + // Adjacent in memory to previous block + bop_assert(current_block == 0 || debug_ptr[-1] == 'x'); // Previous byte is the last of the previous + debug_ptr[size - 1] = 'x'; // This is an array, so -1 since the highest array index is -1 than length + } #endif - list_top = headers[class_index]; - // add_next_list( &headers[class_index], head); - if(list_top == NULL){ - headers[class_index] = head; - head->next = head->prev = NULL; - } - else{ - head->next = CAST_UH(list_top); - list_top->prev = CAST_UH(head); - headers[class_index] = head; - } + list_top = headers[class_index]; + // add_next_list( &headers[class_index], head); + if (list_top == NULL) { + headers[class_index] = head; + head->next = head->prev = NULL; + } + else { + head->next = CAST_UH(list_top); + list_top->prev = CAST_UH(head); + headers[class_index] = head; + } } - //post-size class division checks + // Post-size class division checks #ifndef NDEBUG - if(grow_count > 1){ - //ensure that this list is not a giant loop - header * current; - for(current = CAST_H(headers[class_index]->next); current; current = CAST_H(current->next)){ + if (grow_count > 1) { + // Ensure that this list is not a giant loop + header *current; + for (current = CAST_H(headers[class_index]->next); current; current = CAST_H(current->next)) { bop_assert(current != headers[class_index]); bop_assert(current != CAST_H(current->next)); } @@ -363,229 +368,232 @@ static inline void grow (const int tasks) { } // Get the head of the free list. This uses get_index and additional logic for PPR execution -static inline header * get_header (size_t size, int *which) { - header* found = NULL; - int temp = -1; - if (size > MAX_SIZE) { - found = NULL; - temp = -1; - }else{ - temp = get_index (size); - found = headers[temp]; - if ( !SEQUENTIAL() && found != NULL){ - //this will be useless in sequential mode, and useless if found == NULL - if(ends[temp] != NULL && CAST_UH(found) == ends[temp]->next) { - bop_msg(3, "Something may have gone wrong: value of ends[which]: %p\t value of which: %d", ends[temp], temp); +static inline header *get_header(size_t size, int *which) { + header *found = NULL; + int temp = -1; + if (size > MAX_SIZE) { found = NULL; - } + temp = -1; + } else { + temp = get_index(size); + found = headers[temp]; + if (!SEQUENTIAL() && found != NULL) { + // This will be useless in sequential mode, and useless if found == NULL + if (ends[temp] != NULL && CAST_UH(found) == ends[temp]->next) { + bop_msg(3, "Something may have gone wrong: value of ends[which]: %p\t value of which: %d", ends[temp], temp); + found = NULL; + } + } } - } - if(which != NULL) - *which = temp; - return found; + if (which != NULL) + *which = temp; + return found; } + int alist_added = 0; extern void BOP_malloc_rescue(char *, size_t); + // BOP-safe malloc implementation based off of size classes. -void *dm_malloc (const size_t size) { - volatile header * block = NULL; - int which, bigger = -1; - size_t alloc_size; - if(size == 0) - return NULL; - - alloc_size = ALIGN (size + HSIZE); //same regardless of task_status - get_lock(); - //get the right header - malloc_begin: - which = -2; - block = get_header (alloc_size, &which); - bop_assert (which != -2); - if (block == NULL) { - //no item in list. Either correct list is empty OR huge block - if (alloc_size > MAX_SIZE) { - if(SEQUENTIAL()){ //WORKING! - //huge block always use system malloc - block = sys_malloc (alloc_size); - if (block == NULL) { - //ERROR: ran out of system memory. malloc rescue won't help - release_lock(); - return NULL; - } - //don't need to add to free list, just set information - block->blocksize = alloc_size; - goto checks; - }else{ - //not SEQUENTIAL(), and allocating a too-large block. Might be able to rescue - BOP_malloc_rescue("Large allocation in PPR", alloc_size); - goto malloc_begin; //try again - } - } else if (which < DM_NUM_CLASSES - 1 && (bigger = index_bigger (which)) != -1) { - block = dm_split (which, bigger); - ASSERTBLK(block); - } else if (SEQUENTIAL()) { - bop_msg(3, "Is in sequential. Growing"); - grow (1); - goto malloc_begin; - } else { - BOP_malloc_rescue("Need to grow the lists in non-SEQUENTIAL()", alloc_size); - //grow will happen at the next pass through... - goto malloc_begin; //try again - //bop_abort - } - } - block->blocksize = size_of_klass(which); - SET_ALLOCATED(block, true); - bop_assert (headers[which] != CAST_H (block->next)); - headers[which] = CAST_H (block->next); //remove from free list - // Write allocated next information - if( !SEQUENTIAL()){ - bop_assert(which != -1); //valid because -1 == too large, can't do in PPR - add_next_list(&allocated_lists[which], (header*) block); - } - checks: - ASSERTBLK(block); - release_lock(); - return PAYLOAD (block); +void *dm_malloc(const size_t size) { + volatile header * block = NULL; + int which, bigger = -1; + size_t alloc_size; + if (size == 0) + return NULL; + + alloc_size = ALIGN(size + HSIZE); // Same regardless of task_status + get_lock(); + // Get the right header +malloc_begin: + which = -2; + block = get_header(alloc_size, &which); + bop_assert(which != -2); + if (block == NULL) { + // No item in list. Either correct list is empty OR huge block + if (alloc_size > MAX_SIZE) { + if (SEQUENTIAL()) { // WORKING! + // Huge block always use system malloc + block = sys_malloc(alloc_size); + if (block == NULL) { + // ERROR: ran out of system memory. malloc rescue won't help + release_lock(); + return NULL; + } + // Don't need to add to free list, just set information + block->blocksize = alloc_size; + goto checks; + }else{ + // Not SEQUENTIAL(), and allocating a too-large block. Might be able to rescue + BOP_malloc_rescue("Large allocation in PPR", alloc_size); + goto malloc_begin; // Try again + } + } else if (which < DM_NUM_CLASSES - 1 && (bigger = index_bigger(which)) != -1) { + block = dm_split(which, bigger); + ASSERTBLK(block); + } else if (SEQUENTIAL()) { + bop_msg(3, "Is in sequential. Growing"); + grow(1); + goto malloc_begin; + } else { + BOP_malloc_rescue("Need to grow the lists in non-SEQUENTIAL()", alloc_size); + // Grow will happen at the next pass through... + goto malloc_begin; // Try again + // Bop_abort + } + } + block->blocksize = size_of_klass(which); + SET_ALLOCATED(block, true); + bop_assert(headers[which] != CAST_H(block->next)); + headers[which] = CAST_H(block->next); // Remove from free list + // Write allocated next information + if (!SEQUENTIAL()) { + bop_assert(which != -1); // Valid because -1 == too large, can't do in PPR + add_next_list(&allocated_lists[which], (header*) block); + } +checks: + ASSERTBLK(block); + release_lock(); + return PAYLOAD(block); } -void print_headers(){ - int ind; - for(ind = 0; ind < DM_NUM_CLASSES; ind++){ - bop_msg(1, "headers[%d] = %p get_header = %p", ind, headers[ind], get_header(size_of_klass(ind), NULL)); - } + +void print_headers() { + int ind; + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { + bop_msg(1, "headers[%d] = %p get_header = %p", ind, headers[ind], get_header(size_of_klass(ind), NULL)); + } } // Compute the index of the next lagest index > which st the index has a non-null headers -static inline int index_bigger (int which) { +static inline int index_bigger(int which) { if (which == -1) return -1; which++; int index; - while (which < DM_NUM_CLASSES) { - if (get_header(size_of_klass(which), &index) != NULL){ - return which; - } - which++; + while(which < DM_NUM_CLASSES) { + if (get_header(size_of_klass(which), &index) != NULL) { + return which; + } + which++; } return -1; } + // Repeatedly split a larger block into a block of the required size -static inline header* dm_split (int which, int larger) { - if(which > 15){ - bop_msg(3, "In large split"); - } +static inline header* dm_split(int which, int larger) { + if (which > 15) { + bop_msg(3, "In large split"); + } #ifndef NDEBUG split_attempts[which]++; split_gave_head[which]++; #endif - header *block = headers[larger]; //block to split up - header *split = CAST_H((CHARP (block) + size_of_klass(which))); //cut in half - bop_assert (block != split); - //split-specific info sets - - // headers[which] = split; // was null PPR Safe - headers[larger] = CAST_H (headers[larger]->next); //PPR Safe - //remove split up block + header *block = headers[larger]; // Block to split up + header *split = CAST_H((CHARP(block) + size_of_klass(which))); // Cut in half + bop_assert(block != split); + // Split-specific info sets + + // headers[which] = split; // was null PPR Safe + headers[larger] = CAST_H(headers[larger]->next); // PPR Safe + // Remove split up block block->blocksize = size_of_klass(which); SET_ALLOCATED(block, true); - - block->next = CAST_UH (split); + block->next = CAST_UH(split); split->next = split->prev = NULL; - bop_assert (block->blocksize != 0); + bop_assert(block->blocksize != 0); which++; #ifndef NDEBUG if (get_header(size_of_klass(which), NULL) == NULL && which != larger) multi_splits++; split_gave_head[which] += larger - which; #endif - bop_assert (which < DM_NUM_CLASSES); - while (which < larger) { - //update the headers - split = CAST_H ((CHARP (split) + size_of_klass(which - 1))); //which - 1 since only half of the block is used here. which -1 === size / 2 - // bop_msg(1, "Split addr %p val %c", split, *((char*) split)); - if(SEQUENTIAL()){ - assert(headers[which] == NULL); - memset (split, 0, HSIZE); - headers[which] = split; - }else{ - //go through dm_free - split->blocksize = size_of_klass(which); - SET_ALLOCATED(split, true); - release_lock(); //need to let dm_free have the lock - dm_free(PAYLOAD(split)); - } + bop_assert(which < DM_NUM_CLASSES); + while(which < larger) { + // Update the headers + split = CAST_H((CHARP(split) + size_of_klass(which - 1))); // Which - 1 since only half of the block is used here. which -1 === size / 2 + // bop_msg(1, "Split addr %p val %c", split, *((char*) split)); + if (SEQUENTIAL()) { + assert(headers[which] == NULL); + memset(split, 0, HSIZE); + headers[which] = split; + } else { + // Go through dm_free + split->blocksize = size_of_klass(which); + SET_ALLOCATED(split, true); + release_lock(); // Need to let dm_free have the lock + dm_free(PAYLOAD(split)); + } which++; } return block; } + // standard calloc using malloc -void * dm_calloc (size_t n, size_t size) { - header * head; - char *allocd = dm_malloc (size * n); - if(allocd != NULL){ +void *dm_calloc(size_t n, size_t size) { + header *head; + char *allocd = dm_malloc(size * n); + if (allocd != NULL) { head = HEADER(allocd); - assert(head->blocksize >= (size*n)); - memset (allocd, 0, size * n); - ASSERTBLK(HEADER(allocd)); - } + assert(head->blocksize >= (size * n)); + memset(allocd, 0, size * n); + ASSERTBLK(HEADER(allocd)); + } return allocd; } // Reallocator: use sytem realloc with large->large sizes in SEQUENTIAL() mode. Otherwise use standard realloc implementation -void * dm_realloc (void *ptr, size_t gsize) { - header* old_head, * new_head; +void *dm_realloc(void *ptr, size_t gsize) { + header *old_head, *new_head; size_t new_size = ALIGN(gsize + HSIZE), old_size; - if(gsize == 0) + if (gsize == 0) return NULL; - if(ptr == NULL) { + if (ptr == NULL) { new_head = HEADER(dm_malloc(gsize)); - ASSERTBLK (new_head); - return PAYLOAD (new_head); + ASSERTBLK(new_head); + return PAYLOAD(new_head); } - old_head = HEADER (ptr); + old_head = HEADER(ptr); #ifdef DM_REM_ALLOC - if(old_head->allocated == false) - ErrorKillAll(-1); + if (old_head->allocated == false) + ErrorKillAll(-1); #endif ASSERTBLK(old_head); old_size = old_head->blocksize; - int new_index = get_index (new_size); + int new_index = get_index(new_size); if (new_index != -1 && size_of_klass(new_index) <= old_head->blocksize) { - return ptr; //no need to update + return ptr; // No need to update } else if (SEQUENTIAL() && old_head->blocksize > MAX_SIZE && new_size > MAX_SIZE) { - //use system realloc in SEQUENTIAL() mode for large->large blocks - new_head = sys_realloc (old_head, new_size); - new_head->blocksize = new_size; //sytem block + // Use system realloc in SEQUENTIAL() mode for large->large blocks + new_head = sys_realloc(old_head, new_size); + new_head->blocksize = new_size; // Sytem block new_head->next = NULL; SET_ALLOCATED(new_head, true); - ASSERTBLK (new_head); - return PAYLOAD (new_head); - } - else { - //build off malloc and free + ASSERTBLK(new_head); + return PAYLOAD(new_head); + } else { + // Build off malloc and free ASSERTBLK(old_head); size_t size_cache = old_head->blocksize; - //we're reallocating within managed memory + // We're reallocating within managed memory - void* new_payload = dm_malloc(gsize); //malloc will tweak size again. - if(new_payload == NULL){ - bop_msg(1, "Unable to reallocate %p (size %u) to new size %u", ptr, old_size, new_size); + void *new_payload = dm_malloc(gsize); // Malloc will tweak size again. + if (new_payload == NULL) { + bop_msg(1, "Unable to reallocate %p(size %u) to new size %u", ptr, old_size, new_size); return NULL; } - //copy the data + // Copy the data size_t copy_size = MIN(old_size, new_size) - HSIZE; // block sizes include the header! assert(copy_size != new_size - HSIZE); - bop_assert( HEADER(new_payload)->blocksize >= (copy_size + HSIZE)); //check dm_malloc gave enough space + bop_assert(HEADER(new_payload)->blocksize >= (copy_size + HSIZE)); // Check dm_malloc gave enough space new_payload = memcpy(new_payload, ptr, copy_size); // copy data - bop_assert( ((header *)HEADER(new_payload))->blocksize >= copy_size); + bop_assert(((header *)HEADER(new_payload))->blocksize >= copy_size); ASSERTBLK(old_head); bop_assert(old_head->blocksize == size_cache); - dm_free( (void*) ptr); + dm_free((void *)ptr); return new_payload; } @@ -593,152 +601,155 @@ void * dm_realloc (void *ptr, size_t gsize) { /* * Free a block if any of the following are true - * 1) Any sized block running in SEQ mode - * 2) Small block allocated and freed by this PPR task. - * A free is queued to be free'd at BOP commit time otherwise. + * 1) Any sized block running in SEQ mode + * 2) Small block allocated and freed by this PPR task. + * A free is queued to be free'd at BOP commit time otherwise. */ -void dm_free (void *ptr) { - header *free_header = HEADER (ptr); +void dm_free(void *ptr) { + header *free_header = HEADER(ptr); ASSERTBLK(free_header); get_lock(); #ifdef DM_REM_ALLOC - if(free_header->allocated == false){ - ErrorKillAll(-1); + if (free_header->allocated == false) { + ErrorKillAll(-1); } #endif - if(SEQUENTIAL() || remove_from_alloc_list (free_header)){ + if (SEQUENTIAL() || remove_from_alloc_list(free_header)) { release_lock(); - free_now (free_header); + free_now(free_header); } else{ SET_ALLOCATED(free_header, false); add_freed_list(free_header); } - - release_lock(); + release_lock(); } -//free a (regular or huge) block now. all saftey checks must be done before calling this function -static inline void free_now (header * head) { + +// Free a(regular or huge) block now. all saftey checks must be done before calling this function +static inline void free_now(header * head) { int which; size_t size = head->blocksize; ASSERTBLK(head); - bop_assert (size >= HSIZE && size == ALIGN (size)); //size is aligned, ie right value was written - //test for system block - if (size > MAX_SIZE){ - if(SEQUENTIAL() ) { - sys_free(head); - }else{ - get_lock(); - add_freed_list(head); - release_lock(); - } - return; + bop_assert(size >= HSIZE && size == ALIGN(size)); // Size is aligned, ie right value was written + // Test for system block + if (size > MAX_SIZE) { + if (SEQUENTIAL() ) { + sys_free(head); + } else { + get_lock(); + add_freed_list(head); + release_lock(); + } + return; } - //synchronised region + // Synchronised region get_lock(); - header *free_stack = get_header (size, &which); + header *free_stack = get_header(size, &which); bop_assert(size <= MAX_SIZE); bop_assert(which != -1); - if(which != -1) - bop_assert (size_of_klass(which) == size); //should exactly align + if (which != -1) + bop_assert(size_of_klass(which) == size); // Should exactly align if (free_stack == NULL) { - //empty free_stack + // Empty free_stack head->next = head->prev = NULL; headers[which] = head; release_lock(); return; } - free_stack->prev = CAST_UH (head); - head->next = CAST_UH (free_stack); + free_stack->prev = CAST_UH(head); + head->next = CAST_UH(free_stack); headers[which] = head; - release_lock(); } -inline size_t dm_malloc_usable_size(void* ptr) { - if(ptr == NULL) - return 0; - header *free_header = HEADER (ptr); + +inline size_t dm_malloc_usable_size(void *ptr) { + if (ptr == NULL) + return 0; + header *free_header = HEADER(ptr); size_t head_size = free_header->blocksize; - if(head_size > MAX_SIZE){ - head_size = sys_malloc_usable_size(free_header); + if (head_size > MAX_SIZE) { + head_size = sys_malloc_usable_size(free_header); } - return head_size - HSIZE; //even for system-allocated chunks. + return head_size - HSIZE; // Even for system-allocated chunks. } + /*malloc library utility functions: utility functions, debugging, list management etc */ -static bool remove_from_alloc_list (header * val) { - //remove val from the list - header* current, * prev = NULL; - const int index = get_index(val->blocksize); - for(current = allocated_lists[index]; current; prev = current, current = CAST_H(current->next)) { - if(current == val) { - if(prev == NULL){ - allocated_lists[index] = CAST_H(current->next); - }else{ - prev->next = CAST_UH(current->next); - } - return true; +static bool remove_from_alloc_list(header * val) { + // Remove val from the list + header* current, * prev = NULL; + const int index = get_index(val->blocksize); + for (current = allocated_lists[index]; current; prev = current, current = CAST_H(current->next)) { + if (current == val) { + if (prev == NULL) { + allocated_lists[index] = CAST_H(current->next); + } else { + prev->next = CAST_UH(current->next); + } + return true; + } } - } - bop_msg(4, "Allocation not found on alloc list"); - return false; + bop_msg(4, "Allocation not found on alloc list"); + return false; } -static inline bool list_contains (header * list, header * search_value) { + +static inline bool list_contains(header * list, header * search_value) { if (list == NULL || search_value == NULL) return false; header *current; - for (current = list; current != NULL; current = CAST_H (current->next)) { + for (current = list; current != NULL; current = CAST_H(current->next)) { if (current == search_value) return true; } return false; } -//add an allocated item to the allocated list + +// Add an allocated item to the allocated list static int added_n = 0; static int nseq_added_n = 0; -static inline void add_next_list (header** list_head, header * item) { - added_n++; - if(!SEQUENTIAL()) - nseq_added_n++; - bop_assert(*list_head != item); - item->next = CAST_UH(*list_head); //works even if *list_head == NULL - *list_head = item; +static inline void add_next_list(header** list_head, header * item) { + added_n++; + if (!SEQUENTIAL()) + nseq_added_n++; + bop_assert(*list_head != item); + item->next = CAST_UH(*list_head); // Works even if *list_head == NULL + *list_head = item; } -static inline void add_freed_list(header* item){ - size_t size = item->blocksize; - int index = get_index(size); - if(index >= DM_NUM_CLASSES){ - add_next_list(&large_free_list, item); - } - item->next = CAST_UH(freedlist[index]); - if(freedlist[index]){ - freedlist[index]->prev = CAST_UH(item); - } - freedlist[index] = item; +static inline void add_freed_list(header* item) { + size_t size = item->blocksize; + int index = get_index(size); + if (index >= DM_NUM_CLASSES) { + add_next_list(&large_free_list, item); + } + item->next = CAST_UH(freedlist[index]); + if (freedlist[index]) { + freedlist[index]->prev = CAST_UH(item); + } + freedlist[index] = item; } /**Print debug info*/ -void dm_print_info (void) { +void dm_print_info(void) { #ifndef NDEBUG setlocale(LC_ALL, ""); - int * counts = count_lists(true); //we don't actually have the lock, but don't care about thread saftey here + int *counts = count_lists(true); // We don't actually have the lock, but don't care about thread saftey here int i; - int GROW_S = 0; - for(i = 0; i < DM_NUM_CLASSES; i++) - GROW_S += size_of_klass(i); + int GROW_S = 0; + for (i = 0; i < DM_NUM_CLASSES; i++) + GROW_S += size_of_klass(i); printf("******DM Debug info******\n"); - printf ("Grow count: %'d\n", grow_count); + printf("Grow count: %'d\n", grow_count); printf("Max grow size: %'d B\n", GROW_S); printf("Total managed mem: %'d B\n", growth_size); printf("Differnce in actual & max: %'d B\n", (grow_count * (GROW_S)) - growth_size); - for(i = 0; i < DM_NUM_CLASSES; i++) { - printf("\tSplit to give class %d (%'lu B) %d times. It was given %d heads\n", + for (i = 0; i < DM_NUM_CLASSES; i++) { + printf("\tSplit to give class %d(%'lu B) %d times. It was given %d heads\n", i+1, size_of_klass(i), split_attempts[i],split_gave_head[i]); } printf("Splits: %'d\n", splits); printf("Miss splits: %'d\n", missed_splits); printf("Multi splits: %'d\n", multi_splits); - for(i = 0; i < DM_NUM_CLASSES; i++) + for (i = 0; i < DM_NUM_CLASSES; i++) printf("Class %d had %'d remaining items\n", i+1, counts[i]); #else printf("dm malloc not compiled in debug mode. Recompile without NDEBUG defined to keep track of debug information.\n"); @@ -746,8 +757,8 @@ void dm_print_info (void) { } bop_port_t bop_alloc_port = { - .ppr_group_init = carve, - .ppr_task_init = initialize_group, - .task_group_commit = malloc_promise, - .undy_init = dm_malloc_undy_init + .ppr_group_init = carve, + .ppr_task_init = initialize_group, + .task_group_commit = malloc_promise, + .undy_init = dm_malloc_undy_init }; diff --git a/dmmalloc.h b/dmmalloc.h index beba9be..768f0da 100644 --- a/dmmalloc.h +++ b/dmmalloc.h @@ -4,16 +4,16 @@ #include #include -//dm structs, unions etc +// Dm structs, unions etc typedef struct { - struct header * next; + struct header *next; #ifdef DM_REM_ALLOC - bool allocated; + bool allocated; #endif - union{ - size_t blocksize; - struct header * prev; - }; + union { + size_t blocksize; + struct header *prev; + }; } header; #ifdef DM_REM_ALLOC @@ -22,24 +22,24 @@ typedef struct { #define SET_ALLOCATED(h,a) #endif -//prototypes -void * dm_malloc(size_t); -void * dm_realloc(void *, size_t); +// Prototypes +void *dm_malloc(size_t); +void *dm_realloc(void *, size_t); void dm_free(void *); -void * dm_calloc(size_t, size_t); +void *dm_calloc(size_t, size_t); void dm_print_info(void); -size_t dm_malloc_usable_size(void*); -void dm_check(void*); +size_t dm_malloc_usable_size(void *); +void dm_check(void *); -//bop-related functions -void carve(); //divide up avaliable memory -void initialize_group(); //set end pointers for this ppr task +// Bop-related functions +void carve(); // Divide up avaliable memory +void initialize_group(); // Set end pointers for this ppr task -//data accessors for merge time +// Data accessors for merge time void malloc_merge(void); -void malloc_merge_counts(bool); //counts get updated AFTER abort status is known +void malloc_merge_counts(bool); // Counts get updated AFTER abort status is known -//Alignment based on word size +// Alignment based on word size #if __WORDSIZE == 64 #define ALIGNMENT 8 #elif __WORDSIZE == 32 @@ -48,28 +48,27 @@ void malloc_merge_counts(bool); //counts get updated AFTER abort status is known #error "need 32 or 64 bit word size" #endif -//malloc config macros +// Malloc config macros #ifndef DM_BLOCK_SIZE #define DM_BLOCK_SIZE 750 #endif -//alignement/ header macros +// Alignement/ header macros #define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~(ALIGNMENT-1)) #define HSIZE (ALIGN((sizeof(header)))) -#define HEADER(vp) ((header *) (((char *) (vp)) - HSIZE)) -#define CAST_UH(h) ((struct header *) (h)) -#define CAST_H(h) ((header*) (h)) -#define CHARP(p) (((char*) (p))) -#define PAYLOAD(hp) ((header *) (((char *) (hp)) + HSIZE)) +#define HEADER(vp) ((header *)(((char *)(vp)) - HSIZE)) +#define CAST_UH(h) ((struct header *)(h)) +#define CAST_H(h) ((header *)(h)) +#define CHARP(p) (((char *)(p))) +#define PAYLOAD(hp) ((header *)(((char *)(hp)) + HSIZE)) #define PTR_MATH(ptr, d) ((CHARP(ptr)) + d) -#define ASSERTBLK(head) bop_assert ((head)->blocksize > 0); +#define ASSERTBLK(head) bop_assert((head)->blocksize > 0); -//class size macros +// Class size macros #define DM_NUM_CLASSES 16 -#define DM_CLASS_OFFSET 4 //how much extra to shift the bits for size class, ie class k is 2 ^ (k + DM_CLASS_OFFSET) +#define DM_CLASS_OFFSET 4 // How much extra to shift the bits for size class, ie class k is 2 ^ (k + DM_CLASS_OFFSET) #define MAX_SIZE SIZE_C(DM_NUM_CLASSES) -#define SIZE_C(k) (ALIGN((1 << (k + DM_CLASS_OFFSET)))) //allows for iterative spliting +#define SIZE_C(k) (ALIGN((1 << (k + DM_CLASS_OFFSET)))) // Allows for iterative spliting #define DM_MAX_REQ (ALIGN((MAX_SIZE) - (HSIZE))) - #endif From 21f1936e56ae3f3a0ef3b5ca620d77aa47b2a15a Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 22 Jun 2016 10:23:48 -0400 Subject: [PATCH 18/37] Add sandbox, with add.c example --- sandbox/.gitignore | 1 + sandbox/Makefile | 15 ++++++++++ sandbox/add.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 sandbox/.gitignore create mode 100644 sandbox/Makefile create mode 100644 sandbox/add.c diff --git a/sandbox/.gitignore b/sandbox/.gitignore new file mode 100644 index 0000000..76d4bb8 --- /dev/null +++ b/sandbox/.gitignore @@ -0,0 +1 @@ +add diff --git a/sandbox/Makefile b/sandbox/Makefile new file mode 100644 index 0000000..d684ca2 --- /dev/null +++ b/sandbox/Makefile @@ -0,0 +1,15 @@ +CFLAGS = -O2 -fPIC -pthread -I.. -DBOP=1 +LDFLAGS = $(CFLAGS) -L.. +LDLIBS = -linst -lm -ldl + +.PHONY: all +all: ../libinst.a add + +../libinst.a: + $(MAKE) -C .. + +add: add.o + +.PHONY: clean +clean: + rm -f *.o add diff --git a/sandbox/add.c b/sandbox/add.c new file mode 100644 index 0000000..61c310b --- /dev/null +++ b/sandbox/add.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include + +#include "bop_api.h" + +/* The program makes an array of randomly initialized integers and adds them together. */ + +int +main(int argc, char **argv) +{ + int blocksize, parallelism, datasize; + double sum, *data; + + /* Processing the input */ + if (argc != 3) { + printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); + exit(1); + } + + datasize = (int)(atof(argv[1])*1000000); + assert(datasize>0); + parallelism = atoi(argv[2]); + assert(parallelism>0); + + /* Initialization */ + printf("%d: initializing %d million numbers\n", getpid(), datasize/1000000); + + data = (double *)malloc(datasize * sizeof(*data)); + for (int i = 0; i < datasize; i++) { + data[i] = i; + } + + printf("%d: adding %d million numbers\n", getpid(), datasize/1000000); + + blocksize = ceil((float)datasize/parallelism); + + for (int i = 0; i < datasize; i += blocksize) { + int n; + double sump = 0.0; + + BOP_ppr_begin(1); + + BOP_record_read(&blocksize, sizeof(blocksize)); + BOP_record_read(&datasize, sizeof(datasize)); + n = i + blocksize > datasize? datasize : i + blocksize; + + BOP_record_read(data + i, (n - i) * sizeof(*data)); + for (int j = i; j Date: Wed, 22 Jun 2016 10:27:22 -0400 Subject: [PATCH 19/37] Fix missing prototypes --- bop_api.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bop_api.h b/bop_api.h index b3568e9..440638f 100644 --- a/bop_api.h +++ b/bop_api.h @@ -55,6 +55,9 @@ typedef struct _mem_range_t { unsigned task; /* optional ppr_index used by post-wait */ } mem_range_t; +int _BOP_ppr_begin(int id); +void _BOP_ppr_end(int id); + // %------------------ Function Prototype -------------- % /* the TOLABEL macro by Grant Farmer */ #define TOL(x) L##x From 391d858971a73459943ceb0bbbef6de2fab177c0 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 22 Jun 2016 10:57:22 -0400 Subject: [PATCH 20/37] Update makefile to save temp files --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4f94d48..4d09aec 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ifeq ($(CC), cc) endif -CFLAGS = -Wall -g -fPIC -pthread -I. -Wno-unused-function $(CUSTOMDEF) +CFLAGS = -Wall -g -fPIC -pthread -I. -Wno-unused-function -save-temps $(CUSTOMDEF) CUSTOMDEF = -D USE_DL_PREFIX -D BOP -D USE_LOCKS -D UNSUPPORTED_MALLOC -D DM_DEBUG LDFLAGS = -Wl,--no-as-needed -ldl OPITIMIZEFLAGS = -O3 @@ -51,7 +51,7 @@ all: $(OBJS) @gcc -c -o $@ $^ $(CFLAGS) clean: - rm -f $(OBJS) $(LIB) *.d *.d.tmp + rm -f $(OBJS) $(LIB) *.d *.d.tmp *.[ios] for dir in $(TEST_DIRS) ; do \ echo $$dir ; \ cd tests/$$dir ; \ From 28ead86773a9d6168067092e88e2940eff06a575 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 22 Jun 2016 10:57:29 -0400 Subject: [PATCH 21/37] Sandbox --- sandbox/add.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sandbox/add.c b/sandbox/add.c index 61c310b..b7ea110 100644 --- a/sandbox/add.c +++ b/sandbox/add.c @@ -6,6 +6,7 @@ #include #include "bop_api.h" +#include "dmmalloc.h" /* The program makes an array of randomly initialized integers and adds them together. */ @@ -64,5 +65,9 @@ main(int argc, char **argv) printf("%d: %d million numbers added. The sum is %.0f million (%.0f) \n", getpid(), datasize/1000000, sum/1000000, sum); + free(data); + + dm_print_info(); + return 0; } From b2b27b1d9043588d9dbec59339d8afc56abebf9e Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 22 Jun 2016 11:31:52 -0400 Subject: [PATCH 22/37] Fix spacing; ignore cscope.out --- .gitignore | 1 + dmmalloc.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ded91d0..11b157b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ inst.a libinst.a *.d *.d.tmp +cscope.out diff --git a/dmmalloc.c b/dmmalloc.c index 12bd024..59091d0 100644 --- a/dmmalloc.c +++ b/dmmalloc.c @@ -298,7 +298,7 @@ static inline void grow(const int tasks) { // THIS IS THE NEW GROW FUNCTION! int class_index, blocks_left, size; if (tasks > 1) - bop_debug("growing tasks = %d", tasks); + bop_debug("growing tasks = %d", tasks); #ifndef NDEBUG grow_count++; #endif From 6dc45d47ef93637f546f35a1ad7e12750bb44467 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 22 Jun 2016 12:10:39 -0400 Subject: [PATCH 23/37] Fix pointer formats --- dmmalloc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dmmalloc.c b/dmmalloc.c index 59091d0..2c737c2 100644 --- a/dmmalloc.c +++ b/dmmalloc.c @@ -395,7 +395,7 @@ extern void BOP_malloc_rescue(char *, size_t); // BOP-safe malloc implementation based off of size classes. void *dm_malloc(const size_t size) { - volatile header * block = NULL; + volatile header *block = NULL; int which, bigger = -1; size_t alloc_size; if (size == 0) @@ -479,7 +479,7 @@ static inline int index_bigger(int which) { } // Repeatedly split a larger block into a block of the required size -static inline header* dm_split(int which, int larger) { +static inline header *dm_split(int which, int larger) { if (which > 15) { bop_msg(3, "In large split"); } @@ -625,7 +625,7 @@ void dm_free(void *ptr) { } // Free a(regular or huge) block now. all saftey checks must be done before calling this function -static inline void free_now(header * head) { +static inline void free_now(header *head) { int which; size_t size = head->blocksize; ASSERTBLK(head); @@ -673,9 +673,9 @@ inline size_t dm_malloc_usable_size(void *ptr) { } /*malloc library utility functions: utility functions, debugging, list management etc */ -static bool remove_from_alloc_list(header * val) { +static bool remove_from_alloc_list(header *val) { // Remove val from the list - header* current, * prev = NULL; + header *current, *prev = NULL; const int index = get_index(val->blocksize); for (current = allocated_lists[index]; current; prev = current, current = CAST_H(current->next)) { if (current == val) { @@ -691,7 +691,7 @@ static bool remove_from_alloc_list(header * val) { return false; } -static inline bool list_contains(header * list, header * search_value) { +static inline bool list_contains(header *list, header *search_value) { if (list == NULL || search_value == NULL) return false; header *current; @@ -706,7 +706,7 @@ static inline bool list_contains(header * list, header * search_value) { static int added_n = 0; static int nseq_added_n = 0; -static inline void add_next_list(header** list_head, header * item) { +static inline void add_next_list(header **list_head, header *item) { added_n++; if (!SEQUENTIAL()) nseq_added_n++; @@ -715,7 +715,7 @@ static inline void add_next_list(header** list_head, header * item) { *list_head = item; } -static inline void add_freed_list(header* item) { +static inline void add_freed_list(header *item) { size_t size = item->blocksize; int index = get_index(size); if (index >= DM_NUM_CLASSES) { From ceedc2bf4f91dbf2fc9f66454802c17723b7761b Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Fri, 1 Jul 2016 00:03:03 -0400 Subject: [PATCH 24/37] Reformat all *.[ch] files --- ary_bitmap.c | 135 ++- ary_bitmap.h | 29 +- atomic.h | 60 +- bop_api.h | 234 ++-- bop_io.c | 350 +++--- bop_map.h | 66 +- bop_merge.c | 515 +++++---- bop_merge.h | 6 +- bop_ordered.c | 118 +- bop_ports.c | 272 +++-- bop_ports.h | 35 +- bop_ppr.c | 1613 +++++++++++++++------------ bop_ppr_sync.c | 302 ++--- bop_ppr_sync.h | 76 +- dmmalloc.c | 580 ++++++---- dmmalloc.h | 42 +- key_value_checks.c | 400 ++++--- key_value_checks.h | 61 +- libc_overrides.c | 17 +- malloc_wrapper.c | 196 ++-- malloc_wrapper.h | 47 +- postwait.c | 824 ++++++++------ postwait.h | 12 +- range_tree/dtree.c | 1072 ++++++++++-------- sandbox/add.c | 32 +- tests/add/add.c | 121 +- tests/add/add_ppr_only.c | 127 ++- tests/malloc_test.c | 45 +- tests/mem/add_mem_test.c | 168 +-- tests/mem/big_alloc.c | 84 +- tests/mem/mem.c | 172 +-- tests/mem/small_alloc.c | 84 +- tests/parallel_alloc/add_ppr_only.c | 35 +- tests/sleep/sleep.c | 87 +- tests/str/BOP_strcmp/string.c | 157 +-- tests/str/BOP_string/string.c | 312 +++--- tests/str/strsub/strsub.c | 527 +++++---- tests/str/strsub2/string.c | 566 +++++----- tests/unit_tests/ary_bitmap_tests.c | 81 +- tests/unit_tests/bop_io_tests.c | 134 ++- tests/unit_tests/bop_malloc_tests.c | 604 +++++----- tests/unit_tests/bop_merge_tests.c | 248 ++-- tests/unit_tests/multi_ppr.c | 31 +- tests/unit_tests/postwait_tests.c | 457 ++++---- tests/unit_tests/range_tree_tests.c | 311 +++--- tests/wrapper_test.c | 46 +- utils.c | 255 +++-- utils.h | 49 +- 48 files changed, 6749 insertions(+), 5046 deletions(-) mode change 100755 => 100644 tests/mem/mem.c diff --git a/ary_bitmap.c b/ary_bitmap.c index 213c20d..6c9538c 100644 --- a/ary_bitmap.c +++ b/ary_bitmap.c @@ -1,74 +1,115 @@ +#include "ary_bitmap.h" +#include "bop_api.h" +#include "external/malloc.h" #include #include -#include "external/malloc.h" -#include "bop_api.h" -#include "ary_bitmap.h" /* each entry an unsigned number, 32 bits */ -uint32_t ary_map_entries( uint32_t ary_size ) { - return (ary_size >> 5) + ((ary_size & 0x1f)? 1: 0); +uint32_t +ary_map_entries(uint32_t ary_size) +{ + return (ary_size >> 5) + ((ary_size & 0x1f) ? 1 : 0); } -void *ary_malloc_with_map( uint32_t length, uint32_t elem_size ) { - void *ary = malloc( length*(elem_size) + ary_map_entries(length) * sizeof(uint32_t) * 2 ); - ary_maps_reset( ary, length, elem_size ); - return ary; +void * +ary_malloc_with_map(uint32_t length, uint32_t elem_size) +{ + void *ary = malloc(length * (elem_size) + + ary_map_entries(length) * sizeof(uint32_t) * 2); + + ary_maps_reset(ary, length, elem_size); + return ary; } -void *ary_realloc_with_map( void *mem, uint32_t new_len, uint32_t elem_size ) { - void *ary = realloc( mem, new_len*elem_size + ary_map_entries(new_len) * sizeof(uint32_t) * 2 ); - ary_maps_reset( ary, new_len, elem_size ); - return ary; +void * +ary_realloc_with_map(void *mem, uint32_t new_len, uint32_t elem_size) +{ + void *ary = realloc(mem, + new_len * elem_size + + ary_map_entries(new_len) * sizeof(uint32_t) * 2); + + ary_maps_reset(ary, new_len, elem_size); + return ary; } -uint32_t *get_ary_use_map( void *base, uint32_t length, uint32_t elem_size ) { - return (uint32_t *) (((char*)base) + elem_size * length); +uint32_t * +get_ary_use_map(void *base, uint32_t length, uint32_t elem_size) +{ + return (uint32_t *)(((char *)base) + elem_size * length); } -uint32_t *get_ary_mod_map( void *base, uint32_t length, uint32_t elem_size ) { - return (uint32_t *) (((char*)base) + elem_size * length + ary_map_entries(length) * sizeof(uint32_t)); +uint32_t * +get_ary_mod_map(void *base, uint32_t length, uint32_t elem_size) +{ + return (uint32_t *)(((char *)base) + elem_size * length + + ary_map_entries(length) * sizeof(uint32_t)); } -void ary_maps_reset( void *base, uint32_t length, uint32_t elem_size ) { - char * maps_base = (char*) get_ary_use_map( base, length, elem_size ); - memset( maps_base, 0, ary_map_entries( length ) * 2 * sizeof( uint32_t ) ); - BOP_promise( maps_base, ary_map_entries( length ) * 2 * sizeof( uint32_t ) ); +void +ary_maps_reset(void *base, uint32_t length, uint32_t elem_size) +{ + char *maps_base = (char *)get_ary_use_map(base, length, elem_size); + + memset(maps_base, 0, ary_map_entries(length) * 2 * sizeof(uint32_t)); + BOP_promise(maps_base, ary_map_entries(length) * 2 * sizeof(uint32_t)); } -static void mark_bit( uint32_t *map, uint32_t idx ) { - uint32_t word_idx = idx >> 5; - uint32_t offset = idx & 0x1f; - map[ word_idx ] |= 0x1 << offset; +static void +mark_bit(uint32_t *map, uint32_t idx) +{ + uint32_t word_idx = idx >> 5; + uint32_t offset = idx & 0x1f; + + map[word_idx] |= 0x1 << offset; } -void ary_use_elem( void *base, uint32_t length, - uint32_t elem_size, uint32_t idx ) { - uint32_t *use_map = get_ary_use_map( base, length, elem_size ); - mark_bit( use_map, idx ); +void +ary_use_elem(void *base, uint32_t length, uint32_t elem_size, uint32_t idx) +{ + uint32_t *use_map = get_ary_use_map(base, length, elem_size); + + mark_bit(use_map, idx); } -void ary_promise_elem( void *base, uint32_t length, - uint32_t elem_size, uint32_t idx ) { - uint32_t *mod_map = get_ary_mod_map( base, length, elem_size ); - mark_bit( mod_map, idx ); +void +ary_promise_elem(void *base, uint32_t length, uint32_t elem_size, uint32_t idx) +{ + uint32_t *mod_map = get_ary_mod_map(base, length, elem_size); + + mark_bit(mod_map, idx); } -static void scan_one_map( void *base, uint32_t length, uint32_t elem_size, - uint32_t *map, monitor_t *bop_mon ) { - uint32_t num = ary_map_entries( length ); +static void +scan_one_map(void *base, + uint32_t length, + uint32_t elem_size, + uint32_t *map, + monitor_t *bop_mon) +{ + uint32_t num = ary_map_entries(length); int i, j; - for ( i = 0; i < num; i++ ) { - uint32_t word = map[ i ]; - uint32_t idx = i << 5; - for ( j = 0; j < 32; j++ ) - if ( (word >> j) & 0x1 ) - (*bop_mon)( ((char*) base) + (idx + j) * elem_size, elem_size ); + + for (i = 0; i < num; i++) { + uint32_t word = map[i]; + uint32_t idx = i << 5; + + for (j = 0; j < 32; j++) + if ((word >> j) & 0x1) + (*bop_mon)(((char *)base) + (idx + j) * elem_size, elem_size); } } -void scan_ary_maps( void *base, uint32_t length, uint32_t elem_size ) { - scan_one_map( base, length, elem_size, - get_ary_use_map(base, length, elem_size), & BOP_record_read ); - scan_one_map( base, length, elem_size, - get_ary_mod_map(base, length, elem_size), & BOP_record_write ); +void +scan_ary_maps(void *base, uint32_t length, uint32_t elem_size) +{ + scan_one_map(base, + length, + elem_size, + get_ary_use_map(base, length, elem_size), + &BOP_record_read); + scan_one_map(base, + length, + elem_size, + get_ary_mod_map(base, length, elem_size), + &BOP_record_write); } diff --git a/ary_bitmap.h b/ary_bitmap.h index e423953..265ed08 100644 --- a/ary_bitmap.h +++ b/ary_bitmap.h @@ -2,24 +2,31 @@ #define _ARY_BITMAP_H_ #include -void *ary_malloc_with_map( uint32_t length, uint32_t elem_size ); -void *ary_realloc_with_map( void *var, uint32_t length, uint32_t elem_size ); +void * +ary_malloc_with_map(uint32_t length, uint32_t elem_size); +void * +ary_realloc_with_map(void *var, uint32_t length, uint32_t elem_size); /* each entry an unsigned number, 32 bits */ -uint32_t ary_map_entries( uint32_t ary_size ); +uint32_t +ary_map_entries(uint32_t ary_size); -uint32_t *get_ary_use_map( void *base, uint32_t lenth, uint32_t elem_size ); +uint32_t * +get_ary_use_map(void *base, uint32_t lenth, uint32_t elem_size); -uint32_t *get_ary_mod_map( void *base, uint32_t lenth, uint32_t elem_size ); +uint32_t * +get_ary_mod_map(void *base, uint32_t lenth, uint32_t elem_size); -void ary_maps_reset( void *base, uint32_t lenth, uint32_t elem_size ); +void +ary_maps_reset(void *base, uint32_t lenth, uint32_t elem_size); -void ary_use_elem( void *base, uint32_t lenth, - uint32_t elem_size, uint32_t idx ); +void +ary_use_elem(void *base, uint32_t lenth, uint32_t elem_size, uint32_t idx); -void ary_promise_elem( void *base, uint32_t lenth, - uint32_t elem_size, uint32_t idx ); +void +ary_promise_elem(void *base, uint32_t lenth, uint32_t elem_size, uint32_t idx); -void scan_ary_maps( void *base, uint32_t length, uint32_t elem_size ); +void +scan_ary_maps(void *base, uint32_t length, uint32_t elem_size); #endif diff --git a/atomic.h b/atomic.h index e37c75b..d34cb60 100644 --- a/atomic.h +++ b/atomic.h @@ -2,61 +2,75 @@ #define ATOMIC_H #include "utils.h" /* for GCC internals see - http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Atomic-Builtins.html */ + * http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Atomic-Builtins.html */ /* We use only 0-1 values with the lock */ #ifdef USE_PTHREAD_LOCK -#include +#include typedef pthread_mutex_t bop_lock_t; #else typedef char bop_lock_t; #endif /* nop, backoff, and slowpath locking code based on RSTM -http://www.cs.rochester.edu/~sandhya/csc258/assignments/ass2/atomic_ops.h*/ + * http://www.cs.rochester.edu/~sandhya/csc258/assignments/ass2/atomic_ops.h */ + +static inline void +backoff(int *b) +{ + int i; -static inline void backoff( int *b ) { - int i; for (i = *b; i; i--) - nop(); //from utils.h + nop(); // from utils.h if (*b < 4096) *b <<= 1; } -static inline void lock_acquire_slowpath(char *lock) +static inline void +lock_acquire_slowpath(char *lock) { int b = 64; - do - { + do { backoff(&b); - } - while (__sync_bool_compare_and_swap( (lock), 0, 1 ) == 0); + } while (__sync_bool_compare_and_swap((lock), 0, 1) == 0); } #ifdef USE_PTHREAD_LOCK -static inline void bop_lock_acquire( bop_lock_t *lock ) { - pthread_mutex_lock (lock); +static inline void +bop_lock_acquire(bop_lock_t *lock) +{ + pthread_mutex_lock(lock); } -static inline void bop_lock_release( bop_lock_t *lock ) { - pthread_mutex_unlock (lock); + +static inline void +bop_lock_release(bop_lock_t *lock) +{ + pthread_mutex_unlock(lock); } #else -static inline void bop_lock_acquire( bop_lock_t *lock ) { - if ( __sync_bool_compare_and_swap( (lock), 0, 1 ) == 0 ) lock_acquire_slowpath( lock ); +static inline void +bop_lock_acquire(bop_lock_t *lock) +{ + if (__sync_bool_compare_and_swap((lock), 0, 1) == 0) + lock_acquire_slowpath(lock); } -#define bop_lock_release( lock ) *(lock) = 0 -static inline void bop_wait_flag( bop_lock_t *flag ) { - int b = 64; - while ( ! *flag ) - backoff( &b ); +#define bop_lock_release(lock) *(lock) = 0 + +static inline void +bop_wait_flag(bop_lock_t *flag) +{ + int b = 64; + + while (!*flag) + backoff(&b); } #endif -#define bop_lock_clear( lock ) bop_lock_release( (lock) ) +#define bop_lock_clear(lock) bop_lock_release((lock)) #endif diff --git a/bop_api.h b/bop_api.h index 440638f..bf200c3 100644 --- a/bop_api.h +++ b/bop_api.h @@ -1,62 +1,65 @@ /* Behavior-oriented parallelization. See Ding et al. PLDI 2007 and Ke - et al. OOPSLA 2011. A complete re-write on June 29, 2012. -*/ + * et al. OOPSLA 2011. A complete re-write on June 29, 2012. + */ #ifndef _BOP_API_H_ #define _BOP_API_H_ #ifndef NDEBUG -/* We want the task status while debugging->bop_msg **/ -#define bop_debug(x, ...) bop_msg(1, "%s:%d " x "" , __FILE__, __LINE__, ##__VA_ARGS__); +/* We want the task status while debugging->bop_msg * */ +#define bop_debug(x, ...) \ + bop_msg(1, "%s:%d " x "", __FILE__, __LINE__, ##__VA_ARGS__); #else #define bop_debug(...) #endif -void error_alert_monitor(void); +void +error_alert_monitor(void); + #if defined(BOP) -#include /* for bop_msg */ -#include /* for assert */ -#include /* for IO */ +#include /* for assert */ +#include /* for bop_msg */ #include +#include /* for IO */ typedef uintptr_t addr_t; #define TRUE 1 #define FALSE 0 typedef enum { - SEQ = -2, // sequential mode, ready to change at next PPR - UNDY, // the understudy - MAIN, // first PPR task after SEQ mode - SPEC // a speculation process + SEQ = -2, // sequential mode, ready to change at next PPR + UNDY, // the understudy + MAIN, // first PPR task after SEQ mode + SPEC // a speculation process } task_status_t; -typedef enum { - PPR = 0, - GAP, - PSEQ -} ppr_pos_t; +typedef enum { PPR = 0, GAP, PSEQ } ppr_pos_t; -typedef enum { - SERIAL = 0, - PARALLEL -} bop_mode_t; +typedef enum { SERIAL = 0, PARALLEL } bop_mode_t; -task_status_t BOP_task_status(void); -ppr_pos_t BOP_ppr_pos(void); -bop_mode_t BOP_mode(void); -int BOP_spec_order(void); -int BOP_ppr_index(void); +task_status_t +BOP_task_status(void); +ppr_pos_t +BOP_ppr_pos(void); +bop_mode_t +BOP_mode(void); +int +BOP_spec_order(void); +int +BOP_ppr_index(void); /* system wide data structure for a memory range */ typedef struct _mem_range_t { - addr_t base; - size_t size; - void *rec; /* optional data record */ - unsigned task; /* optional ppr_index used by post-wait */ + addr_t base; + size_t size; + void *rec; /* optional data record */ + unsigned task; /* optional ppr_index used by post-wait */ } mem_range_t; -int _BOP_ppr_begin(int id); -void _BOP_ppr_end(int id); +int +_BOP_ppr_begin(int id); +void +_BOP_ppr_end(int id); // %------------------ Function Prototype -------------- % /* the TOLABEL macro by Grant Farmer */ @@ -64,90 +67,125 @@ void _BOP_ppr_end(int id); #define TOLABEL(x) TOL(x) #define TOS(x) #x #define TOSTRING(x) TOS(x) -#define BOP_ppr_begin(id) if (_BOP_ppr_begin(id)==1) goto TOLABEL(id) -#define BOP_ppr_end(id) _BOP_ppr_end(id); TOLABEL(id): +#define BOP_ppr_begin(id) \ + if (_BOP_ppr_begin(id) == 1) \ + goto TOLABEL(id) +#define BOP_ppr_end(id) \ + _BOP_ppr_end(id); \ + TOLABEL(id) : #define BOP_group_over(id) _BOP_group_over(id) -void BOP_ordered_begin( addr_t ); -void BOP_ordered_end( addr_t ); -void BOP_ordered_skip( addr_t ); - -int BOP_get_group_size(void); -int BOP_get_verbose(void); +void BOP_ordered_begin(addr_t); +void BOP_ordered_end(addr_t); +void BOP_ordered_skip(addr_t); -void BOP_set_group_size(int sz); -void BOP_set_verbose(int x); +int +BOP_get_group_size(void); +int +BOP_get_verbose(void); +void +BOP_set_group_size(int sz); +void +BOP_set_verbose(int x); /* Byte granularity interface */ -void BOP_record_read(void* addr, size_t size); -void BOP_record_write(void* addr, size_t size); -#define BOP_use( x, y ) BOP_record_read( x, y ) -#define BOP_promise( x, y ) BOP_record_write( x, y ) +void +BOP_record_read(void *addr, size_t size); +void +BOP_record_write(void *addr, size_t size); -typedef void monitor_t (void *, size_t); +#define BOP_use(x, y) BOP_record_read(x, y) +#define BOP_promise(x, y) BOP_record_write(x, y) + +typedef void +monitor_t(void *, size_t); /* Called by a speculation process in case of error. */ -void BOP_abort_spec( const char* msg, ...) __attribute__ ((format (printf, 1, 2))); -void BOP_abort_next_spec( char* msg, ... ) __attribute__ ((format (printf, 1, 2))); +void +BOP_abort_spec(const char *msg, ...) __attribute__((format(printf, 1, 2))); +void +BOP_abort_next_spec(char *msg, ...) __attribute__((format(printf, 1, 2))); /* FILE I/O */ -int BOP_printf(const char *format, ...); -int BOP_fprintf(FILE *stream, const char *format, ...); +int +BOP_printf(const char *format, ...); +int +BOP_fprintf(FILE *stream, const char *format, ...); /* Check if addr has been read/written. Return the memory range; - otherwise NULL*/ -mem_range_t *BOP_check_read(void* addr); -mem_range_t *BOP_check_write(void* addr); -mem_range_t *BOP_check_access(void* addr); + * otherwise NULL */ +mem_range_t * +BOP_check_read(void *addr); +mem_range_t * +BOP_check_write(void *addr); +mem_range_t * +BOP_check_access(void *addr); // %--------------- For Debug ------------- % -void bop_set_verbose( int ); -int bop_get_verbose( void ); -void bop_msg(int level, const char * msg, ...); +void +bop_set_verbose(int); +int +bop_get_verbose(void); +void +bop_msg(int level, const char *msg, ...); extern short malloc_panic; -#define bop_assert(x) if(!(x)) {malloc_panic = 1; bop_msg(0, ("Assertion: %s failed, %s:%d %s"), #x, __FILE__, __LINE__, __func__); abort();} + +#define bop_assert(x) \ + if (!(x)) { \ + malloc_panic = 1; \ + bop_msg(0, \ + ("Assertion: %s failed, %s:%d %s"), \ + #x, \ + __FILE__, \ + __LINE__, \ + __func__); \ + abort(); \ + } /* For collecting statistics */ typedef struct { - double start_time; - int num_by_spec; - int num_by_main; - int num_by_undy; - int data_copied; - int data_posted; + double start_time; + int num_by_spec; + int num_by_main; + int num_by_undy; + int data_copied; + int data_posted; } stats_t; extern stats_t bop_stats; /* For BOP_malloc */ -void *_BOP_malloc(size_t sz, char *file, unsigned line); -void *_BOP_calloc(size_t n_elements, size_t elem_size, char *file, unsigned line); -void _BOP_free(void* mem, char *file, unsigned line); -void *_BOP_realloc(void* mem, size_t newsize, char *file, unsigned line); +void * +_BOP_malloc(size_t sz, char *file, unsigned line); +void * +_BOP_calloc(size_t n_elements, size_t elem_size, char *file, unsigned line); +void +_BOP_free(void *mem, char *file, unsigned line); +void * +_BOP_realloc(void *mem, size_t newsize, char *file, unsigned line); #include "dmmalloc.h" #include "malloc_wrapper.h" -#define BOP_malloc( sz ) malloc( sz ) -#define BOP_alloc( n, s ) calloc( n, s ) -#define BOP_free( m ) free ( m ) -#define BOP_realloc( m, nsz ) realloc( m, nsz ) - +#define BOP_malloc(sz) malloc(sz) +#define BOP_alloc(n, s) calloc(n, s) +#define BOP_free(m) free(m) +#define BOP_realloc(m, nsz) realloc(m, nsz) // Original Code /* -#define BOP_malloc( sz ) _BOP_malloc( sz, __FILE__, __LINE__ ) -#define BOP_calloc( n, s ) _BOP_calloc( n, s, __FILE__, __LINE__ ) -#define BOP_free( m ) _BOP_free( m, __FILE__, __LINE__ ) -#define BOP_realloc( m, nsz ) _BOP_realloc( m, nsz, __FILE__, __LINE__ ) -*/ + * #define BOP_malloc( sz ) _BOP_malloc( sz, __FILE__, __LINE__ ) + * #define BOP_calloc( n, s ) _BOP_calloc( n, s, __FILE__, __LINE__ ) + * #define BOP_free( m ) _BOP_free( m, __FILE__, __LINE__ ) + * #define BOP_realloc( m, nsz ) _BOP_realloc( m, nsz, __FILE__, __LINE__ ) + */ /* should be disabled if defining BOP_printf printf -#define printf BOP_printf -#define fprintf BOP_fprintf -#define scanf BOP_abort_spec_group(); scanf -#define fscanf BOP_abort_spec_group(); fscanf -*/ + * #define printf BOP_printf + * #define fprintf BOP_fprintf + * #define scanf BOP_abort_spec_group(); scanf + * #define fscanf BOP_abort_spec_group(); fscanf + */ //#define BOP_malloc(s) malloc(s) //#define BOP_free(s) free(s) @@ -160,27 +198,27 @@ size_t max_ppr_request; #else /* original code */ -#define BOP_set_verbose( x ) -#define BOP_set_group_size( x ) -#define BOP_spec_order( ) 0 -#define BOP_ppr_index( ) 0 +#define BOP_set_verbose(x) +#define BOP_set_group_size(x) +#define BOP_spec_order() 0 +#define BOP_ppr_index() 0 #define BOP_ppr_begin(id) #define BOP_ppr_end(id) -#define BOP_ordered_begin( ) -#define BOP_ordered_end( ) +#define BOP_ordered_begin() +#define BOP_ordered_end() #define BOP_group_over(id) -#define BOP_record_read( addr, size ) -#define BOP_record_write( addr, size ) -#define BOP_use( addr, size ) -#define BOP_promise( addr, size ) +#define BOP_record_read(addr, size) +#define BOP_record_write(addr, size) +#define BOP_use(addr, size) +#define BOP_promise(addr, size) -#define bop_msg(ignored, ...) printf( __VA_ARGS__ ) +#define bop_msg(ignored, ...) printf(__VA_ARGS__) -#define BOP_abort_spec( msg, ... ) -#define BOP_abort_next_spec( msg, ...) -#define BOP_abort_spec_group( msg, ... ) +#define BOP_abort_spec(msg, ...) +#define BOP_abort_next_spec(msg, ...) +#define BOP_abort_spec_group(msg, ...) #define bop_assert(x) assert(x) #include diff --git a/bop_io.c b/bop_io.c index 1f243dd..67f3553 100644 --- a/bop_io.c +++ b/bop_io.c @@ -1,108 +1,118 @@ -#include -#include -#include -#include #include "bop_api.h" #include "bop_ports.h" -#include "utils.h" #include "external/malloc.h" +#include "utils.h" +#include +#include +#include +#include #include - static mspace io_mspace = NULL; typedef struct { - size_t alloc; - size_t used; - char *data; + size_t alloc; + size_t used; + char *data; } output_buffer; static output_buffer *output_buffers = NULL; -static output_buffer undy_buffer = { 0, 0, NULL }; +static output_buffer undy_buffer = {0, 0, NULL}; + static unsigned num_buffers = 0; -static inline int all_buffs_empty(){ - int x; - for(x = 0; x < num_buffers; x++) - if(output_buffers[x].used != 0) - return 1; - return 0; +static inline int +all_buffs_empty() +{ + int x; + + for (x = 0; x < num_buffers; x++) + if (output_buffers[x].used != 0) + return 1; + return 0; } -int BOP_printf(const char *format, ...) + +int +BOP_printf(const char *format, ...) { - va_list v, v2; - va_start(v, format); - int size; - output_buffer *buf; - - switch (BOP_task_status()) { - case SEQ: - case MAIN: - size = vfprintf( stdout, format, v ); - va_end(v); - return size; - case UNDY: - buf = &undy_buffer; - break; - case SPEC: - assert( output_buffers != NULL ); - buf = &output_buffers[BOP_spec_order() - 1]; /* - main */ - default: - _exit(0); //never reaches here - } - assert(buf->data != NULL); - - char *data = buf->data + buf->used - 1; /* For '\0' */ - size_t avail = buf->alloc - buf->used; - assert(*data == '\0'); - - /* Try to store */ - va_copy(v2, v); - size = vsnprintf(data, avail, format, v2); - va_end(v2); - if (size < 0) { - /* return errors */ - va_end(v); - return size; - } - - /* Tried to use more space than we have */ - if (size > avail) { - size_t new_size = buf->alloc; - do { - new_size *= 2; - } while (new_size < buf->used + size); - - if (BOP_task_status() == SPEC) { - data = (char *) mspace_realloc(io_mspace, buf->data, new_size); - if (data == NULL) - BOP_abort_spec("Ran out of output buffer"); - } else { - data = (char *) realloc(buf->data, new_size); - } - if (data == NULL) { - va_end(v); - return -1; + va_list v, v2; + + va_start(v, format); + int size; + output_buffer *buf; + + switch (BOP_task_status()) { + case SEQ: + case MAIN: + size = vfprintf(stdout, format, v); + va_end(v); + return size; + case UNDY: + buf = &undy_buffer; + break; + case SPEC: + assert(output_buffers != NULL); + buf = &output_buffers[BOP_spec_order() - 1]; /* - main */ + default: + _exit(0); // never reaches here } + assert(buf->data != NULL); - buf->data = data; - buf->alloc = new_size; - avail = new_size - buf->used; - assert(avail >= size); + char *data = buf->data + buf->used - 1; /* For '\0' */ + size_t avail = buf->alloc - buf->used; - data += buf->used - 1; /* For '\0' */ + assert(*data == '\0'); + + /* Try to store */ va_copy(v2, v); size = vsnprintf(data, avail, format, v2); va_end(v2); - } + if (size < 0) { + /* return errors */ + va_end(v); + return size; + } + + /* Tried to use more space than we have */ + if (size > avail) { + size_t new_size = buf->alloc; + + do { + new_size *= 2; + } while (new_size < buf->used + size); + + if (BOP_task_status() == SPEC) { + data = (char *)mspace_realloc(io_mspace, buf->data, new_size); + if (data == NULL) + BOP_abort_spec("Ran out of output buffer"); + } else { + data = (char *)realloc(buf->data, new_size); + } + if (data == NULL) { + va_end(v); + return -1; + } + + buf->data = data; + buf->alloc = new_size; + avail = new_size - buf->used; + assert(avail >= size); + + data += buf->used - 1; /* For '\0' */ + va_copy(v2, v); + size = vsnprintf(data, avail, format, v2); + va_end(v2); + } - buf->used += size; - assert( buf->used <= buf->alloc ); + buf->used += size; + assert(buf->used <= buf->alloc); - va_end(v); - return size; + va_end(v); + return size; } -static void init_buffer(output_buffer *buf, char *data, size_t size) { +static void +init_buffer(output_buffer *buf, char *data, size_t size) +{ assert(data != NULL); assert(size >= 1); buf->alloc = size; @@ -112,99 +122,127 @@ static void init_buffer(output_buffer *buf, char *data, size_t size) { } /* stop speculation if printing to a file */ -int BOP_fprintf(FILE *stream, const char *format, ...) +int +BOP_fprintf(FILE *stream, const char *format, ...) { - va_list v; - BOP_abort_spec("File output not yet supported in I/O port"); - va_start(v, format); + va_list v; + + BOP_abort_spec("File output not yet supported in I/O port"); + va_start(v, format); - return vfprintf(stream, format, v); + return vfprintf(stream, format, v); } -static void io_group_init( void ) { - num_buffers = BOP_get_group_size() - 1; /* - main */ - - /* Create a shared memory space */ - if (!io_mspace) - io_mspace = create_mspace(0, 1, 1); /* Default size, locked, shared */ - assert(io_mspace != NULL); - - /* Create a set of output buffers */ - assert(output_buffers == NULL || all_buffs_empty()); - output_buffers = mspace_calloc(io_mspace, num_buffers, sizeof(output_buffer)); - assert(output_buffers != NULL); - - /* Initialize understudy buffer */ - assert(undy_buffer.data == NULL); - init_buffer(&undy_buffer, malloc(1), 1); - - /* Initialize buffers */ - int i; - for (i = 0; i < num_buffers; ++i) { - char *data = mspace_malloc(io_mspace, 1); - init_buffer(&output_buffers[i], data, 1); - } - /* From this point forward, only the task will access its buffer */ +static void +io_group_init(void) +{ + num_buffers = BOP_get_group_size() - 1; /* - main */ + + /* Create a shared memory space */ + if (!io_mspace) + io_mspace = create_mspace(0, 1, 1); /* Default size, locked, shared */ + assert(io_mspace != NULL); + + /* Create a set of output buffers */ + assert(output_buffers == NULL || all_buffs_empty()); + output_buffers = + mspace_calloc(io_mspace, num_buffers, sizeof(output_buffer)); + assert(output_buffers != NULL); + + /* Initialize understudy buffer */ + assert(undy_buffer.data == NULL); + init_buffer(&undy_buffer, malloc(1), 1); + + /* Initialize buffers */ + int i; + + for (i = 0; i < num_buffers; ++i) { + char *data = mspace_malloc(io_mspace, 1); + + init_buffer(&output_buffers[i], data, 1); + } + /* From this point forward, only the task will access its buffer */ } -static void free_all_buffers( void ) { - /* Free buffers */ - free(undy_buffer.data); - undy_buffer.data = NULL; +static void +free_all_buffers(void) +{ + /* Free buffers */ + free(undy_buffer.data); + undy_buffer.data = NULL; + + int i; - int i; - for (i = 0; i < num_buffers; ++i) - mspace_free(io_mspace, output_buffers[i].data); - mspace_free(io_mspace, output_buffers); - output_buffers = NULL; + for (i = 0; i < num_buffers; ++i) + mspace_free(io_mspace, output_buffers[i].data); + mspace_free(io_mspace, output_buffers); + output_buffers = NULL; } -static void io_group_succ( void ) { - /* Print specs */ - int i; - for (i = 0; i < num_buffers; ++i) - printf("%s", output_buffers[i].data); +static void +io_group_succ(void) +{ + /* Print specs */ + int i; - free_all_buffers( ); + for (i = 0; i < num_buffers; ++i) + printf("%s", output_buffers[i].data); + + free_all_buffers(); } -static void io_undy_succ( void ) { - /* Print undy */ - printf("%s", undy_buffer.data); +static void +io_undy_succ(void) +{ + /* Print undy */ + printf("%s", undy_buffer.data); - free_all_buffers( ); + free_all_buffers(); } -void io_on_malloc_rescue(){ - free_all_buffers(); - init_buffer(&undy_buffer, malloc(1), 1); + +void +io_on_malloc_rescue() +{ + free_all_buffers(); + init_buffer(&undy_buffer, malloc(1), 1); } -bop_port_t bop_io_port = { - .ppr_group_init = io_group_init, - .task_group_succ_fini = io_group_succ, - .undy_succ_fini = io_undy_succ -}; + +bop_port_t bop_io_port = {.ppr_group_init = io_group_init, + .task_group_succ_fini = io_group_succ, + .undy_succ_fini = io_undy_succ}; /**Terminal IO functions*/ extern int monitor_process_id; -extern int monitor_group; //Note: this value is negated! -int terminal_helper(char* msg, int gpid){ - //return true on success - block_signal(SIGTTIN); - int e = tcsetpgrp(STDIN_FILENO, gpid < 0 ? -gpid : gpid); - if(e != 0){ - if(BOP_get_verbose() > 2) - perror(msg); - } - unblock_signal(SIGTTIN); - return e; +extern int monitor_group; // Note: this value is negated! +int +terminal_helper(char *msg, int gpid) +{ + // return true on success + block_signal(SIGTTIN); + int e = tcsetpgrp(STDIN_FILENO, gpid < 0 ? -gpid : gpid); + + if (e != 0) { + if (BOP_get_verbose() > 2) + perror(msg); + } + unblock_signal(SIGTTIN); + return e; } -bool given_to_workers = false; //starts in the monitor proc -int bop_terminal_to_monitor(){ - given_to_workers = false; - return terminal_helper("Couldn't send terminal to monitor process", monitor_process_id); + +bool given_to_workers = false; // starts in the monitor proc +int +bop_terminal_to_monitor() +{ + given_to_workers = false; + return terminal_helper("Couldn't send terminal to monitor process", + monitor_process_id); } -int bop_terminal_to_workers(){ - if(!given_to_workers) - return terminal_helper("Couldn't send terminal to worker processes", monitor_group); - return 0; + +int +bop_terminal_to_workers() +{ + if (!given_to_workers) + return terminal_helper("Couldn't send terminal to worker processes", + monitor_group); + return 0; } diff --git a/bop_map.h b/bop_map.h index 1452308..b39b478 100644 --- a/bop_map.h +++ b/bop_map.h @@ -5,42 +5,60 @@ #include "external/malloc.h" typedef struct _range_node_t { - struct _range_node_t *lc, *rc; - mem_range_t r; + struct _range_node_t *lc, *rc; + mem_range_t r; } range_node_t; typedef struct { - char is_hash; - mspace residence; /* where the map is stored */ - range_node_t *root; - size_t size; - char *name; + char is_hash; + mspace residence; /* where the map is stored */ + range_node_t *root; + size_t size; + char *name; } map_t; -void init_empty_map( map_t *ret, mspace res, char *nm ); -map_t *new_range_set( mspace ms, char *nm ); -map_t *map_clone( map_t *base, mspace space ); +void +init_empty_map(map_t *ret, mspace res, char *nm); +map_t * +new_range_set(mspace ms, char *nm); +map_t * +map_clone(map_t *base, mspace space); -mem_range_t *map_add_range( map_t *map, addr_t base, size_t size, void *rec ); -mem_range_t *map_add_range_from_task(map_t *map, addr_t base, size_t size, void *obj, unsigned ppr_id); -mem_range_t *map_remove( map_t *map, addr_t addr ); +mem_range_t * +map_add_range(map_t *map, addr_t base, size_t size, void *rec); +mem_range_t * +map_add_range_from_task( + map_t *map, addr_t base, size_t size, void *obj, unsigned ppr_id); +mem_range_t * +map_remove(map_t *map, addr_t addr); -mem_range_t *map_contains( map_t *map, addr_t addr ); -char map_overlaps( map_t *map, mem_range_t *inp, mem_range_t *c_range); +mem_range_t * +map_contains(map_t *map, addr_t addr); +char +map_overlaps(map_t *map, mem_range_t *inp, mem_range_t *c_range); -void map_foreach( map_t *map, void (*func)(mem_range_t *) ); -void map_inject( map_t *map, void *sum, void (*func)( void *, mem_range_t * ) ); +void +map_foreach(map_t *map, void (*func)(mem_range_t *)); +void +map_inject(map_t *map, void *sum, void (*func)(void *, mem_range_t *)); -void map_to_array(map_t *map, mem_range_t **ranges, unsigned *size); +void +map_to_array(map_t *map, mem_range_t **ranges, unsigned *size); /* Destructive: the ref_map is freed afterwards */ -void map_intersect( map_t *base_map, map_t *ref_map ); -void map_union( map_t *base_map, map_t *ref_map ); +void +map_intersect(map_t *base_map, map_t *ref_map); +void +map_union(map_t *base_map, map_t *ref_map); -void map_free( map_t *map ); -void map_clear( map_t *map ); +void +map_free(map_t *map); +void +map_clear(map_t *map); -size_t map_size_in_bytes( map_t *map ); -void map_inspect( int verbose, map_t *map ); +size_t +map_size_in_bytes(map_t *map); +void +map_inspect(int verbose, map_t *map); #endif diff --git a/bop_merge.c b/bop_merge.c index 816d1db..ac6bb8e 100644 --- a/bop_merge.c +++ b/bop_merge.c @@ -1,271 +1,376 @@ -#include /* for PRIdPTR */ -#include /* for NULL */ -#include /* for memcpy */ #include "bop_api.h" -#include "external/malloc.h" -#include "bop_ports.h" -#include "bop_merge.h" #include "bop_map.h" +#include "bop_merge.h" +#include "bop_ports.h" +#include "external/malloc.h" +#include /* for PRIdPTR */ +#include /* for NULL */ +#include /* for memcpy */ + +map_t read_map = {.residence = NULL} -map_t read_map = {.residence = NULL}, write_map; +, + write_map; -mspace commit_space = NULL; /* shared memory space for merge meta data*/ -mspace metacow_space = NULL; /* copy-on-write memory */ -map_t *patches = NULL; /* an array of map_t */ +mspace commit_space = NULL; /* shared memory space for merge meta data */ +mspace metacow_space = NULL; /* copy-on-write memory */ +map_t *patches = NULL; /* an array of map_t */ unsigned num_patches; map_t *write_union = NULL; -static void ppr_reset( void ) { - map_clear( & read_map ); - map_clear( & write_map ); +static void +ppr_reset(void) +{ + map_clear(&read_map); + map_clear(&write_map); } -void BOP_record_read(void* addr, size_t size) { - if ( task_status == UNDY || task_status == SEQ ) return; - if ( ppr_pos == GAP ) return; - if ( read_map.residence == NULL ) return; /* not initialized */ - - map_add_range( & read_map, (addr_t) addr, size, NULL ); +void +BOP_record_read(void *addr, size_t size) +{ + if (task_status == UNDY || task_status == SEQ) + return; + if (ppr_pos == GAP) + return; + if (read_map.residence == NULL) + return; /* not initialized */ + + map_add_range(&read_map, (addr_t)addr, size, NULL); } extern char in_ordered_region; extern map_t ordered_writes; -void BOP_record_write(void* addr, size_t size) { - if ( task_status == UNDY || task_status == SEQ ) return; - if ( ppr_pos == GAP ) return; - if ( read_map.residence == NULL ) return; /* not initialized */ +void +BOP_record_write(void *addr, size_t size) +{ + if (task_status == UNDY || task_status == SEQ) + return; + if (ppr_pos == GAP) + return; + if (read_map.residence == NULL) + return; /* not initialized */ - map_add_range( & write_map, (addr_t) addr, size, NULL ); + map_add_range(&write_map, (addr_t)addr, size, NULL); - if ( in_ordered_region ) - map_add_range( & ordered_writes, (addr_t) addr, size, NULL ); + if (in_ordered_region) + map_add_range(&ordered_writes, (addr_t)addr, size, NULL); } -static void free_shm_copy( mem_range_t *r ) { - mspace_free( commit_space, r->rec ); +static void +free_shm_copy(mem_range_t *r) +{ + mspace_free(commit_space, r->rec); } /* Patch initialization is done by individual tasks, and the cleaning - up is done by the last spec task. */ -static void bop_merge_init( void ) { - if (commit_space == NULL) { - char use_lock = 1; - char is_shared_mem = 1; /* true */ - size_t init_size = 100000000; /* 100MB init size */ - commit_space = create_mspace( init_size, use_lock, is_shared_mem ); - use_lock = 0; - is_shared_mem = 0; - write_union = new_range_set( commit_space, "write_union" ); - num_patches = BOP_get_group_size(); - patches = (map_t *) mspace_calloc( commit_space, - num_patches, - sizeof(map_t) ); - metacow_space = create_mspace( init_size, use_lock, is_shared_mem ); - bop_msg( 3, "created commit (shared memory) mspace at %p", commit_space ); - init_empty_map( & read_map, metacow_space, "read_map" ); - init_empty_map( & write_map, metacow_space, "write_map" ); - } - else { - unsigned gs = BOP_get_group_size(); - if ( num_patches < gs ) - patches = (map_t *) mspace_realloc( commit_space, patches, - gs * sizeof(map_t) ); - num_patches = gs; - map_clear( write_union ); - } - - bop_msg(4, "bop_merge_init: (%d) patches and write union map (re-)initialized", num_patches ); + * up is done by the last spec task. */ +static void +bop_merge_init(void) +{ + if (commit_space == NULL) { + char use_lock = 1; + char is_shared_mem = 1; /* true */ + size_t init_size = 100000000; /* 100MB init size */ + + commit_space = create_mspace(init_size, use_lock, is_shared_mem); + use_lock = 0; + is_shared_mem = 0; + write_union = new_range_set(commit_space, "write_union"); + num_patches = BOP_get_group_size(); + patches = + (map_t *)mspace_calloc(commit_space, num_patches, sizeof(map_t)); + metacow_space = create_mspace(init_size, use_lock, is_shared_mem); + bop_msg( + 3, "created commit (shared memory) mspace at %p", commit_space); + init_empty_map(&read_map, metacow_space, "read_map"); + init_empty_map(&write_map, metacow_space, "write_map"); + } else { + unsigned gs = BOP_get_group_size(); + + if (num_patches < gs) + patches = (map_t *)mspace_realloc( + commit_space, patches, gs * sizeof(map_t)); + num_patches = gs; + map_clear(write_union); + } + + bop_msg( + 4, + "bop_merge_init: (%d) patches and write union map (re-)initialized", + num_patches); } -static inline char mem_range_eq( mem_range_t *r1, mem_range_t *r2 ) { - return r1->base == r2->base && r1->size == r2->size; +static inline char +mem_range_eq(mem_range_t *r1, mem_range_t *r2) +{ + return r1->base == r2->base && r1->size == r2->size; } -extern map_t received, received_n_used; /* postwait.c */ +extern map_t received, received_n_used; /* postwait.c */ addr_t conflict_addr; /* Check my access map with write_union while updating write_union. Return the - base of a conflict range. 0 if there is no conflict. */ -static addr_t check_for_overlap( map_t *my_access, char is_write_map ) { - int i; - bop_msg( 2, "%d ranges in %s", my_access->size, my_access->name ); - map_inspect(5, my_access); - - if ( write_union->size == 0 ) return 0; - - mem_range_t *my_ranges; unsigned num; - map_to_array( my_access, &my_ranges, &num ); - - for (i = 0; i < num; i ++) { - mem_range_t *mseg = &my_ranges[ i ]; - mem_range_t access_overlap, recv_overlap; - char same_access, same_recv; - - bop_msg(4, "testing range %d, from %p ["PRIdPTR"] for %zd bytes", i, mseg->base, mseg->base >> PAGESIZEX, mseg->size); - - mem_range_t tseg = *mseg; - char still_conf_free = 1; - - // do { - same_access = map_overlaps(write_union, &tseg, &access_overlap); - - if (same_access) { - mem_range_t *mod_range = map_contains(write_union, access_overlap.base); - bop_msg(2, "Overlap with access map from %p ["PRIdPTR"] for %zd bytes, %s %p-%p for %zd bytes, write union %p-%p for %zd bytes", access_overlap.base, access_overlap.base >> PAGESIZEX, access_overlap.size, my_access->name, mseg->base, mseg->base+mseg->size, mseg->size, mod_range->base, mod_range->base + mod_range->size, mod_range->size); - - still_conf_free = 0; - if ( mem_range_eq( &access_overlap, mseg ) ) { - - mem_range_t *acc_range = map_contains(write_union, access_overlap.base); - conflict_addr = access_overlap.base; - if ( mem_range_eq( acc_range, &access_overlap) ) { - same_recv = map_overlaps( & received, & tseg, & recv_overlap); - if (same_recv) { - bop_msg(3, "Overlap with receive set from %p ["PRIdPTR"] for %zd bytes", recv_overlap.base, recv_overlap.base >> PAGESIZEX, recv_overlap.size); - - if ( mem_range_eq( &access_overlap, &recv_overlap) ) { - mem_range_t *recv_range = map_contains( & received, recv_overlap.base ); - if (recv_range->task == acc_range->task ) { - bop_msg(2, "The overlap is not a conflict as the data was received from the last writer %d", recv_range->task); - /* save it to check for modify-after-post conflicts */ - map_add_range_from_task( & received_n_used, - acc_range->base, acc_range->size, - recv_range->rec, acc_range->task ); - still_conf_free = 1; - } - else - bop_msg(2, "The overlap is a post-wait ordering conflict since the page was received from %d but last written by %d", recv_range->task, acc_range->task ); - } - } - else - bop_msg( 1, "Read or write conflict with a prior task" ); - } - else { - bop_msg( 2, "The range in write_union, %p for %zu bytes, does not equal to the overlap. Treat it as a conflict", acc_range->base, acc_range->size); - } - } - else - bop_msg( 2, "The range in %s, %p for %zu bytes, does not equal to the overlap. Treat it as a conflict", my_access->name, mseg->base, mseg->size ); - - if ( !still_conf_free) - return access_overlap.base; - + * base of a conflict range. 0 if there is no conflict. */ +static addr_t +check_for_overlap(map_t *my_access, char is_write_map) +{ + int i; + + bop_msg(2, "%d ranges in %s", my_access->size, my_access->name); + map_inspect(5, my_access); + + if (write_union->size == 0) + return 0; + + mem_range_t *my_ranges; + unsigned num; + + map_to_array(my_access, &my_ranges, &num); + + for (i = 0; i < num; i++) { + mem_range_t *mseg = &my_ranges[i]; + mem_range_t access_overlap, recv_overlap; + char same_access, same_recv; + + bop_msg(4, + "testing range %d, from %p [" PRIdPTR "] for %zd bytes", + i, + mseg->base, + mseg->base >> PAGESIZEX, + mseg->size); + + mem_range_t tseg = *mseg; + char still_conf_free = 1; + + // do { + same_access = map_overlaps(write_union, &tseg, &access_overlap); + + if (same_access) { + mem_range_t *mod_range = + map_contains(write_union, access_overlap.base); + + bop_msg(2, + "Overlap with access map from %p [" PRIdPTR + "] for %zd bytes, %s %p-%p for %zd bytes, write union " + "%p-%p for %zd bytes", + access_overlap.base, + access_overlap.base >> PAGESIZEX, + access_overlap.size, + my_access->name, + mseg->base, + mseg->base + mseg->size, + mseg->size, + mod_range->base, + mod_range->base + mod_range->size, + mod_range->size); + + still_conf_free = 0; + if (mem_range_eq(&access_overlap, mseg)) { + mem_range_t *acc_range = + map_contains(write_union, access_overlap.base); + + conflict_addr = access_overlap.base; + if (mem_range_eq(acc_range, &access_overlap)) { + same_recv = map_overlaps(&received, &tseg, &recv_overlap); + if (same_recv) { + bop_msg(3, + "Overlap with receive set from %p [" PRIdPTR + "] for %zd bytes", + recv_overlap.base, + recv_overlap.base >> PAGESIZEX, + recv_overlap.size); + + if (mem_range_eq(&access_overlap, &recv_overlap)) { + mem_range_t *recv_range = + map_contains(&received, recv_overlap.base); + + if (recv_range->task == acc_range->task) { + bop_msg(2, + "The overlap is not a conflict as the " + "data was received from the last " + "writer %d", + recv_range->task); + /* save it to check for modify-after-post + * conflicts */ + map_add_range_from_task(&received_n_used, + acc_range->base, + acc_range->size, + recv_range->rec, + acc_range->task); + still_conf_free = 1; + } else + bop_msg(2, + "The overlap is a post-wait ordering " + "conflict since the page was received " + "from %d but last written by %d", + recv_range->task, + acc_range->task); + } + } else + bop_msg(1, "Read or write conflict with a prior task"); + } else { + bop_msg(2, + "The range in write_union, %p for %zu bytes, does " + "not equal to the overlap. Treat it as a " + "conflict", + acc_range->base, + acc_range->size); + } + } else + bop_msg(2, + "The range in %s, %p for %zu bytes, does not equal to " + "the overlap. Treat it as a conflict", + my_access->name, + mseg->base, + mseg->size); + + if (!still_conf_free) + return access_overlap.base; + } + //} while ( same_access && still_conf_free ); } - //} while ( same_access && still_conf_free ); - } - return 0; + return 0; } -void union_add_range( mem_range_t *range ) { - map_add_range_from_task( write_union, range->base, range->size, NULL, BOP_ppr_index( ) ); +void +union_add_range(mem_range_t *range) +{ + map_add_range_from_task( + write_union, range->base, range->size, NULL, BOP_ppr_index()); } /* Return 1 if no conflict found, otherwise 0 */ -static int ppr_is_correct( void ) { - - if ( task_status == UNDY || task_status == SEQ ) return 1; - - bop_msg( 3, "%d ranges in %s", write_union->size, write_union->name ); - bop_msg(3,"Check for dependence conflicts"); - - addr_t ret = check_for_overlap( & read_map, 0 /* not write map */ ); - if (ret != 0) { - bop_msg(1, "Read-after-write conflict. Address %p, page "PRIuPTR".\n", ret, ret >> PAGESIZEX); - return 0; - } - map_foreach( & write_map, union_add_range ); +static int +ppr_is_correct(void) +{ + if (task_status == UNDY || task_status == SEQ) + return 1; + + bop_msg(3, "%d ranges in %s", write_union->size, write_union->name); + bop_msg(3, "Check for dependence conflicts"); + + addr_t ret = check_for_overlap(&read_map, 0 /* not write map */); + + if (ret != 0) { + bop_msg(1, + "Read-after-write conflict. Address %p, page " PRIuPTR ".\n", + ret, + ret >> PAGESIZEX); + return 0; + } + map_foreach(&write_map, union_add_range); - bop_msg( 3, "%d ranges in %s", write_union->size, write_union->name ); - map_inspect( 5, write_union ); + bop_msg(3, "%d ranges in %s", write_union->size, write_union->name); + map_inspect(5, write_union); - /* ret = check_for_overlap( write_map, 1 ); union the write map */ - return 1; /* correctness check passed */ + /* ret = check_for_overlap( write_map, 1 ); union the write map */ + return 1; /* correctness check passed */ } - struct patch_inject_t { - map_t *patch; - unsigned total; + map_t *patch; + unsigned total; }; -static void add_range_block( void *_sum, mem_range_t *range ) { - struct patch_inject_t *sum = (struct patch_inject_t *) _sum; - char *data_rec; - data_rec = (char*) mspace_calloc( sum->patch->residence, 1, range->size ); - memcpy( data_rec, (void*) range->base, range->size ); - map_add_range( sum->patch, range->base, range->size, data_rec ); - sum->total += range->size; +static void +add_range_block(void *_sum, mem_range_t *range) +{ + struct patch_inject_t *sum = (struct patch_inject_t *)_sum; + char *data_rec; + + data_rec = (char *)mspace_calloc(sum->patch->residence, 1, range->size); + memcpy(data_rec, (void *)range->base, range->size); + map_add_range(sum->patch, range->base, range->size, data_rec); + sum->total += range->size; } /* If col is NULL, create a new collection. Otherwise, augment. */ -void create_patch( map_t *patch, map_t *change_set, mspace space ) { - init_empty_map( patch, space, "patch" ); +void +create_patch(map_t *patch, map_t *change_set, mspace space) +{ + init_empty_map(patch, space, "patch"); - struct patch_inject_t sum = { - .patch = patch, - .total = 0 - }; + struct patch_inject_t sum = {.patch = patch, .total = 0}; - map_inject( change_set, &sum, add_range_block ); + map_inject(change_set, &sum, add_range_block); - bop_stats.data_copied += sum.total; - bop_msg(2, "Created a patch with %d range(s) for a total of %d bytes.", patch->size, sum.total); + bop_stats.data_copied += sum.total; + bop_msg(2, + "Created a patch with %d range(s) for a total of %d bytes.", + patch->size, + sum.total); } -static void apply_range_block( void *_sum, mem_range_t *range ) { - unsigned *sum = (unsigned *) _sum; - memcpy( (void *) range->base, range->rec, range->size ); - bop_msg(6, "Copy-in starting %p (page "PRIdPTR") for %zd bytes.", range->base, range->base >> PAGESIZEX, range->size ); - *sum += range->size; +static void +apply_range_block(void *_sum, mem_range_t *range) +{ + unsigned *sum = (unsigned *)_sum; + + memcpy((void *)range->base, range->rec, range->size); + bop_msg(6, + "Copy-in starting %p (page " PRIdPTR ") for %zd bytes.", + range->base, + range->base >> PAGESIZEX, + range->size); + *sum += range->size; } -void apply_patch( map_t *patch ) { - unsigned sum = 0; - map_inject( patch, &sum, apply_range_block ); - bop_stats.data_copied += sum; - map_clear( patch ); /* cleaning up */ +void +apply_patch(map_t *patch) +{ + unsigned sum = 0; + + map_inject(patch, &sum, apply_range_block); + bop_stats.data_copied += sum; + map_clear(patch); /* cleaning up */ } -static void free_range_data( void *space, mem_range_t *range ) { - mspace_free( (mspace) space, range->rec ); /* cleaning up */ +static void +free_range_data(void *space, mem_range_t *range) +{ + mspace_free((mspace)space, range->rec); /* cleaning up */ } -void clear_patch( map_t *patch ) { - map_inject( patch, (void*) patch->residence, free_range_data ); - map_clear( patch ); +void +clear_patch(map_t *patch) +{ + map_inject(patch, (void *)patch->residence, free_range_data); + map_clear(patch); } -static void ppr_commit( void ) { - assert( spec_order >= 0 ); - bop_msg(3, "Data commit start"); - create_patch( & patches[ spec_order ], & write_map, commit_space ); - bop_msg(3, "Data commit done"); +static void +ppr_commit(void) +{ + assert(spec_order >= 0); + bop_msg(3, "Data commit start"); + create_patch(&patches[spec_order], &write_map, commit_space); + bop_msg(3, "Data commit done"); } -static void ppr_group_commit( void ) { - /* copy updated data */ - bop_msg(4, "Copying in modified data."); - int ppr; - for (ppr = 0 ; ppr <= spec_order ; ppr ++ ) { - apply_patch( & patches[ ppr ] ); +static void +ppr_group_commit(void) +{ + /* copy updated data */ + bop_msg(4, "Copying in modified data."); + int ppr; - bop_msg(4, "Copied modified data from group member %d.", ppr); - } + for (ppr = 0; ppr <= spec_order; ppr++) { + apply_patch(&patches[ppr]); - for (ppr = 0 ; ppr <= spec_order ; ppr ++ ) { - clear_patch( & patches[ ppr ] ); - } + bop_msg(4, "Copied modified data from group member %d.", ppr); + } - // map_clear( write_union ); // do it in task group init + for (ppr = 0; ppr <= spec_order; ppr++) { + clear_patch(&patches[ppr]); + } + // map_clear( write_union ); // do it in task group init } -bop_port_t bop_merge_port = { - .ppr_group_init = bop_merge_init, - .ppr_task_init = ppr_reset, - .ppr_check_correctness = ppr_is_correct, - .data_commit = ppr_commit, - .task_group_commit = ppr_group_commit -}; +bop_port_t bop_merge_port = {.ppr_group_init = bop_merge_init, + .ppr_task_init = ppr_reset, + .ppr_check_correctness = ppr_is_correct, + .data_commit = ppr_commit, + .task_group_commit = ppr_group_commit}; diff --git a/bop_merge.h b/bop_merge.h index 2badc79..f06fc1a 100644 --- a/bop_merge.h +++ b/bop_merge.h @@ -3,7 +3,9 @@ #include "bop_map.h" -void create_patch( map_t *patch, map_t *change_set, mspace space ); -void clear_patch( map_t *patch ); +void +create_patch(map_t *patch, map_t *change_set, mspace space); +void +clear_patch(map_t *patch); #endif /* __BOP_MERGE_H */ diff --git a/bop_ordered.c b/bop_ordered.c index 3e344dd..6a170af 100644 --- a/bop_ordered.c +++ b/bop_ordered.c @@ -3,72 +3,100 @@ #include "bop_api.h" #include "bop_map.h" #include "bop_ports.h" +#include "bop_ppr_sync.h" #include "external/malloc.h" #include "postwait.h" -#include "bop_ppr_sync.h" extern mspace metacow_space; map_t ordered_writes = {.residence = NULL}; + char in_ordered_region = 0; addr_t ordered_region_id; -static addr_t channel_for_region( addr_t region_id ) { - int gs = BOP_get_group_size( ); - return region_id * gs + BOP_ppr_index( ); +static addr_t +channel_for_region(addr_t region_id) +{ + int gs = BOP_get_group_size(); + + return region_id * gs + BOP_ppr_index(); } -void BOP_ordered_begin( addr_t id ) { - if ( ordered_writes.residence == NULL ) { - bop_msg( 2, "BOP ordered port not active. BOP_ordered_region( "PRIdPTR" ) ignored.", id ); - return; - } - - if ( ! in_ordered_region ) { - in_ordered_region = 1; - ordered_region_id = id; - bop_msg( 2, "Entering ordered region "PRIdPTR, id ); - addr_t my_ch = channel_for_region( id ); - channel_wait( my_ch - 1 ); - on_enter_ordered(); - } - else - bop_msg( 2, "Currently in ordered region "PRIdPTR". BOP_ordered_region( "PRIdPTR" ) ignored.", ordered_region_id, id ); +void +BOP_ordered_begin(addr_t id) +{ + if (ordered_writes.residence == NULL) { + bop_msg(2, + "BOP ordered port not active. BOP_ordered_region( " PRIdPTR + " ) ignored.", + id); + return; + } + + if (!in_ordered_region) { + in_ordered_region = 1; + ordered_region_id = id; + bop_msg(2, "Entering ordered region " PRIdPTR, id); + addr_t my_ch = channel_for_region(id); + + channel_wait(my_ch - 1); + on_enter_ordered(); + } else + bop_msg(2, + "Currently in ordered region " PRIdPTR + ". BOP_ordered_region( " PRIdPTR " ) ignored.", + ordered_region_id, + id); } /* pass over, leave out, disregard */ -void BOP_ordered_skip( addr_t id ) { - addr_t my_ch = channel_for_region( id ); - channel_chain( my_ch - 1, my_ch ); +void +BOP_ordered_skip(addr_t id) +{ + addr_t my_ch = channel_for_region(id); + + channel_chain(my_ch - 1, my_ch); } -static void fill_range( void *sum, mem_range_t *range ) { - addr_t ch = (addr_t) sum; - channel_fill( ch, range->base, range->size ); +static void +fill_range(void *sum, mem_range_t *range) +{ + addr_t ch = (addr_t)sum; + + channel_fill(ch, range->base, range->size); } -void BOP_ordered_end( addr_t id ) { - if ( in_ordered_region && ordered_region_id == id ) { - bop_msg( 2, "Leaving ordered region %"PRIdPTR, id ); - addr_t my_ch = channel_for_region( id ); - map_inject( & ordered_writes, (void *) my_ch, fill_range ); - channel_post( my_ch ); - on_exit_ordered(); - map_clear( & ordered_writes ); - in_ordered_region = 0; - - } - else - bop_msg( 2, "No matching ordered region (%d "PRIdPTR"). BOP_ordered_end( "PRIdPTR" ) ignored.", in_ordered_region, ordered_region_id, id ); +void +BOP_ordered_end(addr_t id) +{ + if (in_ordered_region && ordered_region_id == id) { + bop_msg(2, "Leaving ordered region %" PRIdPTR, id); + addr_t my_ch = channel_for_region(id); + + map_inject(&ordered_writes, (void *)my_ch, fill_range); + channel_post(my_ch); + on_exit_ordered(); + map_clear(&ordered_writes); + in_ordered_region = 0; + + } else + bop_msg(2, + "No matching ordered region (%d " PRIdPTR + "). BOP_ordered_end( " PRIdPTR " ) ignored.", + in_ordered_region, + ordered_region_id, + id); } -static void ppr_reset( void ) { - if ( ordered_writes.residence == NULL ) - init_empty_map( & ordered_writes, metacow_space, "ordered_writes" ); - else - map_clear( & ordered_writes ); +static void +ppr_reset(void) +{ + if (ordered_writes.residence == NULL) + init_empty_map(&ordered_writes, metacow_space, "ordered_writes"); + else + map_clear(&ordered_writes); } bop_port_t bop_ordered_port = { - .ppr_task_init = ppr_reset, + .ppr_task_init = ppr_reset, }; diff --git a/bop_ports.c b/bop_ports.c index 30f6390..054ba74 100644 --- a/bop_ports.c +++ b/bop_ports.c @@ -1,147 +1,193 @@ -#include // for NULL -#include #include "bop_api.h" #include "bop_ports.h" #include "bop_ppr_sync.h" +#include +#include // for NULL static bop_port_t **bop_ports = NULL; static unsigned num_ports, alloc_size; -void register_port( bop_port_t *port, char * desc ) { - assert( BOP_task_status() == SEQ ); - if (bop_ports == NULL) { - bop_ports = (bop_port_t **) calloc( 10, sizeof(bop_port_t*) ); - alloc_size = 10; - num_ports = 0; - } - else if (num_ports == alloc_size) { - bop_ports = (bop_port_t **) - realloc( bop_ports, alloc_size*2*sizeof(bop_port_t*)); - alloc_size *= 2; - } - - bop_ports[ num_ports ] = port; - num_ports ++; - - bop_msg( 3, "New BOP port %s (num. %d, %p) is added.", - desc, num_ports, port ); +void +register_port(bop_port_t *port, char *desc) +{ + assert(BOP_task_status() == SEQ); + if (bop_ports == NULL) { + bop_ports = (bop_port_t **)calloc(10, sizeof(bop_port_t *)); + alloc_size = 10; + num_ports = 0; + } else if (num_ports == alloc_size) { + bop_ports = (bop_port_t **)realloc( + bop_ports, alloc_size * 2 * sizeof(bop_port_t *)); + alloc_size *= 2; + } + + bop_ports[num_ports] = port; + num_ports++; + + bop_msg( + 3, "New BOP port %s (num. %d, %p) is added.", desc, num_ports, port); } -static int port_call_int_func( int func(void) ) { - if (func != NULL ) - return ( * func )( ); - else - return TRUE; +static int +port_call_int_func(int func(void)) +{ + if (func != NULL) + return (*func)(); + else + return TRUE; } -static void port_call( void func(void) ) { - if (func != NULL ) - ( * func )( ); +static void +port_call(void func(void)) +{ + if (func != NULL) + (*func)(); } -void ppr_group_init( void ) { - int i; - for (i = 0; i < num_ports; i ++) - port_call( bop_ports[i]->ppr_group_init ); +void +ppr_group_init(void) +{ + int i; + + for (i = 0; i < num_ports; i++) + port_call(bop_ports[i]->ppr_group_init); } -void ppr_task_init( void ) { - int i; - for (i = 0; i < num_ports; i ++) - port_call( bop_ports[i]->ppr_task_init ); + +void +ppr_task_init(void) +{ + int i; + + for (i = 0; i < num_ports; i++) + port_call(bop_ports[i]->ppr_task_init); } + extern addr_t conflict_addr; -void report_conflict( void ) { - int i; - for (i = 0; i < num_ports; i ++) - if ( bop_ports[i]->report_conflict != NULL ) - ( * bop_ports[i]->report_conflict )( conflict_addr ); -} -int ppr_check_correctness( void ) { - int i, passed = TRUE; - for (i = 0; i < num_ports && passed; i ++) - passed = passed && - port_call_int_func( bop_ports[i]->ppr_check_correctness ); - if ( !passed ) report_conflict( ); - return passed; -} -void data_commit( void ) { - int i; - for (i = 0; i < num_ports; i ++) - port_call( bop_ports[i]->data_commit ); +void +report_conflict(void) +{ + int i; + + for (i = 0; i < num_ports; i++) + if (bop_ports[i]->report_conflict != NULL) + (*bop_ports[i]->report_conflict)(conflict_addr); } -void task_group_commit( void ) { - int i; - for (i = 0; i < num_ports; i ++) - port_call( bop_ports[i]->task_group_commit ); + +int +ppr_check_correctness(void) +{ + int i, passed = TRUE; + + for (i = 0; i < num_ports && passed; i++) + passed = + passed && port_call_int_func(bop_ports[i]->ppr_check_correctness); + if (!passed) + report_conflict(); + return passed; } -void task_group_succ_fini( void ) { - int i; - bop_msg(3, "Task Group Succ Fini"); - for (i = 0; i < num_ports; i ++) - port_call( bop_ports[i]->task_group_succ_fini ); +void +data_commit(void) +{ + int i; + + for (i = 0; i < num_ports; i++) + port_call(bop_ports[i]->data_commit); } -void undy_init( void ) { - int i; - for (i = 0; i < num_ports; i ++) - port_call( bop_ports[i]->undy_init ); +void +task_group_commit(void) +{ + int i; + + for (i = 0; i < num_ports; i++) + port_call(bop_ports[i]->task_group_commit); } -void undy_succ_fini( void ) { - int i; - for (i = 0; i < num_ports; i ++) { - if (bop_ports[i]->undy_succ_fini!=NULL) bop_msg( 1, "bop_ports[%d]->undy_succ_fini", i ); - port_call( bop_ports[i]->undy_succ_fini ); - } +void +task_group_succ_fini(void) +{ + int i; + + bop_msg(3, "Task Group Succ Fini"); + for (i = 0; i < num_ports; i++) + port_call(bop_ports[i]->task_group_succ_fini); } -void on_exit_ordered( void ) { - int i; - for (i = 0; i < num_ports; i ++) { - if (bop_ports[i]->on_exit_ordered!=NULL) - port_call( bop_ports[i]->on_exit_ordered ); - } +void +undy_init(void) +{ + int i; + + for (i = 0; i < num_ports; i++) + port_call(bop_ports[i]->undy_init); } -void on_enter_ordered( void ) { - int i; - for (i = 0; i < num_ports; i ++) { - if (bop_ports[i]->on_enter_ordered!=NULL) - port_call( bop_ports[i]->on_enter_ordered ); - } +void +undy_succ_fini(void) +{ + int i; + + for (i = 0; i < num_ports; i++) { + if (bop_ports[i]->undy_succ_fini != NULL) + bop_msg(1, "bop_ports[%d]->undy_succ_fini", i); + port_call(bop_ports[i]->undy_succ_fini); + } } -/* Port code gen. See [compiler repos]/tools/scripts/codegen.rb +void +on_exit_ordered(void) +{ + int i; -methods = ["ppr_group_init", "ppr_task_init", "spec_check", "data_commit", "task_group_commit", "task_group_succ_fini", "undy_init", "undy_succ_fini"] - -def gen_decl( methods ) - a = "typedef struct {\n" - methods.each { |m| - a += " void (*#{m})( void );\n" - } - a += "} bop_port_t;\n" - puts a -end - -def gen_one_func( nm ) - return <#{nm} ); + for (i = 0; i < num_ports; i++) { + if (bop_ports[i]->on_exit_ordered != NULL) + port_call(bop_ports[i]->on_exit_ordered); + } } -Q -end -def gen_funcs( methods ) - methods.each { |m| - puts gen_one_func( m ) - } -end +void +on_enter_ordered(void) +{ + int i; -gen_decl(methods) -gen_funcs(methods) + for (i = 0; i < num_ports; i++) { + if (bop_ports[i]->on_enter_ordered != NULL) + port_call(bop_ports[i]->on_enter_ordered); + } +} -*/ +/* Port code gen. See [compiler repos]/tools/scripts/codegen.rb + * + * methods = ["ppr_group_init", "ppr_task_init", "spec_check", "data_commit", + * "task_group_commit", "task_group_succ_fini", "undy_init", "undy_succ_fini"] + * + * def gen_decl( methods ) + * a = "typedef struct {\n" + * methods.each { |m| + * a += " void (*#{m})( void );\n" + * } + * a += "} bop_port_t;\n" + * puts a + * end + * + * def gen_one_func( nm ) + * return <#{nm} ); + * } + * Q + * end + * + * def gen_funcs( methods ) + * methods.each { |m| + * puts gen_one_func( m ) + * } + * end + * + * gen_decl(methods) + * gen_funcs(methods) + * + */ diff --git a/bop_ports.h b/bop_ports.h index 557ee54..21be395 100644 --- a/bop_ports.h +++ b/bop_ports.h @@ -4,20 +4,21 @@ #include "bop_api.h" typedef struct { - void (*ppr_group_init)( void ); - void (*ppr_task_init)( void ); - int (*ppr_check_correctness)( void ); - void (*report_conflict)( addr_t ); - void (*data_commit)( void ); - void (*task_group_commit)( void ); - void (*task_group_succ_fini)( void ); - void (*undy_init)( void ); - void (*undy_succ_fini)( void ); - void (*on_enter_ordered) (void); - void (*on_exit_ordered) (void); + void (*ppr_group_init)(void); + void (*ppr_task_init)(void); + int (*ppr_check_correctness)(void); + void (*report_conflict)(addr_t); + void (*data_commit)(void); + void (*task_group_commit)(void); + void (*task_group_succ_fini)(void); + void (*undy_init)(void); + void (*undy_succ_fini)(void); + void (*on_enter_ordered)(void); + void (*on_exit_ordered)(void); } bop_port_t; -void register_port( bop_port_t *port, char * desc ); +void +register_port(bop_port_t *port, char *desc); /* common vars needed in a port */ @@ -25,12 +26,16 @@ extern volatile task_status_t task_status; extern volatile ppr_pos_t ppr_pos; extern bop_mode_t bop_mode; extern int spec_order; + // extern int ppr_index; *Don't* use it directly, call BOP_ppr_index( ) instead -#define task_parallel_p (ppr_pos == PPR && (task_status == MAIN || task_status == SPEC)) +#define task_parallel_p \ + (ppr_pos == PPR && (task_status == MAIN || task_status == SPEC)) -// should be defined in the files that include bop_ports.h: extern mspace metacow_space; +// should be defined in the files that include bop_ports.h: extern mspace +// metacow_space; #define meta_malloc(type) (type *)mspace_malloc(metacow_space, sizeof(type)) -#define meta_calloc(num, type) (type*)mspace_calloc(metacow_space, (num), sizeof(type)) +#define meta_calloc(num, type) \ + (type *)mspace_calloc(metacow_space, (num), sizeof(type)) #endif diff --git a/bop_ppr.c b/bop_ppr.c index 461e9d1..feb9e92 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -1,835 +1,1052 @@ #include +#include #include #include +#include #include #include -#include -#include -#include //BOP_msg locking #include +#include //BOP_msg locking #include //#include -#include #include +#include #include "bop_api.h" #include "bop_ports.h" #include "bop_ppr_sync.h" #include "utils.h" -#define OWN_GROUP() if (setpgid(0, 0) != 0) { perror("setpgid"); exit(-1); } +#define OWN_GROUP() \ + if (setpgid(0, 0) != 0) { \ + perror("setpgid"); \ + exit(-1); \ + } extern bop_port_t bop_io_port; extern bop_port_t bop_merge_port; extern bop_port_t postwait_port; extern bop_port_t bop_ordered_port; extern bop_port_t bop_alloc_port; -extern void bop_msg_va(int level, const char * msg, va_list v); +extern void +bop_msg_va(int level, const char *msg, va_list v); volatile task_status_t task_status = SEQ; -volatile ppr_pos_t ppr_pos = GAP; -bop_mode_t bop_mode = PARALLEL; -int spec_order = 0; -int ppr_index = 0; +volatile ppr_pos_t ppr_pos = GAP; +bop_mode_t bop_mode = PARALLEL; +int spec_order = 0; +int ppr_index = 0; static int ppr_static_id; -stats_t bop_stats = { 0 }; +stats_t bop_stats = {0}; static int bopgroup; -int monitor_process_id = 0; -int monitor_group = 0; //the process group that PPR tasks are using +int monitor_process_id = 0; +int monitor_group = 0; // the process group that PPR tasks are using static bool is_monitoring = false; -static bool errored = false; +static bool errored = false; static void __attribute__((noreturn)) wait_process(void); -static void __attribute__((noreturn)) end_clean(void); //exit if children errored or call abort -static int cleanup_children(void); //returns the value that end_clean would call with _exit (or 0 if would have aborted) -void SigBopExit( int signo ); -static void block_wait(void); -static void unblock_wait(void); -//exec pipe +static void __attribute__((noreturn)) +end_clean(void); // exit if children errored or call abort +static int +cleanup_children(void); // returns the value that end_clean would call with -//Semaphore msg init -extern void msg_init(); +// _exit (or 0 if would have aborted) +void +SigBopExit(int signo); +static void +block_wait(void); +static void +unblock_wait(void); -void (*external_reporter)(const char *, ...); +// exec pipe +// Semaphore msg init +extern void +msg_init(); -static void _ppr_group_init( void ) { - bop_msg( 3, "task group starts (gs %d)", BOP_get_group_size() ); +void (*external_reporter)(const char *, ...); - /* setup bop group id.*/ - bopgroup = getpid(); - assert( getpgrp() == -monitor_group ); - spec_order = 0; - ppr_sync_data_reset( ); - ppr_group_init( ); - task_status = MAIN; // at the end so monitoring is disabled until this point +static void +_ppr_group_init(void) +{ + bop_msg(3, "task group starts (gs %d)", BOP_get_group_size()); + + /* setup bop group id. */ + bopgroup = getpid(); + assert(getpgrp() == -monitor_group); + spec_order = 0; + ppr_sync_data_reset(); + ppr_group_init(); + task_status = + MAIN; // at the end so monitoring is disabled until this point } /* Called at the ppr start of a main task and the end of the prior ppr - of a spec task. */ -static void _ppr_task_init( void ) { - switch (task_status) { - case MAIN: - assert( spec_order == 0); - break; - case SPEC: - spec_order += 1; - break; - case UNDY: - case SEQ: - assert(0); - } - - bop_msg( 2, "ppr task %d (%d total) starts. pgrp = %d", spec_order, BOP_get_group_size(), getpgrp() ); - - //assert( setpgid(0, bopgroup)==0 ); - assert (getpgrp() == -monitor_group); - ppr_task_init( ); -} - -int _BOP_ppr_begin(int id) { - ppr_pos_t old_pos = ppr_pos; - ppr_pos = PPR; - ppr_index ++; - - switch (task_status) { - case UNDY: - return 0; - case SEQ: - _ppr_group_init( ); - - /* NO BREAK. either the ppr task was started by SPEC earlier or - now it is SPEC continuing into the next PPR region */ - case SPEC: - if (task_status == SPEC && old_pos != GAP) { - bop_msg(2, "Nested begin PPR (region %d inside region %d) ignored", id, ppr_static_id); - return 0; + * of a spec task. */ +static void +_ppr_task_init(void) +{ + switch (task_status) { + case MAIN: + assert(spec_order == 0); + break; + case SPEC: + spec_order += 1; + break; + case UNDY: + case SEQ: + assert(0); } - ppr_static_id = id; + bop_msg(2, + "ppr task %d (%d total) starts. pgrp = %d", + spec_order, + BOP_get_group_size(), + getpgrp()); - /* no spawn if sequential or reaching group size */ - if (bop_mode == SERIAL || spec_order >= partial_group_get_size( ) - 1) { - if (bop_mode == SERIAL) _ppr_task_init( ); - return 0; - } - block_wait(); - int fid = fork( ); - unblock_wait(); - if (fid == -1) { - bop_msg (2, "OS unable to fork more tasks" ); - if ( task_status == MAIN) { - task_status = SEQ; - bop_mode = SERIAL; - } - else - partial_group_set_size( spec_order + 1 ); + // assert( setpgid(0, bopgroup)==0 ); + assert(getpgrp() == -monitor_group); + ppr_task_init(); +} - return 0; - } +int +_BOP_ppr_begin(int id) +{ + ppr_pos_t old_pos = ppr_pos; - if (fid > 0) { /* main or senior spec continues */ - if (task_status == MAIN) _ppr_task_init( ); - return 0; - } + ppr_pos = PPR; + ppr_index++; - /* new spec task */ - task_status = SPEC; - ppr_pos = GAP; - _ppr_task_init( ); - return 1; + switch (task_status) { + case UNDY: + return 0; + case SEQ: + _ppr_group_init(); - case MAIN: - bop_msg(2, "Nested begin PPR (region %d inside region %d) ignored", id, ppr_static_id); - return 0; + /* NO BREAK. either the ppr task was started by SPEC earlier or + * now it is SPEC continuing into the next PPR region */ + case SPEC: + if (task_status == SPEC && old_pos != GAP) { + bop_msg(2, + "Nested begin PPR (region %d inside region %d) ignored", + id, + ppr_static_id); + return 0; + } + + ppr_static_id = id; + + /* no spawn if sequential or reaching group size */ + if (bop_mode == SERIAL || spec_order >= partial_group_get_size() - 1) { + if (bop_mode == SERIAL) + _ppr_task_init(); + return 0; + } + block_wait(); + int fid = fork(); + + unblock_wait(); + if (fid == -1) { + bop_msg(2, "OS unable to fork more tasks"); + if (task_status == MAIN) { + task_status = SEQ; + bop_mode = SERIAL; + } else + partial_group_set_size(spec_order + 1); + + return 0; + } + + if (fid > 0) { /* main or senior spec continues */ + if (task_status == MAIN) + _ppr_task_init(); + return 0; + } + + /* new spec task */ + task_status = SPEC; + ppr_pos = GAP; + _ppr_task_init(); + return 1; + + case MAIN: + bop_msg(2, + "Nested begin PPR (region %d inside region %d) ignored", + id, + ppr_static_id); + return 0; - default: - assert(0); - } - return 0; + default: + assert(0); + } + return 0; } /* Not supported because of too many cases we have to worry depending - on when this called. Also there is no need for this call. - BOP_abort_spec should suffice. In any case, sending SIGUSR2 will - break the system unless UNDY is running. */ + * on when this called. Also there is no need for this call. + * BOP_abort_spec should suffice. In any case, sending SIGUSR2 will + * break the system unless UNDY is running. */ // void BOP_abort_spec_group( char *msg ) { // bop_msg(2, "Abort all speculation because %s", msg ); // kill( 0, SIGUSR2 ); // } bool waiting = false; -void temp_sigint(int sigo){ - waiting = true; -} -void error_alert_monitor(){ - kill(monitor_process_id, SIGUSR2); -} -extern void io_on_malloc_rescue(void); -int spawn_undy(void); -extern void print_headers(void); -//if malloc cannot meet a request, it calls this funcion -void BOP_malloc_rescue(char * msg, size_t size){ - bop_msg(2, "Malloc rescue begin. aligned size & header: %u Failure: %s", size, msg); - // print_headers(); - if(task_status == SEQ || task_status == UNDY || bop_mode == SERIAL){ - bop_msg(1, "ERROR. Malloc failed while logically sequential"); - }else if(task_status == MAIN || (task_status == SPEC && spec_order == 0)){ - bop_msg(3, "Changing pid %d (mode %s)", getpid(), - task_status == MAIN ? "Main" : "SPEC"); - //Hangs here... io_on_malloc_rescue(); //before anything changes, but something will change - // //'undy wins the race' - int now_undy = spawn_undy(); - if(!now_undy){ - //die - bop_msg(1, "Aborting malloc failing proc."); +void +temp_sigint(int sigo) +{ + waiting = true; +} + +void +error_alert_monitor() +{ + kill(monitor_process_id, SIGUSR2); +} + +extern void +io_on_malloc_rescue(void); +int +spawn_undy(void); +extern void +print_headers(void); + +// if malloc cannot meet a request, it calls this funcion +void +BOP_malloc_rescue(char *msg, size_t size) +{ + bop_msg(2, + "Malloc rescue begin. aligned size & header: %u Failure: %s", + size, + msg); + // print_headers(); + if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) { + bop_msg(1, "ERROR. Malloc failed while logically sequential"); + } else if (task_status == MAIN || + (task_status == SPEC && spec_order == 0)) { + bop_msg(3, + "Changing pid %d (mode %s)", + getpid(), + task_status == MAIN ? "Main" : "SPEC"); + // Hangs here... io_on_malloc_rescue(); //before anything changes, but + // something will change + // //'undy wins the race' + int now_undy = spawn_undy(); + + if (!now_undy) { + // die + bop_msg(1, "Aborting malloc failing proc."); + _exit(0); + } else { + bop_msg(1, "New saved undy returning."); + return; + } + return; // user-process + } else if (task_status == SPEC && spec_order > 0) { + bop_msg(3, "Unable to save later SPEC tasks. Exiting"); _exit(0); - }else{ - bop_msg(1, "New saved undy returning."); + } else { + BOP_abort_spec("Didn't know how to process BOP_malloc_rescue"); + _exit(0); // for exit! + } + _exit(0); // my sanity +} + +static inline void +abort_printf(const char *abrt_msg, const char *usr_msg, va_list argptr) +{ + char buffer[strlen(usr_msg) + strlen(abrt_msg) + 2]; + size_t size = sizeof(buffer); + size_t written = + snprintf(buffer, sizeof(buffer), "%s %s", abrt_msg, usr_msg); + + assert(written < size); + bop_msg_va(2, buffer, argptr); +} + +void __attribute__((format(printf, 1, 2))) BOP_abort_spec(const char *msg, ...) +{ + if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) + return; + va_list argptr; + + va_start(argptr, msg); + if (task_status == MAIN) { /* non-mergeable actions have happened */ + if (partial_group_get_size() > 1) { + abort_printf("Abort main speculation because", msg, argptr); + va_end(argptr); + partial_group_set_size(1); + } + } else { + abort_printf("Abort alt speculation because", msg, argptr); + va_end(argptr); + partial_group_set_size(spec_order); + signal_commit_done(); + end_clean(); //_exit(0); /* die silently, but reap children*/ + } +} + +void __attribute__((format(printf, 1, 2))) BOP_abort_next_spec(char *msg, ...) +{ + if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) return; - } - return;//user-process - }else if(task_status == SPEC && spec_order > 0){ - bop_msg(3, "Unable to save later SPEC tasks. Exiting"); - _exit(0); - }else{ - BOP_abort_spec("Didn't know how to process BOP_malloc_rescue"); - _exit(0); //for exit! - } - _exit(0); //my sanity -} -static inline void abort_printf(const char * abrt_msg, const char * usr_msg, - va_list argptr){ - char buffer[strlen(usr_msg) + strlen(abrt_msg) + 2] ; - size_t size = sizeof(buffer); - size_t written = snprintf(buffer, sizeof(buffer), "%s %s", abrt_msg, usr_msg); - assert(written < size); - bop_msg_va(2, buffer, argptr); -} - -void __attribute__ ((format (printf, 1, 2))) BOP_abort_spec(const char* msg, ...){ - if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) - return; - va_list argptr; - va_start(argptr,msg); - if (task_status == MAIN) { /* non-mergeable actions have happened */ - if ( partial_group_get_size() > 1 ) { - abort_printf("Abort main speculation because", msg, argptr); - va_end(argptr); - partial_group_set_size( 1 ); - } - }else{ - abort_printf("Abort alt speculation because", msg, argptr); + va_list argptr; + + va_start(argptr, msg); + abort_printf("Abort next speculation because", msg, argptr); va_end(argptr); - partial_group_set_size( spec_order ); - signal_commit_done( ); - end_clean(); //_exit(0); /* die silently, but reap children*/ - } -} -void __attribute__ ((format (printf, 1, 2))) BOP_abort_next_spec( char *msg, ... ) { - if (task_status == SEQ || task_status == UNDY || bop_mode == SERIAL) - return; - va_list argptr; - va_start(argptr,msg); - abort_printf("Abort next speculation because", msg, argptr); - va_end(argptr); - if (task_status == MAIN) /* non-mergeable actions have happened */ - partial_group_set_size( 1 ); - else - partial_group_set_size( spec_order + 1 ); + if (task_status == MAIN) /* non-mergeable actions have happened */ + partial_group_set_size(1); + else + partial_group_set_size(spec_order + 1); } static int undy_ppr_count; -void post_ppr_undy( void ) { - undy_ppr_count ++; +void +post_ppr_undy(void) +{ + undy_ppr_count++; - if (undy_ppr_count < partial_group_get_size() - 1) { - bop_msg(3,"Undy reaches EndPPR %d times", undy_ppr_count); - return; - } + if (undy_ppr_count < partial_group_get_size() - 1) { + bop_msg(3, "Undy reaches EndPPR %d times", undy_ppr_count); + return; + } - /* Ladies and Gent: This is the finish line. If understudy lives to block - off SIGUSR2 (without being aborted by it before), then it wins the race - (and thumb down for parallelism).*/ - bop_msg(3,"Understudy finishes and wins the race"); + /* Ladies and Gent: This is the finish line. If understudy lives to block + * off SIGUSR2 (without being aborted by it before), then it wins the race + * (and thumb down for parallelism). */ + bop_msg(3, "Understudy finishes and wins the race"); - // indicate the success of the understudy - kill(0, SIGUSR2); - kill(-monitor_group, SIGUSR1); //TODO why is this here????? main requires a special signal? + // indicate the success of the understudy + kill(0, SIGUSR2); + kill( + -monitor_group, + SIGUSR1); // TODO why is this here????? main requires a special signal? - undy_succ_fini( ); + undy_succ_fini(); - task_status = SEQ; - ppr_pos = GAP; - bop_stats.num_by_undy += undy_ppr_count; + task_status = SEQ; + ppr_pos = GAP; + bop_stats.num_by_undy += undy_ppr_count; } /* Return true if it is UNDY (or SEQ in the rare case). */ -int spawn_undy( void ) { - pid_t caller = getpid(); - block_wait(); - int fid = fork( ); - unblock_wait(); - switch( fid ) { - case -1: - bop_msg(3,"OS cannot fork more process."); - /* Turn main into the understudy and effectively abort all - speculation (by not committing).*/ - task_status = SEQ; - bop_mode = SERIAL; - return TRUE; - case 0: - task_status = UNDY; - ppr_pos = GAP; - spec_order = -1; - //assert( setpgid(0, bopgroup) == 0 ); - assert (getpgrp() == -monitor_group); - bop_msg(3,"Understudy starts pid %d pgrp %d parent: %d", getpid(), getpgrp(), caller); - - signal_undy_created( fid ); +int +spawn_undy(void) +{ + pid_t caller = getpid(); - bop_stats.num_by_main += 1; - undy_ppr_count = 0; + block_wait(); + int fid = fork(); - undy_init( ); + unblock_wait(); + switch (fid) { + case -1: + bop_msg(3, "OS cannot fork more process."); + /* Turn main into the understudy and effectively abort all + * speculation (by not committing). */ + task_status = SEQ; + bop_mode = SERIAL; + return TRUE; + case 0: + task_status = UNDY; + ppr_pos = GAP; + spec_order = -1; + // assert( setpgid(0, bopgroup) == 0 ); + assert(getpgrp() == -monitor_group); + bop_msg(3, + "Understudy starts pid %d pgrp %d parent: %d", + getpid(), + getpgrp(), + caller); - return TRUE; - default: - return FALSE; - } + signal_undy_created(fid); + + bop_stats.num_by_main += 1; + undy_ppr_count = 0; + + undy_init(); + + return TRUE; + default: + return FALSE; + } } -void undy_on_create(){ +void +undy_on_create() +{ } + /* It won't return if not correct. */ -static void _ppr_check_correctness( void ) { - if ( task_status != MAIN ) - wait_prior_check_done( ); +static void +_ppr_check_correctness(void) +{ + if (task_status != MAIN) + wait_prior_check_done(); + + int passed = ppr_check_correctness(); - int passed = ppr_check_correctness( ); - if ( task_status == MAIN ) assert( passed ); + if (task_status == MAIN) + assert(passed); - signal_check_done( passed ); + signal_check_done(passed); - if ( !passed ) - BOP_abort_spec( "correctness check failed."); + if (!passed) + BOP_abort_spec("correctness check failed."); } /* Called when spec group is succeeding. */ -void _task_group_commit( void ) { - if (task_status == MAIN) { - if (bop_mode == SERIAL) { - task_group_commit( ); - task_group_succ_fini( ); - bop_stats.num_by_main += 1; - task_status = SEQ; - return; +void +_task_group_commit(void) +{ + if (task_status == MAIN) { + if (bop_mode == SERIAL) { + task_group_commit(); + task_group_succ_fini(); + bop_stats.num_by_main += 1; + task_status = SEQ; + return; + } else + end_clean(); // abort( ); /* UNDY has run ahead */ } - else - end_clean();//abort( ); /* UNDY has run ahead */ - } - wait_group_commit_done( ); - task_group_commit( ); - signal_commit_done( ); + wait_group_commit_done(); + task_group_commit(); + signal_commit_done(); - bop_msg(2,"The task group (0 to %d) has succeeded", spec_order); + bop_msg(2, "The task group (0 to %d) has succeeded", spec_order); - if (bop_mode == PARALLEL) { - wait_undy_created( ); - kill( 0, SIGUSR1 ); /* not just get_undy_pid( ) */ - wait_undy_conceded( ); - } + if (bop_mode == PARALLEL) { + wait_undy_created(); + kill(0, SIGUSR1); /* not just get_undy_pid( ) */ + wait_undy_conceded(); + } - task_group_succ_fini( ); + task_group_succ_fini(); - bop_msg(5,"Spec wins"); + bop_msg(5, "Spec wins"); - bop_stats.num_by_spec += spec_order; - bop_stats.num_by_main += 1; + bop_stats.num_by_spec += spec_order; + bop_stats.num_by_main += 1; - task_status = SEQ; + task_status = SEQ; } /* MAIN-SPEC and SPEC-SPEC commits */ -void ppr_task_commit( void ) { - bop_msg( 4, "ppr task commits" ); - - /* Earlier spec aborted further tasks */ - if ( spec_order >= partial_group_get_size( ) ) { - bop_msg( 4, "ppr task outside group size" ); - exit(cleanup_children()); - //abort( ); //error - } - - _ppr_check_correctness( ); - - if ( spec_order < partial_group_get_size()-1 ) { - /* not the last task */ - data_commit( ); - - signal_commit_done( ); - if (bop_mode == SERIAL) return; - wait_next_commit_done( ); - bop_msg( 4, "the next ppr has finished" ); - } - - /* check again in case the next ppr fails after my last check */ - if ( spec_order == partial_group_get_size()-1 ) { - bop_msg( 3, "task group commits." ); - _task_group_commit( ); - return; - } - - end_clean();//abort( ); -} -void _BOP_group_over(int id){ - if(ppr_static_id != id){ - bop_msg(3, "Mis-matched ppr ids. Continuing"); - }else if(task_status == SPEC){ - bop_msg(3, "Speculative process extended past PPR region. _exiting"); - _exit(0); - }else{ - bop_msg(3, "Valid state while hitting BOP_group_over. Allowing to pass barrier"); - } -} -void BOP_this_group_over(){ - _BOP_group_over(ppr_static_id); -} -void _BOP_ppr_end(int id) { - bop_msg(2, "Reached PPR end (pid %d)", getpid()); - if (ppr_pos == GAP || ppr_static_id != id) { - bop_msg(4, "Unmatched end PPR (region %d in/after region %d) ignored", id, ppr_static_id); - return; - } - - switch (task_status) { - case SEQ: - return; - case MAIN: - if ( bop_mode != SERIAL && spawn_undy( ) ) - return; /* UNDY */ +void +ppr_task_commit(void) +{ + bop_msg(4, "ppr task commits"); + + /* Earlier spec aborted further tasks */ + if (spec_order >= partial_group_get_size()) { + bop_msg(4, "ppr task outside group size"); + exit(cleanup_children()); + // abort( ); //error + } + + _ppr_check_correctness(); + + if (spec_order < partial_group_get_size() - 1) { + /* not the last task */ + data_commit(); + + signal_commit_done(); + if (bop_mode == SERIAL) + return; + wait_next_commit_done(); + bop_msg(4, "the next ppr has finished"); + } + + /* check again in case the next ppr fails after my last check */ + if (spec_order == partial_group_get_size() - 1) { + bop_msg(3, "task group commits."); + _task_group_commit(); + return; + } + + end_clean(); // abort( ); +} + +void +_BOP_group_over(int id) +{ + if (ppr_static_id != id) { + bop_msg(3, "Mis-matched ppr ids. Continuing"); + } else if (task_status == SPEC) { + bop_msg(3, "Speculative process extended past PPR region. _exiting"); + _exit(0); + } else { + bop_msg(3, + "Valid state while hitting BOP_group_over. Allowing to " + "pass barrier"); + } +} + +void +BOP_this_group_over() +{ + _BOP_group_over(ppr_static_id); +} + +void +_BOP_ppr_end(int id) +{ + bop_msg(2, "Reached PPR end (pid %d)", getpid()); + if (ppr_pos == GAP || ppr_static_id != id) { + bop_msg(4, + "Unmatched end PPR (region %d in/after region %d) ignored", + id, + ppr_static_id); + return; + } + + switch (task_status) { + case SEQ: + return; + case MAIN: + if (bop_mode != SERIAL && spawn_undy()) + return; /* UNDY */ /* still MAIN, fall through */ - case SPEC: - ppr_task_commit( ); - break; - case UNDY: - post_ppr_undy( ); - ppr_pos = GAP; - return; - default: - assert(0); - } + case SPEC: + ppr_task_commit(); + break; + case UNDY: + post_ppr_undy(); + ppr_pos = GAP; + return; + default: + assert(0); + } } /* The arbitration channel for parallel-sequential race between - speculation processes and understudy. - - There are two needs for "poking" a task when it runs. The first is - to abort speculation processes when Undy completes. The second is - to signal Undy and wait for its surrender when speculation - completes. The first is accomplisned by Undy sending SIGUSR1 to - SPEC group. The second is by the succeeding SPEC sending SIGUSR2 - to Undy. - - In addition, the monitor/timing process begins it's clean up process when it recieves SigUsr1. - - When the monitor process recieves SIGUSR2, it immediately kills all running processes using SIGKILL, - and exits in error. - All processes have the same SIGUSR1 and SIGUSR2 handlers. - -*/ -void MonitorInteruptFwd(int signo){ - bop_msg(1, "forwarding signal '%s' to children of pgrp %d", strsignal(signo), monitor_group); - assert(getpid() == monitor_process_id); - kill(monitor_group, signo); - is_monitoring = is_monitoring && signo == SIGINT; //stop monitoring - if(signo == SIGINT){ - _exit(0); // Don't clean up, just end - } -} -void print_backtrace(void){ - bop_msg(1, "\nBACKTRACE pid = %d parent pid %d", getpid(), getppid()); - void *bt[1024]; - int bt_size; - char **bt_syms; - int i; - - bt_size = backtrace(bt, 1024); - bt_syms = backtrace_symbols(bt, bt_size); - for (i = 1; i < bt_size; i++) { - size_t len = strlen(bt_syms[i]); - bop_msg(1, "\tBT: %s", bt_syms[i], len); - } - bop_msg(1, "\nEND BACKTRACE"); -} -void ErrorKillAll(int signo){ - static const char * msg_f = "Error caught signal %d"; - //don't need to reap children. We know that it's an erroring-exit, - //intecept the call, allert monitor process, execute def behavior - /**Horrible things are happening. Go to SEQ mode so malloc won't have issues*/ - malloc_panic = true; - if(external_reporter != NULL) - external_reporter(msg_f, signo); - else{ - bop_msg(1, msg_f, signo); - print_backtrace(); - } - error_alert_monitor(); - exit(-1); -} -void SigUsr1(int signo, siginfo_t *siginfo, ucontext_t *cntxt) { - assert( SIGUSR1 == signo ); - - if (task_status == UNDY) { - bop_msg(3,"Understudy concedes the race (sender pid %d)", siginfo->si_pid); - signal_undy_conceded( ); - _exit(0); //has no children. don't need to reap - } - if (task_status == SPEC || task_status == MAIN) { - if ( spec_order == partial_group_get_size() - 1 ) return; - bop_msg(3,"Quiting after the last spec succeeds (sender pid %d)", siginfo->si_pid); - end_clean(); //wait for children. doesn't return - } - if(getpid() == monitor_process_id){ - bop_msg(3, "Monitor process setting is_monitoring to false. Sender %d", siginfo->si_pid); - is_monitoring = false; - } + * speculation processes and understudy. + * + * There are two needs for "poking" a task when it runs. The first is + * to abort speculation processes when Undy completes. The second is + * to signal Undy and wait for its surrender when speculation + * completes. The first is accomplisned by Undy sending SIGUSR1 to + * SPEC group. The second is by the succeeding SPEC sending SIGUSR2 + * to Undy. + * + * In addition, the monitor/timing process begins it's clean up process when it + * recieves SigUsr1. + * + * When the monitor process recieves SIGUSR2, it immediately kills all running + * processes using SIGKILL, + * and exits in error. + * All processes have the same SIGUSR1 and SIGUSR2 handlers. + * + */ +void +MonitorInteruptFwd(int signo) +{ + bop_msg(1, + "forwarding signal '%s' to children of pgrp %d", + strsignal(signo), + monitor_group); + assert(getpid() == monitor_process_id); + kill(monitor_group, signo); + is_monitoring = is_monitoring && signo == SIGINT; // stop monitoring + if (signo == SIGINT) { + _exit(0); // Don't clean up, just end + } +} + +void +print_backtrace(void) +{ + bop_msg(1, "\nBACKTRACE pid = %d parent pid %d", getpid(), getppid()); + void *bt[1024]; + int bt_size; + char **bt_syms; + int i; + + bt_size = backtrace(bt, 1024); + bt_syms = backtrace_symbols(bt, bt_size); + for (i = 1; i < bt_size; i++) { + size_t len = strlen(bt_syms[i]); + + bop_msg(1, "\tBT: %s", bt_syms[i], len); + } + bop_msg(1, "\nEND BACKTRACE"); +} + +void +ErrorKillAll(int signo) +{ + static const char *msg_f = "Error caught signal %d"; + + // don't need to reap children. We know that it's an erroring-exit, + // intecept the call, allert monitor process, execute def behavior + + /**Horrible things are happening. Go to SEQ mode so malloc won't have + * issues*/ + malloc_panic = true; + if (external_reporter != NULL) + external_reporter(msg_f, signo); + else { + bop_msg(1, msg_f, signo); + print_backtrace(); + } + error_alert_monitor(); + exit(-1); +} + +void +SigUsr1(int signo, siginfo_t *siginfo, ucontext_t *cntxt) +{ + assert(SIGUSR1 == signo); + + if (task_status == UNDY) { + bop_msg(3, + "Understudy concedes the race (sender pid %d)", + siginfo->si_pid); + signal_undy_conceded(); + _exit(0); // has no children. don't need to reap + } + if (task_status == SPEC || task_status == MAIN) { + if (spec_order == partial_group_get_size() - 1) + return; + bop_msg(3, + "Quiting after the last spec succeeds (sender pid %d)", + siginfo->si_pid); + end_clean(); // wait for children. doesn't return + } + if (getpid() == monitor_process_id) { + bop_msg(3, + "Monitor process setting is_monitoring to false. Sender %d", + siginfo->si_pid); + is_monitoring = false; + } } /* Used to remove all SPEC tasks and MAIN when UNDY wins, when a spec group - finishes partially, or BOP_abort_spec_group is called. */ -void SigUsr2(int signo, siginfo_t *siginfo, ucontext_t *cntxt) { - assert( SIGUSR2 == signo ); - assert( cntxt ); - if(getpid() == monitor_process_id){ - bop_msg(1, "Monitor process exiting main loop because of SIGUSR2 (error)", siginfo->si_pid); - is_monitoring = false; - errored = true; - }else if (task_status == SPEC || task_status == MAIN) { - bop_msg(3,"PID %d exit upon receiving SIGUSR2", getpid()); - _exit(0); - } -} - -void SigBopExit( int signo ){ - bop_msg( 3,"Recieved signal %s (#%d)", strsignal(signo), signo ); - bop_terminal_to_monitor(); - _exit(0); //done. No cleanup, just end the process now + * finishes partially, or BOP_abort_spec_group is called. */ +void +SigUsr2(int signo, siginfo_t *siginfo, ucontext_t *cntxt) +{ + assert(SIGUSR2 == signo); + assert(cntxt); + if (getpid() == monitor_process_id) { + bop_msg(1, + "Monitor process exiting main loop because of SIGUSR2 (error)", + siginfo->si_pid); + is_monitoring = false; + errored = true; + } else if (task_status == SPEC || task_status == MAIN) { + bop_msg(3, "PID %d exit upon receiving SIGUSR2", getpid()); + _exit(0); + } +} + +void +SigBopExit(int signo) +{ + bop_msg(3, "Recieved signal %s (#%d)", strsignal(signo), signo); + bop_terminal_to_monitor(); + _exit(0); // done. No cleanup, just end the process now } + /* Initial process heads into this code before forking. * * Waits until all children have exited before exiting itself. */ - #define DEF_EXIT 0 //assume it works unless shown otherwise -int report_child(pid_t child, int status){ - if(child == -1 || !child) - return DEF_EXIT; - char * msg; - int val = -1; - int rval = DEF_EXIT; - if(WIFEXITED(status)){ - msg = "Child %d exited with value %d"; - rval = val = WEXITSTATUS(status); - } - //Have it return true if the signal that kill the process is either SIGABRT or SIGSEGV - else if(WIFSIGNALED(status)){ - msg = "Child %d was terminated by signal %d"; - val = WTERMSIG(status); - if (WTERMSIG(status) == SIGABRT || WTERMSIG(status) == SIGSEGV){ - rval = 1; - } - }else if(WIFSTOPPED(status)){ - msg = "Child %d was stopped by signal %d"; - val = WSTOPSIG(status); - }else if(WIFCONTINUED(status)){ - msg = "Child %d was continued"; - }else{ - msg = "Child %d exit unkown status = %d"; - val = status; - } - // if(child == -monitor_group){ - // //edge case: first child is dead, monitor wind down - // is_monitoring = false; - // } - if(val != -1) - bop_msg(2, msg, child, val); - else - bop_msg(2, msg, child); - return rval; -} -static inline void block_wait(){ - sigset_t set; - sigemptyset(&set); //block everything - sigaddset(&set, SIGUSR2); - sigaddset(&set, SIGUSR1); - sigprocmask(SIG_BLOCK,&set, NULL); -} -static inline void unblock_wait(){ - //set blocking signals to what it was before block_wait - sigset_t set; - sigemptyset(&set); //block everything - sigaddset(&set, SIGUSR2); - sigaddset(&set, SIGUSR1); - sigprocmask(SIG_UNBLOCK, &set, NULL); -} -//don't actually need this -static void wait_process() { - int status; - pid_t child; - assert (monitor_group != 0); //was actually written by the PIPE before this call - bop_msg(3, "Monitoring pg %d from pid %d (group %d)", monitor_group, getpid(), getpgrp()); - int my_exit = 0; //success - while (is_monitoring) { - block_wait(); - if (((child = waitpid(monitor_group, &status, WNOHANG | WUNTRACED)) != -1)) { - my_exit = my_exit || report_child(child, status); //we only care about zero v. not-zero +#define DEF_EXIT 0 // assume it works unless shown otherwise +int +report_child(pid_t child, int status) +{ + if (child == -1 || !child) + return DEF_EXIT; + char *msg; + int val = -1; + int rval = DEF_EXIT; + + if (WIFEXITED(status)) { + msg = "Child %d exited with value %d"; + rval = val = WEXITSTATUS(status); } - unblock_wait(); - } - errno = 0; - //handle remaining processes. Above may not have gotten everything - block_wait(); - while (((child = waitpid(monitor_group, &status, WUNTRACED)) != -1)) { - my_exit = my_exit || report_child(child, status); //we only care about zero v. not-zero - } - unblock_wait(); - if(errno && errno != ECHILD){ - perror("Error in wait_process. errno != ECHILD. Monitor process endings"); - _exit(EXIT_FAILURE); - } - my_exit = my_exit || errored; - my_exit = my_exit ? 1 : 0; - bop_msg(1, "Monitoring process %d ending with exit value %d", getpid(), my_exit); - msg_destroy(); - kill(monitor_group, SIGKILL); //ensure that everything is killed. - //Once the monitor process is done, everything should have already terminated - _exit(my_exit); -} -int block_signal(int signo){ - sigset_t mask; - sigemptyset(&mask); - if(sigaddset(&mask, signo) < 0) { - return -1; - } - sigprocmask(SIG_BLOCK, &mask, NULL); - return 0; -} -int unblock_signal(int signo){ - sigset_t mask; - sigemptyset(&mask); - if(sigaddset(&mask, signo) < 0){ - return -1; - } - sigprocmask(SIG_UNBLOCK, &mask, NULL); - return 0; -} -static void child_handler(int signo){ - assert(signo == SIGCHLD); - int val = cleanup_children(); - if(val) - _exit(val); -} -int cleanup_children(){ - int my_exit = 0; - pid_t child; - int status; - while((child = waitpid(monitor_group, &status, WUNTRACED)) != -1){ //any child - my_exit = my_exit || report_child(child, status); - } - return my_exit; -} -void end_clean(){ - int exit_code = cleanup_children(); - if(exit_code) - _exit(exit_code); - else - _exit(0); -} - -static void BOP_fini(void); + // Have it return true if the signal that kill the process is either + // SIGABRT or SIGSEGV + else if (WIFSIGNALED(status)) { + msg = "Child %d was terminated by signal %d"; + val = WTERMSIG(status); + if (WTERMSIG(status) == SIGABRT || WTERMSIG(status) == SIGSEGV) { + rval = 1; + } + } else if (WIFSTOPPED(status)) { + msg = "Child %d was stopped by signal %d"; + val = WSTOPSIG(status); + } else if (WIFCONTINUED(status)) { + msg = "Child %d was continued"; + } else { + msg = "Child %d exit unkown status = %d"; + val = status; + } + // if(child == -monitor_group){ + // //edge case: first child is dead, monitor wind down + // is_monitoring = false; + // } + if (val != -1) + bop_msg(2, msg, child, val); + else + bop_msg(2, msg, child); + return rval; +} -extern int bop_verbose; -extern int errno; -/* Initialize allocation map. Installs the timer process. */ -void __attribute__ ((constructor)) BOP_init(void) { - //install signal handlers - /* two user signals for sequential-parallel race arbitration, block - for SIGUSR2 initially */ - msg_init(); - struct sigaction action; - sigaction(SIGUSR1, NULL, &action); - sigemptyset(&action.sa_mask); - action.sa_flags = SA_SIGINFO; //ie only SA_SIGINFO and SA_RESTART - action.sa_sigaction = (void *) SigUsr1; - sigaction(SIGUSR1, &action, NULL); - action.sa_sigaction = (void *) SigUsr2; - sigaction(SIGUSR2, &action, NULL); - - /** Set up SIGTTOU/SIGTTIN handlers (terminal reads) */ - sigemptyset(&action.sa_mask); - action.sa_flags = SA_SIGINFO | SA_RESTART; - action.sa_sigaction = (void*) bop_terminal_to_workers; - sigaction(SIGTTOU, &action, NULL); - sigaction(SIGTTIN, &action, NULL); - - - /* Read environment variables: BOP_GroupSize, BOP_Verbose */ - bop_verbose = get_int_from_env("BOP_Verbose", 0, 6, 0); - int g = get_int_from_env("BOP_GroupSize", 1, 100, 2); - - BOP_set_group_size( g ); - bop_mode = g<2? SERIAL: PARALLEL; - - /* start the time */ - struct timeval tv; - gettimeofday(&tv, NULL); - bop_stats.start_time = tv.tv_sec + (tv.tv_usec/1000000.0); - - - /* setting up the timing process and initialize the SEQ task */ - if (bop_mode != SERIAL) { - /* create a process to allow the use of time command */ - monitor_process_id = getpid(); +static inline void +block_wait() +{ + sigset_t set; + + sigemptyset(&set); // block everything + sigaddset(&set, SIGUSR2); + sigaddset(&set, SIGUSR1); + sigprocmask(SIG_BLOCK, &set, NULL); +} + +static inline void +unblock_wait() +{ + // set blocking signals to what it was before block_wait + sigset_t set; + + sigemptyset(&set); // block everything + sigaddset(&set, SIGUSR2); + sigaddset(&set, SIGUSR1); + sigprocmask(SIG_UNBLOCK, &set, NULL); +} + +// don't actually need this +static void +wait_process() +{ + int status; + pid_t child; + + assert(monitor_group != + 0); // was actually written by the PIPE before this call + bop_msg(3, + "Monitoring pg %d from pid %d (group %d)", + monitor_group, + getpid(), + getpgrp()); + int my_exit = 0; // success + + while (is_monitoring) { + block_wait(); + if (((child = waitpid(monitor_group, &status, WNOHANG | WUNTRACED)) != + -1)) { + my_exit = + my_exit || + report_child(child, + status); // we only care about zero v. not-zero + } + unblock_wait(); + } + errno = 0; + // handle remaining processes. Above may not have gotten everything block_wait(); - int fd = fork(); + while (((child = waitpid(monitor_group, &status, WUNTRACED)) != -1)) { + my_exit = + my_exit || + report_child(child, status); // we only care about zero v. not-zero + } unblock_wait(); - switch (fd) { - case -1: - perror("fork() for timer process"); - exit(-1); - case 0: - /* Child process continues after switch */ - //We must first set up process group - //set up a new group - - OWN_GROUP(); - monitor_group = -getpid(); //negative-> work on process group + if (errno && errno != ECHILD) { + perror( + "Error in wait_process. errno != ECHILD. Monitor process endings"); + _exit(EXIT_FAILURE); + } + my_exit = my_exit || errored; + my_exit = my_exit ? 1 : 0; + bop_msg(1, + "Monitoring process %d ending with exit value %d", + getpid(), + my_exit); + msg_destroy(); + kill(monitor_group, SIGKILL); // ensure that everything is killed. + // Once the monitor process is done, everything should have already + // terminated + _exit(my_exit); +} - break; - default: - monitor_group = -fd; //child will set up its monitor_group variable - OWN_GROUP(); //monitoring process gets its own group, useful for ruby test suite +int +block_signal(int signo) +{ + sigset_t mask; - bop_msg(1, "Child proc id: %d pgrd %d", getpid(), getpgrp() ); - //forward SIGINT to children/monitor group - signal( SIGINT, MonitorInteruptFwd ); //sigint gets forwarded to children - is_monitoring = true; //the real monitor process is the only one to actually loop - // give the child process the terminal + sigemptyset(&mask); + if (sigaddset(&mask, signo) < 0) { + return -1; + } + sigprocmask(SIG_BLOCK, &mask, NULL); + return 0; +} +int +unblock_signal(int signo) +{ + sigset_t mask; - wait_process(); //never returns - _exit(0); /* Should never get here */ + sigemptyset(&mask); + if (sigaddset(&mask, signo) < 0) { + return -1; } + sigprocmask(SIG_UNBLOCK, &mask, NULL); + return 0; +} + +static void +child_handler(int signo) +{ + assert(signo == SIGCHLD); + int val = cleanup_children(); - /* the child process continues */ + if (val) + _exit(val); +} - /* register BOP_End at exit */ - if (atexit(BOP_fini)) { - perror("Failed to register exit-time BOP_end call"); +int +cleanup_children() +{ + int my_exit = 0; + pid_t child; + int status; + + while ((child = waitpid(monitor_group, &status, WUNTRACED)) != + -1) { // any child + my_exit = my_exit || report_child(child, status); } + return my_exit; +} - /* - sigset_t mask; - sigemptyset( &mask ); - sigaddset( &mask, SIGUSR2 ); - sigprocmask( SIG_BLOCK, &mask, NULL ); - */ - } - assert(getpgrp() == -monitor_group); - task_status = SEQ; - - /* prepare related signals. Need these???*/ - signal( SIGINT, SigBopExit ); //user-process - signal( SIGQUIT, SigBopExit ); - signal( SIGTERM, SigBopExit ); - signal( SIGCHLD, child_handler); - signal( SIGSEGV, ErrorKillAll); - - /* Load ports */ - register_port(&bop_merge_port, "Copy-n-merge Port"); - register_port(&postwait_port, "Post-wait Port"); - register_port(&bop_ordered_port, "Bop Ordered Port"); - register_port(&bop_io_port, "I/O Port"); - register_port(&bop_alloc_port, "Malloc Port"); - bop_msg(3, "Library initialized successfully."); -} -char* status_name(){ - switch (task_status) { - case SPEC: - return "SPEC"; - case UNDY: - return "UNDY"; - case MAIN: - return "MAIN"; - case SEQ: - return "SEQ"; - default: - return "UNKOWN"; - } -} -static void BOP_fini(void) { - bop_msg(3, "An exit is reached in %s mode", status_name()); - switch (task_status) { - case SPEC: - BOP_abort_spec("SPEC reached an exit"); /* will abort */ - signal(SIGUSR2, SIG_IGN); - kill(0, SIGUSR2); //send SIGUSR to spec group but not ourself-> own group - //everything is termininating - if (bop_mode == SERIAL) { - data_commit( ); - partial_group_set_size( 1 ); - task_group_commit( ); - task_group_succ_fini( ); - } - goto kill_monitor; - break; - - case UNDY: - kill(0, SIGUSR2); - kill(-monitor_group, SIGUSR1); //main requires a special signal - undy_succ_fini( ); - bop_stats.num_by_undy += undy_ppr_count; - break; +void +end_clean() +{ + int exit_code = cleanup_children(); + + if (exit_code) + _exit(exit_code); + else + _exit(0); +} + +static void +BOP_fini(void); - case MAIN: - case SEQ: - break; +extern int bop_verbose; +extern int errno; - default: - bop_msg(1, "invalid task status in bop_fini"); - assert(0); //should never get here - } +/* Initialize allocation map. Installs the timer process. */ +void __attribute__((constructor)) BOP_init(void) +{ + // install signal handlers + /* two user signals for sequential-parallel race arbitration, block + * for SIGUSR2 initially */ + msg_init(); + struct sigaction action; + + sigaction(SIGUSR1, NULL, &action); + sigemptyset(&action.sa_mask); + action.sa_flags = SA_SIGINFO; // ie only SA_SIGINFO and SA_RESTART + action.sa_sigaction = (void *)SigUsr1; + sigaction(SIGUSR1, &action, NULL); + action.sa_sigaction = (void *)SigUsr2; + sigaction(SIGUSR2, &action, NULL); + + /** Set up SIGTTOU/SIGTTIN handlers (terminal reads) */ + sigemptyset(&action.sa_mask); + action.sa_flags = SA_SIGINFO | SA_RESTART; + action.sa_sigaction = (void *)bop_terminal_to_workers; + sigaction(SIGTTOU, &action, NULL); + sigaction(SIGTTIN, &action, NULL); + + /* Read environment variables: BOP_GroupSize, BOP_Verbose */ + bop_verbose = get_int_from_env("BOP_Verbose", 0, 6, 0); + int g = get_int_from_env("BOP_GroupSize", 1, 100, 2); + + BOP_set_group_size(g); + bop_mode = g < 2 ? SERIAL : PARALLEL; + + /* start the time */ + struct timeval tv; + + gettimeofday(&tv, NULL); + bop_stats.start_time = tv.tv_sec + (tv.tv_usec / 1000000.0); + + /* setting up the timing process and initialize the SEQ task */ + if (bop_mode != SERIAL) { + /* create a process to allow the use of time command */ + monitor_process_id = getpid(); + block_wait(); + int fd = fork(); + + unblock_wait(); + switch (fd) { + case -1: + perror("fork() for timer process"); + exit(-1); + case 0: + /* Child process continues after switch */ + // We must first set up process group + // set up a new group + + OWN_GROUP(); + monitor_group = -getpid(); // negative-> work on process group + + break; + default: + monitor_group = -fd; // child will set up its monitor_group + // variable + OWN_GROUP(); // monitoring process gets its own group, useful for + // ruby test suite + + bop_msg(1, "Child proc id: %d pgrd %d", getpid(), getpgrp()); + // forward SIGINT to children/monitor group + signal(SIGINT, + MonitorInteruptFwd); // sigint gets forwarded to children + is_monitoring = true; // the real monitor process is the only one + // to actually loop + // give the child process the terminal + + wait_process(); // never returns + _exit(0); /* Should never get here */ + } + + /* the child process continues */ + + /* register BOP_End at exit */ + if (atexit(BOP_fini)) { + perror("Failed to register exit-time BOP_end call"); + } + + /* + * sigset_t mask; + * sigemptyset( &mask ); + * sigaddset( &mask, SIGUSR2 ); + * sigprocmask( SIG_BLOCK, &mask, NULL ); + */ + } + assert(getpgrp() == -monitor_group); + task_status = SEQ; - struct timeval tv; - gettimeofday(&tv, NULL); - double bop_end_time = tv.tv_sec+(tv.tv_usec/1000000.0); + /* prepare related signals. Need these??? */ + signal(SIGINT, SigBopExit); // user-process + signal(SIGQUIT, SigBopExit); + signal(SIGTERM, SigBopExit); + signal(SIGCHLD, child_handler); + signal(SIGSEGV, ErrorKillAll); + + /* Load ports */ + register_port(&bop_merge_port, "Copy-n-merge Port"); + register_port(&postwait_port, "Post-wait Port"); + register_port(&bop_ordered_port, "Bop Ordered Port"); + register_port(&bop_io_port, "I/O Port"); + register_port(&bop_alloc_port, "Malloc Port"); + bop_msg(3, "Library initialized successfully."); +} - bop_msg(1, "\n***BOP Report***\n The total run time is %.2lf seconds. There were %d ppr tasks, %d executed speculatively and %d non-speculatively (%d by main and %d by understudy). pid %d\n", - bop_end_time - bop_stats.start_time, ppr_index, - bop_stats.num_by_spec, bop_stats.num_by_undy + bop_stats.num_by_main, bop_stats.num_by_main, bop_stats.num_by_undy, getpid()); +char * +status_name() +{ + switch (task_status) { + case SPEC: + return "SPEC"; + case UNDY: + return "UNDY"; + case MAIN: + return "MAIN"; + case SEQ: + return "SEQ"; + default: + return "UNKOWN"; + } +} - bop_msg( 3, "A total of %d bytes are copied during the commit and %d bytes are posted during parallel execution. The speculation group size is %d.\n\n", - bop_stats.data_copied, bop_stats.data_posted, - BOP_get_group_size( )); +static void +BOP_fini(void) +{ + bop_msg(3, "An exit is reached in %s mode", status_name()); + switch (task_status) { + case SPEC: + BOP_abort_spec("SPEC reached an exit"); /* will abort */ + signal(SIGUSR2, SIG_IGN); + kill(0, + SIGUSR2); // send SIGUSR to spec group but not ourself-> own group + // everything is termininating + if (bop_mode == SERIAL) { + data_commit(); + partial_group_set_size(1); + task_group_commit(); + task_group_succ_fini(); + } + goto kill_monitor; + break; + + case UNDY: + kill(0, SIGUSR2); + kill(-monitor_group, SIGUSR1); // main requires a special signal + undy_succ_fini(); + bop_stats.num_by_undy += undy_ppr_count; + break; + + case MAIN: + case SEQ: + break; + default: + bop_msg(1, "invalid task status in bop_fini"); + assert(0); // should never get here + } - kill_monitor: + struct timeval tv; + + gettimeofday(&tv, NULL); + double bop_end_time = tv.tv_sec + (tv.tv_usec / 1000000.0); + + bop_msg(1, + "\n***BOP Report***\n The total run time is %.2lf seconds. There " + "were %d ppr tasks, %d executed speculatively and %d " + "non-speculatively (%d by main and %d by understudy). pid %d\n", + bop_end_time - bop_stats.start_time, + ppr_index, + bop_stats.num_by_spec, + bop_stats.num_by_undy + bop_stats.num_by_main, + bop_stats.num_by_main, + bop_stats.num_by_undy, + getpid()); + + bop_msg(3, + "A total of %d bytes are copied during the commit and %d bytes " + "are posted during parallel execution. The speculation group size " + "is %d.\n\n", + bop_stats.data_copied, + bop_stats.data_posted, + BOP_get_group_size()); + +kill_monitor: bop_msg(3, "Final process forwarding children..."); int exitv = cleanup_children(); - bop_msg(3, "Sending shutdown signal to monitor process %d from pid %d", monitor_process_id, getpid()); + + bop_msg(3, + "Sending shutdown signal to monitor process %d from pid %d", + monitor_process_id, + getpid()); kill(monitor_process_id, SIGUSR1); bop_msg(3, "Terminal process %d exiting with value %d", getpid(), exitv); bop_terminal_to_monitor(); // dm_print_info(); - if(exitv) - _exit(exitv); - //don't need to call normal exit, + if (exitv) + _exit(exitv); + // don't need to call normal exit, } diff --git a/bop_ppr_sync.c b/bop_ppr_sync.c index 058f3f7..cdc05de 100644 --- a/bop_ppr_sync.c +++ b/bop_ppr_sync.c @@ -1,169 +1,217 @@ -#include /* for NULL */ -#include "bop_api.h" // for TRUE #include "atomic.h" // for locking -#include "external/malloc.h" // for mspace +#include "bop_api.h" // for TRUE #include "bop_ppr_sync.h" +#include "external/malloc.h" // for mspace +#include /* for NULL */ extern int spec_order; extern int task_status; typedef struct { - /* steps of commit */ - bop_lock_t spec_checked; - int spec_correct; - bop_lock_t data_committed; + /* steps of commit */ + bop_lock_t spec_checked; + int spec_correct; + bop_lock_t data_committed; - char space[64]; /* avoid cache block sharing */ + char space[64]; /* avoid cache block sharing */ } sync_status_t; typedef struct { - bop_lock_t lock; + bop_lock_t lock; - int alloc_size; - int group_size; - int partial_size; /* used during a parallel run to support partial - completion */ + int alloc_size; + int group_size; + int partial_size; /* used during a parallel run to support partial + * completion */ - sync_status_t *sync_status; + sync_status_t *sync_status; - bop_lock_t undy_created; - pid_t undy_pid; - bop_lock_t undy_conceded; + bop_lock_t undy_created; + pid_t undy_pid; + bop_lock_t undy_conceded; } sync_data_t; - -static mspace sync_space = NULL; + +static mspace sync_space = NULL; static sync_data_t *sync_data = NULL; -void partial_group_set_size( int psize ) { - assert( psize >= 1 && psize <= 100 ); - - if (sync_data->partial_size > psize) { - bop_lock_acquire( & sync_data->lock ); - sync_data->partial_size = psize; - bop_lock_release( & sync_data->lock ); - } -} +void +partial_group_set_size(int psize) +{ + assert(psize >= 1 && psize <= 100); -int partial_group_get_size( void ) { - return sync_data->partial_size; + if (sync_data->partial_size > psize) { + bop_lock_acquire(&sync_data->lock); + sync_data->partial_size = psize; + bop_lock_release(&sync_data->lock); + } } -int ppr_group_get_size( void ) { - if ( sync_data == NULL ) return 1; - else return sync_data->group_size; +int +partial_group_get_size(void) +{ + return sync_data->partial_size; } -void ppr_sync_data_reset( void ) { - int i; - for (i = 0; i < sync_data->alloc_size; i ++ ) { - sync_status_t *sync_status = & sync_data->sync_status[i]; - bop_lock_clear( & sync_status->spec_checked ); - bop_lock_acquire( & sync_status->spec_checked ); - bop_lock_clear( & sync_status->data_committed ); - bop_lock_acquire( & sync_status->data_committed ); - } - - bop_lock_clear( & sync_data->undy_created ); - bop_lock_acquire( & sync_data->undy_created ); - bop_lock_clear( & sync_data->undy_conceded ); - bop_lock_acquire( & sync_data->undy_conceded ); - - bop_lock_clear( & sync_data->lock ); - - sync_data->partial_size = sync_data->group_size; +int +ppr_group_get_size(void) +{ + if (sync_data == NULL) + return 1; + else + return sync_data->group_size; } -/* Called before a parallel execution to initialize the sync meta data - and during a parallel execution to signal early termination. */ -void ppr_group_set_size( int gsize ) { - assert( gsize >= 1 && gsize <= 100 ); - - if ( task_status == SEQ ) - bop_msg( 3, "setting group size to %d", gsize ); - else { - bop_msg( 3, "setting group size is not allowed unless by SEQ" ); - return; - } +void +ppr_sync_data_reset(void) +{ + int i; - if (sync_data == NULL) { - /* allocate sync space */ - char is_shared_mem = TRUE; /* true */ - char use_lock = TRUE; - size_t init_size = 20000; /* 20KB init size */ - sync_space = create_mspace( init_size, use_lock, is_shared_mem ); + for (i = 0; i < sync_data->alloc_size; i++) { + sync_status_t *sync_status = &sync_data->sync_status[i]; - sync_data = (sync_data_t *) - mspace_calloc( sync_space, 1, sizeof( sync_data_t ) ); + bop_lock_clear(&sync_status->spec_checked); + bop_lock_acquire(&sync_status->spec_checked); + bop_lock_clear(&sync_status->data_committed); + bop_lock_acquire(&sync_status->data_committed); + } - sync_data->sync_status = - mspace_calloc( sync_space, gsize, sizeof( sync_status_t ) ); - sync_data->alloc_size = gsize; - } - - /* Initialization */ - if ( sync_data->group_size < gsize ) { - sync_data->sync_status = (sync_status_t *) - mspace_realloc( sync_space, sync_data->sync_status, - gsize*sizeof( sync_status_t ) ); - sync_data->alloc_size = gsize; - } - sync_data->group_size = gsize; - ppr_sync_data_reset( ); -} - -int BOP_get_group_size( void ) { - return ppr_group_get_size(); -} + bop_lock_clear(&sync_data->undy_created); + bop_lock_acquire(&sync_data->undy_created); + bop_lock_clear(&sync_data->undy_conceded); + bop_lock_acquire(&sync_data->undy_conceded); -void BOP_set_group_size( int size ) { - ppr_group_set_size ( size ); -} - -void signal_check_done( int passed ) { - sync_data->sync_status[ spec_order ].spec_correct = passed; - bop_lock_release( & sync_data->sync_status[ spec_order ].spec_checked ); -} + bop_lock_clear(&sync_data->lock); -void signal_commit_done( void ) { - bop_lock_release( & sync_data->sync_status[ spec_order ].data_committed ); - bop_msg( 4, "signal commit (%d, partial group_size %d)", spec_order, partial_group_get_size() ); + sync_data->partial_size = sync_data->group_size; } -void wait_prior_check_done( void ) { - assert( spec_order >= 1 ); - bop_lock_acquire( & sync_data->sync_status[ spec_order - 1 ].spec_checked ); -} - -void wait_next_commit_done( void ) { - bop_msg( 4, "wait commit (%d, partial_group_size %d)", spec_order+1, partial_group_get_size() ); - bop_lock_acquire( & sync_data->sync_status[ spec_order+1 ].data_committed ); - bop_lock_release( & sync_data->sync_status[ spec_order+1 ].data_committed ); -} +/* Called before a parallel execution to initialize the sync meta data + * and during a parallel execution to signal early termination. */ +void +ppr_group_set_size(int gsize) +{ + assert(gsize >= 1 && gsize <= 100); + + if (task_status == SEQ) + bop_msg(3, "setting group size to %d", gsize); + else { + bop_msg(3, "setting group size is not allowed unless by SEQ"); + return; + } + + if (sync_data == NULL) { + /* allocate sync space */ + char is_shared_mem = TRUE; /* true */ + char use_lock = TRUE; + size_t init_size = 20000; /* 20KB init size */ -void wait_group_commit_done( void ) { - int i; - bop_msg( 4, "wait group commit (%d, partial_group_size %d)", spec_order, partial_group_get_size() ); - for ( i = 0; i < partial_group_get_size() - 1; i ++ ) - bop_lock_acquire( & sync_data->sync_status[ i ].data_committed ); -} + sync_space = create_mspace(init_size, use_lock, is_shared_mem); + + sync_data = + (sync_data_t *)mspace_calloc(sync_space, 1, sizeof(sync_data_t)); -void signal_undy_created( int pid ) { - sync_data->undy_pid = pid; - bop_lock_release( & sync_data->undy_created ); + sync_data->sync_status = + mspace_calloc(sync_space, gsize, sizeof(sync_status_t)); + sync_data->alloc_size = gsize; + } + + /* Initialization */ + if (sync_data->group_size < gsize) { + sync_data->sync_status = (sync_status_t *)mspace_realloc( + sync_space, sync_data->sync_status, gsize * sizeof(sync_status_t)); + sync_data->alloc_size = gsize; + } + sync_data->group_size = gsize; + ppr_sync_data_reset(); +} + +int +BOP_get_group_size(void) +{ + return ppr_group_get_size(); +} + +void +BOP_set_group_size(int size) +{ + ppr_group_set_size(size); +} + +void +signal_check_done(int passed) +{ + sync_data->sync_status[spec_order].spec_correct = passed; + bop_lock_release(&sync_data->sync_status[spec_order].spec_checked); +} + +void +signal_commit_done(void) +{ + bop_lock_release(&sync_data->sync_status[spec_order].data_committed); + bop_msg(4, + "signal commit (%d, partial group_size %d)", + spec_order, + partial_group_get_size()); +} + +void +wait_prior_check_done(void) +{ + assert(spec_order >= 1); + bop_lock_acquire(&sync_data->sync_status[spec_order - 1].spec_checked); +} + +void +wait_next_commit_done(void) +{ + bop_msg(4, + "wait commit (%d, partial_group_size %d)", + spec_order + 1, + partial_group_get_size()); + bop_lock_acquire(&sync_data->sync_status[spec_order + 1].data_committed); + bop_lock_release(&sync_data->sync_status[spec_order + 1].data_committed); +} + +void +wait_group_commit_done(void) +{ + int i; + + bop_msg(4, + "wait group commit (%d, partial_group_size %d)", + spec_order, + partial_group_get_size()); + for (i = 0; i < partial_group_get_size() - 1; i++) + bop_lock_acquire(&sync_data->sync_status[i].data_committed); +} + +void +signal_undy_created(int pid) +{ + sync_data->undy_pid = pid; + bop_lock_release(&sync_data->undy_created); } -int get_undy_pid( void ) { - return sync_data->undy_pid; +int +get_undy_pid(void) +{ + return sync_data->undy_pid; } -void signal_undy_conceded( void ) { - bop_lock_release( & sync_data->undy_conceded ); +void +signal_undy_conceded(void) +{ + bop_lock_release(&sync_data->undy_conceded); } -void wait_undy_created( void ) { - bop_lock_acquire( & sync_data->undy_created ); +void +wait_undy_created(void) +{ + bop_lock_acquire(&sync_data->undy_created); } -void wait_undy_conceded( void ) { - bop_lock_acquire( & sync_data->undy_conceded ); +void +wait_undy_conceded(void) +{ + bop_lock_acquire(&sync_data->undy_conceded); } diff --git a/bop_ppr_sync.h b/bop_ppr_sync.h index eee19c4..45a827e 100644 --- a/bop_ppr_sync.h +++ b/bop_ppr_sync.h @@ -1,36 +1,62 @@ #ifndef __BOP_PPR_SYNC_H #define __BOP_PPR_SYNC_H -void ppr_sync_data_reset( void ); +void +ppr_sync_data_reset(void); -int partial_group_get_size( void ); -void partial_group_set_size( int psize ); +int +partial_group_get_size(void); +void +partial_group_set_size(int psize); -void signal_check_done( int passed ); -void signal_commit_done( void ); -void signal_undy_conceded( void ); -void signal_undy_created( int pid ); +void +signal_check_done(int passed); +void +signal_commit_done(void); +void +signal_undy_conceded(void); +void +signal_undy_created(int pid); -void wait_prior_check_done( void ); -void wait_group_commit_done( void ); -void wait_next_commit_done( void ); -void wait_undy_conceded( void ); -void wait_undy_created( void ); +void +wait_prior_check_done(void); +void +wait_group_commit_done(void); +void +wait_next_commit_done(void); +void +wait_undy_conceded(void); +void +wait_undy_created(void); /* Call ports */ -void ppr_group_init( void ); -void ppr_task_init( void ); -void undy_succ_fini( void ); -void ppr_group_init( void ); -void ppr_task_init( void ); -int ppr_check_correctness( void ); -void on_exit_ordered(void); -void on_enter_ordered(void); +void +ppr_group_init(void); +void +ppr_task_init(void); +void +undy_succ_fini(void); +void +ppr_group_init(void); +void +ppr_task_init(void); +int +ppr_check_correctness(void); +void +on_exit_ordered(void); +void +on_enter_ordered(void); + /* void report_conflict( void ); Name conflicts with something in utils.h */ -void data_commit( void ); -void task_group_commit( void ); -void task_group_succ_fini( void ); -void undy_init( void ); -void undy_succ_fini( void ); +void +data_commit(void); +void +task_group_commit(void); +void +task_group_succ_fini(void); +void +undy_init(void); +void +undy_succ_fini(void); #endif /* __BOP_PPR_SYNC_H */ diff --git a/dmmalloc.c b/dmmalloc.c index 2c737c2..5052232 100644 --- a/dmmalloc.c +++ b/dmmalloc.c @@ -1,20 +1,21 @@ #ifndef NDEBUG #include // Commas numbers(debug information) #endif -#include // Print errors -#include // Mutex -#include // System malloc & free -#include // Memcopy -#include // Debug -#include // Boolean types -#include // Get page size -#include "dmmalloc.h" -#include "malloc_wrapper.h" #include "bop_api.h" #include "bop_ports.h" +#include "dmmalloc.h" +#include "malloc_wrapper.h" #include "utils.h" +#include // Debug +#include // Mutex +#include // Boolean types +#include // Print errors +#include // System malloc & free +#include // Memcopy +#include // Get page size -#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) +#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || \ + defined(_M_IX86) #define LOG(x) llog2(x) #else #include @@ -27,7 +28,9 @@ short malloc_panic = 0; // Force sequential allocation rules // BOP macros & structures -#define SEQUENTIAL() (malloc_panic || bop_mode == SERIAL || BOP_task_status() == SEQ || BOP_task_status() == UNDY) +#define SEQUENTIAL() \ + (malloc_panic || bop_mode == SERIAL || BOP_task_status() == SEQ || \ + BOP_task_status() == UNDY) typedef struct { header *start[DM_NUM_CLASSES]; @@ -35,95 +38,136 @@ typedef struct { } ppr_list; static ppr_list *regions = NULL; + // Header info -static header *headers[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; // Current heads of free lists -static header *ends[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; // End of lists in PPR region +static header *headers[DM_NUM_CLASSES] = + {[0 ... DM_NUM_CLASSES - 1] = NULL}; // Current heads of free lists + +static header *ends[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = + NULL}; // End of lists in PPR region + +static header *freedlist[DM_NUM_CLASSES] = + {[0 ... DM_NUM_CLASSES - 1] = + NULL}; // List of items freed during PPR-mode. -static header *freedlist[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = NULL}; // List of items freed during PPR-mode. static header *large_free_list = NULL; -static header *allocated_lists[DM_NUM_CLASSES]= {[0 ... DM_NUM_CLASSES - 1] = NULL}; // List of items allocated during PPR-mode NOTE: info of allocated block + +static header *allocated_lists[DM_NUM_CLASSES] = {[0 ... DM_NUM_CLASSES - 1] = + NULL}; // List of items + +// allocated +// during PPR-mode +// NOTE: info of +// allocated block // Helper prototypes static inline int get_index(size_t); -static inline void grow(int); -static inline void free_now(header *); -static inline bool list_contains(header *list, header *item); -static bool remove_from_alloc_list(header *); -static inline void add_next_list(header **, header *); -static inline void add_freed_list(header *); -static inline header *dm_split(int which, int larger); -static inline int index_bigger(int); -static inline size_t align(size_t size, size_t align); -static inline void get_lock(); -static inline void release_lock(); +static inline void +grow(int); +static inline void +free_now(header *); +static inline bool +list_contains(header *list, header *item); +static bool +remove_from_alloc_list(header *); +static inline void +add_next_list(header **, header *); +static inline void +add_freed_list(header *); +static inline header * +dm_split(int which, int larger); +static inline int +index_bigger(int); +static inline size_t +align(size_t size, size_t align); +static inline void +get_lock(); +static inline void +release_lock(); #ifndef NDEBUG -static int grow_count = 0; -static int growth_size = 0; +static int grow_count = 0; +static int growth_size = 0; static int missed_splits = 0; -static int splits = 0; -static int multi_splits = 0; +static int splits = 0; +static int multi_splits = 0; static int split_attempts[DM_NUM_CLASSES]; static int split_gave_head[DM_NUM_CLASSES]; #endif #define FORCE_INLINE inline __attribute__((always_inline)) - /** x86 assembly code for computing the log2 of a value. This is much faster than math.h log2*/ -static inline int llog2(const int x) { +static inline int +llog2(const int x) +{ int y; - __asm__( "\tbsr %1, %0\n" - : "=r"(y) - : "r" (x) - ); + + __asm__("\tbsr %1, %0\n" : "=r"(y) : "r"(x)); return y; } /**Note: This is the INDEX of the old array of the class index, ie param 0 - * means SIZE class 1. The original implementation had an array that had these values*/ -const FORCE_INLINE size_t size_of_klass(int klass_index) { + * means SIZE class 1. The original implementation had an array that had these + * values*/ +const FORCE_INLINE size_t +size_of_klass(int klass_index) +{ return SIZE_C(klass_index + 1); } -const FORCE_INLINE int goal_blocks(int klass) { - switch(klass) { - case 0 ... 3: - return DM_BLOCK_SIZE * 10; - case 4 ... 12: - return DM_BLOCK_SIZE; - case 13 ... 16: - return MAX(DM_BLOCK_SIZE / (klass - 8), 1); - default: - return 1; +const FORCE_INLINE int +goal_blocks(int klass) +{ + switch (klass) { + case 0 ... 3: + return DM_BLOCK_SIZE * 10; + case 4 ... 12: + return DM_BLOCK_SIZE; + case 13 ... 16: + return MAX(DM_BLOCK_SIZE / (klass - 8), 1); + default: + return 1; } } -static int *goal_counts() { - static int goal[DM_NUM_CLASSES] = {[0 ... (DM_NUM_CLASSES - 1)] = -1}; +static int * +goal_counts() +{ + static int goal[DM_NUM_CLASSES] = {[0 ...(DM_NUM_CLASSES - 1)] = -1}; int ind; + if (goal[0] == -1) - for (ind = 0; ind < DM_NUM_CLASSES; ind++) + for (ind = 0; ind < DM_NUM_CLASSES; ind++) goal[ind] = goal_blocks(ind); - return goal; + return goal; } -void dm_check(void *payload) { +void +dm_check(void *payload) +{ if (payload == NULL) return; header *head = HEADER(payload); + ASSERTBLK(head); } -static inline size_t align(size_t size, size_t alignment) { +static inline size_t +align(size_t size, size_t alignment) +{ int log = LOG(alignment); + bop_assert(alignment == (1 << log)); - return(((size) + (alignment-1)) & ~(alignment-1)); + return (((size) + (alignment - 1)) & ~(alignment - 1)); } -/**Get the index corresponding to the given size. If size > MAX_SIZE, then return -1*/ -static inline int get_index(size_t size) { +/**Get the index corresponding to the given size. If size > MAX_SIZE, then + * return -1*/ +static inline int +get_index(size_t size) +{ bop_assert(size == ALIGN(size)); bop_assert(size >= HSIZE); // Space is too big. @@ -131,39 +175,61 @@ static inline int get_index(size_t size) { return -1; // Too big int index = LOG(size) - DM_CLASS_OFFSET - 1; - if (index == -1 || size_of_klass(index) < size) // this is how it gets rounded up only if needed + if (index == -1 || + size_of_klass(index) < + size) // this is how it gets rounded up only if needed index++; bop_assert(index >= 0 && index < DM_NUM_CLASSES); - bop_assert(size_of_klass(index) >= size); // This size class is large enough - bop_assert(index == 0 || size_of_klass(index - 1) < size); // Using the minimal valid size class + bop_assert(size_of_klass(index) >= + size); // This size class is large enough + bop_assert(index == 0 || + size_of_klass(index - 1) < + size); // Using the minimal valid size class return index; } /**Locking functions*/ #ifdef USE_LOCKS static pthread_mutex_t lock; -static inline void get_lock() { +static inline void +get_lock() +{ pthread_mutex_lock(&lock); } -static inline void release_lock() { + +static inline void +release_lock() +{ pthread_mutex_unlock(&lock); } #else #warning "Dmmalloc malloc not locking for thread" -static inline void get_lock() {/*Do nothing*/} -static inline void release_lock() {/*Do nothing*/} +static inline void +get_lock() +{ /*Do nothing */ +} + +static inline void +release_lock() +{ /*Do nothing */ +} #endif // Use locks + /** Bop-related functionss*/ /** Divide up the currently allocated groups into regions. Insures that each task will have a percentage of a SEQUENTIAL() goal*/ -static int *count_lists(bool is_locked) { +static int * +count_lists(bool is_locked) +{ static int counts[DM_NUM_CLASSES]; int i, loc_count; + if (!is_locked) get_lock(); header *head; + for (i = 0; i < DM_NUM_CLASSES; i++) { loc_count = 0; for (head = headers[i]; head; head = CAST_H(head->next)) @@ -174,34 +240,40 @@ static int *count_lists(bool is_locked) { release_lock(); return counts; } + /** BOP Port functions */ -void carve() { +void +carve() +{ bop_assert(SEQUENTIAL()); int tasks = BOP_get_group_size(); + if (regions != NULL) { dm_free(regions); // Dm_free -> don't have lock } regions = dm_calloc(tasks, sizeof(ppr_list)); - get_lock(); // Now locked + get_lock(); // Now locked grow(tasks); // Need to already have the lock int *counts = count_lists(true); // true -> we have the lock + bop_assert(tasks >= 2); int index, count, j, r; header *current_headers[DM_NUM_CLASSES]; header *temp = (header *)-1; - for (index = 0; index < DM_NUM_CLASSES; index++) + + for (index = 0; index < DM_NUM_CLASSES; index++) current_headers[index] = CAST_H(headers[index]); - // Actually split the lists + // Actually split the lists for (index = 0; index < DM_NUM_CLASSES; index++) { bop_assert(counts[index] > 0); count = counts[index] / tasks; bop_assert(count > 0); for (r = 0; r < tasks; r++) { regions[r].start[index] = current_headers[index]; - temp = CAST_H(current_headers[index]->next); + temp = CAST_H(current_headers[index]->next); for (j = 0; j < count && temp; j++) { temp = CAST_H(temp->next); } @@ -216,23 +288,27 @@ void carve() { } /**set the range of values to be used by this PPR task*/ -void initialize_group() { +void +initialize_group() +{ bop_msg(2, "DM Malloc initializing spec task %d", spec_order); // bop_assert(! SEQUENTIAL() ); - int group_num = spec_order; + int group_num = spec_order; ppr_list my_list = regions[group_num]; int ind; + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { ends[ind] = my_list.end[ind]; if (task_status != MAIN) headers[ind] = my_list.start[ind]; if (group_num != 0) { - bop_assert(headers[ind] != NULL); + bop_assert(headers[ind] != NULL); } else { bop_assert(task_status == MAIN); } bop_assert(headers[ind] != ends[ind]); - // bop_msg(3, "DM malloc task %d header[%d] = %p", spec_order, ind, headers[ind]); + // bop_msg(3, "DM malloc task %d header[%d] = %p", spec_order, ind, + // headers[ind]); } #ifndef NDEBUG for (ind = 0; ind < DM_NUM_CLASSES; ind++) { @@ -245,13 +321,18 @@ void initialize_group() { /** Merge 1) Promise everything in both allocated and free list */ -// NOTE: only the heads should be promised. The payloads should be the job of the caller? -void malloc_promise() { +// NOTE: only the heads should be promised. The payloads should be the job of +// the caller? +void +malloc_promise() +{ header *head; int i; int allocs = 0, frees = 0; + for (i = 0; i < DM_NUM_CLASSES; i++) { - for (head = allocated_lists[i]; head != NULL; head = CAST_H(head->next)) { + for (head = allocated_lists[i]; head != NULL; + head = CAST_H(head->next)) { BOP_promise(head, head->blocksize); // Playload matters allocs++; } @@ -270,45 +351,57 @@ void malloc_promise() { bop_msg(3, "Number of promised allocs: \t%d", allocs); } -void dm_malloc_undy_init() { - return; // TODO this method should actually work, but it causes Travis to fail. - // Called when the under study begins. Free everything in the freed list - bop_assert(SEQUENTIAL()); - header *current, *next; - int ind; - for (ind = 0; ind < DM_NUM_CLASSES; ind++) { - for (current = freedlist[ind]; current != NULL; current = CAST_H(current->next)) { - dm_free(PAYLOAD(current)); +void +dm_malloc_undy_init() +{ + return; // TODO this method should actually work, but it causes Travis to + // fail. + // Called when the under study begins. Free everything in the freed list + bop_assert(SEQUENTIAL()); + header *current, *next; + int ind; + + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { + for (current = freedlist[ind]; current != NULL; + current = CAST_H(current->next)) { + dm_free(PAYLOAD(current)); + } + freedlist[ind] = NULL; } - freedlist[ind] = NULL; - } - for (current = large_free_list; current != NULL; current = CAST_H(current->next)) { - dm_free(PAYLOAD(current)); - } - for (ind = 0; ind < DM_NUM_CLASSES; ind++) { - for (current = allocated_lists[ind]; current != NULL; current = next) { - next = CAST_H(current->next); - current->next = NULL; + for (current = large_free_list; current != NULL; + current = CAST_H(current->next)) { + dm_free(PAYLOAD(current)); + } + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { + for (current = allocated_lists[ind]; current != NULL; current = next) { + next = CAST_H(current->next); + current->next = NULL; + } + allocated_lists[ind] = NULL; } - allocated_lists[ind] = NULL; - } } -static inline void grow(const int tasks) { +static inline void +grow(const int tasks) +{ // THIS IS THE NEW GROW FUNCTION! int class_index, blocks_left, size; + if (tasks > 1) bop_debug("growing tasks = %d", tasks); #ifndef NDEBUG grow_count++; #endif int *goal_counts_arr = goal_counts(); + // Compute the number of blocks to allocate // size_t growth = HSIZE; int blocks[DM_NUM_CLASSES]; int *counts = count_lists(true); // We have the lock + for (class_index = 0; class_index < DM_NUM_CLASSES; class_index++) { - blocks_left = tasks * goal_counts_arr[class_index] - counts[class_index]; + blocks_left = + tasks * goal_counts_arr[class_index] - counts[class_index]; blocks[class_index] = blocks_left >= 0 ? blocks_left : 0; // growth += blocks[class_index] * size_of_klass(class_index); } @@ -317,28 +410,41 @@ static inline void grow(const int tasks) { char *space_head; int current_block; char *debug_ptr; - for (class_index = 0; class_index < DM_NUM_CLASSES; class_index++) { - size = size_of_klass(class_index); - space_head = sys_calloc(blocks[class_index], size); // system malloc, use byte-sized type - bop_assert(blocks[class_index] == 0 || space_head != NULL); // Ran out of sys memory - for (current_block = 0; current_block < blocks[class_index]; current_block++) { + for (class_index = 0; class_index < DM_NUM_CLASSES; class_index++) { + size = size_of_klass(class_index); + space_head = sys_calloc(blocks[class_index], + size); // system malloc, use byte-sized type + bop_assert(blocks[class_index] == 0 || + space_head != NULL); // Ran out of sys memory + + for (current_block = 0; current_block < blocks[class_index]; + current_block++) { // Set up this space head = (header *)&space_head[current_block * size]; - // Make sure the last B in the head is writtable +// Make sure the last B in the head is writtable #ifndef NDEBUG + if (grow_count > 1) { /** Utilization tests */ debug_ptr = (char *)head; // Check stack is growing correctly - bop_assert(current_block == 0 || - headers[class_index] == (header *)&space_head[(current_block - 1) * size]); + bop_assert( + current_block == 0 || + headers[class_index] == + (header *)&space_head[(current_block - 1) * size]); // calloc'd return & seperate from previous head bop_assert(*debug_ptr == (char)0); // last byte is readable - bop_assert(current_block == blocks[class_index] - 1 || debug_ptr[size -1] == (char) 0); + bop_assert(current_block == blocks[class_index] - 1 || + debug_ptr[size - 1] == (char)0); // Adjacent in memory to previous block - bop_assert(current_block == 0 || debug_ptr[-1] == 'x'); // Previous byte is the last of the previous - debug_ptr[size - 1] = 'x'; // This is an array, so -1 since the highest array index is -1 than length + bop_assert( + current_block == 0 || + debug_ptr[-1] == + 'x'); // Previous byte is the last of the previous + debug_ptr[size - 1] = 'x'; // This is an array, so -1 since the + // highest array index is -1 than + // length } #endif list_top = headers[class_index]; @@ -346,41 +452,51 @@ static inline void grow(const int tasks) { if (list_top == NULL) { headers[class_index] = head; head->next = head->prev = NULL; - } - else { - head->next = CAST_UH(list_top); - list_top->prev = CAST_UH(head); + } else { + head->next = CAST_UH(list_top); + list_top->prev = CAST_UH(head); headers[class_index] = head; } } - // Post-size class division checks +// Post-size class division checks #ifndef NDEBUG if (grow_count > 1) { // Ensure that this list is not a giant loop header *current; - for (current = CAST_H(headers[class_index]->next); current; current = CAST_H(current->next)) { - bop_assert(current != headers[class_index]); - bop_assert(current != CAST_H(current->next)); + + for (current = CAST_H(headers[class_index]->next); current; + current = CAST_H(current->next)) { + bop_assert(current != headers[class_index]); + bop_assert(current != CAST_H(current->next)); } } #endif } } -// Get the head of the free list. This uses get_index and additional logic for PPR execution -static inline header *get_header(size_t size, int *which) { +// Get the head of the free list. This uses get_index and additional logic for +// PPR execution +static inline header * +get_header(size_t size, int *which) +{ header *found = NULL; - int temp = -1; + int temp = -1; + if (size > MAX_SIZE) { found = NULL; - temp = -1; + temp = -1; } else { - temp = get_index(size); + temp = get_index(size); found = headers[temp]; if (!SEQUENTIAL() && found != NULL) { - // This will be useless in sequential mode, and useless if found == NULL + // This will be useless in sequential mode, and useless if found == + // NULL if (ends[temp] != NULL && CAST_UH(found) == ends[temp]->next) { - bop_msg(3, "Something may have gone wrong: value of ends[which]: %p\t value of which: %d", ends[temp], temp); + bop_msg(3, + "Something may have gone wrong: value of ends[which]: " + "%p\t value of which: %d", + ends[temp], + temp); found = NULL; } } @@ -391,19 +507,23 @@ static inline header *get_header(size_t size, int *which) { } int alist_added = 0; -extern void BOP_malloc_rescue(char *, size_t); +extern void +BOP_malloc_rescue(char *, size_t); // BOP-safe malloc implementation based off of size classes. -void *dm_malloc(const size_t size) { +void * +dm_malloc(const size_t size) +{ volatile header *block = NULL; int which, bigger = -1; size_t alloc_size; + if (size == 0) - return NULL; + return NULL; alloc_size = ALIGN(size + HSIZE); // Same regardless of task_status get_lock(); - // Get the right header +// Get the right header malloc_begin: which = -2; block = get_header(alloc_size, &which); @@ -415,19 +535,22 @@ void *dm_malloc(const size_t size) { // Huge block always use system malloc block = sys_malloc(alloc_size); if (block == NULL) { - // ERROR: ran out of system memory. malloc rescue won't help + // ERROR: ran out of system memory. malloc rescue won't + // help release_lock(); return NULL; } // Don't need to add to free list, just set information block->blocksize = alloc_size; goto checks; - }else{ - // Not SEQUENTIAL(), and allocating a too-large block. Might be able to rescue + } else { + // Not SEQUENTIAL(), and allocating a too-large block. Might be + // able to rescue BOP_malloc_rescue("Large allocation in PPR", alloc_size); goto malloc_begin; // Try again } - } else if (which < DM_NUM_CLASSES - 1 && (bigger = index_bigger(which)) != -1) { + } else if (which < DM_NUM_CLASSES - 1 && + (bigger = index_bigger(which)) != -1) { block = dm_split(which, bigger); ASSERTBLK(block); } else if (SEQUENTIAL()) { @@ -435,7 +558,8 @@ void *dm_malloc(const size_t size) { grow(1); goto malloc_begin; } else { - BOP_malloc_rescue("Need to grow the lists in non-SEQUENTIAL()", alloc_size); + BOP_malloc_rescue("Need to grow the lists in non-SEQUENTIAL()", + alloc_size); // Grow will happen at the next pass through... goto malloc_begin; // Try again // Bop_abort @@ -447,8 +571,9 @@ void *dm_malloc(const size_t size) { headers[which] = CAST_H(block->next); // Remove from free list // Write allocated next information if (!SEQUENTIAL()) { - bop_assert(which != -1); // Valid because -1 == too large, can't do in PPR - add_next_list(&allocated_lists[which], (header*) block); + bop_assert(which != + -1); // Valid because -1 == too large, can't do in PPR + add_next_list(&allocated_lists[which], (header *)block); } checks: ASSERTBLK(block); @@ -456,20 +581,31 @@ void *dm_malloc(const size_t size) { return PAYLOAD(block); } -void print_headers() { +void +print_headers() +{ int ind; + for (ind = 0; ind < DM_NUM_CLASSES; ind++) { - bop_msg(1, "headers[%d] = %p get_header = %p", ind, headers[ind], get_header(size_of_klass(ind), NULL)); + bop_msg(1, + "headers[%d] = %p get_header = %p", + ind, + headers[ind], + get_header(size_of_klass(ind), NULL)); } } -// Compute the index of the next lagest index > which st the index has a non-null headers -static inline int index_bigger(int which) { +// Compute the index of the next lagest index > which st the index has a +// non-null headers +static inline int +index_bigger(int which) +{ if (which == -1) return -1; which++; int index; - while(which < DM_NUM_CLASSES) { + + while (which < DM_NUM_CLASSES) { if (get_header(size_of_klass(which), &index) != NULL) { return which; } @@ -479,7 +615,9 @@ static inline int index_bigger(int which) { } // Repeatedly split a larger block into a block of the required size -static inline header *dm_split(int which, int larger) { +static inline header * +dm_split(int which, int larger) +{ if (which > 15) { bop_msg(3, "In large split"); } @@ -488,7 +626,9 @@ static inline header *dm_split(int which, int larger) { split_gave_head[which]++; #endif header *block = headers[larger]; // Block to split up - header *split = CAST_H((CHARP(block) + size_of_klass(which))); // Cut in half + header *split = + CAST_H((CHARP(block) + size_of_klass(which))); // Cut in half + bop_assert(block != split); // Split-specific info sets @@ -509,14 +649,18 @@ static inline header *dm_split(int which, int larger) { split_gave_head[which] += larger - which; #endif bop_assert(which < DM_NUM_CLASSES); - while(which < larger) { + while (which < larger) { // Update the headers - split = CAST_H((CHARP(split) + size_of_klass(which - 1))); // Which - 1 since only half of the block is used here. which -1 === size / 2 + split = CAST_H( + (CHARP(split) + size_of_klass(which - 1))); // Which - 1 since only + // half of the block is + // used here. which -1 + // === size / 2 // bop_msg(1, "Split addr %p val %c", split, *((char*) split)); if (SEQUENTIAL()) { assert(headers[which] == NULL); memset(split, 0, HSIZE); - headers[which] = split; + headers[which] = split; } else { // Go through dm_free split->blocksize = size_of_klass(which); @@ -530,9 +674,12 @@ static inline header *dm_split(int which, int larger) { } // standard calloc using malloc -void *dm_calloc(size_t n, size_t size) { +void * +dm_calloc(size_t n, size_t size) +{ header *head; char *allocd = dm_malloc(size * n); + if (allocd != NULL) { head = HEADER(allocd); assert(head->blocksize >= (size * n)); @@ -542,10 +689,14 @@ void *dm_calloc(size_t n, size_t size) { return allocd; } -// Reallocator: use sytem realloc with large->large sizes in SEQUENTIAL() mode. Otherwise use standard realloc implementation -void *dm_realloc(void *ptr, size_t gsize) { +// Reallocator: use sytem realloc with large->large sizes in SEQUENTIAL() mode. +// Otherwise use standard realloc implementation +void * +dm_realloc(void *ptr, size_t gsize) +{ header *old_head, *new_head; size_t new_size = ALIGN(gsize + HSIZE), old_size; + if (gsize == 0) return NULL; if (ptr == NULL) { @@ -561,16 +712,17 @@ void *dm_realloc(void *ptr, size_t gsize) { #endif ASSERTBLK(old_head); - old_size = old_head->blocksize; + old_size = old_head->blocksize; int new_index = get_index(new_size); if (new_index != -1 && size_of_klass(new_index) <= old_head->blocksize) { return ptr; // No need to update - } else if (SEQUENTIAL() && old_head->blocksize > MAX_SIZE && new_size > MAX_SIZE) { + } else if (SEQUENTIAL() && old_head->blocksize > MAX_SIZE && + new_size > MAX_SIZE) { // Use system realloc in SEQUENTIAL() mode for large->large blocks - new_head = sys_realloc(old_head, new_size); + new_head = sys_realloc(old_head, new_size); new_head->blocksize = new_size; // Sytem block - new_head->next = NULL; + new_head->next = NULL; SET_ALLOCATED(new_head, true); ASSERTBLK(new_head); return PAYLOAD(new_head); @@ -578,17 +730,26 @@ void *dm_realloc(void *ptr, size_t gsize) { // Build off malloc and free ASSERTBLK(old_head); size_t size_cache = old_head->blocksize; + // We're reallocating within managed memory void *new_payload = dm_malloc(gsize); // Malloc will tweak size again. + if (new_payload == NULL) { - bop_msg(1, "Unable to reallocate %p(size %u) to new size %u", ptr, old_size, new_size); - return NULL; + bop_msg(1, + "Unable to reallocate %p(size %u) to new size %u", + ptr, + old_size, + new_size); + return NULL; } // Copy the data - size_t copy_size = MIN(old_size, new_size) - HSIZE; // block sizes include the header! + size_t copy_size = + MIN(old_size, new_size) - HSIZE; // block sizes include the header! + assert(copy_size != new_size - HSIZE); - bop_assert(HEADER(new_payload)->blocksize >= (copy_size + HSIZE)); // Check dm_malloc gave enough space + bop_assert(HEADER(new_payload)->blocksize >= + (copy_size + HSIZE)); // Check dm_malloc gave enough space new_payload = memcpy(new_payload, ptr, copy_size); // copy data bop_assert(((header *)HEADER(new_payload))->blocksize >= copy_size); ASSERTBLK(old_head); @@ -604,9 +765,12 @@ void *dm_realloc(void *ptr, size_t gsize) { * 1) Any sized block running in SEQ mode * 2) Small block allocated and freed by this PPR task. * A free is queued to be free'd at BOP commit time otherwise. -*/ -void dm_free(void *ptr) { + */ +void +dm_free(void *ptr) +{ header *free_header = HEADER(ptr); + ASSERTBLK(free_header); get_lock(); #ifdef DM_REM_ALLOC @@ -617,22 +781,28 @@ void dm_free(void *ptr) { if (SEQUENTIAL() || remove_from_alloc_list(free_header)) { release_lock(); free_now(free_header); - } else{ - SET_ALLOCATED(free_header, false); - add_freed_list(free_header); + } else { + SET_ALLOCATED(free_header, false); + add_freed_list(free_header); } release_lock(); } -// Free a(regular or huge) block now. all saftey checks must be done before calling this function -static inline void free_now(header *head) { +// Free a(regular or huge) block now. all saftey checks must be done before +// calling this function +static inline void +free_now(header *head) +{ int which; size_t size = head->blocksize; + ASSERTBLK(head); - bop_assert(size >= HSIZE && size == ALIGN(size)); // Size is aligned, ie right value was written + bop_assert(size >= HSIZE && + size == + ALIGN(size)); // Size is aligned, ie right value was written // Test for system block if (size > MAX_SIZE) { - if (SEQUENTIAL() ) { + if (SEQUENTIAL()) { sys_free(head); } else { get_lock(); @@ -644,6 +814,7 @@ static inline void free_now(header *head) { // Synchronised region get_lock(); header *free_stack = get_header(size, &which); + bop_assert(size <= MAX_SIZE); bop_assert(which != -1); if (which != -1) @@ -651,33 +822,41 @@ static inline void free_now(header *head) { if (free_stack == NULL) { // Empty free_stack head->next = head->prev = NULL; - headers[which] = head; + headers[which] = head; release_lock(); return; } free_stack->prev = CAST_UH(head); - head->next = CAST_UH(free_stack); - headers[which] = head; + head->next = CAST_UH(free_stack); + headers[which] = head; release_lock(); } -inline size_t dm_malloc_usable_size(void *ptr) { +inline size_t +dm_malloc_usable_size(void *ptr) +{ if (ptr == NULL) return 0; header *free_header = HEADER(ptr); - size_t head_size = free_header->blocksize; + size_t head_size = free_header->blocksize; + if (head_size > MAX_SIZE) { head_size = sys_malloc_usable_size(free_header); } return head_size - HSIZE; // Even for system-allocated chunks. } -/*malloc library utility functions: utility functions, debugging, list management etc */ -static bool remove_from_alloc_list(header *val) { +/*malloc library utility functions: utility functions, debugging, list + * management etc */ +static bool +remove_from_alloc_list(header *val) +{ // Remove val from the list header *current, *prev = NULL; const int index = get_index(val->blocksize); - for (current = allocated_lists[index]; current; prev = current, current = CAST_H(current->next)) { + + for (current = allocated_lists[index]; current; + prev = current, current = CAST_H(current->next)) { if (current == val) { if (prev == NULL) { allocated_lists[index] = CAST_H(current->next); @@ -691,10 +870,13 @@ static bool remove_from_alloc_list(header *val) { return false; } -static inline bool list_contains(header *list, header *search_value) { +static inline bool +list_contains(header *list, header *search_value) +{ if (list == NULL || search_value == NULL) return false; header *current; + for (current = list; current != NULL; current = CAST_H(current->next)) { if (current == search_value) return true; @@ -703,10 +885,12 @@ static inline bool list_contains(header *list, header *search_value) { } // Add an allocated item to the allocated list -static int added_n = 0; +static int added_n = 0; static int nseq_added_n = 0; -static inline void add_next_list(header **list_head, header *item) { +static inline void +add_next_list(header **list_head, header *item) +{ added_n++; if (!SEQUENTIAL()) nseq_added_n++; @@ -715,9 +899,12 @@ static inline void add_next_list(header **list_head, header *item) { *list_head = item; } -static inline void add_freed_list(header *item) { +static inline void +add_freed_list(header *item) +{ size_t size = item->blocksize; - int index = get_index(size); + int index = get_index(size); + if (index >= DM_NUM_CLASSES) { add_next_list(&large_free_list, item); } @@ -729,36 +916,45 @@ static inline void add_freed_list(header *item) { } /**Print debug info*/ -void dm_print_info(void) { +void +dm_print_info(void) +{ #ifndef NDEBUG setlocale(LC_ALL, ""); - int *counts = count_lists(true); // We don't actually have the lock, but don't care about thread saftey here + int *counts = count_lists(true); // We don't actually have the lock, but + + // don't care about thread saftey here int i; int GROW_S = 0; + for (i = 0; i < DM_NUM_CLASSES; i++) GROW_S += size_of_klass(i); printf("******DM Debug info******\n"); printf("Grow count: %'d\n", grow_count); printf("Max grow size: %'d B\n", GROW_S); printf("Total managed mem: %'d B\n", growth_size); - printf("Differnce in actual & max: %'d B\n", (grow_count * (GROW_S)) - growth_size); + printf("Differnce in actual & max: %'d B\n", + (grow_count * (GROW_S)) - growth_size); for (i = 0; i < DM_NUM_CLASSES; i++) { - printf("\tSplit to give class %d(%'lu B) %d times. It was given %d heads\n", - i+1, size_of_klass(i), split_attempts[i],split_gave_head[i]); + printf("\tSplit to give class %d(%'lu B) %d times. It was given %d " + "heads\n", + i + 1, + size_of_klass(i), + split_attempts[i], + split_gave_head[i]); } printf("Splits: %'d\n", splits); printf("Miss splits: %'d\n", missed_splits); printf("Multi splits: %'d\n", multi_splits); for (i = 0; i < DM_NUM_CLASSES; i++) - printf("Class %d had %'d remaining items\n", i+1, counts[i]); + printf("Class %d had %'d remaining items\n", i + 1, counts[i]); #else - printf("dm malloc not compiled in debug mode. Recompile without NDEBUG defined to keep track of debug information.\n"); + printf("dm malloc not compiled in debug mode. Recompile without NDEBUG " + "defined to keep track of debug information.\n"); #endif } -bop_port_t bop_alloc_port = { - .ppr_group_init = carve, - .ppr_task_init = initialize_group, - .task_group_commit = malloc_promise, - .undy_init = dm_malloc_undy_init -}; +bop_port_t bop_alloc_port = {.ppr_group_init = carve, + .ppr_task_init = initialize_group, + .task_group_commit = malloc_promise, + .undy_init = dm_malloc_undy_init}; diff --git a/dmmalloc.h b/dmmalloc.h index 768f0da..44ac031 100644 --- a/dmmalloc.h +++ b/dmmalloc.h @@ -1,8 +1,8 @@ #ifndef DM_MALLOC_H #define DM_MALLOC_H -#include #include +#include // Dm structs, unions etc typedef struct { @@ -17,27 +17,36 @@ typedef struct { } header; #ifdef DM_REM_ALLOC -#define SET_ALLOCATED(h,a) (h->allocated = a) +#define SET_ALLOCATED(h, a) (h->allocated = a) #else -#define SET_ALLOCATED(h,a) +#define SET_ALLOCATED(h, a) #endif // Prototypes void *dm_malloc(size_t); -void *dm_realloc(void *, size_t); -void dm_free(void *); +void * +dm_realloc(void *, size_t); +void +dm_free(void *); void *dm_calloc(size_t, size_t); -void dm_print_info(void); -size_t dm_malloc_usable_size(void *); -void dm_check(void *); +void +dm_print_info(void); +size_t +dm_malloc_usable_size(void *); +void +dm_check(void *); // Bop-related functions -void carve(); // Divide up avaliable memory -void initialize_group(); // Set end pointers for this ppr task +void +carve(); // Divide up avaliable memory +void +initialize_group(); // Set end pointers for this ppr task // Data accessors for merge time -void malloc_merge(void); -void malloc_merge_counts(bool); // Counts get updated AFTER abort status is known +void +malloc_merge(void); +void +malloc_merge_counts(bool); // Counts get updated AFTER abort status is known // Alignment based on word size #if __WORDSIZE == 64 @@ -54,7 +63,7 @@ void malloc_merge_counts(bool); // Counts get updated AFTER abort status is know #endif // Alignement/ header macros -#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~(ALIGNMENT-1)) +#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1)) #define HSIZE (ALIGN((sizeof(header)))) #define HEADER(vp) ((header *)(((char *)(vp)) - HSIZE)) #define CAST_UH(h) ((struct header *)(h)) @@ -66,9 +75,12 @@ void malloc_merge_counts(bool); // Counts get updated AFTER abort status is know // Class size macros #define DM_NUM_CLASSES 16 -#define DM_CLASS_OFFSET 4 // How much extra to shift the bits for size class, ie class k is 2 ^ (k + DM_CLASS_OFFSET) +#define DM_CLASS_OFFSET \ + 4 // How much extra to shift the bits for size class, ie class k is 2 ^ (k + // + DM_CLASS_OFFSET) #define MAX_SIZE SIZE_C(DM_NUM_CLASSES) -#define SIZE_C(k) (ALIGN((1 << (k + DM_CLASS_OFFSET)))) // Allows for iterative spliting +#define SIZE_C(k) \ + (ALIGN((1 << (k + DM_CLASS_OFFSET)))) // Allows for iterative spliting #define DM_MAX_REQ (ALIGN((MAX_SIZE) - (HSIZE))) #endif diff --git a/key_value_checks.c b/key_value_checks.c index bd2ea1a..857b936 100644 --- a/key_value_checks.c +++ b/key_value_checks.c @@ -1,49 +1,53 @@ #include "bop_api.h" -#include "key_value_checks.h" -#include "external/malloc.h" #include "bop_ports.h" +#include "external/malloc.h" +#include "key_value_checks.h" -#include -#include #include +#include +#include #include static mspace kv_mspace; static kv_object_t kv_list = NULL; /** head of linked - list*/ -static pthread_mutex_t lock; /** Lock for the list operations */ -void get_lock(); -void release_lock(); - +static pthread_mutex_t lock; /** Lock for the list operations */ +void +get_lock(); +void +release_lock(); #define SIZE(dr) (dr.data.complex.size) #define DATA(dr) (dr.data.complex.start) -#define SET(var, new_val) var = (typeof((var))) (new_val) +#define SET(var, new_val) var = (typeof((var)))(new_val) static inline void record_internal(kv_object_t, mem_op, kv_entry_t); -extern int spec_order; //used to index into the array - - -//recording functions -static inline void record_internal(kv_object_t obj, mem_op op, kv_entry_t new_entry){ - get_lock(); - //add to the write/read region - bop_assert(spec_order > 0 && spec_order < BOP_get_group_size()); //sanity checks - if(op == READ || op == READ_AND_WRITE){ - SET(new_entry->next, obj->reads[spec_order]); - obj->reads[spec_order] = new_entry; - }else if(op == WRITE || op == READ_AND_WRITE){ - if(op == READ_AND_WRITE){ - const kv_entry_t prev_entry = new_entry; - new_entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); - memcpy(new_entry, prev_entry, sizeof(__raw_kv_entry_t)); +extern int spec_order; // used to index into the array + +// recording functions +static inline void +record_internal(kv_object_t obj, mem_op op, kv_entry_t new_entry) +{ + get_lock(); + // add to the write/read region + bop_assert(spec_order > 0 && + spec_order < BOP_get_group_size()); // sanity checks + if (op == READ || op == READ_AND_WRITE) { + SET(new_entry->next, obj->reads[spec_order]); + obj->reads[spec_order] = new_entry; + } else if (op == WRITE || op == READ_AND_WRITE) { + if (op == READ_AND_WRITE) { + const kv_entry_t prev_entry = new_entry; + + new_entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); + memcpy(new_entry, prev_entry, sizeof(__raw_kv_entry_t)); + } + SET(new_entry->next, obj->writes[spec_order]); + obj->writes[spec_order] = new_entry; + } else { + bop_msg(1, "Unkown mem_op for object-level monitoring"); } - SET(new_entry->next, obj->writes[spec_order]); - obj->writes[spec_order] = new_entry; - }else{ - bop_msg(1, "Unkown mem_op for object-level monitoring"); - } - release_lock(); + release_lock(); } /** @@ -51,141 +55,209 @@ static inline void record_internal(kv_object_t obj, mem_op op, kv_entry_t new_en 1) R/W both not-null and key-value pairs are the same Plan (there's lots of for loops) -If any 2 spec tasks R/W the same KEY pair with different VALUE writes, its a failure. +If any 2 spec tasks R/W the same KEY pair with different VALUE writes, its a +failure. The check for this is a little messy because theres lots of loops to check. */ -static inline int data_range_eq(data_range read, data_range write){ - - int index; - - if(read.is_simple != write.is_simple) - return 0; - if(read.is_simple) - return read.data.simple == write.data.simple; - //here: both are complex - if(SIZE(read) != SIZE(write)) - return 0; - for(index = 0; index < SIZE(read); index++){ - if(DATA(read)[index] != DATA(write)[index]) - return 0; - } - return 1; -} -//compare the same part in each struct -static inline int entry_conflicts(kv_entry_t read, kv_entry_t write){ - //only care if keys are equal - return data_range_eq(read->key, write->key) && //accessed the same part of struct - ! data_range_eq(read->value, write->value); //didn't see the same things -} -//TODO this needs to be stored in hash tables. Lists are bad. -int obj_correct(){ - kv_object_t kv_obj; - const int gs = BOP_get_group_size(); - int read_index, write_index; - kv_entry_t read_data, write_data; - for(kv_obj = kv_list; kv_obj != NULL; SET(kv_obj, kv_obj->next)){ - for(read_index = 0; read_index < gs; read_index++){ - for(SET(read_data, kv_obj->reads[read_index]); read_data != NULL; SET(read_data, read_data->next)){ - for(write_index = read_index + 1; write_index < gs; write_index++){ - for(SET(write_data, kv_obj->writes[write_index]); write_data != NULL; SET(write_data, write_data->next)){ - if( entry_conflicts(read_data, write_data) ){ - return 0; +static inline int +data_range_eq(data_range read, data_range write) +{ + int index; + + if (read.is_simple != write.is_simple) + return 0; + if (read.is_simple) + return read.data.simple == write.data.simple; + // here: both are complex + if (SIZE(read) != SIZE(write)) + return 0; + for (index = 0; index < SIZE(read); index++) { + if (DATA(read)[index] != DATA(write)[index]) + return 0; + } + return 1; +} + +// compare the same part in each struct +static inline int +entry_conflicts(kv_entry_t read, kv_entry_t write) +{ + // only care if keys are equal + return data_range_eq(read->key, + write->key) && // accessed the same part of struct + !data_range_eq(read->value, + write->value); // didn't see the same things +} + +// TODO this needs to be stored in hash tables. Lists are bad. +int +obj_correct() +{ + kv_object_t kv_obj; + const int gs = BOP_get_group_size(); + int read_index, write_index; + kv_entry_t read_data, write_data; + + for (kv_obj = kv_list; kv_obj != NULL; SET(kv_obj, kv_obj->next)) { + for (read_index = 0; read_index < gs; read_index++) { + for (SET(read_data, kv_obj->reads[read_index]); read_data != NULL; + SET(read_data, read_data->next)) { + for (write_index = read_index + 1; write_index < gs; + write_index++) { + for (SET(write_data, kv_obj->writes[write_index]); + write_data != NULL; + SET(write_data, write_data->next)) { + if (entry_conflicts(read_data, write_data)) { + return 0; + } + } + } } - } } - } } - } - //loop through everything and check for conflicts. - return 1; -} -//inter-process locking set-up -static inline typeof(lock) * init_obj_lock(){ - static pthread_mutexattr_t attr; //don't want this too die after the process is over - pthread_mutexattr_init(&attr); - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); - pthread_mutex_init(&lock, &attr); - return &lock; -} -static inline void destroy_lock(typeof(lock) * lck){ - pthread_mutex_destroy(lck); -} -static inline void init_mspace(){ - if(!kv_mspace) - kv_mspace = create_mspace(0, 1, 1); //same as bop io -} - -void obj_marking_init(){ - init_obj_lock(); - init_mspace(); -} - -void obj_marking_teardown(){ - //kill the lock - destroy_lock(&lock); - if(!kv_mspace) - kv_mspace = create_mspace(0, 1, 1); //def. size, locked, shared -} -void get_lock(){ - pthread_mutex_lock(&lock); -} -void release_lock(){ - pthread_mutex_unlock(&lock); -} -kv_object_t register_new_object(){ - init_mspace(); - kv_object_t kvo= mspace_calloc(kv_mspace, 1, sizeof(__raw_kv_object_t)); - SET(kvo->next, kv_list); - kv_list = kvo; - return kvo; -} - -static inline void * copy_range(void * data, size_t size){ - void * dest = mspace_malloc(kv_mspace, size); - return memcpy(dest, data, size); -} -static inline void complex_data(data_range * data_range, void * data, size_t len){ - data_range->is_simple = 0; - data_range->data.complex.start = copy_range(data, len); - data_range->data.complex.size = len; -} -static inline void simple_data(data_range * data_range, int num){ - data_range->is_simple = 1; - data_range->data.simple = num; -} -void record_str_pr(kv_object_t obj, mem_op op, char * key, char * value){ - kv_entry_t entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); - complex_data(&entry->key, key, strlen(key)); - complex_data(&entry->value, value, strlen(value)); - record_internal(obj, op, entry); -} -void record_array(kv_object_t obj, mem_op op, void* array, int index, size_t array_data_size){ - kv_entry_t entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); - //for generic arrays, we store the index (KEY) and the (complex) data, array[index]. - //indexing etc for the array[index] in a generic way - char * chars = (char*) array; - char * value = chars + (index * array_data_size); - complex_data(&entry->value, value, array_data_size); - simple_data(&entry->key, index); //easy part - record_internal(obj, op, entry); -} -void record_str_array(kv_object_t obj, mem_op op, int ind, char * value){ - kv_entry_t entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); - simple_data(&entry->key, ind); - complex_data(&entry->value, value, strlen(value)); - record_internal(obj, op, entry); -} -void record_int_array(kv_object_t obj, mem_op op, int ind, int * array){ - record_int_pair(obj, op, ind, array[ind]); -} -void record_int_pair(kv_object_t obj, mem_op op, int ind, int value){ - kv_entry_t entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); - simple_data(&entry->key, ind); - simple_data(&entry->value, value); - record_internal(obj, op, entry); -} - -bop_port_t object_rw_port = { - .ppr_check_correctness = obj_correct, - .ppr_group_init = obj_marking_init -}; + // loop through everything and check for conflicts. + return 1; +} + +// inter-process locking set-up +static inline typeof(lock) *init_obj_lock() +{ + static pthread_mutexattr_t + attr; // don't want this too die after the process is over + + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&lock, &attr); + return &lock; +} + +static inline void +destroy_lock(typeof(lock) *lck) +{ + pthread_mutex_destroy(lck); +} + +static inline void +init_mspace() +{ + if (!kv_mspace) + kv_mspace = create_mspace(0, 1, 1); // same as bop io +} + +void +obj_marking_init() +{ + init_obj_lock(); + init_mspace(); +} + +void +obj_marking_teardown() +{ + // kill the lock + destroy_lock(&lock); + if (!kv_mspace) + kv_mspace = create_mspace(0, 1, 1); // def. size, locked, shared +} + +void +get_lock() +{ + pthread_mutex_lock(&lock); +} + +void +release_lock() +{ + pthread_mutex_unlock(&lock); +} + +kv_object_t +register_new_object() +{ + init_mspace(); + kv_object_t kvo = mspace_calloc(kv_mspace, 1, sizeof(__raw_kv_object_t)); + + SET(kvo->next, kv_list); + kv_list = kvo; + return kvo; +} + +static inline void * +copy_range(void *data, size_t size) +{ + void *dest = mspace_malloc(kv_mspace, size); + + return memcpy(dest, data, size); +} + +static inline void +complex_data(data_range *data_range, void *data, size_t len) +{ + data_range->is_simple = 0; + data_range->data.complex.start = copy_range(data, len); + data_range->data.complex.size = len; +} + +static inline void +simple_data(data_range *data_range, int num) +{ + data_range->is_simple = 1; + data_range->data.simple = num; +} + +void +record_str_pr(kv_object_t obj, mem_op op, char *key, char *value) +{ + kv_entry_t entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); + + complex_data(&entry->key, key, strlen(key)); + complex_data(&entry->value, value, strlen(value)); + record_internal(obj, op, entry); +} + +void +record_array( + kv_object_t obj, mem_op op, void *array, int index, size_t array_data_size) +{ + kv_entry_t entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); + + // for generic arrays, we store the index (KEY) and the (complex) data, + // array[index]. + // indexing etc for the array[index] in a generic way + char *chars = (char *)array; + char *value = chars + (index * array_data_size); + + complex_data(&entry->value, value, array_data_size); + simple_data(&entry->key, index); // easy part + record_internal(obj, op, entry); +} + +void +record_str_array(kv_object_t obj, mem_op op, int ind, char *value) +{ + kv_entry_t entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); + + simple_data(&entry->key, ind); + complex_data(&entry->value, value, strlen(value)); + record_internal(obj, op, entry); +} + +void +record_int_array(kv_object_t obj, mem_op op, int ind, int *array) +{ + record_int_pair(obj, op, ind, array[ind]); +} + +void +record_int_pair(kv_object_t obj, mem_op op, int ind, int value) +{ + kv_entry_t entry = mspace_malloc(kv_mspace, sizeof(__raw_kv_entry_t)); + + simple_data(&entry->key, ind); + simple_data(&entry->value, value); + record_internal(obj, op, entry); +} + +bop_port_t object_rw_port = {.ppr_check_correctness = obj_correct, + .ppr_group_init = obj_marking_init}; diff --git a/key_value_checks.h b/key_value_checks.h index 067e58a..cff687c 100644 --- a/key_value_checks.h +++ b/key_value_checks.h @@ -1,43 +1,46 @@ #ifndef __OBJ_MARKING_H #define __OBJ_MARKING_H -#include #include +#include -typedef enum{ - READ, - WRITE, - READ_AND_WRITE -} mem_op; +typedef enum { READ, WRITE, READ_AND_WRITE } mem_op; -typedef struct{ - bool is_simple : 1; - union { - struct{ - char * start; - size_t size; - } complex; - int simple; - } data; +typedef struct { + bool is_simple : 1; + union { + struct { + char *start; + size_t size; + } complex; + int simple; + } data; } data_range; -typedef struct{ - data_range key; - data_range value; - struct __raw_kv_entry_t * next; // used in BOP lib -} __raw_kv_entry_t, * kv_entry_t; +typedef struct { + data_range key; + data_range value; + struct __raw_kv_entry_t *next; // used in BOP lib +} __raw_kv_entry_t, *kv_entry_t; typedef struct { - struct __raw_kv_object_t * next; - kv_entry_t * reads; //anther pointer because of arrays - kv_entry_t * writes; // ^ length == GROUPSIZE + struct __raw_kv_object_t *next; + kv_entry_t *reads; // anther pointer because of arrays + kv_entry_t *writes; // ^ length == GROUPSIZE } __raw_kv_object_t, *kv_object_t; -void record_str_pr(kv_object_t, mem_op, char * key, char * value); -void record_array(kv_object_t,mem_op, void* array, int index, size_t array_data_size); -void record_str_array(kv_object_t, mem_op, int ind, char * value); -void record_int_array(kv_object_t, mem_op, int ind, int * array); //no data pointers -void record_int_pair(kv_object_t obj, mem_op op, int ind, int value); +void +record_str_pr(kv_object_t, mem_op, char *key, char *value); +void +record_array( + kv_object_t, mem_op, void *array, int index, size_t array_data_size); +void +record_str_array(kv_object_t, mem_op, int ind, char *value); +void +record_int_array(kv_object_t, mem_op, int ind, int *array); // no data pointers +void +record_int_pair(kv_object_t obj, mem_op op, int ind, int value); -kv_object_t register_new_object(void); +kv_object_t +register_new_object(void); #endif diff --git a/libc_overrides.c b/libc_overrides.c index 59b4b9d..eab9794 100644 --- a/libc_overrides.c +++ b/libc_overrides.c @@ -1,10 +1,13 @@ -#include #include "bop_api.h" +#include + +void * +memmove(void *dest, const void *source, size_t num) +{ + char holder[num]; -void *memmove(void *dest, const void *source, size_t num){ - char holder[num]; - memcpy(holder, source, num); - memcpy(dest, holder, num); - BOP_promise(dest, num); - return dest; + memcpy(holder, source, num); + memcpy(dest, holder, num); + BOP_promise(dest, num); + return dest; } diff --git a/malloc_wrapper.c b/malloc_wrapper.c index 3d04ca7..ef5cb81 100644 --- a/malloc_wrapper.c +++ b/malloc_wrapper.c @@ -1,17 +1,17 @@ #define _GNU_SOURCE +#include #include -#include +#include #include -#include -#include +#include #include +#include #include -#include -#include "external/malloc.h" +#include "bop_api.h" #include "dmmalloc.h" +#include "external/malloc.h" #include "malloc_wrapper.h" -#include "bop_api.h" #ifndef NDEBUG #define VISUALIZE(s) @@ -20,52 +20,67 @@ #endif #define SEQUENTIAL (BOP_task_status() == SEQ || BOP_task_status() == UNDY) -#define SPEC_VISUALIZE(s) if(!SEQUENTIAL) bop_msg(5, s) - +#define SPEC_VISUALIZE(s) \ + if (!SEQUENTIAL) \ + bop_msg(5, s) #define TABLESIZE 100000 #define CHARSIZE 100 -//Macros for the custom allocator +// Macros for the custom allocator #define u_malloc dm_malloc #define u_realloc dm_realloc #define u_free dm_free #define u_calloc dm_calloc #define u_malloc_usable_size dm_malloc_usable_size +// prototypes for the dlsym using calloc workaround +void *tempcalloc(size_t, size_t); +static __attribute__((noinline)) void +calloc_init(); - -//prototypes for the dlsym using calloc workaround -void* tempcalloc(size_t, size_t); -static __attribute__ ((noinline)) void calloc_init(); - - -static void *(*calloc_func)(size_t, size_t) = tempcalloc; //part of dlsym workaround +static void *(*calloc_func)(size_t, + size_t) = tempcalloc; // part of dlsym workaround static void *(*libc_calloc)(size_t, size_t) = NULL; static char calloc_hack[CHARSIZE]; static volatile short initializing = 0; -//Warning: Unsupported functions are currently ignored unless UNSUPPORTED_MALLOC is defined at compile time +// Warning: Unsupported functions are currently ignored unless +// UNSUPPORTED_MALLOC is defined at compile time #ifdef UNSUPPORTED_MALLOC -//unsupported malloc operations are aborted immediately -void* memalign(size_t size, size_t boundary) { +// unsupported malloc operations are aborted immediately +void * +memalign(size_t size, size_t boundary) +{ printf("\nUNSUPPORTED OPERATION memalign\n"); _exit(0); } -int posix_memalign (void **memptr, size_t alignment, size_t size) { + +int +posix_memalign(void **memptr, size_t alignment, size_t size) +{ printf("\nUNSUPPORTED OPERATION posix_memalign\n"); _exit(0); } -void* aligned_malloc(size_t size, size_t boundary) { + +void * +aligned_malloc(size_t size, size_t boundary) +{ printf("\nUNSUPPORTED OPERATION: aligned_malloc\n"); _exit(0); } -void* valloc(size_t size) { + +void * +valloc(size_t size) +{ printf("\nUNSUPPORTED OPERATION: valloc\n"); _exit(0); } -struct mallinfo mallinfo() { + +struct mallinfo +mallinfo() +{ printf("\nUNSUPPORTED OPERATION: mallinfo\n"); _exit(0); } @@ -73,105 +88,152 @@ struct mallinfo mallinfo() { #warning "not overriding unsupported" #endif -void* malloc(size_t s) { - void* p = u_malloc(s); +void * +malloc(size_t s) +{ + void *p = u_malloc(s); + return p; } -void* realloc(void *p , size_t s) { - assert (p != calloc_hack); - void* p2 = u_realloc(p, s); + +void * +realloc(void *p, size_t s) +{ + assert(p != calloc_hack); + void *p2 = u_realloc(p, s); + return p2; } -void free(void * p) { - if(p == NULL || p == calloc_hack) return; + +void +free(void *p) +{ + if (p == NULL || p == calloc_hack) + return; u_free(p); } -size_t malloc_usable_size(void* ptr) { +size_t +malloc_usable_size(void *ptr) +{ assert(ptr != calloc_hack); size_t size = u_malloc_usable_size(ptr); + return size; } - -void * calloc(volatile size_t sz, volatile size_t n) { +void * +calloc(volatile size_t sz, volatile size_t n) +{ calloc_init(); - //make sure the right calloc_func is being used + // make sure the right calloc_func is being used assert(calloc_func != NULL); - assert( (initializing && calloc_func == tempcalloc) || - (!initializing && calloc_func == dm_calloc) ); - void* p = calloc_func(sz, n); - if(calloc_func == u_calloc) { - dm_check(p); + assert((initializing && calloc_func == tempcalloc) || + (!initializing && calloc_func == dm_calloc)); + void *p = calloc_func(sz, n); + + if (calloc_func == u_calloc) { + dm_check(p); } return p; } -static __attribute__ ((noinline)) void calloc_init() { - if(libc_calloc == NULL && !initializing) { - //first allocation - initializing = 1; //don't recurse - calloc_func = tempcalloc; - libc_calloc = dlsym(RTLD_NEXT, "calloc"); +static __attribute__((noinline)) void +calloc_init() +{ + if (libc_calloc == NULL && !initializing) { + // first allocation + initializing = 1; // don't recurse + calloc_func = tempcalloc; + libc_calloc = dlsym(RTLD_NEXT, "calloc"); initializing = 0; assert(libc_calloc != NULL); calloc_func = u_calloc; } } -void* tempcalloc(size_t s, size_t n) { - if(s * n > CHARSIZE) { + +void * +tempcalloc(size_t s, size_t n) +{ + if (s * n > CHARSIZE) { _exit(0); return NULL; } int i; - for(i = 0; i < CHARSIZE; i++) + + for (i = 0; i < CHARSIZE; i++) calloc_hack[i] = '\0'; return calloc_hack; } -inline void * sys_malloc(size_t s) { + +inline void * +sys_malloc(size_t s) +{ static void *(*libc_malloc)(size_t) = NULL; - if(libc_malloc == NULL) + + if (libc_malloc == NULL) libc_malloc = dlsym(RTLD_NEXT, "malloc"); assert(libc_malloc != NULL); return libc_malloc(s); } -inline void * sys_realloc(void * p , size_t size) { - static void *(*libc_realloc)(void*, size_t) = NULL; + +inline void * +sys_realloc(void *p, size_t size) +{ + static void *(*libc_realloc)(void *, size_t) = NULL; + assert(p != calloc_hack); - if(libc_realloc == NULL) + if (libc_realloc == NULL) libc_realloc = dlsym(RTLD_NEXT, "realloc"); assert(libc_realloc != NULL); - void* p2 = libc_realloc(p, size); + void *p2 = libc_realloc(p, size); + return p2; } -inline void sys_free(void * p) { - static void (*libc_free)(void*) = NULL; - if(p == calloc_hack) + +inline void +sys_free(void *p) +{ + static void (*libc_free)(void *) = NULL; + + if (p == calloc_hack) return; - if(libc_free == NULL) + if (libc_free == NULL) libc_free = dlsym(RTLD_NEXT, "free"); assert(libc_free != NULL); libc_free(p); } -inline size_t sys_malloc_usable_size(void* p) { - static size_t (*libc_malloc_usable_size)(void*) = NULL; - if(libc_malloc_usable_size == NULL) + +inline size_t +sys_malloc_usable_size(void *p) +{ + static size_t (*libc_malloc_usable_size)(void *) = NULL; + + if (libc_malloc_usable_size == NULL) libc_malloc_usable_size = dlsym(RTLD_NEXT, "malloc_usable_size"); - assert (libc_malloc_usable_size != NULL); + assert(libc_malloc_usable_size != NULL); return libc_malloc_usable_size(p); } -inline int sys_posix_memalign(void** p, size_t a, size_t s) { - static int (*libc_posix_memalign)(void**, size_t, size_t) = NULL; - if(libc_posix_memalign == NULL) + +inline int +sys_posix_memalign(void **p, size_t a, size_t s) +{ + static int (*libc_posix_memalign)(void **, size_t, size_t) = NULL; + + if (libc_posix_memalign == NULL) libc_posix_memalign = dlsym(RTLD_NEXT, "posix_memalign"); assert(libc_posix_memalign != NULL); return libc_posix_memalign(p, a, s); } -inline void * sys_calloc(size_t s, size_t n) { +inline void * +sys_calloc(size_t s, size_t n) +{ calloc_init(); assert(libc_calloc != NULL); - void* p = libc_calloc(s, n); + void *p = libc_calloc(s, n); + return p; } + #undef CHARSIZE diff --git a/malloc_wrapper.h b/malloc_wrapper.h index b264dab..59ff6d5 100644 --- a/malloc_wrapper.h +++ b/malloc_wrapper.h @@ -1,25 +1,38 @@ #ifndef MALLOC_WRAPPER_H #define MALLOC_WRAPPER_H #include -void * malloc(size_t); -void * realloc(void *, size_t); -void free(void *); -void * calloc(size_t, size_t); +void *malloc(size_t); +void * +realloc(void *, size_t); +void +free(void *); +void *calloc(size_t, size_t); #ifdef UNSUPPORTED_MALLOC -int posix_memalign(void**, size_t alignment, size_t size); -void* aligned_malloc(size_t alignment, size_t size); -size_t malloc_usable_size(void*); -void* memalign(size_t size, size_t boundary); -void* aligned_alloc(size_t size, size_t boundary); -void* valloc(size_t size); -struct mallinfo mallinfo(); +int +posix_memalign(void **, size_t alignment, size_t size); +void * +aligned_malloc(size_t alignment, size_t size); +size_t +malloc_usable_size(void *); +void * +memalign(size_t size, size_t boundary); +void * +aligned_alloc(size_t size, size_t boundary); +void * +valloc(size_t size); +struct mallinfo +mallinfo(); #endif -void * sys_malloc(size_t); -void * sys_realloc(void *, size_t); -void sys_free(void *); -void * sys_calloc(size_t, size_t); -size_t sys_malloc_usable_size(void*); -int sys_posix_memalign(void**, size_t, size_t); +void *sys_malloc(size_t); +void * +sys_realloc(void *, size_t); +void +sys_free(void *); +void *sys_calloc(size_t, size_t); +size_t +sys_malloc_usable_size(void *); +int +sys_posix_memalign(void **, size_t, size_t); #endif diff --git a/postwait.c b/postwait.c index 0abc1f7..2f4fd30 100644 --- a/postwait.c +++ b/postwait.c @@ -1,432 +1,554 @@ -#include /* for PRIdPTR */ -#include /* for NULL */ -#include /* for memcpy */ +#include "atomic.h" // for locking #include "bop_api.h" -#include "external/malloc.h" -#include "atomic.h" // for locking -#include "bop_ports.h" -#include "bop_merge.h" #include "bop_map.h" +#include "bop_merge.h" +#include "bop_ports.h" +#include "external/malloc.h" +#include /* for PRIdPTR */ +#include /* for NULL */ +#include /* for memcpy */ extern mspace metacow_space; -map_t received; /* for checking ordering conflicts */ -map_t received_n_used; /* for checking write-after-post conflicts */ +map_t received; /* for checking ordering conflicts */ +map_t received_n_used; /* for checking write-after-post conflicts */ -mspace pw_space = NULL; /* shared memory space */ +mspace pw_space = NULL; /* shared memory space */ typedef struct _channel_t { - addr_t id; /* valid if not zero */ - map_t data; - unsigned sender; /* non-zero means posted */ - char is_posted; + addr_t id; /* valid if not zero */ + map_t data; + unsigned sender; /* non-zero means posted */ + char is_posted; - /* for channel chaining */ - struct _channel_t *cc_first, *cc_next; + /* for channel chaining */ + struct _channel_t *cc_first, *cc_next; } channel_t; struct switch_board_t { - channel_t *channels; /* first come, first serve */ - unsigned size; /* no re-sizing during ppr */ - bop_lock_t lock; /* global lock, needed for channel chaining */ + channel_t *channels; /* first come, first serve */ + unsigned size; /* no re-sizing during ppr */ + bop_lock_t lock; /* global lock, needed for channel chaining */ } switch_board; addr_t local_ch_id = 0; map_t local_ch_data; -void channel_local_reset( void ) { - local_ch_id = 0; - map_clear( & local_ch_data ); +void +channel_local_reset(void) +{ + local_ch_id = 0; + map_clear(&local_ch_data); } -static void ppr_reset( void ) { - channel_local_reset( ); - map_clear( & received ); - map_clear( & received_n_used ); +static void +ppr_reset(void) +{ + channel_local_reset(); + map_clear(&received); + map_clear(&received_n_used); } -static void clear_channel_shm_data( void ) { - int i; - for ( i = 0; i < switch_board.size; i ++ ) - if ( switch_board.channels[ i ].id != 0 ) - clear_patch( & switch_board.channels[ i ].data ); +static void +clear_channel_shm_data(void) +{ + int i; + + for (i = 0; i < switch_board.size; i++) + if (switch_board.channels[i].id != 0) + clear_patch(&switch_board.channels[i].data); } -static void postwait_init( void ) { - if (pw_space == NULL) { - char use_lock = 1; - char is_shared_mem = 1; /* true */ - size_t init_size = 8000; /* 8KB init size */ - pw_space = create_mspace( init_size, use_lock, is_shared_mem ); - bop_msg( 3, "created postwait (shared memory) mspace at %p", pw_space ); - switch_board.size = 10 * BOP_get_group_size(); - switch_board.channels = - (channel_t *) mspace_calloc( pw_space, - switch_board.size, - sizeof( channel_t )); - assert( metacow_space != NULL ); /* bop_merge_port.ppr_group_init needed */ - init_empty_map( & local_ch_data, metacow_space, "local_ch_data" ); - init_empty_map( & received, metacow_space, "received" ); - init_empty_map( & received_n_used, metacow_space, "received_n_used" ); - } - else { - clear_channel_shm_data( ); - unsigned newsize = 10 * BOP_get_group_size( ); - if ( switch_board.size < newsize ) { - switch_board.size = newsize; - switch_board.channels = - (channel_t *) mspace_realloc( pw_space, - switch_board.channels, - switch_board.size * sizeof( channel_t )); +static void +postwait_init(void) +{ + if (pw_space == NULL) { + char use_lock = 1; + char is_shared_mem = 1; /* true */ + size_t init_size = 8000; /* 8KB init size */ + + pw_space = create_mspace(init_size, use_lock, is_shared_mem); + bop_msg(3, "created postwait (shared memory) mspace at %p", pw_space); + switch_board.size = 10 * BOP_get_group_size(); + switch_board.channels = (channel_t *)mspace_calloc( + pw_space, switch_board.size, sizeof(channel_t)); + assert(metacow_space != + NULL); /* bop_merge_port.ppr_group_init needed */ + init_empty_map(&local_ch_data, metacow_space, "local_ch_data"); + init_empty_map(&received, metacow_space, "received"); + init_empty_map(&received_n_used, metacow_space, "received_n_used"); + } else { + clear_channel_shm_data(); + unsigned newsize = 10 * BOP_get_group_size(); + + if (switch_board.size < newsize) { + switch_board.size = newsize; + switch_board.channels = (channel_t *)mspace_realloc( + pw_space, + switch_board.channels, + switch_board.size * sizeof(channel_t)); + } } - } - memset( switch_board.channels, 0, - switch_board.size * sizeof( channel_t ) ); - bop_lock_clear( & switch_board.lock ); + memset(switch_board.channels, 0, switch_board.size * sizeof(channel_t)); + bop_lock_clear(&switch_board.lock); - bop_msg(4, "postwait_init: (%d) channels (re-)initialized", - switch_board.size ); + bop_msg( + 4, "postwait_init: (%d) channels (re-)initialized", switch_board.size); } -static int has_local_channel( addr_t id ) { - assert( id > 0 ); - if ( local_ch_id != 0 && local_ch_id != id ) { - bop_msg( 1, "channel fill/post for "PRIdPTR" is ignored (currently "PRIdPTR"). use channel_local_reset to clear the previous record or wait for next BOP version to allow working on multiple channels at the same time.", id, local_ch_id ); - return 0; - } - return 1; +static int +has_local_channel(addr_t id) +{ + assert(id > 0); + if (local_ch_id != 0 && local_ch_id != id) { + bop_msg(1, + "channel fill/post for " PRIdPTR + " is ignored (currently " PRIdPTR + "). use channel_local_reset to clear the previous record or " + "wait for next BOP version to allow working on multiple " + "channels at the same time.", + id, + local_ch_id); + return 0; + } + return 1; } -void channel_fill( addr_t id, addr_t base, unsigned size ) { - if ( task_status == SEQ || task_status == UNDY ) return; - if ( ! has_local_channel( id ) ) return; - - if ( local_ch_id == 0 ) local_ch_id = id; - - map_add_range( & local_ch_data, base, size, NULL ); - bop_msg( 4, "channel fill : map_add_range %p, %p, %.0f, %d", &local_ch_data, base, *((double *)base), size); +void +channel_fill(addr_t id, addr_t base, unsigned size) +{ + if (task_status == SEQ || task_status == UNDY) + return; + if (!has_local_channel(id)) + return; + + if (local_ch_id == 0) + local_ch_id = id; + + map_add_range(&local_ch_data, base, size, NULL); + bop_msg(4, + "channel fill : map_add_range %p, %p, %.0f, %d", + &local_ch_data, + base, + *((double *)base), + size); } extern map_t read_map; extern map_t write_map; -extern void map_subtract(map_t *, map_t *); - -void channel_post( addr_t id ) { - if ( task_status == SEQ || task_status == UNDY ) return; - if ( ! has_local_channel( id ) ) return; - - /* write-only data */ - map_intersect( & local_ch_data, & write_map ); - - if ( local_ch_data.size == 0 ) { - bop_msg( 1, "zero-content channel "PRIdPTR" post", id ); - } - - map_inspect( 6, & local_ch_data ); - - unsigned index = id % switch_board.size; - channel_t *ch = & switch_board.channels[ index ]; - bop_lock_acquire( & switch_board.lock ); - if ( ch->id != 0 && ch->id != id ) { - bop_msg( 1, "channel "PRIdPTR" conflict with "PRIdPTR" (task %u), fail to allocate", id, ch->id, ch->sender ); - bop_lock_release( & switch_board.lock ); - return; - } - ch->id = id; - if ( ch->is_posted ) { - bop_msg( 1, "Posting to posted channel "PRIdPTR" (by task %u), ignored", ch->id, ch->sender ); - bop_lock_release( & switch_board.lock ); - return; - } - ch->sender = BOP_ppr_index( ); - - create_patch( & ch->data, & local_ch_data, pw_space ); - - if ( ch->cc_first == NULL ) - ch->is_posted = 1; - else { - ch = ch->cc_first; - while ( ch != NULL ) { - ch->is_posted = 1; - ch = ch->cc_next; +extern void +map_subtract(map_t *, map_t *); + +void +channel_post(addr_t id) +{ + if (task_status == SEQ || task_status == UNDY) + return; + if (!has_local_channel(id)) + return; + + /* write-only data */ + map_intersect(&local_ch_data, &write_map); + + if (local_ch_data.size == 0) { + bop_msg(1, "zero-content channel " PRIdPTR " post", id); } - } - bop_lock_release( & switch_board.lock ); - map_subtract( & write_map, & local_ch_data ); + map_inspect(6, &local_ch_data); + + unsigned index = id % switch_board.size; + channel_t *ch = &switch_board.channels[index]; + + bop_lock_acquire(&switch_board.lock); + if (ch->id != 0 && ch->id != id) { + bop_msg(1, + "channel " PRIdPTR " conflict with " PRIdPTR + " (task %u), fail to allocate", + id, + ch->id, + ch->sender); + bop_lock_release(&switch_board.lock); + return; + } + ch->id = id; + if (ch->is_posted) { + bop_msg(1, + "Posting to posted channel " PRIdPTR " (by task %u), ignored", + ch->id, + ch->sender); + bop_lock_release(&switch_board.lock); + return; + } + ch->sender = BOP_ppr_index(); + + create_patch(&ch->data, &local_ch_data, pw_space); + + if (ch->cc_first == NULL) + ch->is_posted = 1; + else { + ch = ch->cc_first; + while (ch != NULL) { + ch->is_posted = 1; + ch = ch->cc_next; + } + } + bop_lock_release(&switch_board.lock); + + map_subtract(&write_map, &local_ch_data); - channel_local_reset( ); + channel_local_reset(); } /* Allocate a channel record (and initialize the map) if it is the - first request. NULL if no channel record is available */ -static channel_t *get_channel( addr_t id ) { - channel_t *ch = & switch_board.channels[ id % switch_board.size ]; - if ( ch->id != 0 && ch->id != id ) return NULL; /* no resource */ - if ( ch->id == 0 ) { /* init */ - ch->id = id; - init_empty_map( & ch->data, pw_space, "channel data" ); - } - return ch; + * first request. NULL if no channel record is available */ +static channel_t * +get_channel(addr_t id) +{ + channel_t *ch = &switch_board.channels[id % switch_board.size]; + + if (ch->id != 0 && ch->id != id) + return NULL; /* no resource */ + if (ch->id == 0) { /* init */ + ch->id = id; + init_empty_map(&ch->data, pw_space, "channel data"); + } + return ch; } -static void set_chain( channel_t *ch, channel_t *fst, channel_t *nxt, char posted ) { - ch->cc_first = fst; - ch->cc_next = nxt; - ch->is_posted = posted; +static void +set_chain(channel_t *ch, channel_t *fst, channel_t *nxt, char posted) +{ + ch->cc_first = fst; + ch->cc_next = nxt; + ch->is_posted = posted; } /* new_ch may or may not be in a chain */ -static void connect_chain( channel_t *head, channel_t *new_ch, char posted ) { - if ( new_ch->cc_first != NULL ) - new_ch = new_ch->cc_first; - - channel_t *p = head; - while ( p->cc_next != NULL ) - p = p->cc_next; - set_chain( p, head, new_ch, posted ); - while ( new_ch != NULL ) { - set_chain( new_ch, head, new_ch->cc_next, posted ); - new_ch = new_ch->cc_next; - } +static void +connect_chain(channel_t *head, channel_t *new_ch, char posted) +{ + if (new_ch->cc_first != NULL) + new_ch = new_ch->cc_first; + + channel_t *p = head; + + while (p->cc_next != NULL) + p = p->cc_next; + set_chain(p, head, new_ch, posted); + while (new_ch != NULL) { + set_chain(new_ch, head, new_ch->cc_next, posted); + new_ch = new_ch->cc_next; + } } -void channel_chain( addr_t id1, addr_t id2 ) { - if ( task_status == SEQ || task_status == UNDY ) return; - bop_lock_acquire( & switch_board.lock ); - channel_t *ch1 = get_channel( id1 ); - channel_t *ch2 = get_channel( id2 ); - if ( ch1 == NULL || ch2 == NULL ) { - bop_msg( 1, "chaining of "PRIdPTR" and "PRIdPTR" failed for lack of resource", id1, id2 ); - bop_lock_release( & switch_board.lock ); - return; - } - - char posted = ch1->is_posted || ch2->is_posted; - - if ( ch1->cc_first == NULL && ch2->cc_first == NULL ) { - set_chain( ch1, ch1, ch2, posted ); - set_chain( ch2, ch1, NULL, posted ); - } - else { - if ( ch1->cc_first != NULL ) - connect_chain( ch1->cc_first, ch2, posted ); - else - connect_chain( ch2->cc_first, ch1, posted ); - } - bop_lock_release( & switch_board.lock ); +void +channel_chain(addr_t id1, addr_t id2) +{ + if (task_status == SEQ || task_status == UNDY) + return; + bop_lock_acquire(&switch_board.lock); + channel_t *ch1 = get_channel(id1); + channel_t *ch2 = get_channel(id2); + + if (ch1 == NULL || ch2 == NULL) { + bop_msg(1, + "chaining of " PRIdPTR " and " PRIdPTR + " failed for lack of resource", + id1, + id2); + bop_lock_release(&switch_board.lock); + return; + } + + char posted = ch1->is_posted || ch2->is_posted; + + if (ch1->cc_first == NULL && ch2->cc_first == NULL) { + set_chain(ch1, ch1, ch2, posted); + set_chain(ch2, ch1, NULL, posted); + } else { + if (ch1->cc_first != NULL) + connect_chain(ch1->cc_first, ch2, posted); + else + connect_chain(ch2->cc_first, ch1, posted); + } + bop_lock_release(&switch_board.lock); } -range_node_t * new_node( mspace msp, addr_t base, size_t size, void *obj ); -range_node_t * splay (range_node_t * t, addr_t key); -char overlap(mem_range_t *b, mem_range_t *r, addr_t *base, size_t *size); +range_node_t * +new_node(mspace msp, addr_t base, size_t size, void *obj); +range_node_t * +splay(range_node_t *t, addr_t key); +char +overlap(mem_range_t *b, mem_range_t *r, addr_t *base, size_t *size); /* Split the range when needed, which will return a non-nil range node - leftover */ -static range_node_t *range_remove_overlap_return_leftover( mem_range_t *range, mspace lospace, addr_t obase, size_t osize ) { - if ( range->base < obase ) - range->size = obase - range->base; - if ( range->base + range->size > obase + osize ) { - range_node_t * n = new_node( lospace, obase + osize, - range->base + range->size - (obase + osize), - NULL ); - n->r.task = range->task; - return n; - } - else - return NULL; + * leftover */ +static range_node_t * +range_remove_overlap_return_leftover(mem_range_t *range, + mspace lospace, + addr_t obase, + size_t osize) +{ + if (range->base < obase) + range->size = obase - range->base; + if (range->base + range->size > obase + osize) { + range_node_t *n = new_node(lospace, + obase + osize, + range->base + range->size - (obase + osize), + NULL); + + n->r.task = range->task; + return n; + } else + return NULL; } -static char *data_clone( mspace space, char *src, size_t size ) { - char *newdata = (char *) mspace_malloc( space, size ); - memcpy( newdata, src, size ); - return newdata; +static char * +data_clone(mspace space, char *src, size_t size) +{ + char *newdata = (char *)mspace_malloc(space, size); + + memcpy(newdata, src, size); + return newdata; } -mem_range_t *map_add_range_from_task(map_t *map, addr_t base, size_t size, void *obj, unsigned ppr_id) { - assert( map != NULL ); - assert( size > 0 ); - - bop_msg( 6, "map %s (%p) adding from task %u the range %p, size %zd, obj %p", map->name, map, ppr_id, base, size, obj ); - - char *data = obj == NULL? NULL : - data_clone( map->residence, (char *) obj, size ); - range_node_t * n = new_node( map->residence, base, size, (void *) data ); - n->r.task = ppr_id; - - if(map->root == NULL) { - map->root = n; - map->size = 1; - return & map->root->r; - } - - range_node_t *top = splay( map->root, base); - - /* If there is overlap, split the root node to remove the overlap. A - future extension is to keep the part from a later ppr_id. It - would require the full implementation of reordered receives. */ - addr_t cbase; size_t csize; - mem_range_t *target = &top->r; - char has_overlap = overlap( &n->r, target, &cbase, &csize); - if ( ! has_overlap && top->lc != NULL ) { - target = &top->lc->r; /* could be overlapping with left child */ - has_overlap = overlap( &n->r, target, &cbase, &csize); - } - - if ( ! has_overlap ) { /* no overlap */ - map->root = n; - if ( n->r.base < top->r.base ) { /* insert left */ - n->rc = top; - n->lc = top->lc; - // if (!(n->lc->r.base + n->lc->r.size <= n->r.base )) - // bop_msg( 3, "n->lc->r.base %p, n->lc->r.size %zd, n->r.base %p, n->rc->r.base %p", n->lc->r.base, n->lc->r.size, n->r.base, n->rc->r.base); - assert( n->lc == NULL || n->lc->r.base + n->lc->r.size <= n->r.base ); - top->lc = NULL; +mem_range_t * +map_add_range_from_task( + map_t *map, addr_t base, size_t size, void *obj, unsigned ppr_id) +{ + assert(map != NULL); + assert(size > 0); + + bop_msg(6, + "map %s (%p) adding from task %u the range %p, size %zd, obj %p", + map->name, + map, + ppr_id, + base, + size, + obj); + + char *data = + obj == NULL ? NULL : data_clone(map->residence, (char *)obj, size); + range_node_t *n = new_node(map->residence, base, size, (void *)data); + + n->r.task = ppr_id; + + if (map->root == NULL) { + map->root = n; + map->size = 1; + return &map->root->r; } - else { /* insert right */ - n->lc = top; - n->rc = top->rc; - assert( n->rc == NULL || n->r.base + n->r.size <= n->rc->r.base ); - top->rc = NULL; + + range_node_t *top = splay(map->root, base); + + /* If there is overlap, split the root node to remove the overlap. A + * future extension is to keep the part from a later ppr_id. It + * would require the full implementation of reordered receives. */ + addr_t cbase; + size_t csize; + mem_range_t *target = &top->r; + char has_overlap = overlap(&n->r, target, &cbase, &csize); + + if (!has_overlap && top->lc != NULL) { + target = &top->lc->r; /* could be overlapping with left child */ + has_overlap = overlap(&n->r, target, &cbase, &csize); } - map->size ++; - return & n->r; - } - - bop_msg( 3, "Overlap, write_union [%p, %p), new range [%p, %p)", target->base, target->base + target->size, base, base + size ); - - /* An exact overlap. Replace the node. */ - if ( n->r.base == top->r.base && n->r.size == top->r.size ) { - void *newdata = n->r.rec; - unsigned newtask = n->r.task; - mspace_free( map->residence, n ); - if ( top->r.task > newtask ) - mspace_free( map->residence, newdata ); /* silent drop */ - else { - mspace_free( map->residence, top->r.rec ); - top->r.rec = newdata; - top->r.task = newtask; + + if (!has_overlap) { /* no overlap */ + map->root = n; + if (n->r.base < top->r.base) { /* insert left */ + n->rc = top; + n->lc = top->lc; + // if (!(n->lc->r.base + n->lc->r.size <= n->r.base )) + // bop_msg( 3, "n->lc->r.base %p, n->lc->r.size %zd, n->r.base + // %p, n->rc->r.base %p", n->lc->r.base, n->lc->r.size, + // n->r.base, n->rc->r.base); + assert(n->lc == NULL || + n->lc->r.base + n->lc->r.size <= n->r.base); + top->lc = NULL; + } else { /* insert right */ + n->lc = top; + n->rc = top->rc; + assert(n->rc == NULL || n->r.base + n->r.size <= n->rc->r.base); + top->rc = NULL; + } + map->size++; + return &n->r; } - map->root = top; - return & top->r; - } - - BOP_abort_spec( "non-perfect range overlap in post-wait is not implemented" ); - return NULL; - - /* overlapping cases not implemented - range_node_t *leftover = - range_remove_overlap_return_leftover( &top->r, map->residence, - cbase, csize ); - */ - /* Call this function recursively to add the leftover. Take care to - split the patch data accordingly. */ + + bop_msg(3, + "Overlap, write_union [%p, %p), new range [%p, %p)", + target->base, + target->base + target->size, + base, + base + size); + + /* An exact overlap. Replace the node. */ + if (n->r.base == top->r.base && n->r.size == top->r.size) { + void *newdata = n->r.rec; + unsigned newtask = n->r.task; + + mspace_free(map->residence, n); + if (top->r.task > newtask) + mspace_free(map->residence, newdata); /* silent drop */ + else { + mspace_free(map->residence, top->r.rec); + top->r.rec = newdata; + top->r.task = newtask; + } + map->root = top; + return &top->r; + } + + BOP_abort_spec( + "non-perfect range overlap in post-wait is not implemented"); + return NULL; + + /* overlapping cases not implemented + * range_node_t *leftover = + * range_remove_overlap_return_leftover( &top->r, map->residence, + * cbase, csize ); + */ + /* Call this function recursively to add the leftover. Take care to + * split the patch data accordingly. */ } /* Return 1 if assertion passes. */ -static char assert_no_overlap( map_t *map1, map_t *map2 ) { - map_t *copy = map_clone( map1, metacow_space ); - map_intersect( copy, map2); - char has_overlap = ( copy->size != 0 ); - if ( has_overlap ) { - bop_msg( 1, "maps %s and %s overlap at %p for %zd bytes", map1->name, map2->name, copy->root->r.base, copy->root->r.size ); - map_inspect( 5, map1 ); - map_inspect( 5, map2 ); - map_inspect( 6, copy ); - map_free( copy ); - return 0; - } - else { - map_free( copy ); - return 1; - } +static char +assert_no_overlap(map_t *map1, map_t *map2) +{ + map_t *copy = map_clone(map1, metacow_space); + + map_intersect(copy, map2); + char has_overlap = (copy->size != 0); + + if (has_overlap) { + bop_msg(1, + "maps %s and %s overlap at %p for %zd bytes", + map1->name, + map2->name, + copy->root->r.base, + copy->root->r.size); + map_inspect(5, map1); + map_inspect(5, map2); + map_inspect(6, copy); + map_free(copy); + return 0; + } else { + map_free(copy); + return 1; + } } -static void receive_range( void *sum, mem_range_t *range ) { - channel_t *ch = (channel_t *) sum; - mem_range_t *approved = - map_add_range_from_task( & received, range->base, range->size, - range->rec, ch->sender ); - memcpy( (void *) approved->base, approved->rec, approved->size ); +static void +receive_range(void *sum, mem_range_t *range) +{ + channel_t *ch = (channel_t *)sum; + mem_range_t *approved = map_add_range_from_task( + &received, range->base, range->size, range->rec, ch->sender); + memcpy((void *)approved->base, approved->rec, approved->size); } -static inline void wait_until_posted( channel_t *ch ) { - if ( ch->is_posted ) return; - int b = 1; - while ( ! ch->is_posted ) - backoff( &b ); +static inline void +wait_until_posted(channel_t *ch) +{ + if (ch->is_posted) + return; + int b = 1; + + while (!ch->is_posted) + backoff(&b); } -void channel_wait( addr_t id ) { - if ( task_status == SEQ || task_status == UNDY || task_status == MAIN ) - return; - bop_msg( 3, "waiting for channel %d", id ); - unsigned index = id % switch_board.size; - channel_t *ch = & switch_board.channels[ index ]; - wait_until_posted( ch ); - if ( ch->id != id ) - BOP_abort_spec( "no forthcoming post" ); - bop_msg( 4, "received channel %d", id ); - - if ( ch->cc_first != NULL ) { /* there is chaining */ - ch = ch->cc_first; - while ( ch->data.size == 0 && ch->cc_next != NULL ) - ch = ch->cc_next; - assert( ch->data.size != 0 ); /* can't find a non-empty post */ - } - - /* a more conservative check - if ( ! assert_no_overlap( & received, & ch->data ) ) { - bop_msg( 1, "channel wait abandoned since data is received again" ); - return; - } */ - - if ( ! assert_no_overlap( & ch->data, & read_map ) || - ! assert_no_overlap( & ch->data, & write_map ) ) { - bop_msg( 1, "channel wait abandoned due to a access-before-wait conflict" ); - return; - } - - map_inject( & ch->data, (void *) ch, receive_range ); +void +channel_wait(addr_t id) +{ + if (task_status == SEQ || task_status == UNDY || task_status == MAIN) + return; + bop_msg(3, "waiting for channel %d", id); + unsigned index = id % switch_board.size; + channel_t *ch = &switch_board.channels[index]; + + wait_until_posted(ch); + if (ch->id != id) + BOP_abort_spec("no forthcoming post"); + bop_msg(4, "received channel %d", id); + + if (ch->cc_first != NULL) { /* there is chaining */ + ch = ch->cc_first; + while (ch->data.size == 0 && ch->cc_next != NULL) + ch = ch->cc_next; + assert(ch->data.size != 0); /* can't find a non-empty post */ + } + + /* a more conservative check + * if ( ! assert_no_overlap( & received, & ch->data ) ) { + * bop_msg( 1, "channel wait abandoned since data is received again" ); + * return; + * } */ + + if (!assert_no_overlap(&ch->data, &read_map) || + !assert_no_overlap(&ch->data, &write_map)) { + bop_msg(1, + "channel wait abandoned due to a access-before-wait conflict"); + return; + } + + map_inject(&ch->data, (void *)ch, receive_range); } extern map_t *patches; -static void mdfy_aftr_pst_chk( mem_range_t *mem ) { - unsigned sender_spec_order = spec_order - (BOP_ppr_index( ) - mem->task); - map_t *patch = & patches[ sender_spec_order ]; - mem_range_t *match = map_contains( patch, mem->base ); - assert( match != NULL ); - void *committed = match->rec; - void *received = mem->rec; - char diff = memcmp( committed + mem->base - match->base, - received, mem->size ); - if ( diff ) { - bop_msg( 1, "modify-after-post by task %u for %p, %zd bytes", mem->task, mem->base, mem->size ); - BOP_abort_spec( "correctness checking failed" ); - } +static void +mdfy_aftr_pst_chk(mem_range_t *mem) +{ + unsigned sender_spec_order = spec_order - (BOP_ppr_index() - mem->task); + map_t *patch = &patches[sender_spec_order]; + mem_range_t *match = map_contains(patch, mem->base); + + assert(match != NULL); + void *committed = match->rec; + void *received = mem->rec; + char diff = + memcmp(committed + mem->base - match->base, received, mem->size); + + if (diff) { + bop_msg(1, + "modify-after-post by task %u for %p, %zd bytes", + mem->task, + mem->base, + mem->size); + BOP_abort_spec("correctness checking failed"); + } } -static void ppr_commit( void ) { - if ( received_n_used.size == 0 ) return; +static void +ppr_commit(void) +{ + if (received_n_used.size == 0) + return; - /* check for modify-after-post conflicts */ - map_foreach( & received_n_used, mdfy_aftr_pst_chk ); + /* check for modify-after-post conflicts */ + map_foreach(&received_n_used, mdfy_aftr_pst_chk); - bop_msg( 4, "finish checking modify-after-post conflicts" ); + bop_msg(4, "finish checking modify-after-post conflicts"); } -char channel_is_posted( addr_t id ) { - unsigned index = id % switch_board.size; - channel_t *ch = & switch_board.channels[ index ]; - if ( ch->id != id ) return 0; - return ch->is_posted; +char +channel_is_posted(addr_t id) +{ + unsigned index = id % switch_board.size; + channel_t *ch = &switch_board.channels[index]; + + if (ch->id != id) + return 0; + return ch->is_posted; } bop_port_t postwait_port = { - .ppr_group_init = postwait_init, - .ppr_task_init = ppr_reset, - .data_commit = ppr_commit, + .ppr_group_init = postwait_init, + .ppr_task_init = ppr_reset, + .data_commit = ppr_commit, }; - diff --git a/postwait.h b/postwait.h index 6b77f6d..d0730bf 100644 --- a/postwait.h +++ b/postwait.h @@ -3,9 +3,13 @@ #include "bop_api.h" -void channel_chain( addr_t id1, addr_t id2 ); -void channel_fill( addr_t id, addr_t base, unsigned size ); -void channel_post( addr_t id ); -void channel_wait( addr_t id ); +void +channel_chain(addr_t id1, addr_t id2); +void +channel_fill(addr_t id, addr_t base, unsigned size); +void +channel_post(addr_t id); +void +channel_wait(addr_t id); #endif /* __POSTWAIT_H */ diff --git a/range_tree/dtree.c b/range_tree/dtree.c index 59667b4..f131a9a 100644 --- a/range_tree/dtree.c +++ b/range_tree/dtree.c @@ -3,535 +3,699 @@ #include -#include /* for bop_msg */ +#include /* for bop_msg */ #include -#define min(a, b) ((a)<(b)? (a): (b)) -#define max(a, b) ((a)<(b)? (b): (a)) +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) < (b) ? (b) : (a)) -static void subtree_foreach( range_node_t *node, void (*func)( mem_range_t * ) ) { - if ( node == NULL ) return; - subtree_foreach( node->lc, func ); - (*func)( &node->r ); - subtree_foreach( node->rc, func ); +static void +subtree_foreach(range_node_t *node, void (*func)(mem_range_t *)) +{ + if (node == NULL) + return; + subtree_foreach(node->lc, func); + (*func)(&node->r); + subtree_foreach(node->rc, func); } // func must not change base/size in the range. -void map_foreach( map_t *map, void (*func)( mem_range_t * ) ) { - if ( map == NULL ) return; - subtree_foreach( map->root, func ); -} - -static void subtree_inject( range_node_t *node, void *sum, - void (*func)( void *, mem_range_t * ) ) { - if ( node == NULL ) return; - subtree_inject( node->lc, sum, func ); - (*func)( sum, &node->r ); - subtree_inject( node->rc, sum, func ); +void +map_foreach(map_t *map, void (*func)(mem_range_t *)) +{ + if (map == NULL) + return; + subtree_foreach(map->root, func); +} + +static void +subtree_inject(range_node_t *node, + void *sum, + void (*func)(void *, mem_range_t *)) +{ + if (node == NULL) + return; + subtree_inject(node->lc, sum, func); + (*func)(sum, &node->r); + subtree_inject(node->rc, sum, func); } // func must not change base/size in the range. -void map_inject( map_t *map, void *sum, - void (*func)( void *, mem_range_t * ) ) { - if ( map == NULL ) return; - subtree_inject( map->root, sum, func ); +void +map_inject(map_t *map, void *sum, void (*func)(void *, mem_range_t *)) +{ + if (map == NULL) + return; + subtree_inject(map->root, sum, func); } struct ta_t { - mem_range_t *ranges; - unsigned size; + mem_range_t *ranges; + unsigned size; }; -static void to_array_block( void *_rgs, mem_range_t *range ) { - struct ta_t * rgs = (struct ta_t *) _rgs; - rgs->ranges[ rgs->size++ ] = *range; +static void +to_array_block(void *_rgs, mem_range_t *range) +{ + struct ta_t *rgs = (struct ta_t *)_rgs; + + rgs->ranges[rgs->size++] = *range; } -void map_to_array(map_t *map, mem_range_t **ranges, unsigned *size) { - assert( map != NULL ); +void +map_to_array(map_t *map, mem_range_t **ranges, unsigned *size) +{ + assert(map != NULL); - *size = map->size; - if ( *size == 0 ) { /* calloc 0 byte is problematic */ - *ranges = NULL; - return; - } + *size = map->size; + if (*size == 0) { /* calloc 0 byte is problematic */ + *ranges = NULL; + return; + } + + *ranges = mspace_calloc(map->residence, map->size, sizeof(mem_range_t)); + struct ta_t tmp = {.ranges = *ranges, .size = 0}; - *ranges = mspace_calloc(map->residence, map->size, sizeof(mem_range_t)); - struct ta_t tmp = { - .ranges = *ranges, - .size = 0 - }; - - map_inject( map, &tmp, to_array_block ); + map_inject(map, &tmp, to_array_block); } /* The code for this function is adapted from - http://www.link.cs.cmu.edu/link/ftp-site/splaying/top-down-splay.c */ -range_node_t * splay (range_node_t * t, addr_t key) { + * http://www.link.cs.cmu.edu/link/ftp-site/splaying/top-down-splay.c */ +range_node_t * +splay(range_node_t *t, addr_t key) +{ range_node_t N, *l, *r, *y; - if (t == NULL) return t; + + if (t == NULL) + return t; N.lc = N.rc = NULL; l = r = &N; for (;;) { - if (key < t->r.base) { - if (t->lc != NULL && key < t->lc->r.base) { - y = t->lc; t->lc = y->rc; y->rc = t; t = y; - } - if (t->lc == NULL) break; - r->lc = t; r = t; t = t->lc; - } else if (key > t->r.base) { - if (t->rc != NULL && key > t->rc->r.base) { - y = t->rc; t->rc = y->lc; y->lc = t; t = y; - } - if (t->rc == NULL) break; - l->rc = t; l = t; t = t->rc; - } else break; + if (key < t->r.base) { + if (t->lc != NULL && key < t->lc->r.base) { + y = t->lc; + t->lc = y->rc; + y->rc = t; + t = y; + } + if (t->lc == NULL) + break; + r->lc = t; + r = t; + t = t->lc; + } else if (key > t->r.base) { + if (t->rc != NULL && key > t->rc->r.base) { + y = t->rc; + t->rc = y->lc; + y->lc = t; + t = y; + } + if (t->rc == NULL) + break; + l->rc = t; + l = t; + t = t->rc; + } else + break; } - l->rc=t->lc; r->lc=t->rc; t->lc=N.rc; t->rc=N.lc; + l->rc = t->lc; + r->lc = t->rc; + t->lc = N.rc; + t->rc = N.lc; return t; } -char overlap(mem_range_t *b, mem_range_t *r, addr_t *base, size_t *size) { - if(b->base <= r->base) { - if(b->base+b->size > r->base) { - if(b->base+b->size <= r->base+r->size) { - *base = r->base; - *size = b->base+b->size-r->base; - } else { - *base = r->base; - *size = r->size; - } - return 1; /* true */ +char +overlap(mem_range_t *b, mem_range_t *r, addr_t *base, size_t *size) +{ + if (b->base <= r->base) { + if (b->base + b->size > r->base) { + if (b->base + b->size <= r->base + r->size) { + *base = r->base; + *size = b->base + b->size - r->base; + } else { + *base = r->base; + *size = r->size; + } + return 1; /* true */ + } else { + return 0; /* false */ + } } else { - return 0; /* false */ + if (r->base + r->size > b->base) { + if (r->base + r->size <= b->base + b->size) { + *base = b->base; + *size = r->base + r->size - b->base; + } else { + *base = b->base; + *size = b->size; + } + return 1; /* true */ + } else { + return 0; /* false */ + } } - } else { - if(r->base+r->size > b->base) { - if(r->base+r->size <= b->base+b->size) { - *base = b->base; - *size = r->base+r->size-b->base; - } else { - *base = b->base; - *size = b->size; - } - return 1; /* true */ +} + +range_node_t * +new_node(mspace msp, addr_t base, size_t size, void *obj) +{ + range_node_t *n = mspace_calloc(msp, 1, sizeof(range_node_t)); + + n->r.base = base; + n->r.size = size; + n->r.rec = obj; + n->lc = n->rc = NULL; + return n; +} + +static void +union_ranges(mem_range_t *r1, mem_range_t *r2, addr_t *ubase, size_t *usize) +{ + *ubase = min(r1->base, r2->base); + *usize = max(r1->base + r1->size, r2->base + r2->size) - *ubase; + return; +} + +static void +free_subtree(range_node_t *t, map_t *map) +{ + if (t == NULL) + return; + free_subtree(t->lc, map); + free_subtree(t->rc, map); + t->lc = NULL; + t->rc = NULL; + mspace_free(map->residence, t); + map->size--; +} + +static range_node_t * +absorb_left(range_node_t *node, mem_range_t *range, map_t *map) +{ + if (node == NULL) + return NULL; + + if (range->base > node->r.base + node->r.size) { + node->rc = absorb_left(node->rc, range, map); + return node; } else { - return 0; /* false */ + addr_t oldbase = range->base; + + range->base = min(node->r.base, range->base); + range->size = oldbase + range->size - range->base; + range_node_t *ret = node->lc; + + node->lc = NULL; + free_subtree(node, map); + + return absorb_left(ret, range, map); } - } } -range_node_t * new_node( mspace msp, addr_t base, size_t size, void *obj ) { - range_node_t *n = mspace_calloc(msp, 1, sizeof(range_node_t)); - n->r.base = base; - n->r.size = size; - n->r.rec = obj; - n->lc = n->rc = NULL; - return n; -} - -static void union_ranges( mem_range_t *r1, mem_range_t *r2, addr_t *ubase, size_t *usize) { - *ubase = min( r1->base, r2->base ); - *usize = max( r1->base + r1->size, - r2->base + r2->size ) - *ubase; - return; -} - -static void free_subtree( range_node_t *t, map_t *map ) { - if (t == NULL) return; - free_subtree( t->lc, map ); - free_subtree( t->rc, map ); - t->lc = NULL; - t->rc = NULL; - mspace_free( map->residence, t ); - map->size --; -} - -static range_node_t *absorb_left( range_node_t *node, - mem_range_t * range, map_t *map ) { - if ( node == NULL ) return NULL; - - if ( range->base > node->r.base+node->r.size ) { - node->rc = absorb_left( node->rc, range, map ); - return node; - } - else { - addr_t oldbase = range->base; - range->base = min( node->r.base, range->base ); - range->size = oldbase + range->size - range->base; - range_node_t *ret = node->lc; - - node->lc = NULL; - free_subtree( node, map ); - - return absorb_left( ret, range, map ); - } -} - -static range_node_t *absorb_right( range_node_t *node, - mem_range_t *range, map_t *map ) { - if ( node == NULL ) return NULL; - - if ( range->base + range->size < node->r.base ) { - node->lc = absorb_right( node->lc, range, map ); - return node; - } - else { - addr_t rb = max( range->base + range->size, - node->r.base + node->r.size ); - range->size = rb - range->base; - range_node_t *ret = node->rc; - - node->rc = NULL; - free_subtree( node, map ); - - return absorb_right( ret, range, map ); - } -} - -mem_range_t *map_add_key_val( map_t *map, addr_t key, void *obj ) { - assert( map->is_hash ); - mem_range_t *r = map_add_range( map, key, 1, obj ); - return r; -} - -void *map_search_key( map_t *map, addr_t addr ) { - assert( map->is_hash ); - mem_range_t *k = map_contains( map, addr ); - if ( k != NULL) - return k->rec; - else - return NULL; -} - -mem_range_t *map_add_range(map_t *map, addr_t base, size_t size, void *obj) { - assert( map != NULL ); - assert( size > 0 ); - - bop_msg( 5, "map %s (%p) adding range %p, size %zu, obj %p", map->name, map, base, size, obj ); - - range_node_t * n = new_node( map->residence, base, size, obj ); - - if(map->root == NULL) { - map->root = n; - map->size = 1; - return & map->root->r; - } - - range_node_t *top = splay( map->root, base); - - /* if there is overlap, expand the root node */ - addr_t cbase; size_t csize; - char has_overlap = overlap( &n->r, &top->r, &cbase, &csize); - char bordering = 0; /* false */ - if ( n->r.base < top->r.base ) - bordering = (n->r.base + n->r.size == top->r.base); - else - bordering = (top->r.base + top->r.size == n->r.base ); - - if (has_overlap || bordering) { - addr_t ubase; size_t usize; - union_ranges( &n->r, &top->r, &ubase, &usize ); - top->r.base = ubase; - top->r.size = usize; - top->lc = absorb_left( top->lc, &top->r, map ); - top->rc = absorb_right( top->rc, &top->r, map ); +static range_node_t * +absorb_right(range_node_t *node, mem_range_t *range, map_t *map) +{ + if (node == NULL) + return NULL; + + if (range->base + range->size < node->r.base) { + node->lc = absorb_right(node->lc, range, map); + return node; + } else { + addr_t rb = + max(range->base + range->size, node->r.base + node->r.size); + + range->size = rb - range->base; + range_node_t *ret = node->rc; + + node->rc = NULL; + free_subtree(node, map); + + return absorb_right(ret, range, map); + } +} + +mem_range_t * +map_add_key_val(map_t *map, addr_t key, void *obj) +{ + assert(map->is_hash); + mem_range_t *r = map_add_range(map, key, 1, obj); + + return r; +} + +void * +map_search_key(map_t *map, addr_t addr) +{ + assert(map->is_hash); + mem_range_t *k = map_contains(map, addr); + + if (k != NULL) + return k->rec; + else + return NULL; +} + +mem_range_t * +map_add_range(map_t *map, addr_t base, size_t size, void *obj) +{ + assert(map != NULL); + assert(size > 0); + + bop_msg(5, + "map %s (%p) adding range %p, size %zu, obj %p", + map->name, + map, + base, + size, + obj); + + range_node_t *n = new_node(map->residence, base, size, obj); + + if (map->root == NULL) { + map->root = n; + map->size = 1; + return &map->root->r; + } + + range_node_t *top = splay(map->root, base); + + /* if there is overlap, expand the root node */ + addr_t cbase; + size_t csize; + char has_overlap = overlap(&n->r, &top->r, &cbase, &csize); + char bordering = 0; /* false */ + + if (n->r.base < top->r.base) + bordering = (n->r.base + n->r.size == top->r.base); + else + bordering = (top->r.base + top->r.size == n->r.base); + + if (has_overlap || bordering) { + addr_t ubase; + size_t usize; + + union_ranges(&n->r, &top->r, &ubase, &usize); + top->r.base = ubase; + top->r.size = usize; + top->lc = absorb_left(top->lc, &top->r, map); + top->rc = absorb_right(top->rc, &top->r, map); + + map->root = top; + mspace_free(map->residence, n); + + bop_msg(6, + "map %s (%p) added range %p, size %zu, obj %p", + map, + map->name, + map->root->r.base, + map->root->r.size, + map->root->r.rec); + + return &map->root->r; + } + + if (base < top->r.base) { + n->lc = top->lc; + n->rc = top; + top->lc = NULL; + map->size++; + top = n; + top->lc = absorb_left(top->lc, &top->r, map); + } else if (base > top->r.base) { + n->rc = top->rc; + n->lc = top; + top->rc = NULL; + map->size++; + top = n; + top->rc = absorb_right(top->rc, &top->r, map); + } map->root = top; - mspace_free( map->residence, n ); - bop_msg( 6, "map %s (%p) added range %p, size %zu, obj %p", map, map->name, map->root->r.base, map->root->r.size, map->root->r.rec ); + bop_msg(6, + "map %s (%p) added range %p, size %u, obj %p", + map, + map->name, + map->root->r.base, + map->root->r.size, + map->root->r.rec); - return & map->root->r; - } + return &map->root->r; +} - if ( base < top->r.base ) { - n->lc = top->lc; - n->rc = top; - top->lc = NULL; - map->size ++; - top = n; - top->lc = absorb_left( top->lc, &top->r, map ); - } - else if ( base > top->r.base ) { - n->rc = top->rc; - n->lc = top; - top->rc = NULL; - map->size ++; - top = n; - top->rc = absorb_right( top->rc, &top->r, map ); - } - - map->root = top; +static addr_t +subtree_size(range_node_t *n) +{ + if (n == NULL) + return 0; + return n->r.size + subtree_size(n->lc) + subtree_size(n->rc); +} - bop_msg( 6, "map %s (%p) added range %p, size %u, obj %p", map, map->name, map->root->r.base, map->root->r.size, map->root->r.rec ); +addr_t +map_size_in_bytes(map_t *map) +{ + assert(map != NULL); - return & map->root->r; + return subtree_size(map->root); } -static addr_t subtree_size( range_node_t *n ) { - if (n == NULL) return 0; - return n->r.size + subtree_size( n->lc ) + subtree_size( n->rc ); +static char +subtree_overlaps(range_node_t *n, mem_range_t *inp, addr_t *base, size_t *size) +{ + if (n == NULL) + return 0; /* false */ + + if (n->r.base + n->r.size <= inp->base) + return subtree_overlaps(n->rc, inp, base, size); + + if (n->r.base > inp->base + inp->size) + return subtree_overlaps(n->lc, inp, base, size); + + if (n->r.base > inp->base) { + mem_range_t head; + + head.base = inp->base; + head.size = n->r.base - inp->base; + char overlap = subtree_overlaps(n->lc, &head, base, size); + + if (overlap) + return overlap; + } + + return overlap(&n->r, inp, base, size); } -addr_t map_size_in_bytes( map_t *map ) { - assert( map != NULL ); +/* return the smallest overlap. This is useful for enumerating all overlaps by + * repeatedly calling this function. */ - return subtree_size( map->root ); +char +map_overlaps(map_t *map, mem_range_t *inp, mem_range_t *c_range) +{ + assert(map != NULL); + + addr_t base; + size_t size; + char is_overlap = subtree_overlaps(map->root, inp, &base, &size); + + if (is_overlap && c_range != NULL) { + c_range->base = base; + c_range->size = size; + } + return is_overlap; } -static char subtree_overlaps( range_node_t *n, mem_range_t *inp, addr_t *base, size_t *size ) { - if (n == NULL) return 0; /* false */ +void +map_intersect(map_t *base_map, map_t *ref_map) +{ + if (!base_map || base_map->root == NULL) + return; - if ( n->r.base + n->r.size <= inp->base ) - return subtree_overlaps( n->rc, inp, base, size ); - - if ( n->r.base > inp->base + inp->size ) - return subtree_overlaps( n->lc, inp, base, size ); - - if ( n->r.base > inp->base ) { - mem_range_t head; - head.base = inp->base; - head.size = n->r.base - inp->base; - char overlap = subtree_overlaps( n->lc, &head, base, size ); - if ( overlap ) return overlap; - } - - return overlap( & n->r, inp, base, size ); -} - -/* return the smallest overlap. This is useful for enumerating all overlaps by repeatedly calling this function. */ - -char map_overlaps( map_t *map, mem_range_t *inp, mem_range_t *c_range) { - assert( map != NULL ); - - addr_t base; size_t size; - char is_overlap = subtree_overlaps( map->root, inp, &base, &size ); - if (is_overlap && c_range != NULL) { - c_range->base = base; - c_range->size = size; - } - return is_overlap; -} - -void map_intersect(map_t *base_map, map_t *ref_map) { - - if( !base_map || base_map->root == NULL ) return; - - mem_range_t *ranges; unsigned num, i; - map_to_array( base_map, &ranges, &num ); - - map_clear( base_map ); - if ( !ref_map || ref_map->root == NULL ) return; - - for ( i = 0; i < num; ++ i ) { - mem_range_t range = ranges[ i ]; - mem_range_t orange; - char overlap; - do { - overlap = map_overlaps( ref_map, &range, &orange ); - if (overlap) { - map_add_range( base_map, orange.base, orange.size, range.rec ); - addr_t old_bound = range.base + range.size; - range.base = orange.base + orange.size; - range.size = old_bound - range.base; - } - } while (overlap && range.size != 0); - } - - mspace_free( base_map->residence, ranges ); - return; -} - -void map_union(map_t *base_map, map_t *ref_map) { - if(!ref_map || ref_map->root == NULL ) return; - assert( base_map != NULL ); - - mem_range_t *ranges; unsigned num, i; - map_to_array( ref_map, &ranges, &num ); - - for ( i = 0; i < num; ++ i ) { - mem_range_t range = ranges[ i ]; - - map_add_range( base_map, range.base, range.size, range.rec ); - - if ( range.rec != NULL ) - bop_msg( 2, "map_union warning: individual node information not nil, which may be lost after union"); - } - - mspace_free( ref_map->residence, ranges ); - return; -} - -map_t *map_clone( map_t *source, mspace space ) { - if ( space == NULL ) space = source->residence; - map_t *clone = new_range_set( space, "clone" ); - map_union( clone, source ); - return clone; -} - -void map_subtract(map_t *base_map, map_t *ref_map) { - if(!ref_map || ref_map->root == NULL) return; - if(!base_map || base_map->root == NULL) return; - - /* make copy_map be the intersection */ - map_t *copy_map = new_range_set(base_map->residence, "map_subtract_temp"); - map_union(copy_map, base_map); - map_intersect(copy_map, ref_map); - - /* do the subtraction => base_map-copy_map */ - mem_range_t *ranges; unsigned num, i; - map_to_array(base_map, &ranges, &num); - - map_clear(base_map); - - for (i=0;i range.base) - map_add_range(base_map, range.base, orange.base-range.base, - range.rec); - addr_t old_bound = range.base + range.size; - range.base = orange.base + orange.size; - range.size = old_bound - range.base; - } - } while (overlap && range.size != 0); - if (range.size != 0) - map_add_range(base_map, range.base, range.size, range.rec); - } - - /* free the space */ - mspace_free(base_map->residence, ranges); - map_free(copy_map); - - return; -} - -mem_range_t *map_contains(map_t *map, addr_t addr) { - assert( map != NULL ); - if ( map->root == NULL ) return NULL; - - map->root = splay(map->root, addr); - range_node_t *top = map->root; - if ( addr < top->r.base ) { - if ( top->lc == NULL) return NULL; - range_node_t *node = top->lc; - while ( node->rc != NULL ) - node = node->rc; - assert( node->r.base <= addr ); - if ( node->r.base + node->r.size > addr ) - return & node->r; - else - return NULL; - } - else { - if( top->r.base + top->r.size > addr) - return &map->root->r; - else - return NULL; - } + mem_range_t *ranges; + unsigned num, i; + + map_to_array(base_map, &ranges, &num); + + map_clear(base_map); + if (!ref_map || ref_map->root == NULL) + return; + + for (i = 0; i < num; ++i) { + mem_range_t range = ranges[i]; + mem_range_t orange; + char overlap; + + do { + overlap = map_overlaps(ref_map, &range, &orange); + if (overlap) { + map_add_range(base_map, orange.base, orange.size, range.rec); + addr_t old_bound = range.base + range.size; + + range.base = orange.base + orange.size; + range.size = old_bound - range.base; + } + } while (overlap && range.size != 0); + } + + mspace_free(base_map->residence, ranges); + return; +} + +void +map_union(map_t *base_map, map_t *ref_map) +{ + if (!ref_map || ref_map->root == NULL) + return; + assert(base_map != NULL); + + mem_range_t *ranges; + unsigned num, i; + + map_to_array(ref_map, &ranges, &num); + + for (i = 0; i < num; ++i) { + mem_range_t range = ranges[i]; + + map_add_range(base_map, range.base, range.size, range.rec); + + if (range.rec != NULL) + bop_msg(2, + "map_union warning: individual node information not " + "nil, which may be lost after union"); + } + + mspace_free(ref_map->residence, ranges); + return; } -void map_range_to_array(map_t *map, addr_t base, size_t size, mem_range_t **ranges, unsigned *ranges_size) { - assert( map != NULL ); +map_t * +map_clone(map_t *source, mspace space) +{ + if (space == NULL) + space = source->residence; + map_t *clone = new_range_set(space, "clone"); + + map_union(clone, source); + return clone; +} + +void +map_subtract(map_t *base_map, map_t *ref_map) +{ + if (!ref_map || ref_map->root == NULL) + return; + if (!base_map || base_map->root == NULL) + return; + + /* make copy_map be the intersection */ + map_t *copy_map = new_range_set(base_map->residence, "map_subtract_temp"); + + map_union(copy_map, base_map); + map_intersect(copy_map, ref_map); + + /* do the subtraction => base_map-copy_map */ + mem_range_t *ranges; + unsigned num, i; + + map_to_array(base_map, &ranges, &num); + + map_clear(base_map); + + for (i = 0; i < num; i++) { + mem_range_t range = ranges[i]; + mem_range_t orange; + char overlap; + + do { + overlap = map_overlaps(copy_map, &range, &orange); + if (overlap) { + if (orange.base > range.base) + map_add_range(base_map, + range.base, + orange.base - range.base, + range.rec); + addr_t old_bound = range.base + range.size; + + range.base = orange.base + orange.size; + range.size = old_bound - range.base; + } + } while (overlap && range.size != 0); + if (range.size != 0) + map_add_range(base_map, range.base, range.size, range.rec); + } + + /* free the space */ + mspace_free(base_map->residence, ranges); + map_free(copy_map); - range_node_t *rn; - unsigned i; - *ranges_size = 0; - map->root = splay(map->root, base); + return; +} - if(map->root->r.base+map->root->r.size > base) { - while(map->root->r.base < base+size) { - ++*ranges_size; - rn = splay(map->root->rc, base); - rn->lc = map->root; - map->root->rc = NULL; - map->root = rn; +mem_range_t * +map_contains(map_t *map, addr_t addr) +{ + assert(map != NULL); + if (map->root == NULL) + return NULL; + + map->root = splay(map->root, addr); + range_node_t *top = map->root; + + if (addr < top->r.base) { + if (top->lc == NULL) + return NULL; + range_node_t *node = top->lc; + + while (node->rc != NULL) + node = node->rc; + assert(node->r.base <= addr); + if (node->r.base + node->r.size > addr) + return &node->r; + else + return NULL; + } else { + if (top->r.base + top->r.size > addr) + return &map->root->r; + else + return NULL; } - } +} - *ranges = mspace_calloc(map->residence, *ranges_size, sizeof(mem_range_t)); - map->root = splay(map->root, base); +void +map_range_to_array(map_t *map, + addr_t base, + size_t size, + mem_range_t **ranges, + unsigned *ranges_size) +{ + assert(map != NULL); + + range_node_t *rn; + unsigned i; + + *ranges_size = 0; + map->root = splay(map->root, base); + + if (map->root->r.base + map->root->r.size > base) { + while (map->root->r.base < base + size) { + ++*ranges_size; + rn = splay(map->root->rc, base); + rn->lc = map->root; + map->root->rc = NULL; + map->root = rn; + } + } + + *ranges = mspace_calloc(map->residence, *ranges_size, sizeof(mem_range_t)); + map->root = splay(map->root, base); - for(i = 0; i < *ranges_size; ++i) { - ranges[i] = &map->root->r; - rn = splay(map->root->rc, base); - rn->lc = map->root; - map->root->rc = NULL; - map->root = rn; - } + for (i = 0; i < *ranges_size; ++i) { + ranges[i] = &map->root->r; + rn = splay(map->root->rc, base); + rn->lc = map->root; + map->root->rc = NULL; + map->root = rn; + } } -static void subtree_to_array( range_node_t *node, mem_range_t **ranges, unsigned *indx ) { - if ( node == NULL ) return; - subtree_to_array( node->lc, ranges, indx ); - (*ranges)[*indx] = node->r; - *indx = *indx + 1; - subtree_to_array( node->rc, ranges, indx ); +static void +subtree_to_array(range_node_t *node, mem_range_t **ranges, unsigned *indx) +{ + if (node == NULL) + return; + subtree_to_array(node->lc, ranges, indx); + (*ranges)[*indx] = node->r; + *indx = *indx + 1; + subtree_to_array(node->rc, ranges, indx); } -void map_remove_node( map_t *map, addr_t node_base ) { - assert( map != NULL && map->root != NULL ); - range_node_t *rt = splay(map->root, node_base); - assert( rt->r.base == node_base ); +void +map_remove_node(map_t *map, addr_t node_base) +{ + assert(map != NULL && map->root != NULL); + range_node_t *rt = splay(map->root, node_base); - range_node_t *x; - if ( rt->lc == NULL ) - x = rt->rc; - else { - x = splay( rt->lc, node_base ); - x->rc = rt->rc; - } - map->root = x; - map->size --; - rt->lc = rt->rc = NULL; /* must do this before the free */ - mspace_free( map->residence, rt ); + assert(rt->r.base == node_base); + + range_node_t *x; + + if (rt->lc == NULL) + x = rt->rc; + else { + x = splay(rt->lc, node_base); + x->rc = rt->rc; + } + map->root = x; + map->size--; + rt->lc = rt->rc = NULL; /* must do this before the free */ + mspace_free(map->residence, rt); } -void map_clear( map_t *map ) { - free_subtree(map->root, map); - map->root = NULL; - map->size = 0; +void +map_clear(map_t *map) +{ + free_subtree(map->root, map); + map->root = NULL; + map->size = 0; } -void map_free(map_t *map) { - free_subtree(map->root, map); - mspace_free( map->residence, map ); +void +map_free(map_t *map) +{ + free_subtree(map->root, map); + mspace_free(map->residence, map); } -void map_inspect( int verbose, map_t *map ) { - int i; - if ( map == NULL ) { - bop_msg( verbose, "range tree %s is not yet initialized", map->name); - return; - } +void +map_inspect(int verbose, map_t *map) +{ + int i; + + if (map == NULL) { + bop_msg(verbose, "range tree %s is not yet initialized", map->name); + return; + } - bop_msg( verbose, "%d range(s) in %s. (mspace %p, is_hash %d)", map->size, map->name, map->residence, map->is_hash); + bop_msg(verbose, + "%d range(s) in %s. (mspace %p, is_hash %d)", + map->size, + map->name, + map->residence, + map->is_hash); - mem_range_t *ranges; unsigned num; - map_to_array( map, &ranges, &num ); + mem_range_t *ranges; + unsigned num; - for(i = 0; i < num; ++i) - bop_msg( verbose, "\t(%p - %p, page "PRIuPTR", size %zd)", ranges[i].base, ranges[i].base + ranges[i].size, ranges[i].base >> PAGESIZEX, ranges[i].size); + map_to_array(map, &ranges, &num); - mspace_free( map->residence, ranges ); + for (i = 0; i < num; ++i) + bop_msg(verbose, + "\t(%p - %p, page " PRIuPTR ", size %zd)", + ranges[i].base, + ranges[i].base + ranges[i].size, + ranges[i].base >> PAGESIZEX, + ranges[i].size); + + mspace_free(map->residence, ranges); } -void init_empty_map( map_t *ret, mspace res, char *nm ) { - ret->residence = res; - ret->root = NULL; - ret->size = 0; - ret->name = nm; - ret->is_hash = 0; +void +init_empty_map(map_t *ret, mspace res, char *nm) +{ + ret->residence = res; + ret->root = NULL; + ret->size = 0; + ret->name = nm; + ret->is_hash = 0; } -map_t *new_range_set( mspace res, char *nm ) { - map_t *ret = mspace_malloc(res, sizeof(map_t)); - init_empty_map( ret, res, nm ); - return ret; +map_t * +new_range_set(mspace res, char *nm) +{ + map_t *ret = mspace_malloc(res, sizeof(map_t)); + + init_empty_map(ret, res, nm); + return ret; } diff --git a/sandbox/add.c b/sandbox/add.c index b7ea110..7131867 100644 --- a/sandbox/add.c +++ b/sandbox/add.c @@ -1,14 +1,15 @@ -#include -#include #include #include +#include +#include #include #include #include "bop_api.h" #include "dmmalloc.h" -/* The program makes an array of randomly initialized integers and adds them together. */ +/* The program makes an array of randomly initialized integers and adds them + * together. */ int main(int argc, char **argv) @@ -22,22 +23,23 @@ main(int argc, char **argv) exit(1); } - datasize = (int)(atof(argv[1])*1000000); - assert(datasize>0); + datasize = (int)(atof(argv[1]) * 1000000); + assert(datasize > 0); parallelism = atoi(argv[2]); - assert(parallelism>0); + assert(parallelism > 0); /* Initialization */ - printf("%d: initializing %d million numbers\n", getpid(), datasize/1000000); + printf( + "%d: initializing %d million numbers\n", getpid(), datasize / 1000000); data = (double *)malloc(datasize * sizeof(*data)); for (int i = 0; i < datasize; i++) { data[i] = i; } - printf("%d: adding %d million numbers\n", getpid(), datasize/1000000); + printf("%d: adding %d million numbers\n", getpid(), datasize / 1000000); - blocksize = ceil((float)datasize/parallelism); + blocksize = ceil((float)datasize / parallelism); for (int i = 0; i < datasize; i += blocksize) { int n; @@ -47,11 +49,11 @@ main(int argc, char **argv) BOP_record_read(&blocksize, sizeof(blocksize)); BOP_record_read(&datasize, sizeof(datasize)); - n = i + blocksize > datasize? datasize : i + blocksize; + n = i + blocksize > datasize ? datasize : i + blocksize; BOP_record_read(data + i, (n - i) * sizeof(*data)); - for (int j = i; j -#include #include #include +#include +#include -/* The program makes an array of randomly initialized integers and adds them together. */ +/* The program makes an array of randomly initialized integers and adds them + * together. */ #include "bop_api.h" -double * data; +double *data; double sum; -void initialize( int ); -double lots_of_computation_on_block( int start, int end ); +void +initialize(int); +double +lots_of_computation_on_block(int start, int end); -int main(int argc, char ** argv) +int +main(int argc, char **argv) { - int i, s; - int data_size, num_blocks; - int block_size; + int i, s; + int data_size, num_blocks; + int block_size; - /* processing the input */ - if (argc>3 || argc<2) { - printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); - exit(1); - } - data_size = (int) (atof(argv[1])*1000000); - assert(data_size>0); - num_blocks = atoi(argv[2]); - assert(num_blocks>0); + /* processing the input */ + if (argc > 3 || argc < 2) { + printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); + exit(1); + } + data_size = (int)(atof(argv[1]) * 1000000); + assert(data_size > 0); + num_blocks = atoi(argv[2]); + assert(num_blocks > 0); - initialize(data_size ); + initialize(data_size); - printf("%d: adding %d million numbers\n", getpid(), data_size/1000000); + printf("%d: adding %d million numbers\n", getpid(), data_size / 1000000); - block_size = ceil( (float) data_size / num_blocks ); + block_size = ceil((float)data_size / num_blocks); - while ( data_size > 0 ) { - int block_end = data_size; - data_size -= block_size; - int block_begin = data_size >= 0 ? data_size : 0 ; + while (data_size > 0) { + int block_end = data_size; - BOP_ppr_begin(1); /* Begin PPR */ + data_size -= block_size; + int block_begin = data_size >= 0 ? data_size : 0; - double block_sum = lots_of_computation_on_block( block_begin, block_end ); + BOP_ppr_begin(1); /* Begin PPR */ - BOP_ordered_begin( 1 ); + double block_sum = + lots_of_computation_on_block(block_begin, block_end); - BOP_use( &sum, sizeof( double) ); + BOP_ordered_begin(1); - sum += block_sum; + BOP_use(&sum, sizeof(double)); - BOP_promise( &sum, sizeof( double ) ); + sum += block_sum; - BOP_ordered_end( 1 ); + BOP_promise(&sum, sizeof(double)); - BOP_ppr_end(1); /* End PPR */ - } + BOP_ordered_end(1); - printf("%d: The sum is %.0f million (%.0f) \n", getpid(), sum/1000000, sum); - return 0; -} + BOP_ppr_end(1); /* End PPR */ + } + printf( + "%d: The sum is %.0f million (%.0f) \n", getpid(), sum / 1000000, sum); + return 0; +} -void initialize( int data_size ) { - int i, _s; +void +initialize(int data_size) +{ + int i, _s; - /* initialization */ - printf("%d: initializing %d million numbers\n", getpid(), data_size/1000000); + /* initialization */ + printf("%d: initializing %d million numbers\n", + getpid(), + data_size / 1000000); - data = (double *) malloc(data_size*sizeof(double)); - assert(data != NULL); + data = (double *)malloc(data_size * sizeof(double)); + assert(data != NULL); - for(i = 0; i < data_size; i++) - data[i] = i; + for (i = 0; i < data_size; i++) + data[i] = i; - sum = 0; + sum = 0; } -double lots_of_computation_on_block( int start, int end ) { - int j; - double total = 0; - for ( j = start ; j < end ; j ++ ) - total += sin(data[ j ]) * sin(data[ j ]) + cos(data[ j ]) * cos(data[ j ]); +double +lots_of_computation_on_block(int start, int end) +{ + int j; + double total = 0; + + for (j = start; j < end; j++) + total += sin(data[j]) * sin(data[j]) + cos(data[j]) * cos(data[j]); - BOP_record_read( &data[j], sizeof( double )*(end - start) ); + BOP_record_read(&data[j], sizeof(double) * (end - start)); - return total; + return total; } diff --git a/tests/add/add_ppr_only.c b/tests/add/add_ppr_only.c index a7b7f4a..6ae6362 100644 --- a/tests/add/add_ppr_only.c +++ b/tests/add/add_ppr_only.c @@ -1,87 +1,102 @@ -#include -#include #include #include +#include +#include -/* The program makes an array of randomly initialized integers and adds them together. */ +/* The program makes an array of randomly initialized integers and adds them + * together. */ #include "bop_api.h" -double * data; +double *data; double sum; -void initialize( int ); -double lots_of_computation_on_block( int start, int end ); +void +initialize(int); +double +lots_of_computation_on_block(int start, int end); -int main(int argc, char ** argv) +int +main(int argc, char **argv) { - int data_size, num_blocks; - int block_size; + int data_size, num_blocks; + int block_size; - /* processing the input */ - if (argc>3 || argc<2) { - printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); - exit(1); - } - data_size = (int) (atof(argv[1])*1000000); - assert(data_size>0); - num_blocks = atoi(argv[2]); - assert(num_blocks>0); - double *sums = (double *) malloc( num_blocks * sizeof(double) ); + /* processing the input */ + if (argc > 3 || argc < 2) { + printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); + exit(1); + } + data_size = (int)(atof(argv[1]) * 1000000); + assert(data_size > 0); + num_blocks = atoi(argv[2]); + assert(num_blocks > 0); + double *sums = (double *)malloc(num_blocks * sizeof(double)); - initialize(data_size ); + initialize(data_size); - printf("%d: adding %d million numbers\n", getpid(), data_size/1000000); - block_size = ceil( (float) data_size / num_blocks ); - int index = 0; - while ( data_size > 0 ) { - int block_end = data_size; - data_size -= block_size; - int block_begin = data_size >= 0 ? data_size : 0 ; + printf("%d: adding %d million numbers\n", getpid(), data_size / 1000000); + block_size = ceil((float)data_size / num_blocks); + int index = 0; - BOP_ppr_begin(1); /* Begin PPR */ + while (data_size > 0) { + int block_end = data_size; - double block_sum = lots_of_computation_on_block( block_begin, block_end ); + data_size -= block_size; + int block_begin = data_size >= 0 ? data_size : 0; - sums[ index ] = block_sum; + BOP_ppr_begin(1); /* Begin PPR */ - BOP_promise( &sums[ index ], sizeof( double ) ); + double block_sum = + lots_of_computation_on_block(block_begin, block_end); - BOP_ppr_end(1); /* End PPR */ - index ++; - } + sums[index] = block_sum; - int i; - for ( i = 0; i < index; i ++ ) - sum += sums[ i ]; + BOP_promise(&sums[index], sizeof(double)); - printf("%d: The sum is %.0f million (%.0f) \n", getpid(), sum/1000000, sum); - return 0; -} + BOP_ppr_end(1); /* End PPR */ + index++; + } + int i; -void initialize( int data_size ) { - int i, _s; + for (i = 0; i < index; i++) + sum += sums[i]; - /* initialization */ - printf("%d: initializing %d million numbers\n", getpid(), data_size/1000000); + printf( + "%d: The sum is %.0f million (%.0f) \n", getpid(), sum / 1000000, sum); + return 0; +} - data = (double *) malloc(data_size*sizeof(double)); - assert(data != NULL); +void +initialize(int data_size) +{ + int i, _s; + + /* initialization */ + printf("%d: initializing %d million numbers\n", + getpid(), + data_size / 1000000); + + data = (double *)malloc(data_size * sizeof(double)); + assert(data != NULL); - for(i = 0; i < data_size; i++) - data[i] = i; + for (i = 0; i < data_size; i++) + data[i] = i; - sum = 0; + sum = 0; } -double lots_of_computation_on_block( int start, int end ) { - int j; - double total = 0; - for ( j = start ; j < end ; j ++ ) - total += sin(data[ j ]) * sin(data[ j ]) + cos(data[ j ]) * cos(data[ j ]); +double +lots_of_computation_on_block(int start, int end) +{ + int j; + double total = 0; + + for (j = start; j < end; j++) + total += sin(data[j]) * sin(data[j]) + cos(data[j]) * cos(data[j]); - BOP_record_read( &data[j], sizeof( double )*(end - start) ); + BOP_record_read(&data[j], sizeof(double) * (end - start)); - return total; + return total; } diff --git a/tests/malloc_test.c b/tests/malloc_test.c index dbeaab9..9aa4a74 100644 --- a/tests/malloc_test.c +++ b/tests/malloc_test.c @@ -1,26 +1,29 @@ #include "malloc_wrapper.h" #include -int main(){ - int count = 0; - int mod; - void* ptr; - for(count = 1; count < 1000; count++){ - mod = count % 3; - switch (mod) { - case 0: - ptr = malloc(count * 3); - break; - case 1: - ptr = calloc(count, 4); - case 2: - ptr = malloc(count * 7); - ptr = realloc(ptr, count * 8); - ptr = realloc(ptr, count * 3); - break; +int +main() +{ + int count = 0; + int mod; + void *ptr; + + for (count = 1; count < 1000; count++) { + mod = count % 3; + switch (mod) { + case 0: + ptr = malloc(count * 3); + break; + case 1: + ptr = calloc(count, 4); + case 2: + ptr = malloc(count * 7); + ptr = realloc(ptr, count * 8); + ptr = realloc(ptr, count * 3); + break; + } + free(ptr); } - free(ptr); - } - printf("malloc test complete\n"); - return 0; + printf("malloc test complete\n"); + return 0; } diff --git a/tests/mem/add_mem_test.c b/tests/mem/add_mem_test.c index c35b61f..2978cc3 100644 --- a/tests/mem/add_mem_test.c +++ b/tests/mem/add_mem_test.c @@ -1,96 +1,112 @@ -#include -#include #include #include +#include +#include -/* The program makes an array of randomly initialized integers and adds them together. */ +/* The program makes an array of randomly initialized integers and adds them + * together. */ #include "../../bop/bop_api.h" -double * data; +double *data; double sum; -void initialize( int ); -double lots_of_computation_on_block( int start, int end , int index); +void +initialize(int); +double +lots_of_computation_on_block(int start, int end, int index); -int main(int argc, char ** argv) +int +main(int argc, char **argv) { - int data_size, num_blocks; - int block_size; - - /* processing the input */ - if (argc>3 || argc<2) { - printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); - exit(1); - } - data_size = (int) (atof(argv[1])*1000000); - assert(data_size>0); - num_blocks = atoi(argv[2]); - assert(num_blocks>0); - double *sums = (double *) malloc( num_blocks * sizeof(double) ); - - initialize(data_size ); - - printf("%d: adding %d million numbers\n", getpid(), data_size/1000000); - - block_size = ceil( (float) data_size / num_blocks ); - - int** sums_per_task = malloc(sizeof(void*)*block_size); - int index = 0; - while ( data_size > 0 ) { - int block_end = data_size; - data_size -= block_size; - int block_begin = data_size >= 0 ? data_size : 0 ; - BOP_ppr_begin(1); /* Begin PPR */ - - double block_sum = lots_of_computation_on_block( block_begin, block_end ,index); - - sums_per_task[index] = malloc(sizeof(double)); - *sums_per_task[index] = block_sum; - BOP_promise( &sums_per_task[index], sizeof(void*)); - BOP_promise( sums_per_task[index], sizeof(double)); - sums[ index ] = block_sum; - - BOP_promise( &sums[ index ], sizeof( double ) ); - - BOP_ppr_end(1); /* End PPR */ - - index ++; - } - - int i; - for ( i = 0; i < index; i ++ ){ - sum += sums[ i ]; - printf("The sum of index %d is %d\n", i, *sums_per_task[i]); - } - printf("%d: The sum is %.0f million (%.0f) \n", getpid(), sum/1000000, sum); - exit(0); -} + int data_size, num_blocks; + int block_size; + + /* processing the input */ + if (argc > 3 || argc < 2) { + printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); + exit(1); + } + data_size = (int)(atof(argv[1]) * 1000000); + assert(data_size > 0); + num_blocks = atoi(argv[2]); + assert(num_blocks > 0); + double *sums = (double *)malloc(num_blocks * sizeof(double)); + + initialize(data_size); + + printf("%d: adding %d million numbers\n", getpid(), data_size / 1000000); + + block_size = ceil((float)data_size / num_blocks); + + int **sums_per_task = malloc(sizeof(void *) * block_size); + int index = 0; + + while (data_size > 0) { + int block_end = data_size; + + data_size -= block_size; + int block_begin = data_size >= 0 ? data_size : 0; + BOP_ppr_begin(1); /* Begin PPR */ -void initialize( int data_size ) { - int i, _s; + double block_sum = + lots_of_computation_on_block(block_begin, block_end, index); - /* initialization */ - printf("%d: initializing %d million numbers\n", getpid(), data_size/1000000); + sums_per_task[index] = malloc(sizeof(double)); + *sums_per_task[index] = block_sum; + BOP_promise(&sums_per_task[index], sizeof(void *)); + BOP_promise(sums_per_task[index], sizeof(double)); + sums[index] = block_sum; - data = (double *) malloc(data_size*sizeof(double)); - assert(data != NULL); + BOP_promise(&sums[index], sizeof(double)); - for(i = 0; i < data_size; i++) - data[i] = i; + BOP_ppr_end(1); /* End PPR */ - sum = 0; + index++; + } + + int i; + + for (i = 0; i < index; i++) { + sum += sums[i]; + printf("The sum of index %d is %d\n", i, *sums_per_task[i]); + } + printf( + "%d: The sum is %.0f million (%.0f) \n", getpid(), sum / 1000000, sum); + exit(0); } -double lots_of_computation_on_block( int start, int end , int index) { - int j; - double total = 0; - for ( j = start ; j < end ; j ++ ){ - total += sin(data[ j ]) * sin(data[ j ]) + cos(data[ j ]) * cos(data[ j ]); - } - total+=index; - BOP_record_read( &data[j], sizeof( double )*(end - start) ); +void +initialize(int data_size) +{ + int i, _s; + + /* initialization */ + printf("%d: initializing %d million numbers\n", + getpid(), + data_size / 1000000); + + data = (double *)malloc(data_size * sizeof(double)); + assert(data != NULL); + + for (i = 0; i < data_size; i++) + data[i] = i; + + sum = 0; +} + +double +lots_of_computation_on_block(int start, int end, int index) +{ + int j; + double total = 0; + + for (j = start; j < end; j++) { + total += sin(data[j]) * sin(data[j]) + cos(data[j]) * cos(data[j]); + } + total += index; + BOP_record_read(&data[j], sizeof(double) * (end - start)); - return total; + return total; } diff --git a/tests/mem/big_alloc.c b/tests/mem/big_alloc.c index 6f56a40..c4368a5 100644 --- a/tests/mem/big_alloc.c +++ b/tests/mem/big_alloc.c @@ -1,12 +1,13 @@ -#include -#include #include #include +#include +#include -/* The program makes an array of randomly initialized integers and adds them together. */ +/* The program makes an array of randomly initialized integers and adds them + * together. */ -#include "dmmalloc.h" #include "bop_api.h" +#include "dmmalloc.h" #ifdef BOP unsigned int max_ppr = DM_MAX_REQ; @@ -15,39 +16,52 @@ unsigned int max_ppr = 1 << 20; #endif #define num_arrays 5 -int set(int ind){ - return ind + 1; +int +set(int ind) +{ + return ind + 1; } -int main(int argc, char ** argv) +int +main(int argc, char **argv) { - unsigned int alloc_size = max_ppr + 100; - bop_debug("dm max size is %u", max_ppr); - bop_debug("Allocation size for test %u", alloc_size); - - int * some_arrays[num_arrays] = {NULL, NULL, NULL, NULL, NULL}; - void * raw; - int ind = 0; - for(ind = 0; ind < num_arrays; ind++){ - BOP_ppr_begin(1); - raw = calloc(alloc_size, 1); //something larger - some_arrays[ind] = raw; - some_arrays[ind][0] = set(ind); - bop_debug("allocation %d at : %p val @ 0: %d", ind, raw, some_arrays[ind][0]); - BOP_promise(&(some_arrays[ind][0]), sizeof(int)); - BOP_promise(&(some_arrays[ind]), sizeof(some_arrays[ind])); - sleep(3); - BOP_ppr_end(1); - } - BOP_group_over(1); - // BOP_use(&some_arrays, sizeof(some_arrays)); - int eval = 0; - for(ind = 0; ind < num_arrays; ind++){ - bop_debug("index %d begins at address %p", ind, &some_arrays[ind][0]); - if(some_arrays[ind][0] != set(ind)){ - bop_debug("array %d has invalid values! mem not copied. expected: %d actual: %d", ind, ind+1, some_arrays[ind][0]); - eval = 1; + unsigned int alloc_size = max_ppr + 100; + + bop_debug("dm max size is %u", max_ppr); + bop_debug("Allocation size for test %u", alloc_size); + + int *some_arrays[num_arrays] = {NULL, NULL, NULL, NULL, NULL}; + void *raw; + int ind = 0; + + for (ind = 0; ind < num_arrays; ind++) { + BOP_ppr_begin(1); + raw = calloc(alloc_size, 1); // something larger + some_arrays[ind] = raw; + some_arrays[ind][0] = set(ind); + bop_debug("allocation %d at : %p val @ 0: %d", + ind, + raw, + some_arrays[ind][0]); + BOP_promise(&(some_arrays[ind][0]), sizeof(int)); + BOP_promise(&(some_arrays[ind]), sizeof(some_arrays[ind])); + sleep(3); + BOP_ppr_end(1); + } + BOP_group_over(1); + // BOP_use(&some_arrays, sizeof(some_arrays)); + int eval = 0; + + for (ind = 0; ind < num_arrays; ind++) { + bop_debug("index %d begins at address %p", ind, &some_arrays[ind][0]); + if (some_arrays[ind][0] != set(ind)) { + bop_debug("array %d has invalid values! mem not copied. expected: " + "%d actual: %d", + ind, + ind + 1, + some_arrays[ind][0]); + eval = 1; + } } - } - exit(eval); + exit(eval); } diff --git a/tests/mem/mem.c b/tests/mem/mem.c old mode 100755 new mode 100644 index bf5032c..44650d9 --- a/tests/mem/mem.c +++ b/tests/mem/mem.c @@ -1,99 +1,103 @@ -#include -#include #include #include +#include +#include -/* The program makes an array of randomly initialized integers and adds them together. */ +/* The program makes an array of randomly initialized integers and adds them + * together. */ #include "bop_api.h" int *dest; int sum; -//void initialize( int ); -void lots_of_allocation_on_block( int start, int end ); +// void initialize( int ); +void +lots_of_allocation_on_block(int start, int end); -int main(int argc, char ** argv) +int +main(int argc, char **argv) { - int i; - int data_size; - int num_blocks; - int block_size; - - - /* processing the input */ - if (argc>3 || argc<2) { - printf("Usage: %s array_size num-blocks\n", argv[0]); - exit(1); - } - data_size = (int) (atof(argv[1])); - assert(data_size>0); - num_blocks = atoi(argv[2]); - assert(num_blocks>0); - dest = (int*) malloc(sizeof(int)*data_size); - int size = data_size; - - //initialize(data_size ); - - printf("%d: adding %d numbers\n", getpid(), data_size); - - block_size = ceil( (float) data_size / num_blocks ); - - while ( data_size > 0 ) { - int block_end = data_size; - data_size -= block_size; - int block_begin = data_size >= 0 ? data_size : 0 ; - - - BOP_ppr_begin(1); /* Begin PPR */ - - lots_of_allocation_on_block(block_begin, block_end); - - BOP_ppr_end(1); /* End PPR */ - } - - for (i=0; i < size; i++) { - int diff = 1; - - /* - if ( dest[i] != i ) { - printf("diff: %d; dest[i]: %d; i: %d \n", diff, dest[i], i); - } - */ - assert (dest[i] == i); - } - //printf("%d: The sum is %.0f \n", getpid(), ); - printf("end\n"); - return 0; + int i; + int data_size; + int num_blocks; + int block_size; + + /* processing the input */ + if (argc > 3 || argc < 2) { + printf("Usage: %s array_size num-blocks\n", argv[0]); + exit(1); + } + data_size = (int)(atof(argv[1])); + assert(data_size > 0); + num_blocks = atoi(argv[2]); + assert(num_blocks > 0); + dest = (int *)malloc(sizeof(int) * data_size); + int size = data_size; + + // initialize(data_size ); + + printf("%d: adding %d numbers\n", getpid(), data_size); + + block_size = ceil((float)data_size / num_blocks); + + while (data_size > 0) { + int block_end = data_size; + + data_size -= block_size; + int block_begin = data_size >= 0 ? data_size : 0; + + BOP_ppr_begin(1); /* Begin PPR */ + + lots_of_allocation_on_block(block_begin, block_end); + + BOP_ppr_end(1); /* End PPR */ + } + + for (i = 0; i < size; i++) { + int diff = 1; + + /* + * if ( dest[i] != i ) { + * printf("diff: %d; dest[i]: %d; i: %d \n", diff, dest[i], i); + * } + */ + assert(dest[i] == i); + } + // printf("%d: The sum is %.0f \n", getpid(), ); + printf("end\n"); + return 0; } /* -void initialize( int data_size ) { - int i, _s; - - // initialization - printf("%d: initializing %d million numbers\n", getpid(), data_size/1000000); - - data = (double *) malloc(data_size*sizeof(double)); - assert(data != NULL); - - for(i = 0; i < data_size; i++) - data[i] = i; - - sum = 0; -} -*/ - -void lots_of_allocation_on_block( int start, int end ) { - int j; - int *addr; - - for (j = start; j < end; j++) { - addr = malloc(sizeof(int)); - *addr = j; - dest[j] = *addr; - //printf("dest[j]: %d and addr: %d\n", dest[j], *addr); - BOP_promise( &dest[j], sizeof(int) ); - } - + * void initialize( int data_size ) { + * int i, _s; + * + * // initialization + * printf("%d: initializing %d million numbers\n", getpid(), + * data_size/1000000); + * + * data = (double *) malloc(data_size*sizeof(double)); + * assert(data != NULL); + * + * for(i = 0; i < data_size; i++) + * data[i] = i; + * + * sum = 0; + * } + */ + +void +lots_of_allocation_on_block(int start, int end) +{ + int j; + int *addr; + + for (j = start; j < end; j++) { + addr = malloc(sizeof(int)); + *addr = j; + dest[j] = *addr; + // printf("dest[j]: %d and addr: %d\n", dest[j], *addr); + BOP_promise(&dest[j], sizeof(int)); + } } diff --git a/tests/mem/small_alloc.c b/tests/mem/small_alloc.c index 113259f..fad9283 100644 --- a/tests/mem/small_alloc.c +++ b/tests/mem/small_alloc.c @@ -1,12 +1,13 @@ -#include -#include #include #include +#include +#include -/* The program makes an array of randomly initialized integers and adds them together. */ +/* The program makes an array of randomly initialized integers and adds them + * together. */ -#include "dmmalloc.h" #include "bop_api.h" +#include "dmmalloc.h" #ifdef BOP unsigned int max_ppr = DM_MAX_REQ; @@ -15,39 +16,52 @@ unsigned int max_ppr = 1 << 20; #endif #define num_arrays 5 -int set(int ind){ - return ind + 1; +int +set(int ind) +{ + return ind + 1; } -int main(int argc, char ** argv) +int +main(int argc, char **argv) { - unsigned int alloc_size = max_ppr - 100; - bop_debug("dm max size is %u", max_ppr); - bop_debug("Allocation size for test %u", alloc_size); - - int * some_arrays[num_arrays] = {NULL, NULL, NULL, NULL, NULL}; - void * raw; - int ind = 0; - for(ind = 0; ind < num_arrays; ind++){ - BOP_ppr_begin(1); - raw = calloc(alloc_size, 1); //something larger - some_arrays[ind] = raw; - some_arrays[ind][0] = set(ind); - bop_debug("allocation %d at : %p val @ 0: %d", ind, raw, some_arrays[ind][0]); - BOP_promise(&(some_arrays[ind][0]), sizeof(int)); - BOP_promise(&(some_arrays[ind]), sizeof(some_arrays[ind])); - sleep(3); - BOP_ppr_end(1); - } - BOP_group_over(1); - // BOP_use(&some_arrays, sizeof(some_arrays)); - int eval = 0; - for(ind = 0; ind < num_arrays; ind++){ - bop_debug("index %d begins at address %p", ind, &some_arrays[ind][0]); - if(some_arrays[ind][0] != set(ind)){ - bop_debug("array %d has invalid values! mem not copied. expected: %d actual: %d", ind, ind+1, some_arrays[ind][0]); - eval = 1; + unsigned int alloc_size = max_ppr - 100; + + bop_debug("dm max size is %u", max_ppr); + bop_debug("Allocation size for test %u", alloc_size); + + int *some_arrays[num_arrays] = {NULL, NULL, NULL, NULL, NULL}; + void *raw; + int ind = 0; + + for (ind = 0; ind < num_arrays; ind++) { + BOP_ppr_begin(1); + raw = calloc(alloc_size, 1); // something larger + some_arrays[ind] = raw; + some_arrays[ind][0] = set(ind); + bop_debug("allocation %d at : %p val @ 0: %d", + ind, + raw, + some_arrays[ind][0]); + BOP_promise(&(some_arrays[ind][0]), sizeof(int)); + BOP_promise(&(some_arrays[ind]), sizeof(some_arrays[ind])); + sleep(3); + BOP_ppr_end(1); + } + BOP_group_over(1); + // BOP_use(&some_arrays, sizeof(some_arrays)); + int eval = 0; + + for (ind = 0; ind < num_arrays; ind++) { + bop_debug("index %d begins at address %p", ind, &some_arrays[ind][0]); + if (some_arrays[ind][0] != set(ind)) { + bop_debug("array %d has invalid values! mem not copied. expected: " + "%d actual: %d", + ind, + ind + 1, + some_arrays[ind][0]); + eval = 1; + } } - } - exit(eval); + exit(eval); } diff --git a/tests/parallel_alloc/add_ppr_only.c b/tests/parallel_alloc/add_ppr_only.c index 78ea872..f91189f 100644 --- a/tests/parallel_alloc/add_ppr_only.c +++ b/tests/parallel_alloc/add_ppr_only.c @@ -1,13 +1,14 @@ -#include -#include #include #include +#include +#include #include #include #include -/* The program makes an array of randomly initialized integers and adds them together. */ +/* The program makes an array of randomly initialized integers and adds them + * together. */ #include "bop_api.h" @@ -15,7 +16,7 @@ static void initialize(double *array, size_t len) { for (size_t i = 0; i < len; ++i) { - array[i] = sin(i)*sin(i) + cos(i)*cos(i); + array[i] = sin(i) * sin(i) + cos(i) * cos(i); } } @@ -23,6 +24,7 @@ static double get_sum(double *array, size_t len) { double sum = 0; + for (size_t i = 0; i < len; ++i) { sum += array[i]; } @@ -30,36 +32,40 @@ get_sum(double *array, size_t len) } int -main(int argc, char ** argv) +main(int argc, char **argv) { int data_size, num_blocks; int block_size; /* processing the input */ - if (argc>3 || argc<2) { + if (argc > 3 || argc < 2) { printf("Usage: %s array_size-in-millions num-blocks\n", argv[0]); exit(1); } - data_size = (int) (atof(argv[1])*1000000); - assert(data_size>0); + data_size = (int)(atof(argv[1]) * 1000000); + assert(data_size > 0); num_blocks = atoi(argv[2]); - assert(num_blocks>0); + assert(num_blocks > 0); - printf("%d: adding %d million numbers\n", getpid(), data_size/1000000); + printf("%d: adding %d million numbers\n", getpid(), data_size / 1000000); block_size = ceil((float)data_size / num_blocks); double sums[num_blocks]; + memset(&sums, 0, num_blocks * sizeof(double)); int index = 0; + while (data_size > 0) { int block_end = data_size; + data_size -= block_size; - int block_begin = data_size >= 0 ? data_size : 0 ; + int block_begin = data_size >= 0 ? data_size : 0; - BOP_ppr_begin(1); /* Begin PPR */ + BOP_ppr_begin(1); /* Begin PPR */ double *block = malloc((block_end - block_begin) * sizeof(*block)); + assert(block != NULL); initialize(block, block_end - block_begin); BOP_promise(block, (block_end - block_begin) * sizeof(*block)); @@ -69,12 +75,13 @@ main(int argc, char ** argv) BOP_promise(&sums[index], sizeof(double)); free(block); - BOP_ppr_end(1); /* End PPR */ + BOP_ppr_end(1); /* End PPR */ index++; } double sum = get_sum(sums, num_blocks); - printf("%d: The sum is %.0f million (%.0f) \n", getpid(), sum/1000000, sum); + printf( + "%d: The sum is %.0f million (%.0f) \n", getpid(), sum / 1000000, sum); return 0; } diff --git a/tests/sleep/sleep.c b/tests/sleep/sleep.c index f0a3037..0042029 100644 --- a/tests/sleep/sleep.c +++ b/tests/sleep/sleep.c @@ -1,53 +1,58 @@ +#include #include -#include -#include +#include #include +#include +#include #include -#include -#include #include "bop_api.h" int ITERS = 4; int *t; -int main(int argc, char ** argv) { - - int i, left, total=0; - - if (argc>1) { - ITERS = atoi(argv[1]); - assert(ITERS > 0); - } - - t = (int *) malloc(ITERS * sizeof(int)); - - printf("%d naps:", ITERS); - for(i=0;i 1) { + ITERS = atoi(argv[1]); + assert(ITERS > 0); + } + + t = (int *)malloc(ITERS * sizeof(int)); + + printf("%d naps:", ITERS); + for (i = 0; i < ITERS; i++) { + t[i] = rand() % 2; + total += t[i]; + printf(" %d", t[i]); + } + printf("\n"); + + time_t start, end; + + // srand(getpid()); + start = time(NULL); + + for (i = 0; i < ITERS; i++) { + BOP_ppr_begin(1); + int pid = getpid(); + + printf("%d: try to sleep for %d sec\n", pid, t[i]); + left = sleep(t[i]); + while (left != 0) { + printf("%d: try finishing incomplete sleep (%d sec left)\n", + pid, + left); + left = sleep(left); + } + BOP_ppr_end(1); } - BOP_ppr_end( 1 ); - } - end = time(NULL); - printf("process time: %d seconds\n", total); - printf("clock time: %d seconds\n", (int) end-start); - return 0; + end = time(NULL); + printf("process time: %d seconds\n", total); + printf("clock time: %d seconds\n", (int)end - start); + return 0; } diff --git a/tests/str/BOP_strcmp/string.c b/tests/str/BOP_strcmp/string.c index f6ffe27..fabd632 100644 --- a/tests/str/BOP_strcmp/string.c +++ b/tests/str/BOP_strcmp/string.c @@ -1,91 +1,112 @@ #include -#include #include +#include #include "bop_api.h" #define STEP 20000000 -#define min(a,b) ((a < b) ? a : b) +#define min(a, b) ((a < b) ? a : b) #define read(x) BOP_use(&x, sizeof x) #define write(x) BOP_promise(&x, sizeof x) /* compares two strings for equality */ /* Compare bs1 and bs2, returning less than, equal to or - greater than zero if bs1 is lexicographically less than, - equal to or greater than bs2. */ -int BOP_strcmp(char* p1, char* p2) { - - register const unsigned char *s1 = (const unsigned char *) p1; - register const unsigned char *s2 = (const unsigned char *) p2; - unsigned register char c1, c2; - - int equal = 1; - int ret; - int done = 0; - long int ub = 0; - - do { - s1 = p1 + ub; - s2 = p2 + ub; - unsigned const register char* itr = s1 + STEP; - BOP_ppr_begin(1); - do { - c1 = (unsigned char) *s1++; - c2 = (unsigned char) *s2++; - if (c1 == '\0') break; - } while ((c1 == c2) && (s1 < itr)); - if (c1 == '\0' || c1 != c2) { - write(done); - ret = ((c1) - (c2)); - done = 1; - } - bop_msg(1,"Distance from base pointer: %d",(long int) s1 - (long int) p1); - BOP_ppr_end(1); - - ub += STEP; - read(done); - } while (!done); - - return ret; + * greater than zero if bs1 is lexicographically less than, + * equal to or greater than bs2. */ +int +BOP_strcmp(char *p1, char *p2) +{ + register const unsigned char *s1 = (const unsigned char *)p1; + register const unsigned char *s2 = (const unsigned char *)p2; + unsigned register char c1, c2; + + int equal = 1; + int ret; + int done = 0; + long int ub = 0; + + do { + s1 = p1 + ub; + s2 = p2 + ub; + unsigned const register char *itr = s1 + STEP; + + BOP_ppr_begin(1); + do { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0') + break; + } while ((c1 == c2) && (s1 < itr)); + if (c1 == '\0' || c1 != c2) { + write(done); + ret = ((c1) - (c2)); + done = 1; + } + bop_msg( + 1, "Distance from base pointer: %d", (long int)s1 - (long int)p1); + BOP_ppr_end(1); + + ub += STEP; + read(done); + } while (!done); + + return ret; } /* reads a string in from a file */ -char* read_string(char* file_name) { - /* open file for reading */ - FILE* fStream = fopen(file_name, "r"); - if(fStream == NULL){fputs("File open error\n",stderr); exit(1);} +char * +read_string(char *file_name) +{ + /* open file for reading */ + FILE *fStream = fopen(file_name, "r"); + + if (fStream == NULL) { + fputs("File open error\n", stderr); + exit(1); + } + + /* get file size */ + fseek(fStream, 0, SEEK_END); + int fSize = ftell(fStream); + + rewind(fStream); + + /* allocate memory */ + char *str = malloc(fSize * sizeof *str); - /* get file size */ - fseek(fStream, 0, SEEK_END); - int fSize = ftell(fStream); - rewind(fStream); + if (str == NULL) { + fputs("Memory error\n", stderr); + exit(2); + } - /* allocate memory */ - char* str = malloc(fSize * sizeof *str); - if(str == NULL){fputs("Memory error\n", stderr); exit(2);} + /* read sequence into buffer */ + size_t result = fread(str, 1, fSize - 1, fStream); - /* read sequence into buffer */ - size_t result = fread(str, 1, fSize - 1, fStream); - if(result != fSize - 1){fputs("Reading error\n", stderr); exit(3);} + if (result != fSize - 1) { + fputs("Reading error\n", stderr); + exit(3); + } - /* terminate */ - fclose(fStream); + /* terminate */ + fclose(fStream); - return str; + return str; } /* test the functions defined in this file */ -int main(int argc, char *argv[]) { - char* a = read_string(argv[1]); - char* b = read_string(argv[2]); - - bop_msg(1,"before string compare",0); - - if (argv[3][0] == 'b') { - printf("Compaing...\n"); - printf("The Result: %d\n",BOP_strcmp(a,b)); - } else { - printf("%d\n",strcmp(a,b)); - } - return 0; +int +main(int argc, char *argv[]) +{ + char *a = read_string(argv[1]); + char *b = read_string(argv[2]); + + bop_msg(1, "before string compare", 0); + + if (argv[3][0] == 'b') { + printf("Compaing...\n"); + printf("The Result: %d\n", BOP_strcmp(a, b)); + } else { + printf("%d\n", strcmp(a, b)); + } + return 0; } diff --git a/tests/str/BOP_string/string.c b/tests/str/BOP_string/string.c index 24067c2..191b00d 100644 --- a/tests/str/BOP_string/string.c +++ b/tests/str/BOP_string/string.c @@ -1,177 +1,207 @@ #include -#include #include +#include #include "bop_api.h" #define STEP 20000000 -#define min(a,b) ((a < b) ? a : b) +#define min(a, b) ((a < b) ? a : b) #define read(x) BOP_use(&x, sizeof x) #define write(x) BOP_promise(&x, sizeof x) -typedef struct -{ +typedef struct { size_t size; - char * string; + char *string; } BOP_string; /* creates a BOP_string struct from a char array */ -BOP_string* BOP_create_string(char* str) { - BOP_string* ret = malloc(sizeof *ret); - size_t len = strlen(str); - /* have to add one for the terminating character */ - ret->string = malloc((len+1) * sizeof *(ret->string)); - strcpy(ret->string,str); - ret->size = len; - return ret; +BOP_string * +BOP_create_string(char *str) +{ + BOP_string *ret = malloc(sizeof *ret); + size_t len = strlen(str); + + /* have to add one for the terminating character */ + ret->string = malloc((len + 1) * sizeof *(ret->string)); + strcpy(ret->string, str); + ret->size = len; + return ret; } /* returns a copy of the string as a char array */ -char* BOP_get_string(BOP_string* bstr) { - /* have to add one for the terminating character */ - char* ret = malloc(bstr->size * sizeof *ret); - strcpy(ret, (const char*) ret); - return ret; +char * +BOP_get_string(BOP_string *bstr) +{ + /* have to add one for the terminating character */ + char *ret = malloc(bstr->size * sizeof *ret); + + strcpy(ret, (const char *)ret); + return ret; } /* compares two BOP_strings for equality */ /* Compare bs1 and bs2, returning less than, equal to or - greater than zero if bs1 is lexicographically less than, - equal to or greater than bs2. */ -int BOP_strcmp2(BOP_string *bs1, BOP_string *bs2) { - char* s1 = bs1->string; - char* s2 = bs2->string; - size_t min_size = min(bs1->size,bs2->size); - if (min_size < STEP) { - int i; - for (i=0;i index) { - return ret; - } - BOP_ppr_begin(1); - int j; - read(index); - for (j=i;jstring; + char *s2 = bs2->string; + size_t min_size = min(bs1->size, bs2->size); + + if (min_size < STEP) { + int i; + + for (i = 0; i < min_size; i++) { + if (s1[i] != s2[i]) { + return ((unsigned char)s1[i]) - ((unsigned char)s2[i]); + } + } + return 0; + } + /* performs string comparison in parallel using BOP */ + int i; + int index = min_size + 1; + int ret = 0; + + for (i = 0; i < min_size; i += STEP) { + if (i > index) { + return ret; + } + BOP_ppr_begin(1); + int j; + + read(index); + for (j = i; j < min(i + STEP, min_size); j++) { + if (s1[j] != s2[j]) { + // BOP_ordered_begin(); + if (j < index) { + write(index); + index = j; + write(ret); + ret = ((unsigned char)s1[j]) - ((unsigned char)s2[j]); + } + break; + // BOP_ordered_end(); + } + } + BOP_ppr_end(1); + } + return ret; } /* compares two strings for equality */ /* Compare bs1 and bs2, returning less than, equal to or - greater than zero if bs1 is lexicographically less than, - equal to or greater than bs2. */ -int BOP_strcmp(char* p1, char* p2) { - - register const unsigned char *s1 = (const unsigned char *) p1; - register const unsigned char *s2 = (const unsigned char *) p2; - unsigned register char c1, c2; - - int equal = 1; - int ret; - int visited = 0; - long int ub = 0; - - do { - - s1 = p1 + ub; - s2 = p2 + ub; - unsigned const register char* itr = s1 + STEP; - BOP_ppr_begin(1); - do { - c1 = (unsigned char) *s1++; - c2 = (unsigned char) *s2++; - if (c1 == '\0') { - write(ret); - write(visited); - ret = c1 - c2; - visited = 1; - break; - } - } while ((c1 == c2) && (s1 < itr)); - if (c1 != c2) { - write(ret); - write(visited); - ret = c1 - c2; - visited = 1; - } - - bop_msg(1,"Distance from base pointer: %d",(long int) s1 - (long int) p1); - BOP_ppr_end(1); - read(visited); - if (visited) { - read(ret); - return ret; - } - - ub += STEP; - - } while (1); - - BOP_abort_spec("end of loop"); - - return c1 - c2; + * greater than zero if bs1 is lexicographically less than, + * equal to or greater than bs2. */ +int +BOP_strcmp(char *p1, char *p2) +{ + register const unsigned char *s1 = (const unsigned char *)p1; + register const unsigned char *s2 = (const unsigned char *)p2; + unsigned register char c1, c2; + + int equal = 1; + int ret; + int visited = 0; + long int ub = 0; + + do { + s1 = p1 + ub; + s2 = p2 + ub; + unsigned const register char *itr = s1 + STEP; + + BOP_ppr_begin(1); + do { + c1 = (unsigned char)*s1++; + c2 = (unsigned char)*s2++; + if (c1 == '\0') { + write(ret); + write(visited); + ret = c1 - c2; + visited = 1; + break; + } + } while ((c1 == c2) && (s1 < itr)); + if (c1 != c2) { + write(ret); + write(visited); + ret = c1 - c2; + visited = 1; + } + + bop_msg( + 1, "Distance from base pointer: %d", (long int)s1 - (long int)p1); + BOP_ppr_end(1); + read(visited); + if (visited) { + read(ret); + return ret; + } + + ub += STEP; + + } while (1); + + BOP_abort_spec("end of loop"); + + return c1 - c2; } /* reads a string in from a file */ -char* read_string(char* file_name) { - /* open file for reading */ - FILE* fStream = fopen(file_name, "r"); - if(fStream == NULL){fputs("File open error\n",stderr); exit(1);} +char * +read_string(char *file_name) +{ + /* open file for reading */ + FILE *fStream = fopen(file_name, "r"); + + if (fStream == NULL) { + fputs("File open error\n", stderr); + exit(1); + } + + /* get file size */ + fseek(fStream, 0, SEEK_END); + int fSize = ftell(fStream); + + rewind(fStream); - /* get file size */ - fseek(fStream, 0, SEEK_END); - int fSize = ftell(fStream); - rewind(fStream); + /* allocate memory */ + char *str = malloc(fSize * sizeof *str); - /* allocate memory */ - char* str = malloc(fSize * sizeof *str); - if(str == NULL){fputs("Memory error\n", stderr); exit(2);} + if (str == NULL) { + fputs("Memory error\n", stderr); + exit(2); + } - /* read sequence into buffer */ - size_t result = fread(str, 1, fSize - 1, fStream); - if(result != fSize - 1){fputs("Reading error\n", stderr); exit(3);} + /* read sequence into buffer */ + size_t result = fread(str, 1, fSize - 1, fStream); - /* terminate */ - fclose(fStream); + if (result != fSize - 1) { + fputs("Reading error\n", stderr); + exit(3); + } - return str; + /* terminate */ + fclose(fStream); + + return str; } /* test the functions defined in this file */ -int main(int argc, char *argv[]) { - char* a = read_string(argv[1]); - char* b = read_string(argv[2]); - - bop_msg(1,"before string compare",0); - - if (argv[3][0] == 'b') { - printf("%d\n",BOP_strcmp(a,b)); - } else { - printf("%d\n",strcmp(a,b)); - } - return 0; +int +main(int argc, char *argv[]) +{ + char *a = read_string(argv[1]); + char *b = read_string(argv[2]); + + bop_msg(1, "before string compare", 0); + + if (argv[3][0] == 'b') { + printf("%d\n", BOP_strcmp(a, b)); + } else { + printf("%d\n", strcmp(a, b)); + } + return 0; } diff --git a/tests/str/strsub/strsub.c b/tests/str/strsub/strsub.c index 9b0dc17..c2499cd 100644 --- a/tests/str/strsub/strsub.c +++ b/tests/str/strsub/strsub.c @@ -1,276 +1,321 @@ +#include +#include #include #include -#include #include -#include #include "bop_api.h" -//6/20/2011 -//parallel string subsitution +// 6/20/2011 +// parallel string subsitution -int avg_subs = 3; -int blocks = 2; +int avg_subs = 3; +int blocks = 2; int step_size = 10000000; #define read(x) BOP_use(&x, sizeof x) #define write(x) BOP_promise(&x, sizeof x) -char* strsub_original(char* orig_begin, char* sub_begin, char* replace_begin) { +char * +strsub_original(char *orig_begin, char *sub_begin, char *replace_begin) +{ + char *orig = orig_begin; + int sub_len = 0; + bool sub_set = false; + char *sub = sub_begin; + int replace_len = 0; + bool replace_set = false; + char *replace = replace_begin; + int orig_len = 0; + bool orig_set = false; + + // sets orig_len, sub_len, and replace_len + while (*orig || *replace || *sub) { + if (!orig_set) { + if (!*orig) { + orig_set = true; + } else { + *orig++; + orig_len++; + } + } + if (!replace_set) { + if (!*replace) { + replace_set = true; + } else { + *replace++; + replace_len++; + } + } + if (!sub_set) { + if (!*sub) { + sub_set = true; + } else { + *sub++; + sub_len++; + } + } + } + if (sub_len < 1) { + return orig_begin; + } + // searches through the original string and replaces what it finds + sub = sub_begin, replace = replace_begin; + orig = malloc((orig_len + 1) * sizeof *orig); + strcpy(orig, orig_begin); + int i, j; + int count = 0; + + for (i = 0; i < orig_len; i++) { + if (orig[i] == sub[count]) { + count++; + } else if (orig[i] == sub[count - 1]) { + count = 1; + } else { + count = 0; + } + if (count == sub_len) { + if (sub_len == replace_len) { + int itr_start = i - replace_len + 1; + int itr_end = i + 1; + int replace_itr = 0; - char* orig = orig_begin; int sub_len = 0; bool sub_set = false; - char* sub = sub_begin; int replace_len = 0; bool replace_set = false; - char* replace = replace_begin; int orig_len = 0; bool orig_set = false; + for (j = itr_start; j < itr_end; j++) { + orig[j] = replace[replace_itr]; + replace_itr++; + } + i = itr_start - 1; + } else { + int orig_temp_len = orig_len + replace_len - sub_len; + char *orig_temp = + malloc((orig_temp_len + 1) * sizeof *orig_temp); + int itr_start = i - sub_len + 1; + int itr_end = itr_start + replace_len; - //sets orig_len, sub_len, and replace_len - while (*orig || *replace || *sub) { - if (!orig_set) { - if (!*orig) { - orig_set = true; - } else { - *orig++; - orig_len++; - } - } - if (!replace_set) { - if (!*replace) { - replace_set = true; - } else { - *replace++; - replace_len++; - } - } - if (!sub_set) { - if (!*sub) { - sub_set = true; - } else { - *sub++; - sub_len++; - } - } - } - if (sub_len < 1) { - return orig_begin; - } + for (j = 0; j < itr_start; j++) { + orig_temp[j] = orig[j]; + } + int replace_itr = 0; - //searches through the original string and replaces what it finds - sub = sub_begin, replace = replace_begin; - orig = malloc((orig_len + 1) * sizeof *orig); - strcpy(orig, orig_begin); - int i,j; - int count = 0; - for (i=0;i -#include #include +#include #include "bop_api.h" #define STEP 8000000 -#define min(a,b) ((a < b) ? a : b) +#define min(a, b) ((a < b) ? a : b) #define read(x) BOP_use(&x, sizeof x) #define write(x) BOP_promise(&x, sizeof x) @@ -14,279 +14,343 @@ /* A BOP_String contains an array of strings (char pointers) */ #define SUBSTRING_SIZE 100000 -typedef struct -{ - char ** string; +typedef struct { + char **string; } BOP_string; /* creates a BOP_string struct from a char array * the BOP_string contains an array of char pointers * the last pointer is a null pointer, the rest of * the pointers contain substrings that make up the string */ -BOP_string* BOP_create_string(char* str) { - BOP_string* ret = malloc(sizeof *ret); - size_t len = strlen(str); - /* If empty string, return an array with one element: - * a null pointer */ - if (len == 0) { - ret->string = malloc(sizeof(char*)); - ret->string[0] = NULL; - } - /* Otherwise create an array of char pointers - * and loop through the string giving each pointer - * SUBSTRING_SIZE chars */ - int num = len/SUBSTRING_SIZE + 2; - ret->string = malloc(num * sizeof(char*)); - /* Set the end to NULL */ - ret->string[num-1] = NULL; - /* Allocate the first substring */ - ret->string[0] = malloc((SUBSTRING_SIZE + 1) * sizeof(char)); - int count = 0; - int substring = 0; - /* Copy chars from str to substring/allocate new substrings - * when requried */ - do { - if (count == SUBSTRING_SIZE) { - ret->string[substring++][count] = '\0'; - count=0; - ret->string[substring] = malloc((SUBSTRING_SIZE + 1) * sizeof(char)); - } - ret->string[substring][count] = *str; - count++; - } while (*(str++) != '\0'); - ret->string[substring][count] = '\0'; - return ret; +BOP_string * +BOP_create_string(char *str) +{ + BOP_string *ret = malloc(sizeof *ret); + size_t len = strlen(str); + + /* If empty string, return an array with one element: + * a null pointer */ + if (len == 0) { + ret->string = malloc(sizeof(char *)); + ret->string[0] = NULL; + } + /* Otherwise create an array of char pointers + * and loop through the string giving each pointer + * SUBSTRING_SIZE chars */ + int num = len / SUBSTRING_SIZE + 2; + + ret->string = malloc(num * sizeof(char *)); + /* Set the end to NULL */ + ret->string[num - 1] = NULL; + /* Allocate the first substring */ + ret->string[0] = malloc((SUBSTRING_SIZE + 1) * sizeof(char)); + int count = 0; + int substring = 0; + + /* Copy chars from str to substring/allocate new substrings + * when requried */ + do { + if (count == SUBSTRING_SIZE) { + ret->string[substring++][count] = '\0'; + count = 0; + ret->string[substring] = + malloc((SUBSTRING_SIZE + 1) * sizeof(char)); + } + ret->string[substring][count] = *str; + count++; + } while (*(str++) != '\0'); + ret->string[substring][count] = '\0'; + return ret; } /* Prints a BOP_string to stdout */ -void BOP_print_string(BOP_string* str) { - int i = 0; - while (str->string[i] != NULL) { - printf("%s",str->string[i]); - i++; - } - printf("\n"); +void +BOP_print_string(BOP_string *str) +{ + int i = 0; + + while (str->string[i] != NULL) { + printf("%s", str->string[i]); + i++; + } + printf("\n"); } /* Finds all instances of find and replaces them with replace */ -BOP_string* BOP_replace(BOP_string* original, char* find, char* replace) { - int i = 0; - int len = strlen(find); - int len_replace = strlen(replace); - while (original->string[i] != NULL) { - BOP_ppr_begin(1); - int j = 0; - /* count is the number of characters that match */ - int count = 0; - int num_matches = 0; - /* size is the number of chars in the array */ - int size = 0; - while (original->string[i][j] != '\0') { - size++; - if (original->string[i][j] == find[count]) { - count++; - if (count == len) { - count = 0; - if (len == len_replace) { - int k; - int h = 0; - for (k=j-len+1;kstring[i][k] = replace[h]; - h++; - } - } else { - num_matches++; - } - } - } else { - count = 0; - } - j++; - } - BOP_use(original->string[i], (size + 1) * sizeof(char)); - /* If at least one instance of find was found in the substring */ - if (num_matches != 0 || count != 0) { - /* First, we have to check to see if there is a match that is - * split between two substrings */ - int first_copy = false; - if (count != 0) { - int f_count = count; - if (original->string[i+1] != NULL) { - int ii = 0; - int leftover = 0; - while (original->string[i+1][ii] == find[f_count]) { - f_count++; - ii++; - if (f_count == 0) { - leftover = 0; - break; - } else if (f_count == len) { - leftover = ii; - break; - } - } - if (leftover > 0) { - size += len_replace - count; - first_copy = true; - int jj = 0; - /* Shifts the second substring over by leftover */ - BOP_promise(original->string[i+1],strlen(original->string[i+1]+1) * sizeof(char)); - while ((original->string[i+1][jj] = original->string[i+1][jj+leftover]) != '\0') { - jj++; - } - } - } - } - /* This piece of code reallocates the block if the size increased */ - int jump_size = len_replace - len; - int new_size = size + (num_matches * jump_size); - int old_substring_size = size/SUBSTRING_SIZE + 1; - int new_substring_size = new_size/SUBSTRING_SIZE + 1; - char* ret = original->string[i]; - if (new_substring_size > old_substring_size) { - ret = malloc((new_substring_size * SUBSTRING_SIZE + 1) * sizeof(char)); - } - - /* If a match was found between substrings, it gets added to the tail of - * the first substring */ - if (first_copy) { - int ii; - int jj = size-1; - ret[size] = '\0'; - for (ii = len_replace-1;ii>=0;ii--) { - ret[jj] = replace[ii]; - jj--; - } - } - - /* Next, the substring is iterated through and find/replace is performed. - * When find/replace occurs in this code, it ends up iterating through the - * string twice, once to count the number of finds, and once to actually do - * the replaces. If this were not the case, then some kind of data structure - * would be needed to keep track of these finds. But then, all characters after - * a replace would still need to be iterated over. So overall, I don't think - * any speed would be gained by doing that and it would add some complexity */ - - if (jump_size > 0 && num_matches != 0) { - int r_count = len; - int jump = num_matches * jump_size; - /* The search is performed backwards if new the substring is larger than the - * original substring. This makes it eacier and more efficient */ - for (;j>=0;j--) { - if (original->string[i][j] == find[r_count-1]) { - r_count--; - if (r_count == 0) { - int h; - int k = j+len+jump-1; - for (h = len_replace-1;h>=0;h--) { - ret[k] = replace[h]; - k--; - } - jump -= jump_size; - r_count = len; - if (jump == 0 && new_substring_size < old_substring_size) { - break; - } - } else { - ret[j+jump] = original->string[i][j]; - } - } else { - r_count = len; - ret[j+jump] = original->string[i][j]; - } - } - if (new_substring_size > old_substring_size) { - free(original->string[i]); - original->string[i] = ret; - } - } else if (jump_size < 0 && num_matches != 0) { - /* The search is performed forwards otherwise */ - int jump = 0; - char current = original->string[i][0]; - int f_count = 0; - for (j=0;;j++) { - ret[j] = ret[j-jump]; - if (ret[j] == '\0') { - break; - } - if (ret[j] == find[f_count]) { - f_count++; - if (f_count == len) { - int k = j - len + 1; - int h; - for (h=0;hstring[i]); - BOP_promise(original->string[i], ((new_substring_size * SUBSTRING_SIZE + 1) * sizeof(char))); - num_matches = 0; - } - BOP_ppr_end(1); - i++; - } - return original; +BOP_string * +BOP_replace(BOP_string *original, char *find, char *replace) +{ + int i = 0; + int len = strlen(find); + int len_replace = strlen(replace); + + while (original->string[i] != NULL) { + BOP_ppr_begin(1); + int j = 0; + + /* count is the number of characters that match */ + int count = 0; + int num_matches = 0; + + /* size is the number of chars in the array */ + int size = 0; + + while (original->string[i][j] != '\0') { + size++; + if (original->string[i][j] == find[count]) { + count++; + if (count == len) { + count = 0; + if (len == len_replace) { + int k; + int h = 0; + + for (k = j - len + 1; k < j + 1; k++) { + original->string[i][k] = replace[h]; + h++; + } + } else { + num_matches++; + } + } + } else { + count = 0; + } + j++; + } + BOP_use(original->string[i], (size + 1) * sizeof(char)); + /* If at least one instance of find was found in the substring */ + if (num_matches != 0 || count != 0) { + /* First, we have to check to see if there is a match that is + * split between two substrings */ + int first_copy = false; + + if (count != 0) { + int f_count = count; + + if (original->string[i + 1] != NULL) { + int ii = 0; + int leftover = 0; + + while (original->string[i + 1][ii] == find[f_count]) { + f_count++; + ii++; + if (f_count == 0) { + leftover = 0; + break; + } else if (f_count == len) { + leftover = ii; + break; + } + } + if (leftover > 0) { + size += len_replace - count; + first_copy = true; + int jj = 0; + + /* Shifts the second substring over by leftover */ + BOP_promise(original->string[i + 1], + strlen(original->string[i + 1] + 1) * + sizeof(char)); + while ((original->string[i + 1][jj] = + original->string[i + 1][jj + leftover]) != + '\0') { + jj++; + } + } + } + } + /* This piece of code reallocates the block if the size increased + */ + int jump_size = len_replace - len; + int new_size = size + (num_matches * jump_size); + int old_substring_size = size / SUBSTRING_SIZE + 1; + int new_substring_size = new_size / SUBSTRING_SIZE + 1; + char *ret = original->string[i]; + + if (new_substring_size > old_substring_size) { + ret = malloc((new_substring_size * SUBSTRING_SIZE + 1) * + sizeof(char)); + } + + /* If a match was found between substrings, it gets added to the + * tail of + * the first substring */ + if (first_copy) { + int ii; + int jj = size - 1; + + ret[size] = '\0'; + for (ii = len_replace - 1; ii >= 0; ii--) { + ret[jj] = replace[ii]; + jj--; + } + } + + /* Next, the substring is iterated through and find/replace is + * performed. + * When find/replace occurs in this code, it ends up iterating + * through the + * string twice, once to count the number of finds, and once to + * actually do + * the replaces. If this were not the case, then some kind of data + * structure + * would be needed to keep track of these finds. But then, all + * characters after + * a replace would still need to be iterated over. So overall, I + * don't think + * any speed would be gained by doing that and it would add some + * complexity */ + + if (jump_size > 0 && num_matches != 0) { + int r_count = len; + int jump = num_matches * jump_size; + + /* The search is performed backwards if new the substring is + * larger than the + * original substring. This makes it eacier and more efficient + */ + for (; j >= 0; j--) { + if (original->string[i][j] == find[r_count - 1]) { + r_count--; + if (r_count == 0) { + int h; + int k = j + len + jump - 1; + + for (h = len_replace - 1; h >= 0; h--) { + ret[k] = replace[h]; + k--; + } + jump -= jump_size; + r_count = len; + if (jump == 0 && + new_substring_size < old_substring_size) { + break; + } + } else { + ret[j + jump] = original->string[i][j]; + } + } else { + r_count = len; + ret[j + jump] = original->string[i][j]; + } + } + if (new_substring_size > old_substring_size) { + free(original->string[i]); + original->string[i] = ret; + } + } else if (jump_size < 0 && num_matches != 0) { + /* The search is performed forwards otherwise */ + int jump = 0; + char current = original->string[i][0]; + int f_count = 0; + + for (j = 0;; j++) { + ret[j] = ret[j - jump]; + if (ret[j] == '\0') { + break; + } + if (ret[j] == find[f_count]) { + f_count++; + if (f_count == len) { + int k = j - len + 1; + int h; + + for (h = 0; h < len_replace; h++) { + ret[k] = replace[h]; + k++; + } + jump += jump_size; + f_count = 0; + j = j - len + 1; + } + } else { + f_count = 0; + } + } + } + write(original->string[i]); + BOP_promise( + original->string[i], + ((new_substring_size * SUBSTRING_SIZE + 1) * sizeof(char))); + num_matches = 0; + } + BOP_ppr_end(1); + i++; + } + return original; } /* returns a copy of the string as a char array */ -char* BOP_get_string(BOP_string* bstr) { - return NULL; +char * +BOP_get_string(BOP_string *bstr) +{ + return NULL; } /* reads a string in from a file */ -char* read_string(char* file_name) { - /* open file for reading */ - FILE* fStream = fopen(file_name, "r"); - if(fStream == NULL){fputs("File open error\n",stderr); exit(1);} +char * +read_string(char *file_name) +{ + /* open file for reading */ + FILE *fStream = fopen(file_name, "r"); - /* get file size */ - fseek(fStream, 0, SEEK_END); - int fSize = ftell(fStream); - rewind(fStream); + if (fStream == NULL) { + fputs("File open error\n", stderr); + exit(1); + } - /* allocate memory */ - char* str = malloc(fSize * sizeof *str); - if(str == NULL){fputs("Memory error\n", stderr); exit(2);} + /* get file size */ + fseek(fStream, 0, SEEK_END); + int fSize = ftell(fStream); - /* read sequence into buffer */ - size_t result = fread(str, 1, fSize - 1, fStream); - if(result != fSize - 1){fputs("Reading error\n", stderr); exit(3);} + rewind(fStream); - /* terminate */ - fclose(fStream); + /* allocate memory */ + char *str = malloc(fSize * sizeof *str); - return str; + if (str == NULL) { + fputs("Memory error\n", stderr); + exit(2); + } + + /* read sequence into buffer */ + size_t result = fread(str, 1, fSize - 1, fStream); + + if (result != fSize - 1) { + fputs("Reading error\n", stderr); + exit(3); + } + + /* terminate */ + fclose(fStream); + + return str; } /* test the functions defined in this file */ -int main(int argc, char *argv[]) { - char* a = read_string(argv[1]); - - BOP_string* a2 = BOP_create_string(a); - - BOP_replace(a2,argv[2],argv[3]); - BOP_print_string(a2); -return 0; - /*if (argv[3][0] == 'b') { - printf("%d\n",BOP_strcmp(a,b)); - } else { - printf("%d\n",strcmp(a,b)); - }*/ - - //BOP_string* a = BOP_create_string(read_string(argv[1])); - //BOP_print_string(a); - - /*BOP_string* b = BOP_create_string("My name is Inigo Montoya. You killed my father. Prepare to name."); - BOP_print_string(b); - BOP_replace(b,"name","q"); - BOP_print_string(b);*/ +int +main(int argc, char *argv[]) +{ + char *a = read_string(argv[1]); + + BOP_string *a2 = BOP_create_string(a); + + BOP_replace(a2, argv[2], argv[3]); + BOP_print_string(a2); + return 0; + /*if (argv[3][0] == 'b') { + * printf("%d\n",BOP_strcmp(a,b)); + * } else { + * printf("%d\n",strcmp(a,b)); + * } */ + + // BOP_string* a = BOP_create_string(read_string(argv[1])); + // BOP_print_string(a); + + /*BOP_string* b = BOP_create_string("My name is Inigo Montoya. You killed + * my father. Prepare to name."); + * BOP_print_string(b); + * BOP_replace(b,"name","q"); + * BOP_print_string(b); */ } diff --git a/tests/unit_tests/ary_bitmap_tests.c b/tests/unit_tests/ary_bitmap_tests.c index 0c6bb4d..3de1a70 100644 --- a/tests/unit_tests/ary_bitmap_tests.c +++ b/tests/unit_tests/ary_bitmap_tests.c @@ -1,51 +1,56 @@ -#include #include -#include #include +#include #include +#include #include extern map_t read_map, write_map; extern bop_port_t bop_merge_port; -void test1( void ) { - BOP_set_group_size( 2 ); - bop_merge_port.ppr_group_init( ); - spec_order = 0; - task_status = MAIN; - ppr_pos = PPR; - bop_merge_port.ppr_task_init( ); - - unsigned len = 100, i; - void *ptrs = ary_malloc_with_map( len, sizeof( void * ) ); - for ( i=0; i #include #include -#include "bop_api.h" -#include "bop_ports.h" extern bop_port_t bop_io_port; /* Print a number apparently from a given process */ -void do_print( int n, task_status_t status, int order ) { - static count = 0; - - /* Sanity test status and spec order */ - switch (status) { - case UNDY: assert(order == -1); break; - case MAIN: assert(order == 0); break; - case SPEC: assert(order > 0); break; - default: assert(0); - } - - task_status = status; - spec_order = order; - - BOP_printf( - "stdout: %d, status %d, spec order %d, count %d.\n", - n, task_status, spec_order, count++); - - /* Not yet implemented - BOP_fprintf( stderr, - "stderr: %d, status %d, spec order %d, count %d.\n", - n, task_status, spec_order, count++); +void +do_print(int n, task_status_t status, int order) +{ + static count = 0; + + /* Sanity test status and spec order */ + switch (status) { + case UNDY: + assert(order == -1); + break; + case MAIN: + assert(order == 0); + break; + case SPEC: + assert(order > 0); + break; + default: + assert(0); + } + + task_status = status; + spec_order = order; + + BOP_printf("stdout: %d, status %d, spec order %d, count %d.\n", + n, + task_status, + spec_order, + count++); + + /* Not yet implemented + * BOP_fprintf( stderr, + * "stderr: %d, status %d, spec order %d, count %d.\n", + * n, task_status, spec_order, count++); */ } /* Print one thing in N PPRs, with a particular side succeeding */ -void run_test( task_status_t status, int group_size) { - assert(status != MAIN); /* Main shouldn't win the race. */ - - /* Initialization */ - BOP_set_group_size( group_size ); - bop_io_port.ppr_group_init( ); - - /* First PPR prints in MAIN */ - do_print( 0, MAIN, 0 ); - - /* Other PPRs print in both a SPEC and UNDY */ - int i; - for (i = 1; i < group_size; i++) { - do_print( i, SPEC, i ); - do_print( i, UNDY, -1 ); - } - - /* Trigger a "win" */ - switch (status) { - case UNDY: - bop_io_port.undy_succ_fini(); - break; - - case SPEC: - bop_io_port.task_group_succ_fini(); - break; - - default: - assert(0); /* Huh? */ - } +void +run_test(task_status_t status, int group_size) +{ + assert(status != MAIN); /* Main shouldn't win the race. */ + + /* Initialization */ + BOP_set_group_size(group_size); + bop_io_port.ppr_group_init(); + + /* First PPR prints in MAIN */ + do_print(0, MAIN, 0); + + /* Other PPRs print in both a SPEC and UNDY */ + int i; + + for (i = 1; i < group_size; i++) { + do_print(i, SPEC, i); + do_print(i, UNDY, -1); + } + + /* Trigger a "win" */ + switch (status) { + case UNDY: + bop_io_port.undy_succ_fini(); + break; + + case SPEC: + bop_io_port.task_group_succ_fini(); + break; + + default: + assert(0); /* Huh? */ + } } -int main( ) { - run_test( SPEC, 3 ); - run_test( UNDY, 3 ); +int +main() +{ + run_test(SPEC, 3); + run_test(UNDY, 3); - printf("The tests end.\n"); - abort( ); + printf("The tests end.\n"); + abort(); } diff --git a/tests/unit_tests/bop_malloc_tests.c b/tests/unit_tests/bop_malloc_tests.c index af8c208..69fc79a 100644 --- a/tests/unit_tests/bop_malloc_tests.c +++ b/tests/unit_tests/bop_malloc_tests.c @@ -1,319 +1,345 @@ -#include /* for NULL */ -#include "bop_api.h" /* for PAGESIZEX */ +#include "bop_api.h" /* for PAGESIZEX */ #include "bop_map.h" #include "bop_ports.h" #include "external/malloc.h" +#include /* for NULL */ -static void two_tasks_test(void); +static void +two_tasks_test(void); extern bop_port_t bop_alloc_port; extern bop_port_t bop_merge_port; -int main( ) +int +main() { - printf("The tests begin: \n"); - two_tasks_test( ); - task_status = UNDY; - printf("The tests end! \n"); - return 0; /* must return 0 for rake test to succeed */ + printf("The tests begin: \n"); + two_tasks_test(); + task_status = UNDY; + printf("The tests end! \n"); + return 0; /* must return 0 for rake test to succeed */ } -static void init_main(void); -static void init_undy(void); -static void init_spec(int); +static void +init_main(void); +static void +init_undy(void); +static void +init_spec(int); -static void task_commit(void); -static void group_commit(void); +static void +task_commit(void); +static void +group_commit(void); -static void two_tasks_test( void ) +static void +two_tasks_test(void) { - BOP_set_group_size( 2 ); - char *a, *b ; - a = NULL; - b = NULL; - - printf("\tcase 1\n"); - printf("\t1\n"); - /* case 1 */ - /** - ppr1 ppr2 - a = malloc b = malloc - */ - - printf("\t2\n"); - init_main(); - - printf("\t3\n"); - a = malloc(10); - BOP_record_write( &a, sizeof( char * ) ); - - printf("\t4\n"); - *a = 'c'; -// BOP_record_write( a, sizeof( char ) ); - *(a+1) = 'd'; -// BOP_record_write( a+1, sizeof( char ) ); - - task_commit(); - - printf("\t5\n"); - a = NULL; - init_spec(1); - b = malloc(20); - BOP_record_write( &b, sizeof( char * ) ); - - printf("\t6\n"); - *b = '1'; -// BOP_record_write( b, sizeof( char ) ); - *(b+1) = '2'; -// BOP_record_write( b+1, sizeof( char ) ); - - task_commit(); - printf("\t7\n"); - - a = NULL; - b = NULL; - group_commit(); - printf("\t8\n"); - printf("a : addr [%p], value %c\n", a, *a ); - printf("b : addr [%p], value %c\n", b, *b ); - printf("\t9\n"); - - printf("\tcase 2\n"); - /* case 2 */ - /** - ppr1 ppr2 - a = malloc b = malloc - free(a) - a = NULL - */ - - printf("\t2\n"); - init_main(); - - printf("\t3\n"); - a = malloc(10); - BOP_record_write( &a, sizeof( char * ) ); - - printf("\t4\n"); - *a = 'c'; - *(a+1) = 'd'; - free(a); - a = NULL; - BOP_record_write( &a, sizeof( char * ) ); - - task_commit(); - - printf("\t5\n"); - a = NULL; - init_spec(1); - b = malloc(20); - BOP_record_write( &b, sizeof( char * ) ); - - printf("\t6\n"); - *b = '1'; - *(b+1) = '2'; - - task_commit(); - printf("\t7\n"); - - a = NULL; - b = NULL; - group_commit(); - printf("\t8\n"); - printf("a : addr [%p] \n", a); /* should be NULL */ - printf("b : addr [%p], value %c\n", b, *b ); - printf("\t9\n"); - - printf("\tcase 3\n"); - /* case 3 */ - /** - ppr1 ppr2 - a = malloc - free(a) - a = NULL - */ - printf("a_addr %p, b_addr %p\n", &a, &b); - - printf("\t2\n"); - init_main(); - printf("\t3\n"); - a = malloc(10); - BOP_record_write( &a, sizeof( char * ) ); - - printf("\t4\n"); - *a = 'c'; - *(a+1) = 'd'; - - task_commit(); - - printf("\t5\n"); -// a = NULL; - init_spec(1); -// b = malloc(20); -// BOP_record_write( &b, sizeof( char * ) ); - - printf("\t6\n"); -// *b = '1'; -// *(b+1) = '2'; - free(a); - a = NULL; - BOP_record_write( &a, sizeof( char * ) ); - - task_commit(); - printf("\t7\n"); - - a = NULL; - b = NULL; - group_commit(); - printf("\t8\n"); - printf("a : addr [%p]\n", a); -// printf("b : addr [%p], value %c\n", b, *b ); - printf("\t9\n"); - - printf("\tcase 4\n"); - /* case 4 */ - /** - ppr1 ppr2 - a = malloc b = malloc - ------------------------------------------ commit - ppr3 ppr4 ppr5 - c = malloc - free(b) free(a) - ------------------------------------------ commit - */ - - printf("a_addr %p, b_addr %p\n", &a, &b); - - printf("\t2\n"); - init_main(); - - printf("\t3\n"); - a = malloc(10); - BOP_record_write( &a, sizeof( char * ) ); - - printf("\t4\n"); - *a = 'c'; - *(a+1) = 'd'; - - task_commit(); - - printf("\t5\n"); - a = NULL; - init_spec(1); - - b = malloc(20); - BOP_record_write( &b, sizeof( char * ) ); - - printf("\t6\n"); - *b = '1'; - *(b+1) = '2'; - - task_commit(); - printf("\t7\n"); - - a = NULL; - b = NULL; - group_commit(); - printf("\t8\n"); - printf("a : addr [%p], value %c\n", a, *a); - printf("b : addr [%p], value %c\n", b, *b); - printf("\t9\n"); - - char * tmp_a = a; - char * tmp_b = b; - - //----------------------------- commit once - task_status = SEQ; - BOP_set_group_size( 3 ); - - ppr_pos = PPR; - char *c, *d; - c = NULL; - d = NULL; - - printf("\t10\n"); - init_main(); - - printf("\t11\n"); - c = malloc(30); - BOP_record_write( &c, sizeof( char * ) ); - - printf("\t12\n"); - *c = 'm'; - *(c+1) = 'n'; - - task_commit(); - - printf("\t13\n"); - c = NULL; - init_spec(1); - - free(b); - b = NULL; - BOP_record_write( &b, sizeof( char * ) ); - - task_commit(); - - printf("\t14\n"); - - b = tmp_b; - c = NULL; - init_spec(2); - - free(a); - a = NULL; - BOP_record_write( &a, sizeof( char * ) ); - - task_commit(); - - printf("\t15\n"); + BOP_set_group_size(2); + char *a, *b; + + a = NULL; + b = NULL; + + printf("\tcase 1\n"); + printf("\t1\n"); + /* case 1 */ + + /** + ppr1 ppr2 + a = malloc b = malloc + */ + + printf("\t2\n"); + init_main(); + + printf("\t3\n"); + a = malloc(10); + BOP_record_write(&a, sizeof(char *)); + + printf("\t4\n"); + *a = 'c'; + // BOP_record_write( a, sizeof( char ) ); + *(a + 1) = 'd'; + // BOP_record_write( a+1, sizeof( char ) ); + + task_commit(); + + printf("\t5\n"); + a = NULL; + init_spec(1); + b = malloc(20); + BOP_record_write(&b, sizeof(char *)); + + printf("\t6\n"); + *b = '1'; + // BOP_record_write( b, sizeof( char ) ); + *(b + 1) = '2'; + // BOP_record_write( b+1, sizeof( char ) ); + + task_commit(); + printf("\t7\n"); + + a = NULL; + b = NULL; + group_commit(); + printf("\t8\n"); + printf("a : addr [%p], value %c\n", a, *a); + printf("b : addr [%p], value %c\n", b, *b); + printf("\t9\n"); + + printf("\tcase 2\n"); + /* case 2 */ + + /** + ppr1 ppr2 + a = malloc b = malloc + free(a) + a = NULL + */ + + printf("\t2\n"); + init_main(); + + printf("\t3\n"); + a = malloc(10); + BOP_record_write(&a, sizeof(char *)); + + printf("\t4\n"); + *a = 'c'; + *(a + 1) = 'd'; + free(a); + a = NULL; + BOP_record_write(&a, sizeof(char *)); + + task_commit(); + + printf("\t5\n"); + a = NULL; + init_spec(1); + b = malloc(20); + BOP_record_write(&b, sizeof(char *)); + + printf("\t6\n"); + *b = '1'; + *(b + 1) = '2'; + + task_commit(); + printf("\t7\n"); + + a = NULL; + b = NULL; + group_commit(); + printf("\t8\n"); + printf("a : addr [%p] \n", a); /* should be NULL */ + printf("b : addr [%p], value %c\n", b, *b); + printf("\t9\n"); + + printf("\tcase 3\n"); + /* case 3 */ + + /** + ppr1 ppr2 + a = malloc + free(a) + a = NULL + */ + printf("a_addr %p, b_addr %p\n", &a, &b); + + printf("\t2\n"); + init_main(); + printf("\t3\n"); + a = malloc(10); + BOP_record_write(&a, sizeof(char *)); + + printf("\t4\n"); + *a = 'c'; + *(a + 1) = 'd'; + + task_commit(); + + printf("\t5\n"); + // a = NULL; + init_spec(1); + // b = malloc(20); + // BOP_record_write( &b, sizeof( char * ) ); + + printf("\t6\n"); + // *b = '1'; + // *(b+1) = '2'; + free(a); + a = NULL; + BOP_record_write(&a, sizeof(char *)); + + task_commit(); + printf("\t7\n"); + + a = NULL; + b = NULL; + group_commit(); + printf("\t8\n"); + printf("a : addr [%p]\n", a); + // printf("b : addr [%p], value %c\n", b, *b ); + printf("\t9\n"); + + printf("\tcase 4\n"); + /* case 4 */ + + /** + ppr1 ppr2 + a = malloc b = malloc + ------------------------------------------ commit + ppr3 ppr4 ppr5 + c = malloc + free(b) free(a) + ------------------------------------------ commit + */ + + printf("a_addr %p, b_addr %p\n", &a, &b); + + printf("\t2\n"); + init_main(); + + printf("\t3\n"); + a = malloc(10); + BOP_record_write(&a, sizeof(char *)); + + printf("\t4\n"); + *a = 'c'; + *(a + 1) = 'd'; + + task_commit(); + + printf("\t5\n"); + a = NULL; + init_spec(1); + + b = malloc(20); + BOP_record_write(&b, sizeof(char *)); + + printf("\t6\n"); + *b = '1'; + *(b + 1) = '2'; + + task_commit(); + printf("\t7\n"); + + a = NULL; + b = NULL; + group_commit(); + printf("\t8\n"); + printf("a : addr [%p], value %c\n", a, *a); + printf("b : addr [%p], value %c\n", b, *b); + printf("\t9\n"); + + char *tmp_a = a; + char *tmp_b = b; + + //----------------------------- commit once + task_status = SEQ; + BOP_set_group_size(3); + + ppr_pos = PPR; + char *c, *d; + + c = NULL; + d = NULL; + + printf("\t10\n"); + init_main(); + + printf("\t11\n"); + c = malloc(30); + BOP_record_write(&c, sizeof(char *)); - a = tmp_a ; - b = tmp_b ; - c = NULL; - d = NULL; - group_commit(); - printf("\t16\n"); - printf("a : addr [%p]\n", a); - printf("b : addr [%p]\n", b); - printf("c : addr [%p], value %c\n", c, *c); - printf("\t17\n"); + printf("\t12\n"); + *c = 'm'; + *(c + 1) = 'n'; + + task_commit(); + + printf("\t13\n"); + c = NULL; + init_spec(1); + + free(b); + b = NULL; + BOP_record_write(&b, sizeof(char *)); + + task_commit(); + + printf("\t14\n"); + + b = tmp_b; + c = NULL; + init_spec(2); + + free(a); + a = NULL; + BOP_record_write(&a, sizeof(char *)); + + task_commit(); + + printf("\t15\n"); + + a = tmp_a; + b = tmp_b; + c = NULL; + d = NULL; + group_commit(); + printf("\t16\n"); + printf("a : addr [%p]\n", a); + printf("b : addr [%p]\n", b); + printf("c : addr [%p], value %c\n", c, *c); + printf("\t17\n"); } extern int ppr_index; -static void task_init( task_status_t status, int order ) { - task_status = status; - spec_order = order; - ppr_pos = PPR; - ppr_index++; - bop_alloc_port.ppr_task_init(); - bop_merge_port.ppr_task_init(); +static void +task_init(task_status_t status, int order) +{ + task_status = status; + spec_order = order; + ppr_pos = PPR; + ppr_index++; + bop_alloc_port.ppr_task_init(); + bop_merge_port.ppr_task_init(); } -static void init_main( void ) { - bop_alloc_port.ppr_group_init(); - bop_merge_port.ppr_group_init(); - task_init(MAIN, 0); +static void +init_main(void) +{ + bop_alloc_port.ppr_group_init(); + bop_merge_port.ppr_group_init(); + task_init(MAIN, 0); } -static void init_undy( void ) { - task_init(UNDY, -1); +static void +init_undy(void) +{ + task_init(UNDY, -1); } -static void init_spec( int order ) { - task_init(SPEC, order); +static void +init_spec(int order) +{ + task_init(SPEC, order); } -static void task_commit( void ) { - /* Nothing to do for alloc port, these functions undefined */ - assert( bop_merge_port.ppr_check_correctness() ); - bop_merge_port.data_commit(); - ppr_pos = GAP; +static void +task_commit(void) +{ + /* Nothing to do for alloc port, these functions undefined */ + assert(bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + ppr_pos = GAP; } -static void group_commit( void ) { - bop_alloc_port.task_group_commit(); - bop_merge_port.task_group_commit(); - task_status = SEQ; +static void +group_commit(void) +{ + bop_alloc_port.task_group_commit(); + bop_merge_port.task_group_commit(); + task_status = SEQ; } diff --git a/tests/unit_tests/bop_merge_tests.c b/tests/unit_tests/bop_merge_tests.c index 904a3b5..3c67808 100644 --- a/tests/unit_tests/bop_merge_tests.c +++ b/tests/unit_tests/bop_merge_tests.c @@ -1,135 +1,139 @@ -#include /* for NULL */ -#include /* for PAGESIZEX */ +#include /* for PAGESIZEX */ #include #include +#include /* for NULL */ -static void two_tasks_test(void); +static void +two_tasks_test(void); extern map_t *read_map, *write_map; extern bop_port_t bop_merge_port; -int main( ) { +int +main() +{ + two_tasks_test(); - two_tasks_test( ); - - task_status = UNDY; - printf("The tests end.\n"); - return 0; /* must return 0 for rake test to succeed */ + task_status = UNDY; + printf("The tests end.\n"); + return 0; /* must return 0 for rake test to succeed */ } -static void ppr_access( void* addr, size_t size, int is_read ) { - if ( is_read ) - BOP_record_read( addr, size ); - else - BOP_record_write( addr, size ); +static void +ppr_access(void *addr, size_t size, int is_read) +{ + if (is_read) + BOP_record_read(addr, size); + else + BOP_record_write(addr, size); } -static void two_tasks_test( void ) { - BOP_set_group_size( 2 ); - ppr_pos = PPR; - int x = 0, y = 0; - - /* pair 1: write to different data */ - bop_merge_port.ppr_group_init( ); - spec_order = 0; - task_status = MAIN; - bop_merge_port.ppr_task_init( ); - x = 1; - ppr_access( &x, sizeof( int ), 0 ); - assert( bop_merge_port.ppr_check_correctness( ) ); - bop_merge_port.data_commit( ); - - x = 0; - bop_merge_port.ppr_task_init( ); - spec_order = 1; - task_status = SPEC; - y = 1; - ppr_access( &y, sizeof( int ), 0 ); - assert( bop_merge_port.ppr_check_correctness( ) ); - bop_merge_port.data_commit( ); - - x = 0; - y = 0; - bop_merge_port.task_group_commit( ); - assert( x == 1 && y == 1 ); - - /* pair 2: WAW conflict (false conflict) */ - bop_merge_port.ppr_group_init( ); - spec_order = 0; - task_status = MAIN; - bop_merge_port.ppr_task_init( ); - x = 1; - ppr_access( &x, sizeof( int ), 0 ); - assert( bop_merge_port.ppr_check_correctness( ) ); - bop_merge_port.data_commit( ); - - x = 0; - spec_order = 1; - task_status = SPEC; - bop_merge_port.ppr_task_init( ); - x = 2; - ppr_access( &x, sizeof( int ), 0 ); - assert( bop_merge_port.ppr_check_correctness( ) ); - bop_merge_port.data_commit( ); - - x = 0; - bop_merge_port.task_group_commit( ); - assert( x == 2 ); - - bop_msg( 1, "pair 3: WAR conflict (false conflict)" ); - bop_merge_port.ppr_group_init( ); - x = 1; - spec_order = 0; - task_status = MAIN; - bop_merge_port.ppr_task_init( ); - y = x; - ppr_access( &x, sizeof( int ), 1 ); - ppr_access( &y, sizeof( int ), 0 ); - assert( bop_merge_port.ppr_check_correctness( ) ); - bop_merge_port.data_commit( ); - - x = 0; - y = 0; - spec_order = 1; - task_status = SPEC; - bop_merge_port.ppr_task_init( ); - x = 2; - ppr_access( &x, sizeof( int ), 0 ); - assert( bop_merge_port.ppr_check_correctness( ) ); - bop_merge_port.data_commit( ); - - x = 0; - y = 0; - bop_merge_port.task_group_commit( ); - assert( x == 2 && y == 1 ); - - x = 0; - y = 0; - bop_msg( 1, "pair 4: RAW conflict" ); - bop_merge_port.ppr_group_init( ); - x = 1; - spec_order = 0; - task_status = MAIN; - bop_merge_port.ppr_task_init( ); - x = 2; - ppr_access( &x, sizeof( int ), 0 ); - assert( bop_merge_port.ppr_check_correctness( ) ); - bop_merge_port.data_commit( ); - - x = 1; - spec_order = 1; - task_status = SPEC; - bop_merge_port.ppr_task_init( ); - y = x; - ppr_access( &x, sizeof( int ), 1 ); - ppr_access( &y, sizeof( int ), 0 ); - assert( ! bop_merge_port.ppr_check_correctness( ) ); - bop_merge_port.data_commit( ); - - x = 0; - y = 0; - bop_merge_port.task_group_commit( ); - assert( x == 2 && y == 1 ); - +static void +two_tasks_test(void) +{ + BOP_set_group_size(2); + ppr_pos = PPR; + int x = 0, y = 0; + + /* pair 1: write to different data */ + bop_merge_port.ppr_group_init(); + spec_order = 0; + task_status = MAIN; + bop_merge_port.ppr_task_init(); + x = 1; + ppr_access(&x, sizeof(int), 0); + assert(bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + + x = 0; + bop_merge_port.ppr_task_init(); + spec_order = 1; + task_status = SPEC; + y = 1; + ppr_access(&y, sizeof(int), 0); + assert(bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + + x = 0; + y = 0; + bop_merge_port.task_group_commit(); + assert(x == 1 && y == 1); + + /* pair 2: WAW conflict (false conflict) */ + bop_merge_port.ppr_group_init(); + spec_order = 0; + task_status = MAIN; + bop_merge_port.ppr_task_init(); + x = 1; + ppr_access(&x, sizeof(int), 0); + assert(bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + + x = 0; + spec_order = 1; + task_status = SPEC; + bop_merge_port.ppr_task_init(); + x = 2; + ppr_access(&x, sizeof(int), 0); + assert(bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + + x = 0; + bop_merge_port.task_group_commit(); + assert(x == 2); + + bop_msg(1, "pair 3: WAR conflict (false conflict)"); + bop_merge_port.ppr_group_init(); + x = 1; + spec_order = 0; + task_status = MAIN; + bop_merge_port.ppr_task_init(); + y = x; + ppr_access(&x, sizeof(int), 1); + ppr_access(&y, sizeof(int), 0); + assert(bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + + x = 0; + y = 0; + spec_order = 1; + task_status = SPEC; + bop_merge_port.ppr_task_init(); + x = 2; + ppr_access(&x, sizeof(int), 0); + assert(bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + + x = 0; + y = 0; + bop_merge_port.task_group_commit(); + assert(x == 2 && y == 1); + + x = 0; + y = 0; + bop_msg(1, "pair 4: RAW conflict"); + bop_merge_port.ppr_group_init(); + x = 1; + spec_order = 0; + task_status = MAIN; + bop_merge_port.ppr_task_init(); + x = 2; + ppr_access(&x, sizeof(int), 0); + assert(bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + + x = 1; + spec_order = 1; + task_status = SPEC; + bop_merge_port.ppr_task_init(); + y = x; + ppr_access(&x, sizeof(int), 1); + ppr_access(&y, sizeof(int), 0); + assert(!bop_merge_port.ppr_check_correctness()); + bop_merge_port.data_commit(); + + x = 0; + y = 0; + bop_merge_port.task_group_commit(); + assert(x == 2 && y == 1); } - diff --git a/tests/unit_tests/multi_ppr.c b/tests/unit_tests/multi_ppr.c index a466e21..19bbe1e 100644 --- a/tests/unit_tests/multi_ppr.c +++ b/tests/unit_tests/multi_ppr.c @@ -1,20 +1,21 @@ #include "bop_api.h" #define loop 2 -int main(){ +int +main() +{ + for (int i = 0; i < loop; i++) { + BOP_ppr_begin(1); + sleep(1); + BOP_ppr_end(1); + } + BOP_group_over(1); - for(int i = 0; i < loop; i++){ - BOP_ppr_begin(1); - sleep(1); - BOP_ppr_end(1); - } - BOP_group_over(1); - - for(int i = 0; i < loop; i++){ - BOP_ppr_begin(2); - sleep(1); - BOP_ppr_end(2); - } - BOP_group_over(2); - return 0; + for (int i = 0; i < loop; i++) { + BOP_ppr_begin(2); + sleep(1); + BOP_ppr_end(2); + } + BOP_group_over(2); + return 0; } diff --git a/tests/unit_tests/postwait_tests.c b/tests/unit_tests/postwait_tests.c index 9e2f9a5..dc2c198 100644 --- a/tests/unit_tests/postwait_tests.c +++ b/tests/unit_tests/postwait_tests.c @@ -1,255 +1,272 @@ -#include /* for NULL */ -#include /* for PAGESIZEX */ +#include /* for PAGESIZEX */ #include #include +#include /* for NULL */ -static void interface_tests(void); +static void +interface_tests(void); extern bop_port_t postwait_port; extern bop_port_t bop_merge_port; extern unsigned ppr_index; -void empty_post( void ) { - task_status = SEQ; - BOP_set_group_size( 2 ); - ppr_group_init( ); - - spec_order = 0; - ppr_index = 10; - task_status = MAIN; - ppr_task_init( ); - channel_post( 2 ); - - spec_order += 1; - ppr_index += 1; - task_status = SPEC; - ppr_task_init( ); - channel_wait( 2 ); - task_group_succ_fini( ); +void +empty_post(void) +{ + task_status = SEQ; + BOP_set_group_size(2); + ppr_group_init(); + + spec_order = 0; + ppr_index = 10; + task_status = MAIN; + ppr_task_init(); + channel_post(2); + + spec_order += 1; + ppr_index += 1; + task_status = SPEC; + ppr_task_init(); + channel_wait(2); + task_group_succ_fini(); } -void silent_drop( void ) { - int x = -1; - task_status = SEQ; - BOP_set_group_size( 3 ); - ppr_group_init( ); - - spec_order = 1; - ppr_index = 1; - task_status = SPEC; - ppr_task_init( ); - channel_fill( 2, &x, sizeof( int ) ); - x = 1; - BOP_promise( & x, sizeof( int ) ); - channel_post( 2 ); - - x = 0; - spec_order = 0; - ppr_index = 0; - task_status = MAIN; - ppr_task_init( ); - channel_fill( 1, &x, sizeof( int ) ); - x = 0; - BOP_promise( & x, sizeof( int ) ); - channel_post( 1 ); - - bop_msg( 2, "same datum from two tasks received in reverse sequential order" ); - x = 0; - spec_order = 2; - ppr_index = 2; - task_status = SPEC; - ppr_task_init( ); - channel_wait( 2 ); - assert( x == 1 ); - - channel_wait( 1 ); - assert( x == 1 ); - - task_group_succ_fini( ); - bop_msg( 1, "silent drop test finished" ); +void +silent_drop(void) +{ + int x = -1; + + task_status = SEQ; + BOP_set_group_size(3); + ppr_group_init(); + + spec_order = 1; + ppr_index = 1; + task_status = SPEC; + ppr_task_init(); + channel_fill(2, &x, sizeof(int)); + x = 1; + BOP_promise(&x, sizeof(int)); + channel_post(2); + + x = 0; + spec_order = 0; + ppr_index = 0; + task_status = MAIN; + ppr_task_init(); + channel_fill(1, &x, sizeof(int)); + x = 0; + BOP_promise(&x, sizeof(int)); + channel_post(1); + + bop_msg(2, + "same datum from two tasks received in reverse sequential order"); + x = 0; + spec_order = 2; + ppr_index = 2; + task_status = SPEC; + ppr_task_init(); + channel_wait(2); + assert(x == 1); + + channel_wait(1); + assert(x == 1); + + task_group_succ_fini(); + bop_msg(1, "silent drop test finished"); } -void correctness_check( void ) { - task_status = SEQ; - BOP_set_group_size( 2 ); - ppr_pos = PPR; - int z = 0; - - bop_msg( 2, "correctness checking" ); - ppr_group_init( ); - spec_order = 0; - ppr_index = 42; - task_status = MAIN; - ppr_task_init( ); - channel_fill( &z, &z, sizeof( int ) ); - z = 1; - BOP_promise( & z, sizeof( int ) ); - channel_post( & z ); - // z = 2; // uncomment to test modify-after-post conflict handling, next ppr will abort - // bop_mode = PARALLEL; // uncomment to test modify-after-post conflict handling - assert( ppr_check_correctness( ) ); - data_commit( ); - - z = 0; - ppr_task_init( ); - spec_order = 1; - ppr_index = 43; - task_status = SPEC; - assert( z != 1 ); - channel_wait( &z ); - assert( z == 1 ); - BOP_use( & z, sizeof( int ) ); - assert( ppr_check_correctness( ) ); - data_commit( ); - task_group_succ_fini( ); +void +correctness_check(void) +{ + task_status = SEQ; + BOP_set_group_size(2); + ppr_pos = PPR; + int z = 0; + + bop_msg(2, "correctness checking"); + ppr_group_init(); + spec_order = 0; + ppr_index = 42; + task_status = MAIN; + ppr_task_init(); + channel_fill(&z, &z, sizeof(int)); + z = 1; + BOP_promise(&z, sizeof(int)); + channel_post(&z); + // z = 2; // uncomment to test modify-after-post conflict handling, next + // ppr will abort + // bop_mode = PARALLEL; // uncomment to test modify-after-post conflict + // handling + assert(ppr_check_correctness()); + data_commit(); + + z = 0; + ppr_task_init(); + spec_order = 1; + ppr_index = 43; + task_status = SPEC; + assert(z != 1); + channel_wait(&z); + assert(z == 1); + BOP_use(&z, sizeof(int)); + assert(ppr_check_correctness()); + data_commit(); + task_group_succ_fini(); } -void ordering_conflict( void ) { - task_status = SEQ; - BOP_set_group_size( 3 ); - ppr_pos = PPR; - int k = 0; - - bop_msg( 2, "ordering conflict" ); - ppr_group_init( ); - spec_order = 0; - ppr_index = 142; - task_status = MAIN; - ppr_task_init( ); - channel_fill( &k, &k, sizeof( int ) ); - k = 1; - BOP_promise( & k, sizeof( int ) ); - channel_post( & k ); - assert( ppr_check_correctness( ) ); - data_commit( ); - - spec_order += 1; - ppr_index += 1; - task_status = SPEC; - ppr_task_init( ); - k = 2; - BOP_promise( & k, sizeof( int ) ); - assert( ppr_check_correctness( ) ); - data_commit( ); - - k = 0; - spec_order += 1; - ppr_index += 1; - task_status = SPEC; - ppr_task_init( ); - assert( k != 1 ); - channel_wait( &k ); - assert( k == 1 ); - BOP_use( & k, sizeof( int ) ); - assert( ! ppr_check_correctness( ) ); - task_group_succ_fini( ); +void +ordering_conflict(void) +{ + task_status = SEQ; + BOP_set_group_size(3); + ppr_pos = PPR; + int k = 0; + + bop_msg(2, "ordering conflict"); + ppr_group_init(); + spec_order = 0; + ppr_index = 142; + task_status = MAIN; + ppr_task_init(); + channel_fill(&k, &k, sizeof(int)); + k = 1; + BOP_promise(&k, sizeof(int)); + channel_post(&k); + assert(ppr_check_correctness()); + data_commit(); + + spec_order += 1; + ppr_index += 1; + task_status = SPEC; + ppr_task_init(); + k = 2; + BOP_promise(&k, sizeof(int)); + assert(ppr_check_correctness()); + data_commit(); + + k = 0; + spec_order += 1; + ppr_index += 1; + task_status = SPEC; + ppr_task_init(); + assert(k != 1); + channel_wait(&k); + assert(k == 1); + BOP_use(&k, sizeof(int)); + assert(!ppr_check_correctness()); + task_group_succ_fini(); } -int main( ) { +int +main() +{ + interface_tests(); - interface_tests( ); + silent_drop(); - silent_drop( ); + correctness_check(); - correctness_check( ); + ordering_conflict(); - ordering_conflict( ); + empty_post(); - empty_post( ); - - printf("The tests end.\n"); - return 0; /* must return 0 for rake test to succeed */ + printf("The tests end.\n"); + return 0; /* must return 0 for rake test to succeed */ } extern bop_port_t postwait_port; #include typedef struct _channel_t { - addr_t id; /* valid if not zero */ - map_t data; - unsigned sender; /* non-zero means posted */ - char is_posted; + addr_t id; /* valid if not zero */ + map_t data; + unsigned sender; /* non-zero means posted */ + char is_posted; - /* for channel chaining */ - struct _channel_t *cc_first, *cc_next; + /* for channel chaining */ + struct _channel_t *cc_first, *cc_next; } channel_t; struct switch_board_t { - channel_t *channels; /* first come, first serve */ - unsigned size; /* no re-sizing during ppr */ - bop_lock_t lock; /* global lock, needed for channel chaining */ + channel_t *channels; /* first come, first serve */ + unsigned size; /* no re-sizing during ppr */ + bop_lock_t lock; /* global lock, needed for channel chaining */ } switch_board; -static void interface_tests( void ) { - task_status = SEQ; - BOP_set_group_size( 2 ); - ppr_pos = PPR; - int x = 0, y = 0; - - bop_msg( 2, "test 1: two pprs, pass one number, one successful and two failed posts" ); - task_status = SEQ; - ppr_group_init( ); - spec_order = 0; - task_status = MAIN; - ppr_task_init( ); - channel_fill( 1, &x, sizeof( int ) ); - x = 1; - BOP_promise( & x, sizeof( int ) ); - channel_post( 1 ); - - x = 2; - channel_post( 21 ); /* empty post */ - channel_fill( 21, &x, sizeof( int ) ); - channel_post( 21 ); /* resource conflict (depending on the number of channels allocated */ - assert( ! channel_is_posted( 21 ) ); - - - x = 0; - ppr_task_init( ); - spec_order = 1; - task_status = SPEC; - assert( x != 1 ); - channel_wait( 1 ); - assert( x == 1 ); - task_group_succ_fini( ); - - bop_msg( 2, "test 2: channel chaining, 3 pprs, 4 channels" ); - task_status = SEQ; - ppr_group_init( ); - spec_order = 0; - task_status = MAIN; - ppr_task_init( ); - channel_fill( 1, &x, sizeof( int ) ); - x = 2; - y = 3; - channel_fill( 1, &y, sizeof( int ) ); - BOP_promise( & x, sizeof( int ) ); - BOP_promise( & y, sizeof( int ) ); - channel_post( 1 ); - channel_chain( 4, 5 ); - - x = 0; - y = 0; - ppr_task_init( ); - spec_order = 1; - task_status = SPEC; - channel_chain( 1, 2 ); - channel_chain( 2, 4 ); - assert( x != 2 ); - channel_wait( 4 ); - assert( x == 2 ); - assert( y == 3 ); - - x = 0; - y = 0; - ppr_task_init( ); - spec_order = 1; - task_status = SPEC; - assert( x != 2 ); - channel_wait( 2 ); - assert( x == 2 ); - assert( y == 3 ); - task_group_succ_fini( ); +static void +interface_tests(void) +{ + task_status = SEQ; + BOP_set_group_size(2); + ppr_pos = PPR; + int x = 0, y = 0; + + bop_msg(2, + "test 1: two pprs, pass one number, one successful and two " + "failed posts"); + task_status = SEQ; + ppr_group_init(); + spec_order = 0; + task_status = MAIN; + ppr_task_init(); + channel_fill(1, &x, sizeof(int)); + x = 1; + BOP_promise(&x, sizeof(int)); + channel_post(1); + + x = 2; + channel_post(21); /* empty post */ + channel_fill(21, &x, sizeof(int)); + channel_post(21); /* resource conflict (depending on the number of channels + * allocated */ + assert(!channel_is_posted(21)); + + x = 0; + ppr_task_init(); + spec_order = 1; + task_status = SPEC; + assert(x != 1); + channel_wait(1); + assert(x == 1); + task_group_succ_fini(); + + bop_msg(2, "test 2: channel chaining, 3 pprs, 4 channels"); + task_status = SEQ; + ppr_group_init(); + spec_order = 0; + task_status = MAIN; + ppr_task_init(); + channel_fill(1, &x, sizeof(int)); + x = 2; + y = 3; + channel_fill(1, &y, sizeof(int)); + BOP_promise(&x, sizeof(int)); + BOP_promise(&y, sizeof(int)); + channel_post(1); + channel_chain(4, 5); + + x = 0; + y = 0; + ppr_task_init(); + spec_order = 1; + task_status = SPEC; + channel_chain(1, 2); + channel_chain(2, 4); + assert(x != 2); + channel_wait(4); + assert(x == 2); + assert(y == 3); + + x = 0; + y = 0; + ppr_task_init(); + spec_order = 1; + task_status = SPEC; + assert(x != 2); + channel_wait(2); + assert(x == 2); + assert(y == 3); + task_group_succ_fini(); } - diff --git a/tests/unit_tests/range_tree_tests.c b/tests/unit_tests/range_tree_tests.c index 7596294..5f00491 100644 --- a/tests/unit_tests/range_tree_tests.c +++ b/tests/unit_tests/range_tree_tests.c @@ -1,184 +1,209 @@ #include /* for PRIdPTR */ -#include // for malloc +#include // for malloc #include "bop_map.h" -#define min(a, b) ((a)<(b)? (a): (b)) -#define max(a, b) ((a)<(b)? (b): (a)) - -static void check( map_t *map, unsigned nodes, addr_t bytes ) { - // map_inspect( 1, map, "map" ); - assert( map->size == nodes ); - assert( map_size_in_bytes( map ) == bytes ); - bop_msg( 1, "check map passes, %u node(s), "PRIdPTR" byte(s)", nodes, bytes ); +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) < (b) ? (b) : (a)) + +static void +check(map_t *map, unsigned nodes, addr_t bytes) +{ + // map_inspect( 1, map, "map" ); + assert(map->size == nodes); + assert(map_size_in_bytes(map) == bytes); + bop_msg( + 1, "check map passes, %u node(s), " PRIdPTR " byte(s)", nodes, bytes); } -static void check_range( mem_range_t *x, addr_t base, size_t size ) { - assert( x->base == base ); - assert( x->size == size ); +static void +check_range(mem_range_t *x, addr_t base, size_t size) +{ + assert(x->base == base); + assert(x->size == size); } -void test_200k( mspace shm ) { - int i, n = 200000; - unsigned *ary = (unsigned *) mspace_malloc( shm, 2 * n * 4 ); - map_t *set = new_range_set( shm, "200k set 1" ); - for ( i = 0; i < n; i ++ ) - map_add_range( set, (addr_t) & ary[ i ], 4, NULL ); - map_inspect( 1, set ); - check( set, 1, n * 4 ); - map_free( set ); - set = new_range_set( shm, "200k set 2" ); - for ( i = 0; i < n; i ++ ) - map_add_range( set, (addr_t) & ary[ i + n ], 4, NULL ); - map_inspect( 1, set ); - check( set, 1, n * 4 ); - - mspace_free( shm, ary ); +void +test_200k(mspace shm) +{ + int i, n = 200000; + unsigned *ary = (unsigned *)mspace_malloc(shm, 2 * n * 4); + map_t *set = new_range_set(shm, "200k set 1"); + + for (i = 0; i < n; i++) + map_add_range(set, (addr_t)&ary[i], 4, NULL); + map_inspect(1, set); + check(set, 1, n * 4); + map_free(set); + set = new_range_set(shm, "200k set 2"); + for (i = 0; i < n; i++) + map_add_range(set, (addr_t)&ary[i + n], 4, NULL); + map_inspect(1, set); + check(set, 1, n * 4); + + mspace_free(shm, ary); } -int main( ) { - bop_msg( 1, "test0"); - - char is_shared_mem = 1; /* false */ - char use_lock = 0; - size_t init_size = 20000000; /* 20M init size */ - mspace shm = create_mspace( init_size, use_lock, is_shared_mem ); - - test0( shm ); - test1( shm ); - test_inject( shm ); - - test_200k( shm ); - - printf("The tests end.\n"); - /* - test_key_obj( shm ); - test_set_ops( shm ); - test_map_foreach( shm ); */ +int +main() +{ + bop_msg(1, "test0"); + + char is_shared_mem = 1; /* false */ + char use_lock = 0; + size_t init_size = 20000000; /* 20M init size */ + mspace shm = create_mspace(init_size, use_lock, is_shared_mem); + + test0(shm); + test1(shm); + test_inject(shm); + + test_200k(shm); + + printf("The tests end.\n"); + /* + * test_key_obj( shm ); + * test_set_ops( shm ); + * test_map_foreach( shm ); */ } -int test_inject( mspace space ) { - map_t *set = new_range_set( space, "set" ); +int +test_inject(mspace space) +{ + map_t *set = new_range_set(space, "set"); + + int i; + int n = 1000; + + for (i = 0; i < 2 * n; i += 2) { + int *ptr = mspace_calloc(space, 1, sizeof(int)); - int i; - int n = 1000; - for ( i = 0; i < 2*n; i += 2 ) { - int *ptr = mspace_calloc( space, 1, sizeof(int) ); - *ptr = i; - map_add_range( set, (addr_t) i, 1, ptr ); - } + *ptr = i; + map_add_range(set, (addr_t)i, 1, ptr); + } - check( set, n, n ); + check(set, n, n); - mem_range_t *ranges; - int num_ranges; - map_to_array( set, &ranges, &num_ranges ); + mem_range_t *ranges; + int num_ranges; - assert( num_ranges == n ); - for ( i = 0; i < n; i += 1 ) - assert( *((int*) ranges[ i ].rec) == i * 2 ); + map_to_array(set, &ranges, &num_ranges); + + assert(num_ranges == n); + for (i = 0; i < n; i += 1) + assert(*((int *)ranges[i].rec) == i * 2); } -int test0( mspace space ) { - map_t *map; - map = new_range_set( space, "map" ); - int task = 0; - map_add_range( map, 0, 1, NULL ); - check( map, 1, 1 ); +int +test0(mspace space) +{ + map_t *map; + + map = new_range_set(space, "map"); + int task = 0; + + map_add_range(map, 0, 1, NULL); + check(map, 1, 1); + + map_add_range(map, 1, 1, NULL); + check(map, 1, 2); + + map_add_range(map, 3, 1, NULL); + check(map, 2, 3); - map_add_range( map, 1, 1, NULL ); - check( map, 1, 2 ); + map_inspect(1, map); - map_add_range( map, 3, 1, NULL ); - check( map, 2, 3 ); + /* just filling the hole [2,2] */ + map_add_range(map, 2, 1, NULL); + check(map, 1, 4); - map_inspect( 1, map ); + map_add_range(map, 5, 2, NULL); + check(map, 2, 6); - /* just filling the hole [2,2] */ - map_add_range( map, 2, 1, NULL ); - check( map, 1, 4 ); + /* covering a bit larger than the hold [4,4] */ + map_add_range(map, 4, 2, NULL); + check(map, 1, 7); - map_add_range( map, 5, 2, NULL ); - check( map, 2, 6 ); + map_add_range(map, 10, 1, NULL); + check(map, 2, 8); - /* covering a bit larger than the hold [4,4] */ - map_add_range( map, 4, 2, NULL ); - check( map, 1, 7 ); + map_inspect(1, map); - map_add_range( map, 10, 1, NULL ); - check( map, 2, 8 ); + map_add_range(map, 8, 1, NULL); + check(map, 3, 9); - map_inspect( 1, map ); + map_inspect(1, map); - map_add_range( map, 8, 1, NULL ); - check( map, 3, 9 ); + mem_range_t *r = map_contains(map, 4); - map_inspect( 1, map ); + check_range(r, 0, 7); - mem_range_t *r = map_contains( map, 4 ); - check_range( r, 0, 7 ); + r = map_contains(map, 6); + check_range(r, 0, 7); - r = map_contains( map, 6 ); - check_range( r, 0, 7 ); + assert(map_contains(map, 7) == NULL); - assert( map_contains( map, 7 ) == NULL ); + assert(map_contains(map, 11) == NULL); - assert( map_contains( map, 11 ) == NULL ); + mem_range_t x, c; - mem_range_t x, c; - x.base = 7; - x.size = 1; - assert( ! map_overlaps( map, &x, &c ) ); + x.base = 7; + x.size = 1; + assert(!map_overlaps(map, &x, &c)); - x.size = 2; - assert( map_overlaps( map, &x, &c ) ); - check_range( &c, 8, 1 ); + x.size = 2; + assert(map_overlaps(map, &x, &c)); + check_range(&c, 8, 1); - map_t *map2; - map2 = new_range_set(space, "map2"); + map_t *map2; - map_subtract(map, map2); - check(map, 3, 9); + map2 = new_range_set(space, "map2"); - map_add_range(map2, 0, 1, NULL); - map_subtract(map, map2); - check(map, 3, 8); + map_subtract(map, map2); + check(map, 3, 9); - map_add_range(map2, 8, 1, NULL); - map_subtract(map, map2); - check(map, 2, 7); + map_add_range(map2, 0, 1, NULL); + map_subtract(map, map2); + check(map, 3, 8); - map_add_range(map2, 2, 2, NULL); - map_add_range(map2, 6, 1, NULL); - map_subtract(map, map2); - check(map, 3, 4); + map_add_range(map2, 8, 1, NULL); + map_subtract(map, map2); + check(map, 2, 7); + + map_add_range(map2, 2, 2, NULL); + map_add_range(map2, 6, 1, NULL); + map_subtract(map, map2); + check(map, 3, 4); } -int test1( mspace space ) { - int num_segments = 100; - int chunksize = 4096; - - char *vm_data = (char *) malloc( num_segments * chunksize ); - char *vm_data2 = (char *) malloc( num_segments * chunksize ); - - map_t *vms; - vms = new_range_set( space, "vms" ); - - map_add_range( vms, (addr_t) vm_data, num_segments * chunksize, - NULL ); - map_add_range( vms, (addr_t) vm_data2, num_segments * chunksize, - NULL ); - - assert( map_contains( vms, (addr_t) vm_data )); - assert( map_contains( vms, (addr_t) vm_data2 )); - - addr_t larger = max( (addr_t) vm_data, (addr_t) vm_data2 ); - addr_t smaller = min( (addr_t) vm_data, (addr_t) vm_data2 ); - - mem_range_t conflict; - if ( larger - smaller > 2*num_segments * chunksize ) { - mem_range_t gap, conflict; - gap.size = num_segments * chunksize; - gap.base = smaller + gap.size; - assert( ! map_overlaps( vms, &gap, &conflict ) ); - } +int +test1(mspace space) +{ + int num_segments = 100; + int chunksize = 4096; + + char *vm_data = (char *)malloc(num_segments * chunksize); + char *vm_data2 = (char *)malloc(num_segments * chunksize); + + map_t *vms; + + vms = new_range_set(space, "vms"); + + map_add_range(vms, (addr_t)vm_data, num_segments * chunksize, NULL); + map_add_range(vms, (addr_t)vm_data2, num_segments * chunksize, NULL); + + assert(map_contains(vms, (addr_t)vm_data)); + assert(map_contains(vms, (addr_t)vm_data2)); + + addr_t larger = max((addr_t)vm_data, (addr_t)vm_data2); + addr_t smaller = min((addr_t)vm_data, (addr_t)vm_data2); + + mem_range_t conflict; + + if (larger - smaller > 2 * num_segments * chunksize) { + mem_range_t gap, conflict; + + gap.size = num_segments * chunksize; + gap.base = smaller + gap.size; + assert(!map_overlaps(vms, &gap, &conflict)); + } } diff --git a/tests/wrapper_test.c b/tests/wrapper_test.c index c269e07..9bafe31 100644 --- a/tests/wrapper_test.c +++ b/tests/wrapper_test.c @@ -1,25 +1,29 @@ #include "malloc_wrapper.h" -#include #include +#include + +int +main() +{ + printf("start\n"); + int k; + int nums = 50; + int *ints; + + for (k = 0; k < 5; k++) { + if (k % 2) + ints = calloc(nums, sizeof(int)); + else + ints = malloc(nums * sizeof(int)); + int i; + int count = 0; -int main(){ - printf("start\n"); - int k; - int nums = 50; - int * ints; - for(k = 0; k < 5; k++){ - if(k % 2) - ints = calloc(nums, sizeof(int)); - else - ints = malloc(nums * sizeof(int)); - int i; - int count = 0; - for(i = 0; i < nums; i++) - ints[i] = i*(k+1); - for(i = 0; i < nums; i++) - count += ints[i]; - free(ints); - printf("sum %d\n", count); - } - return 0; + for (i = 0; i < nums; i++) + ints[i] = i * (k + 1); + for (i = 0; i < nums; i++) + count += ints[i]; + free(ints); + printf("sum %d\n", count); + } + return 0; } diff --git a/utils.c b/utils.c index a6f2c0d..2d3446a 100644 --- a/utils.c +++ b/utils.c @@ -1,13 +1,13 @@ +#include "bop_api.h" +#include "utils.h" #include #include -#include /* for bop_msg */ -#include /* getenv */ +#include +#include +#include /* for bop_msg */ +#include /* getenv */ #include #include -#include -#include -#include "bop_api.h" -#include "utils.h" extern task_status_t task_status; extern ppr_pos_t ppr_pos; @@ -15,135 +15,186 @@ extern int ppr_index; extern int spec_order; extern bop_mode_t bop_mode; -task_status_t BOP_task_status(void) { - return task_status; +task_status_t +BOP_task_status(void) +{ + return task_status; } -ppr_pos_t BOP_ppr_pos( void ) { - return ppr_pos; +ppr_pos_t +BOP_ppr_pos(void) +{ + return ppr_pos; } -int BOP_ppr_index( void ) { - if ( ppr_pos == GAP ) return ppr_index + 1; - else return ppr_index; +int +BOP_ppr_index(void) +{ + if (ppr_pos == GAP) + return ppr_index + 1; + else + return ppr_index; } -int BOP_spec_order( void ) { - return spec_order; +int +BOP_spec_order(void) +{ + return spec_order; } -bop_mode_t BOP_mode( void ) { - return bop_mode; +bop_mode_t +BOP_mode(void) +{ + return bop_mode; } -unsigned long long read_tsc(void) { - unsigned long long tsc; - asm ("rdtsc":"=A" (tsc):); - return tsc; +unsigned long long +read_tsc(void) +{ + unsigned long long tsc; + + asm("rdtsc" : "=A"(tsc) :); + return tsc; } int bop_verbose = 0; -void BOP_set_verbose(int x) { - assert( x < 6 && x > 0 ); - bop_verbose = x; +void +BOP_set_verbose(int x) +{ + assert(x < 6 && x > 0); + bop_verbose = x; } -int BOP_get_verbose( void ) { - return bop_verbose; +int +BOP_get_verbose(void) +{ + return bop_verbose; } -extern char in_ordered_region; // bop_ordered.c +extern char in_ordered_region; // bop_ordered.c extern int errno; -char *strerror(int errnum); - -void bop_msg_va(int level, const char * msg, va_list v){ - if(bop_verbose >= level) { - fprintf(stderr, "%d-", getpid()); - char *pos; - switch (ppr_pos) { - case PPR: - pos = ""; - break; - case GAP: - pos = "g"; - break; - default: - assert(0); - } - if (in_ordered_region) { - assert( ppr_pos == PPR ); - pos = "od"; - } - unsigned pidx = BOP_ppr_index( ); - switch(task_status) { - case UNDY: fprintf(stderr, "Undy-(idx %d%s): ", pidx, pos); break; - case MAIN: fprintf(stderr, "Main-%d(idx %d%s): ", spec_order, pidx, pos); break; - case SEQ: fprintf(stderr, "Seq-(idx %d%s): ", pidx, pos); break; - case SPEC: fprintf(stderr, "Spec-%d(idx %d%s): ", spec_order, pidx, pos); break; - } - struct timeval tv; - gettimeofday(&tv, NULL); - double curr_time = tv.tv_sec + (tv.tv_usec/1000000.0); - if (bop_stats.start_time != 0) - fprintf(stderr, " (%.6lfs) ", curr_time - bop_stats.start_time); - - vfprintf(stderr,msg,v); - fprintf(stderr,"\n"); - fflush(stderr); - } -} +char * +strerror(int errnum); -void bop_msg(int level, const char * msg, ...) { - if(bop_verbose >= level) - { - va_list v; - va_start(v,msg); - bop_msg_va(level, msg, v); - va_end(v); - } +void +bop_msg_va(int level, const char *msg, va_list v) +{ + if (bop_verbose >= level) { + fprintf(stderr, "%d-", getpid()); + char *pos; + + switch (ppr_pos) { + case PPR: + pos = ""; + break; + case GAP: + pos = "g"; + break; + default: + assert(0); + } + if (in_ordered_region) { + assert(ppr_pos == PPR); + pos = "od"; + } + unsigned pidx = BOP_ppr_index(); + + switch (task_status) { + case UNDY: + fprintf(stderr, "Undy-(idx %d%s): ", pidx, pos); + break; + case MAIN: + fprintf(stderr, "Main-%d(idx %d%s): ", spec_order, pidx, pos); + break; + case SEQ: + fprintf(stderr, "Seq-(idx %d%s): ", pidx, pos); + break; + case SPEC: + fprintf(stderr, "Spec-%d(idx %d%s): ", spec_order, pidx, pos); + break; + } + struct timeval tv; + + gettimeofday(&tv, NULL); + double curr_time = tv.tv_sec + (tv.tv_usec / 1000000.0); + + if (bop_stats.start_time != 0) + fprintf(stderr, " (%.6lfs) ", curr_time - bop_stats.start_time); + + vfprintf(stderr, msg, v); + fprintf(stderr, "\n"); + fflush(stderr); + } } -void msg_init(){ +void +bop_msg(int level, const char *msg, ...) +{ + if (bop_verbose >= level) { + va_list v; -} -void msg_destroy(){ + va_start(v, msg); + bop_msg_va(level, msg, v); + va_end(v); + } } -/* read the environment variable env, and returns it's integer value. - if the value is undefined, the default value def is returned. - the value is restricted to the range [min,max] */ -int get_int_from_env(const char* env, int min, int max, int def) +void +msg_init() { - char* cval; - - assert( min < max ); - - cval = getenv( env ); - if (cval == NULL) { - bop_msg( 2, "Variable %s is set to default (%d).", env, def); - return def; - } +} - int ival = atoi( cval ); - if ( ival < min ) ival = min; - if ( ival > max ) ival = max; - bop_msg( 2, "Variable %s is set as %d based on env ([%d, %d]).", env, ival, min, max); +void +msg_destroy() +{ +} - return ival; +/* read the environment variable env, and returns it's integer value. + * if the value is undefined, the default value def is returned. + * the value is restricted to the range [min,max] */ +int +get_int_from_env(const char *env, int min, int max, int def) +{ + char *cval; + + assert(min < max); + + cval = getenv(env); + if (cval == NULL) { + bop_msg(2, "Variable %s is set to default (%d).", env, def); + return def; + } + + int ival = atoi(cval); + + if (ival < min) + ival = min; + if (ival > max) + ival = max; + bop_msg(2, + "Variable %s is set as %d based on env ([%d, %d]).", + env, + ival, + min, + max); + + return ival; } -char * BOP_task_str(){ - switch(task_status){ +char * +BOP_task_str() +{ + switch (task_status) { case MAIN: - return "Main speculation"; + return "Main speculation"; case SPEC: - return "Speculation"; + return "Speculation"; case UNDY: - return "Understudy"; + return "Understudy"; case SEQ: - return "Sequential"; + return "Sequential"; default: - return "Unkown!"; - } + return "Unkown!"; + } } diff --git a/utils.h b/utils.h index 478a79e..1dc3baf 100644 --- a/utils.h +++ b/utils.h @@ -1,31 +1,44 @@ #ifndef _BOP_UTILS_H_ #define _BOP_UTILS_H_ -#include #include "bop_api.h" +#include -int bop_terminal_to_workers(); -int bop_terminal_to_monitor(); -int block_signal(int signo); -int unblock_signal(int signo); - -void bop_msg(int level, const char * msg, ...); -int get_int_from_env(const char* env, int min, int max, int def); - -void msg_init(void); -void msg_destroy(void); - -void report_conflict( int verbose, mem_range_t *c1, char *n1, - mem_range_t *c2, char *n2 ); +int +bop_terminal_to_workers(); +int +bop_terminal_to_monitor(); +int +block_signal(int signo); +int +unblock_signal(int signo); + +void +bop_msg(int level, const char *msg, ...); +int +get_int_from_env(const char *env, int min, int max, int def); + +void +msg_init(void); +void +msg_destroy(void); + +void +report_conflict( + int verbose, mem_range_t *c1, char *n1, mem_range_t *c2, char *n2); #define nop() asm volatile("nop") /** so it's 'inlined' */ -char mem_range_eq( mem_range_t *r1, mem_range_t *r2 ); +char +mem_range_eq(mem_range_t *r1, mem_range_t *r2); #include "external/malloc.h" -mspace mspace_small_new( void ); -mspace mspace_medium_new( void ); -mspace mspace_large_new( void ); +mspace +mspace_small_new(void); +mspace +mspace_medium_new(void); +mspace +mspace_large_new(void); #endif From 0d72192e4edec5058c3f31a4c46677aa01ba280f Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Fri, 1 Jul 2016 00:27:32 -0400 Subject: [PATCH 25/37] Rewrite Makefile to be cleaner and more extendable --- Makefile | 55 ++++++++++++++++--------------------------------------- 1 file changed, 16 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 4d09aec..0c80e16 100644 --- a/Makefile +++ b/Makefile @@ -1,33 +1,22 @@ -CC ?= gcc -ifeq ($(CC), cc) - CC = gcc -endif - - -CFLAGS = -Wall -g -fPIC -pthread -I. -Wno-unused-function -save-temps $(CUSTOMDEF) -CUSTOMDEF = -D USE_DL_PREFIX -D BOP -D USE_LOCKS -D UNSUPPORTED_MALLOC -D DM_DEBUG -LDFLAGS = -Wl,--no-as-needed -ldl -OPITIMIZEFLAGS = -O3 -DEBUG_FLAGS = -ggdb3 -g3 -pg -D CHECK_COUNTS -U NDEBUG +FLAGS = -Wall -Wno-unused-function -pthread -g3 -fPIC -I. -save-temps \ + -D USE_DL_PREFIX -D BOP -D USE_LOCKS -D UNSUPPORTED_MALLOC \ + -D DM_DEBUG -D CHECK_COUNTS LIB = inst.a +CFLAGS_ALL = $(FLAGS) $(CFLAGS) +LDFLAGS_ALL = -Wl,--no-as-needed $(LDFLAGS) +LDLIBS_ALL = -ldl $(LDLIBS) -SRC := $(wildcard *.c) $(wildcard external/*.c) $(wildcard range_tree/*.c) +SRC := $(wildcard *.c) $(wildcard range_tree/*.c) $(wildcard external/*.c) OBJS = $(SRC:.c=.o) - TEST_DIRS = add sleep str/BOP_string str/strsub str/strsub2 parallel_alloc -library: print_info $(LIB) +.PHONY: all +all: $(LIB) -print_info: - @echo cc = $(CC) - @echo CFLAGS = $(CFLAGS) - @echo LDFLAGS = $(LDFLAGS) - @echo OBJS = $(OBJS) - - -test: library +.PHONY: test +test: $(LIB) @for dir in $(TEST_DIRS) ; do \ echo $$dir ; \ cd tests/$$dir ; \ @@ -37,24 +26,12 @@ test: library done $(LIB): $(OBJS) - @echo building archive "$(LIB)" - @ar r $(LIB) $(OBJS) - @ranlib $(LIB) - -all: $(OBJS) - -# -include $(OBJS:.o=.d) + ar r $(LIB) $(OBJS) + ranlib $(LIB) %.o: %.c - @echo compiling $^ - @gcc -MM $(CFLAGS) $^ > $*.d - @gcc -c -o $@ $^ $(CFLAGS) + $(CC) $(CPPFLAGS) $(CFLAGS_ALL) -c -o $@ $< +.PHONY: clean clean: - rm -f $(OBJS) $(LIB) *.d *.d.tmp *.[ios] - for dir in $(TEST_DIRS) ; do \ - echo $$dir ; \ - cd tests/$$dir ; \ - rake clean ; \ - cd -; \ - done + find -type f -name '*.[ios]' -delete From d9aea5e38bf7bea1814fb3bf1a70a1e645ab4e9c Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Sun, 10 Jul 2016 18:43:12 -0400 Subject: [PATCH 26/37] Sandbox: change CFLAGS --- sandbox/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sandbox/Makefile b/sandbox/Makefile index d684ca2..85a964f 100644 --- a/sandbox/Makefile +++ b/sandbox/Makefile @@ -1,4 +1,4 @@ -CFLAGS = -O2 -fPIC -pthread -I.. -DBOP=1 +CFLAGS = -g3 -fPIC -pthread -I.. -DBOP=1 LDFLAGS = $(CFLAGS) -L.. LDLIBS = -linst -lm -ldl From 581db07f1f0c9f7e65095de19ebb5dce34d6c07d Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Sun, 10 Jul 2016 18:45:32 -0400 Subject: [PATCH 27/37] Fix `make clean` to remove more Also remove, if there, inst.a, tags, and cscope.out. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 0c80e16..4ae5cd0 100644 --- a/Makefile +++ b/Makefile @@ -35,3 +35,4 @@ $(LIB): $(OBJS) .PHONY: clean clean: find -type f -name '*.[ios]' -delete + rm -f $(LIB) tags cscope.out From c2e60afa17dbe9c0bb260eaedd6bbc858db28291 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Mon, 11 Jul 2016 12:48:36 -0400 Subject: [PATCH 28/37] Update sandbox --- sandbox/Makefile | 6 +++--- sandbox/add.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sandbox/Makefile b/sandbox/Makefile index 85a964f..5a3bd78 100644 --- a/sandbox/Makefile +++ b/sandbox/Makefile @@ -3,12 +3,12 @@ LDFLAGS = $(CFLAGS) -L.. LDLIBS = -linst -lm -ldl .PHONY: all -all: ../libinst.a add +all: add -../libinst.a: +../libinst.a: $(wildcard ../*.[ch]) $(MAKE) -C .. -add: add.o +add: add.o ../libinst.a .PHONY: clean clean: diff --git a/sandbox/add.c b/sandbox/add.c index 7131867..5be2124 100644 --- a/sandbox/add.c +++ b/sandbox/add.c @@ -52,7 +52,7 @@ main(int argc, char **argv) n = i + blocksize > datasize ? datasize : i + blocksize; BOP_record_read(data + i, (n - i) * sizeof(*data)); - for (int j = i; j < n; j++) { + for (int j = i; j < n; j += 3) { sump += sin(data[j]) * sin(data[j]) + cos(data[j]) * cos(data[j]); } From 1dd5b71ff6986afbbfcfd45b0e1df6dc5d6f50dc Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Mon, 11 Jul 2016 12:49:28 -0400 Subject: [PATCH 29/37] Fix hanging bug On fork failure (ENOMEM), tried to initialize the gorup again and ended up hanging. --- bop_ppr.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bop_ppr.c b/bop_ppr.c index feb9e92..80d4c95 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -75,6 +75,12 @@ void (*external_reporter)(const char *, ...); static void _ppr_group_init(void) { + static int group_init = 0; + if (group_init) { + return; + } + group_init = 1; + bop_msg(3, "task group starts (gs %d)", BOP_get_group_size()); /* setup bop group id. */ @@ -100,8 +106,9 @@ _ppr_task_init(void) spec_order += 1; break; case UNDY: - case SEQ: assert(0); + case SEQ: + return; } bop_msg(2, From 44c7bce691afa82177534c392401aeb102f24c39 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Mon, 11 Jul 2016 12:50:42 -0400 Subject: [PATCH 30/37] Don't just busy-wait - sleep(1) between wait()s --- bop_ppr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/bop_ppr.c b/bop_ppr.c index 80d4c95..aaeb0b6 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -759,6 +759,7 @@ wait_process() status); // we only care about zero v. not-zero } unblock_wait(); + sleep(1); } errno = 0; // handle remaining processes. Above may not have gotten everything From c641aa28eb262e71ab40e468b95290f6cb121573 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Mon, 11 Jul 2016 12:52:11 -0400 Subject: [PATCH 31/37] Rename environment variables to be uppercase --- bop_ppr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bop_ppr.c b/bop_ppr.c index aaeb0b6..8d93b8b 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -880,8 +880,8 @@ void __attribute__((constructor)) BOP_init(void) sigaction(SIGTTIN, &action, NULL); /* Read environment variables: BOP_GroupSize, BOP_Verbose */ - bop_verbose = get_int_from_env("BOP_Verbose", 0, 6, 0); - int g = get_int_from_env("BOP_GroupSize", 1, 100, 2); + bop_verbose = get_int_from_env("BOP_VERBOSE", 0, 6, 0); + int g = get_int_from_env("BOP_GROUPSIZE", 1, 100, 2); BOP_set_group_size(g); bop_mode = g < 2 ? SERIAL : PARALLEL; From 94ec6ba1da9e3e5926e704fc1dca12d460a896b5 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Mon, 11 Jul 2016 12:52:34 -0400 Subject: [PATCH 32/37] Minor improvements --- bop_ppr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bop_ppr.c b/bop_ppr.c index 8d93b8b..e90d4fc 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -72,6 +72,9 @@ msg_init(); void (*external_reporter)(const char *, ...); +char * +status_name(void); + static void _ppr_group_init(void) { @@ -151,8 +154,9 @@ _BOP_ppr_begin(int id) /* no spawn if sequential or reaching group size */ if (bop_mode == SERIAL || spec_order >= partial_group_get_size() - 1) { - if (bop_mode == SERIAL) + if (bop_mode == SERIAL) { _ppr_task_init(); + } return 0; } block_wait(); From 73d2f2569f3c006fd8112eb77502dc995f924c8b Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Mon, 11 Jul 2016 13:50:13 -0400 Subject: [PATCH 33/37] Updates for tests --- Makefile | 1 + tests/parallel_alloc/rakefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4ae5cd0..05c851f 100644 --- a/Makefile +++ b/Makefile @@ -36,3 +36,4 @@ $(LIB): $(OBJS) clean: find -type f -name '*.[ios]' -delete rm -f $(LIB) tags cscope.out + find -type f -iname rakefile -execdir rake clean \; 2>/dev/null || true diff --git a/tests/parallel_alloc/rakefile b/tests/parallel_alloc/rakefile index a5f6d43..b551117 100755 --- a/tests/parallel_alloc/rakefile +++ b/tests/parallel_alloc/rakefile @@ -2,7 +2,7 @@ load '../bop_test.rake' $c_flags = '-g3' -$params = '200 2' +$params = '20 2' # bop_test 'add', nil, false # Orig version fails bop_test 'add_ppr_only' From d2d4840c75c274b207e34d8590807f1946f60672 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 13 Jul 2016 11:39:30 -0400 Subject: [PATCH 34/37] Revert "Don't just busy-wait - sleep(1) between wait()s" This reverts commit 44c7bce691afa82177534c392401aeb102f24c39. --- bop_ppr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/bop_ppr.c b/bop_ppr.c index e90d4fc..6d3a931 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -763,7 +763,6 @@ wait_process() status); // we only care about zero v. not-zero } unblock_wait(); - sleep(1); } errno = 0; // handle remaining processes. Above may not have gotten everything From 06a42cb20670b281dd90ff57b6dd048260090e56 Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 13 Jul 2016 13:15:15 -0400 Subject: [PATCH 35/37] Add level to bop_msg output --- utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.c b/utils.c index 2d3446a..77c7464 100644 --- a/utils.c +++ b/utils.c @@ -81,7 +81,7 @@ void bop_msg_va(int level, const char *msg, va_list v) { if (bop_verbose >= level) { - fprintf(stderr, "%d-", getpid()); + fprintf(stderr, "%d [%d] ", getpid(), level); char *pos; switch (ppr_pos) { From fb7f4d376ca49d15e29cb82e4d08b27b0204e44e Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Mon, 25 Jul 2016 13:14:17 -0400 Subject: [PATCH 36/37] Fix bugs in CBOP - Reset spec_order to 0 (not -1) when going from UNDY to MAIN - Don't hang when no child is left --- bop_ppr.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bop_ppr.c b/bop_ppr.c index 6d3a931..ec53e03 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -101,6 +101,7 @@ _ppr_group_init(void) static void _ppr_task_init(void) { + assert(spec_order >= 0); switch (task_status) { case MAIN: assert(spec_order == 0); @@ -343,6 +344,7 @@ post_ppr_undy(void) undy_succ_fini(); + spec_order = 0; task_status = SEQ; ppr_pos = GAP; bop_stats.num_by_undy += undy_ppr_count; @@ -755,12 +757,16 @@ wait_process() while (is_monitoring) { block_wait(); - if (((child = waitpid(monitor_group, &status, WNOHANG | WUNTRACED)) != - -1)) { + child = waitpid(monitor_group, &status, WNOHANG | WUNTRACED); + if (child != -1) { my_exit = my_exit || report_child(child, status); // we only care about zero v. not-zero + } else { + if (errno == ECHILD) { + is_monitoring = false; + } } unblock_wait(); } From d9544923313dc49ccc68f2d5c9e1422452fd7bae Mon Sep 17 00:00:00 2001 From: Joel Kottas Date: Wed, 27 Jul 2016 12:33:12 -0400 Subject: [PATCH 37/37] Hack wait fix with usleep; add unit_tests to tests --- Makefile | 2 +- bop_ppr.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 05c851f..9ea15c7 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ LDLIBS_ALL = -ldl $(LDLIBS) SRC := $(wildcard *.c) $(wildcard range_tree/*.c) $(wildcard external/*.c) OBJS = $(SRC:.c=.o) -TEST_DIRS = add sleep str/BOP_string str/strsub str/strsub2 parallel_alloc +TEST_DIRS = add sleep str/BOP_string str/strsub str/strsub2 parallel_alloc unit_tests .PHONY: all all: $(LIB) diff --git a/bop_ppr.c b/bop_ppr.c index ec53e03..f1499c6 100644 --- a/bop_ppr.c +++ b/bop_ppr.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include //BOP_msg locking @@ -770,6 +771,7 @@ wait_process() } unblock_wait(); } + usleep(10000); errno = 0; // handle remaining processes. Above may not have gotten everything block_wait();