Skip to content

Commit

Permalink
Merge pull request #121 from kernigh/kernigh-openbsd
Browse files Browse the repository at this point in the history
Use mmap(2) MAP_STACK to allocate stacks on OpenBSD
  • Loading branch information
olk authored Oct 4, 2019
2 parents 14b4f45 + 7e14ab9 commit a4bdc60
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 3 deletions.
5 changes: 5 additions & 0 deletions include/boost/context/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,9 @@ static constexpr std::size_t prefetch_stride{ 4 * cacheline_length };
# include <cxxabi.h>
#endif

#if defined(__OpenBSD__)
// stacks need mmap(2) with MAP_STACK
# define BOOST_CONTEXT_USE_MAP_STACK
#endif

#endif // BOOST_CONTEXT_DETAIL_CONFIG_H
17 changes: 17 additions & 0 deletions include/boost/context/fixedsize_stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
#include <boost/context/stack_context.hpp>
#include <boost/context/stack_traits.hpp>

#if defined(BOOST_CONTEXT_USE_MAP_STACK)
extern "C" {
#include <sys/mman.h>
}
#endif

#if defined(BOOST_USE_VALGRIND)
#include <valgrind/valgrind.h>
#endif
Expand All @@ -42,10 +48,17 @@ class basic_fixedsize_stack {
}

stack_context allocate() {
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
void * vp = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
if ( vp == MAP_FAILED) {
throw std::bad_alloc();
}
#else
void * vp = std::malloc( size_);
if ( ! vp) {
throw std::bad_alloc();
}
#endif
stack_context sctx;
sctx.size = size_;
sctx.sp = static_cast< char * >( vp) + sctx.size;
Expand All @@ -62,7 +75,11 @@ class basic_fixedsize_stack {
VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
#endif
void * vp = static_cast< char * >( sctx.sp) - sctx.size;
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
::munmap( vp, sctx.size);
#else
std::free( vp);
#endif
}
};

Expand Down
36 changes: 36 additions & 0 deletions include/boost/context/pooled_fixedsize_stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
#include <boost/context/stack_context.hpp>
#include <boost/context/stack_traits.hpp>

#if defined(BOOST_CONTEXT_USE_MAP_STACK)
extern "C" {
#include <sys/mman.h>
#include <stdlib.h>
}
#endif

#if defined(BOOST_USE_VALGRIND)
#include <valgrind/valgrind.h>
#endif
Expand All @@ -32,14 +39,43 @@
namespace boost {
namespace context {

#if defined(BOOST_CONTEXT_USE_MAP_STACK)
namespace detail {
template< typename traitsT >
struct map_stack_allocator {
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;

static char * malloc( const size_type bytes) {
void * block;
if ( ::posix_memalign( &block, traitsT::page_size(), bytes) != 0) {
return 0;
}
if ( mmap( block, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_STACK, -1, 0) == MAP_FAILED) {
std::free( block);
return 0;
}
return reinterpret_cast< char * >( block);
}
static void free( char * const block) {
std::free( block);
}
};
}
#endif

template< typename traitsT >
class basic_pooled_fixedsize_stack {
private:
class storage {
private:
std::atomic< std::size_t > use_count_;
std::size_t stack_size_;
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
boost::pool< detail::map_stack_allocator< traitsT > > storage_;
#else
boost::pool< boost::default_user_allocator_malloc_free > storage_;
#endif

public:
storage( std::size_t stack_size, std::size_t next_size, std::size_t max_size) :
Expand Down
5 changes: 3 additions & 2 deletions include/boost/context/posix/protected_fixedsize_stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ class basic_protected_fixedsize_stack {
// add one page at bottom that will be used as guard-page
const std::size_t size__ = ( pages + 1) * traits_type::page_size();

// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
#if defined(MAP_ANON)
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
#elif defined(MAP_ANON)
void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#else
void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Expand Down
4 changes: 3 additions & 1 deletion test/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ project boost/context/test
rule native-impl ( properties * )
{
local result ;
if ( <target-os>darwin in $(properties) || <target-os>android in $(properties) )
if ( <target-os>android in $(properties) ||
<target-os>darwin in $(properties) ||
<target-os>openbsd in $(properties) )
{
result = <build>no ;
}
Expand Down

0 comments on commit a4bdc60

Please sign in to comment.