move the stack alloc impl bits into a source file

master
Daniel Kolesa 2017-03-09 00:59:10 +01:00
parent fb592f8c2c
commit 5fafcdf954
3 changed files with 210 additions and 170 deletions

View File

@ -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

View File

@ -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>

View 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 */