Commit 01596ff3 by FritzFlorian

Change context_switch app to use context_switcher library.

parent 6ee522a3
Pipeline #1392 failed with stages
in 27 seconds
......@@ -2,10 +2,8 @@ add_subdirectory(deboost.context)
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
SET(SWITCH_ASSEMBLY "custom_stack_callback_x86_64.s")
SET(FIBER_ASSEMBLY "fiber_call_x86_64.s" "fiber_continue_x86_64.s")
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
SET(SWITCH_ASSEMBLY "custom_stack_callback_arm32.s" fiber_call.h context_switcher.cpp)
SET(FIBER_ASSEMBLY "fiber_call_arm32.s" "fiber_continue_arm32.s")
SET(SWITCH_ASSEMBLY "custom_stack_callback_arm32.s")
else ()
MESSAGE(FATAL_ERROR "Platform (${CMAKE_SYSTEM_PROCESSOR} on ${CMAKE_SYSTEM_NAME}) not supported! Please see Readme for instructions to port.")
endif ()
......@@ -13,9 +11,7 @@ endif ()
add_executable(context_switch
main.cpp
${SWITCH_ASSEMBLY}
fiber_call.h
${FIBER_ASSEMBLY})
${SWITCH_ASSEMBLY})
# Example for adding the library to your app (as a cmake project dependency)
target_link_libraries(context_switch fcontext)
target_link_libraries(context_switch fcontext context_switcher)
#ifndef PREDICTABLE_PARALLEL_PATTERNS_APP_CONTEXT_SWITCH_FIBER_CALL_H_
#define PREDICTABLE_PARALLEL_PATTERNS_APP_CONTEXT_SWITCH_FIBER_CALL_H_
#include <utility>
#include <cstdio>
#include <cstdint>
#include <new>
namespace pls {
namespace internal {
namespace base {
using continuation_t = void *;
using stack_pointer_t = char *;
using callback_t = continuation_t (*)(continuation_t, void *);
template<typename F>
struct lambda_capture {
F lambda_;
explicit lambda_capture(F &&lambda) : lambda_{std::forward<F>(lambda)} {}
continuation_t operator()(continuation_t continuation) {
return lambda_(continuation);
}
};
template<typename T>
continuation_t execute_callable(continuation_t continuation, void *param) {
T *callable = reinterpret_cast<T *>(param);
continuation_t result = (*callable)(continuation);
callable->~T();
return result;
}
extern "C" {
continuation_t __fiber_call(stack_pointer_t stack_base,
void *callback_arg,
callback_t callback,
stack_pointer_t stack_limit);
continuation_t __fiber_continue(continuation_t continuation);
}
template<typename F>
static lambda_capture<F> *place_lambda_capture(F &&lambda, char *memory) {
return new(memory) lambda_capture<F>(std::forward<F>(lambda));
}
template<typename F>
continuation_t fiber_call(stack_pointer_t stack_memory, size_t stack_size, F &&lambda) {
stack_pointer_t lambda_memory = stack_memory + stack_size - sizeof(lambda_capture<F>);
auto *captured_lambda = place_lambda_capture(std::forward<F>(lambda), lambda_memory);
stack_pointer_t stack_base = lambda_memory;
stack_pointer_t stack_limit = stack_memory;
callback_t callback = execute_callable<lambda_capture<F>>;
return __fiber_call(stack_base, captured_lambda, callback, stack_limit);
}
}
}
}
#endif //PREDICTABLE_PARALLEL_PATTERNS_APP_CONTEXT_SWITCH_FIBER_CALL_H_
.arm
.text
.global __fiber_call
.type __fiber_call, %function
__fiber_call:
/* Parameter List (in order)
* r0 = new stack pointer
* r1 = first parameter to callback
* r2 = callback function pointer
* r3 = new stack limit (not used on most platforms)
*
* Return
* r0 = continuation that returned control back to the caller (null if fallthrough)
*
* Variables
* r4 = temporary for the old stack pointer */
/* ========== Save State ========== */
/* store programm counter for later return */
push {lr}
/* store callee saved registers */
push {r4-r12,lr}
/* ========== Save State ========== */
/* Perform change to new stack */
/* Keep old stack as second parameter to our callback function. */
mov r4, sp
/* Make sure that stack start is properly aligned. */
and r0, r0, #-16
/* Switch to new stack pointer. */
mov sp, r0
/* Perform actual function call, this will now be on the new stack */
/* r0 = first parametor to callback (continuation) */
/* r1 = second parameter to callback (arbetary pointer) */
mov r0, r4
blx r2
/* Restore state of returned continuation. */
/* To do so we first reset the stack pointer (which we get returned in r0). */
/* After that we execute our standard restore procedere to pop the state from the stack. */
mov sp, r0
/* ========== Restore State ========== */
/* restore callee saved registers */
pop {r4-r12,lr}
/* ========== Restore State ========== */
/* Just return back from the call. */
/* This is the end of a fiber, so we have no continuation. */
eor r0, r0, r0
pop {pc}
.file "fiber_call_x86_64.s"
.text
.global __fiber_call
.type __fiber_call, @function
.align 16
__fiber_call:
# Parameter List (in order)
# rdi = new stack pointer
# rsi = first parameter to callback
# rdx = callback function pointer
# rcx = new stack limit (not used on most platforms)
# Return
# rax = continuation that returned control back to the caller (null if fallthrough)
# Variables
# r12 = temporary for the old stack pointer
############### Save State ###############
# Make space for all register state we will store.
leaq -0x38(%rsp), %rsp
# Store calee saved general registers.
movq %r12, 0x00(%rsp)
movq %r13, 0x08(%rsp)
movq %r14, 0x10(%rsp)
movq %r15, 0x18(%rsp)
movq %rbx, 0x20(%rsp)
movq %rbp, 0x28(%rsp)
# Store MMX control- and status-word
stmxcsr 0x30(%rsp)
# Store x87 control-word
fnstcw 0x34(%rsp)
############### Save State ###############
# Perform change to new stack.
# Keep old stack as second parameter to our callback function.
movq %rsp, %r12
# Make sure that stack start is properly aligned.
andq $-16, %rdi
# Switch to new stack pointer.
movq %rdi, %rsp
# Perform actual function call, this will now be on the new stack
# rdi = first parametor to callback (continuation)
# rsi = second parameter to callback (arbetary pointer)
movq %r12, %rdi
call *%rdx
# Restore state of returned continuation.
# To do so we first reset the stack pointer (which we get returned in rax).
# After that we execute our standard restore procedere to pop the state from the stack.
movq %rax, %rsp
############ Restore State ############
# restore calee saved general registers
movq 0x00(%rsp), %r12
movq 0x08(%rsp), %r13
movq 0x10(%rsp), %r14
movq 0x18(%rsp), %r15
movq 0x20(%rsp), %rbx
movq 0x28(%rsp), %rbp
# restore MMX control- and status-word
ldmxcsr 0x30(%rsp)
# restore x87 control-word
fldcw 0x34(%rsp)
# Free space for restored state
leaq 0x38(%rsp), %rsp
############ Restore State ############
# TODO: Maybe look into a 'cleanup' hook for freeing the stack space here.
# Just return back from the call.
# This is the end of a fiber, so we have no continuation.
xor %rax, %rax
ret
.arm
.text
.global __fiber_continue
.type __fiber_continue, %function
__fiber_continue:
/* Parameter List (in order)
* r0 = pointer to continuation (should hold value of target stack will be filled with this continuation)
*
* Return
* r0 = continuation that returned control back to the caller (null if fallthrough)
*
* Variables
* r1 = temporary for the old stack pointer */
/* ========== Save State ========== */
/* store programm counter for later return */
push {lr}
/* store callee saved registers */
push {r4-r12,lr}
/* ========== Save State ========== */
/* Perform change to new stack */
/* Keep old stack as result from this function. */
mov r1, sp
/* Switch to new stack pointer. */
mov sp, r0
/* ========== Restore State ========== */
/* restore callee saved registers */
pop {r4-r12,lr}
/* ========== Restore State ========== */
/* Just return back from the call. */
/* This is the end of a fiber, so we have no continuation. */
mov r0, r1
pop {pc}
.file "fiber_continue_x86_64.s"
.text
.global __fiber_continue
.type __fiber_continue, @function
.align 16
__fiber_continue:
# Parameter List (in order)
# rdi = pointer to continuation (should hold value of target stack will be filled with this continuation)
# Return
# rax = continuation that returned control back to the caller (null if fallthrough)
############### Save State ###############
# Make space for all register state we will store.
leaq -0x38(%rsp), %rsp
# Store calee saved general registers.
movq %r12, 0x00(%rsp)
movq %r13, 0x08(%rsp)
movq %r14, 0x10(%rsp)
movq %r15, 0x18(%rsp)
movq %rbx, 0x20(%rsp)
movq %rbp, 0x28(%rsp)
# Store MMX control- and status-word
stmxcsr 0x30(%rsp)
# Store x87 control-word
fnstcw 0x34(%rsp)
############### Save State ###############
# Perform change to new stack.
# Keep old stack as result from this function
movq %rsp, %rax
# switch to new stack pointer
movq %rdi, %rsp
############ Restore State ############
# restore calee saved general registers
movq 0x00(%rsp), %r12
movq 0x08(%rsp), %r13
movq 0x10(%rsp), %r14
movq 0x18(%rsp), %r15
movq 0x20(%rsp), %rbx
movq 0x28(%rsp), %rbp
# restore MMX control- and status-word
ldmxcsr 0x30(%rsp)
# restore x87 control-word
fldcw 0x34(%rsp)
# Free space for restored state
leaq 0x38(%rsp), %rsp
############ Restore State ############
# Return the context we came from as a continuation.
# Result is already in rax.
ret
......@@ -2,10 +2,12 @@
#include <csetjmp>
#include <cstring>
#include <chrono>
#include <utility>
#include "fcontext/fcontext.h"
#include "fiber_call.h"
#include "context_switcher/context_switcher.h"
#include "context_switcher/continuation.h"
using namespace std;
......@@ -128,13 +130,11 @@ long measure_fcontext_callcc() {
}
long measure_custom() {
using namespace pls::internal::base;
auto start_time = chrono::steady_clock::now();
for (unsigned int i = 0; i < NUM_RUNS; i++) {
fiber_call(custom_stack_1, STACK_SIZE, [](continuation_t continuation) {
context_switcher::enter_context(custom_stack_1, STACK_SIZE, [](context_switcher::continuation &&continuation) {
callback();
return continuation;
return std::move(continuation);
});
}
auto end_time = chrono::steady_clock::now();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment