diff --git a/backends/meson.build b/backends/meson.build index 7fc41c7c734ca75f7d395d56ca5c77dfb9f703c9..947cf1ca39acd9a76d49324c9c5f87e814ba53fd 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -1,5 +1,6 @@ subdir('emper') subdir('fibril') +subdir('nowa') subdir('openmp') subdir('serial-elision') subdir('tbb') diff --git a/backends/nowa/backend-nowa.cc b/backends/nowa/backend-nowa.cc new file mode 100644 index 0000000000000000000000000000000000000000..488e2d01f5b4db3a07f7ac043e292002193f8d6b --- /dev/null +++ b/backends/nowa/backend-nowa.cc @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright © 2021 Florian Schmaus +#include <functional> + +extern "C" { +auto fibril_rt_init(int nprocs) -> int; +auto fibril_rt_exit() -> int; +} + +auto mzs_rts_init(int nthreads) -> int { + fibril_rt_init(nthreads); + return 0; +} + +auto mzs_rts_exit() -> int { + fibril_rt_exit(); + return 0; +} + +void mzs_rts_enter(const std::function<void()>& function) { function(); } diff --git a/backends/nowa/concrete-mazstab-backend.hpp b/backends/nowa/concrete-mazstab-backend.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d0ce89da47cfc63e4f1a3bd595328636d4d0c2fc --- /dev/null +++ b/backends/nowa/concrete-mazstab-backend.hpp @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright © 2021 Florian Schmaus +#pragma once + +#include "fibril.hpp" + +// NOLINTNEXTLINE(clang-diagnostic-unknown-attributes) +#define mzs_sf fibril + +#define mzs_sf_state fibril_t + +#define mzs_init fibril_init + +// NOLINTNEXTLINE(clang-diagnostic-unknown-attributes) +#define mzs_spawn_nrt(sf_state, fn, ag) fibril_fork_nrt(sf_state, fn, ag) + +// NOLINTNEXTLINE(clang-diagnostic-unknown-attributes) +#define mzs_spawn_wrt(sf_state, rtp, fn, ag) fibril_fork_wrt(sf_state, rtp, fn, ag) + +#define mzs_sync(sf_state) fibril_join(sf_state) diff --git a/backends/nowa/fibril.hpp b/backends/nowa/fibril.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f5cf8648fa9b09afacd1d3ba23141b305ae53d79 --- /dev/null +++ b/backends/nowa/fibril.hpp @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright © 2021 Florian Schmaus +#pragma once + +// This is the combination of fibril.h and fibrile.h where fibril_fork +// uses lambda functions instead of inner C functions (which are a GCC +// extension and do not work with C++). Hence part of this is MIT +// licensed. + +#ifdef __cplusplus +extern "C" { +#endif + +#include "fibril/fibrili.h" + +#define FIBRIL_SUCCESS 0 +#define FIBRIL_FAILURE -1 + +/** + * These are special arguments to fibril_rt_init(). + * FIBRIL_NPROCS tells the runtime to fetch the number of processors + * from the environment variable FIBRIL_NPROCS (getenv(FIBRIL_NPROCS)). + * FIBRIL_NPROCS_ONLN tells the runtime to use all available processors + * in the system (sysconf(_SC_NPROCESSORS_ONLN)). + */ +#define FIBRIL_NPROCS 0 +#define FIBRIL_NPROCS_ONLN -1 + +/** fibril. */ +#define fibril __attribute__((optimize("no-omit-frame-pointer"))) + +/** fibril_t. */ +typedef struct _fibril_t fibril_t; + +/** fibril_init. */ +__attribute__((always_inline)) extern inline void fibril_init(fibril_t* frptr) { + register void* rbp asm("rbp"); + register void* rsp asm("rsp"); + + frptr->unmapped = 0; + frptr->count = 0; + frptr->steals = 0; + frptr->resumable = 0; + // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign) + frptr->stack.btm = rbp; + frptr->stack.top = rsp; + frptr->stack.ptr = fibrili_deq.stack; +} + +/** fibril_join. */ +__attribute__((always_inline)) extern inline void fibril_join(fibril_t* frptr) { + if (frptr->steals > 0) { + fibrili_membar(fibrili_join(frptr)); + frptr->steals = 0; + frptr->resumable = 0; + } +} + +#include "fibril/fork.h" + +/** _fibril_fork_nrt. */ +#define fibril_fork_nrt(fp, fn, ag) \ + do { \ + auto _fibril_##fn##_fork = \ + [](_fibril_defs ag fibril_t * f) __attribute__((noinline, hot, optimize(3))) { \ + fibrili_push(f); \ + fn(_fibril_args ag); \ + if (!fibrili_pop()) fibrili_resume(f, 1); \ + }; \ + fibrili_membar(_fibril_##fn##_fork(_fibril_expand ag fp)); \ + } while (0) + +/** _fibril_fork_wrt. */ +#define fibril_fork_wrt(fp, rtp, fn, ag) \ + do { \ + auto _fibril_##fn##_fork = [](_fibril_defs ag fibril_t * f, __typeof__(rtp) p) \ + __attribute__((noinline, hot, optimize(3))) { \ + fibrili_push(f); \ + *p = fn(_fibril_args ag); \ + if (!fibrili_pop()) fibrili_resume(f, 1); \ + }; \ + fibrili_membar(_fibril_##fn##_fork(_fibril_expand ag fp, rtp)); \ + } while (0) + +extern int fibril_rt_init(int nprocs); +extern int fibril_rt_exit(); +extern int fibril_rt_nprocs(); + +/** fibril_fork has two versions: one with return value and one without. */ +#define fibril_fork(...) _fibril_fork_(_fibril_nth(__VA_ARGS__), __VA_ARGS__) +#define _fibril_fork_(n, ...) _fibril_concat(_fibril_fork_, n)(__VA_ARGS__) + +/** If nargs is 3, use the no-return-value version. */ +#define _fibril_fork_3(...) fibril_fork_nrt(__VA_ARGS__) + +/** If nargs is 4, use the with-return-value version. */ +#define _fibril_fork_4(...) fibril_fork_wrt(__VA_ARGS__) + +/** Helper macros to count number of arguments. */ +#define _fibril_nth(...) \ + _fibril_nth_(__VA_ARGS__, ##__VA_ARGS__, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, \ + 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 0) +#define _fibril_nth_(_1, _1_, _2, _2_, _3, _3_, _4, _4_, _5, _5_, _6, _6_, _7, _7_, _8, _8_, _9, \ + _9_, _10, _10_, _11, _11_, _12, _12_, _13, _13_, _14, _14_, _15, _15_, _16, \ + _16_, N, ...) \ + N +#define _fibril_concat(left, right) left##right + +#ifdef __cplusplus +} +#endif diff --git a/backends/nowa/meson.build b/backends/nowa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..2e82196a395ca41422c6e798c25c9ae4b5d0b9fc --- /dev/null +++ b/backends/nowa/meson.build @@ -0,0 +1,38 @@ +backend_name = 'nowa' + +backend_conf_option = 'backend-' + backend_name +backend_option = get_option(backend_conf_option) +if backend_option + nowa_proj = subproject('nowa') + nowa_dep = nowa_proj.get_variable('nowa_dep') + + lib = library( + 'backend-nowa', + 'backend-nowa.cc', + dependencies: [common_dep, nowa_dep, threads_dep], + ) + + dep = declare_dependency( + include_directories: [include_directories('.')], + link_with: lib, + dependencies: nowa_dep, + ) + + c_compiler = meson.get_compiler('c') + c_compiler_id = c_compiler.get_id() + + unavailable_reason = '' + if c_compiler_id != 'gcc' + unavailable_reason = 'Backend ' + backend_name \ + + ' requires GCC (currently:' + c_compiler_id + ')' + endif + + libdir = get_option('libdir') + rpath = '$ORIGIN/subprojects/nowa/dist/usr/local/' + libdir + backends += { + 'name': backend_name, + 'dep': dep, + 'rpath': rpath, + 'unavailable_reason': unavailable_reason, + } +endif diff --git a/meson_options.txt b/meson_options.txt index f4767a610fd48e8380ae49fabb4b97806d0adfb3..b1972b92cc0869a2e2f25c527abcdbfd8da42b7b 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,6 +10,12 @@ option( value: true, description: 'Build the benchmarks with the Fibril backend' ) +option( + 'backend-nowa', + type: 'boolean', + value: true, + description: 'Build the benchmarks with the Nowa backend' +) option( 'backend-tbb', type: 'boolean', diff --git a/subprojects/.gitignore b/subprojects/.gitignore index 4c3a0d4e71ca8bf585e4eb27559a81f233f0e594..7c81d70b8d0546097bb0b004449d465b75320977 100644 --- a/subprojects/.gitignore +++ b/subprojects/.gitignore @@ -1,2 +1,3 @@ -/fibril/ /emper/ +/fibril/ +/nowa/ diff --git a/subprojects/fibril.wrap b/subprojects/fibril.wrap index ddb2515db24bdead20ad8e30e0ce4159eea48885..8e41946909eeaddc47f1ce155b5586fc48024a35 100644 --- a/subprojects/fibril.wrap +++ b/subprojects/fibril.wrap @@ -1,5 +1,6 @@ [wrap-git] -url = https://github.com/chaoran/fibril.git +# Actual home is https://github.com/chaoran/fibril.git +url = https://gitlab.cs.fau.de/i4/manycore/fibril.git revision = 9991aac319908136edebcee8607743e23d1b6894 depth = 1 patch_directory = fibril diff --git a/subprojects/nowa.wrap b/subprojects/nowa.wrap new file mode 100644 index 0000000000000000000000000000000000000000..2fcf1aad7709b87061aa2d084cbbe5f7b31a18d8 --- /dev/null +++ b/subprojects/nowa.wrap @@ -0,0 +1,5 @@ +[wrap-git] +url = https://gitlab.cs.fau.de/i4/manycore/nowa.git +revision = 213e5425c1dcc825636d92aad7ca6a90fe8443ab +depth = 1 +patch_directory = nowa diff --git a/subprojects/packagefiles/nowa/meson.build b/subprojects/packagefiles/nowa/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..1405633c039977a54cfae481f0b2eee8ad160473 --- /dev/null +++ b/subprojects/packagefiles/nowa/meson.build @@ -0,0 +1,18 @@ +project('nowa', 'c', + meson_version : '>=0.57.0', +) + +mod = import('unstable_external_project') + +bootstrap_command = run_command('bootstrap') +if bootstrap_command.returncode() != 0 + error('bootstrap failed') +endif + +p = mod.add_project( + 'configure', + verbose: true, +) + +# Nowa being based on Fibril produced a library called fibril. +nowa_dep = p.dependency('fibril')