|
Boost-Commit : |
From: hartmut.kaiser_at_[hidden]
Date: 2007-11-28 12:20:21
Author: hkaiser
Date: 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
New Revision: 41437
URL: http://svn.boost.org/trac/boost/changeset/41437
Log:
[Coroutine] Added support for Linux/gcc 64 Bit systems. Fixed a lot of typos in comments, untabified files.
Added:
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_linux64.hpp (contents, props changed)
sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext32.cpp (contents, props changed)
sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext64.cpp (contents, props changed)
Text files modified:
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/coroutine.hpp | 62 +++++++++---------
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_base.hpp | 8 +-
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_linux.hpp | 131 ++++++++++++++++++++-------------------
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_windows.hpp | 76 +++++++++++-----------
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/coroutine_accessor.hpp | 4
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/coroutine_impl.hpp | 57 ++++++++--------
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/default_context_impl.hpp | 27 ++++++-
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/posix_utility.hpp | 4
sandbox/SOC/2006/coroutine/trunk/boost/coroutine/shared_coroutine.hpp | 2
sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext.cpp | 95 ++--------------------------
10 files changed, 203 insertions(+), 263 deletions(-)
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/coroutine.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/coroutine.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/coroutine.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -54,8 +54,8 @@
template<typename T>
struct optional_result_type :
boost::mpl::if_<boost::is_same<T, void>,
- void,
- boost::optional<T> > { };
+ void,
+ boost::optional<T> > { };
template<typename T>
BOOST_DEDUCED_TYPENAME
@@ -65,12 +65,12 @@
template<typename T>
BOOST_DEDUCED_TYPENAME
boost::disable_if<boost::is_same<T, void>,
- BOOST_DEDUCED_TYPENAME
- optional_result_type<T>::type
- >::type
+ BOOST_DEDUCED_TYPENAME
+ optional_result_type<T>::type
+ >::type
optional_result() {
return BOOST_DEDUCED_TYPENAME
- optional_result_type<T>::type();
+ optional_result_type<T>::type();
}
}
@@ -84,7 +84,7 @@
struct is_coroutine<coroutine<Sig, Con> > : boost::mpl::true_{};
template<typename Signature,
- typename ContextImpl = detail::default_context_impl>
+ typename ContextImpl = detail::default_context_impl>
class coroutine : public movable<coroutine<Signature, ContextImpl> > {
public:
typedef coroutine<Signature, ContextImpl> type;
@@ -124,14 +124,14 @@
template<typename Functor>
coroutine (Functor f,
- std::ptrdiff_t stack_size = detail::default_stack_size,
- BOOST_DEDUCED_TYPENAME boost::enable_if<
- boost::mpl::and_<
- detail::is_callable<Functor>,
- boost::mpl::not_<is_coroutine<Functor> >
- > >
- ::type * = 0
- ) :
+ std::ptrdiff_t stack_size = detail::default_stack_size,
+ BOOST_DEDUCED_TYPENAME boost::enable_if<
+ boost::mpl::and_<
+ detail::is_callable<Functor>,
+ boost::mpl::not_<is_coroutine<Functor> >
+ > >
+ ::type * = 0
+ ) :
m_pimpl(impl_type::create(f, stack_size)) {}
coroutine(move_from<coroutine> src)
@@ -160,15 +160,15 @@
/**/
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX,
- BOOST_COROUTINE_generate_argument_n_type,
- arg_slot_traits);
+ BOOST_COROUTINE_generate_argument_n_type,
+ arg_slot_traits);
static const int arity = arg_slot_traits::length;
struct yield_traits {
BOOST_PP_REPEAT(BOOST_COROUTINE_ARG_MAX,
- BOOST_COROUTINE_generate_argument_n_type,
- result_slot_traits);
+ BOOST_COROUTINE_generate_argument_n_type,
+ result_slot_traits);
static const int arity = result_slot_traits::length;
};
@@ -184,12 +184,12 @@
result_type operator()
(BOOST_PP_ENUM
(BOOST_COROUTINE_ARG_MAX,
- BOOST_COROUTINE_param_with_default,
- arg)) {
+ BOOST_COROUTINE_param_with_default,
+ arg)) {
return call_impl
- (arg_slot_type(BOOST_PP_ENUM_PARAMS
- (BOOST_COROUTINE_ARG_MAX,
- arg)));
+ (arg_slot_type(BOOST_PP_ENUM_PARAMS
+ (BOOST_COROUTINE_ARG_MAX,
+ arg)));
}
BOOST_DEDUCED_TYPENAME
@@ -198,12 +198,12 @@
(const std::nothrow_t&
BOOST_PP_ENUM_TRAILING
(BOOST_COROUTINE_ARG_MAX,
- BOOST_COROUTINE_param_with_default,
- arg)) {
+ BOOST_COROUTINE_param_with_default,
+ arg)) {
return call_impl_nothrow
- (arg_slot_type(BOOST_PP_ENUM_PARAMS
- (BOOST_COROUTINE_ARG_MAX,
- arg)));
+ (arg_slot_type(BOOST_PP_ENUM_PARAMS
+ (BOOST_COROUTINE_ARG_MAX,
+ arg)));
}
# undef BOOST_COROUTINE_param_typedef
@@ -244,7 +244,7 @@
protected:
// The second parameter is used to avoid calling this constructor
- // by mistake from other member funcitons (specifically operator=).
+ // by mistake from other member functions (specifically operator=).
coroutine(impl_type * pimpl, detail::init_from_impl_tag) :
m_pimpl(pimpl) {}
@@ -272,7 +272,7 @@
result_slot_type * ptr;
m_pimpl->bind_result_pointer(&ptr);
if(!m_pimpl->wake_up())
- return detail::optional_result<result_type>();
+ return detail::optional_result<result_type>();
return detail::fix_result<result_slot_traits>(*m_pimpl->result());
}
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_base.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_base.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_base.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -205,7 +205,7 @@
void invoke() {
BOOST_ASSERT(ready());
do_invoke();
- // TODO: could use a bynary or here to eliminate
+ // TODO: could use a binary or here to eliminate
// shortcut evaluation (and a branch), but maybe the compiler is
// smart enough to do it anyway as there are no side effects.
if(m_exit_status || m_state == ctx_waiting) {
@@ -220,7 +220,7 @@
} else if(m_exit_status == ctx_exited_exit)
throw coroutine_exited();
else {
- BOOST_ASSERT(0 && "unkonw exit status");
+ BOOST_ASSERT(0 && "unknown exit status");
}
}
}
@@ -263,7 +263,7 @@
// The exit_exception would cause the future to be destroyed and
// an assertion to be generated. Removing an assertion is not a
// solution because we would leak the coroutine impl. The callback
- // bound to the future in fact hold a refrence to it. If the coroutine
+ // bound to the future in fact hold a reference to it. If the coroutine
// is exited the callback cannot be called.
void wait(int n) {
BOOST_ASSERT(!(n<0));
@@ -300,7 +300,7 @@
// Cause this coroutine to exit.
// Can only be called on a ready coroutine.
// Cannot be called if there are pending operations.
- // It follws that cannot be called from 'this'.
+ // It follows that cannot be called from 'this'.
// Nothrow.
void exit() throw(){
BOOST_ASSERT(!pending());
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_linux.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_linux.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_linux.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -37,7 +37,7 @@
/*
* Defining BOOST_COROUTINE_INLINE_ASM will enable the inlin3
- * assembler verwsion of swapcontext_stack.
+ * assembler version of swapcontext_stack.
* The inline asm, with all required clobber flags, is usually no faster
* than the out-of-line function, and it is not yet clear if
* it is always reliable (i.e. if the compiler always saves the correct
@@ -109,26 +109,26 @@
fun_type get_swapper(){
fun_type ptr;
asm volatile("mov $0f, %[result]"
- "\n\t jmp 1f"
- "\n0:"
- //"\n\t movl 16(%%edx), %%ecx"
- "\n\t pushl %%ebp"
- "\n\t pushl %%ebx"
- "\n\t pushl %%esi"
- "\n\t pushl %%edi"
- "\n\t movl %%esp, (%%eax)"
- "\n\t movl %%edx, %%esp"
- "\n\t popl %%edi"
- "\n\t popl %%esi"
- "\n\t popl %%ebx"
- "\n\t popl %%ebp"
- "\n\t popl %%ecx"
- "\n\t jmp *%%ecx"
- "\n1:"
- :
- [result] "=g" (ptr)
- :
- );
+ "\n\t jmp 1f"
+ "\n0:"
+ //"\n\t movl 16(%%edx), %%ecx"
+ "\n\t pushl %%ebp"
+ "\n\t pushl %%ebx"
+ "\n\t pushl %%esi"
+ "\n\t pushl %%edi"
+ "\n\t movl %%esp, (%%eax)"
+ "\n\t movl %%edx, %%esp"
+ "\n\t popl %%edi"
+ "\n\t popl %%esi"
+ "\n\t popl %%ebx"
+ "\n\t popl %%ebp"
+ "\n\t popl %%ecx"
+ "\n\t jmp *%%ecx"
+ "\n1:"
+ :
+ [result] "=g" (ptr)
+ :
+ );
return ptr;
};
@@ -167,16 +167,16 @@
ia32_gcc_context_impl_base() {};
void prefetch() const {
- __builtin_prefetch (m_sp, 1, 3);
- __builtin_prefetch (m_sp, 0, 3);
- __builtin_prefetch ((void**)m_sp+64/4, 1, 3);
- __builtin_prefetch ((void**)m_sp+64/4, 0, 3);
- __builtin_prefetch ((void**)m_sp+32/4, 1, 3);
- __builtin_prefetch ((void**)m_sp+32/4, 0, 3);
- __builtin_prefetch ((void**)m_sp-32/4, 1, 3);
- __builtin_prefetch ((void**)m_sp-32/4, 0, 3);
- __builtin_prefetch ((void**)m_sp-64/4, 1, 3);
- __builtin_prefetch ((void**)m_sp-64/4, 0, 3);
+ __builtin_prefetch (m_sp, 1, 3);
+ __builtin_prefetch (m_sp, 0, 3);
+ __builtin_prefetch ((void**)m_sp+64/4, 1, 3);
+ __builtin_prefetch ((void**)m_sp+64/4, 0, 3);
+ __builtin_prefetch ((void**)m_sp+32/4, 1, 3);
+ __builtin_prefetch ((void**)m_sp+32/4, 0, 3);
+ __builtin_prefetch ((void**)m_sp-32/4, 1, 3);
+ __builtin_prefetch ((void**)m_sp-32/4, 0, 3);
+ __builtin_prefetch ((void**)m_sp-64/4, 1, 3);
+ __builtin_prefetch ((void**)m_sp-64/4, 0, 3);
}
/**
@@ -187,29 +187,29 @@
friend
void
swap_context(ia32_gcc_context_impl_base& from,
- ia32_gcc_context_impl_base const& to,
- default_hint) {
- to.prefetch();
- swapcontext_stack(&from.m_sp, to.m_sp);
+ ia32_gcc_context_impl_base const& to,
+ default_hint) {
+ to.prefetch();
+ swapcontext_stack(&from.m_sp, to.m_sp);
}
#ifndef BOOST_COROUTINE_NO_SEPARATE_CALL_SITES
friend
void
swap_context(ia32_gcc_context_impl_base& from,
- ia32_gcc_context_impl_base const& to,
- yield_hint) {
- to.prefetch();
- swapcontext_stack2(&from.m_sp, to.m_sp);
+ ia32_gcc_context_impl_base const& to,
+ yield_hint) {
+ to.prefetch();
+ swapcontext_stack2(&from.m_sp, to.m_sp);
}
friend
void
swap_context(ia32_gcc_context_impl_base& from,
- ia32_gcc_context_impl_base const& to,
- yield_to_hint) {
- to.prefetch();
- swapcontext_stack2(&from.m_sp, to.m_sp);
+ ia32_gcc_context_impl_base const& to,
+ yield_to_hint) {
+ to.prefetch();
+ swapcontext_stack2(&from.m_sp, to.m_sp);
}
#endif
@@ -226,41 +226,42 @@
typedef ia32_gcc_context_impl_base context_impl_base;
ia32_gcc_context_impl() :
- m_stack(0) {}
+ m_stack(0) {}
/**
* Create a context that on restore invokes Functor on
* a new stack. The stack size can be optionally specified.
*/
template<typename Functor>
- ia32_gcc_context_impl(Functor& cb, std::ptrdiff_t stack_size = -1) :
- m_stack_size(stack_size == -1? default_stack_size: stack_size),
- m_stack(posix::alloc_stack(m_stack_size)) {
- m_sp = ((void**)m_stack + (m_stack_size/sizeof(void*))),
- BOOST_ASSERT(m_stack);
- typedef void fun(Functor*);
- fun * funp = trampoline;
+ ia32_gcc_context_impl(Functor& cb, std::ptrdiff_t stack_size = -1) :
+ m_stack_size(stack_size == -1? default_stack_size: stack_size),
+ m_stack(posix::alloc_stack(m_stack_size))
+ {
+ m_sp = ((void**)m_stack + (m_stack_size/sizeof(void*)));
+ BOOST_ASSERT(m_stack);
+ typedef void fun(Functor*);
+ fun * funp = trampoline;
#ifndef BOOST_COROUTINE_INLINE_ASM
- *--m_sp = &cb; // parm 0 of trampoline;
- *--m_sp = 0; // dummy return address for trampoline
- *--m_sp = (void*) funp ;// return addr (here: start addr) NOTE: the unsafe cast is safe on IA32
- *--m_sp = 0; // ebp
- *--m_sp = 0; // ebx
- *--m_sp = 0; // esi
- *--m_sp = 0; // edi
+ *--m_sp = &cb; // parm 0 of trampoline;
+ *--m_sp = 0; // dummy return address for trampoline
+ *--m_sp = (void*) funp ;// return addr (here: start addr) NOTE: the unsafe cast is safe on IA32
+ *--m_sp = 0; // ebp
+ *--m_sp = 0; // ebx
+ *--m_sp = 0; // esi
+ *--m_sp = 0; // edi
#else
- *--m_sp = &cb; // parm 0 of trampoline;
- *--m_sp = 0; // dummy return address for trampoline
- *--m_sp = (void*) funp ;// return addr (here: start addr) NOTE: the unsafe cast is safe on IA32
+ *--m_sp = &cb; // parm 0 of trampoline;
+ *--m_sp = 0; // dummy return address for trampoline
+ *--m_sp = (void*) funp ;// return addr (here: start addr) NOTE: the unsafe cast is safe on IA32
#endif
}
~ia32_gcc_context_impl() {
- if(m_stack)
- posix::free_stack(m_stack, m_stack_size);
+ if(m_stack)
+ posix::free_stack(m_stack, m_stack_size);
}
private:
- std::ptrdiff_t m_stack_size;
+ std::ptrdiff_t m_stack_size;
void * m_stack;
};
@@ -269,6 +270,7 @@
} } }
#elif defined(__linux)
+
/**
* For all other linux systems use the standard posix implementation.
*/
@@ -276,6 +278,7 @@
namespace boost { namespace coroutines { namespace detail { namespace oslinux {
typedef posix::context_impl context_impl;
} } } }
+
#else
#error This header can only be included when compiling for linux systems.
#endif
Added: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_linux64.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_linux64.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -0,0 +1,167 @@
+// Copyright (c) 2007 Robert Perricone
+// Copyright (c) 2007 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_COROUTINE_CONTEXT_LINUX_HPP_20071126
+#define BOOST_COROUTINE_CONTEXT_LINUX_HPP_20071126
+
+#if defined(__GNUC__) && defined(__x86_64__) && !defined(BOOST_COROUTINE_NO_ASM)
+#include <cstdlib>
+#include <cstddef>
+#include <boost/coroutine/detail/posix_utility.hpp>
+#include <boost/coroutine/detail/swap_context.hpp>
+
+/*
+ * Defining BOOST_COROUTINE_NO_SEPARATE_CALL_SITES will disable separate
+ * invoke, yield and yield_to swap_context functions. Separate calls sites
+ * increase performance by 25% at least on P4 for invoke+yield back loops
+ * at the cost of a slightly higher instruction cache use and is thus enabled by
+ * default.
+ */
+//#define BOOST_COROUTINE_NO_SEPARATE_CALL_SITES
+
+extern "C" void swapcontext_stack (void***, void**) throw();
+extern "C" void swapcontext_stack2 (void***, void**) throw();
+extern "C" void swapcontext_stack3 (void***, void**) throw();
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace coroutines { namespace detail {
+ namespace oslinux64
+ {
+ template<typename T>
+ void trampoline(T* fun);
+
+ template<typename T>
+ inline void
+ trampoline(T* fun)
+ {
+ (*fun)();
+ std::abort();
+ }
+
+ class ia64_gcc_context_impl_base
+ {
+ public:
+ ia64_gcc_context_impl_base() {}
+
+ void prefetch() const
+ {
+ __builtin_prefetch (m_sp, 1, 3);
+ __builtin_prefetch (m_sp, 0, 3);
+ __builtin_prefetch ((void**)m_sp+64/8, 1, 3);
+ __builtin_prefetch ((void**)m_sp+64/8, 0, 3);
+ __builtin_prefetch ((void**)m_sp+32/8, 1, 3);
+ __builtin_prefetch ((void**)m_sp+32/8, 0, 3);
+ __builtin_prefetch ((void**)m_sp-32/8, 1, 3);
+ __builtin_prefetch ((void**)m_sp-32/8, 0, 3);
+ __builtin_prefetch ((void**)m_sp-64/8, 1, 3);
+ __builtin_prefetch ((void**)m_sp-64/8, 0, 3);
+ }
+
+ /**
+ * Free function. Saves the current context in @p from
+ * and restores the context in @p to.
+ * @note This function is found by ADL.
+ */
+ friend void
+ swap_context(ia64_gcc_context_impl_base& from,
+ ia64_gcc_context_impl_base const& to,
+ default_hint)
+ {
+ to.prefetch();
+ swapcontext_stack(&from.m_sp, to.m_sp);
+ }
+
+#ifndef BOOST_COROUTINE_NO_SEPARATE_CALL_SITES
+ friend void
+ swap_context(ia64_gcc_context_impl_base& from,
+ ia64_gcc_context_impl_base const& to,
+ yield_hint)
+ {
+ to.prefetch();
+ swapcontext_stack2(&from.m_sp, to.m_sp);
+ }
+
+ friend void
+ swap_context(ia64_gcc_context_impl_base& from,
+ ia64_gcc_context_impl_base const& to,
+ yield_to_hint)
+ {
+ to.prefetch();
+ swapcontext_stack3(&from.m_sp, to.m_sp);
+ }
+#endif
+
+ protected:
+ void ** m_sp;
+ };
+
+ class ia64_gcc_context_impl : public ia64_gcc_context_impl_base
+ {
+ public:
+ enum { default_stack_size = 8192 };
+
+ typedef ia64_gcc_context_impl_base context_impl_base;
+
+ ia64_gcc_context_impl() :
+ m_stack(0) {}
+
+ /**
+ * Create a context that on restore invokes Functor on
+ * a new stack. The stack size can be optionally specified.
+ */
+ template<typename Functor>
+ ia64_gcc_context_impl(Functor& cb, std::ptrdiff_t stack_size = -1)
+ : m_stack_size(stack_size == -1 ? default_stack_size : stack_size),
+ m_stack(posix::alloc_stack(m_stack_size))
+ {
+ BOOST_ASSERT(m_stack);
+ m_sp = ((void**)m_stack + (m_stack_size/sizeof(void*)));
+
+ typedef void fun(Functor*);
+ fun * funp = trampoline;
+
+ *--m_sp = &cb; // parm 0 of trampoline;
+ *--m_sp = 0; // dummy return address for trampoline
+ *--m_sp = (void*) funp ;// return addr (here: start addr) NOTE: the unsafe cast is safe on IA64
+ *--m_sp = 0; // rbp
+ *--m_sp = 0; // rbx
+ *--m_sp = 0; // rsi
+ *--m_sp = 0; // rdi
+ }
+
+ ~ia64_gcc_context_impl()
+ {
+ if(m_stack)
+ posix::free_stack(m_stack, m_stack_size);
+ }
+
+ private:
+ std::ptrdiff_t m_stack_size;
+ void * m_stack;
+ };
+
+ typedef ia64_gcc_context_impl context_impl;
+ }
+}}}
+
+#elif defined(__linux)
+/**
+ * For all other linux systems use the standard posix implementation.
+ */
+#include <boost/coroutine/detail/context_posix.hpp>
+namespace boost { namespace coroutines { namespace detail {
+ namespace oslinux64
+ {
+ typedef posix::context_impl context_impl;
+ }
+}}}
+#else
+#error This header can only be included when compiling for linux systems.
+#endif
+
+#endif
+
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_windows.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_windows.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/context_windows.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -42,17 +42,17 @@
/*
* This number (0x1E00) has been sighted in the wild (at least on windows XP systems)
- * as return value from GetCurrentFiber() on non fibrous threads. This is sowehow related
+ * as return value from GetCurrentFiber() on non fibrous threads. This is somehow related
* to OS/2 where the current fiber pointer is overloaded as a version field.
* On non-NT systems, 0 is returned.
*/
- fiber_ptr fiber_magic = reinterpret_cast<fiber_ptr>(0x1E00);
-
+ fiber_ptr const fiber_magic = reinterpret_cast<fiber_ptr>(0x1E00);
+
/*
* Return true if current thread is a fiber.
- * FIXME: on longhorn shoud use IsThreadAFiber
+ * FIXME: on longhorn should use IsThreadAFiber
*/
- bool is_fiber() {
+ inline bool is_fiber() {
fiber_ptr current = GetCurrentFiber();
return current != 0 && current != fiber_magic;
}
@@ -71,8 +71,8 @@
* but can be saved in.
*/
fibers_context_impl_base() :
- m_ctx(0) {}
-
+ m_ctx(0) {}
+
/*
* Free function. Saves the current context in @p from
* and restores the context in @p to. On windows the from
@@ -89,34 +89,34 @@
friend
void
swap_context(fibers_context_impl_base& from,
- const fibers_context_impl_base& to,
- default_hint) {
- if(!is_fiber()) {
- BOOST_ASSERT(from.m_ctx == 0);
- from.m_ctx = ConvertThreadToFiber(0);
- BOOST_ASSERT(from.m_ctx != 0);
-
- SwitchToFiber(to.m_ctx);
-
- BOOL result = ConvertFiberToThread();
- BOOST_ASSERT(result);
- (void)result;
- from.m_ctx = 0;
- } else {
- bool call_from_main = from.m_ctx == 0;
- if(call_from_main)
- from.m_ctx = GetCurrentFiber();
- SwitchToFiber(to.m_ctx);
- if(call_from_main)
- from.m_ctx = 0;
- }
+ const fibers_context_impl_base& to,
+ default_hint) {
+ if(!is_fiber()) {
+ BOOST_ASSERT(from.m_ctx == 0);
+ from.m_ctx = ConvertThreadToFiber(0);
+ BOOST_ASSERT(from.m_ctx != 0);
+
+ SwitchToFiber(to.m_ctx);
+
+ BOOL result = ConvertFiberToThread();
+ BOOST_ASSERT(result);
+ (void)result;
+ from.m_ctx = 0;
+ } else {
+ bool call_from_main = from.m_ctx == 0;
+ if(call_from_main)
+ from.m_ctx = GetCurrentFiber();
+ SwitchToFiber(to.m_ctx);
+ if(call_from_main)
+ from.m_ctx = 0;
+ }
}
~fibers_context_impl_base() {}
protected:
explicit
fibers_context_impl_base(fiber_ptr ctx) :
- m_ctx(ctx) {}
+ m_ctx(ctx) {}
fiber_ptr m_ctx;
};
@@ -139,24 +139,24 @@
enum {default_stack_size = 8192};
/**
- * Create a context that on restore inovkes Functor on
+ * Create a context that on restore invokes Functor on
* a new stack. The stack size can be optionally specified.
*/
template<typename Functor>
explicit
fibers_context_impl(Functor& cb, std::ptrdiff_t stack_size) :
- fibers_context_impl_base
- (CreateFiber(stack_size== -1? 0 : stack_size,
- static_cast<LPFIBER_START_ROUTINE>(&trampoline<Functor>),
- static_cast<LPVOID>(&cb)))
+ fibers_context_impl_base
+ (CreateFiber(stack_size== -1? default_stack_size : stack_size,
+ static_cast<LPFIBER_START_ROUTINE>(&trampoline<Functor>),
+ static_cast<LPVOID>(&cb)))
{
- BOOST_ASSERT(m_ctx);
+ BOOST_ASSERT(m_ctx);
}
-
+
~fibers_context_impl() {
- DeleteFiber(m_ctx);
+ DeleteFiber(m_ctx);
}
-
+
private:
};
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/coroutine_accessor.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/coroutine_accessor.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/coroutine_accessor.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -62,11 +62,11 @@
struct in_place_assign : boost::in_place_factory_base {
in_place_assign(Ctx * ctx) :
- m_ctx(ctx) {}
+ m_ctx(ctx) {}
template<typename Coroutine>
void apply(void * memory) const {
- construct<Coroutine>(m_ctx, memory);
+ construct<Coroutine>(m_ctx, memory);
}
Ctx * m_ctx;
};
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/coroutine_impl.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/coroutine_impl.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/coroutine_impl.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -40,7 +40,7 @@
#include <boost/coroutine/detail/context_base.hpp>
namespace boost { namespace coroutines { namespace detail {
-
+
// This class augment the contest_base class with
// the coroutine signature type.
// This is mostly just a place to put
@@ -64,10 +64,10 @@
typedef boost::intrusive_ptr<type> pointer;
template<typename DerivedType>
- coroutine_impl(DerivedType * this_, std::ptrdiff_t stack_size) :
+ coroutine_impl(DerivedType * this_, std::ptrdiff_t stack_size) :
context_base(*this_, stack_size),
- m_arg(0),
- m_result(0){}
+ m_arg(0),
+ m_result(0){}
arg_slot_type * args() {
BOOST_ASSERT(m_arg);
@@ -81,8 +81,8 @@
}
template<typename Functor>
- static inline
- pointer create(Functor, std::ptrdiff_t);
+ static inline
+ pointer create(Functor, std::ptrdiff_t);
void bind_args(arg_slot_type* arg) {
m_arg = arg;
@@ -92,7 +92,7 @@
*m_result = res;
}
- // Another level of indirecition is needed to handle
+ // Another level of indirection is needed to handle
// yield_to correctly.
void bind_result_pointer(result_slot_type** resp) {
m_result = resp;
@@ -141,26 +141,25 @@
typedef coroutine_impl<CoroutineType, ContextImpl> super_type;
typedef FunctorType functor_type;
- coroutine_impl_wrapper(functor_type f, std::ptrdiff_t stack_size) :
-
- super_type(this, stack_size),
+ coroutine_impl_wrapper(functor_type f, std::ptrdiff_t stack_size) :
+ super_type(this, stack_size),
m_fun(f){}
void operator()() {
typedef typename super_type::context_exit_status
- context_exit_status;
+ context_exit_status;
context_exit_status status = super_type::ctx_exited_return;
std::type_info const* tinfo = 0;
try {
- this->check_exit_state();
- do_call<result_type>();
+ this->check_exit_state();
+ do_call<result_type>();
} catch (const exit_exception&) {
- status = super_type::ctx_exited_exit;
+ status = super_type::ctx_exited_exit;
} catch (std::exception const& e) {
- status = super_type::ctx_exited_abnormally;
- tinfo = &typeid(e);
+ status = super_type::ctx_exited_abnormally;
+ tinfo = &typeid(e);
} catch (...) {
- status = super_type::ctx_exited_abnormally;
+ status = super_type::ctx_exited_abnormally;
}
this->do_return(status, tinfo);
}
@@ -178,16 +177,16 @@
do_call(dummy<0> = 0) {
BOOST_ASSERT(this->count() > 0);
typedef BOOST_DEDUCED_TYPENAME
- coroutine_type::self self_type;
+ coroutine_type::self self_type;
boost::optional<self_type> self (coroutine_accessor::in_place(this));
detail::unpack_ex
- (m_fun,
- *self,
- *this->args(),
- detail::trait_tag<typename coroutine_type::arg_slot_traits>());
+ (m_fun,
+ *self,
+ *this->args(),
+ detail::trait_tag<typename coroutine_type::arg_slot_traits>());
typedef BOOST_DEDUCED_TYPENAME coroutine_type::result_slot_type
- result_slot_type;
+ result_slot_type;
// In this particulare case result_slot_type is guaranteed to be
// default constructible.
@@ -207,13 +206,13 @@
typedef BOOST_DEDUCED_TYPENAME coroutine_type::arg_slot_traits traits;
typedef BOOST_DEDUCED_TYPENAME coroutine_type::result_slot_type
- result_slot_type;
-
+ result_slot_type;
+
this->m_result_last = boost::in_place(result_slot_type(detail::unpack_ex
- (m_fun,
- *self,
- *this->args(),
- detail::trait_tag<traits>())));
+ (m_fun,
+ *self,
+ *this->args(),
+ detail::trait_tag<traits>())));
this->bind_result(&*this->m_result_last);
}
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/default_context_impl.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/default_context_impl.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/default_context_impl.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -61,7 +61,7 @@
context_impl_base must have conform to the ContextImplBase concept:
- DefaultConstructible. A default constructed ContextImplBase is in
- an unitialized state.
+ an initialized state.
A ContextImpl is an initialized ContextImplBase.
- ContextImplBase is Copyable. A copy of a ContextImplBase holds
@@ -81,33 +81,48 @@
Postconditions:
The current context is saved in the 'from' context, and the
'to' context is restored.
- It is undefined behaviour if the 'to' argument is an invalid
- (uninitialized) swapcontext.
+ It is undefined behavior if the 'to' argument is an invalid
+ (uninitialized) swap context.
A ContextImplBase is meant to be used when an empty temporary
context is needed to store the current context before
restoring a ContextImpl and no current context is
available. It could be possible to simply have ContextImpl
- default constructible, but on destruciton it would need to
+ default constructible, but on destruction it would need to
check if a stack has been allocated and would slow down the
- fast invcation path. Also a stackful context could not be
- make copiable.
+ fast invocation path. Also a stack-full context could not be
+ make copyable.
*/
#if defined(__linux) || defined(linux) || defined(__linux__)
+#if defined(__x86_64__)
+// 64 bit systems, use appropriate context switching
+
+#include <boost/coroutine/detail/context_linux64.hpp>
+namespace boost { namespace coroutines { namespace detail {
+ typedef oslinux64::context_impl default_context_impl;
+} } }
+
+#else
+// use 32 bit context switching
+
#include <boost/coroutine/detail/context_linux.hpp>
namespace boost { namespace coroutines { namespace detail {
typedef oslinux::context_impl default_context_impl;
} } }
+#endif
+
#elif defined(_POSIX_VERSION)
#include <boost/coroutine/detail/context_posix.hpp>
namespace boost { namespace coroutines { namespace detail {
typedef posix::context_impl default_context_impl;
} } }
+
#elif defined(BOOST_WINDOWS)
+
#include <boost/coroutine/detail/context_windows.hpp>
namespace boost { namespace coroutines { namespace detail {
typedef windows::context_impl default_context_impl;
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/posix_utility.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/posix_utility.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/detail/posix_utility.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -58,9 +58,9 @@
* Better implementations are possible using
* mmap (might be required on some systems) and/or
* using a pooling allocator.
- * NOTE: the SuSv3 documentation explictly allows
+ * NOTE: the SuSv3 documentation explicitly allows
* the use of malloc to allocate stacks for makectx.
- * We use free for guaranteed alignment.
+ * We use new/delete for guaranteed alignment.
*/
inline
void* alloc_stack(std::size_t size) {
Modified: sandbox/SOC/2006/coroutine/trunk/boost/coroutine/shared_coroutine.hpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/boost/coroutine/shared_coroutine.hpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/boost/coroutine/shared_coroutine.hpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -31,7 +31,7 @@
#include <boost/coroutine/coroutine.hpp>
namespace boost { namespace coroutines {
// This class is a workaround for the widespread lack of move
- // semantics support. It is a refrence counted wrapper around
+ // semantics support. It is a reference counted wrapper around
// the coroutine object.
// FIXME: ATM a shared_coroutine is-a coroutine. This is to avoid
// inheriting privately and cluttering the code with lots of using
Modified: sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext.cpp
==============================================================================
--- sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext.cpp (original)
+++ sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext.cpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -1,95 +1,18 @@
-// Copyright (c) 2006, Giovanni P. Deretta
-//
-// This code may be used under either of the following two licences:
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE. OF SUCH DAMAGE.
-//
-// Or:
+// Copyright (c) 2007 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-
-#if !defined(i386)
-#error This file is for x86 CPUs only.
-#endif
-
#if !defined(__GNUC__)
-#error This file requires gcc.
+#error This file requires compilation using gcc.
#endif
-/*
- * This file should really be a plain assembler file.
- * Unfortunately Boost.Build v2 doesn't handle asm files (yet).
- * For now resort to inline asm.
- */
-
-
-/*
- EAX is &from.sp
- EDX is to.sp
- This is the simplest version of swapcontext
- It saves registers on the old stack,
- saves the old stack pointer,
- load the new stack pointer,
- pop registers from the new stack
- and returns to new caller.
- EAX is simpy passed to the function it returns to.
- The first time EAX is the first parameter of the trampoline.
- Otherwise it is simply discarded.
- NOTE: This function should work on any IA32 CPU.
- NOTE: The biggest penality is the last jump that
- will be always mispredicted (~50 cycles on P4).
- We try to make its address available as soon as possible
- to try to reduce the penality. Doing a ret instead of a
- 'add $4, %esp'
- 'jmp *%ecx'
- really kills performance.
- NOTE: popl is slightly better than mov+add to pop registers
- so is pushl rather than mov+sub.
- */
-#define BOOST_COROUTINE_swapcontext(name) \
-asm volatile ( \
-".text \n\t" \
-".global " #name "\n\t" \
-".type " #name "@function\n\t" \
-".align 16\n\t" \
-#name":\n\t" \
-"movl 16(%edx), %ecx\n\t" \
-"pushl %ebp\n\t" \
-"pushl %ebx\n\t" \
-"pushl %esi\n\t" \
-"pushl %edi\n\t" \
-"movl %esp, (%eax)\n\t" \
-"movl %edx, %esp\n\r" \
-"popl %edi\n\t" \
-"popl %esi\n\t" \
-"popl %ebx\n\t" \
-"popl %ebp\n\t" \
-"add $4, %esp\n\t" \
-"jmp *%ecx\n\t" \
-"ud2\n\t") \
-/**/
-
-BOOST_COROUTINE_swapcontext(swapcontext_stack);
-BOOST_COROUTINE_swapcontext(swapcontext_stack2);
-BOOST_COROUTINE_swapcontext(swapcontext_stack3);
+#if defined(__i386__)
+#include "swapcontext32.cpp"
+#elif defined(__x86_64__)
+#include "swapcontext64.cpp"
+#else
+#error Undefined platform (should be __386__ or __x86_64__)
+#endif
-#undef BOOST_COROUTINE_swapcontext
Added: sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext32.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext32.cpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -0,0 +1,95 @@
+// Copyright (c) 2006, Giovanni P. Deretta
+//
+// This code may be used under either of the following two licences:
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE. OF SUCH DAMAGE.
+//
+// Or:
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#if !defined(i386)
+#error This file is for x86 CPUs only.
+#endif
+
+#if !defined(__GNUC__)
+#error This file requires gcc.
+#endif
+
+/*
+ * This file should really be a plain assembler file.
+ * Unfortunately Boost.Build v2 doesn't handle asm files (yet).
+ * For now resort to inline asm.
+ */
+
+
+/*
+ EAX is &from.sp
+ EDX is to.sp
+ This is the simplest version of swapcontext
+ It saves registers on the old stack,
+ saves the old stack pointer,
+ load the new stack pointer,
+ pop registers from the new stack
+ and returns to new caller.
+ EAX is simpy passed to the function it returns to.
+ The first time EAX is the first parameter of the trampoline.
+ Otherwise it is simply discarded.
+ NOTE: This function should work on any IA32 CPU.
+ NOTE: The biggest penality is the last jump that
+ will be always mispredicted (~50 cycles on P4).
+ We try to make its address available as soon as possible
+ to try to reduce the penality. Doing a ret instead of a
+ 'add $4, %esp'
+ 'jmp *%ecx'
+ really kills performance.
+ NOTE: popl is slightly better than mov+add to pop registers
+ so is pushl rather than mov+sub.
+ */
+#define BOOST_COROUTINE_swapcontext(name) \
+asm volatile ( \
+".text \n\t" \
+".global " #name "\n\t" \
+".type " #name "@function\n\t" \
+".align 16\n\t" \
+#name":\n\t" \
+"movl 16(%edx), %ecx\n\t" \
+"pushl %ebp\n\t" \
+"pushl %ebx\n\t" \
+"pushl %esi\n\t" \
+"pushl %edi\n\t" \
+"movl %esp, (%eax)\n\t" \
+"movl %edx, %esp\n\r" \
+"popl %edi\n\t" \
+"popl %esi\n\t" \
+"popl %ebx\n\t" \
+"popl %ebp\n\t" \
+"add $4, %esp\n\t" \
+"jmp *%ecx\n\t" \
+"ud2\n\t") \
+/**/
+
+BOOST_COROUTINE_swapcontext(swapcontext_stack);
+BOOST_COROUTINE_swapcontext(swapcontext_stack2);
+BOOST_COROUTINE_swapcontext(swapcontext_stack3);
+
+#undef BOOST_COROUTINE_swapcontext
Added: sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext64.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/swapcontext64.cpp 2007-11-28 12:20:20 EST (Wed, 28 Nov 2007)
@@ -0,0 +1,79 @@
+// Copyright (c) 2007 Robert Perricone
+// Copyright (c) 2007 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(__x86_64__)
+#error This file is for x86 CPUs only.
+#endif
+
+#if !defined(__GNUC__)
+#error This file requires compilation with gcc.
+#endif
+
+/*
+ * This file should really be a plain assembler file.
+ * Unfortunately Boost.Build v2 doesn't handle asm files (yet).
+ * For now resort to inline asm.
+ */
+
+// RDI is &from.sp
+// RSI is to.sp
+//
+// This is the simplest version of swapcontext
+// It saves registers on the old stack, saves the old stack pointer,
+// load the new stack pointer, pop registers from the new stack
+// and returns to new caller.
+//
+// RDI is set to be the parameter for the function to be called.
+// The first time RDI is the first parameter of the trampoline.
+// Otherwise it is simply discarded.
+//
+// NOTE: This function should work on any IA64 CPU.
+// NOTE: The biggest penalty is the last jump that
+// will be always mis-predicted (~50 cycles on P4).
+//
+// We try to make its address available as soon as possible
+// to try to reduce the penalty. Doing a return instead of a
+//
+// 'add $8, %esp'
+// 'jmp *%ecx'
+//
+// really kills performance.
+//
+// NOTE: popl is slightly better than mov+add to pop registers
+// so is pushl rather than mov+sub.
+
+#define BOOST_COROUTINE_SWAPCONTEXT(name) \
+ asm volatile ( \
+ ".text \n\t" \
+ ".global " #name "\n\t" \
+ ".type " #name ", @function\n\t" \
+ ".align 16\n" \
+ #name ":\n\t" \
+ "movq 32(%rsi), %rcx\n\t" \
+ "pushq %rbp\n\t" \
+ "pushq %rbx\n\t" \
+ "pushq %rax\n\t" \
+ "pushq %rdx\n\t" \
+ "movq %rsp, (%rdi)\n\t" \
+ "movq %rsi, %rsp\n\t" \
+ "popq %rdx\n\t" \
+ "popq %rax\n\t" \
+ "popq %rbx\n\t" \
+ "popq %rbp\n\t" \
+ "movq 48(%rsi), %rdi\n\t" \
+ "add $8, %rsp\n\t" \
+ "jmp *%rcx\n\t" \
+ "ud2\n\t" \
+ ) \
+/**/
+
+BOOST_COROUTINE_SWAPCONTEXT(swapcontext_stack);
+BOOST_COROUTINE_SWAPCONTEXT(swapcontext_stack2);
+BOOST_COROUTINE_SWAPCONTEXT(swapcontext_stack3);
+
+#undef BOOST_COROUTINE_SWAPCONTEXT
+
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