Commit 3f7b5ad0 by FritzFlorian

Implement custom fast call fiber for arm32.

The basic calling works, next we measure on both x86 and arm and then decide on how we implement our fiber/'staggered stack' abstraction.
parent 5b791d0e
Pipeline #1379 failed with stages
in 36 seconds
......@@ -3,8 +3,9 @@ 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 "arm" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
# SET(SWITCH_ASSEMBLY "custom_stack_callback_arm32.s" fiber_call.h fiber_call.cpp)
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
SET(SWITCH_ASSEMBLY "custom_stack_callback_arm32.s" fiber_call.h fiber_call.cpp)
SET(FIBER_ASSEMBLY "fiber_call_arm32.s" "fiber_continue_arm32.s")
else ()
MESSAGE(FATAL_ERROR "Platform (${CMAKE_SYSTEM_PROCESSOR} on ${CMAKE_SYSTEM_NAME}) not supported! Please see Readme for instructions to port.")
endif ()
......
......@@ -4,18 +4,18 @@ project(fcontext C)
if (NOT CMAKE_MODULE_PATH)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
endif()
endif ()
if (MSVC)
enable_language(CXX ASM_MASM)
else()
else ()
enable_language(CXX ASM)
endif()
endif ()
if(MSVC)
if (MSVC)
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
add_definitions(-D_HAS_EXCEPTIONS=0)
endif()
endif ()
add_definitions(-DBOOST_CONTEXT_EXPORT=)
set(HEADER "include/fcontext/fcontext.h")
......@@ -39,24 +39,28 @@ elseif (ANDROID)
elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64")
set(CPU_ARCH "x86_64")
set(ASM_EXT "sysv_elf_gas.S")
endif()
endif ()
elseif (UNIX)
# PC (x86/x64)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l")
set(CPU_ARCH "arm")
set(ASM_EXT "aapcs_elf_gas.S") # Untested, but should work for linux/unix
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(CPU_ARCH "x86_64")
else()
set(ASM_EXT "sysv_elf_gas.S") # Linux/Unix
else ()
set(CPU_ARCH "i386")
endif()
set(ASM_EXT "sysv_elf_gas.S") # Linux/Unix
endif ()
elseif (WIN32)
# Windows PC
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(CPU_ARCH "x86_64")
else()
else ()
set(CPU_ARCH "i386")
endif()
endif ()
set(ASM_EXT "ms_pe_masm.asm")
endif()
endif ()
set(ASM_SOURCES "asm/make_${CPU_ARCH}_${ASM_EXT}"
"asm/jump_${CPU_ARCH}_${ASM_EXT}"
......
.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}
.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
* 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 result from this function. */
mov r4, 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, r4
pop {pc}
......@@ -32,7 +32,7 @@ __fiber_continue:
############### Save State ###############
# Perform change to new stack.
# Keep old stack as second parameter to our callback function.
# Keep old stack as result from this function
movq %rsp, %r12
# switch to new stack pointer
movq %rdi, %rsp
......
......@@ -28,6 +28,16 @@ void __attribute__ ((noinline)) callback() {
}
}
long measure_loop() {
auto start_time = chrono::steady_clock::now();
volatile int tmp;
for (unsigned int i = 0; i < NUM_RUNS; i++) {
tmp = 0;
}
auto end_time = chrono::steady_clock::now();
return chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count();
}
long measure_function_call() {
auto start_time = chrono::steady_clock::now();
for (unsigned int i = 0; i < NUM_RUNS; i++) {
......@@ -138,6 +148,7 @@ int main() {
auto time_cont = measure_continuation();
auto time_stack = measure_stack_switch();
auto time_func = measure_function_call();
auto time_loop = measure_loop();
auto time_fcontext_fast = measure_fcontext_fast();
auto time_fcontext_clean = measure_fcontext_clean();
auto time_fcontext_calcc = measure_fcontext_callcc();
......@@ -145,6 +156,7 @@ int main() {
printf("Base\n");
printf("Function Call : %10ld, %5.5f\n", time_func, ((float) time_func / NUM_RUNS));
printf("Simple Loop : %10ld, %5.5f\n", time_loop, ((float) time_loop / NUM_RUNS));
printf("Longjmp\n");
printf("Stack Switching : %10ld, %5.5f\n", time_stack, ((float) time_stack / NUM_RUNS));
printf("Full Continuation: %10ld, %5.5f\n", time_cont, ((float) time_cont / NUM_RUNS));
......
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