From 0739dc63936d66e23a31867d8e214de9fcaf54d4 Mon Sep 17 00:00:00 2001 From: Avril Date: Mon, 5 Jul 2021 22:09:59 +0100 Subject: [PATCH] C: added `madvise()` calls for sequential map preloading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fortune for fcmp's current commit: Half blessing − 半吉 --- include/map.h | 1 + src/main.c | 21 ++++++++++++++++++++- src/map.c | 29 +++++++++++++++++++++++++++-- src/sched.c | 4 +++- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/include/map.h b/include/map.h index 7574cf2..79e7c7f 100644 --- a/include/map.h +++ b/include/map.h @@ -17,6 +17,7 @@ typedef struct mmap { int open_and_map(const char* file, mmap_t* restrict ptr); int unmap_and_close(mmap_t map); +int set_preload_map(mmap_t* restrict map); #ifdef _cplusplus } diff --git a/src/main.c b/src/main.c index 853d40a..c0de377 100644 --- a/src/main.c +++ b/src/main.c @@ -56,6 +56,12 @@ static int compare_then_close(const mmap_t * restrict map1, mmap_t map2) return rval; } +static void prep_map(mmap_t* restrict map) +{ + if(!set_preload_map(map)) + fprintf(stderr, "Error: failed to prep map %p (%d), continuing anyway\n", map->ptr, map->fd); +} + #ifdef _RUN_THREADED struct t_task { _Atomic int* _ALIAS othis; @@ -81,7 +87,10 @@ void proc_thread(vec_t* restrict v_tasks) { for(register int i=0;ilen;i++) { + // Copy map into local buffer mrest[i] = tasks[i].mthis; + // Prep this map + prep_map(&mrest[i]); #ifdef DEBUG frest[i] = tasks[i].fthis; #endif @@ -137,6 +146,9 @@ int main(int argc, char** argv) return -1; } + // Prep map 1 + prep_map(&map1); + for(register int i=0;i +static inline int _map_advise(const mmap_t* restrict map, int adv) +{ + return madvise(map->ptr, map->len, adv); +} + +int set_preload_map(mmap_t* restrict map) +{ + if(_map_advise(map, ADVICE) != 0) { + perror("failed to advise kernel about mapped page(s)"); + return 0; + } + return 1; +} + int open_and_map(const char* file, mmap_t* restrict ptr) { int fd; @@ -27,7 +45,7 @@ int open_and_map(const char* file, mmap_t* restrict ptr) return 0; } - register struct mmap map = { .fd = fd, .ptr = NULL, .len = st.st_size }; + struct mmap map = { .fd = fd, .ptr = NULL, .len = st.st_size }; if ((map.ptr = mmap(NULL, map.len, PROT_READ, MAP_SHARED,fd, 0)) == MAP_FAILED) { perror("mmap() failed"); @@ -35,8 +53,15 @@ int open_and_map(const char* file, mmap_t* restrict ptr) return 0; } + if(_map_advise(&map, DEFAULT_ADVICE) != 0) { + perror("madvise(): failed to set default advice"); + //XXX: Should this be a hard error, or should we return the map if this fails anyway? + unmap_and_close(map); + return 0; + } + *ptr = map; - + return 1; } diff --git a/src/sched.c b/src/sched.c index 37fb2e4..95425a0 100644 --- a/src/sched.c +++ b/src/sched.c @@ -28,7 +28,9 @@ static void* _spawn(void* _arg) bool sched_should(size_t ntasks) { - register size_t num = num_cpus(); + static size_t num = 0; + // XXX: This is not thread-safe, but this function is only ever called by the main thread, so... + if(!num) num = num_cpus(); return (num > 1 && ntasks > 1); }