|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r86533 - trunk/libs/coroutine/src/detail
From: oliver.kowalke_at_[hidden]
Date: 2013-11-01 10:07:06
Author: olli
Date: 2013-11-01 10:07:06 EDT (Fri, 01 Nov 2013)
New Revision: 86533
URL: http://svn.boost.org/trac/boost/changeset/86533
Log:
coroutine: fix calculating page-count in stackallocator
Text files modified:
trunk/libs/coroutine/src/detail/standard_stack_allocator_posix.cpp | 6 +
trunk/libs/coroutine/src/detail/standard_stack_allocator_windows.cpp | 120 +++++++++++++++++++++------------------
2 files changed, 69 insertions(+), 57 deletions(-)
Modified: trunk/libs/coroutine/src/detail/standard_stack_allocator_posix.cpp
==============================================================================
--- trunk/libs/coroutine/src/detail/standard_stack_allocator_posix.cpp Fri Nov 1 05:32:55 2013 (r86532)
+++ trunk/libs/coroutine/src/detail/standard_stack_allocator_posix.cpp 2013-11-01 10:07:06 EDT (Fri, 01 Nov 2013) (r86533)
@@ -71,7 +71,7 @@
std::size_t page_count( std::size_t stacksize)
{
return static_cast< std::size_t >(
- std::ceil(
+ std::floor(
static_cast< float >( stacksize) / pagesize() ) );
}
@@ -108,9 +108,11 @@
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
- const std::size_t pages( detail::page_count( size) + 1); // add one guard page
+ const std::size_t pages( detail::page_count( size) ); // page at bottom will be used as guard-page
+ BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
const std::size_t size_( pages * detail::pagesize() );
BOOST_ASSERT( 0 < size && 0 < size_);
+ BOOST_ASSERT( size_ <= size);
const int fd( ::open("/dev/zero", O_RDONLY) );
BOOST_ASSERT( -1 != fd);
Modified: trunk/libs/coroutine/src/detail/standard_stack_allocator_windows.cpp
==============================================================================
--- trunk/libs/coroutine/src/detail/standard_stack_allocator_windows.cpp Fri Nov 1 05:32:55 2013 (r86532)
+++ trunk/libs/coroutine/src/detail/standard_stack_allocator_windows.cpp 2013-11-01 10:07:06 EDT (Fri, 01 Nov 2013) (r86533)
@@ -7,40 +7,31 @@
#include "boost/coroutine/detail/standard_stack_allocator.hpp"
extern "C" {
-#include <windows.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
}
-//#if defined (BOOST_WINDOWS) || _POSIX_C_SOURCE >= 200112L
+//#if _POSIX_C_SOURCE >= 200112L
#include <algorithm>
#include <cmath>
-#include <cstddef>
#include <cstring>
#include <stdexcept>
#include <boost/assert.hpp>
-#include <boost/context/detail/config.hpp>
#include <boost/context/fcontext.hpp>
#include <boost/coroutine/stack_context.hpp>
-# if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable:4244 4267)
-# endif
-
-// x86_64
-// test x86_64 before i386 because icc might
-// define __i686__ for x86_64 too
-#if defined(__x86_64__) || defined(__x86_64) \
- || defined(__amd64__) || defined(__amd64) \
- || defined(_M_X64) || defined(_M_AMD64)
-
-// Windows seams not to provide a constant or function
-// telling the minimal stacksize
-# define MIN_STACKSIZE 8 * 1024
-#else
-# define MIN_STACKSIZE 4 * 1024
+#if !defined (SIGSTKSZ)
+# define SIGSTKSZ (8 * 1024)
+# define UDEF_SIGSTKSZ
#endif
#ifdef BOOST_HAS_ABI_HEADERS
@@ -51,59 +42,64 @@
namespace coroutines {
namespace detail {
-SYSTEM_INFO system_info_()
+std::size_t pagesize()
{
- SYSTEM_INFO si;
- ::GetSystemInfo( & si);
- return si;
+ // conform to POSIX.1-2001
+ static std::size_t size = ::sysconf( _SC_PAGESIZE);
+ return size;
}
-SYSTEM_INFO system_info()
+rlimit stacksize_limit_()
{
- static SYSTEM_INFO si = system_info_();
- return si;
+ rlimit limit;
+ // conforming to POSIX.1-2001
+#if defined(BOOST_DISABLE_ASSERTS)
+ ::getrlimit( RLIMIT_STACK, & limit);
+#else
+ const int result = ::getrlimit( RLIMIT_STACK, & limit);
+ BOOST_ASSERT( 0 == result);
+#endif
+ return limit;
}
-std::size_t pagesize()
-{ return static_cast< std::size_t >( system_info().dwPageSize); }
+rlimit stacksize_limit()
+{
+ static rlimit limit = stacksize_limit_();
+ return limit;
+}
std::size_t page_count( std::size_t stacksize)
{
- return static_cast< std::size_t >(
- std::ceil(
+ return static_cast< std::size_t >(
+ std::floor(
static_cast< float >( stacksize) / pagesize() ) );
}
-// Windows seams not to provide a limit for the stacksize
bool
standard_stack_allocator::is_stack_unbound()
-{ return true; }
+{ return RLIM_INFINITY == detail::stacksize_limit().rlim_max; }
std::size_t
standard_stack_allocator::default_stacksize()
{
- std::size_t size = 64 * 1024; // 64 kB
- if ( is_stack_unbound() )
- return (std::max)( size, minimum_stacksize() );
+ std::size_t size = 8 * minimum_stacksize();
+ if ( is_stack_unbound() ) return size;
BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
- return maximum_stacksize() == minimum_stacksize()
- ? minimum_stacksize()
- : ( std::min)( size, maximum_stacksize() );
+ return maximum_stacksize() == size
+ ? size
+ : (std::min)( size, maximum_stacksize() );
}
-// because Windows seams not to provide a limit for minimum stacksize
std::size_t
standard_stack_allocator::minimum_stacksize()
-{ return MIN_STACKSIZE; }
+{ return SIGSTKSZ + sizeof( context::fcontext_t) + 15; }
-// because Windows seams not to provide a limit for maximum stacksize
-// maximum_stacksize() can never be called (pre-condition ! is_stack_unbound() )
std::size_t
standard_stack_allocator::maximum_stacksize()
{
BOOST_ASSERT( ! is_stack_unbound() );
- return 1 * 1024 * 1024 * 1024; // 1GB
+ return static_cast< std::size_t >( detail::stacksize_limit().rlim_max);
}
void
@@ -112,23 +108,32 @@
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
- const std::size_t pages( detail::page_count( size) + 1); // add one guard page
- const std::size_t size_ = pages * detail::pagesize();
+ const std::size_t pages( detail::page_count( size) ); // page at bottom will be used as guard-page
+ BOOST_ASSERT_MSG( 2 <= pages, "at least two pages must fit into stack (one page is guard-page)");
+ const std::size_t size_( pages * detail::pagesize() );
BOOST_ASSERT( 0 < size && 0 < size_);
+ BOOST_ASSERT( size_ <= size);
- void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
+ const int fd( ::open("/dev/zero", O_RDONLY) );
+ BOOST_ASSERT( -1 != fd);
+ // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
+ void * limit =
+# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+ ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+# else
+ ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+# endif
+ ::close( fd);
if ( ! limit) throw std::bad_alloc();
std::memset( limit, '\0', size_);
- DWORD old_options;
+ // conforming to POSIX.1-2001
#if defined(BOOST_DISABLE_ASSERTS)
- ::VirtualProtect(
- limit, detail::pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
+ ::mprotect( limit, detail::pagesize(), PROT_NONE);
#else
- const BOOL result = ::VirtualProtect(
- limit, detail::pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
- BOOST_ASSERT( FALSE != result);
+ const int result( ::mprotect( limit, detail::pagesize(), PROT_NONE) );
+ BOOST_ASSERT( 0 == result);
#endif
ctx.size = size_;
@@ -143,7 +148,8 @@
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= ctx.size) );
void * limit = static_cast< char * >( ctx.sp) - ctx.size;
- ::VirtualFree( limit, 0, MEM_RELEASE);
+ // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
+ ::munmap( limit, ctx.size);
}
}}}
@@ -151,3 +157,7 @@
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
+
+#ifdef UDEF_SIGSTKSZ
+# undef SIGSTKSZ
+#endif
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk