move the stack alloc impl bits into a source file
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"
|
EXAMPLES="${EXAMPLES} stream1 stream2 coroutine1 coroutine2"
|
||||||
|
|
||||||
# assembly sources
|
# assembly sources
|
||||||
|
ASM_SOURCE_DIR="src/asm"
|
||||||
ASM_SOURCES="jump_all_gas make_all_gas ontop_all_gas"
|
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
|
# compiler
|
||||||
if [ -z "$CXX" ]; then
|
if [ -z "$CXX" ]; then
|
||||||
|
@ -83,22 +90,25 @@ clean() {
|
||||||
rm -f "examples/${ex}" "examples/${ex}.o"
|
rm -f "examples/${ex}" "examples/${ex}.o"
|
||||||
done
|
done
|
||||||
for as in ${ASM_SOURCES}; do
|
for as in ${ASM_SOURCES}; do
|
||||||
rm -f "${as}.o"
|
rm -f "${ASM_SOURCE_DIR}/${as}.o"
|
||||||
done
|
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
|
rm -f test_runner.o test_runner
|
||||||
}
|
}
|
||||||
|
|
||||||
# call_cxx input output
|
# call_cxx input output
|
||||||
call_cxx() {
|
call_cxx() {
|
||||||
echo "CXX: $1"
|
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 input output
|
||||||
call_as() {
|
call_as() {
|
||||||
echo "AS: src/asm/${1}"
|
echo "AS: $1"
|
||||||
eval "${CPP} -x assembler-with-cpp \"src/asm/${1}\" | ${AS} -o \"${2}\""
|
eval "${CPP} -x assembler-with-cpp \"${1}\" | ${AS} -o \"${2}\""
|
||||||
}
|
}
|
||||||
|
|
||||||
# call_ld output file1 file2 ...
|
# call_ld output file1 file2 ...
|
||||||
|
@ -116,22 +126,22 @@ call_ldlib() {
|
||||||
# build_example name
|
# build_example name
|
||||||
build_example() {
|
build_example() {
|
||||||
call_cxx "examples/${1}.cc" "examples/${1}.o"
|
call_cxx "examples/${1}.cc" "examples/${1}.o"
|
||||||
call_ld "examples/${1}" "examples/${1}.o" "$ASM_LIB"
|
call_ld "examples/${1}" "examples/${1}.o" "$OSTD_LIB"
|
||||||
rm "examples/${1}.o"
|
rm -f "examples/${1}.o"
|
||||||
}
|
}
|
||||||
|
|
||||||
# build test runner
|
# build test runner
|
||||||
build_test_runner() {
|
build_test_runner() {
|
||||||
call_cxx test_runner.cc test_runner.o
|
call_cxx test_runner.cc test_runner.o
|
||||||
call_ld test_runner test_runner.o
|
call_ld test_runner test_runner.o "$OSTD_LIB"
|
||||||
rm test_runner.o
|
rm -f test_runner.o
|
||||||
}
|
}
|
||||||
|
|
||||||
# add_ext str ext
|
# add_sfx_pfx str sfx pfx
|
||||||
add_ext() {
|
add_sfx_pfx() {
|
||||||
RET=""
|
RET=""
|
||||||
for it in $1; do
|
for it in $1; do
|
||||||
RET="$RET ${it}${2}"
|
RET="$RET ${3}${it}${2}"
|
||||||
done
|
done
|
||||||
echo $RET
|
echo $RET
|
||||||
}
|
}
|
||||||
|
@ -142,19 +152,26 @@ if [ "$1" = "clean" ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
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
|
# build test runner
|
||||||
echo "Building test runner..."
|
echo "Building test runner..."
|
||||||
build_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
|
# build examples
|
||||||
echo "Building examples..."
|
echo "Building examples..."
|
||||||
for ex in $EXAMPLES; do
|
for ex in $EXAMPLES; do
|
||||||
|
|
|
@ -7,14 +7,11 @@
|
||||||
#ifndef OSTD_CONTEXT_STACK_HH
|
#ifndef OSTD_CONTEXT_STACK_HH
|
||||||
#define OSTD_CONTEXT_STACK_HH
|
#define OSTD_CONTEXT_STACK_HH
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <new>
|
||||||
#include <exception>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include "ostd/types.hh"
|
#include "ostd/types.hh"
|
||||||
#include "ostd/platform.hh"
|
#include "ostd/platform.hh"
|
||||||
#include "ostd/internal/win32.hh"
|
|
||||||
|
|
||||||
#if !defined(OSTD_PLATFORM_POSIX) && !defined(OSTD_PLATFORM_WIN32)
|
#if !defined(OSTD_PLATFORM_POSIX) && !defined(OSTD_PLATFORM_WIN32)
|
||||||
# error "Unsupported platform"
|
# error "Unsupported platform"
|
||||||
|
@ -31,15 +28,6 @@
|
||||||
# define OSTD_CONTEXT_SEGMENTS 10
|
# define OSTD_CONTEXT_SEGMENTS 10
|
||||||
#endif
|
#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
|
#ifdef OSTD_USE_VALGRIND
|
||||||
# include <valgrind/valgrind.h>
|
# include <valgrind/valgrind.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -60,144 +48,18 @@ struct stack_context {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
struct OSTD_EXPORT stack_traits {
|
||||||
inline void ctx_pagesize(size_t *s) noexcept {
|
static bool is_unbounded() noexcept;
|
||||||
#if defined(OSTD_PLATFORM_WIN32)
|
static size_t page_size() noexcept;
|
||||||
SYSTEM_INFO si;
|
static size_t minimum_size() noexcept;
|
||||||
GetSystemInfo(&si);
|
static size_t maximum_size() noexcept;
|
||||||
*s = size_t(si.dwPageSize);
|
static size_t default_size() noexcept;
|
||||||
#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
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
#ifdef OSTD_PLATFORM_POSIX
|
OSTD_EXPORT void *stack_alloc(size_t sz);
|
||||||
# if defined(MAP_ANON) || defined(MAP_ANONYMOUS)
|
OSTD_EXPORT void stack_free(void *p, size_t sz) noexcept;
|
||||||
constexpr bool CONTEXT_USE_MMAP = true;
|
OSTD_EXPORT void stack_protect(void *p, size_t sz) noexcept;
|
||||||
# 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TR, bool Protected>
|
template<typename TR, bool Protected>
|
||||||
|
|
|
@ -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 New Issue