move the stack alloc impl bits into a source file
This commit is contained in:
parent
fb592f8c2c
commit
5fafcdf954
61
build.sh
61
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
|
||||
|
|
|
@ -7,14 +7,11 @@
|
|||
#ifndef OSTD_CONTEXT_STACK_HH
|
||||
#define OSTD_CONTEXT_STACK_HH
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
|
||||
#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 <unistd.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/resource.h>
|
||||
# include <sys/time.h>
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifdef OSTD_USE_VALGRIND
|
||||
# include <valgrind/valgrind.h>
|
||||
#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<typename TR, bool Protected>
|
||||
|
|
161
src/context_stack.cc
Normal file
161
src/context_stack.cc
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* Stack allocation implementation for coroutine contexts.
|
||||
*
|
||||
* This file is part of OctaSTD. See COPYING.md for futher information.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
#include <mutex>
|
||||
|
||||
#include "ostd/internal/win32.hh"
|
||||
#include "ostd/platform.hh"
|
||||
#include "ostd/context_stack.hh"
|
||||
|
||||
#ifdef OSTD_PLATFORM_POSIX
|
||||
# include <unistd.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/resource.h>
|
||||
# include <sys/time.h>
|
||||
# include <signal.h>
|
||||
#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 */
|
Loading…
Reference in a new issue