diff --git a/build.sh b/build.sh index 2e3dbeb..a74d32b 100755 --- a/build.sh +++ b/build.sh @@ -8,8 +8,15 @@ EXAMPLES="format listdir range range_pipe signal" EXAMPLES="${EXAMPLES} stream1 stream2 coroutine1 coroutine2" # assembly sources +ASM_SOURCE_DIR="src/asm" ASM_SOURCES="jump_all_gas make_all_gas ontop_all_gas" -ASM_LIB="context.a" + +# c++ sources +CXX_SOURCE_DIR="src" +CXX_SOURCES="context_stack" + +# output lib +OSTD_LIB="libostd.a" # compiler if [ -z "$CXX" ]; then @@ -83,22 +90,25 @@ clean() { rm -f "examples/${ex}" "examples/${ex}.o" done for as in ${ASM_SOURCES}; do - rm -f "${as}.o" + rm -f "${ASM_SOURCE_DIR}/${as}.o" done - rm -f "$ASM_LIB" + for cs in ${CXX_SOURCES}; do + rm -f "${CXX_SOURCE_DIR}/${cs}.o" + done + rm -f "$OSTD_LIB" rm -f test_runner.o test_runner } # call_cxx input output call_cxx() { echo "CXX: $1" - eval "${CXX} ${OSTD_CPPFLAGS} ${OSTD_CXXFLAGS} -c -o ${2} ${1}" + eval "${CXX} ${OSTD_CPPFLAGS} ${OSTD_CXXFLAGS} -c -o \"${2}\" \"${1}\"" } # call_as input output call_as() { - echo "AS: src/asm/${1}" - eval "${CPP} -x assembler-with-cpp \"src/asm/${1}\" | ${AS} -o \"${2}\"" + echo "AS: $1" + eval "${CPP} -x assembler-with-cpp \"${1}\" | ${AS} -o \"${2}\"" } # call_ld output file1 file2 ... @@ -116,22 +126,22 @@ call_ldlib() { # build_example name build_example() { call_cxx "examples/${1}.cc" "examples/${1}.o" - call_ld "examples/${1}" "examples/${1}.o" "$ASM_LIB" - rm "examples/${1}.o" + call_ld "examples/${1}" "examples/${1}.o" "$OSTD_LIB" + rm -f "examples/${1}.o" } # build test runner build_test_runner() { call_cxx test_runner.cc test_runner.o - call_ld test_runner test_runner.o - rm test_runner.o + call_ld test_runner test_runner.o "$OSTD_LIB" + rm -f test_runner.o } -# add_ext str ext -add_ext() { +# add_sfx_pfx str sfx pfx +add_sfx_pfx() { RET="" for it in $1; do - RET="$RET ${it}${2}" + RET="$RET ${3}${it}${2}" done echo $RET } @@ -142,19 +152,26 @@ if [ "$1" = "clean" ]; then exit 0 fi +# build assembly +echo "Building the library..." +for as in $ASM_SOURCES; do + call_as "${ASM_SOURCE_DIR}/${as}.S" "${ASM_SOURCE_DIR}/${as}.o" & +done +for cs in $CXX_SOURCES; do + call_cxx "${CXX_SOURCE_DIR}/${cs}.cc" "${CXX_SOURCE_DIR}/${cs}.o" & +done +wait +call_ldlib "$OSTD_LIB" \ + $(add_sfx_pfx "$ASM_SOURCES" ".o" "$ASM_SOURCE_DIR/") \ + $(add_sfx_pfx "$CXX_SOURCES" ".o" "$CXX_SOURCE_DIR/") + +rm -f $(add_sfx_pfx "$ASM_SOURCES" ".o" "$ASM_SOURCE_DIR/") +rm -f $(add_sfx_pfx "$CXX_SOURCES" ".o" "$CXX_SOURCE_DIR/") + # build test runner echo "Building test runner..." build_test_runner & -# build assembly -echo "Running assembler..." -for as in $ASM_SOURCES; do - call_as "${as}.S" "${as}.o" & -done -wait -call_ldlib "$ASM_LIB" $(add_ext "$ASM_SOURCES" ".o") -rm $(add_ext "$ASM_SOURCES" ".o") - # build examples echo "Building examples..." for ex in $EXAMPLES; do diff --git a/ostd/context_stack.hh b/ostd/context_stack.hh index 9239f7f..26fd70d 100644 --- a/ostd/context_stack.hh +++ b/ostd/context_stack.hh @@ -7,14 +7,11 @@ #ifndef OSTD_CONTEXT_STACK_HH #define OSTD_CONTEXT_STACK_HH -#include -#include +#include #include -#include #include "ostd/types.hh" #include "ostd/platform.hh" -#include "ostd/internal/win32.hh" #if !defined(OSTD_PLATFORM_POSIX) && !defined(OSTD_PLATFORM_WIN32) # error "Unsupported platform" @@ -31,15 +28,6 @@ # define OSTD_CONTEXT_SEGMENTS 10 #endif - -#ifdef OSTD_PLATFORM_POSIX -# include -# include -# include -# include -# include -#endif - #ifdef OSTD_USE_VALGRIND # include #endif @@ -60,144 +48,18 @@ struct stack_context { #endif }; -namespace detail { - inline void ctx_pagesize(size_t *s) noexcept { -#if defined(OSTD_PLATFORM_WIN32) - SYSTEM_INFO si; - GetSystemInfo(&si); - *s = size_t(si.dwPageSize); -#elif defined(OSTD_PLATFORM_POSIX) - *s = size_t(sysconf(_SC_PAGESIZE)); -#endif - } - -#ifdef OSTD_PLATFORM_POSIX - inline void ctx_rlimit_get(rlimit *l) noexcept { - getrlimit(RLIMIT_STACK, l); - } - - inline rlimit ctx_rlimit() noexcept { - static rlimit l; - static std::once_flag fl; - std::call_once(fl, ctx_rlimit_get, &l); - return l; - } -#endif -} - -struct stack_traits { - static bool is_unbounded() noexcept { -#if defined(OSTD_PLATFORM_WIN32) - return true; -#elif defined(OSTD_PLATFORM_POSIX) - return detail::ctx_rlimit().rlim_max == RLIM_INFINITY; -#endif - } - - static size_t page_size() noexcept { - static size_t size = 0; - static std::once_flag fl; - std::call_once(fl, detail::ctx_pagesize, &size); - return size; - } - - static size_t minimum_size() noexcept { -#if defined(OSTD_PLATFORM_WIN32) - /* no func on windows, sane default */ - return sizeof(void *) * 1024; -#elif defined(OSTD_PLATFORM_POSIX) - return SIGSTKSZ; -#endif - } - - static size_t maximum_size() noexcept { -#if defined(OSTD_PLATFORM_WIN32) - /* no func on windows either */ - return 1024 * 1024 * 1024; -#elif defined(OSTD_PLATFORM_POSIX) - return size_t(detail::ctx_rlimit().rlim_max); -#endif - } - - static size_t default_size() noexcept { -#if defined(OSTD_PLATFORM_WIN32) - /* no func on windows either */ - return sizeof(void *) * minimum_size(); -#elif defined(OSTD_PLATFORM_POSIX) - size_t r = sizeof(void *) * minimum_size(); - if (is_unbounded()) { - return r; - } - size_t m = maximum_size(); - if (r > m) { - return m; - } - return r; -#endif - } +struct OSTD_EXPORT stack_traits { + static bool is_unbounded() noexcept; + static size_t page_size() noexcept; + static size_t minimum_size() noexcept; + static size_t maximum_size() noexcept; + static size_t default_size() noexcept; }; namespace detail { -#ifdef OSTD_PLATFORM_POSIX -# if defined(MAP_ANON) || defined(MAP_ANONYMOUS) - constexpr bool CONTEXT_USE_MMAP = true; -# ifdef MAP_ANON - constexpr auto CONTEXT_MAP_ANON = MAP_ANON; -# else -constexpr auto CONTEXT_MAP_ANON = MAP_ANONYMOUS; -# endif -# else -constexpr bool CONTEXT_USE_MMAP = false; -# endif -#endif - - inline void *stack_alloc(size_t sz) { -#if defined(OSTD_PLATFORM_WIN32) - void *p = VirtualAlloc(0, sz, MEM_COMMIT, PAGE_READWRITE); - if (!p) { - throw std::bad_alloc{} - } - return p; -#elif defined(OSTD_PLATFORM_POSIX) - if constexpr(CONTEXT_USE_MMAP) { - void *p = mmap( - 0, sz, PROT_READ | PROT_WRITE, - MAP_PRIVATE | CONTEXT_MAP_ANON, -1, 0 - ); - if (p == MAP_FAILED) { - throw std::bad_alloc{}; - } - return p; - } - void *p = std::malloc(sz); - if (!p) { - throw std::bad_alloc{}; - } - return p; -#endif - } - - inline void stack_free(void *p, size_t sz) { -#if defined(OSTD_PLATFORM_WIN32) - (void)sz; - VirtualFree(p, 0, MEM_RELEASE); -#elif defined(OSTD_PLATFORM_POSIX) - if constexpr(CONTEXT_USE_MMAP) { - munmap(p, sz); - } else { - std::free(p); - } -#endif - } - - inline void stack_protect(void *p, size_t sz) { -#if defined(OSTD_PLATFORM_WIN32) - DWORD oo; - VirtualProtect(p, sz, PAGE_READWRITE | PAGE_GUARD, &oo); -#elif defined(OSTD_PLATFORM_POSIX) - mprotect(p, sz, PROT_NONE); -#endif - } + OSTD_EXPORT void *stack_alloc(size_t sz); + OSTD_EXPORT void stack_free(void *p, size_t sz) noexcept; + OSTD_EXPORT void stack_protect(void *p, size_t sz) noexcept; } template diff --git a/src/context_stack.cc b/src/context_stack.cc new file mode 100644 index 0000000..a2f6c4b --- /dev/null +++ b/src/context_stack.cc @@ -0,0 +1,161 @@ +/* Stack allocation implementation for coroutine contexts. + * + * This file is part of OctaSTD. See COPYING.md for futher information. + */ + +#include +#include +#include + +#include "ostd/internal/win32.hh" +#include "ostd/platform.hh" +#include "ostd/context_stack.hh" + +#ifdef OSTD_PLATFORM_POSIX +# include +# include +# include +# include +# include +#endif + +namespace ostd { + +namespace detail { +#ifdef OSTD_PLATFORM_POSIX +# if defined(MAP_ANON) || defined(MAP_ANONYMOUS) + constexpr bool CONTEXT_USE_MMAP = true; +# ifdef MAP_ANON + constexpr auto CONTEXT_MAP_ANON = MAP_ANON; +# else + constexpr auto CONTEXT_MAP_ANON = MAP_ANONYMOUS; +# endif +# else + constexpr bool CONTEXT_USE_MMAP = false; +# endif +#endif + + OSTD_EXPORT void *stack_alloc(size_t sz) { +#if defined(OSTD_PLATFORM_WIN32) + void *p = VirtualAlloc(0, sz, MEM_COMMIT, PAGE_READWRITE); + if (!p) { + throw std::bad_alloc{} + } + return p; +#elif defined(OSTD_PLATFORM_POSIX) + if constexpr(CONTEXT_USE_MMAP) { + void *p = mmap( + 0, sz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | CONTEXT_MAP_ANON, -1, 0 + ); + if (p == MAP_FAILED) { + throw std::bad_alloc{}; + } + return p; + } + void *p = std::malloc(sz); + if (!p) { + throw std::bad_alloc{}; + } + return p; +#endif + } + + OSTD_EXPORT void stack_free(void *p, size_t sz) noexcept { +#if defined(OSTD_PLATFORM_WIN32) + (void)sz; + VirtualFree(p, 0, MEM_RELEASE); +#elif defined(OSTD_PLATFORM_POSIX) + if constexpr(CONTEXT_USE_MMAP) { + munmap(p, sz); + } else { + std::free(p); + } +#endif + } + + OSTD_EXPORT void stack_protect(void *p, size_t sz) noexcept { +#if defined(OSTD_PLATFORM_WIN32) + DWORD oo; + VirtualProtect(p, sz, PAGE_READWRITE | PAGE_GUARD, &oo); +#elif defined(OSTD_PLATFORM_POSIX) + mprotect(p, sz, PROT_NONE); +#endif + } + + /* used by stack traits */ + inline void ctx_pagesize(size_t *s) noexcept { +#if defined(OSTD_PLATFORM_WIN32) + SYSTEM_INFO si; + GetSystemInfo(&si); + *s = size_t(si.dwPageSize); +#elif defined(OSTD_PLATFORM_POSIX) + *s = size_t(sysconf(_SC_PAGESIZE)); +#endif + } + +#ifdef OSTD_PLATFORM_POSIX + inline void ctx_rlimit_get(rlimit *l) noexcept { + getrlimit(RLIMIT_STACK, l); + } + + inline rlimit ctx_rlimit() noexcept { + static rlimit l; + static std::once_flag fl; + std::call_once(fl, ctx_rlimit_get, &l); + return l; + } +#endif +} /* namespace detail */ + +bool stack_traits::is_unbounded() noexcept { +#if defined(OSTD_PLATFORM_WIN32) + return true; +#elif defined(OSTD_PLATFORM_POSIX) + return detail::ctx_rlimit().rlim_max == RLIM_INFINITY; +#endif +} + +size_t stack_traits::page_size() noexcept { + static size_t size = 0; + static std::once_flag fl; + std::call_once(fl, detail::ctx_pagesize, &size); + return size; +} + +size_t stack_traits::minimum_size() noexcept { +#if defined(OSTD_PLATFORM_WIN32) + /* no func on windows, sane default */ + return sizeof(void *) * 1024; +#elif defined(OSTD_PLATFORM_POSIX) + return SIGSTKSZ; +#endif +} + +size_t stack_traits::maximum_size() noexcept { +#if defined(OSTD_PLATFORM_WIN32) + /* no func on windows either */ + return 1024 * 1024 * 1024; +#elif defined(OSTD_PLATFORM_POSIX) + return size_t(detail::ctx_rlimit().rlim_max); +#endif +} + +size_t stack_traits::default_size() noexcept { +#if defined(OSTD_PLATFORM_WIN32) + /* no func on windows either */ + return sizeof(void *) * minimum_size(); +#elif defined(OSTD_PLATFORM_POSIX) + size_t r = sizeof(void *) * minimum_size(); + if (is_unbounded()) { + return r; + } + size_t m = maximum_size(); + if (r > m) { + return m; + } + return r; +#endif +} + +} /* namespace ostd */