Index: boost/coroutine/detail/context_linux64.hpp =================================================================== --- boost/coroutine/detail/context_linux64.hpp (revision 66623) +++ boost/coroutine/detail/context_linux64.hpp (working copy) @@ -1,5 +1,5 @@ // Copyright (c) 2007 Robert Perricone -// Copyright (c) 2007 Hartmut Kaiser +// Copyright (c) 2007-2009 Hartmut Kaiser // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -28,12 +28,20 @@ extern "C" void swapcontext_stack3 (void***, void**) throw(); /////////////////////////////////////////////////////////////////////////////// -namespace boost { namespace coroutines { namespace detail { - namespace oslinux64 +namespace boost { namespace coroutines { + + // some platforms need special preparation of the main thread + struct prepare_main_thread { + prepare_main_thread() {} + ~prepare_main_thread() {} + }; + + namespace detail { namespace oslinux64 + { template void trampoline(T* fun); - + template inline void trampoline(T* fun) @@ -42,6 +50,8 @@ std::abort(); } + class ia64_gcc_context_impl; + class ia64_gcc_context_impl_base { public: @@ -66,33 +76,15 @@ * 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); - } + friend void swap_context(ia64_gcc_context_impl_base& from, + ia64_gcc_context_impl const& to, default_hint); #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& from, + ia64_gcc_context_impl_base const& to, yield_hint); - 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); - } + friend void swap_context(ia64_gcc_context_impl& from, + ia64_gcc_context_impl_base const& to, yield_to_hint); #endif protected: @@ -102,13 +94,14 @@ class ia64_gcc_context_impl : public ia64_gcc_context_impl_base { public: - enum { default_stack_size = 8192 }; - + enum { default_stack_size = 2*8192 }; + typedef ia64_gcc_context_impl_base context_impl_base; - ia64_gcc_context_impl() : - m_stack(0) {} - + 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. @@ -120,17 +113,28 @@ { BOOST_ASSERT(m_stack); m_sp = ((void**)m_stack + (m_stack_size/sizeof(void*))); - + + *(void**)m_stack = (void*)~0; // fill the last word with ones + typedef void fun(Functor*); fun * funp = trampoline; + // we have to make sure that the stack pointer is aligned on a 16 Byte + // boundary when the code is entering the trampoline (the stack itself + // is already properly aligned) + *--m_sp = 0; // additional alignment + *--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 + *--m_sp = 0; // rbp + *--m_sp = 0; // rbx + *--m_sp = 0; // rsi + *--m_sp = 0; // rdi + *--m_sp = 0; // r12 + *--m_sp = 0; // r13 + *--m_sp = 0; // r14 + *--m_sp = 0; // r15 } ~ia64_gcc_context_impl() @@ -139,12 +143,55 @@ posix::free_stack(m_stack, m_stack_size); } + friend void swap_context(ia64_gcc_context_impl_base& from, + ia64_gcc_context_impl const& to, default_hint); + +#ifndef BOOST_COROUTINE_NO_SEPARATE_CALL_SITES + friend void swap_context(ia64_gcc_context_impl& from, + ia64_gcc_context_impl_base const& to, yield_hint); + + friend void swap_context(ia64_gcc_context_impl& from, + ia64_gcc_context_impl_base const& to, yield_to_hint); +#endif + private: std::ptrdiff_t m_stack_size; void * m_stack; }; typedef ia64_gcc_context_impl context_impl; + + /** + * Free function. Saves the current context in @p from + * and restores the context in @p to. + * @note This function is found by ADL. + */ + inline void swap_context(ia64_gcc_context_impl_base& from, + ia64_gcc_context_impl const& to, default_hint) + { +// BOOST_ASSERT(*(void**)to.m_stack == (void*)~0); + to.prefetch(); + swapcontext_stack(&from.m_sp, to.m_sp); + } + +#ifndef BOOST_COROUTINE_NO_SEPARATE_CALL_SITES + inline void swap_context(ia64_gcc_context_impl& from, + ia64_gcc_context_impl_base const& to, yield_hint) + { +// BOOST_ASSERT(*(void**)from.m_stack == (void*)~0); + to.prefetch(); + swapcontext_stack2(&from.m_sp, to.m_sp); + } + + inline void swap_context(ia64_gcc_context_impl& from, + ia64_gcc_context_impl_base const& to, yield_to_hint) + { +// BOOST_ASSERT(*(void**)from.m_stack == (void*)~0); + to.prefetch(); + swapcontext_stack3(&from.m_sp, to.m_sp); + } +#endif + } }}} @@ -165,3 +212,4 @@ #endif + Index: boost/coroutine/detail/posix_utility.hpp =================================================================== --- boost/coroutine/detail/posix_utility.hpp (revision 66623) +++ boost/coroutine/detail/posix_utility.hpp (working copy) @@ -38,6 +38,7 @@ #include #include #include +#include #include #include /** @@ -134,7 +135,7 @@ 0 ); if(stack == MAP_FAILED) { - std::cerr < type; - typedef context_base context_base; + typedef context_base context_base2; typedef typename coroutine_type::arg_slot_type arg_slot_type; typedef typename coroutine_type::result_type result_type; typedef typename coroutine_type::result_slot_type result_slot_type; @@ -65,7 +65,7 @@ template coroutine_impl(DerivedType * this_, std::ptrdiff_t stack_size) : - context_base(*this_, stack_size), + context_base2(*this_, stack_size), m_arg(0), m_result(0){} Index: libs/coroutine/src/swapcontext64.cpp =================================================================== --- libs/coroutine/src/swapcontext64.cpp (revision 66623) +++ libs/coroutine/src/swapcontext64.cpp (working copy) @@ -19,7 +19,7 @@ * For now resort to inline asm. */ -// RDI is &from.sp +// RDI is &from.sp // RSI is to.sp // // This is the simplest version of swapcontext @@ -53,22 +53,30 @@ ".type " #name ", @function\n\t" \ ".align 16\n" \ #name ":\n\t" \ - "movq 32(%rsi), %rcx\n\t" \ + "movq 64(%rsi), %rcx\n\t" \ "pushq %rbp\n\t" \ "pushq %rbx\n\t" \ "pushq %rax\n\t" \ "pushq %rdx\n\t" \ + "pushq %r12\n\t" \ + "pushq %r13\n\t" \ + "pushq %r14\n\t" \ + "pushq %r15\n\t" \ "movq %rsp, (%rdi)\n\t" \ "movq %rsi, %rsp\n\t" \ + "popq %r15\n\t" \ + "popq %r14\n\t" \ + "popq %r13\n\t" \ + "popq %r12\n\t" \ "popq %rdx\n\t" \ "popq %rax\n\t" \ "popq %rbx\n\t" \ "popq %rbp\n\t" \ - "movq 48(%rsi), %rdi\n\t" \ + "movq 80(%rsi), %rdi\n\t" \ "add $8, %rsp\n\t" \ "jmp *%rcx\n\t" \ "ud2\n\t" \ - ) \ + ) /**/ BOOST_COROUTINE_SWAPCONTEXT(swapcontext_stack);