diff --git a/Makefile b/Makefile index 912af0d..deb0aa9 100644 --- a/Makefile +++ b/Makefile @@ -20,13 +20,17 @@ SRC_CXX = $(wildcard src/*.cpp) INCLUDE=include +# Set compile-time features +# * PARALLEL - Enable multithreaded processing +FEATURES?=PARALLEL + META_FLAGS:=-D_PROJECT_AUTHOR="\"$(AUTHOR)\"" -D_PROJECT_DESCRIPTION="\"$(DESCRIPTION)\"" -D_PROJECT_NAME="\"$(PROJECT)\"" \ -D_PROJECT_LICENSE="\"$(LICENSE)\"" \ -D_VERSION_MAJOR=$(VERSION_MAJ) -D_VERSION_MINOR=$(VERSION_MIN) \ -D_VERSION_BUGFIX=$(VERSION_BF) -D_VERSION_REVISION=$(VERSION_REV) \ -D_PROJECT_COMPILED=$(COMP_TIME) -COMMON_FLAGS+= -W -Wall -fno-strict-aliasing $(addprefix -I,$(INCLUDE)) $(META_FLAGS) +COMMON_FLAGS+= -W -Wall -fno-strict-aliasing $(addprefix -I,$(INCLUDE)) $(META_FLAGS) $(addprefix -D_FEATURE_,$(FEATURES)) ARCH?=native OPT_FLAGS+= -fgraphite -fopenmp -floop-parallelize-all -ftree-parallelize-loops=4 \ diff --git a/include/comp.h b/include/comp.h index ab52503..ff3ea60 100644 --- a/include/comp.h +++ b/include/comp.h @@ -4,6 +4,20 @@ #include #include +typedef struct comp_aggregate { + bool all_matched; + + int idx_first_failure; + + usize num_results; + struct comp_single_result { + map_t* _shared mapping; + + bool matched; + usize slice_start; + } aggr[]; +} comp_multires_t; + /// Find `needle` in `haystack`, sets the start of `needle`'s `origin` in `haystack`'s to `pos` and returns `true` if a match is found, otherwise returns false. bool cmp_find(const map_t *pIN needle, const map_t *pIN haystack, usize *pOUT pos); /// Check `needle` against `nhaystacks` number of haystack maps, store the offset in `sizes[n]` where `n` is the haystack number. @@ -12,6 +26,9 @@ bool cmp_find(const map_t *pIN needle, const map_t *pIN haystack, usize *pOUT po /// /// # Panics /// Will `FATAL` if any of the haystack pointers are `NULL` -int cmp_find_many(usize nhaystacks; const map_t *pIN needle, usize sizes[pOUT nhaystacks], usize nhaystacks, ...); +int cmp_find_many(const map_t *pIN needle, usize nhaystacks, usize sizes[pOUT nhaystacks], ...); + +// The return value of this function must be `free()`d after use +comp_multires_t* comp_match_all(map_t *pIN needle, usize nh, map_t hs[pIN nh], bool abort_on_fail); #endif /* _COMP_H */ diff --git a/src/comp.c b/src/comp.c index 74f3185..c2b65d2 100644 --- a/src/comp.c +++ b/src/comp.c @@ -1,5 +1,6 @@ #define _GNU_SOURCE +#include #include #include @@ -7,6 +8,8 @@ #include #include +#include + bool cmp_find(const map_t *pIN needle, const map_t *pIN haystack, usize *pOUT pos) { @@ -14,15 +17,15 @@ bool cmp_find(const map_t *pIN needle, const map_t *pIN haystack, usize *pOUT po u8* substr = memmem(start = haystack->origin, haystack->len, needle->origin, needle->len); if(!substr) return false; - debug_assert(substr > start); + debug_assert(substr >= start); *pos = (usize) (substr - start); return true; } -int cmp_find_many(usize nhaystacks; const map_t *pIN needle, usize sizes[pOUT nhaystacks], usize nhaystacks, ...) +int cmp_find_many(const map_t *pIN needle, usize nhaystacks, usize sizes[pOUT nhaystacks], ...) { va_list v_haystacks; - va_start(v_haystacks, nhaystacks); + va_start(v_haystacks, sizes); const map_t* pINOUT haystack; register int rval=-1; @@ -40,3 +43,46 @@ int cmp_find_many(usize nhaystacks; const map_t *pIN needle, usize sizes[pOUT nh va_end(v_haystacks); return rval; } + +comp_multires_t* comp_match_all(map_t *pIN needle, usize nh, map_t hs[pIN nh], bool abort_on_fail) +{ + comp_multires_t* result = malloc(sizeof(comp_multires_t) + (sizeof(struct comp_single_result) * nh)); + debug_assert(result); + + result->all_matched = true; + result->idx_first_failure = -1; + result->num_results = nh; + + + usize i; + for(i =0;iaggr[i] = res; + if(!res.matched) { + WARN("Matching haystack %lu failed", i); + result->all_matched = false; + if(result->idx_first_failure < 0) { + INFO("First match failure is %lu", i); + result->idx_first_failure = (int)i; + } + if(abort_on_fail) { + result->num_results = i; + break; + } + } + } + INFO("Aggregate result for %lu / %lu haystack matches: Full passed: %s, first filaure: %d", + i, nh, + result->all_matched ? "yes" : "no", + result->idx_first_failure); + TRACE("Output result aggregate size: %lu (alloc: %p)", sizeof(comp_multires_t) + (sizeof(struct comp_single_result) * nh), result); + return result; +} diff --git a/src/main.c b/src/main.c index c3d23c4..804ad8a 100644 --- a/src/main.c +++ b/src/main.c @@ -88,18 +88,28 @@ inv_args: // Remove exe name from argv: now is (needle, haystacks...) argv+=1; // Setup haystack maps - map_t haystacks[argc-2]; - TRACE("Attempting to map %d haystacks", argc-2); + usize hsn = AS(argc-2, usize); + map_t haystacks[hsn]; + TRACE("Attempting to map %lu haystacks", hsn); if(!map_haystacks((const char**)(argv+1), haystacks)) return PROG_RET_MAP_HAYSTACK_FAILED; - + +#ifdef _FEATURE_PARALLEL // Multi-threaded //TODO: Setup thread-pool. //TODO: Dispatch haystack maps to threadpool. //TODO: Use either `cmp_find()` or `cmp_find_many()` to find the `needle` (mapped above) within those haystacks. //TODO: Within the threadpool: output information regarding each match/nonmatch. //TODO: Join the threadpool and consolidate results. //TODO: Iterate through the haystack numbers match results, return the first non-match haystack number through `PROG_RET_MATCH_HAYSTACK_N_FAILED(n)` (haystack numbers are always nonzero). If all were matched, return 0 +#else // Single-threaded + INFO("Computing result for %lu haystacks...", hsn); + comp_multires_t* full_result = comp_match_all(&needle, hsn, haystacks, false); + // Number of results actually computed by `comp_match_all()` may differ from `hsn` if `abort_on_fail` is true (currently its hardcoded to false but that may change.) + usize cres = full_result->num_results; + INFO("Computed result: Suc. Matched %lu / %lu hs. Full match: %s (first failure: %d)", cres, hsn, full_result->all_matched ? "yes" : "no", full_result->idx_first_failure); + free(full_result); +#endif - for(int i=0;i<(argc-2);i++) { + for(int i=0;i<(int)hsn;i++) { INFO("Unmapping haystack haystack file `%s' (#%d) (map addr %p)", argv[i+1], i+1, haystacks+i); if(!map_handle_err(map_free(haystacks[i]))) return PROG_RET_UNMAP_HAYSTACK_N_FAILED(i+1); } diff --git a/vgcore.6232 b/vgcore.6232 new file mode 100644 index 0000000..d0387c5 Binary files /dev/null and b/vgcore.6232 differ diff --git a/vgcore.6246 b/vgcore.6246 new file mode 100644 index 0000000..84c69b9 Binary files /dev/null and b/vgcore.6246 differ