diff --git a/doc/todo.qbk b/doc/todo.qbk new file mode 100644 index 00000000..da579930 --- /dev/null +++ b/doc/todo.qbk @@ -0,0 +1,13 @@ +[/ + Copyright Oliver Kowalke 2009. + 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 +] + +[section:todo Todo] + +* provide support for SPARC, SuperH (SH4), S/390 +* support split-stack feature from gcc/gold linker + +[endsect] diff --git a/include/boost/context/detail/fcontext_arm.hpp b/include/boost/context/detail/fcontext_arm.hpp new file mode 100644 index 00000000..8b88ccfd --- /dev/null +++ b/include/boost/context/detail/fcontext_arm.hpp @@ -0,0 +1,68 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_ARM_H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * sp; + std::size_t size; + + stack_t() : + sp( 0), size( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[16]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[11]; + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_H diff --git a/include/boost/context/detail/fcontext_arm_mac.hpp b/include/boost/context/detail/fcontext_arm_mac.hpp new file mode 100644 index 00000000..a8416efd --- /dev/null +++ b/include/boost/context/detail/fcontext_arm_mac.hpp @@ -0,0 +1,70 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * sp; + std::size_t size; + + stack_t() : + sp( 0), size( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[16]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[11]; + stack_t fc_stack; + fp_t fc_fp; + void * fc_unwind_sjlj; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp(), + fc_unwind_sjlj( 0) + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_MAC_H diff --git a/include/boost/context/detail/fcontext_arm_win.hpp b/include/boost/context/detail/fcontext_arm_win.hpp new file mode 100644 index 00000000..5449ae76 --- /dev/null +++ b/include/boost/context/detail/fcontext_arm_win.hpp @@ -0,0 +1,71 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * sp; + std::size_t size; + void * limit; + + stack_t() : + sp( 0), size( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[16]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[11]; + stack_t fc_stack; + fp_t fc_fp; + boost::uint32_t fc_dealloc; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp(), + fc_dealloc( 0) + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_ARM_WIN_H diff --git a/include/boost/context/detail/fcontext_i386.hpp b/include/boost/context/detail/fcontext_i386.hpp new file mode 100644 index 00000000..2e013235 --- /dev/null +++ b/include/boost/context/detail/fcontext_i386.hpp @@ -0,0 +1,59 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_I386H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_I386H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL __attribute__((cdecl)) + +struct stack_t +{ + void * sp; + std::size_t size; + + stack_t() : + sp( 0), size( 0) + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[6]; + stack_t fc_stack; + boost::uint32_t fc_freg[2]; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_freg() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_I386_H diff --git a/include/boost/context/detail/fcontext_i386_win.hpp b/include/boost/context/detail/fcontext_i386_win.hpp new file mode 100644 index 00000000..44c6b0ef --- /dev/null +++ b/include/boost/context/detail/fcontext_i386_win.hpp @@ -0,0 +1,88 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_I386H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_I386H + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +#include +#include + +#include + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable:4351) +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL __cdecl + +struct stack_t +{ + void * sp; + std::size_t size; + void * limit; + + stack_t() : + sp( 0), size( 0), limit( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[2]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[6]; + stack_t fc_stack; + void * fc_excpt_lst; + void * fc_local_storage; + fp_t fc_fp; + boost::uint32_t fc_dealloc; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_excpt_lst( 0), + fc_local_storage( 0), + fc_fp(), + fc_dealloc( 0) + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_I386_H diff --git a/include/boost/context/detail/fcontext_mips.hpp b/include/boost/context/detail/fcontext_mips.hpp new file mode 100644 index 00000000..d3cd60de --- /dev/null +++ b/include/boost/context/detail/fcontext_mips.hpp @@ -0,0 +1,70 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_MIPS_H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_MIPS_H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +// on MIPS we assume 64bit regsiters - even for 32bit ABIs + +struct stack_t +{ + void * sp; + std::size_t size; + + stack_t() : + sp( 0), size( 0) + {} +}; + +struct fp_t +{ + boost::uint64_t fc_freg[6]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint32_t fc_greg[12]; + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_MIPS_H diff --git a/include/boost/context/detail/fcontext_ppc.hpp b/include/boost/context/detail/fcontext_ppc.hpp new file mode 100644 index 00000000..6cb019f5 --- /dev/null +++ b/include/boost/context/detail/fcontext_ppc.hpp @@ -0,0 +1,72 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_PPC_H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_PPC_H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * sp; + std::size_t size; + + stack_t() : + sp( 0), size( 0) + {} +}; + +struct fp_t +{ + boost::uint64_t fc_freg[19]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ +# if defined(__powerpc64__) + boost::uint64_t fc_greg[23]; +# else + boost::uint32_t fc_greg[23]; +# endif + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_PPC_H diff --git a/include/boost/context/detail/fcontext_sparc.hpp b/include/boost/context/detail/fcontext_sparc.hpp new file mode 100644 index 00000000..9264714a --- /dev/null +++ b/include/boost/context/detail/fcontext_sparc.hpp @@ -0,0 +1,90 @@ +// Copyright Martin Husemann 2012 +// 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_CTX_DETAIL_FCONTEXT_SPARC_H +#define BOOST_CTX_DETAIL_FCONTEXT_SPARC_H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +// if defined(_LP64) we are compiling for sparc64, otherwise it is 32 bit +// sparc. + + +struct stack_t +{ + void * sp; + std::size_t size; + + stack_t() : + sp( 0), size( 0) + {} +}; + +struct fp_t +{ +#ifdef _LP64 + boost::uint64_t fp_freg[32]; + boost::uint64_t fp_fprs, fp_fsr; +#else + boost::uint64_t fp_freg[16]; + boost::uint32_t fp_fsr; +#endif + + fp_t() : + fp_freg(), +#ifdef _LP64 + fp_fprs(), +#endif + fp_fsr() + {} +} +#ifdef _LP64 + __attribute__((__aligned__(64))) // allow VIS instructions to be used +#endif +; + +struct fcontext_t +{ + fp_t fc_fp; // fpu stuff first, for easier alignement +#ifdef _LP64 + boost::uint64_t +#else + boost::uint32_t +#endif + fc_greg[8]; + stack_t fc_stack; + + fcontext_t() : + fc_fp(), + fc_greg(), + fc_stack() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CTX_DETAIL_FCONTEXT_SPARC_H diff --git a/include/boost/context/detail/fcontext_x86_64.hpp b/include/boost/context/detail/fcontext_x86_64.hpp new file mode 100644 index 00000000..6e8d93c0 --- /dev/null +++ b/include/boost/context/detail/fcontext_x86_64.hpp @@ -0,0 +1,68 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_X86_64_H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H + +#include + +#include +#include + +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * sp; + std::size_t size; + + stack_t() : + sp( 0), size( 0) + {} +}; + +struct fp_t +{ + boost::uint32_t fc_freg[2]; + + fp_t() : + fc_freg() + {} +}; + +struct fcontext_t +{ + boost::uint64_t fc_greg[8]; + stack_t fc_stack; + fp_t fc_fp; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_fp() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H diff --git a/include/boost/context/detail/fcontext_x86_64_win.hpp b/include/boost/context/detail/fcontext_x86_64_win.hpp new file mode 100644 index 00000000..7bcea55f --- /dev/null +++ b/include/boost/context/detail/fcontext_x86_64_win.hpp @@ -0,0 +1,77 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_X86_64_H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +#include +#include + +#include + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable:4351) +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { + +extern "C" { + +#define BOOST_CONTEXT_CALLDECL + +struct stack_t +{ + void * sp; + std::size_t size; + void * limit; + + stack_t() : + sp( 0), size( 0), limit( 0) + {} +}; + +struct fcontext_t +{ + boost::uint64_t fc_greg[10]; + stack_t fc_stack; + void * fc_local_storage; + boost::uint64_t fc_fp[24]; + boost::uint64_t fc_dealloc; + + fcontext_t() : + fc_greg(), + fc_stack(), + fc_local_storage( 0), + fc_fp(), + fc_dealloc() + {} +}; + +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_X86_64_H diff --git a/include/boost/context/execution_context.hpp b/include/boost/context/execution_context.hpp index 7e38c8fd..94e63658 100644 --- a/include/boost/context/execution_context.hpp +++ b/include/boost/context/execution_context.hpp @@ -245,7 +245,7 @@ class BOOST_CONTEXT_DECL execution_context { ptr_( create_worker_fcontext( salloc, std::forward< Fn >( fn), std::make_tuple( std::forward< Args >( args) ... ), - std::index_sequence_for< Args ... >() ) ) { + std::index_sequence_for< Args ... >() ) ), use_segmented_stack_( true) { } @@ -254,7 +254,7 @@ class BOOST_CONTEXT_DECL execution_context { ptr_( create_worker_fcontext( palloc, salloc, std::forward< Fn >( fn), std::make_tuple( std::forward< Args >( args) ... ), - std::index_sequence_for< Args ... >() ) ) { + std::index_sequence_for< Args ... >() ) ), use_segmented_stack_( true) { } # endif diff --git a/performance/Jamfile.v2 b/performance/Jamfile.v2 new file mode 100644 index 00000000..108c0e1c --- /dev/null +++ b/performance/Jamfile.v2 @@ -0,0 +1,64 @@ + +# Copyright Oliver Kowalke 2009. +# 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) + +# For more information, see http://www.boost.org/ + +import common ; +import feature ; +import indirect ; +import modules ; +import os ; +import toolset ; + +project boost/context/performance + : requirements + /boost/context//boost_context + static + "-lrt" + single + ; + +alias sources + : performance.cpp + bind_processor_aix.cpp + : aix + ; + +alias sources + : performance.cpp + bind_processor_freebsd.cpp + : freebsd + ; + +alias sources + : performance.cpp + bind_processor_hpux.cpp + : hpux + ; + +alias sources + : performance.cpp + bind_processor_linux.cpp + : linux + ; + +alias sources + : performance.cpp + bind_processor_solaris.cpp + : solaris + ; + +alias sources + : performance.cpp + bind_processor_windows.cpp + : windows + ; + +explicit sources ; + +exe performance + : sources + ; diff --git a/performance/performance.cpp b/performance/performance.cpp new file mode 100644 index 00000000..998518c9 --- /dev/null +++ b/performance/performance.cpp @@ -0,0 +1,264 @@ + +// Copyright Oliver Kowalke 2009. +// 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) + +#define BOOST_PP_LIMIT_MAG 10 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../example/simple_stack_allocator.hpp" + +#ifdef BOOST_USE_UCONTEXT +#include +#endif + +#include "bind_processor.hpp" +#include "cycle.hpp" + +#if _POSIX_C_SOURCE >= 199309L +#include "zeit.hpp" +#endif + +namespace ctx = boost::context; + +typedef ctx::simple_stack_allocator< + 8 * 1024 * 1024, // 8MB + 64 * 1024, // 64kB + 8 * 1024 // 8kB +> stack_allocator; + +bool pres_fpu = false; + +#define CALL_FCONTEXT(z,n,unused) ctx::jump_fcontext( & fcm, fc, 7, pres_fpu); + +#ifdef BOOST_USE_UCONTEXT +# define CALL_UCONTEXT(z,n,unused) ::swapcontext( & ucm, & uc); +#endif + +#define CALL_FUNCTION(z,n,unused) fn(); + + +ctx::fcontext_t fcm, * fc; + +#ifdef BOOST_USE_UCONTEXT +ucontext_t uc, ucm; +#endif + + +static void f1( intptr_t) +{ while ( true) ctx::jump_fcontext( fc, & fcm, 7, pres_fpu); } + +#ifdef BOOST_USE_UCONTEXT +static void f2() +{ while ( true) ::swapcontext( & uc, & ucm); } +#endif + +static void f3() +{} + + +#ifdef BOOST_CONTEXT_CYCLE +cycle_t test_fcontext_cycle( cycle_t ov) +{ + stack_allocator alloc; + fc = ctx::make_fcontext( + alloc.allocate(stack_allocator::default_stacksize()), + stack_allocator::default_stacksize(), + f1); + + ctx::jump_fcontext( & fcm, fc, 7, pres_fpu); + + // cache warum-up +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~) + + cycle_t start( cycles() ); +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~) + cycle_t total( cycles() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} + +# ifdef BOOST_USE_UCONTEXT +cycle_t test_ucontext_cycle( cycle_t ov) +{ + stack_allocator alloc; + + ::getcontext( & uc); + uc.uc_stack.ss_sp = alloc.allocate(stack_allocator::default_stacksize()); + uc.uc_stack.ss_size = stack_allocator::default_stacksize(); + ::makecontext( & uc, f2, 7); + + // cache warum-up +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_UCONTEXT, ~) + + cycle_t start( cycles() ); +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_UCONTEXT, ~) + cycle_t total( cycles() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} +# endif + +cycle_t test_function_cycle( cycle_t ov) +{ + boost::function< void() > fn( boost::bind( f3) ); + // cache warum-up +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~) + + cycle_t start( cycles() ); +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~) + cycle_t total( cycles() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} +#endif + + +#if _POSIX_C_SOURCE >= 199309L +zeit_t test_fcontext_zeit( zeit_t ov) +{ + stack_allocator alloc; + fc = ctx::make_fcontext( + alloc.allocate(stack_allocator::default_stacksize()), + stack_allocator::default_stacksize(), + f1); + + ctx::jump_fcontext( & fcm, fc, 7, pres_fpu); + + // cache warum-up +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~) + + zeit_t start( zeit() ); +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FCONTEXT, ~) + zeit_t total( zeit() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} + +# ifdef BOOST_USE_UCONTEXT +zeit_t test_ucontext_zeit( zeit_t ov) +{ + stack_allocator alloc; + + ::getcontext( & uc); + uc.uc_stack.ss_sp = alloc.allocate(stack_allocator::default_stacksize()); + uc.uc_stack.ss_size = stack_allocator::default_stacksize(); + ::makecontext( & uc, f2, 7); + + // cache warum-up +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_UCONTEXT, ~) + + zeit_t start( zeit() ); +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_UCONTEXT, ~) + zeit_t total( zeit() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} +# endif + +zeit_t test_function_zeit( zeit_t ov) +{ + boost::function< void() > fn( boost::bind( f3) ); + // cache warum-up +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~) + + zeit_t start( zeit() ); +BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_FUNCTION, ~) + zeit_t total( zeit() - start); + + // we have two jumps and two measuremt-overheads + total -= ov; // overhead of measurement + total /= BOOST_PP_LIMIT_MAG; // per call + total /= 2; // 2x jump_to c1->c2 && c2->c1 + + return total; +} +#endif + +int main( int argc, char * argv[]) +{ + try + { + bind_to_processor( 0); + +#ifdef BOOST_CONTEXT_CYCLE + { + cycle_t ov( overhead_cycles() ); + std::cout << "overhead for rdtsc == " << ov << " cycles" << std::endl; + + unsigned int res = test_fcontext_cycle( ov); + std::cout << "fcontext: average of " << res << " cycles per switch" << std::endl; +# ifdef BOOST_USE_UCONTEXT + res = test_ucontext_cycle( ov); + std::cout << "ucontext: average of " << res << " cycles per switch" << std::endl; +# endif + res = test_function_cycle( ov); + std::cout << "boost::function: average of " << res << " cycles per switch" << std::endl; + } +#endif + +#if _POSIX_C_SOURCE >= 199309L + { + zeit_t ov( overhead_zeit() ); + std::cout << "\noverhead for clock_gettime() == " << ov << " ns" << std::endl; + + unsigned int res = test_fcontext_zeit( ov); + std::cout << "fcontext: average of " << res << " ns per switch" << std::endl; +# ifdef BOOST_USE_UCONTEXT + res = test_ucontext_zeit( ov); + std::cout << "ucontext: average of " << res << " ns per switch" << std::endl; +# endif + res = test_function_zeit( ov); + std::cout << "boost::function: average of " << res << " ns per switch" << std::endl; + } +#endif + + return EXIT_SUCCESS; + } + catch ( std::exception const& e) + { std::cerr << "exception: " << e.what() << std::endl; } + catch (...) + { std::cerr << "unhandled exception" << std::endl; } + return EXIT_FAILURE; +} + +#undef CALL_FCONTEXT +#undef CALL_UCONTEXT diff --git a/performance/zeit.hpp b/performance/zeit.hpp new file mode 100644 index 00000000..2c082bf2 --- /dev/null +++ b/performance/zeit.hpp @@ -0,0 +1,53 @@ + +// Copyright Oliver Kowalke 2009. +// 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 ZEIT_H +#define ZEIT_H + +#include + +#include +#include +#include +#include + +#include +#include +#include + +typedef boost::uint64_t zeit_t; + +inline +zeit_t zeit() +{ + timespec t; + ::clock_gettime( CLOCK_PROCESS_CPUTIME_ID, & t); + return t.tv_sec * 1000000000 + t.tv_nsec; +} + +struct measure_zeit +{ + zeit_t operator()() + { + zeit_t start( zeit() ); + return zeit() - start; + } +}; + +inline +zeit_t overhead_zeit() +{ + std::size_t iterations( 10); + std::vector< zeit_t > overhead( iterations, 0); + for ( std::size_t i( 0); i < iterations; ++i) + std::generate( + overhead.begin(), overhead.end(), + measure_zeit() ); + BOOST_ASSERT( overhead.begin() != overhead.end() ); + return std::accumulate( overhead.begin(), overhead.end(), 0) / iterations; +} + +#endif // ZEIT_H