mirror of
https://github.com/boostorg/context.git
synced 2026-01-19 04:02:17 +00:00
unwind without throw
This commit is contained in:
669
build/Jamfile.v2
669
build/Jamfile.v2
@@ -52,18 +52,11 @@ project boost/context
|
||||
local rule default_binary_format ( )
|
||||
{
|
||||
local tmp = elf ;
|
||||
if [ os.name ] = "NT" { tmp = pe ; }
|
||||
else if [ os.name ] = "CYGWIN" { tmp = pe ; }
|
||||
else if [ os.name ] = "AIX" { tmp = xcoff ; }
|
||||
else if [ os.name ] = "MACOSX" { tmp = mach-o ; }
|
||||
return $(tmp) ;
|
||||
}
|
||||
|
||||
feature.feature binary-format
|
||||
: elf
|
||||
mach-o
|
||||
pe
|
||||
xcoff
|
||||
: propagated
|
||||
;
|
||||
feature.set-default binary-format : [ default_binary_format ] ;
|
||||
@@ -72,23 +65,11 @@ feature.set-default binary-format : [ default_binary_format ] ;
|
||||
local rule default_abi ( )
|
||||
{
|
||||
local tmp = sysv ;
|
||||
if [ os.name ] = "NT" { tmp = ms ; }
|
||||
else if [ os.name ] = "CYGWIN" { tmp = ms ; }
|
||||
else if [ os.platform ] = "ARM" { tmp = aapcs ; }
|
||||
else if [ os.platform ] = "MIPS" { tmp = o32 ; }
|
||||
return $(tmp) ;
|
||||
}
|
||||
|
||||
feature.feature abi
|
||||
: aapcs
|
||||
eabi
|
||||
ms
|
||||
n32
|
||||
n64
|
||||
o32
|
||||
o64
|
||||
sysv
|
||||
x32
|
||||
: sysv
|
||||
: propagated
|
||||
;
|
||||
feature.set-default abi : [ default_abi ] ;
|
||||
@@ -96,454 +77,14 @@ feature.set-default abi : [ default_abi ] ;
|
||||
|
||||
feature.feature context-impl
|
||||
: fcontext
|
||||
ucontext
|
||||
winfib
|
||||
: propagated
|
||||
composite
|
||||
;
|
||||
feature.set-default context-impl : fcontext ;
|
||||
feature.compose <context-impl>ucontext : <define>BOOST_USE_UCONTEXT ;
|
||||
feature.compose <context-impl>winfib : <define>BOOST_USE_WINFIB ;
|
||||
|
||||
# ARM
|
||||
# ARM/AAPCS/ELF
|
||||
alias asm_sources
|
||||
: asm/make_arm_aapcs_elf_gas.S
|
||||
asm/jump_arm_aapcs_elf_gas.S
|
||||
asm/ontop_arm_aapcs_elf_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>32
|
||||
<architecture>arm
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_arm_aapcs_elf_gas.S
|
||||
asm/jump_arm_aapcs_elf_gas.S
|
||||
asm/ontop_arm_aapcs_elf_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>32
|
||||
<architecture>arm
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_arm_aapcs_elf_gas.S
|
||||
asm/jump_arm_aapcs_elf_gas.S
|
||||
asm/ontop_arm_aapcs_elf_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>32
|
||||
<architecture>arm
|
||||
<binary-format>elf
|
||||
<toolset>qcc
|
||||
;
|
||||
|
||||
# ARM/AAPCS/MACH-O
|
||||
alias asm_sources
|
||||
: asm/make_arm_aapcs_macho_gas.S
|
||||
asm/jump_arm_aapcs_macho_gas.S
|
||||
asm/ontop_arm_aapcs_macho_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>32
|
||||
<architecture>arm
|
||||
<binary-format>mach-o
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_arm_aapcs_macho_gas.S
|
||||
asm/jump_arm_aapcs_macho_gas.S
|
||||
asm/ontop_arm_aapcs_macho_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>32
|
||||
<architecture>arm
|
||||
<binary-format>mach-o
|
||||
<toolset>darwin
|
||||
;
|
||||
|
||||
# ARM/AAPCS/PE
|
||||
alias asm_sources
|
||||
: asm/make_arm_aapcs_pe_armasm.asm
|
||||
asm/jump_arm_aapcs_pe_armasm.asm
|
||||
asm/ontop_arm_aapcs_pe_armasm.asm
|
||||
untested.cpp
|
||||
: <abi>aapcs
|
||||
<address-model>32
|
||||
<architecture>arm
|
||||
<binary-format>pe
|
||||
<toolset>msvc
|
||||
;
|
||||
|
||||
# ARM64
|
||||
# ARM64/AAPCS/ELF
|
||||
alias asm_sources
|
||||
: asm/make_arm64_aapcs_elf_gas.S
|
||||
asm/jump_arm64_aapcs_elf_gas.S
|
||||
asm/ontop_arm64_aapcs_elf_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>64
|
||||
<architecture>arm
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_arm64_aapcs_elf_gas.S
|
||||
asm/jump_arm64_aapcs_elf_gas.S
|
||||
asm/ontop_arm64_aapcs_elf_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>64
|
||||
<architecture>arm
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
# ARM64/AAPCS/MACH-O
|
||||
alias asm_sources
|
||||
: asm/make_arm64_aapcs_macho_gas.S
|
||||
asm/jump_arm64_aapcs_macho_gas.S
|
||||
asm/ontop_arm64_aapcs_macho_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>64
|
||||
<architecture>arm
|
||||
<binary-format>mach-o
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_arm64_aapcs_macho_gas.S
|
||||
asm/jump_arm64_aapcs_macho_gas.S
|
||||
asm/ontop_arm64_aapcs_macho_gas.S
|
||||
: <abi>aapcs
|
||||
<address-model>64
|
||||
<architecture>arm
|
||||
<binary-format>mach-o
|
||||
<toolset>darwin
|
||||
;
|
||||
|
||||
# MIPS
|
||||
# MIPS32/O32/ELF
|
||||
alias asm_sources
|
||||
: asm/make_mips32_o32_elf_gas.S
|
||||
asm/jump_mips32_o32_elf_gas.S
|
||||
asm/ontop_mips32_o32_elf_gas.S
|
||||
: <abi>o32
|
||||
<address-model>32
|
||||
<architecture>mips1
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_mips32_o32_elf_gas.S
|
||||
asm/jump_mips32_o32_elf_gas.S
|
||||
asm/ontop_mips32_o32_elf_gas.S
|
||||
: <abi>o32
|
||||
<address-model>32
|
||||
<architecture>mips1
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
# MIPS64/N64/ELF
|
||||
alias asm_sources
|
||||
: asm/make_mips64_n64_elf_gas.S
|
||||
asm/jump_mips64_n64_elf_gas.S
|
||||
asm/ontop_mips64_n64_elf_gas.S
|
||||
: <abi>n64
|
||||
<address-model>64
|
||||
<architecture>mips1
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_mips64_n64_elf_gas.S
|
||||
asm/jump_mips64_n64_elf_gas.S
|
||||
asm/ontop_mips64_n64_elf_gas.S
|
||||
: <abi>n64
|
||||
<address-model>64
|
||||
<architecture>mips1
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
# POWERPC_32
|
||||
# POWERPC_32/SYSV/ELF
|
||||
alias asm_sources
|
||||
: asm/make_ppc32_sysv_elf_gas.S
|
||||
asm/jump_ppc32_sysv_elf_gas.S
|
||||
asm/ontop_ppc32_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>power
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_ppc32_sysv_elf_gas.S
|
||||
asm/jump_ppc32_sysv_elf_gas.S
|
||||
asm/ontop_ppc32_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>power
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_ppc32_sysv_macho_gas.S
|
||||
asm/jump_ppc32_sysv_macho_gas.S
|
||||
asm/ontop_ppc32_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>power
|
||||
<binary-format>mach-o
|
||||
<toolset>darwin
|
||||
;
|
||||
|
||||
#POWERPC_32/SYSV/XCOFF
|
||||
alias asm_sources
|
||||
: asm/make_ppc32_sysv_xcoff_gas.S
|
||||
asm/jump_ppc32_sysv_xcoff_gas.S
|
||||
asm/ontop_ppc32_sysv_xcoff_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>power
|
||||
<binary-format>xcoff
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_ppc32_sysv_xcoff_gas.S
|
||||
asm/jump_ppc32_sysv_xcoff_gas.S
|
||||
asm/ontop_ppc32_sysv_xcoff_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>power
|
||||
<binary-format>xcoff
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
# POWERPC_64
|
||||
# POWERPC_64/SYSV/ELF
|
||||
alias asm_sources
|
||||
: asm/make_ppc64_sysv_elf_gas.S
|
||||
asm/jump_ppc64_sysv_elf_gas.S
|
||||
asm/ontop_ppc64_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>power
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_ppc64_sysv_elf_gas.S
|
||||
asm/jump_ppc64_sysv_elf_gas.S
|
||||
asm/ontop_ppc64_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>power
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
# POWERPC_64/SYSV/MACH-O
|
||||
alias asm_sources
|
||||
: asm/make_ppc64_sysv_macho_gas.S
|
||||
asm/jump_ppc64_sysv_macho_gas.S
|
||||
asm/ontop_ppc64_sysv_macho_gas.S
|
||||
untested.cpp
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>power
|
||||
<binary-format>mach-o
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_ppc64_sysv_macho_gas.S
|
||||
asm/jump_ppc64_sysv_macho_gas.S
|
||||
asm/ontop_ppc64_sysv_macho_gas.S
|
||||
untested.cpp
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>power
|
||||
<binary-format>mach-o
|
||||
<toolset>darwin
|
||||
;
|
||||
|
||||
# POWERPC_64/SYSV/XCOFF
|
||||
alias asm_sources
|
||||
: asm/make_ppc64_sysv_xcoff_gas.S
|
||||
asm/jump_ppc64_sysv_xcoff_gas.S
|
||||
asm/ontop_ppc64_sysv_xcoff_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>power
|
||||
<binary-format>xcoff
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_ppc64_sysv_xcoff_gas.S
|
||||
asm/jump_ppc64_sysv_xcoff_gas.S
|
||||
asm/ontop_ppc64_sysv_xcoff_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>power
|
||||
<binary-format>xcoff
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
# POWERPC universal
|
||||
# POWERPC_32_64/SYSV/MACH-O
|
||||
alias asm_sources
|
||||
: asm/make_ppc32_ppc64_sysv_macho_gas.S
|
||||
asm/jump_ppc32_ppc64_sysv_macho_gas.S
|
||||
asm/ontop_ppc32_ppc64_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32_64
|
||||
<architecture>power
|
||||
<binary-format>mach-o
|
||||
;
|
||||
|
||||
# X86
|
||||
# X86/SYSV/ELF
|
||||
alias asm_sources
|
||||
: asm/make_i386_sysv_elf_gas.S
|
||||
asm/jump_i386_sysv_elf_gas.S
|
||||
asm/ontop_i386_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_i386_sysv_elf_gas.S
|
||||
asm/jump_i386_sysv_elf_gas.S
|
||||
asm/ontop_i386_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_i386_sysv_elf_gas.S
|
||||
asm/jump_i386_sysv_elf_gas.S
|
||||
asm/ontop_i386_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>elf
|
||||
<toolset>intel
|
||||
;
|
||||
|
||||
# X86/SYSV/MACH-O
|
||||
alias asm_sources
|
||||
: asm/make_i386_sysv_macho_gas.S
|
||||
asm/jump_i386_sysv_macho_gas.S
|
||||
asm/ontop_i386_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>mach-o
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_i386_sysv_macho_gas.S
|
||||
asm/jump_i386_sysv_macho_gas.S
|
||||
asm/ontop_i386_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>mach-o
|
||||
<toolset>darwin
|
||||
;
|
||||
|
||||
# X86/MS/PE
|
||||
alias asm_sources
|
||||
: asm/make_i386_ms_pe_gas.asm
|
||||
asm/jump_i386_ms_pe_gas.asm
|
||||
asm/ontop_i386_ms_pe_gas.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_i386_ms_pe_masm.asm
|
||||
asm/jump_i386_ms_pe_masm.asm
|
||||
asm/ontop_i386_ms_pe_masm.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>clang-win
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_i386_ms_pe_gas.asm
|
||||
asm/jump_i386_ms_pe_gas.asm
|
||||
asm/ontop_i386_ms_pe_gas.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_i386_ms_pe_masm.asm
|
||||
asm/jump_i386_ms_pe_masm.asm
|
||||
asm/ontop_i386_ms_pe_masm.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>intel
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_i386_ms_pe_masm.asm
|
||||
asm/jump_i386_ms_pe_masm.asm
|
||||
asm/ontop_i386_ms_pe_masm.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>32
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>msvc
|
||||
;
|
||||
|
||||
# X86_64
|
||||
# X86_64/SYSV/ELF
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_elf_gas.S
|
||||
asm/jump_x86_64_sysv_elf_gas.S
|
||||
asm/ontop_x86_64_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_elf_gas.S
|
||||
asm/jump_x86_64_sysv_elf_gas.S
|
||||
@@ -555,167 +96,6 @@ alias asm_sources
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_elf_gas.S
|
||||
asm/jump_x86_64_sysv_elf_gas.S
|
||||
asm/ontop_x86_64_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>elf
|
||||
<toolset>intel
|
||||
;
|
||||
|
||||
# X86_64/SYSV/MACH-O
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_macho_gas.S
|
||||
asm/jump_x86_64_sysv_macho_gas.S
|
||||
asm/ontop_x86_64_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>mach-o
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_macho_gas.S
|
||||
asm/jump_x86_64_sysv_macho_gas.S
|
||||
asm/ontop_x86_64_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>mach-o
|
||||
<toolset>darwin
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_macho_gas.S
|
||||
asm/jump_x86_64_sysv_macho_gas.S
|
||||
asm/ontop_x86_64_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>mach-o
|
||||
<toolset>intel
|
||||
;
|
||||
|
||||
# X86_64/MS/PE
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_ms_pe_gas.asm
|
||||
asm/jump_x86_64_ms_pe_gas.asm
|
||||
asm/ontop_x86_64_ms_pe_gas.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_ms_pe_masm.asm
|
||||
asm/jump_x86_64_ms_pe_masm.asm
|
||||
asm/ontop_x86_64_ms_pe_masm.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>clang-win
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_ms_pe_gas.asm
|
||||
asm/jump_x86_64_ms_pe_gas.asm
|
||||
asm/ontop_x86_64_ms_pe_gas.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_ms_pe_masm.asm
|
||||
asm/jump_x86_64_ms_pe_masm.asm
|
||||
asm/ontop_x86_64_ms_pe_masm.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>intel
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_ms_pe_masm.asm
|
||||
asm/jump_x86_64_ms_pe_masm.asm
|
||||
asm/ontop_x86_64_ms_pe_masm.asm
|
||||
dummy.cpp
|
||||
: <abi>ms
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>msvc
|
||||
;
|
||||
|
||||
# X86_64/SYSV/X32
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_elf_gas.S
|
||||
asm/jump_x86_64_sysv_elf_gas.S
|
||||
asm/ontop_x86_64_sysv_elf_gas.S
|
||||
: <abi>x32
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>elf
|
||||
<toolset>clang
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_elf_gas.S
|
||||
asm/jump_x86_64_sysv_elf_gas.S
|
||||
asm/ontop_x86_64_sysv_elf_gas.S
|
||||
: <abi>x32
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_elf_gas.S
|
||||
asm/jump_x86_64_sysv_elf_gas.S
|
||||
asm/ontop_x86_64_sysv_elf_gas.S
|
||||
: <abi>x32
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>elf
|
||||
<toolset>intel
|
||||
;
|
||||
|
||||
#X86 universal
|
||||
alias asm_sources
|
||||
: asm/make_i386_x86_64_sysv_macho_gas.S
|
||||
asm/jump_i386_x86_64_sysv_macho_gas.S
|
||||
asm/ontop_i386_x86_64_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>32_64
|
||||
<architecture>x86
|
||||
<binary-format>mach-o
|
||||
;
|
||||
|
||||
# COMBINED
|
||||
alias asm_sources
|
||||
: asm/make_combined_sysv_macho_gas.S
|
||||
asm/jump_combined_sysv_macho_gas.S
|
||||
asm/ontop_combined_sysv_macho_gas.S
|
||||
: <abi>sysv
|
||||
<architecture>combined
|
||||
<binary-format>mach-o
|
||||
;
|
||||
|
||||
explicit asm_sources ;
|
||||
|
||||
|
||||
@@ -725,46 +105,6 @@ alias impl_sources
|
||||
: <context-impl>fcontext
|
||||
;
|
||||
|
||||
# ucontext_t
|
||||
alias impl_sources
|
||||
: continuation.cpp
|
||||
fiber.cpp
|
||||
: <context-impl>ucontext
|
||||
[ requires cxx11_auto_declarations
|
||||
cxx11_constexpr
|
||||
cxx11_defaulted_functions
|
||||
cxx11_final
|
||||
cxx11_hdr_thread
|
||||
cxx11_hdr_tuple
|
||||
cxx11_lambdas
|
||||
cxx11_noexcept
|
||||
cxx11_nullptr
|
||||
cxx11_rvalue_references
|
||||
cxx11_template_aliases
|
||||
cxx11_thread_local
|
||||
cxx11_variadic_templates ]
|
||||
;
|
||||
|
||||
# WinFiber
|
||||
alias impl_sources
|
||||
: continuation.cpp
|
||||
fiber.cpp
|
||||
: <context-impl>winfib
|
||||
[ requires cxx11_auto_declarations
|
||||
cxx11_constexpr
|
||||
cxx11_defaulted_functions
|
||||
cxx11_final
|
||||
cxx11_hdr_thread
|
||||
cxx11_hdr_tuple
|
||||
cxx11_lambdas
|
||||
cxx11_noexcept
|
||||
cxx11_nullptr
|
||||
cxx11_rvalue_references
|
||||
cxx11_template_aliases
|
||||
cxx11_thread_local
|
||||
cxx11_variadic_templates ]
|
||||
;
|
||||
|
||||
explicit impl_sources ;
|
||||
|
||||
obj cxx11_hdr_mutex_check : ../build/cxx11_hdr_mutex.cpp ;
|
||||
@@ -775,13 +115,6 @@ local cxx11_mutex = [ check-target-builds
|
||||
: <library>/boost/thread//boost_thread
|
||||
] ;
|
||||
|
||||
alias stack_traits_sources
|
||||
: windows/stack_traits.cpp
|
||||
: <target-os>windows
|
||||
:
|
||||
: $(cxx11_mutex)
|
||||
;
|
||||
|
||||
alias stack_traits_sources
|
||||
: posix/stack_traits.cpp
|
||||
:
|
||||
|
||||
@@ -15,7 +15,7 @@ import os ;
|
||||
import toolset ;
|
||||
import architecture ;
|
||||
|
||||
project boost/context/example/fiber
|
||||
project boost/context/example
|
||||
: requirements
|
||||
<library>/boost/context//boost_context
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
@@ -74,6 +74,14 @@ exe circle
|
||||
: circle.cpp
|
||||
;
|
||||
|
||||
exe unwind_ucontext
|
||||
: unwind_ucontext.cpp
|
||||
;
|
||||
|
||||
exe unwind_fiber_context
|
||||
: unwind_fiber_context.cpp
|
||||
;
|
||||
|
||||
#exe backtrace
|
||||
# : backtrace.cpp
|
||||
# ;
|
||||
91
example/backtrace.cpp
Normal file
91
example/backtrace.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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 UNW_LOCAL_ONLY
|
||||
|
||||
#include <unwind.h>
|
||||
#include <cxxabi.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
#define _U_VERSION 1
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
struct X {
|
||||
int i;
|
||||
X(int i_) : i{ i_ } { std::cout << "X(" << i << ")" << std::endl; }
|
||||
~X() { std::cout << "~X(" << i << ")" << std::endl; }
|
||||
};
|
||||
|
||||
void print_data( unw_cursor_t * cursor) {
|
||||
unw_proc_info_t pi;
|
||||
if ( 0 > unw_get_proc_info( cursor, & pi) ) {
|
||||
std::fprintf( stderr, "unw_get_proc_info failed\n");
|
||||
return;
|
||||
}
|
||||
char sym[256];
|
||||
unw_word_t offset;
|
||||
if ( 0 > unw_get_proc_name( cursor, sym, sizeof( sym), & offset) ) {
|
||||
std::fprintf( stderr, "unw_get_proc_name failed\n");
|
||||
return;
|
||||
}
|
||||
char * nameptr = sym;
|
||||
int status;
|
||||
char * demangled = abi::__cxa_demangle( sym, nullptr, nullptr, & status);
|
||||
if ( 0 == status) {
|
||||
nameptr = demangled;
|
||||
}
|
||||
std::printf("(%s\n", nameptr);
|
||||
std::free( demangled);
|
||||
std::printf("lsda=0x%lx, personality=0x%lx\n", pi.lsda, pi.handler);
|
||||
}
|
||||
|
||||
void backtrace( ctx::fiber_context && c) {
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
unw_getcontext( & context);
|
||||
unw_init_local( & cursor, & context);
|
||||
// print_data( & cursor);
|
||||
while ( 0 < unw_step( & cursor) ) {
|
||||
print_data( & cursor);
|
||||
std::printf("\n");
|
||||
}
|
||||
std::printf("unwinding done\n");
|
||||
std::move( c).resume();
|
||||
}
|
||||
|
||||
void /* __attribute__((optimize("O0"))) */ bar( ctx::fiber_context && c) {
|
||||
X x{ 3 };
|
||||
backtrace( std::move( c) );
|
||||
std::cout << "returned from unwind()" << std::endl;
|
||||
}
|
||||
|
||||
void /* __attribute__((optimize("O0"))) */ foo( ctx::fiber_context && c) {
|
||||
X x{ 2 };
|
||||
bar( std::move( c) );
|
||||
std::cout << "returned from bar()" << std::endl;
|
||||
}
|
||||
|
||||
ctx::fiber_context /* __attribute__((optimize("O0"))) */ f( ctx::fiber_context && c) {
|
||||
X x{ 1 };
|
||||
foo( std::move( c) );
|
||||
std::cout << "returned from foo()" << std::endl;
|
||||
return std::move( c);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::fiber_context{ f }.resume();
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
# Boost.Context Library Examples Jamfile
|
||||
|
||||
# Copyright Oliver Kowalke 2014.
|
||||
# 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 ;
|
||||
import architecture ;
|
||||
|
||||
project boost/context/example/callcc
|
||||
: requirements
|
||||
<library>/boost/context//boost_context
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<link>static
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
exe stack
|
||||
: stack.cpp
|
||||
;
|
||||
|
||||
exe jump_void
|
||||
: jump_void.cpp
|
||||
;
|
||||
|
||||
exe jump
|
||||
: jump.cpp
|
||||
;
|
||||
|
||||
exe jump_mov
|
||||
: jump_mov.cpp
|
||||
;
|
||||
|
||||
exe ontop_void
|
||||
: ontop_void.cpp
|
||||
;
|
||||
|
||||
exe throw
|
||||
: throw.cpp
|
||||
;
|
||||
|
||||
exe fibonacci
|
||||
: fibonacci.cpp
|
||||
;
|
||||
|
||||
exe parser
|
||||
: parser.cpp
|
||||
;
|
||||
|
||||
exe ontop
|
||||
: ontop.cpp
|
||||
;
|
||||
|
||||
exe endless_loop
|
||||
: endless_loop.cpp
|
||||
;
|
||||
|
||||
exe segmented
|
||||
: segmented.cpp
|
||||
;
|
||||
|
||||
#exe backtrace
|
||||
# : backtrace.cpp
|
||||
# ;
|
||||
|
||||
#exe echosse
|
||||
# : echosse.cpp
|
||||
# ;
|
||||
@@ -1,57 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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 UNW_LOCAL_ONLY
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
void backtrace() {
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
unw_getcontext( & context);
|
||||
unw_init_local( & cursor, & context);
|
||||
while ( 0 < unw_step( & cursor) ) {
|
||||
unw_word_t offset, pc;
|
||||
unw_get_reg( & cursor, UNW_REG_IP, & pc);
|
||||
if ( 0 == pc) {
|
||||
break;
|
||||
}
|
||||
std::cout << "0x" << pc << ":";
|
||||
|
||||
char sym[256];
|
||||
if ( 0 == unw_get_proc_name( & cursor, sym, sizeof( sym), & offset) ) {
|
||||
std::cout << " (" << sym << "+0x" << offset << ")" << std::endl;
|
||||
} else {
|
||||
std::cout << " -- error: unable to obtain symbol name for this frame" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bar() {
|
||||
backtrace();
|
||||
}
|
||||
|
||||
void foo() {
|
||||
bar();
|
||||
}
|
||||
|
||||
ctx::continuation f1( ctx::continuation && c) {
|
||||
foo();
|
||||
return std::move( c);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::callcc( f1);
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
ctx::fiber f1, f2, f3;
|
||||
f3 = ctx::fiber{[&](ctx::fiber && f)->ctx::fiber{
|
||||
f2 = std::move( f);
|
||||
for (;;) {
|
||||
std::cout << "f3\n";
|
||||
f2 = f1.resume();
|
||||
}
|
||||
return {};
|
||||
}};
|
||||
f2 = ctx::fiber{[&](ctx::fiber && f)->ctx::fiber{
|
||||
f1 = std::move( f);
|
||||
for (;;) {
|
||||
std::cout << "f2\n";
|
||||
f1 = f3.resume();
|
||||
}
|
||||
return {};
|
||||
}};
|
||||
f1 = ctx::fiber{[&](ctx::fiber && /*main*/)->ctx::fiber{
|
||||
for (;;) {
|
||||
std::cout << "f1\n";
|
||||
f3 = f2.resume();
|
||||
}
|
||||
return {};
|
||||
}};
|
||||
f1.resume();
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <emmintrin.h>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
void echoSSE( int i) {
|
||||
__m128i xmm;
|
||||
xmm = _mm_set_epi32( i, i + 1, i + 2, i + 3);
|
||||
uint32_t v32[4];
|
||||
memcpy( & v32, & xmm, 16);
|
||||
std::cout << v32[0];
|
||||
std::cout << v32[1];
|
||||
std::cout << v32[2];
|
||||
std::cout << v32[3];
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char * argv[]) {
|
||||
int i = 0;
|
||||
ctx::continuation c = ctx::callcc(
|
||||
[&i](ctx::continuation && c) {
|
||||
for (;;) {
|
||||
std::cout << i;
|
||||
echoSSE( i);
|
||||
std::cout << " ";
|
||||
c = c.resume();
|
||||
}
|
||||
return std::move( c);
|
||||
});
|
||||
for (; i < 10; ++i) {
|
||||
c = c.resume();
|
||||
}
|
||||
std::cout << "\nmain: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::continuation foo( ctx::continuation && c) {
|
||||
do {
|
||||
std::cout << "foo\n";
|
||||
} while ( ( c = c.resume() ) );
|
||||
return std::move( c);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::continuation c = ctx::callcc( foo);
|
||||
do {
|
||||
std::cout << "bar\n";
|
||||
} while ( ( c = c.resume() ) );
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
int a;
|
||||
ctx::continuation c=ctx::callcc(
|
||||
[&a](ctx::continuation && c){
|
||||
a=0;
|
||||
int b=1;
|
||||
for(;;){
|
||||
c=c.resume();
|
||||
int next=a+b;
|
||||
a=b;
|
||||
b=next;
|
||||
}
|
||||
return std::move( c);
|
||||
});
|
||||
for ( int j = 0; j < 10; ++j) {
|
||||
std::cout << a << " ";
|
||||
c=c.resume();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
ctx::continuation c;
|
||||
int data = 1;
|
||||
c = ctx::callcc(
|
||||
[&data](ctx::continuation && c){
|
||||
std::cout << "entered first time: " << data << std::endl;
|
||||
data += 2;
|
||||
c = c.resume();
|
||||
std::cout << "entered second time: " << data << std::endl;
|
||||
return std::move( c);
|
||||
});
|
||||
std::cout << "returned first time: " << data << std::endl;
|
||||
data += 2;
|
||||
c = c.resume();
|
||||
if ( c) {
|
||||
std::cout << "returned second time: " << data << std::endl;
|
||||
} else {
|
||||
std::cout << "returned second time: execution context terminated" << std::endl;
|
||||
}
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
class moveable {
|
||||
public:
|
||||
int value;
|
||||
|
||||
moveable() :
|
||||
value( -1) {
|
||||
}
|
||||
|
||||
moveable( int v) :
|
||||
value( v) {
|
||||
}
|
||||
|
||||
moveable( moveable && other) {
|
||||
std::swap( value, other.value);
|
||||
}
|
||||
|
||||
moveable & operator=( moveable && other) {
|
||||
if ( this == & other) return * this;
|
||||
value = other.value;
|
||||
other.value = -1;
|
||||
return * this;
|
||||
}
|
||||
|
||||
moveable( moveable const& other) = delete;
|
||||
moveable & operator=( moveable const& other) = delete;
|
||||
};
|
||||
|
||||
int main() {
|
||||
ctx::continuation c;
|
||||
moveable data{ 1 };
|
||||
c = ctx::callcc( std::allocator_arg, ctx::fixedsize_stack{},
|
||||
[&data](ctx::continuation && c){
|
||||
std::cout << "entered first time: " << data.value << std::endl;
|
||||
data = std::move( moveable{ 3 });
|
||||
c = c.resume();
|
||||
std::cout << "entered second time: " << data.value << std::endl;
|
||||
data = std::move( moveable{});
|
||||
return std::move( c);
|
||||
});
|
||||
std::cout << "returned first time: " << data.value << std::endl;
|
||||
data.value = 5;
|
||||
c = c.resume();
|
||||
std::cout << "returned second time: " << data.value << std::endl;
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::continuation f1( ctx::continuation && c) {
|
||||
std::cout << "f1: entered first time" << std::endl;
|
||||
c = c.resume();
|
||||
std::cout << "f1: entered second time" << std::endl;
|
||||
return std::move( c);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::continuation c = ctx::callcc( f1);
|
||||
std::cout << "f1: returned first time" << std::endl;
|
||||
c = c.resume();
|
||||
std::cout << "f1: returned second time" << std::endl;
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
int data = 0;
|
||||
ctx::continuation c = ctx::callcc( [&data](ctx::continuation && c) {
|
||||
std::cout << "f1: entered first time: " << data << std::endl;
|
||||
data += 1;
|
||||
c = c.resume();
|
||||
std::cout << "f1: entered second time: " << data << std::endl;
|
||||
data += 1;
|
||||
c = c.resume();
|
||||
std::cout << "f1: entered third time: " << data << std::endl;
|
||||
return std::move( c);
|
||||
});
|
||||
std::cout << "f1: returned first time: " << data << std::endl;
|
||||
data += 1;
|
||||
c = c.resume();
|
||||
std::cout << "f1: returned second time: " << data << std::endl;
|
||||
data += 1;
|
||||
c = c.resume_with( [&data](ctx::continuation && c){
|
||||
std::cout << "f2: entered: " << data << std::endl;
|
||||
data = -1;
|
||||
return std::move( c);
|
||||
});
|
||||
std::cout << "f1: returned third time" << std::endl;
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::continuation f1( ctx::continuation && c) {
|
||||
std::cout << "f1: entered first time" << std::endl;
|
||||
c = c.resume();
|
||||
std::cout << "f1: entered second time" << std::endl;
|
||||
c = c.resume();
|
||||
std::cout << "f1: entered third time" << std::endl;
|
||||
return std::move( c);
|
||||
}
|
||||
|
||||
ctx::continuation f2( ctx::continuation && c) {
|
||||
std::cout << "f2: entered" << std::endl;
|
||||
return std::move( c);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::continuation c = ctx::callcc( f1);
|
||||
std::cout << "f1: returned first time" << std::endl;
|
||||
c = c.resume();
|
||||
std::cout << "f1: returned second time" << std::endl;
|
||||
c = c.resume_with( f2);
|
||||
std::cout << "f1: returned third time" << std::endl;
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
/*
|
||||
* grammar:
|
||||
* P ---> E '\0'
|
||||
* E ---> T {('+'|'-') T}
|
||||
* T ---> S {('*'|'/') S}
|
||||
* S ---> digit | '(' E ')'
|
||||
*/
|
||||
class Parser{
|
||||
char next;
|
||||
std::istream& is;
|
||||
std::function<void(char)> cb;
|
||||
|
||||
char pull(){
|
||||
return std::char_traits<char>::to_char_type(is.get());
|
||||
}
|
||||
|
||||
void scan(){
|
||||
do{
|
||||
next=pull();
|
||||
}
|
||||
while(isspace(next));
|
||||
}
|
||||
|
||||
public:
|
||||
Parser(std::istream& is_,std::function<void(char)> cb_) :
|
||||
next(), is(is_), cb(cb_)
|
||||
{}
|
||||
|
||||
void run() {
|
||||
scan();
|
||||
E();
|
||||
}
|
||||
|
||||
private:
|
||||
void E(){
|
||||
T();
|
||||
while (next=='+'||next=='-'){
|
||||
cb(next);
|
||||
scan();
|
||||
T();
|
||||
}
|
||||
}
|
||||
|
||||
void T(){
|
||||
S();
|
||||
while (next=='*'||next=='/'){
|
||||
cb(next);
|
||||
scan();
|
||||
S();
|
||||
}
|
||||
}
|
||||
|
||||
void S(){
|
||||
if (isdigit(next)){
|
||||
cb(next);
|
||||
scan();
|
||||
}
|
||||
else if(next=='('){
|
||||
cb(next);
|
||||
scan();
|
||||
E();
|
||||
if (next==')'){
|
||||
cb(next);
|
||||
scan();
|
||||
}else{
|
||||
throw std::runtime_error("parsing failed");
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw std::runtime_error("parsing failed");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
try {
|
||||
std::istringstream is("1+1");
|
||||
// execute parser in new execution context
|
||||
ctx::continuation source;
|
||||
// user-code pulls parsed data from parser
|
||||
// invert control flow
|
||||
char c;
|
||||
bool done = false;
|
||||
source=ctx::callcc(
|
||||
[&is,&c,&done](ctx::continuation && sink){
|
||||
// create parser with callback function
|
||||
Parser p( is,
|
||||
[&sink,&c](char c_){
|
||||
// resume main execution context
|
||||
c = c_;
|
||||
sink=sink.resume();
|
||||
});
|
||||
// start recursive parsing
|
||||
p.run();
|
||||
// signal termination
|
||||
done = true;
|
||||
// resume main execution context
|
||||
return std::move(sink);
|
||||
});
|
||||
while(!done){
|
||||
printf("Parsed: %c\n",c);
|
||||
source=source.resume();
|
||||
}
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
} catch (std::exception const& e) {
|
||||
std::cerr << "exception: " << e.what() << std::endl;
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
#ifdef BOOST_MSVC //MS VisualStudio
|
||||
__declspec(noinline) void access( char *buf);
|
||||
#else // GCC
|
||||
void access( char *buf) __attribute__ ((noinline));
|
||||
#endif
|
||||
void access( char *buf) {
|
||||
buf[0] = '\0';
|
||||
}
|
||||
|
||||
void bar( int i) {
|
||||
char buf[4 * 1024];
|
||||
if ( i > 0) {
|
||||
access( buf);
|
||||
std::cout << i << ". iteration" << std::endl;
|
||||
bar( i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int count = 100*1024;
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
std::cout << "using segmented_stack stacks: allocates " << count << " * 4kB == " << 4 * count << "kB on stack, ";
|
||||
std::cout << "initial stack size = " << ctx::segmented_stack::traits_type::default_size() / 1024 << "kB" << std::endl;
|
||||
std::cout << "application should not fail" << std::endl;
|
||||
#else
|
||||
std::cout << "using standard stacks: allocates " << count << " * 4kB == " << 4 * count << "kB on stack, ";
|
||||
std::cout << "initial stack size = " << ctx::fixedsize_stack::traits_type::default_size() / 1024 << "kB" << std::endl;
|
||||
std::cout << "application might fail" << std::endl;
|
||||
#endif
|
||||
ctx::continuation c = ctx::callcc(
|
||||
[count](ctx::continuation && c){
|
||||
bar( count);
|
||||
return std::move( c);
|
||||
});
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
struct my_exception : public std::runtime_error {
|
||||
ctx::continuation c;
|
||||
my_exception( ctx::continuation && c_, std::string const& what) :
|
||||
std::runtime_error{ what },
|
||||
c{ std::move( c_) } {
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
ctx::continuation c = ctx::callcc([](ctx::continuation && c) {
|
||||
for (;;) {
|
||||
try {
|
||||
std::cout << "entered" << std::endl;
|
||||
c = c.resume();
|
||||
} catch ( my_exception & ex) {
|
||||
std::cerr << "my_exception: " << ex.what() << std::endl;
|
||||
return std::move( ex.c);
|
||||
}
|
||||
}
|
||||
return std::move( c);
|
||||
});
|
||||
c = c.resume_with(
|
||||
[](ctx::continuation && c){
|
||||
throw my_exception(std::move( c), "abc");
|
||||
return std::move( c);
|
||||
});
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
ctx::fiber f1, f2, f3;
|
||||
f3 = ctx::fiber{[&](ctx::fiber && f)->ctx::fiber{
|
||||
ctx::fiber_context f1, f2, f3;
|
||||
f3 = ctx::fiber_context{[&](ctx::fiber_context && f)->ctx::fiber_context{
|
||||
f2 = std::move( f);
|
||||
for (;;) {
|
||||
std::cout << "f3\n";
|
||||
@@ -22,7 +22,7 @@ int main() {
|
||||
}
|
||||
return {};
|
||||
}};
|
||||
f2 = ctx::fiber{[&](ctx::fiber && f)->ctx::fiber{
|
||||
f2 = ctx::fiber_context{[&](ctx::fiber_context && f)->ctx::fiber_context{
|
||||
f1 = std::move( f);
|
||||
for (;;) {
|
||||
std::cout << "f2\n";
|
||||
@@ -30,7 +30,7 @@ int main() {
|
||||
}
|
||||
return {};
|
||||
}};
|
||||
f1 = ctx::fiber{[&](ctx::fiber && /*main*/)->ctx::fiber{
|
||||
f1 = ctx::fiber_context{[&](ctx::fiber_context && /*main*/)->ctx::fiber_context{
|
||||
for (;;) {
|
||||
std::cout << "f1\n";
|
||||
f3 = std::move( f2).resume();
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <iostream>
|
||||
#include <emmintrin.h>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
@@ -28,8 +28,8 @@ void echoSSE( int i) {
|
||||
|
||||
int main( int argc, char * argv[]) {
|
||||
int i = 0;
|
||||
ctx::fiber f{
|
||||
[&i](ctx::fiber && f) {
|
||||
ctx::fiber_context f{
|
||||
[&i](ctx::fiber_context && f) {
|
||||
for (;;) {
|
||||
std::cout << i;
|
||||
echoSSE( i);
|
||||
@@ -7,11 +7,11 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::fiber bar( ctx::fiber && f) {
|
||||
ctx::fiber_context bar( ctx::fiber_context && f) {
|
||||
do {
|
||||
std::cout << "bar\n";
|
||||
f = std::move( f).resume();
|
||||
@@ -20,7 +20,7 @@ ctx::fiber bar( ctx::fiber && f) {
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::fiber f{ bar };
|
||||
ctx::fiber_context f{ bar };
|
||||
do {
|
||||
std::cout << "foo\n";
|
||||
f = std::move( f).resume();
|
||||
@@ -1,68 +0,0 @@
|
||||
# Boost.Context Library Examples Jamfile
|
||||
|
||||
# Copyright Oliver Kowalke 2014.
|
||||
# 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 ;
|
||||
import architecture ;
|
||||
|
||||
project boost/context/example/execution_context_v2
|
||||
: requirements
|
||||
<library>/boost/context//boost_context
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<link>static
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
exe jump_void
|
||||
: jump_void.cpp
|
||||
;
|
||||
|
||||
exe jump
|
||||
: jump.cpp
|
||||
;
|
||||
|
||||
exe fibonacci
|
||||
: fibonacci.cpp
|
||||
;
|
||||
|
||||
exe parser
|
||||
: parser.cpp
|
||||
;
|
||||
|
||||
exe parameter
|
||||
: parameter.cpp
|
||||
;
|
||||
|
||||
exe ontop_void
|
||||
: ontop_void.cpp
|
||||
;
|
||||
|
||||
exe ontop
|
||||
: ontop.cpp
|
||||
;
|
||||
|
||||
exe throw
|
||||
: throw.cpp
|
||||
;
|
||||
|
||||
exe echosse
|
||||
: echosse.cpp
|
||||
;
|
||||
|
||||
#exe backtrace
|
||||
# : backtrace.cpp
|
||||
# : <linkflags>"-lunwind"
|
||||
# ;
|
||||
@@ -1,58 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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 UNW_LOCAL_ONLY
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
void backtrace() {
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
unw_getcontext( & context);
|
||||
unw_init_local( & cursor, & context);
|
||||
while ( 0 < unw_step( & cursor) ) {
|
||||
unw_word_t offset, pc;
|
||||
unw_get_reg( & cursor, UNW_REG_IP, & pc);
|
||||
if ( 0 == pc) {
|
||||
break;
|
||||
}
|
||||
std::cout << "0x" << pc << ":";
|
||||
|
||||
char sym[256];
|
||||
if ( 0 == unw_get_proc_name( & cursor, sym, sizeof( sym), & offset) ) {
|
||||
std::cout << " (" << sym << "+0x" << offset << ")" << std::endl;
|
||||
} else {
|
||||
std::cout << " -- error: unable to obtain symbol name for this frame" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bar() {
|
||||
backtrace();
|
||||
}
|
||||
|
||||
void foo() {
|
||||
bar();
|
||||
}
|
||||
|
||||
ctx::execution_context< void > f1( ctx::execution_context< void > && ctxm) {
|
||||
foo();
|
||||
return std::move( ctxm);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::execution_context< void > ctx1( f1);
|
||||
ctx1 = ctx1();
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <emmintrin.h>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
void echoSSE( int i) {
|
||||
__m128i xmm;
|
||||
xmm = _mm_set_epi32( i, i + 1, i + 2, i + 3);
|
||||
uint32_t v32[4];
|
||||
memcpy( & v32, & xmm, 16);
|
||||
std::cout << v32[0];
|
||||
std::cout << v32[1];
|
||||
std::cout << v32[2];
|
||||
std::cout << v32[3];
|
||||
}
|
||||
|
||||
ctx::execution_context< int > echo( ctx::execution_context< int > && ctx, int i) {
|
||||
for (;;) {
|
||||
std::cout << i;
|
||||
echoSSE( i);
|
||||
std::cout << " ";
|
||||
std::tie( ctx, i) = ctx( 0);
|
||||
}
|
||||
return std::move( ctx);
|
||||
}
|
||||
|
||||
int main( int argc, char * argv[]) {
|
||||
ctx::execution_context< int > ctx( echo);
|
||||
for ( int i = 0; i < 10; ++i) {
|
||||
ctx = std::get< 0 >( ctx( i) );
|
||||
}
|
||||
std::cout << "\nDone" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
int n=35;
|
||||
ctx::execution_context< int > source(
|
||||
[n](ctx::execution_context< int > && sink, int) mutable {
|
||||
int a=0;
|
||||
int b=1;
|
||||
while(n-->0){
|
||||
auto result=sink(a);
|
||||
sink=std::move(std::get<0>(result));
|
||||
auto next=a+b;
|
||||
a=b;
|
||||
b=next;
|
||||
}
|
||||
return std::move( sink);
|
||||
});
|
||||
for(int i=0;i<10;++i){
|
||||
auto result=source(i);
|
||||
source=std::move(std::get<0>(result));
|
||||
std::cout<<std::get<1>(result)<<" ";
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::execution_context< int > f1( ctx::execution_context< int > && ctxm, int data) {
|
||||
std::cout << "f1: entered first time: " << data << std::endl;
|
||||
std::tie( ctxm, data) = ctxm( data + 2);
|
||||
std::cout << "f1: entered second time: " << data << std::endl;
|
||||
return std::move( ctxm);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int data = 1;
|
||||
ctx::execution_context< int > ctx1( f1);
|
||||
std::tie( ctx1, data) = ctx1( data + 2);
|
||||
std::cout << "f1: returned first time: " << data << std::endl;
|
||||
std::tie( ctx1, data) = ctx1( data + 2);
|
||||
std::cout << "f1: returned second time: " << data << std::endl;
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::execution_context< void > f1( ctx::execution_context< void > && ctxm) {
|
||||
std::cout << "f1: entered first time" << std::endl;
|
||||
ctxm = ctxm();
|
||||
std::cout << "f1: entered second time" << std::endl;
|
||||
return std::move( ctxm);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::execution_context< void > ctx1( f1);
|
||||
ctx1 = ctx1();
|
||||
std::cout << "f1: returned first time" << std::endl;
|
||||
ctx1 = ctx1();
|
||||
std::cout << "f1: returned second time" << std::endl;
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::execution_context< int > f1( ctx::execution_context< int > && ctx, int data) {
|
||||
std::cout << "f1: entered first time: " << data << std::endl;
|
||||
std::tie( ctx, data) = ctx( data + 1);
|
||||
std::cout << "f1: entered second time: " << data << std::endl;
|
||||
std::tie( ctx, data) = ctx( data + 1);
|
||||
std::cout << "f1: entered third time: " << data << std::endl;
|
||||
return std::move( ctx);
|
||||
}
|
||||
|
||||
int f2( int data) {
|
||||
std::cout << "f2: entered: " << data << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int data = 0;
|
||||
ctx::execution_context< int > ctx( f1);
|
||||
std::tie( ctx, data) = ctx( data + 1);
|
||||
std::cout << "f1: returned first time: " << data << std::endl;
|
||||
std::tie( ctx, data) = ctx( data + 1);
|
||||
std::cout << "f1: returned second time: " << data << std::endl;
|
||||
std::tie( ctx, data) = ctx( ctx::exec_ontop_arg, f2, data + 1);
|
||||
std::cout << "f1: returned third time" << std::endl;
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::execution_context< void > f1( ctx::execution_context< void > && ctx) {
|
||||
std::cout << "f1: entered first time" << std::endl;
|
||||
ctx = ctx();
|
||||
std::cout << "f1: entered second time" << std::endl;
|
||||
ctx = ctx();
|
||||
std::cout << "f1: entered third time" << std::endl;
|
||||
return std::move( ctx);
|
||||
}
|
||||
|
||||
void f2() {
|
||||
std::cout << "f2: entered" << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::execution_context< void > ctx( f1);
|
||||
ctx = ctx();
|
||||
std::cout << "f1: returned first time" << std::endl;
|
||||
ctx = ctx();
|
||||
std::cout << "f1: returned second time" << std::endl;
|
||||
ctx = ctx( ctx::exec_ontop_arg, f2);
|
||||
std::cout << "f1: returned third time" << std::endl;
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/context/execution_context.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
typedef boost::variant<int,std::string> variant_t;
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
class X{
|
||||
private:
|
||||
std::exception_ptr excptr_;
|
||||
ctx::execution_context<variant_t> ctx_;
|
||||
|
||||
public:
|
||||
X():
|
||||
excptr_(),
|
||||
ctx_(
|
||||
[this](ctx::execution_context<variant_t> && ctx, variant_t data){
|
||||
try {
|
||||
for (;;) {
|
||||
int i = boost::get<int>(data);
|
||||
data = boost::lexical_cast<std::string>(i);
|
||||
auto result = ctx( data);
|
||||
ctx = std::move( std::get<0>( result) );
|
||||
data = std::get<1>( result);
|
||||
}
|
||||
} catch ( std::bad_cast const&) {
|
||||
excptr_=std::current_exception();
|
||||
}
|
||||
return std::move( ctx);
|
||||
})
|
||||
{}
|
||||
|
||||
std::string operator()(int i){
|
||||
variant_t data = i;
|
||||
auto result = ctx_( data);
|
||||
ctx_ = std::move( std::get<0>( result) );
|
||||
data = std::get<1>( result);
|
||||
if(excptr_){
|
||||
std::rethrow_exception(excptr_);
|
||||
}
|
||||
return boost::get<std::string>(data);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
X x;
|
||||
std::cout<<x(7)<<std::endl;
|
||||
std::cout << "done" << std::endl;
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
/*
|
||||
* grammar:
|
||||
* P ---> E '\0'
|
||||
* E ---> T {('+'|'-') T}
|
||||
* T ---> S {('*'|'/') S}
|
||||
* S ---> digit | '(' E ')'
|
||||
*/
|
||||
class Parser{
|
||||
char next;
|
||||
std::istream& is;
|
||||
std::function<void(char)> cb;
|
||||
|
||||
char pull(){
|
||||
return std::char_traits<char>::to_char_type(is.get());
|
||||
}
|
||||
|
||||
void scan(){
|
||||
do{
|
||||
next=pull();
|
||||
}
|
||||
while(isspace(next));
|
||||
}
|
||||
|
||||
public:
|
||||
Parser(std::istream& is_,std::function<void(char)> cb_) :
|
||||
next(), is(is_), cb(cb_)
|
||||
{}
|
||||
|
||||
void run() {
|
||||
scan();
|
||||
E();
|
||||
}
|
||||
|
||||
private:
|
||||
void E(){
|
||||
T();
|
||||
while (next=='+'||next=='-'){
|
||||
cb(next);
|
||||
scan();
|
||||
T();
|
||||
}
|
||||
}
|
||||
|
||||
void T(){
|
||||
S();
|
||||
while (next=='*'||next=='/'){
|
||||
cb(next);
|
||||
scan();
|
||||
S();
|
||||
}
|
||||
}
|
||||
|
||||
void S(){
|
||||
if (isdigit(next)){
|
||||
cb(next);
|
||||
scan();
|
||||
}
|
||||
else if(next=='('){
|
||||
cb(next);
|
||||
scan();
|
||||
E();
|
||||
if (next==')'){
|
||||
cb(next);
|
||||
scan();
|
||||
}else{
|
||||
throw std::runtime_error("parsing failed");
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw std::runtime_error("parsing failed");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
try {
|
||||
std::istringstream is("1+1");
|
||||
bool done=false;
|
||||
std::exception_ptr except;
|
||||
|
||||
// execute parser in new execution context
|
||||
ctx::execution_context<char> source(
|
||||
[&is,&done,&except](ctx::execution_context<char> && sink,char){
|
||||
// create parser with callback function
|
||||
Parser p( is,
|
||||
[&sink](char ch){
|
||||
// resume main execution context
|
||||
auto result = sink(ch);
|
||||
sink = std::move(std::get<0>(result));
|
||||
});
|
||||
try {
|
||||
// start recursive parsing
|
||||
p.run();
|
||||
} catch (...) {
|
||||
// store other exceptions in exception-pointer
|
||||
except = std::current_exception();
|
||||
}
|
||||
// set termination flag
|
||||
done=true;
|
||||
// resume main execution context
|
||||
return std::move( sink);
|
||||
});
|
||||
|
||||
// user-code pulls parsed data from parser
|
||||
// invert control flow
|
||||
auto result = source('\0');
|
||||
source = std::move(std::get<0>(result));
|
||||
char c = std::get<1>(result);
|
||||
if ( except) {
|
||||
std::rethrow_exception(except);
|
||||
}
|
||||
while( ! done) {
|
||||
printf("Parsed: %c\n",c);
|
||||
std::tie(source,c) = source('\0');
|
||||
if (except) {
|
||||
std::rethrow_exception(except);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
} catch ( std::exception const& e) {
|
||||
std::cerr << "exception: " << e.what() << std::endl;
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
struct my_exception : public std::runtime_error {
|
||||
my_exception( std::string const& what) :
|
||||
std::runtime_error{ what } {
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
ctx::execution_context< void > ctx([](ctx::execution_context<void> && ctx) {
|
||||
for (;;) {
|
||||
try {
|
||||
std::cout << "entered" << std::endl;
|
||||
ctx = ctx();
|
||||
} catch ( ctx::ontop_error const& e) {
|
||||
try {
|
||||
std::rethrow_if_nested( e);
|
||||
} catch ( my_exception const& ex) {
|
||||
std::cerr << "my_exception: " << ex.what() << std::endl;
|
||||
}
|
||||
return e.get_context< void >();
|
||||
}
|
||||
}
|
||||
return std::move( ctx);
|
||||
});
|
||||
ctx = ctx();
|
||||
ctx = ctx();
|
||||
ctx = ctx( ctx::exec_ontop_arg, []() { throw my_exception("abc"); });
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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 UNW_LOCAL_ONLY
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
void backtrace() {
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
unw_getcontext( & context);
|
||||
unw_init_local( & cursor, & context);
|
||||
while ( 0 < unw_step( & cursor) ) {
|
||||
unw_word_t offset, pc;
|
||||
unw_get_reg( & cursor, UNW_REG_IP, & pc);
|
||||
if ( 0 == pc) {
|
||||
break;
|
||||
}
|
||||
std::cout << "0x" << pc << ":";
|
||||
|
||||
char sym[256];
|
||||
if ( 0 == unw_get_proc_name( & cursor, sym, sizeof( sym), & offset) ) {
|
||||
std::cout << " (" << sym << "+0x" << offset << ")" << std::endl;
|
||||
} else {
|
||||
std::cout << " -- error: unable to obtain symbol name for this frame" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bar() {
|
||||
backtrace();
|
||||
}
|
||||
|
||||
void foo() {
|
||||
bar();
|
||||
}
|
||||
|
||||
ctx::fiber f1( ctx::fiber && c) {
|
||||
foo();
|
||||
return std::move( c);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::fiber{ f1 }.resume();
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2016.
|
||||
// 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)
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
std::cout << "minimum stack size: " << ctx::stack_traits::minimum_size() << " byte\n";
|
||||
std::cout << "default stack size: " << ctx::stack_traits::default_size() << " byte\n";
|
||||
std::cout << "maximum stack size: ";
|
||||
if ( ctx::stack_traits::is_unbounded() ) {
|
||||
std::cout << "unlimited\n";
|
||||
} else {
|
||||
std::cout << ctx::stack_traits::maximum_size() << " byte\n";
|
||||
}
|
||||
std::cout << "main: done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -8,14 +8,14 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
int a;
|
||||
ctx::fiber f{
|
||||
[&a](ctx::fiber && f){
|
||||
ctx::fiber_context f{
|
||||
[&a](ctx::fiber_context && f){
|
||||
a=0;
|
||||
int b=1;
|
||||
for(;;){
|
||||
@@ -7,14 +7,14 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
int data = 1;
|
||||
ctx::fiber f{
|
||||
[&data](ctx::fiber && f){
|
||||
ctx::fiber_context f{
|
||||
[&data](ctx::fiber_context && f){
|
||||
std::cout << "entered first time: " << data << std::endl;
|
||||
data += 2;
|
||||
f = std::move( f).resume();
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
@@ -40,8 +40,8 @@ public:
|
||||
|
||||
int main() {
|
||||
moveable data{ 1 };
|
||||
ctx::fiber f{ std::allocator_arg, ctx::fixedsize_stack{},
|
||||
[&data](ctx::fiber && f){
|
||||
ctx::fiber_context f{ std::allocator_arg, ctx::fixedsize_stack{},
|
||||
[&data](ctx::fiber_context && f){
|
||||
std::cout << "entered first time: " << data.value << std::endl;
|
||||
data = std::move( moveable{ 3 });
|
||||
f = std::move( f).resume();
|
||||
@@ -7,11 +7,11 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::fiber f1( ctx::fiber && f) {
|
||||
ctx::fiber_context f1( ctx::fiber_context && f) {
|
||||
std::cout << "f1: entered first time" << std::endl;
|
||||
f = std::move( f).resume();
|
||||
std::cout << "f1: entered second time" << std::endl;
|
||||
@@ -19,7 +19,7 @@ ctx::fiber f1( ctx::fiber && f) {
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::fiber f{ f1 };
|
||||
ctx::fiber_context f{ f1 };
|
||||
f = std::move( f).resume();
|
||||
std::cout << "f1: returned first time" << std::endl;
|
||||
f = std::move( f).resume();
|
||||
@@ -8,13 +8,13 @@
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
int main() {
|
||||
int data = 0;
|
||||
ctx::fiber f{ [&data](ctx::fiber && f) {
|
||||
ctx::fiber_context f{ [&data](ctx::fiber_context && f) {
|
||||
std::cout << "f1: entered first time: " << data << std::endl;
|
||||
data += 1;
|
||||
f = std::move( f).resume();
|
||||
@@ -30,7 +30,7 @@ int main() {
|
||||
f = std::move( f).resume();
|
||||
std::cout << "f1: returned second time: " << data << std::endl;
|
||||
data += 1;
|
||||
f = std::move( f).resume_with([&data](ctx::fiber && f){
|
||||
f = std::move( f).resume_with([&data](ctx::fiber_context && f){
|
||||
std::cout << "f2: entered: " << data << std::endl;
|
||||
data = -1;
|
||||
return std::move( f);
|
||||
@@ -8,11 +8,11 @@
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
ctx::fiber f1( ctx::fiber && f) {
|
||||
ctx::fiber_context f1( ctx::fiber_context && f) {
|
||||
std::cout << "f1: entered first time" << std::endl;
|
||||
f = std::move( f).resume();
|
||||
std::cout << "f1: entered second time" << std::endl;
|
||||
@@ -21,13 +21,13 @@ ctx::fiber f1( ctx::fiber && f) {
|
||||
return std::move( f);
|
||||
}
|
||||
|
||||
ctx::fiber f2( ctx::fiber && f) {
|
||||
ctx::fiber_context f2( ctx::fiber_context && f) {
|
||||
std::cout << "f2: entered" << std::endl;
|
||||
return std::move( f);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ctx::fiber f{ f1 };
|
||||
ctx::fiber_context f{ f1 };
|
||||
f = std::move( f).resume();
|
||||
std::cout << "f1: returned first time" << std::endl;
|
||||
f = std::move( f).resume();
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
@@ -98,7 +98,7 @@ int main() {
|
||||
char c;
|
||||
bool done = false;
|
||||
// execute parser in new execution context
|
||||
ctx::fiber source{[&is,&c,&done](ctx::fiber && sink){
|
||||
ctx::fiber_context source{[&is,&c,&done](ctx::fiber_context && sink){
|
||||
// create parser with callback function
|
||||
Parser p( is,
|
||||
[&sink,&c](char c_){
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
@@ -41,8 +41,8 @@ int main() {
|
||||
std::cout << "initial stack size = " << ctx::fixedsize_stack::traits_type::default_size() / 1024 << "kB" << std::endl;
|
||||
std::cout << "application might fail" << std::endl;
|
||||
#endif
|
||||
ctx::fiber{
|
||||
[count](ctx::fiber && f){
|
||||
ctx::fiber_context{
|
||||
[count](ctx::fiber_context && f){
|
||||
bar( count);
|
||||
return std::move( f);
|
||||
}}.resume();
|
||||
@@ -10,20 +10,20 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <boost/context/fiber.hpp>
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
struct my_exception : public std::runtime_error {
|
||||
ctx::fiber f;
|
||||
my_exception( ctx::fiber && f_, std::string const& what) :
|
||||
ctx::fiber_context f;
|
||||
my_exception( ctx::fiber_context && f_, std::string const& what) :
|
||||
std::runtime_error{ what },
|
||||
f{ std::move( f_) } {
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
ctx::fiber f{[](ctx::fiber && f) ->ctx::fiber {
|
||||
ctx::fiber_context f{[](ctx::fiber_context && f) ->ctx::fiber_context {
|
||||
std::cout << "entered" << std::endl;
|
||||
try {
|
||||
f = std::move( f).resume();
|
||||
@@ -34,7 +34,7 @@ int main() {
|
||||
return {};
|
||||
}};
|
||||
f = std::move( f).resume();
|
||||
f = std::move( f).resume_with([](ctx::fiber && f) ->ctx::fiber {
|
||||
f = std::move( f).resume_with([](ctx::fiber_context && f) ->ctx::fiber_context {
|
||||
throw my_exception(std::move( f), "abc");
|
||||
return {};
|
||||
});
|
||||
69
example/unwind_fiber_context.cpp
Normal file
69
example/unwind_fiber_context.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2019.
|
||||
// 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)
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <unwind.h>
|
||||
|
||||
#include <boost/context/fiber_context.hpp>
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
struct X {
|
||||
int i;
|
||||
X( int i_) : i{ i_ } { std::printf("X(%d)\n", i); }
|
||||
~X() { std::printf("~X(%d)\n", i); }
|
||||
};
|
||||
|
||||
void bar( int i, ctx::fiber_context && fc) {
|
||||
if ( 0 < i) {
|
||||
X x{ i };
|
||||
bar( --i, std::move( fc) );
|
||||
} else {
|
||||
try {
|
||||
std::move( fc).resume();
|
||||
} catch (...) {
|
||||
std::printf("catch-all: needs throw\n");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
std::printf("bar returns\n");
|
||||
}
|
||||
|
||||
ctx::fiber_context foo( ctx::fiber_context && fc) {
|
||||
bar( 5, std::move( fc) );
|
||||
std::printf("foo returns\n");
|
||||
return {};
|
||||
};
|
||||
|
||||
void throw_int() {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (...) {
|
||||
std::printf("int catched\n");
|
||||
}
|
||||
}
|
||||
|
||||
void throw_exception() {
|
||||
try {
|
||||
throw std::runtime_error("abc");
|
||||
} catch (...) {
|
||||
std::printf("std::runtime_error() catched\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc, char * argv[]) {
|
||||
throw_int();
|
||||
throw_exception();
|
||||
{
|
||||
ctx::fiber_context f{ foo };
|
||||
f = std::move( f).resume();
|
||||
}
|
||||
std::printf("main: done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
76
example/unwind_ucontext.cpp
Normal file
76
example/unwind_ucontext.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2019.
|
||||
// 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)
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include <ucontext.h>
|
||||
#include <unwind.h>
|
||||
|
||||
struct context_t {
|
||||
ucontext_t ucf;
|
||||
ucontext_t ucm;
|
||||
};
|
||||
|
||||
struct X {
|
||||
int i;
|
||||
X( int i_) : i{ i_ } { std::printf("X(%d)\n", i); }
|
||||
~X() { std::printf("~X(%d)\n", i); }
|
||||
};
|
||||
|
||||
_Unwind_Reason_Code stop_fn( int version,
|
||||
_Unwind_Action actions,
|
||||
_Unwind_Exception_Class exc_class,
|
||||
_Unwind_Exception *exc,
|
||||
_Unwind_Context *context,
|
||||
void * param) {
|
||||
context_t * ctx = ( context_t *) param;
|
||||
if ( actions & _UA_END_OF_STACK) {
|
||||
std::printf("end of stack, jump back\n");
|
||||
_Unwind_DeleteException( exc);
|
||||
if ( -1 == ::swapcontext( & ctx->ucf, & ctx->ucm) ) {
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
void foo( int i, context_t * ctx) {
|
||||
if ( 0 < i) {
|
||||
X x{ i };
|
||||
foo( --i, ctx);
|
||||
} else {
|
||||
_Unwind_Exception * exc = ( _Unwind_Exception *) std::malloc( sizeof( _Unwind_Exception) );
|
||||
std::memset( exc, 0, sizeof( * exc) );
|
||||
_Unwind_ForcedUnwind( exc, stop_fn, ctx);
|
||||
//ctx::detail::unwind( stop_fn, ctx);
|
||||
}
|
||||
std::printf("return from foo()\n");
|
||||
}
|
||||
|
||||
int main( int argc, char * argv[]) {
|
||||
context_t ctx;
|
||||
std::vector< char > buffer(16384, '\0');
|
||||
void * fn_stack = & buffer[0];
|
||||
std::printf("buffer : %p\n", fn_stack);
|
||||
fn_stack = ( char * )( ( ( ( ( uintptr_t) fn_stack) - 16) >> 4) << 4);
|
||||
std::printf("aligned : %p\n", fn_stack);
|
||||
if ( -1 == ::getcontext( & ctx.ucf) ) {
|
||||
std::abort();
|
||||
}
|
||||
ctx.ucf.uc_stack.ss_sp = fn_stack;
|
||||
ctx.ucf.uc_stack.ss_size = buffer.size();
|
||||
::makecontext( & ctx.ucf, (void(*)())( foo), 2, 5, & ctx);
|
||||
if ( -1 == ::swapcontext( & ctx.ucm, & ctx.ucf) ) {
|
||||
std::abort();
|
||||
}
|
||||
std::printf("main: done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2017.
|
||||
// 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(BOOST_USE_UCONTEXT)
|
||||
#include <boost/context/continuation_ucontext.hpp>
|
||||
#elif defined(BOOST_USE_WINFIB)
|
||||
#include <boost/context/continuation_winfib.hpp>
|
||||
#else
|
||||
#include <boost/context/continuation_fcontext.hpp>
|
||||
#endif
|
||||
@@ -1,373 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2017.
|
||||
// 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_CONTINUATION_H
|
||||
#define BOOST_CONTEXT_CONTINUATION_H
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
#include <boost/context/detail/exchange.hpp>
|
||||
#endif
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
#include <boost/context/detail/invoke.hpp>
|
||||
#endif
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#include <boost/context/detail/exception.hpp>
|
||||
#include <boost/context/detail/fcontext.hpp>
|
||||
#include <boost/context/detail/tuple.hpp>
|
||||
#include <boost/context/fixedsize_stack.hpp>
|
||||
#include <boost/context/flags.hpp>
|
||||
#include <boost/context/preallocated.hpp>
|
||||
#include <boost/context/segmented_stack.hpp>
|
||||
#include <boost/context/stack_context.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4702)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
transfer_t context_unwind( transfer_t t) {
|
||||
throw forced_unwind( t.fctx);
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
template< typename Rec >
|
||||
transfer_t context_exit( transfer_t t) noexcept {
|
||||
Rec * rec = static_cast< Rec * >( t.data);
|
||||
// destroy context stack
|
||||
rec->deallocate();
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
template< typename Rec >
|
||||
void context_entry( transfer_t t) noexcept {
|
||||
// transfer control structure to the context-stack
|
||||
Rec * rec = static_cast< Rec * >( t.data);
|
||||
BOOST_ASSERT( nullptr != t.fctx);
|
||||
BOOST_ASSERT( nullptr != rec);
|
||||
try {
|
||||
// jump back to `create_context()`
|
||||
t = jump_fcontext( t.fctx, nullptr);
|
||||
// start executing
|
||||
t.fctx = rec->run( t.fctx);
|
||||
} catch ( forced_unwind const& ex) {
|
||||
t = { ex.fctx, nullptr };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
const_cast< forced_unwind & >( ex).caught = true;
|
||||
#endif
|
||||
}
|
||||
BOOST_ASSERT( nullptr != t.fctx);
|
||||
// destroy context-stack of `this`context on next context
|
||||
ontop_fcontext( t.fctx, rec, context_exit< Rec >);
|
||||
BOOST_ASSERT_MSG( false, "context already terminated");
|
||||
}
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
transfer_t context_ontop( transfer_t t) {
|
||||
auto p = static_cast< std::tuple< Fn > * >( t.data);
|
||||
BOOST_ASSERT( nullptr != p);
|
||||
typename std::decay< Fn >::type fn = std::get< 0 >( * p);
|
||||
t.data = nullptr;
|
||||
Ctx c{ t.fctx };
|
||||
// execute function, pass continuation via reference
|
||||
c = fn( std::move( c) );
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return { exchange( c.fctx_, nullptr), nullptr };
|
||||
#else
|
||||
return { std::exchange( c.fctx_, nullptr), nullptr };
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
class record {
|
||||
private:
|
||||
stack_context sctx_;
|
||||
typename std::decay< StackAlloc >::type salloc_;
|
||||
typename std::decay< Fn >::type fn_;
|
||||
|
||||
static void destroy( record * p) noexcept {
|
||||
typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
|
||||
stack_context sctx = p->sctx_;
|
||||
// deallocate record
|
||||
p->~record();
|
||||
// destroy stack with stack allocator
|
||||
salloc.deallocate( sctx);
|
||||
}
|
||||
|
||||
public:
|
||||
record( stack_context sctx, StackAlloc && salloc,
|
||||
Fn && fn) noexcept :
|
||||
sctx_( sctx),
|
||||
salloc_( std::forward< StackAlloc >( salloc)),
|
||||
fn_( std::forward< Fn >( fn) ) {
|
||||
}
|
||||
|
||||
record( record const&) = delete;
|
||||
record & operator=( record const&) = delete;
|
||||
|
||||
void deallocate() noexcept {
|
||||
destroy( this);
|
||||
}
|
||||
|
||||
fcontext_t run( fcontext_t fctx) {
|
||||
Ctx c{ fctx };
|
||||
// invoke context-function
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
c = boost::context::detail::invoke( fn_, std::move( c) );
|
||||
#else
|
||||
c = std::invoke( fn_, std::move( c) );
|
||||
#endif
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.fctx_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.fctx_, nullptr);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Record, typename StackAlloc, typename Fn >
|
||||
fcontext_t create_context1( StackAlloc && salloc, Fn && fn) {
|
||||
auto sctx = salloc.allocate();
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( Record) ) )
|
||||
& ~static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
Record * record = new ( storage) Record{
|
||||
sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// 64byte gab between control structure and stack top
|
||||
// should be 16byte aligned
|
||||
void * stack_top = reinterpret_cast< void * >(
|
||||
reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) );
|
||||
void * stack_bottom = reinterpret_cast< void * >(
|
||||
reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) );
|
||||
// create fast-context
|
||||
const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom);
|
||||
const fcontext_t fctx = make_fcontext( stack_top, size, & context_entry< Record >);
|
||||
BOOST_ASSERT( nullptr != fctx);
|
||||
// transfer control structure to context-stack
|
||||
return jump_fcontext( fctx, record).fctx;
|
||||
}
|
||||
|
||||
template< typename Record, typename StackAlloc, typename Fn >
|
||||
fcontext_t create_context2( preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( Record) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context-stack
|
||||
Record * record = new ( storage) Record{
|
||||
palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// 64byte gab between control structure and stack top
|
||||
void * stack_top = reinterpret_cast< void * >(
|
||||
reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) );
|
||||
void * stack_bottom = reinterpret_cast< void * >(
|
||||
reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) );
|
||||
// create fast-context
|
||||
const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom);
|
||||
const fcontext_t fctx = make_fcontext( stack_top, size, & context_entry< Record >);
|
||||
BOOST_ASSERT( nullptr != fctx);
|
||||
// transfer control structure to context-stack
|
||||
return jump_fcontext( fctx, record).fctx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class continuation {
|
||||
private:
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend class detail::record;
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
friend detail::transfer_t
|
||||
detail::context_ontop( detail::transfer_t);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend continuation
|
||||
callcc( std::allocator_arg_t, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend continuation
|
||||
callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
detail::fcontext_t fctx_{ nullptr };
|
||||
|
||||
continuation( detail::fcontext_t fctx) noexcept :
|
||||
fctx_{ fctx } {
|
||||
}
|
||||
|
||||
public:
|
||||
continuation() noexcept = default;
|
||||
|
||||
~continuation() {
|
||||
if ( BOOST_UNLIKELY( nullptr != fctx_) ) {
|
||||
detail::ontop_fcontext(
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::exchange( fctx_, nullptr),
|
||||
#else
|
||||
std::exchange( fctx_, nullptr),
|
||||
#endif
|
||||
nullptr,
|
||||
detail::context_unwind);
|
||||
}
|
||||
}
|
||||
|
||||
continuation( continuation && other) noexcept {
|
||||
swap( other);
|
||||
}
|
||||
|
||||
continuation & operator=( continuation && other) noexcept {
|
||||
if ( BOOST_LIKELY( this != & other) ) {
|
||||
continuation tmp = std::move( other);
|
||||
swap( tmp);
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
continuation( continuation const& other) noexcept = delete;
|
||||
continuation & operator=( continuation const& other) noexcept = delete;
|
||||
|
||||
continuation resume() & {
|
||||
return std::move( * this).resume();
|
||||
}
|
||||
|
||||
continuation resume() && {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
return { detail::jump_fcontext(
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::exchange( fctx_, nullptr),
|
||||
#else
|
||||
std::exchange( fctx_, nullptr),
|
||||
#endif
|
||||
nullptr).fctx };
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
continuation resume_with( Fn && fn) & {
|
||||
return std::move( * this).resume_with( std::forward< Fn >( fn) );
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
continuation resume_with( Fn && fn) && {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
auto p = std::make_tuple( std::forward< Fn >( fn) );
|
||||
return { detail::ontop_fcontext(
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::exchange( fctx_, nullptr),
|
||||
#else
|
||||
std::exchange( fctx_, nullptr),
|
||||
#endif
|
||||
& p,
|
||||
detail::context_ontop< continuation, Fn >).fctx };
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return nullptr != fctx_;
|
||||
}
|
||||
|
||||
bool operator!() const noexcept {
|
||||
return nullptr == fctx_;
|
||||
}
|
||||
|
||||
bool operator<( continuation const& other) const noexcept {
|
||||
return fctx_ < other.fctx_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
|
||||
if ( nullptr != other.fctx_) {
|
||||
return os << other.fctx_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
void swap( continuation & other) noexcept {
|
||||
std::swap( fctx_, other.fctx_);
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
typename Fn,
|
||||
typename = detail::disable_overload< continuation, Fn >
|
||||
>
|
||||
continuation
|
||||
callcc( Fn && fn) {
|
||||
return callcc(
|
||||
std::allocator_arg, fixedsize_stack(),
|
||||
std::forward< Fn >( fn) );
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
continuation
|
||||
callcc( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) {
|
||||
using Record = detail::record< continuation, StackAlloc, Fn >;
|
||||
return continuation{
|
||||
detail::create_context1< Record >(
|
||||
std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume();
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
continuation
|
||||
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
using Record = detail::record< continuation, StackAlloc, Fn >;
|
||||
return continuation{
|
||||
detail::create_context2< Record >(
|
||||
palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume();
|
||||
}
|
||||
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
template< typename Fn >
|
||||
continuation
|
||||
callcc( std::allocator_arg_t, segmented_stack, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
continuation
|
||||
callcc( std::allocator_arg_t, preallocated, segmented_stack, Fn &&);
|
||||
#endif
|
||||
|
||||
inline
|
||||
void swap( continuation & l, continuation & r) noexcept {
|
||||
l.swap( r);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_CONTINUATION_H
|
||||
@@ -1,526 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2017.
|
||||
// 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_CONTINUATION_H
|
||||
#define BOOST_CONTEXT_CONTINUATION_H
|
||||
|
||||
#include <boost/predef.h>
|
||||
#if BOOST_OS_MACOS
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <ucontext.h>
|
||||
}
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <system_error>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
#include <boost/context/detail/exchange.hpp>
|
||||
#endif
|
||||
#include <boost/context/detail/externc.hpp>
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
#include <boost/context/detail/invoke.hpp>
|
||||
#endif
|
||||
#include <boost/context/fixedsize_stack.hpp>
|
||||
#include <boost/context/flags.hpp>
|
||||
#include <boost/context/preallocated.hpp>
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
#include <boost/context/segmented_stack.hpp>
|
||||
#endif
|
||||
#include <boost/context/stack_context.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
// tampoline function
|
||||
// entered if the execution context
|
||||
// is resumed for the first time
|
||||
template< typename Record >
|
||||
static void entry_func( void * data) noexcept {
|
||||
Record * record = static_cast< Record * >( data);
|
||||
BOOST_ASSERT( nullptr != record);
|
||||
// start execution of toplevel context-function
|
||||
record->run();
|
||||
}
|
||||
|
||||
struct BOOST_CONTEXT_DECL activation_record {
|
||||
ucontext_t uctx{};
|
||||
stack_context sctx{};
|
||||
bool main_ctx{ true };
|
||||
activation_record * from{ nullptr };
|
||||
std::function< activation_record*(activation_record*&) > ontop{};
|
||||
bool terminated{ false };
|
||||
bool force_unwind{ false };
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
void * fake_stack{ nullptr };
|
||||
void * stack_bottom{ nullptr };
|
||||
std::size_t stack_size{ 0 };
|
||||
#endif
|
||||
|
||||
static activation_record *& current() noexcept;
|
||||
|
||||
// used for toplevel-context
|
||||
// (e.g. main context, thread-entry context)
|
||||
activation_record() {
|
||||
if ( BOOST_UNLIKELY( 0 != ::getcontext( & uctx) ) ) {
|
||||
throw std::system_error(
|
||||
std::error_code( errno, std::system_category() ),
|
||||
"getcontext() failed");
|
||||
}
|
||||
}
|
||||
|
||||
activation_record( stack_context sctx_) noexcept :
|
||||
sctx( sctx_ ),
|
||||
main_ctx( false ) {
|
||||
}
|
||||
|
||||
virtual ~activation_record() {
|
||||
}
|
||||
|
||||
activation_record( activation_record const&) = delete;
|
||||
activation_record & operator=( activation_record const&) = delete;
|
||||
|
||||
bool is_main_context() const noexcept {
|
||||
return main_ctx;
|
||||
}
|
||||
|
||||
activation_record * resume() {
|
||||
from = current();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
current() = this;
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
// adjust segmented stack properties
|
||||
__splitstack_getcontext( from->sctx.segments_ctx);
|
||||
__splitstack_setcontext( sctx.segments_ctx);
|
||||
#endif
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
if ( terminated) {
|
||||
__sanitizer_start_switch_fiber( nullptr, stack_bottom, stack_size);
|
||||
} else {
|
||||
__sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size);
|
||||
}
|
||||
#endif
|
||||
// context switch from parent context to `this`-context
|
||||
::swapcontext( & from->uctx, & uctx);
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_finish_switch_fiber( current()->fake_stack,
|
||||
(const void **) & current()->from->stack_bottom,
|
||||
& current()->from->stack_size);
|
||||
#endif
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( current()->from, nullptr);
|
||||
#else
|
||||
return std::exchange( current()->from, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
activation_record * resume_with( Fn && fn) {
|
||||
from = current();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
// returned by continuation::current()
|
||||
current() = this;
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
current()->ontop = std::bind(
|
||||
[](typename std::decay< Fn >::type & fn, activation_record *& ptr){
|
||||
Ctx c{ ptr };
|
||||
c = fn( std::move( c) );
|
||||
if ( ! c) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.ptr_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.ptr_, nullptr);
|
||||
#endif
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1);
|
||||
#else
|
||||
current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){
|
||||
Ctx c{ ptr };
|
||||
c = fn( std::move( c) );
|
||||
if ( ! c) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.ptr_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.ptr_, nullptr);
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
// adjust segmented stack properties
|
||||
__splitstack_getcontext( from->sctx.segments_ctx);
|
||||
__splitstack_setcontext( sctx.segments_ctx);
|
||||
#endif
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size);
|
||||
#endif
|
||||
// context switch from parent context to `this`-context
|
||||
::swapcontext( & from->uctx, & uctx);
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_finish_switch_fiber( current()->fake_stack,
|
||||
(const void **) & current()->from->stack_bottom,
|
||||
& current()->from->stack_size);
|
||||
#endif
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( current()->from, nullptr);
|
||||
#else
|
||||
return std::exchange( current()->from, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void deallocate() noexcept {
|
||||
}
|
||||
};
|
||||
|
||||
struct BOOST_CONTEXT_DECL activation_record_initializer {
|
||||
activation_record_initializer() noexcept;
|
||||
~activation_record_initializer();
|
||||
};
|
||||
|
||||
struct forced_unwind {
|
||||
activation_record * from{ nullptr };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
bool caught{ false };
|
||||
#endif
|
||||
|
||||
forced_unwind( activation_record * from_) noexcept :
|
||||
from{ from_ } {
|
||||
}
|
||||
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
~forced_unwind() {
|
||||
BOOST_ASSERT( caught);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
class capture_record : public activation_record {
|
||||
private:
|
||||
typename std::decay< StackAlloc >::type salloc_;
|
||||
typename std::decay< Fn >::type fn_;
|
||||
|
||||
static void destroy( capture_record * p) noexcept {
|
||||
typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
|
||||
stack_context sctx = p->sctx;
|
||||
// deallocate activation record
|
||||
p->~capture_record();
|
||||
// destroy stack with stack allocator
|
||||
salloc.deallocate( sctx);
|
||||
}
|
||||
|
||||
public:
|
||||
capture_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept :
|
||||
activation_record{ sctx },
|
||||
salloc_{ std::forward< StackAlloc >( salloc) },
|
||||
fn_( std::forward< Fn >( fn) ) {
|
||||
}
|
||||
|
||||
void deallocate() noexcept override final {
|
||||
BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) );
|
||||
destroy( this);
|
||||
}
|
||||
|
||||
void run() {
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_finish_switch_fiber( fake_stack,
|
||||
(const void **) & from->stack_bottom,
|
||||
& from->stack_size);
|
||||
#endif
|
||||
Ctx c{ from };
|
||||
try {
|
||||
// invoke context-function
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
c = boost::context::detail::invoke( fn_, std::move( c) );
|
||||
#else
|
||||
c = std::invoke( fn_, std::move( c) );
|
||||
#endif
|
||||
} catch ( forced_unwind const& ex) {
|
||||
c = Ctx{ ex.from };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
const_cast< forced_unwind & >( ex).caught = true;
|
||||
#endif
|
||||
}
|
||||
// this context has finished its task
|
||||
from = nullptr;
|
||||
ontop = nullptr;
|
||||
terminated = true;
|
||||
force_unwind = false;
|
||||
c.resume();
|
||||
BOOST_ASSERT_MSG( false, "continuation already terminated");
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
static activation_record * create_context1( StackAlloc && salloc, Fn && fn) {
|
||||
typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
|
||||
|
||||
auto sctx = salloc.allocate();
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
capture_t * record = new ( storage) capture_t{
|
||||
sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// stack bottom
|
||||
void * stack_bottom = reinterpret_cast< void * >(
|
||||
reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) );
|
||||
// create user-context
|
||||
if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) {
|
||||
record->~capture_t();
|
||||
salloc.deallocate( sctx);
|
||||
throw std::system_error(
|
||||
std::error_code( errno, std::system_category() ),
|
||||
"getcontext() failed");
|
||||
}
|
||||
record->uctx.uc_stack.ss_sp = stack_bottom;
|
||||
// 64byte gap between control structure and stack top
|
||||
record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) -
|
||||
reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64);
|
||||
record->uctx.uc_link = nullptr;
|
||||
::makecontext( & record->uctx, ( void (*)() ) & entry_func< capture_t >, 1, record);
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
record->stack_bottom = record->uctx.uc_stack.ss_sp;
|
||||
record->stack_size = record->uctx.uc_stack.ss_size;
|
||||
#endif
|
||||
return record;
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
static activation_record * create_context2( preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
|
||||
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
capture_t * record = new ( storage) capture_t{
|
||||
palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// stack bottom
|
||||
void * stack_bottom = reinterpret_cast< void * >(
|
||||
reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) );
|
||||
// create user-context
|
||||
if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) {
|
||||
record->~capture_t();
|
||||
salloc.deallocate( palloc.sctx);
|
||||
throw std::system_error(
|
||||
std::error_code( errno, std::system_category() ),
|
||||
"getcontext() failed");
|
||||
}
|
||||
record->uctx.uc_stack.ss_sp = stack_bottom;
|
||||
// 64byte gap between control structure and stack top
|
||||
record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) -
|
||||
reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64);
|
||||
record->uctx.uc_link = nullptr;
|
||||
::makecontext( & record->uctx, ( void (*)() ) & entry_func< capture_t >, 1, record);
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
record->stack_bottom = record->uctx.uc_stack.ss_sp;
|
||||
record->stack_size = record->uctx.uc_stack.ss_size;
|
||||
#endif
|
||||
return record;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class BOOST_CONTEXT_DECL continuation {
|
||||
private:
|
||||
friend struct detail::activation_record;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend class detail::capture_record;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend detail::activation_record * detail::create_context1( StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend detail::activation_record * detail::create_context2( preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend continuation
|
||||
callcc( std::allocator_arg_t, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend continuation
|
||||
callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
detail::activation_record * ptr_{ nullptr };
|
||||
|
||||
continuation( detail::activation_record * ptr) noexcept :
|
||||
ptr_{ ptr } {
|
||||
}
|
||||
|
||||
public:
|
||||
continuation() = default;
|
||||
|
||||
~continuation() {
|
||||
if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) {
|
||||
if ( BOOST_LIKELY( ! ptr_->terminated) ) {
|
||||
ptr_->force_unwind = true;
|
||||
ptr_->resume();
|
||||
BOOST_ASSERT( ptr_->terminated);
|
||||
}
|
||||
ptr_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
continuation( continuation const&) = delete;
|
||||
continuation & operator=( continuation const&) = delete;
|
||||
|
||||
continuation( continuation && other) noexcept {
|
||||
swap( other);
|
||||
}
|
||||
|
||||
continuation & operator=( continuation && other) noexcept {
|
||||
if ( BOOST_LIKELY( this != & other) ) {
|
||||
continuation tmp = std::move( other);
|
||||
swap( tmp);
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
continuation resume() & {
|
||||
return std::move( * this).resume();
|
||||
}
|
||||
|
||||
continuation resume() && {
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume();
|
||||
#else
|
||||
detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
|
||||
#endif
|
||||
if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
|
||||
throw detail::forced_unwind{ ptr};
|
||||
} else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
|
||||
ptr = detail::activation_record::current()->ontop( ptr);
|
||||
detail::activation_record::current()->ontop = nullptr;
|
||||
}
|
||||
return { ptr };
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
continuation resume_with( Fn && fn) & {
|
||||
return std::move( * this).resume_with( std::forward< Fn >( fn) );
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
continuation resume_with( Fn && fn) && {
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::activation_record * ptr =
|
||||
detail::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
|
||||
#else
|
||||
detail::activation_record * ptr =
|
||||
std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
|
||||
#endif
|
||||
if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
|
||||
throw detail::forced_unwind{ ptr};
|
||||
} else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
|
||||
ptr = detail::activation_record::current()->ontop( ptr);
|
||||
detail::activation_record::current()->ontop = nullptr;
|
||||
}
|
||||
return { ptr };
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return nullptr != ptr_ && ! ptr_->terminated;
|
||||
}
|
||||
|
||||
bool operator!() const noexcept {
|
||||
return nullptr == ptr_ || ptr_->terminated;
|
||||
}
|
||||
|
||||
bool operator<( continuation const& other) const noexcept {
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
|
||||
if ( nullptr != other.ptr_) {
|
||||
return os << other.ptr_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
void swap( continuation & other) noexcept {
|
||||
std::swap( ptr_, other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
typename Fn,
|
||||
typename = detail::disable_overload< continuation, Fn >
|
||||
>
|
||||
continuation
|
||||
callcc( Fn && fn) {
|
||||
return callcc(
|
||||
std::allocator_arg,
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
segmented_stack(),
|
||||
#else
|
||||
fixedsize_stack(),
|
||||
#endif
|
||||
std::forward< Fn >( fn) );
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
continuation
|
||||
callcc( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) {
|
||||
return continuation{
|
||||
detail::create_context1< continuation >(
|
||||
std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume();
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
continuation
|
||||
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
return continuation{
|
||||
detail::create_context2< continuation >(
|
||||
palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume();
|
||||
}
|
||||
|
||||
inline
|
||||
void swap( continuation & l, continuation & r) noexcept {
|
||||
l.swap( r);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_CONTINUATION_H
|
||||
@@ -1,461 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2017.
|
||||
// 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_CONTINUATION_H
|
||||
#define BOOST_CONTEXT_CONTINUATION_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <system_error>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
#include <boost/context/detail/exchange.hpp>
|
||||
#endif
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
#include <boost/context/detail/invoke.hpp>
|
||||
#endif
|
||||
#include <boost/context/fixedsize_stack.hpp>
|
||||
#include <boost/context/flags.hpp>
|
||||
#include <boost/context/preallocated.hpp>
|
||||
#include <boost/context/stack_context.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4702)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
// tampoline function
|
||||
// entered if the execution context
|
||||
// is resumed for the first time
|
||||
template< typename Record >
|
||||
static VOID WINAPI entry_func( LPVOID data) noexcept {
|
||||
Record * record = static_cast< Record * >( data);
|
||||
BOOST_ASSERT( nullptr != record);
|
||||
// start execution of toplevel context-function
|
||||
record->run();
|
||||
}
|
||||
|
||||
struct BOOST_CONTEXT_DECL activation_record {
|
||||
LPVOID fiber{ nullptr };
|
||||
stack_context sctx{};
|
||||
bool main_ctx{ true };
|
||||
activation_record * from{ nullptr };
|
||||
std::function< activation_record*(activation_record*&) > ontop{};
|
||||
bool terminated{ false };
|
||||
bool force_unwind{ false };
|
||||
|
||||
static activation_record *& current() noexcept;
|
||||
|
||||
// used for toplevel-context
|
||||
// (e.g. main context, thread-entry context)
|
||||
activation_record() noexcept {
|
||||
#if ( _WIN32_WINNT > 0x0600)
|
||||
if ( ::IsThreadAFiber() ) {
|
||||
fiber = ::GetCurrentFiber();
|
||||
} else {
|
||||
fiber = ::ConvertThreadToFiber( nullptr);
|
||||
}
|
||||
#else
|
||||
fiber = ::ConvertThreadToFiber( nullptr);
|
||||
if ( BOOST_UNLIKELY( nullptr == fiber) ) {
|
||||
DWORD err = ::GetLastError();
|
||||
BOOST_ASSERT( ERROR_ALREADY_FIBER == err);
|
||||
fiber = ::GetCurrentFiber();
|
||||
BOOST_ASSERT( nullptr != fiber);
|
||||
BOOST_ASSERT( reinterpret_cast< LPVOID >( 0x1E00) != fiber);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
activation_record( stack_context sctx_) noexcept :
|
||||
sctx{ sctx_ },
|
||||
main_ctx{ false } {
|
||||
}
|
||||
|
||||
virtual ~activation_record() {
|
||||
if ( BOOST_UNLIKELY( main_ctx) ) {
|
||||
::ConvertFiberToThread();
|
||||
} else {
|
||||
::DeleteFiber( fiber);
|
||||
}
|
||||
}
|
||||
|
||||
activation_record( activation_record const&) = delete;
|
||||
activation_record & operator=( activation_record const&) = delete;
|
||||
|
||||
bool is_main_context() const noexcept {
|
||||
return main_ctx;
|
||||
}
|
||||
|
||||
activation_record * resume() {
|
||||
from = current();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
current() = this;
|
||||
// context switch from parent context to `this`-context
|
||||
// context switch
|
||||
::SwitchToFiber( fiber);
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return detail::exchange( current()->from, nullptr);
|
||||
#else
|
||||
return std::exchange( current()->from, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
activation_record * resume_with( Fn && fn) {
|
||||
from = current();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
// returned by continuation::current()
|
||||
current() = this;
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
current()->ontop = std::bind(
|
||||
[](typename std::decay< Fn >::type & fn, activation_record *& ptr){
|
||||
Ctx c{ ptr };
|
||||
c = fn( std::move( c) );
|
||||
if ( ! c) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.ptr_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.ptr_, nullptr);
|
||||
#endif
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1);
|
||||
#else
|
||||
current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){
|
||||
Ctx c{ ptr };
|
||||
c = fn( std::move( c) );
|
||||
if ( ! c) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.ptr_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.ptr_, nullptr);
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
// context switch
|
||||
::SwitchToFiber( fiber);
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return detail::exchange( current()->from, nullptr);
|
||||
#else
|
||||
return std::exchange( current()->from, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void deallocate() noexcept {
|
||||
}
|
||||
};
|
||||
|
||||
struct BOOST_CONTEXT_DECL activation_record_initializer {
|
||||
activation_record_initializer() noexcept;
|
||||
~activation_record_initializer();
|
||||
};
|
||||
|
||||
struct forced_unwind {
|
||||
activation_record * from{ nullptr };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
bool caught{ false };
|
||||
#endif
|
||||
|
||||
explicit forced_unwind( activation_record * from_) :
|
||||
from{ from_ } {
|
||||
}
|
||||
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
~forced_unwind() {
|
||||
BOOST_ASSERT( caught);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
class capture_record : public activation_record {
|
||||
private:
|
||||
typename std::decay< StackAlloc >::type salloc_;
|
||||
typename std::decay< Fn >::type fn_;
|
||||
|
||||
static void destroy( capture_record * p) noexcept {
|
||||
typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
|
||||
stack_context sctx = p->sctx;
|
||||
// deallocate activation record
|
||||
p->~capture_record();
|
||||
// destroy stack with stack allocator
|
||||
salloc.deallocate( sctx);
|
||||
}
|
||||
|
||||
public:
|
||||
capture_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept :
|
||||
activation_record( sctx),
|
||||
salloc_( std::forward< StackAlloc >( salloc)),
|
||||
fn_( std::forward< Fn >( fn) ) {
|
||||
}
|
||||
|
||||
void deallocate() noexcept override final {
|
||||
BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) );
|
||||
destroy( this);
|
||||
}
|
||||
|
||||
void run() {
|
||||
Ctx c{ from };
|
||||
try {
|
||||
// invoke context-function
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
c = boost::context::detail::invoke( fn_, std::move( c) );
|
||||
#else
|
||||
c = std::invoke( fn_, std::move( c) );
|
||||
#endif
|
||||
} catch ( forced_unwind const& ex) {
|
||||
c = Ctx{ ex.from };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
const_cast< forced_unwind & >( ex).caught = true;
|
||||
#endif
|
||||
}
|
||||
// this context has finished its task
|
||||
from = nullptr;
|
||||
ontop = nullptr;
|
||||
terminated = true;
|
||||
force_unwind = false;
|
||||
c.resume();
|
||||
BOOST_ASSERT_MSG( false, "continuation already terminated");
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
static activation_record * create_context1( StackAlloc && salloc, Fn && fn) {
|
||||
typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
|
||||
|
||||
auto sctx = salloc.allocate();
|
||||
BOOST_ASSERT( ( sizeof( capture_t) ) < sctx.size);
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
capture_t * record = new ( storage) capture_t{
|
||||
sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// create user-context
|
||||
record->fiber = ::CreateFiber( sctx.size, & detail::entry_func< capture_t >, record);
|
||||
return record;
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
static activation_record * create_context2( preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
typedef capture_record< Ctx, StackAlloc, Fn > capture_t;
|
||||
|
||||
BOOST_ASSERT( ( sizeof( capture_t) ) < palloc.size);
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
capture_t * record = new ( storage) capture_t{
|
||||
palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// create user-context
|
||||
record->fiber = ::CreateFiber( palloc.sctx.size, & detail::entry_func< capture_t >, record);
|
||||
return record;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class BOOST_CONTEXT_DECL continuation {
|
||||
private:
|
||||
friend struct detail::activation_record;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend class detail::capture_record;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend detail::activation_record * detail::create_context1( StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend detail::activation_record * detail::create_context2( preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend continuation
|
||||
callcc( std::allocator_arg_t, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend continuation
|
||||
callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
detail::activation_record * ptr_{ nullptr };
|
||||
|
||||
continuation( detail::activation_record * ptr) noexcept :
|
||||
ptr_{ ptr } {
|
||||
}
|
||||
|
||||
public:
|
||||
continuation() = default;
|
||||
|
||||
~continuation() {
|
||||
if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) {
|
||||
if ( BOOST_LIKELY( ! ptr_->terminated) ) {
|
||||
ptr_->force_unwind = true;
|
||||
ptr_->resume();
|
||||
BOOST_ASSERT( ptr_->terminated);
|
||||
}
|
||||
ptr_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
continuation( continuation const&) = delete;
|
||||
continuation & operator=( continuation const&) = delete;
|
||||
|
||||
continuation( continuation && other) noexcept {
|
||||
swap( other);
|
||||
}
|
||||
|
||||
continuation & operator=( continuation && other) noexcept {
|
||||
if ( BOOST_LIKELY( this != & other) ) {
|
||||
continuation tmp = std::move( other);
|
||||
swap( tmp);
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
continuation resume() & {
|
||||
return std::move( * this).resume();
|
||||
}
|
||||
|
||||
continuation resume() && {
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume();
|
||||
#else
|
||||
detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
|
||||
#endif
|
||||
if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
|
||||
throw detail::forced_unwind{ ptr};
|
||||
} else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
|
||||
ptr = detail::activation_record::current()->ontop( ptr);
|
||||
detail::activation_record::current()->ontop = nullptr;
|
||||
}
|
||||
return { ptr };
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
continuation resume_with( Fn && fn) & {
|
||||
return std::move( * this).resume_with( std::forward< Fn >( fn) );
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
continuation resume_with( Fn && fn) && {
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::activation_record * ptr =
|
||||
detail::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
|
||||
#else
|
||||
detail::activation_record * ptr =
|
||||
std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) );
|
||||
#endif
|
||||
if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) {
|
||||
throw detail::forced_unwind{ ptr};
|
||||
} else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) {
|
||||
ptr = detail::activation_record::current()->ontop( ptr);
|
||||
detail::activation_record::current()->ontop = nullptr;
|
||||
}
|
||||
return { ptr };
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return nullptr != ptr_ && ! ptr_->terminated;
|
||||
}
|
||||
|
||||
bool operator!() const noexcept {
|
||||
return nullptr == ptr_ || ptr_->terminated;
|
||||
}
|
||||
|
||||
bool operator<( continuation const& other) const noexcept {
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
|
||||
if ( nullptr != other.ptr_) {
|
||||
return os << other.ptr_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
void swap( continuation & other) noexcept {
|
||||
std::swap( ptr_, other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
typename Fn,
|
||||
typename = detail::disable_overload< continuation, Fn >
|
||||
>
|
||||
continuation
|
||||
callcc( Fn && fn) {
|
||||
return callcc(
|
||||
std::allocator_arg,
|
||||
fixedsize_stack(),
|
||||
std::forward< Fn >( fn) );
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
continuation
|
||||
callcc( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) {
|
||||
return continuation{
|
||||
detail::create_context1< continuation >(
|
||||
std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume();
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
continuation
|
||||
callcc( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
return continuation{
|
||||
detail::create_context2< continuation >(
|
||||
palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume();
|
||||
}
|
||||
|
||||
inline
|
||||
void swap( continuation & l, continuation & r) noexcept {
|
||||
l.swap( r);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_CONTINUATION_H
|
||||
@@ -1,48 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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_EXCEPTION_H
|
||||
#define BOOST_CONTEXT_DETAIL_EXCEPTION_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/detail/fcontext.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
struct forced_unwind {
|
||||
fcontext_t fctx{ nullptr };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
bool caught{ false };
|
||||
#endif
|
||||
|
||||
forced_unwind() = default;
|
||||
|
||||
forced_unwind( fcontext_t fctx_) :
|
||||
fctx( fctx_) {
|
||||
}
|
||||
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
~forced_unwind() {
|
||||
BOOST_ASSERT( caught);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
#include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_DETAIL_EXCEPTION_H
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_THREAD_LOCAL)
|
||||
# include <boost/context/execution_context_v1.hpp>
|
||||
#endif
|
||||
#include <boost/context/execution_context_v2.hpp>
|
||||
@@ -1,473 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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_EXECUTION_CONTEXT_V1_H
|
||||
#define BOOST_CONTEXT_EXECUTION_CONTEXT_V1_H
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX17_STD_APPLY)
|
||||
#include <boost/context/detail/apply.hpp>
|
||||
#endif
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#include <boost/context/detail/externc.hpp>
|
||||
#include <boost/context/detail/fcontext.hpp>
|
||||
#include <boost/context/fixedsize_stack.hpp>
|
||||
#include <boost/context/flags.hpp>
|
||||
#include <boost/context/preallocated.hpp>
|
||||
#include <boost/context/segmented_stack.hpp>
|
||||
#include <boost/context/stack_context.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
template< typename Fn >
|
||||
transfer_t ecv1_context_ontop( transfer_t);
|
||||
|
||||
struct ecv1_activation_record;
|
||||
|
||||
struct ecv1_data_t {
|
||||
ecv1_activation_record * from;
|
||||
void * data;
|
||||
};
|
||||
|
||||
struct BOOST_CONTEXT_DECL ecv1_activation_record {
|
||||
typedef boost::intrusive_ptr< ecv1_activation_record > ptr_t;
|
||||
|
||||
static ptr_t & current() noexcept;
|
||||
|
||||
std::atomic< std::size_t > use_count{ 0 };
|
||||
fcontext_t fctx{ nullptr };
|
||||
stack_context sctx{};
|
||||
bool main_ctx{ true };
|
||||
|
||||
// used for toplevel-context
|
||||
// (e.g. main context, thread-entry context)
|
||||
ecv1_activation_record() = default;
|
||||
|
||||
ecv1_activation_record( fcontext_t fctx_, stack_context sctx_) noexcept :
|
||||
fctx{ fctx_ },
|
||||
sctx( sctx_ ), // sctx{ sctx_ } - clang-3.6: no viable conversion from 'boost::context::stack_context' to 'std::size_t'
|
||||
main_ctx{ false } {
|
||||
}
|
||||
|
||||
virtual ~ecv1_activation_record() = default;
|
||||
|
||||
bool is_main_context() const noexcept {
|
||||
return main_ctx;
|
||||
}
|
||||
|
||||
void * resume( void * vp) {
|
||||
// store current activation record in local variable
|
||||
auto from = current().get();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
// returned by execution_context::current()
|
||||
current() = this;
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
// adjust segmented stack properties
|
||||
__splitstack_getcontext( from->sctx.segments_ctx);
|
||||
__splitstack_setcontext( sctx.segments_ctx);
|
||||
#endif
|
||||
ecv1_data_t d = { from, vp };
|
||||
// context switch from parent context to `this`-context
|
||||
transfer_t t = jump_fcontext( fctx, & d);
|
||||
ecv1_data_t * dp = reinterpret_cast< ecv1_data_t * >( t.data);
|
||||
dp->from->fctx = t.fctx;
|
||||
// parent context resumed
|
||||
return dp->data;
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
void * resume_ontop( void * data, Fn && fn) {
|
||||
// store current activation record in local variable
|
||||
ecv1_activation_record * from = current().get();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
// returned by execution_context::current()
|
||||
current() = this;
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
// adjust segmented stack properties
|
||||
__splitstack_getcontext( from->sctx.segments_ctx);
|
||||
__splitstack_setcontext( sctx.segments_ctx);
|
||||
#endif
|
||||
std::tuple< void *, Fn > p = std::forward_as_tuple( data, fn);
|
||||
ecv1_data_t d = { from, & p };
|
||||
// context switch from parent context to `this`-context
|
||||
// execute Fn( Tpl) on top of `this`
|
||||
transfer_t t = ontop_fcontext( fctx, & d, ecv1_context_ontop< Fn >);
|
||||
ecv1_data_t * dp = reinterpret_cast< ecv1_data_t * >( t.data);
|
||||
dp->from->fctx = t.fctx;
|
||||
// parent context resumed
|
||||
return dp->data;
|
||||
}
|
||||
|
||||
virtual void deallocate() noexcept {
|
||||
}
|
||||
|
||||
friend void intrusive_ptr_add_ref( ecv1_activation_record * ar) noexcept {
|
||||
++ar->use_count;
|
||||
}
|
||||
|
||||
friend void intrusive_ptr_release( ecv1_activation_record * ar) noexcept {
|
||||
BOOST_ASSERT( nullptr != ar);
|
||||
if ( 0 == --ar->use_count) {
|
||||
ar->deallocate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BOOST_CONTEXT_DECL ecv1_activation_record_initializer {
|
||||
ecv1_activation_record_initializer() noexcept;
|
||||
~ecv1_activation_record_initializer();
|
||||
};
|
||||
|
||||
template< typename Fn >
|
||||
transfer_t ecv1_context_ontop( transfer_t t) {
|
||||
ecv1_data_t * dp = reinterpret_cast< ecv1_data_t * >( t.data);
|
||||
dp->from->fctx = t.fctx;
|
||||
auto tpl = reinterpret_cast< std::tuple< void *, Fn > * >( dp->data);
|
||||
BOOST_ASSERT( nullptr != tpl);
|
||||
auto data = std::get< 0 >( * tpl);
|
||||
typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 1 >( * tpl) );
|
||||
#if defined(BOOST_NO_CXX17_STD_APPLY)
|
||||
dp->data = boost::context::detail::apply( fn, std::tie( data) );
|
||||
#else
|
||||
dp->data = std::apply( fn, std::tie( data) );
|
||||
#endif
|
||||
return { t.fctx, dp };
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Args >
|
||||
class ecv1_capture_record : public ecv1_activation_record {
|
||||
private:
|
||||
typename std::decay< StackAlloc >::type salloc_;
|
||||
typename std::decay< Fn >::type fn_;
|
||||
std::tuple< typename std::decay< Args >::type ... > args_;
|
||||
ecv1_activation_record * caller_;
|
||||
|
||||
static void destroy( ecv1_capture_record * p) noexcept {
|
||||
typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
|
||||
stack_context sctx = p->sctx;
|
||||
// deallocate activation record
|
||||
p->~ecv1_capture_record();
|
||||
// destroy stack with stack allocator
|
||||
salloc.deallocate( sctx);
|
||||
}
|
||||
|
||||
public:
|
||||
ecv1_capture_record( stack_context sctx, StackAlloc && salloc,
|
||||
fcontext_t fctx,
|
||||
ecv1_activation_record * caller,
|
||||
Fn && fn, Args && ... args) noexcept :
|
||||
ecv1_activation_record{ fctx, sctx },
|
||||
salloc_{ std::forward< StackAlloc >( salloc) },
|
||||
fn_( std::forward< Fn >( fn) ),
|
||||
args_( std::forward< Args >( args) ... ),
|
||||
caller_{ caller } {
|
||||
}
|
||||
|
||||
void deallocate() noexcept override final {
|
||||
destroy( this);
|
||||
}
|
||||
|
||||
void run() {
|
||||
auto data = caller_->resume( nullptr);
|
||||
#if defined(BOOST_NO_CXX17_STD_APPLY)
|
||||
boost::context::detail::apply( fn_, std::tuple_cat( args_, std::tie( data) ) );
|
||||
#else
|
||||
std::apply( fn_, std::tuple_cat( args_, std::tie( data) ) );
|
||||
#endif
|
||||
BOOST_ASSERT_MSG( ! main_ctx, "main-context does not execute activation-record::run()");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace v1 {
|
||||
|
||||
class BOOST_CONTEXT_DECL execution_context {
|
||||
private:
|
||||
// tampoline function
|
||||
// entered if the execution context
|
||||
// is resumed for the first time
|
||||
template< typename AR >
|
||||
static void entry_func( detail::transfer_t t) noexcept {
|
||||
detail::ecv1_data_t * dp = reinterpret_cast< detail::ecv1_data_t * >( t.data);
|
||||
AR * ar = static_cast< AR * >( dp->data);
|
||||
BOOST_ASSERT( nullptr != ar);
|
||||
dp->from->fctx = t.fctx;
|
||||
// start execution of toplevel context-function
|
||||
ar->run();
|
||||
}
|
||||
|
||||
typedef boost::intrusive_ptr< detail::ecv1_activation_record > ptr_t;
|
||||
|
||||
ptr_t ptr_;
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Args >
|
||||
static detail::ecv1_activation_record * create_context( StackAlloc && salloc,
|
||||
Fn && fn, Args && ... args) {
|
||||
typedef detail::ecv1_capture_record<
|
||||
StackAlloc, Fn, Args ...
|
||||
> capture_t;
|
||||
|
||||
auto sctx = salloc.allocate();
|
||||
// reserve space for control structure
|
||||
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
const std::size_t size = sctx.size - sizeof( capture_t);
|
||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( capture_t);
|
||||
#else
|
||||
constexpr std::size_t func_alignment = 64; // alignof( capture_t);
|
||||
constexpr std::size_t func_size = sizeof( capture_t);
|
||||
// reserve space on stack
|
||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
||||
// align sp pointer
|
||||
std::size_t space = func_size + func_alignment;
|
||||
sp = std::align( func_alignment, func_size, sp, space);
|
||||
BOOST_ASSERT( nullptr != sp);
|
||||
// calculate remaining size
|
||||
const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
||||
#endif
|
||||
// create fast-context
|
||||
const detail::fcontext_t fctx = detail::make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
|
||||
BOOST_ASSERT( nullptr != fctx);
|
||||
// get current activation record
|
||||
auto curr = execution_context::current().ptr_;
|
||||
// placment new for control structure on fast-context stack
|
||||
return ::new ( sp) capture_t{
|
||||
sctx, std::forward< StackAlloc >( salloc), fctx, curr.get(), std::forward< Fn >( fn), std::forward< Args >( args) ... };
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Args >
|
||||
static detail::ecv1_activation_record * create_context( preallocated palloc, StackAlloc && salloc,
|
||||
Fn && fn, Args && ... args) {
|
||||
typedef detail::ecv1_capture_record<
|
||||
StackAlloc, Fn, Args ...
|
||||
> capture_t;
|
||||
|
||||
// reserve space for control structure
|
||||
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
const std::size_t size = palloc.size - sizeof( capture_t);
|
||||
void * sp = static_cast< char * >( palloc.sp) - sizeof( capture_t);
|
||||
#else
|
||||
constexpr std::size_t func_alignment = 64; // alignof( capture_t);
|
||||
constexpr std::size_t func_size = sizeof( capture_t);
|
||||
// reserve space on stack
|
||||
void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
|
||||
// align sp pointer
|
||||
std::size_t space = func_size + func_alignment;
|
||||
sp = std::align( func_alignment, func_size, sp, space);
|
||||
BOOST_ASSERT( nullptr != sp);
|
||||
// calculate remaining size
|
||||
const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
|
||||
#endif
|
||||
// create fast-context
|
||||
const detail::fcontext_t fctx = detail::make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
|
||||
BOOST_ASSERT( nullptr != fctx);
|
||||
// get current activation record
|
||||
auto curr = execution_context::current().ptr_;
|
||||
// placment new for control structure on fast-context stack
|
||||
return ::new ( sp) capture_t{
|
||||
palloc.sctx, std::forward< StackAlloc >( salloc), fctx, curr.get(), std::forward< Fn >( fn), std::forward< Args >( args) ... };
|
||||
}
|
||||
|
||||
execution_context() noexcept :
|
||||
// default constructed with current ecv1_activation_record
|
||||
ptr_{ detail::ecv1_activation_record::current() } {
|
||||
}
|
||||
|
||||
public:
|
||||
static execution_context current() noexcept;
|
||||
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
template< typename Fn,
|
||||
typename ... Args,
|
||||
typename = detail::disable_overload< execution_context, Fn >
|
||||
>
|
||||
execution_context( Fn && fn, Args && ... args) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
ptr_{ create_context( segmented_stack(),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Args >( args) ...) } {
|
||||
ptr_->resume( ptr_.get() );
|
||||
}
|
||||
|
||||
template< typename Fn,
|
||||
typename ... Args
|
||||
>
|
||||
execution_context( std::allocator_arg_t, segmented_stack salloc, Fn && fn, Args && ... args) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
ptr_{ create_context( salloc,
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Args >( args) ...) } {
|
||||
ptr_->resume( ptr_.get() );
|
||||
}
|
||||
|
||||
template< typename Fn,
|
||||
typename ... Args
|
||||
>
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, segmented_stack salloc, Fn && fn, Args && ... args) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
ptr_{ create_context( palloc, salloc,
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Args >( args) ...) } {
|
||||
ptr_->resume( ptr_.get() );
|
||||
}
|
||||
#else
|
||||
template< typename Fn,
|
||||
typename ... Args,
|
||||
typename = detail::disable_overload< execution_context, Fn >
|
||||
>
|
||||
execution_context( Fn && fn, Args && ... args) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
ptr_{ create_context( fixedsize_stack(),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Args >( args) ...) } {
|
||||
ptr_->resume( ptr_.get() );
|
||||
}
|
||||
|
||||
template< typename StackAlloc,
|
||||
typename Fn,
|
||||
typename ... Args
|
||||
>
|
||||
execution_context( std::allocator_arg_t, StackAlloc && salloc, Fn && fn, Args && ... args) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
ptr_{ create_context( std::forward< StackAlloc >( salloc),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Args >( args) ...) } {
|
||||
ptr_->resume( ptr_.get() );
|
||||
}
|
||||
|
||||
template< typename StackAlloc,
|
||||
typename Fn,
|
||||
typename ... Args
|
||||
>
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn, Args && ... args) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
ptr_{ create_context( palloc, std::forward< StackAlloc >( salloc),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Args >( args) ...) } {
|
||||
ptr_->resume( ptr_.get() );
|
||||
}
|
||||
#endif
|
||||
|
||||
execution_context( execution_context const& other) noexcept :
|
||||
ptr_{ other.ptr_ } {
|
||||
}
|
||||
|
||||
execution_context( execution_context && other) noexcept :
|
||||
ptr_{ other.ptr_ } {
|
||||
other.ptr_.reset();
|
||||
}
|
||||
|
||||
execution_context & operator=( execution_context const& other) noexcept {
|
||||
// intrusive_ptr<> does not test for self-assignment
|
||||
if ( this == & other) return * this;
|
||||
ptr_ = other.ptr_;
|
||||
return * this;
|
||||
}
|
||||
|
||||
execution_context & operator=( execution_context && other) noexcept {
|
||||
if ( this == & other) return * this;
|
||||
execution_context tmp{ std::move( other) };
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
void * operator()( void * vp = nullptr) {
|
||||
return ptr_->resume( vp);
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
void * operator()( exec_ontop_arg_t, Fn && fn, void * vp = nullptr) {
|
||||
return ptr_->resume_ontop( vp,
|
||||
std::forward< Fn >( fn) );
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return nullptr != ptr_.get();
|
||||
}
|
||||
|
||||
bool operator!() const noexcept {
|
||||
return nullptr == ptr_.get();
|
||||
}
|
||||
|
||||
bool operator<( execution_context const& other) const noexcept {
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
|
||||
if ( nullptr != other.ptr_) {
|
||||
return os << other.ptr_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
void swap( execution_context & other) noexcept {
|
||||
ptr_.swap( other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
void swap( execution_context & l, execution_context & r) noexcept {
|
||||
l.swap( r);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_V1_H
|
||||
@@ -1,486 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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_EXECUTION_CONTEXT_V2_H
|
||||
#define BOOST_CONTEXT_EXECUTION_CONTEXT_V2_H
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX17_STD_APPLY)
|
||||
#include <boost/context/detail/apply.hpp>
|
||||
#endif
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#include <boost/context/detail/exception.hpp>
|
||||
#include <boost/context/detail/exchange.hpp>
|
||||
#include <boost/context/detail/fcontext.hpp>
|
||||
#include <boost/context/detail/tuple.hpp>
|
||||
#include <boost/context/fixedsize_stack.hpp>
|
||||
#include <boost/context/flags.hpp>
|
||||
#include <boost/context/preallocated.hpp>
|
||||
#include <boost/context/segmented_stack.hpp>
|
||||
#include <boost/context/stack_context.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4702)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
transfer_t ecv2_context_unwind( transfer_t);
|
||||
|
||||
template< typename Rec >
|
||||
transfer_t ecv2_context_exit( transfer_t) noexcept;
|
||||
|
||||
template< typename Rec >
|
||||
void ecv2_context_etry( transfer_t) noexcept;
|
||||
|
||||
template< typename Ctx, typename Fn, typename ... Args >
|
||||
transfer_t ecv2_context_ontop( transfer_t);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
fcontext_t ecv2_context_create( StackAlloc &&, Fn &&, Params && ...);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
fcontext_t ecv2_context_create( preallocated, StackAlloc &&, Fn &&, Params && ...);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
class ecv2_record {
|
||||
private:
|
||||
typename std::decay< StackAlloc >::type salloc_;
|
||||
stack_context sctx_;
|
||||
typename std::decay< Fn >::type fn_;
|
||||
std::tuple< typename std::decay< Params >::type ... > params_;
|
||||
|
||||
static void destroy( ecv2_record * p) noexcept {
|
||||
typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
|
||||
stack_context sctx = p->sctx_;
|
||||
// deallocate ecv2_record
|
||||
p->~ecv2_record();
|
||||
// destroy stack with stack allocator
|
||||
salloc.deallocate( sctx);
|
||||
}
|
||||
|
||||
public:
|
||||
ecv2_record( stack_context sctx, StackAlloc && salloc,
|
||||
Fn && fn, Params && ... params) noexcept :
|
||||
salloc_( std::forward< StackAlloc >( salloc)),
|
||||
sctx_( sctx),
|
||||
fn_( std::forward< Fn >( fn) ),
|
||||
params_( std::forward< Params >( params) ... ) {
|
||||
}
|
||||
|
||||
ecv2_record( ecv2_record const&) = delete;
|
||||
ecv2_record & operator=( ecv2_record const&) = delete;
|
||||
|
||||
void deallocate() noexcept {
|
||||
destroy( this);
|
||||
}
|
||||
|
||||
transfer_t run( transfer_t t) {
|
||||
Ctx from{ t.fctx };
|
||||
typename Ctx::args_tpl_t args = std::move( std::get<1>( * static_cast< std::tuple< std::exception_ptr, typename Ctx::args_tpl_t > * >( t.data) ) );
|
||||
auto tpl = std::tuple_cat(
|
||||
params_,
|
||||
std::forward_as_tuple( std::move( from) ),
|
||||
std::move( args) );
|
||||
// invoke context-function
|
||||
#if defined(BOOST_NO_CXX17_STD_APPLY)
|
||||
Ctx cc = boost::context::detail::apply( std::move( fn_), std::move( tpl) );
|
||||
#else
|
||||
Ctx cc = std::apply( std::move( fn_), std::move( tpl) );
|
||||
#endif
|
||||
return { exchange( cc.fctx_, nullptr), nullptr };
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
inline namespace v2 {
|
||||
|
||||
template< typename ... Args >
|
||||
class execution_context {
|
||||
private:
|
||||
friend class ontop_error;
|
||||
|
||||
typedef std::tuple< Args ... > args_tpl_t;
|
||||
typedef std::tuple< execution_context, typename std::decay< Args >::type ... > ret_tpl_t;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
friend class detail::ecv2_record;
|
||||
|
||||
template< typename Ctx, typename Fn, typename ... ArgsT >
|
||||
friend detail::transfer_t detail::ecv2_context_ontop( detail::transfer_t);
|
||||
|
||||
detail::fcontext_t fctx_{ nullptr };
|
||||
|
||||
execution_context( detail::fcontext_t fctx) noexcept :
|
||||
fctx_( fctx) {
|
||||
}
|
||||
|
||||
public:
|
||||
execution_context() noexcept = default;
|
||||
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
// segmented-stack requires to preserve the segments of the `current` context
|
||||
// which is not possible (no global pointer to current context)
|
||||
template< typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, segmented_stack, Fn &&, Params && ...) = delete;
|
||||
|
||||
template< typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Params && ...) = delete;
|
||||
#else
|
||||
template< typename Fn,
|
||||
typename ... Params,
|
||||
typename = detail::disable_overload< execution_context, Fn >
|
||||
>
|
||||
execution_context( Fn && fn, Params && ... params) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
fctx_( detail::ecv2_context_create< execution_context >(
|
||||
fixedsize_stack(),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Params >( params) ... ) ) {
|
||||
}
|
||||
|
||||
template< typename StackAlloc,
|
||||
typename Fn,
|
||||
typename ... Params
|
||||
>
|
||||
execution_context( std::allocator_arg_t, StackAlloc && salloc, Fn && fn, Params && ... params) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
fctx_( detail::ecv2_context_create< execution_context >(
|
||||
std::forward< StackAlloc >( salloc),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Params >( params) ... ) ) {
|
||||
}
|
||||
|
||||
template< typename StackAlloc,
|
||||
typename Fn,
|
||||
typename ... Params
|
||||
>
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn, Params && ... params) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
fctx_( detail::ecv2_context_create< execution_context >(
|
||||
palloc, std::forward< StackAlloc >( salloc),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Params >( params) ... ) ) {
|
||||
}
|
||||
#endif
|
||||
|
||||
~execution_context() {
|
||||
if ( nullptr != fctx_) {
|
||||
detail::ontop_fcontext( detail::exchange( fctx_, nullptr), nullptr, detail::ecv2_context_unwind);
|
||||
}
|
||||
}
|
||||
|
||||
execution_context( execution_context && other) noexcept :
|
||||
fctx_( other.fctx_) {
|
||||
other.fctx_ = nullptr;
|
||||
}
|
||||
|
||||
execution_context & operator=( execution_context && other) noexcept {
|
||||
if ( this != & other) {
|
||||
execution_context tmp = std::move( other);
|
||||
swap( tmp);
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
execution_context( execution_context const& other) noexcept = delete;
|
||||
execution_context & operator=( execution_context const& other) noexcept = delete;
|
||||
|
||||
ret_tpl_t operator()( Args ... args);
|
||||
|
||||
template< typename Fn >
|
||||
ret_tpl_t operator()( exec_ontop_arg_t, Fn && fn, Args ... args);
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return nullptr != fctx_;
|
||||
}
|
||||
|
||||
bool operator!() const noexcept {
|
||||
return nullptr == fctx_;
|
||||
}
|
||||
|
||||
bool operator<( execution_context const& other) const noexcept {
|
||||
return fctx_ < other.fctx_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
|
||||
if ( nullptr != other.fctx_) {
|
||||
return os << other.fctx_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
void swap( execution_context & other) noexcept {
|
||||
std::swap( fctx_, other.fctx_);
|
||||
}
|
||||
};
|
||||
|
||||
class ontop_error : public std::exception {
|
||||
private:
|
||||
detail::fcontext_t fctx_;
|
||||
|
||||
public:
|
||||
ontop_error( detail::fcontext_t fctx) noexcept :
|
||||
fctx_{ fctx } {
|
||||
}
|
||||
|
||||
template< typename ... Args >
|
||||
execution_context< Args ... > get_context() const noexcept {
|
||||
return execution_context< Args ... >{ fctx_ };
|
||||
}
|
||||
};
|
||||
|
||||
template< typename ... Args >
|
||||
typename execution_context< Args ... >::ret_tpl_t
|
||||
execution_context< Args ... >::operator()( Args ... args) {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
args_tpl_t data( std::forward< Args >( args) ... );
|
||||
auto p = std::make_tuple( std::exception_ptr{}, std::move( data) );
|
||||
detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), & p);
|
||||
if ( nullptr != t.data) {
|
||||
auto p = static_cast< std::tuple< std::exception_ptr, args_tpl_t > * >( t.data);
|
||||
std::exception_ptr eptr = std::get< 0 >( * p);
|
||||
if ( eptr) {
|
||||
try {
|
||||
std::rethrow_exception( eptr);
|
||||
} catch (...) {
|
||||
std::throw_with_nested( ontop_error{ t.fctx } );
|
||||
}
|
||||
}
|
||||
data = std::move( std::get< 1 >( * p) );
|
||||
}
|
||||
return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
|
||||
}
|
||||
|
||||
template< typename ... Args >
|
||||
template< typename Fn >
|
||||
typename execution_context< Args ... >::ret_tpl_t
|
||||
execution_context< Args ... >::operator()( exec_ontop_arg_t, Fn && fn, Args ... args) {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
args_tpl_t data{ std::forward< Args >( args) ... };
|
||||
auto p = std::make_tuple( fn, std::make_tuple( std::exception_ptr{}, std::move( data) ) );
|
||||
detail::transfer_t t = detail::ontop_fcontext(
|
||||
detail::exchange( fctx_, nullptr),
|
||||
& p,
|
||||
detail::ecv2_context_ontop< execution_context, Fn, Args ... >);
|
||||
if ( nullptr != t.data) {
|
||||
auto p = static_cast< std::tuple< std::exception_ptr, args_tpl_t > * >( t.data);
|
||||
std::exception_ptr eptr = std::get< 0 >( * p);
|
||||
if ( eptr) {
|
||||
try {
|
||||
std::rethrow_exception( eptr);
|
||||
} catch (...) {
|
||||
std::throw_with_nested( ontop_error{ t.fctx } );
|
||||
}
|
||||
}
|
||||
data = std::move( std::get< 1 >( * p) );
|
||||
}
|
||||
return std::tuple_cat( std::forward_as_tuple( execution_context( t.fctx) ), std::move( data) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template< int N >
|
||||
struct helper {
|
||||
template< typename T >
|
||||
static T convert( T && t) noexcept {
|
||||
return std::forward< T >( t);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct helper< 1 > {
|
||||
template< typename T >
|
||||
static std::tuple< T > convert( T && t) noexcept {
|
||||
return std::make_tuple( std::forward< T >( t) );
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
transfer_t ecv2_context_unwind( transfer_t t) {
|
||||
throw forced_unwind( t.fctx);
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
template< typename Rec >
|
||||
transfer_t ecv2_context_exit( transfer_t t) noexcept {
|
||||
Rec * rec = static_cast< Rec * >( t.data);
|
||||
// destroy context stack
|
||||
rec->deallocate();
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
template< typename Rec >
|
||||
void ecv2_context_etry( transfer_t t_) noexcept {
|
||||
// transfer control structure to the context-stack
|
||||
Rec * rec = static_cast< Rec * >( t_.data);
|
||||
BOOST_ASSERT( nullptr != rec);
|
||||
transfer_t t = { nullptr, nullptr };
|
||||
try {
|
||||
// jump back to `ecv2_context_create()`
|
||||
t = jump_fcontext( t_.fctx, nullptr);
|
||||
// start executing
|
||||
t = rec->run( t);
|
||||
} catch ( forced_unwind const& ex) {
|
||||
t = { ex.fctx, nullptr };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
const_cast< forced_unwind & >( ex).caught = true;
|
||||
#endif
|
||||
}
|
||||
BOOST_ASSERT( nullptr != t.fctx);
|
||||
// destroy context-stack of `this`context on next context
|
||||
ontop_fcontext( t.fctx, rec, ecv2_context_exit< Rec >);
|
||||
BOOST_ASSERT_MSG( false, "context already terminated");
|
||||
}
|
||||
|
||||
template< typename Ctx, typename Fn, typename ... Args >
|
||||
transfer_t ecv2_context_ontop( transfer_t t) {
|
||||
auto p = static_cast< std::tuple< Fn, std::tuple< std::exception_ptr, std::tuple< Args ... > > > * >( t.data);
|
||||
BOOST_ASSERT( nullptr != p);
|
||||
typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
|
||||
auto args = std::move( std::get< 1 >( std::get< 1 >( * p) ) );
|
||||
try {
|
||||
// execute function
|
||||
#if defined(BOOST_NO_CXX17_STD_APPLY)
|
||||
std::get< 1 >( std::get< 1 >( * p) ) = helper< sizeof ... (Args) >::convert( boost::context::detail::apply( fn, std::move( args) ) );
|
||||
#else
|
||||
std::get< 1 >( std::get< 1 >( * p) ) = helper< sizeof ... (Args) >::convert( std::apply( fn, std::move( args) ) );
|
||||
#endif
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
std::get< 0 >( std::get< 1 >( * p) ) = std::current_exception();
|
||||
}
|
||||
// apply returned data
|
||||
return { t.fctx, & std::get< 1 >( * p) };
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
fcontext_t ecv2_context_create( StackAlloc && salloc, Fn && fn, Params && ... params) {
|
||||
typedef ecv2_record< Ctx, StackAlloc, Fn, Params ... > ecv2_record_t;
|
||||
|
||||
auto sctx = salloc.allocate();
|
||||
// reserve space for control structure
|
||||
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
const std::size_t size = sctx.size - sizeof( ecv2_record_t);
|
||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( ecv2_record_t);
|
||||
#else
|
||||
constexpr std::size_t func_alignment = 64; // alignof( ecv2_record_t);
|
||||
constexpr std::size_t func_size = sizeof( ecv2_record_t);
|
||||
// reserve space on stack
|
||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
||||
// align sp pointer
|
||||
std::size_t space = func_size + func_alignment;
|
||||
sp = std::align( func_alignment, func_size, sp, space);
|
||||
BOOST_ASSERT( nullptr != sp);
|
||||
// calculate remaining size
|
||||
const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
||||
#endif
|
||||
// create fast-context
|
||||
const fcontext_t fctx = make_fcontext( sp, size, & ecv2_context_etry< ecv2_record_t >);
|
||||
BOOST_ASSERT( nullptr != fctx);
|
||||
// placment new for control structure on context-stack
|
||||
auto rec = ::new ( sp) ecv2_record_t{
|
||||
sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn), std::forward< Params >( params) ... };
|
||||
// transfer control structure to context-stack
|
||||
return jump_fcontext( fctx, rec).fctx;
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
fcontext_t ecv2_context_create( preallocated palloc, StackAlloc && salloc, Fn && fn, Params && ... params) {
|
||||
typedef ecv2_record< Ctx, StackAlloc, Fn, Params ... > ecv2_record_t;
|
||||
|
||||
// reserve space for control structure
|
||||
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
const std::size_t size = palloc.size - sizeof( ecv2_record_t);
|
||||
void * sp = static_cast< char * >( palloc.sp) - sizeof( ecv2_record_t);
|
||||
#else
|
||||
constexpr std::size_t func_alignment = 64; // alignof( ecv2_record_t);
|
||||
constexpr std::size_t func_size = sizeof( ecv2_record_t);
|
||||
// reserve space on stack
|
||||
void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
|
||||
// align sp pointer
|
||||
std::size_t space = func_size + func_alignment;
|
||||
sp = std::align( func_alignment, func_size, sp, space);
|
||||
BOOST_ASSERT( nullptr != sp);
|
||||
// calculate remaining size
|
||||
const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
|
||||
#endif
|
||||
// create fast-context
|
||||
const fcontext_t fctx = make_fcontext( sp, size, & ecv2_context_etry< ecv2_record_t >);
|
||||
BOOST_ASSERT( nullptr != fctx);
|
||||
// placment new for control structure on context-stack
|
||||
auto rec = ::new ( sp) ecv2_record_t{
|
||||
palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn), std::forward< Params >( params) ... };
|
||||
// transfer control structure to context-stack
|
||||
return jump_fcontext( fctx, rec).fctx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include <boost/context/execution_context_v2_void.ipp>
|
||||
|
||||
inline namespace v2 {
|
||||
|
||||
template< typename ... Args >
|
||||
void swap( execution_context< Args ... > & l, execution_context< Args ... > & r) noexcept {
|
||||
l.swap( r);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_EXECUTION_CONTEXT_V2_H
|
||||
@@ -1,311 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2014.
|
||||
// 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)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
transfer_t ecv2_context_ontop_void( transfer_t);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
fcontext_t ecv2_context_create_void( StackAlloc &&, Fn &&, Params && ...);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
fcontext_t ecv2_context_create_void( preallocated, StackAlloc &&, Fn &&, Params && ...);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
class ecv2_record_void {
|
||||
private:
|
||||
typename std::decay< StackAlloc >::type salloc_;
|
||||
stack_context sctx_;
|
||||
typename std::decay< Fn >::type fn_;
|
||||
std::tuple< typename std::decay< Params >::type ... > params_;
|
||||
|
||||
static void destroy( ecv2_record_void * p) noexcept {
|
||||
typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
|
||||
stack_context sctx = p->sctx_;
|
||||
// deallocate record
|
||||
p->~ecv2_record_void();
|
||||
// destroy stack with stack allocator
|
||||
salloc.deallocate( sctx);
|
||||
}
|
||||
|
||||
public:
|
||||
ecv2_record_void( stack_context sctx, StackAlloc && salloc,
|
||||
Fn && fn, Params && ... params) noexcept :
|
||||
salloc_( std::forward< StackAlloc >( salloc) ),
|
||||
sctx_( sctx),
|
||||
fn_( std::forward< Fn >( fn) ),
|
||||
params_( std::forward< Params >( params) ... ) {
|
||||
}
|
||||
|
||||
ecv2_record_void( ecv2_record_void const&) = delete;
|
||||
ecv2_record_void & operator=( ecv2_record_void const&) = delete;
|
||||
|
||||
void deallocate() noexcept {
|
||||
destroy( this);
|
||||
}
|
||||
|
||||
transfer_t run( transfer_t t) {
|
||||
Ctx from{ t.fctx };
|
||||
// invoke context-function
|
||||
#if defined(BOOST_NO_CXX17_STD_APPLY)
|
||||
Ctx cc = boost::context::detail::apply( fn_, std::tuple_cat( params_, std::forward_as_tuple( std::move( from) ) ) );
|
||||
#else
|
||||
Ctx cc = std::apply( fn_, std::tuple_cat( params_, std::forward_as_tuple( std::move( from) ) ) );
|
||||
#endif
|
||||
return { exchange( cc.fctx_, nullptr), nullptr };
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
inline namespace v2 {
|
||||
|
||||
template<>
|
||||
class execution_context< void > {
|
||||
private:
|
||||
friend class ontop_error;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
friend class detail::ecv2_record_void;
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
friend detail::transfer_t detail::ecv2_context_ontop_void( detail::transfer_t);
|
||||
|
||||
detail::fcontext_t fctx_{ nullptr };
|
||||
|
||||
execution_context( detail::fcontext_t fctx) noexcept :
|
||||
fctx_( fctx) {
|
||||
}
|
||||
|
||||
public:
|
||||
execution_context() noexcept = default;
|
||||
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
// segmented-stack requires to preserve the segments of the `current` context
|
||||
// which is not possible (no global pointer to current context)
|
||||
template< typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, segmented_stack, Fn &&, Params && ...) = delete;
|
||||
|
||||
template< typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Params && ...) = delete;
|
||||
#else
|
||||
template< typename Fn,
|
||||
typename ... Params,
|
||||
typename = detail::disable_overload< execution_context, Fn >
|
||||
>
|
||||
execution_context( Fn && fn, Params && ... params) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
fctx_( detail::ecv2_context_create_void< execution_context >(
|
||||
fixedsize_stack(),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Params >( params) ... ) ) {
|
||||
}
|
||||
|
||||
template< typename StackAlloc,
|
||||
typename Fn,
|
||||
typename ... Params
|
||||
>
|
||||
execution_context( std::allocator_arg_t, StackAlloc && salloc, Fn && fn, Params && ... params) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
fctx_( detail::ecv2_context_create_void< execution_context >(
|
||||
std::forward< StackAlloc >( salloc),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Params >( params) ... ) ) {
|
||||
}
|
||||
|
||||
template< typename StackAlloc,
|
||||
typename Fn,
|
||||
typename ... Params
|
||||
>
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn, Params && ... params) :
|
||||
// deferred execution of fn and its arguments
|
||||
// arguments are stored in std::tuple<>
|
||||
// non-type template parameter pack via std::index_sequence_for<>
|
||||
// preserves the number of arguments
|
||||
// used to extract the function arguments from std::tuple<>
|
||||
fctx_( detail::ecv2_context_create_void< execution_context >(
|
||||
palloc, std::forward< StackAlloc >( salloc),
|
||||
std::forward< Fn >( fn),
|
||||
std::forward< Params >( params) ... ) ) {
|
||||
}
|
||||
#endif
|
||||
|
||||
~execution_context() {
|
||||
if ( nullptr != fctx_) {
|
||||
detail::ontop_fcontext( detail::exchange( fctx_, nullptr), nullptr, detail::ecv2_context_unwind);
|
||||
}
|
||||
}
|
||||
|
||||
execution_context( execution_context && other) noexcept :
|
||||
fctx_( other.fctx_) {
|
||||
other.fctx_ = nullptr;
|
||||
}
|
||||
|
||||
execution_context & operator=( execution_context && other) noexcept {
|
||||
if ( this != & other) {
|
||||
execution_context tmp = std::move( other);
|
||||
swap( tmp);
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
execution_context( execution_context const& other) noexcept = delete;
|
||||
execution_context & operator=( execution_context const& other) noexcept = delete;
|
||||
|
||||
execution_context operator()() {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), nullptr);
|
||||
if ( nullptr != t.data) {
|
||||
std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
|
||||
try {
|
||||
std::rethrow_exception( * eptr);
|
||||
} catch (...) {
|
||||
std::throw_with_nested( ontop_error{ t.fctx } );
|
||||
}
|
||||
}
|
||||
return execution_context( t.fctx);
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
execution_context operator()( exec_ontop_arg_t, Fn && fn) {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
auto p = std::make_tuple( fn, std::exception_ptr{} );
|
||||
detail::transfer_t t = detail::ontop_fcontext(
|
||||
detail::exchange( fctx_, nullptr),
|
||||
& p,
|
||||
detail::ecv2_context_ontop_void< execution_context, Fn >);
|
||||
if ( nullptr != t.data) {
|
||||
std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
|
||||
try {
|
||||
std::rethrow_exception( * eptr);
|
||||
} catch (...) {
|
||||
std::throw_with_nested( ontop_error{ t.fctx } );
|
||||
}
|
||||
}
|
||||
return execution_context( t.fctx);
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return nullptr != fctx_;
|
||||
}
|
||||
|
||||
bool operator!() const noexcept {
|
||||
return nullptr == fctx_;
|
||||
}
|
||||
|
||||
bool operator<( execution_context const& other) const noexcept {
|
||||
return fctx_ < other.fctx_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
|
||||
if ( nullptr != other.fctx_) {
|
||||
return os << other.fctx_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
void swap( execution_context & other) noexcept {
|
||||
std::swap( fctx_, other.fctx_);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
transfer_t ecv2_context_ontop_void( transfer_t t) {
|
||||
auto p = static_cast< std::tuple< Fn, std::exception_ptr > * >( t.data);
|
||||
BOOST_ASSERT( nullptr != p);
|
||||
typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
|
||||
try {
|
||||
// execute function
|
||||
fn();
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
} catch ( abi::__forced_unwind const&) {
|
||||
throw;
|
||||
#endif
|
||||
} catch (...) {
|
||||
std::get< 1 >( * p) = std::current_exception();
|
||||
return { t.fctx, & std::get< 1 >( * p ) };
|
||||
}
|
||||
return { exchange( t.fctx, nullptr), nullptr };
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
fcontext_t ecv2_context_create_void( StackAlloc && salloc, Fn && fn, Params && ... params) {
|
||||
typedef ecv2_record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
|
||||
|
||||
auto sctx = salloc.allocate();
|
||||
// reserve space for control structure
|
||||
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
const std::size_t size = sctx.size - sizeof( record_t);
|
||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
|
||||
#else
|
||||
constexpr std::size_t func_alignment = 64; // alignof( record_t);
|
||||
constexpr std::size_t func_size = sizeof( record_t);
|
||||
// reserve space on stack
|
||||
void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
|
||||
// align sp pointer
|
||||
std::size_t space = func_size + func_alignment;
|
||||
sp = std::align( func_alignment, func_size, sp, space);
|
||||
BOOST_ASSERT( nullptr != sp);
|
||||
// calculate remaining size
|
||||
const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
|
||||
#endif
|
||||
// create fast-context
|
||||
const fcontext_t fctx = make_fcontext( sp, size, & ecv2_context_etry< record_t >);
|
||||
BOOST_ASSERT( nullptr != fctx);
|
||||
// placment new for control structure on context-stack
|
||||
auto rec = ::new ( sp) record_t{
|
||||
sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn), std::forward< Params >( params) ... };
|
||||
// transfer control structure to context-stack
|
||||
return jump_fcontext( fctx, rec).fctx;
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
|
||||
fcontext_t ecv2_context_create_void( preallocated palloc, StackAlloc && salloc, Fn && fn, Params && ... params) {
|
||||
typedef ecv2_record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
|
||||
|
||||
// reserve space for control structure
|
||||
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
|
||||
const std::size_t size = palloc.size - sizeof( record_t);
|
||||
void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
|
||||
#else
|
||||
constexpr std::size_t func_alignment = 64; // alignof( record_t);
|
||||
constexpr std::size_t func_size = sizeof( record_t);
|
||||
// reserve space on stack
|
||||
void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
|
||||
// align sp pointer
|
||||
std::size_t space = func_size + func_alignment;
|
||||
sp = std::align( func_alignment, func_size, sp, space);
|
||||
BOOST_ASSERT( nullptr != sp);
|
||||
// calculate remaining size
|
||||
const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
|
||||
#endif
|
||||
// create fast-context
|
||||
const fcontext_t fctx = make_fcontext( sp, size, & ecv2_context_etry< record_t >);
|
||||
BOOST_ASSERT( nullptr != fctx);
|
||||
// placment new for control structure on context-stack
|
||||
auto rec = ::new ( sp) record_t{
|
||||
palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn), std::forward< Params >( params) ... };
|
||||
// transfer control structure to context-stack
|
||||
return jump_fcontext( fctx, rec).fctx;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2017.
|
||||
// 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(BOOST_USE_UCONTEXT)
|
||||
#include <boost/context/fiber_ucontext.hpp>
|
||||
#elif defined(BOOST_USE_WINFIB)
|
||||
#include <boost/context/fiber_winfib.hpp>
|
||||
#else
|
||||
#include <boost/context/fiber_fcontext.hpp>
|
||||
#endif
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
@@ -20,6 +21,8 @@
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <unwind.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
@@ -31,7 +34,6 @@
|
||||
#include <boost/context/detail/invoke.hpp>
|
||||
#endif
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#include <boost/context/detail/exception.hpp>
|
||||
#include <boost/context/detail/fcontext.hpp>
|
||||
#include <boost/context/detail/tuple.hpp>
|
||||
#include <boost/context/fixedsize_stack.hpp>
|
||||
@@ -49,14 +51,57 @@
|
||||
# pragma warning(disable: 4702)
|
||||
#endif
|
||||
|
||||
constexpr _Unwind_Exception_Class __gxx_fiber_exception_class
|
||||
= ((((((((_Unwind_Exception_Class) 'G'
|
||||
<< 8 | (_Unwind_Exception_Class) 'N')
|
||||
<< 8 | (_Unwind_Exception_Class) 'U')
|
||||
<< 8 | (_Unwind_Exception_Class) 'F')
|
||||
<< 8 | (_Unwind_Exception_Class) 'I')
|
||||
<< 8 | (_Unwind_Exception_Class) 'B')
|
||||
<< 8 | (_Unwind_Exception_Class) 'E')
|
||||
<< 8 | (_Unwind_Exception_Class) 'R');
|
||||
|
||||
#define __GXX_INIT_FIBER_EXCEPTION_CLASS(c) c = __gxx_fiber_exception_class
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
void
|
||||
fiber_unwind_cleanup( _Unwind_Reason_Code code, _Unwind_Exception * exc) {
|
||||
// We only want to be called through _Unwind_DeleteException.
|
||||
if ( _URC_FOREIGN_EXCEPTION_CAUGHT != code) {
|
||||
std::terminate();
|
||||
}
|
||||
delete exc;
|
||||
}
|
||||
|
||||
template< typename Ctx >
|
||||
_Unwind_Reason_Code fiber_unwind_stop( int version,
|
||||
_Unwind_Action actions,
|
||||
_Unwind_Exception_Class exc_class,
|
||||
_Unwind_Exception * exc,
|
||||
_Unwind_Context * context,
|
||||
void * param) {
|
||||
if ( actions & _UA_END_OF_STACK) {
|
||||
_Unwind_DeleteException( exc);
|
||||
Ctx{ param }.resume();
|
||||
}
|
||||
// This is not the destination from. The unwind runtime will call frame's
|
||||
// personality routine with the _UA_FORCE_UNWIND and _UA_CLEANUP_PHASE flag
|
||||
// set in actions, and then unwind to the next frame and call the stop()
|
||||
// function again.
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
template< typename Ctx >
|
||||
transfer_t fiber_unwind( transfer_t t) {
|
||||
throw forced_unwind( t.fctx);
|
||||
return { nullptr, nullptr };
|
||||
_Unwind_Exception * exc = new _Unwind_Exception{};
|
||||
__GXX_INIT_FIBER_EXCEPTION_CLASS( exc->exception_class);
|
||||
exc->exception_cleanup = fiber_unwind_cleanup;
|
||||
_Unwind_ForcedUnwind( exc, fiber_unwind_stop< Ctx >, t.fctx);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
template< typename Rec >
|
||||
@@ -68,22 +113,15 @@ transfer_t fiber_exit( transfer_t t) noexcept {
|
||||
}
|
||||
|
||||
template< typename Rec >
|
||||
void fiber_entry( transfer_t t) noexcept {
|
||||
void fiber_entry( transfer_t t) {
|
||||
// transfer control structure to the context-stack
|
||||
Rec * rec = static_cast< Rec * >( t.data);
|
||||
BOOST_ASSERT( nullptr != t.fctx);
|
||||
BOOST_ASSERT( nullptr != rec);
|
||||
try {
|
||||
// jump back to `create_context()`
|
||||
t = jump_fcontext( t.fctx, nullptr);
|
||||
// start executing
|
||||
t.fctx = rec->run( t.fctx);
|
||||
} catch ( forced_unwind const& ex) {
|
||||
t = { ex.fctx, nullptr };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
const_cast< forced_unwind & >( ex).caught = true;
|
||||
#endif
|
||||
}
|
||||
// jump back to `create_context()`
|
||||
t = jump_fcontext( t.fctx, nullptr);
|
||||
// start executing
|
||||
t.fctx = rec->run( t.fctx);
|
||||
BOOST_ASSERT( nullptr != t.fctx);
|
||||
// destroy context-stack of `this`context on next context
|
||||
ontop_fcontext( t.fctx, rec, fiber_exit< Rec >);
|
||||
@@ -198,7 +236,7 @@ fcontext_t create_fiber2( preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
|
||||
}
|
||||
|
||||
class fiber {
|
||||
class fiber_context {
|
||||
private:
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend class detail::fiber_record;
|
||||
@@ -207,49 +245,49 @@ private:
|
||||
friend detail::transfer_t
|
||||
detail::fiber_ontop( detail::transfer_t);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend fiber
|
||||
callcc( std::allocator_arg_t, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend fiber
|
||||
callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&);
|
||||
template< typename Ctx >
|
||||
friend _Unwind_Reason_Code detail::fiber_unwind_stop( int,
|
||||
_Unwind_Action,
|
||||
_Unwind_Exception_Class,
|
||||
_Unwind_Exception *,
|
||||
_Unwind_Context *,
|
||||
void *);
|
||||
|
||||
detail::fcontext_t fctx_{ nullptr };
|
||||
|
||||
fiber( detail::fcontext_t fctx) noexcept :
|
||||
fiber_context( detail::fcontext_t fctx) noexcept :
|
||||
fctx_{ fctx } {
|
||||
}
|
||||
|
||||
public:
|
||||
fiber() noexcept = default;
|
||||
fiber_context() noexcept = default;
|
||||
|
||||
template< typename Fn, typename = detail::disable_overload< fiber, Fn > >
|
||||
fiber( Fn && fn) :
|
||||
fiber{ std::allocator_arg, fixedsize_stack(), std::forward< Fn >( fn) } {
|
||||
template< typename Fn, typename = detail::disable_overload< fiber_context, Fn > >
|
||||
fiber_context( Fn && fn) :
|
||||
fiber_context{ std::allocator_arg, fixedsize_stack(), std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) :
|
||||
fctx_{ detail::create_fiber1< detail::fiber_record< fiber, StackAlloc, Fn > >(
|
||||
fiber_context( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) :
|
||||
fctx_{ detail::create_fiber1< detail::fiber_record< fiber_context, StackAlloc, Fn > >(
|
||||
std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) :
|
||||
fctx_{ detail::create_fiber2< detail::fiber_record< fiber, StackAlloc, Fn > >(
|
||||
fiber_context( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) :
|
||||
fctx_{ detail::create_fiber2< detail::fiber_record< fiber_context, StackAlloc, Fn > >(
|
||||
palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
template< typename Fn >
|
||||
fiber( std::allocator_arg_t, segmented_stack, Fn &&);
|
||||
fiber_context( std::allocator_arg_t, segmented_stack, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber( std::allocator_arg_t, preallocated, segmented_stack, Fn &&);
|
||||
fiber_context( std::allocator_arg_t, preallocated, segmented_stack, Fn &&);
|
||||
#endif
|
||||
|
||||
~fiber() {
|
||||
~fiber_context() {
|
||||
if ( BOOST_UNLIKELY( nullptr != fctx_) ) {
|
||||
detail::ontop_fcontext(
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
@@ -258,26 +296,26 @@ public:
|
||||
std::exchange( fctx_, nullptr),
|
||||
#endif
|
||||
nullptr,
|
||||
detail::fiber_unwind);
|
||||
detail::fiber_unwind< fiber_context >);
|
||||
}
|
||||
}
|
||||
|
||||
fiber( fiber && other) noexcept {
|
||||
fiber_context( fiber_context && other) noexcept {
|
||||
swap( other);
|
||||
}
|
||||
|
||||
fiber & operator=( fiber && other) noexcept {
|
||||
fiber_context & operator=( fiber_context && other) noexcept {
|
||||
if ( BOOST_LIKELY( this != & other) ) {
|
||||
fiber tmp = std::move( other);
|
||||
fiber_context tmp = std::move( other);
|
||||
swap( tmp);
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
fiber( fiber const& other) noexcept = delete;
|
||||
fiber & operator=( fiber const& other) noexcept = delete;
|
||||
fiber_context( fiber_context const& other) noexcept = delete;
|
||||
fiber_context & operator=( fiber_context const& other) noexcept = delete;
|
||||
|
||||
fiber resume() && {
|
||||
fiber_context resume() && {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
return { detail::jump_fcontext(
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
@@ -289,7 +327,7 @@ public:
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
fiber resume_with( Fn && fn) && {
|
||||
fiber_context resume_with( Fn && fn) && {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
auto p = std::forward< Fn >( fn);
|
||||
return { detail::ontop_fcontext(
|
||||
@@ -299,7 +337,7 @@ public:
|
||||
std::exchange( fctx_, nullptr),
|
||||
#endif
|
||||
& p,
|
||||
detail::fiber_ontop< fiber, decltype(p) >).fctx };
|
||||
detail::fiber_ontop< fiber_context, decltype(p) >).fctx };
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
@@ -310,13 +348,13 @@ public:
|
||||
return nullptr == fctx_;
|
||||
}
|
||||
|
||||
bool operator<( fiber const& other) const noexcept {
|
||||
bool operator<( fiber_context const& other) const noexcept {
|
||||
return fctx_ < other.fctx_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) {
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber_context const& other) {
|
||||
if ( nullptr != other.fctx_) {
|
||||
return os << other.fctx_;
|
||||
} else {
|
||||
@@ -324,18 +362,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void swap( fiber & other) noexcept {
|
||||
void swap( fiber_context & other) noexcept {
|
||||
std::swap( fctx_, other.fctx_);
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
void swap( fiber & l, fiber & r) noexcept {
|
||||
void swap( fiber_context & l, fiber_context & r) noexcept {
|
||||
l.swap( r);
|
||||
}
|
||||
|
||||
typedef fiber fiber_context;
|
||||
|
||||
}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
@@ -1,513 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2017.
|
||||
// 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_FIBER_H
|
||||
#define BOOST_CONTEXT_FIBER_H
|
||||
|
||||
#include <boost/predef.h>
|
||||
#if BOOST_OS_MACOS
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <ucontext.h>
|
||||
}
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <system_error>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
#include <boost/context/detail/exchange.hpp>
|
||||
#endif
|
||||
#include <boost/context/detail/externc.hpp>
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
#include <boost/context/detail/invoke.hpp>
|
||||
#endif
|
||||
#include <boost/context/fixedsize_stack.hpp>
|
||||
#include <boost/context/flags.hpp>
|
||||
#include <boost/context/preallocated.hpp>
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
#include <boost/context/segmented_stack.hpp>
|
||||
#endif
|
||||
#include <boost/context/stack_context.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
// tampoline function
|
||||
// entered if the execution context
|
||||
// is resumed for the first time
|
||||
template< typename Record >
|
||||
static void fiber_entry_func( void * data) noexcept {
|
||||
Record * record = static_cast< Record * >( data);
|
||||
BOOST_ASSERT( nullptr != record);
|
||||
// start execution of toplevel context-function
|
||||
record->run();
|
||||
}
|
||||
|
||||
struct BOOST_CONTEXT_DECL fiber_activation_record {
|
||||
ucontext_t uctx{};
|
||||
stack_context sctx{};
|
||||
bool main_ctx{ true };
|
||||
fiber_activation_record * from{ nullptr };
|
||||
std::function< fiber_activation_record*(fiber_activation_record*&) > ontop{};
|
||||
bool terminated{ false };
|
||||
bool force_unwind{ false };
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
void * fake_stack{ nullptr };
|
||||
void * stack_bottom{ nullptr };
|
||||
std::size_t stack_size{ 0 };
|
||||
#endif
|
||||
|
||||
static fiber_activation_record *& current() noexcept;
|
||||
|
||||
// used for toplevel-context
|
||||
// (e.g. main context, thread-entry context)
|
||||
fiber_activation_record() {
|
||||
if ( BOOST_UNLIKELY( 0 != ::getcontext( & uctx) ) ) {
|
||||
throw std::system_error(
|
||||
std::error_code( errno, std::system_category() ),
|
||||
"getcontext() failed");
|
||||
}
|
||||
}
|
||||
|
||||
fiber_activation_record( stack_context sctx_) noexcept :
|
||||
sctx( sctx_ ),
|
||||
main_ctx( false ) {
|
||||
}
|
||||
|
||||
virtual ~fiber_activation_record() {
|
||||
}
|
||||
|
||||
fiber_activation_record( fiber_activation_record const&) = delete;
|
||||
fiber_activation_record & operator=( fiber_activation_record const&) = delete;
|
||||
|
||||
bool is_main_context() const noexcept {
|
||||
return main_ctx;
|
||||
}
|
||||
|
||||
fiber_activation_record * resume() {
|
||||
from = current();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
current() = this;
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
// adjust segmented stack properties
|
||||
__splitstack_getcontext( from->sctx.segments_ctx);
|
||||
__splitstack_setcontext( sctx.segments_ctx);
|
||||
#endif
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
if ( terminated) {
|
||||
__sanitizer_start_switch_fiber( nullptr, stack_bottom, stack_size);
|
||||
} else {
|
||||
__sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size);
|
||||
}
|
||||
#endif
|
||||
// context switch from parent context to `this`-context
|
||||
::swapcontext( & from->uctx, & uctx);
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_finish_switch_fiber( current()->fake_stack,
|
||||
(const void **) & current()->from->stack_bottom,
|
||||
& current()->from->stack_size);
|
||||
#endif
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( current()->from, nullptr);
|
||||
#else
|
||||
return std::exchange( current()->from, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
fiber_activation_record * resume_with( Fn && fn) {
|
||||
from = current();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
// returned by fiber::current()
|
||||
current() = this;
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
current()->ontop = std::bind(
|
||||
[](typename std::decay< Fn >::type & fn, fiber_activation_record *& ptr){
|
||||
Ctx c{ ptr };
|
||||
c = fn( std::move( c) );
|
||||
if ( ! c) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.ptr_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.ptr_, nullptr);
|
||||
#endif
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1);
|
||||
#else
|
||||
current()->ontop = [fn=std::forward<Fn>(fn)](fiber_activation_record *& ptr){
|
||||
Ctx c{ ptr };
|
||||
c = fn( std::move( c) );
|
||||
if ( ! c) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.ptr_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.ptr_, nullptr);
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
// adjust segmented stack properties
|
||||
__splitstack_getcontext( from->sctx.segments_ctx);
|
||||
__splitstack_setcontext( sctx.segments_ctx);
|
||||
#endif
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size);
|
||||
#endif
|
||||
// context switch from parent context to `this`-context
|
||||
::swapcontext( & from->uctx, & uctx);
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_finish_switch_fiber( current()->fake_stack,
|
||||
(const void **) & current()->from->stack_bottom,
|
||||
& current()->from->stack_size);
|
||||
#endif
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( current()->from, nullptr);
|
||||
#else
|
||||
return std::exchange( current()->from, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void deallocate() noexcept {
|
||||
}
|
||||
};
|
||||
|
||||
struct BOOST_CONTEXT_DECL fiber_activation_record_initializer {
|
||||
fiber_activation_record_initializer() noexcept;
|
||||
~fiber_activation_record_initializer();
|
||||
};
|
||||
|
||||
struct forced_unwind {
|
||||
fiber_activation_record * from{ nullptr };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
bool caught{ false };
|
||||
#endif
|
||||
|
||||
forced_unwind( fiber_activation_record * from_) noexcept :
|
||||
from{ from_ } {
|
||||
}
|
||||
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
~forced_unwind() {
|
||||
BOOST_ASSERT( caught);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
class fiber_capture_record : public fiber_activation_record {
|
||||
private:
|
||||
typename std::decay< StackAlloc >::type salloc_;
|
||||
typename std::decay< Fn >::type fn_;
|
||||
|
||||
static void destroy( fiber_capture_record * p) noexcept {
|
||||
typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
|
||||
stack_context sctx = p->sctx;
|
||||
// deallocate activation record
|
||||
p->~fiber_capture_record();
|
||||
// destroy stack with stack allocator
|
||||
salloc.deallocate( sctx);
|
||||
}
|
||||
|
||||
public:
|
||||
fiber_capture_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept :
|
||||
fiber_activation_record{ sctx },
|
||||
salloc_{ std::forward< StackAlloc >( salloc) },
|
||||
fn_( std::forward< Fn >( fn) ) {
|
||||
}
|
||||
|
||||
void deallocate() noexcept override final {
|
||||
BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) );
|
||||
destroy( this);
|
||||
}
|
||||
|
||||
void run() {
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_finish_switch_fiber( fake_stack,
|
||||
(const void **) & from->stack_bottom,
|
||||
& from->stack_size);
|
||||
#endif
|
||||
Ctx c{ from };
|
||||
try {
|
||||
// invoke context-function
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
c = boost::context::detail::invoke( fn_, std::move( c) );
|
||||
#else
|
||||
c = std::invoke( fn_, std::move( c) );
|
||||
#endif
|
||||
} catch ( forced_unwind const& ex) {
|
||||
c = Ctx{ ex.from };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
const_cast< forced_unwind & >( ex).caught = true;
|
||||
#endif
|
||||
}
|
||||
// this context has finished its task
|
||||
from = nullptr;
|
||||
ontop = nullptr;
|
||||
terminated = true;
|
||||
force_unwind = false;
|
||||
std::move( c).resume();
|
||||
BOOST_ASSERT_MSG( false, "fiber already terminated");
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
static fiber_activation_record * create_fiber1( StackAlloc && salloc, Fn && fn) {
|
||||
typedef fiber_capture_record< Ctx, StackAlloc, Fn > capture_t;
|
||||
|
||||
auto sctx = salloc.allocate();
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
capture_t * record = new ( storage) capture_t{
|
||||
sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// stack bottom
|
||||
void * stack_bottom = reinterpret_cast< void * >(
|
||||
reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) );
|
||||
// create user-context
|
||||
if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) {
|
||||
record->~capture_t();
|
||||
salloc.deallocate( sctx);
|
||||
throw std::system_error(
|
||||
std::error_code( errno, std::system_category() ),
|
||||
"getcontext() failed");
|
||||
}
|
||||
record->uctx.uc_stack.ss_sp = stack_bottom;
|
||||
// 64byte gap between control structure and stack top
|
||||
record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) -
|
||||
reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64);
|
||||
record->uctx.uc_link = nullptr;
|
||||
::makecontext( & record->uctx, ( void (*)() ) & fiber_entry_func< capture_t >, 1, record);
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
record->stack_bottom = record->uctx.uc_stack.ss_sp;
|
||||
record->stack_size = record->uctx.uc_stack.ss_size;
|
||||
#endif
|
||||
return record;
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
static fiber_activation_record * create_fiber2( preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
typedef fiber_capture_record< Ctx, StackAlloc, Fn > capture_t;
|
||||
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
capture_t * record = new ( storage) capture_t{
|
||||
palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// stack bottom
|
||||
void * stack_bottom = reinterpret_cast< void * >(
|
||||
reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) );
|
||||
// create user-context
|
||||
if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) {
|
||||
record->~capture_t();
|
||||
salloc.deallocate( palloc.sctx);
|
||||
throw std::system_error(
|
||||
std::error_code( errno, std::system_category() ),
|
||||
"getcontext() failed");
|
||||
}
|
||||
record->uctx.uc_stack.ss_sp = stack_bottom;
|
||||
// 64byte gap between control structure and stack top
|
||||
record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) -
|
||||
reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64);
|
||||
record->uctx.uc_link = nullptr;
|
||||
::makecontext( & record->uctx, ( void (*)() ) & fiber_entry_func< capture_t >, 1, record);
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
record->stack_bottom = record->uctx.uc_stack.ss_sp;
|
||||
record->stack_size = record->uctx.uc_stack.ss_size;
|
||||
#endif
|
||||
return record;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class BOOST_CONTEXT_DECL fiber {
|
||||
private:
|
||||
friend struct detail::fiber_activation_record;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend class detail::fiber_capture_record;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend detail::fiber_activation_record * detail::create_fiber1( StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend detail::fiber_activation_record * detail::create_fiber2( preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend fiber
|
||||
callcc( std::allocator_arg_t, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend fiber
|
||||
callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
detail::fiber_activation_record * ptr_{ nullptr };
|
||||
|
||||
fiber( detail::fiber_activation_record * ptr) noexcept :
|
||||
ptr_{ ptr } {
|
||||
}
|
||||
|
||||
public:
|
||||
fiber() = default;
|
||||
|
||||
template< typename Fn, typename = detail::disable_overload< fiber, Fn > >
|
||||
fiber( Fn && fn) :
|
||||
fiber{
|
||||
std::allocator_arg,
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
segmented_stack(),
|
||||
#else
|
||||
fixedsize_stack(),
|
||||
#endif
|
||||
std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) :
|
||||
ptr_{ detail::create_fiber1< fiber >(
|
||||
std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) :
|
||||
ptr_{ detail::create_fiber2< fiber >(
|
||||
palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
~fiber() {
|
||||
if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) {
|
||||
if ( BOOST_LIKELY( ! ptr_->terminated) ) {
|
||||
ptr_->force_unwind = true;
|
||||
ptr_->resume();
|
||||
BOOST_ASSERT( ptr_->terminated);
|
||||
}
|
||||
ptr_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
fiber( fiber const&) = delete;
|
||||
fiber & operator=( fiber const&) = delete;
|
||||
|
||||
fiber( fiber && other) noexcept {
|
||||
swap( other);
|
||||
}
|
||||
|
||||
fiber & operator=( fiber && other) noexcept {
|
||||
if ( BOOST_LIKELY( this != & other) ) {
|
||||
fiber tmp = std::move( other);
|
||||
swap( tmp);
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
fiber resume() && {
|
||||
BOOST_ASSERT( nullptr != ptr_);
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::fiber_activation_record * ptr = detail::exchange( ptr_, nullptr)->resume();
|
||||
#else
|
||||
detail::fiber_activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
|
||||
#endif
|
||||
if ( BOOST_UNLIKELY( detail::fiber_activation_record::current()->force_unwind) ) {
|
||||
throw detail::forced_unwind{ ptr};
|
||||
} else if ( BOOST_UNLIKELY( nullptr != detail::fiber_activation_record::current()->ontop) ) {
|
||||
ptr = detail::fiber_activation_record::current()->ontop( ptr);
|
||||
detail::fiber_activation_record::current()->ontop = nullptr;
|
||||
}
|
||||
return { ptr };
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
fiber resume_with( Fn && fn) && {
|
||||
BOOST_ASSERT( nullptr != ptr_);
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::fiber_activation_record * ptr =
|
||||
detail::exchange( ptr_, nullptr)->resume_with< fiber >( std::forward< Fn >( fn) );
|
||||
#else
|
||||
detail::fiber_activation_record * ptr =
|
||||
std::exchange( ptr_, nullptr)->resume_with< fiber >( std::forward< Fn >( fn) );
|
||||
#endif
|
||||
if ( BOOST_UNLIKELY( detail::fiber_activation_record::current()->force_unwind) ) {
|
||||
throw detail::forced_unwind{ ptr};
|
||||
} else if ( BOOST_UNLIKELY( nullptr != detail::fiber_activation_record::current()->ontop) ) {
|
||||
ptr = detail::fiber_activation_record::current()->ontop( ptr);
|
||||
detail::fiber_activation_record::current()->ontop = nullptr;
|
||||
}
|
||||
return { ptr };
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return nullptr != ptr_ && ! ptr_->terminated;
|
||||
}
|
||||
|
||||
bool operator!() const noexcept {
|
||||
return nullptr == ptr_ || ptr_->terminated;
|
||||
}
|
||||
|
||||
bool operator<( fiber const& other) const noexcept {
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) {
|
||||
if ( nullptr != other.ptr_) {
|
||||
return os << other.ptr_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
void swap( fiber & other) noexcept {
|
||||
std::swap( ptr_, other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
void swap( fiber & l, fiber & r) noexcept {
|
||||
l.swap( r);
|
||||
}
|
||||
|
||||
typedef fiber fiber_context;
|
||||
|
||||
}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_FIBER_H
|
||||
@@ -1,446 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2017.
|
||||
// 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_FIBER_H
|
||||
#define BOOST_CONTEXT_FIBER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <system_error>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
#include <boost/context/detail/exchange.hpp>
|
||||
#endif
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
#include <boost/context/detail/invoke.hpp>
|
||||
#endif
|
||||
#include <boost/context/fixedsize_stack.hpp>
|
||||
#include <boost/context/flags.hpp>
|
||||
#include <boost/context/preallocated.hpp>
|
||||
#include <boost/context/stack_context.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4702)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
|
||||
// tampoline function
|
||||
// entered if the execution context
|
||||
// is resumed for the first time
|
||||
template< typename Record >
|
||||
static VOID WINAPI fiber_entry_func( LPVOID data) noexcept {
|
||||
Record * record = static_cast< Record * >( data);
|
||||
BOOST_ASSERT( nullptr != record);
|
||||
// start execution of toplevel context-function
|
||||
record->run();
|
||||
}
|
||||
|
||||
struct BOOST_CONTEXT_DECL fiber_activation_record {
|
||||
LPVOID fiber{ nullptr };
|
||||
stack_context sctx{};
|
||||
bool main_ctx{ true };
|
||||
fiber_activation_record * from{ nullptr };
|
||||
std::function< fiber_activation_record*(fiber_activation_record*&) > ontop{};
|
||||
bool terminated{ false };
|
||||
bool force_unwind{ false };
|
||||
|
||||
static fiber_activation_record *& current() noexcept;
|
||||
|
||||
// used for toplevel-context
|
||||
// (e.g. main context, thread-entry context)
|
||||
fiber_activation_record() noexcept {
|
||||
#if ( _WIN32_WINNT > 0x0600)
|
||||
if ( ::IsThreadAFiber() ) {
|
||||
fiber = ::GetCurrentFiber();
|
||||
} else {
|
||||
fiber = ::ConvertThreadToFiber( nullptr);
|
||||
}
|
||||
#else
|
||||
fiber = ::ConvertThreadToFiber( nullptr);
|
||||
if ( BOOST_UNLIKELY( nullptr == fiber) ) {
|
||||
BOOST_ASSERT( ERROR_ALREADY_FIBER == ::GetLastError());
|
||||
fiber = ::GetCurrentFiber();
|
||||
BOOST_ASSERT( nullptr != fiber);
|
||||
BOOST_ASSERT( reinterpret_cast< LPVOID >( 0x1E00) != fiber);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
fiber_activation_record( stack_context sctx_) noexcept :
|
||||
sctx{ sctx_ },
|
||||
main_ctx{ false } {
|
||||
}
|
||||
|
||||
virtual ~fiber_activation_record() {
|
||||
if ( BOOST_UNLIKELY( main_ctx) ) {
|
||||
::ConvertFiberToThread();
|
||||
} else {
|
||||
::DeleteFiber( fiber);
|
||||
}
|
||||
}
|
||||
|
||||
fiber_activation_record( fiber_activation_record const&) = delete;
|
||||
fiber_activation_record & operator=( fiber_activation_record const&) = delete;
|
||||
|
||||
bool is_main_context() const noexcept {
|
||||
return main_ctx;
|
||||
}
|
||||
|
||||
fiber_activation_record * resume() {
|
||||
from = current();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
current() = this;
|
||||
// context switch from parent context to `this`-context
|
||||
// context switch
|
||||
::SwitchToFiber( fiber);
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return detail::exchange( current()->from, nullptr);
|
||||
#else
|
||||
return std::exchange( current()->from, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
fiber_activation_record * resume_with( Fn && fn) {
|
||||
from = current();
|
||||
// store `this` in static, thread local pointer
|
||||
// `this` will become the active (running) context
|
||||
// returned by fiber::current()
|
||||
current() = this;
|
||||
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
current()->ontop = std::bind(
|
||||
[](typename std::decay< Fn >::type & fn, fiber_activation_record *& ptr){
|
||||
Ctx c{ ptr };
|
||||
c = fn( std::move( c) );
|
||||
if ( ! c) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.ptr_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.ptr_, nullptr);
|
||||
#endif
|
||||
},
|
||||
std::forward< Fn >( fn),
|
||||
std::placeholders::_1);
|
||||
#else
|
||||
current()->ontop = [fn=std::forward<Fn>(fn)](fiber_activation_record *& ptr){
|
||||
Ctx c{ ptr };
|
||||
c = fn( std::move( c) );
|
||||
if ( ! c) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return exchange( c.ptr_, nullptr);
|
||||
#else
|
||||
return std::exchange( c.ptr_, nullptr);
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
// context switch
|
||||
::SwitchToFiber( fiber);
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return detail::exchange( current()->from, nullptr);
|
||||
#else
|
||||
return std::exchange( current()->from, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void deallocate() noexcept {
|
||||
}
|
||||
};
|
||||
|
||||
struct BOOST_CONTEXT_DECL fiber_activation_record_initializer {
|
||||
fiber_activation_record_initializer() noexcept;
|
||||
~fiber_activation_record_initializer();
|
||||
};
|
||||
|
||||
struct forced_unwind {
|
||||
fiber_activation_record * from{ nullptr };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
bool caught{ false };
|
||||
#endif
|
||||
|
||||
explicit forced_unwind( fiber_activation_record * from_) :
|
||||
from{ from_ } {
|
||||
}
|
||||
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
~forced_unwind() {
|
||||
BOOST_ASSERT( caught);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
class fiber_capture_record : public fiber_activation_record {
|
||||
private:
|
||||
typename std::decay< StackAlloc >::type salloc_;
|
||||
typename std::decay< Fn >::type fn_;
|
||||
|
||||
static void destroy( fiber_capture_record * p) noexcept {
|
||||
typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
|
||||
stack_context sctx = p->sctx;
|
||||
// deallocate activation record
|
||||
p->~fiber_capture_record();
|
||||
// destroy stack with stack allocator
|
||||
salloc.deallocate( sctx);
|
||||
}
|
||||
|
||||
public:
|
||||
fiber_capture_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept :
|
||||
fiber_activation_record( sctx),
|
||||
salloc_( std::forward< StackAlloc >( salloc)),
|
||||
fn_( std::forward< Fn >( fn) ) {
|
||||
}
|
||||
|
||||
void deallocate() noexcept override final {
|
||||
BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) );
|
||||
destroy( this);
|
||||
}
|
||||
|
||||
void run() {
|
||||
Ctx c{ from };
|
||||
try {
|
||||
// invoke context-function
|
||||
#if defined(BOOST_NO_CXX17_STD_INVOKE)
|
||||
c = boost::context::detail::invoke( fn_, std::move( c) );
|
||||
#else
|
||||
c = std::invoke( fn_, std::move( c) );
|
||||
#endif
|
||||
} catch ( forced_unwind const& ex) {
|
||||
c = Ctx{ ex.from };
|
||||
#ifndef BOOST_ASSERT_IS_VOID
|
||||
const_cast< forced_unwind & >( ex).caught = true;
|
||||
#endif
|
||||
}
|
||||
// this context has finished its task
|
||||
from = nullptr;
|
||||
ontop = nullptr;
|
||||
terminated = true;
|
||||
force_unwind = false;
|
||||
std::move( c).resume();
|
||||
BOOST_ASSERT_MSG( false, "fiber already terminated");
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
static fiber_activation_record * create_fiber1( StackAlloc && salloc, Fn && fn) {
|
||||
typedef fiber_capture_record< Ctx, StackAlloc, Fn > capture_t;
|
||||
|
||||
auto sctx = salloc.allocate();
|
||||
BOOST_ASSERT( ( sizeof( capture_t) ) < sctx.size);
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
capture_t * record = new ( storage) capture_t{
|
||||
sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// create user-context
|
||||
record->fiber = ::CreateFiber( sctx.size, & detail::fiber_entry_func< capture_t >, record);
|
||||
return record;
|
||||
}
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
static fiber_activation_record * create_fiber2( preallocated palloc, StackAlloc && salloc, Fn && fn) {
|
||||
typedef fiber_capture_record< Ctx, StackAlloc, Fn > capture_t;
|
||||
|
||||
BOOST_ASSERT( ( sizeof( capture_t) ) < palloc.size);
|
||||
// reserve space for control structure
|
||||
void * storage = reinterpret_cast< void * >(
|
||||
( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) )
|
||||
& ~ static_cast< uintptr_t >( 0xff) );
|
||||
// placment new for control structure on context stack
|
||||
capture_t * record = new ( storage) capture_t{
|
||||
palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) };
|
||||
// create user-context
|
||||
record->fiber = ::CreateFiber( palloc.sctx.size, & detail::fiber_entry_func< capture_t >, record);
|
||||
return record;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class BOOST_CONTEXT_DECL fiber {
|
||||
private:
|
||||
friend struct detail::fiber_activation_record;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend class detail::fiber_capture_record;
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend detail::fiber_activation_record * detail::create_fiber1( StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename Ctx, typename StackAlloc, typename Fn >
|
||||
friend detail::fiber_activation_record * detail::create_fiber2( preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend fiber
|
||||
callcc( std::allocator_arg_t, StackAlloc &&, Fn &&);
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
friend fiber
|
||||
callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&);
|
||||
|
||||
detail::fiber_activation_record * ptr_{ nullptr };
|
||||
|
||||
fiber( detail::fiber_activation_record * ptr) noexcept :
|
||||
ptr_{ ptr } {
|
||||
}
|
||||
|
||||
public:
|
||||
fiber() = default;
|
||||
|
||||
template< typename Fn, typename = detail::disable_overload< fiber, Fn > >
|
||||
fiber( Fn && fn) :
|
||||
fiber{ std::allocator_arg,
|
||||
fixedsize_stack(),
|
||||
std::forward< Fn >( fn) } {
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) :
|
||||
ptr_{ detail::create_fiber1< fiber >(
|
||||
std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {;
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) :
|
||||
ptr_{ detail::create_fiber2< fiber >(
|
||||
palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {
|
||||
}
|
||||
|
||||
~fiber() {
|
||||
if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) {
|
||||
if ( BOOST_LIKELY( ! ptr_->terminated) ) {
|
||||
ptr_->force_unwind = true;
|
||||
ptr_->resume();
|
||||
BOOST_ASSERT( ptr_->terminated);
|
||||
}
|
||||
ptr_->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
fiber( fiber const&) = delete;
|
||||
fiber & operator=( fiber const&) = delete;
|
||||
|
||||
fiber( fiber && other) noexcept {
|
||||
swap( other);
|
||||
}
|
||||
|
||||
fiber & operator=( fiber && other) noexcept {
|
||||
if ( BOOST_LIKELY( this != & other) ) {
|
||||
fiber tmp = std::move( other);
|
||||
swap( tmp);
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
fiber resume() && {
|
||||
BOOST_ASSERT( nullptr != ptr_);
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::fiber_activation_record * ptr = detail::exchange( ptr_, nullptr)->resume();
|
||||
#else
|
||||
detail::fiber_activation_record * ptr = std::exchange( ptr_, nullptr)->resume();
|
||||
#endif
|
||||
if ( BOOST_UNLIKELY( detail::fiber_activation_record::current()->force_unwind) ) {
|
||||
throw detail::forced_unwind{ ptr};
|
||||
} else if ( BOOST_UNLIKELY( nullptr != detail::fiber_activation_record::current()->ontop) ) {
|
||||
ptr = detail::fiber_activation_record::current()->ontop( ptr);
|
||||
detail::fiber_activation_record::current()->ontop = nullptr;
|
||||
}
|
||||
return { ptr };
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
fiber resume_with( Fn && fn) && {
|
||||
BOOST_ASSERT( nullptr != ptr_);
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::fiber_activation_record * ptr =
|
||||
detail::exchange( ptr_, nullptr)->resume_with< fiber >( std::forward< Fn >( fn) );
|
||||
#else
|
||||
detail::fiber_activation_record * ptr =
|
||||
std::exchange( ptr_, nullptr)->resume_with< fiber >( std::forward< Fn >( fn) );
|
||||
#endif
|
||||
if ( BOOST_UNLIKELY( detail::fiber_activation_record::current()->force_unwind) ) {
|
||||
throw detail::forced_unwind{ ptr};
|
||||
} else if ( BOOST_UNLIKELY( nullptr != detail::fiber_activation_record::current()->ontop) ) {
|
||||
ptr = detail::fiber_activation_record::current()->ontop( ptr);
|
||||
detail::fiber_activation_record::current()->ontop = nullptr;
|
||||
}
|
||||
return { ptr };
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return nullptr != ptr_ && ! ptr_->terminated;
|
||||
}
|
||||
|
||||
bool operator!() const noexcept {
|
||||
return nullptr == ptr_ || ptr_->terminated;
|
||||
}
|
||||
|
||||
bool operator<( fiber const& other) const noexcept {
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) {
|
||||
if ( nullptr != other.ptr_) {
|
||||
return os << other.ptr_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
void swap( fiber & other) noexcept {
|
||||
std::swap( ptr_, other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
void swap( fiber & l, fiber & r) noexcept {
|
||||
l.swap( r);
|
||||
}
|
||||
|
||||
typedef fiber fiber_context;
|
||||
|
||||
}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_FIBER_H
|
||||
36
patch/libgcc-fiber_context-unwind.patch
Normal file
36
patch/libgcc-fiber_context-unwind.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
diff -pur a/libstdc++-v3/libsupc++/eh_personality.cc b/libstdc++-v3/libsupc++/eh_personality.cc
|
||||
--- a/libstdc++-v3/libsupc++/eh_personality.cc 2018-01-03 11:03:58.000000000 +0100
|
||||
+++ b/libstdc++-v3/libsupc++/eh_personality.cc 2019-04-08 13:59:37.637143970 +0200
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <cxxabi.h>
|
||||
#include "unwind-cxx.h"
|
||||
|
||||
-
|
||||
using namespace __cxxabiv1;
|
||||
|
||||
#include "unwind-pe.h"
|
||||
@@ -590,14 +589,16 @@ PERSONALITY_FUNCTION (int version,
|
||||
|
||||
// Null catch type is a catch-all handler; we can catch foreign
|
||||
// exceptions with this. Otherwise we must match types.
|
||||
- if (! catch_type
|
||||
- || (throw_type
|
||||
- && get_adjusted_ptr (catch_type, throw_type,
|
||||
- &thrown_ptr)))
|
||||
- {
|
||||
- saw_handler = true;
|
||||
- break;
|
||||
- }
|
||||
+ if (-1 != xh->unwindHeader.exception_class)
|
||||
+ {
|
||||
+ if (! catch_type || (throw_type
|
||||
+ && get_adjusted_ptr (catch_type, throw_type,
|
||||
+ &thrown_ptr)))
|
||||
+ {
|
||||
+ saw_handler = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
# 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/callcc
|
||||
: requirements
|
||||
<library>/boost/chrono//boost_chrono
|
||||
<library>/boost/context//boost_context
|
||||
<library>/boost/program_options//boost_program_options
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<link>static
|
||||
<optimization>speed
|
||||
<threading>multi
|
||||
<variant>release
|
||||
<cxxflags>-DBOOST_DISABLE_ASSERTS
|
||||
;
|
||||
|
||||
exe performance
|
||||
: performance.cpp
|
||||
;
|
||||
@@ -1,102 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/context/continuation.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "../clock.hpp"
|
||||
#include "../cycle.hpp"
|
||||
|
||||
boost::uint64_t jobs = 1000000;
|
||||
|
||||
namespace ctx = boost::context;
|
||||
|
||||
static ctx::continuation foo( ctx::continuation && c) {
|
||||
while ( true) {
|
||||
c = c.resume();
|
||||
}
|
||||
return std::move( c);
|
||||
}
|
||||
|
||||
duration_type measure_time() {
|
||||
// cache warum-up
|
||||
ctx::continuation c = ctx::callcc( foo);
|
||||
c = c.resume();
|
||||
|
||||
time_point_type start( clock_type::now() );
|
||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||
c = c.resume();
|
||||
}
|
||||
duration_type total = clock_type::now() - start;
|
||||
total -= overhead_clock(); // overhead of measurement
|
||||
total /= jobs; // loops
|
||||
total /= 2; // 2x jump_fcontext
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
#ifdef BOOST_CONTEXT_CYCLE
|
||||
cycle_type measure_cycles() {
|
||||
// cache warum-up
|
||||
ctx::fixedsize_stack alloc;
|
||||
ctx::continuation c = ctx::callcc( std::allocator_arg, alloc, foo);
|
||||
c = c.resume();
|
||||
|
||||
cycle_type start( cycles() );
|
||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||
c = c.resume();
|
||||
}
|
||||
cycle_type total = cycles() - start;
|
||||
total -= overhead_cycle(); // overhead of measurement
|
||||
total /= jobs; // loops
|
||||
total /= 2; // 2x jump_fcontext
|
||||
|
||||
return total;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main( int argc, char * argv[]) {
|
||||
try {
|
||||
boost::program_options::options_description desc("allowed options");
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
boost::program_options::store(
|
||||
boost::program_options::parse_command_line(
|
||||
argc,
|
||||
argv,
|
||||
desc),
|
||||
vm);
|
||||
boost::program_options::notify( vm);
|
||||
|
||||
if ( vm.count("help") ) {
|
||||
std::cout << desc << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
boost::uint64_t res = measure_time().count();
|
||||
std::cout << "continuation: average of " << res << " nano seconds" << std::endl;
|
||||
#ifdef BOOST_CONTEXT_CYCLE
|
||||
res = measure_cycles();
|
||||
std::cout << "continuation: average of " << res << " cpu cycles" << 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;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
# 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/execution_context_v2
|
||||
: requirements
|
||||
<library>/boost/chrono//boost_chrono
|
||||
<library>/boost/context//boost_context
|
||||
<library>/boost/program_options//boost_program_options
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<link>static
|
||||
<optimization>speed
|
||||
<threading>multi
|
||||
<variant>release
|
||||
<cxxflags>-DBOOST_DISABLE_ASSERTS
|
||||
;
|
||||
|
||||
exe performance
|
||||
: performance.cpp
|
||||
;
|
||||
@@ -1,100 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/context/execution_context.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "../clock.hpp"
|
||||
#include "../cycle.hpp"
|
||||
|
||||
boost::uint64_t jobs = 1000000;
|
||||
|
||||
static boost::context::execution_context< void > foo( boost::context::execution_context< void > && ctx) {
|
||||
while ( true) {
|
||||
ctx = ctx();
|
||||
}
|
||||
return std::move( ctx);
|
||||
}
|
||||
|
||||
duration_type measure_time() {
|
||||
// cache warum-up
|
||||
boost::context::execution_context< void > ctx( foo);
|
||||
ctx = ctx();
|
||||
|
||||
time_point_type start( clock_type::now() );
|
||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||
ctx = ctx();
|
||||
}
|
||||
duration_type total = clock_type::now() - start;
|
||||
total -= overhead_clock(); // overhead of measurement
|
||||
total /= jobs; // loops
|
||||
total /= 2; // 2x jump_fcontext
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
#ifdef BOOST_CONTEXT_CYCLE
|
||||
cycle_type measure_cycles() {
|
||||
// cache warum-up
|
||||
boost::context::fixedsize_stack alloc;
|
||||
boost::context::execution_context< void > ctx( std::allocator_arg, alloc, foo);
|
||||
ctx = ctx();
|
||||
|
||||
cycle_type start( cycles() );
|
||||
for ( std::size_t i = 0; i < jobs; ++i) {
|
||||
ctx = ctx();
|
||||
}
|
||||
cycle_type total = cycles() - start;
|
||||
total -= overhead_cycle(); // overhead of measurement
|
||||
total /= jobs; // loops
|
||||
total /= 2; // 2x jump_fcontext
|
||||
|
||||
return total;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main( int argc, char * argv[]) {
|
||||
try {
|
||||
boost::program_options::options_description desc("allowed options");
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("jobs,j", boost::program_options::value< boost::uint64_t >( & jobs), "jobs to run");
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
boost::program_options::store(
|
||||
boost::program_options::parse_command_line(
|
||||
argc,
|
||||
argv,
|
||||
desc),
|
||||
vm);
|
||||
boost::program_options::notify( vm);
|
||||
|
||||
if ( vm.count("help") ) {
|
||||
std::cout << desc << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
boost::uint64_t res = measure_time().count();
|
||||
std::cout << "execution_context: average of " << res << " nano seconds" << std::endl;
|
||||
#ifdef BOOST_CONTEXT_CYCLE
|
||||
res = measure_cycles();
|
||||
std::cout << "execution_context: average of " << res << " cpu cycles" << 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;
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
Copyright Edward Nevill + Oliver Kowalke 2015
|
||||
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)
|
||||
*/
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | d8 | d9 | d10 | d11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | d12 | d13 | d14 | d15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x19 | x20 | x21 | x22 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x23 | x24 | x25 | x26 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x27 | x28 | FP | LR | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0xa0| 0xa4| 0xa8| 0xac| | | *
|
||||
* ------------------------------------------------- *
|
||||
* | PC | align | | | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.file "jump_arm64_aapcs_elf_gas.S"
|
||||
.text
|
||||
.align 2
|
||||
.global jump_fcontext
|
||||
.type jump_fcontext, %function
|
||||
jump_fcontext:
|
||||
# prepare stack for GP + FPU
|
||||
sub sp, sp, #0xb0
|
||||
|
||||
# save d8 - d15
|
||||
stp d8, d9, [sp, #0x00]
|
||||
stp d10, d11, [sp, #0x10]
|
||||
stp d12, d13, [sp, #0x20]
|
||||
stp d14, d15, [sp, #0x30]
|
||||
|
||||
# save x19-x30
|
||||
stp x19, x20, [sp, #0x40]
|
||||
stp x21, x22, [sp, #0x50]
|
||||
stp x23, x24, [sp, #0x60]
|
||||
stp x25, x26, [sp, #0x70]
|
||||
stp x27, x28, [sp, #0x80]
|
||||
stp x29, x30, [sp, #0x90]
|
||||
|
||||
# save LR as PC
|
||||
str x30, [sp, #0xa0]
|
||||
|
||||
# store RSP (pointing to context-data) in X0
|
||||
mov x4, sp
|
||||
|
||||
# restore RSP (pointing to context-data) from X1
|
||||
mov sp, x0
|
||||
|
||||
# load d8 - d15
|
||||
ldp d8, d9, [sp, #0x00]
|
||||
ldp d10, d11, [sp, #0x10]
|
||||
ldp d12, d13, [sp, #0x20]
|
||||
ldp d14, d15, [sp, #0x30]
|
||||
|
||||
# load x19-x30
|
||||
ldp x19, x20, [sp, #0x40]
|
||||
ldp x21, x22, [sp, #0x50]
|
||||
ldp x23, x24, [sp, #0x60]
|
||||
ldp x25, x26, [sp, #0x70]
|
||||
ldp x27, x28, [sp, #0x80]
|
||||
ldp x29, x30, [sp, #0x90]
|
||||
|
||||
# return transfer_t from jump
|
||||
# pass transfer_t as first arg in context function
|
||||
# X0 == FCTX, X1 == DATA
|
||||
mov x0, x4
|
||||
|
||||
# load pc
|
||||
ldr x4, [sp, #0xa0]
|
||||
|
||||
# restore stack from GP + FPU
|
||||
add sp, sp, #0xb0
|
||||
|
||||
ret x4
|
||||
.size jump_fcontext,.-jump_fcontext
|
||||
# Mark that we don't need executable stack.
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
Copyright Edward Nevill + Oliver Kowalke 2015
|
||||
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)
|
||||
*/
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | d8 | d9 | d10 | d11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | d12 | d13 | d14 | d15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x19 | x20 | x21 | x22 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x23 | x24 | x25 | x26 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x27 | x28 | FP | LR | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0xa0| 0xa4| 0xa8| 0xac| | | *
|
||||
* ------------------------------------------------- *
|
||||
* | PC | align | | | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.text
|
||||
.globl _jump_fcontext
|
||||
.balign 16
|
||||
_jump_fcontext:
|
||||
; prepare stack for GP + FPU
|
||||
sub sp, sp, #0xb0
|
||||
|
||||
; save d8 - d15
|
||||
stp d8, d9, [sp, #0x00]
|
||||
stp d10, d11, [sp, #0x10]
|
||||
stp d12, d13, [sp, #0x20]
|
||||
stp d14, d15, [sp, #0x30]
|
||||
|
||||
; save x19-x30
|
||||
stp x19, x20, [sp, #0x40]
|
||||
stp x21, x22, [sp, #0x50]
|
||||
stp x23, x24, [sp, #0x60]
|
||||
stp x25, x26, [sp, #0x70]
|
||||
stp x27, x28, [sp, #0x80]
|
||||
stp fp, lr, [sp, #0x90]
|
||||
|
||||
; save LR as PC
|
||||
str lr, [sp, #0xa0]
|
||||
|
||||
; store RSP (pointing to context-data) in X0
|
||||
mov x4, sp
|
||||
|
||||
; restore RSP (pointing to context-data) from X1
|
||||
mov sp, x0
|
||||
|
||||
; load d8 - d15
|
||||
ldp d8, d9, [sp, #0x00]
|
||||
ldp d10, d11, [sp, #0x10]
|
||||
ldp d12, d13, [sp, #0x20]
|
||||
ldp d14, d15, [sp, #0x30]
|
||||
|
||||
; load x19-x30
|
||||
ldp x19, x20, [sp, #0x40]
|
||||
ldp x21, x22, [sp, #0x50]
|
||||
ldp x23, x24, [sp, #0x60]
|
||||
ldp x25, x26, [sp, #0x70]
|
||||
ldp x27, x28, [sp, #0x80]
|
||||
ldp fp, lr, [sp, #0x90]
|
||||
|
||||
; return transfer_t from jump
|
||||
; pass transfer_t as first arg in context function
|
||||
; X0 == FCTX, X1 == DATA
|
||||
mov x0, x4
|
||||
|
||||
; load pc
|
||||
ldr x4, [sp, #0xa0]
|
||||
|
||||
; restore stack from GP + FPU
|
||||
add sp, sp, #0xb0
|
||||
|
||||
ret x4
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| *
|
||||
* ------------------------------------------------- *
|
||||
* |hiddn| v1 | v2 | v3 | v4 | v5 | v6 | v7 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| *
|
||||
* ------------------------------------------------- *
|
||||
* | v8 | lr | pc | FCTX| DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.file "jump_arm_aapcs_elf_gas.S"
|
||||
.text
|
||||
.globl jump_fcontext
|
||||
.align 2
|
||||
.type jump_fcontext,%function
|
||||
.syntax unified
|
||||
jump_fcontext:
|
||||
@ save LR as PC
|
||||
push {lr}
|
||||
@ save hidden,V1-V8,LR
|
||||
push {a1,v1-v8,lr}
|
||||
|
||||
@ prepare stack for FPU
|
||||
sub sp, sp, #64
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
@ save S16-S31
|
||||
vstmia sp, {d8-d15}
|
||||
#endif
|
||||
|
||||
@ store RSP (pointing to context-data) in A1
|
||||
mov a1, sp
|
||||
|
||||
@ restore RSP (pointing to context-data) from A2
|
||||
mov sp, a2
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
@ restore S16-S31
|
||||
vldmia sp, {d8-d15}
|
||||
#endif
|
||||
@ prepare stack for FPU
|
||||
add sp, sp, #64
|
||||
|
||||
@ restore hidden,V1-V8,LR
|
||||
pop {a4,v1-v8,lr}
|
||||
|
||||
@ return transfer_t from jump
|
||||
str a1, [a4, #0]
|
||||
str a3, [a4, #4]
|
||||
@ pass transfer_t as first arg in context function
|
||||
@ A1 == FCTX, A2 == DATA
|
||||
mov a2, a3
|
||||
|
||||
@ restore PC
|
||||
pop {pc}
|
||||
.size jump_fcontext,.-jump_fcontext
|
||||
|
||||
@ Mark that we don't need executable stack.
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | sjlj|hiddn| v1 | v2 | v3 | v4 | v5 | v6 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | v7 | v8 | lr | pc | FCTX| DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.text
|
||||
.globl _jump_fcontext
|
||||
.align 2
|
||||
_jump_fcontext:
|
||||
@ save LR as PC
|
||||
push {lr}
|
||||
@ save hidden,V1-V8,LR
|
||||
push {a1,v1-v8,lr}
|
||||
|
||||
@ locate TLS to save/restore SjLj handler
|
||||
mrc p15, 0, v2, c13, c0, #3
|
||||
bic v2, v2, #3
|
||||
|
||||
@ load TLS[__PTK_LIBC_DYLD_Unwind_SjLj_Key]
|
||||
ldr v1, [v2, #8]
|
||||
@ save SjLj handler
|
||||
push {v1}
|
||||
|
||||
@ prepare stack for FPU
|
||||
sub sp, sp, #64
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
@ save S16-S31
|
||||
vstmia sp, {d8-d15}
|
||||
#endif
|
||||
|
||||
@ store RSP (pointing to context-data) in A1
|
||||
mov a1, sp
|
||||
|
||||
@ restore RSP (pointing to context-data) from A2
|
||||
mov sp, a2
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
@ restore S16-S31
|
||||
vldmia sp, {d8-d15}
|
||||
#endif
|
||||
@ prepare stack for FPU
|
||||
add sp, sp, #64
|
||||
|
||||
@ r#estore SjLj handler
|
||||
pop {v1}
|
||||
@ store SjLj handler in TLS
|
||||
str v1, [v2, #8]
|
||||
|
||||
@ restore hidden,V1-V8,LR
|
||||
pop {a4,v1-v8,lr}
|
||||
|
||||
@ return transfer_t from jump
|
||||
str a1, [a4, #0]
|
||||
str a3, [a4, #4]
|
||||
@ pass transfer_t as first arg in context function
|
||||
@ A1 == FCTX, A2 == DATA
|
||||
mov a2, a3
|
||||
|
||||
@ restore PC
|
||||
pop {pc}
|
||||
@@ -1,81 +0,0 @@
|
||||
;/*
|
||||
; 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)
|
||||
;*/
|
||||
|
||||
; *******************************************************
|
||||
; * *
|
||||
; * ------------------------------------------------- *
|
||||
; * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
; * ------------------------------------------------- *
|
||||
; * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
; * ------------------------------------------------- *
|
||||
; * |deall|limit| base|hiddn| v1 | v2 | v3 | v4 | *
|
||||
; * ------------------------------------------------- *
|
||||
; * ------------------------------------------------- *
|
||||
; * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
; * ------------------------------------------------- *
|
||||
; * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
; * ------------------------------------------------- *
|
||||
; * | v5 | v6 | v7 | v8 | lr | pc | FCTX| DATA| *
|
||||
; * ------------------------------------------------- *
|
||||
; * *
|
||||
; *******************************************************
|
||||
|
||||
AREA |.text|, CODE
|
||||
ALIGN 4
|
||||
EXPORT jump_fcontext
|
||||
|
||||
jump_fcontext PROC
|
||||
; save LR as PC
|
||||
push {lr}
|
||||
; save hidden,V1-V8,LR
|
||||
push {a1,v1-v8,lr}
|
||||
|
||||
; load TIB to save/restore thread size and limit.
|
||||
; we do not need preserve CPU flag and can use it's arg register
|
||||
mrc p15, #0, v1, c13, c0, #2
|
||||
|
||||
; save current stack base
|
||||
ldr a5, [v1, #0x04]
|
||||
push {a5}
|
||||
; save current stack limit
|
||||
ldr a5, [v1, #0x08]
|
||||
push {a5}
|
||||
; save current deallocation stack
|
||||
ldr a5, [v1, #0xe0c]
|
||||
push {a5}
|
||||
|
||||
; store RSP (pointing to context-data) in A1
|
||||
mov a1, sp
|
||||
|
||||
; restore RSP (pointing to context-data) from A2
|
||||
mov sp, a2
|
||||
|
||||
; restore deallocation stack
|
||||
pop {a5}
|
||||
str a5, [v1, #0xe0c]
|
||||
; restore stack limit
|
||||
pop {a5}
|
||||
str a5, [v1, #0x08]
|
||||
; restore stack base
|
||||
pop {a5}
|
||||
str a5, [v1, #0x04]
|
||||
|
||||
; restore hidden,V1-V8,LR
|
||||
pop {a4,v1-v8,lr}
|
||||
|
||||
; return transfer_t from jump
|
||||
str a1, [a4, #0]
|
||||
str a3, [a4, #4]
|
||||
; pass transfer_t as first arg in context function
|
||||
; A1 == FCTX, A2 == DATA
|
||||
mov a2, a3
|
||||
|
||||
; restore PC
|
||||
pop {pc}
|
||||
|
||||
ENDP
|
||||
END
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
Copyright Sergue E. Leontiev 2013.
|
||||
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)
|
||||
*/
|
||||
|
||||
// Stub file for universal binary
|
||||
|
||||
#if defined(__i386__)
|
||||
#include "jump_i386_sysv_macho_gas.S"
|
||||
#elif defined(__x86_64__)
|
||||
#include "jump_x86_64_sysv_macho_gas.S"
|
||||
#elif defined(__ppc__)
|
||||
#include "jump_ppc32_sysv_macho_gas.S"
|
||||
#elif defined(__ppc64__)
|
||||
#include "jump_ppc64_sysv_macho_gas.S"
|
||||
#else
|
||||
#error "No arch's"
|
||||
#endif
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
Copyright Oliver Kowalke 2009.
|
||||
Copyright Thomas Sailer 2013.
|
||||
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)
|
||||
*/
|
||||
|
||||
/*************************************************************************************
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | 0h | 04h | 08h | 0ch | 010h | 014h | 018h | 01ch | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo| limit | base | fc_seh | EDI | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | 020h | 024h | 028h | 02ch | 030h | 034h | 038h | 03ch | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | ESI | EBX | EBP | EIP | to | data | EH NXT |SEH HNDLR| *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
**************************************************************************************/
|
||||
|
||||
.file "jump_i386_ms_pe_gas.asm"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
.globl _jump_fcontext
|
||||
.def _jump_fcontext; .scl 2; .type 32; .endef
|
||||
_jump_fcontext:
|
||||
/* prepare stack */
|
||||
leal -0x2c(%esp), %esp
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
/* save MMX control- and status-word */
|
||||
stmxcsr (%esp)
|
||||
/* save x87 control-word */
|
||||
fnstcw 0x4(%esp)
|
||||
#endif
|
||||
|
||||
/* load NT_TIB */
|
||||
movl %fs:(0x18), %edx
|
||||
/* load fiber local storage */
|
||||
movl 0x10(%edx), %eax
|
||||
movl %eax, 0x8(%esp)
|
||||
/* load current dealloction stack */
|
||||
movl 0xe0c(%edx), %eax
|
||||
movl %eax, 0xc(%esp)
|
||||
/* load current stack limit */
|
||||
movl 0x8(%edx), %eax
|
||||
movl %eax, 0x10(%esp)
|
||||
/* load current stack base */
|
||||
movl 0x4(%edx), %eax
|
||||
movl %eax, 0x14(%esp)
|
||||
/* load current SEH exception list */
|
||||
movl (%edx), %eax
|
||||
movl %eax, 0x18(%esp)
|
||||
|
||||
movl %edi, 0x1c(%esp) /* save EDI */
|
||||
movl %esi, 0x20(%esp) /* save ESI */
|
||||
movl %ebx, 0x24(%esp) /* save EBX */
|
||||
movl %ebp, 0x28(%esp) /* save EBP */
|
||||
|
||||
/* store ESP (pointing to context-data) in EAX */
|
||||
movl %esp, %eax
|
||||
|
||||
/* firstarg of jump_fcontext() == fcontext to jump to */
|
||||
movl 0x30(%esp), %ecx
|
||||
|
||||
/* restore ESP (pointing to context-data) from ECX */
|
||||
movl %ecx, %esp
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
/* restore MMX control- and status-word */
|
||||
ldmxcsr (%esp)
|
||||
/* restore x87 control-word */
|
||||
fldcw 0x4(%esp)
|
||||
#endif
|
||||
|
||||
/* restore NT_TIB into EDX */
|
||||
movl %fs:(0x18), %edx
|
||||
/* restore fiber local storage */
|
||||
movl 0x8(%esp), %ecx
|
||||
movl %ecx, 0x10(%edx)
|
||||
/* restore current deallocation stack */
|
||||
movl 0xc(%esp), %ecx
|
||||
movl %ecx, 0xe0c(%edx)
|
||||
/* restore current stack limit */
|
||||
movl 0x10(%esp), %ecx
|
||||
movl %ecx, 0x8(%edx)
|
||||
/* restore current stack base */
|
||||
movl 0x14(%esp), %ecx
|
||||
movl %ecx, 0x4(%edx)
|
||||
/* restore current SEH exception list */
|
||||
movl 0x18(%esp), %ecx
|
||||
movl %ecx, (%edx)
|
||||
|
||||
movl 0x2c(%esp), %ecx /* restore EIP */
|
||||
|
||||
movl 0x1c(%esp), %edi /* restore EDI */
|
||||
movl 0x20(%esp), %esi /* restore ESI */
|
||||
movl 0x24(%esp), %ebx /* restore EBX */
|
||||
movl 0x28(%esp), %ebp /* restore EBP */
|
||||
|
||||
/* prepare stack */
|
||||
leal 0x30(%esp), %esp
|
||||
|
||||
/* return transfer_t */
|
||||
/* FCTX == EAX, DATA == EDX */
|
||||
movl 0x34(%eax), %edx
|
||||
|
||||
/* jump to context */
|
||||
jmp *%ecx
|
||||
|
||||
.section .drectve
|
||||
.ascii " -export:\"jump_fcontext\""
|
||||
@@ -1,116 +0,0 @@
|
||||
|
||||
; 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)
|
||||
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | 0h | 04h | 08h | 0ch | 010h | 014h | 018h | 01ch |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo| limit | base | fc_seh | EDI |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | 020h | 024h | 028h | 02ch | 030h | 034h | 038h | 03ch |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | ESI | EBX | EBP | EIP | to | data | EH NXT |SEH HNDLR|
|
||||
; ---------------------------------------------------------------------------------
|
||||
|
||||
.386
|
||||
.XMM
|
||||
.model flat, c
|
||||
.code
|
||||
|
||||
jump_fcontext PROC BOOST_CONTEXT_EXPORT
|
||||
; prepare stack
|
||||
lea esp, [esp-02ch]
|
||||
|
||||
IFNDEF BOOST_USE_TSX
|
||||
; save MMX control- and status-word
|
||||
stmxcsr [esp]
|
||||
; save x87 control-word
|
||||
fnstcw [esp+04h]
|
||||
ENDIF
|
||||
|
||||
assume fs:nothing
|
||||
; load NT_TIB into ECX
|
||||
mov edx, fs:[018h]
|
||||
assume fs:error
|
||||
; load fiber local storage
|
||||
mov eax, [edx+010h]
|
||||
mov [esp+08h], eax
|
||||
; load current deallocation stack
|
||||
mov eax, [edx+0e0ch]
|
||||
mov [esp+0ch], eax
|
||||
; load current stack limit
|
||||
mov eax, [edx+08h]
|
||||
mov [esp+010h], eax
|
||||
; load current stack base
|
||||
mov eax, [edx+04h]
|
||||
mov [esp+014h], eax
|
||||
; load current SEH exception list
|
||||
mov eax, [edx]
|
||||
mov [esp+018h], eax
|
||||
|
||||
mov [esp+01ch], edi ; save EDI
|
||||
mov [esp+020h], esi ; save ESI
|
||||
mov [esp+024h], ebx ; save EBX
|
||||
mov [esp+028h], ebp ; save EBP
|
||||
|
||||
; store ESP (pointing to context-data) in EAX
|
||||
mov eax, esp
|
||||
|
||||
; firstarg of jump_fcontext() == fcontext to jump to
|
||||
mov ecx, [esp+030h]
|
||||
|
||||
; restore ESP (pointing to context-data) from ECX
|
||||
mov esp, ecx
|
||||
|
||||
IFNDEF BOOST_USE_TSX
|
||||
; restore MMX control- and status-word
|
||||
ldmxcsr [esp]
|
||||
; restore x87 control-word
|
||||
fldcw [esp+04h]
|
||||
ENDIF
|
||||
|
||||
assume fs:nothing
|
||||
; load NT_TIB into EDX
|
||||
mov edx, fs:[018h]
|
||||
assume fs:error
|
||||
; restore fiber local storage
|
||||
mov ecx, [esp+08h]
|
||||
mov [edx+010h], ecx
|
||||
; restore current deallocation stack
|
||||
mov ecx, [esp+0ch]
|
||||
mov [edx+0e0ch], ecx
|
||||
; restore current stack limit
|
||||
mov ecx, [esp+010h]
|
||||
mov [edx+08h], ecx
|
||||
; restore current stack base
|
||||
mov ecx, [esp+014h]
|
||||
mov [edx+04h], ecx
|
||||
; restore current SEH exception list
|
||||
mov ecx, [esp+018h]
|
||||
mov [edx], ecx
|
||||
|
||||
mov ecx, [esp+02ch] ; restore EIP
|
||||
|
||||
mov edi, [esp+01ch] ; restore EDI
|
||||
mov esi, [esp+020h] ; restore ESI
|
||||
mov ebx, [esp+024h] ; restore EBX
|
||||
mov ebp, [esp+028h] ; restore EBP
|
||||
|
||||
; prepare stack
|
||||
lea esp, [esp+030h]
|
||||
|
||||
; return transfer_t
|
||||
; FCTX == EAX, DATA == EDX
|
||||
mov edx, [eax+034h]
|
||||
|
||||
; jump to context
|
||||
jmp ecx
|
||||
jump_fcontext ENDP
|
||||
END
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/****************************************************************************************
|
||||
* *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | hidden | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x20 | 0x24 | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | to | data | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* *
|
||||
****************************************************************************************/
|
||||
|
||||
.file "jump_i386_sysv_elf_gas.S"
|
||||
.text
|
||||
.globl jump_fcontext
|
||||
.align 2
|
||||
.type jump_fcontext,@function
|
||||
jump_fcontext:
|
||||
leal -0x18(%esp), %esp /* prepare stack */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
stmxcsr (%esp) /* save MMX control- and status-word */
|
||||
fnstcw 0x4(%esp) /* save x87 control-word */
|
||||
#endif
|
||||
|
||||
movl %edi, 0x8(%esp) /* save EDI */
|
||||
movl %esi, 0xc(%esp) /* save ESI */
|
||||
movl %ebx, 0x10(%esp) /* save EBX */
|
||||
movl %ebp, 0x14(%esp) /* save EBP */
|
||||
|
||||
/* store ESP (pointing to context-data) in ECX */
|
||||
movl %esp, %ecx
|
||||
|
||||
/* first arg of jump_fcontext() == fcontext to jump to */
|
||||
movl 0x20(%esp), %eax
|
||||
|
||||
/* second arg of jump_fcontext() == data to be transferred */
|
||||
movl 0x24(%esp), %edx
|
||||
|
||||
/* restore ESP (pointing to context-data) from EAX */
|
||||
movl %eax, %esp
|
||||
|
||||
/* address of returned transport_t */
|
||||
movl 0x1c(%esp), %eax
|
||||
/* return parent fcontext_t */
|
||||
movl %ecx, (%eax)
|
||||
/* return data */
|
||||
movl %edx, 0x4(%eax)
|
||||
|
||||
movl 0x18(%esp), %ecx /* restore EIP */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
ldmxcsr (%esp) /* restore MMX control- and status-word */
|
||||
fldcw 0x4(%esp) /* restore x87 control-word */
|
||||
#endif
|
||||
|
||||
movl 0x8(%esp), %edi /* restore EDI */
|
||||
movl 0xc(%esp), %esi /* restore ESI */
|
||||
movl 0x10(%esp), %ebx /* restore EBX */
|
||||
movl 0x14(%esp), %ebp /* restore EBP */
|
||||
|
||||
leal 0x20(%esp), %esp /* prepare stack */
|
||||
|
||||
/* jump to context */
|
||||
jmp *%ecx
|
||||
.size jump_fcontext,.-jump_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/****************************************************************************************
|
||||
* *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | to | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x20 | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | data | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* *
|
||||
****************************************************************************************/
|
||||
|
||||
.text
|
||||
.globl _jump_fcontext
|
||||
.align 2
|
||||
_jump_fcontext:
|
||||
leal -0x18(%esp), %esp /* prepare stack */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
stmxcsr (%esp) /* save MMX control- and status-word */
|
||||
fnstcw 0x4(%esp) /* save x87 control-word */
|
||||
#endif
|
||||
|
||||
movl %edi, 0x8(%esp) /* save EDI */
|
||||
movl %esi, 0xc(%esp) /* save ESI */
|
||||
movl %ebx, 0x10(%esp) /* save EBX */
|
||||
movl %ebp, 0x14(%esp) /* save EBP */
|
||||
|
||||
/* store ESP (pointing to context-data) in ECX */
|
||||
movl %esp, %ecx
|
||||
|
||||
/* first arg of jump_fcontext() == fcontext to jump to */
|
||||
movl 0x1c(%esp), %eax
|
||||
|
||||
/* second arg of jump_fcontext() == data to be transferred */
|
||||
movl 0x20(%esp), %edx
|
||||
|
||||
/* restore ESP (pointing to context-data) from EAX */
|
||||
movl %eax, %esp
|
||||
|
||||
/* return parent fcontext_t */
|
||||
movl %ecx, %eax
|
||||
/* returned data is stored in EDX */
|
||||
|
||||
movl 0x18(%esp), %ecx /* restore EIP */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
ldmxcsr (%esp) /* restore MMX control- and status-word */
|
||||
fldcw 0x4(%esp) /* restore x87 control-word */
|
||||
#endif
|
||||
|
||||
movl 0x8(%esp), %edi /* restore EDI */
|
||||
movl 0xc(%esp), %esi /* restore ESI */
|
||||
movl 0x10(%esp), %ebx /* restore EBX */
|
||||
movl 0x14(%esp), %ebp /* restore EBP */
|
||||
|
||||
leal 0x1c(%esp), %esp /* prepare stack */
|
||||
|
||||
/* jump to context */
|
||||
jmp *%ecx
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
Copyright Sergue E. Leontiev 2013.
|
||||
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)
|
||||
*/
|
||||
|
||||
// Stub file for universal binary
|
||||
|
||||
#if defined(__i386__)
|
||||
#include "jump_i386_sysv_macho_gas.S"
|
||||
#elif defined(__x86_64__)
|
||||
#include "jump_x86_64_sysv_macho_gas.S"
|
||||
#else
|
||||
#error "No arch's"
|
||||
#endif
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F20 | F22 | F24 | F26 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F28 | F30 | S0 | S1 | S2 | S3 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | S4 | S5 | S6 | S7 | FP |hiddn| RA | PC | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | ABI ARGS | GP | FCTX| DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
* *****************************************************/
|
||||
|
||||
.file "jump_mips32_o32_elf_gas.S"
|
||||
.text
|
||||
.globl jump_fcontext
|
||||
.align 2
|
||||
.type jump_fcontext,@function
|
||||
.ent jump_fcontext
|
||||
jump_fcontext:
|
||||
# reserve space on stack
|
||||
addiu $sp, $sp, -96
|
||||
|
||||
sw $s0, 48($sp) # save S0
|
||||
sw $s1, 52($sp) # save S1
|
||||
sw $s2, 56($sp) # save S2
|
||||
sw $s3, 60($sp) # save S3
|
||||
sw $s4, 64($sp) # save S4
|
||||
sw $s5, 68($sp) # save S5
|
||||
sw $s6, 72($sp) # save S6
|
||||
sw $s7, 76($sp) # save S7
|
||||
sw $fp, 80($sp) # save FP
|
||||
sw $a0, 84($sp) # save hidden, address of returned transfer_t
|
||||
sw $ra, 88($sp) # save RA
|
||||
sw $ra, 92($sp) # save RA as PC
|
||||
|
||||
#if defined(__mips_hard_float)
|
||||
s.d $f20, ($sp) # save F20
|
||||
s.d $f22, 8($sp) # save F22
|
||||
s.d $f24, 16($sp) # save F24
|
||||
s.d $f26, 24($sp) # save F26
|
||||
s.d $f28, 32($sp) # save F28
|
||||
s.d $f30, 40($sp) # save F30
|
||||
#endif
|
||||
|
||||
# store SP (pointing to context-data) in A0
|
||||
move $a0, $sp
|
||||
|
||||
# restore SP (pointing to context-data) from A1
|
||||
move $sp, $a1
|
||||
|
||||
#if defined(__mips_hard_float)
|
||||
l.d $f20, ($sp) # restore F20
|
||||
l.d $f22, 8($sp) # restore F22
|
||||
l.d $f24, 16($sp) # restore F24
|
||||
l.d $f26, 24($sp) # restore F26
|
||||
l.d $f28, 32($sp) # restore F28
|
||||
l.d $f30, 40($sp) # restore F30
|
||||
#endif
|
||||
|
||||
lw $s0, 48($sp) # restore S0
|
||||
lw $s1, 52($sp) # restore S1
|
||||
lw $s2, 56($sp) # restore S2
|
||||
lw $s3, 60($sp) # restore S3
|
||||
lw $s4, 64($sp) # restore S4
|
||||
lw $s5, 68($sp) # restore S5
|
||||
lw $s6, 72($sp) # restore S6
|
||||
lw $s7, 76($sp) # restore S7
|
||||
lw $fp, 80($sp) # restore FP
|
||||
lw $v0, 84($sp) # restore hidden, address of returned transfer_t
|
||||
lw $ra, 88($sp) # restore RA
|
||||
|
||||
# load PC
|
||||
lw $t9, 92($sp)
|
||||
|
||||
# adjust stack
|
||||
addiu $sp, $sp, 96
|
||||
|
||||
# return transfer_t from jump
|
||||
sw $a0, ($v0) # fctx of transfer_t
|
||||
sw $a2, 4($v0) # data of transfer_t
|
||||
# pass transfer_t as first arg in context function
|
||||
# A0 == fctx, A1 == data
|
||||
move $a1, $a2
|
||||
|
||||
# jump to context
|
||||
jr $t9
|
||||
.end jump_fcontext
|
||||
.size jump_fcontext, .-jump_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
Copyright Jiaxun Yang 2018.
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 8 | 16 | 24 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F24 | F25 | F26 | F27 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 40 | 48 | 56 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F28 | F29 | F30 | F31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 72 | 80 | 88 | *
|
||||
* ------------------------------------------------- *
|
||||
* | S0 | S1 | S2 | S3 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | S4 | S5 | S6 | S7 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | FP | GP | RA | PC | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
* *****************************************************/
|
||||
|
||||
.file "jump_mips64_n64_elf_gas.S"
|
||||
.text
|
||||
.globl jump_fcontext
|
||||
.align 2
|
||||
.type jump_fcontext,@function
|
||||
.ent jump_fcontext
|
||||
jump_fcontext:
|
||||
# reserve space on stack
|
||||
daddiu $sp, $sp, -160
|
||||
|
||||
sd $s0, 64($sp) # save S0
|
||||
sd $s1, 72($sp) # save S1
|
||||
sd $s2, 80($sp) # save S2
|
||||
sd $s3, 88($sp) # save S3
|
||||
sd $s4, 96($sp) # save S4
|
||||
sd $s5, 104($sp) # save S5
|
||||
sd $s6, 112($sp) # save S6
|
||||
sd $s7, 120($sp) # save S7
|
||||
sd $fp, 128($sp) # save FP
|
||||
sd $ra, 144($sp) # save RA
|
||||
sd $ra, 152($sp) # save RA as PC
|
||||
|
||||
|
||||
s.d $f24, 0($sp) # save F24
|
||||
s.d $f25, 8($sp) # save F25
|
||||
s.d $f26, 16($sp) # save F26
|
||||
s.d $f27, 24($sp) # save F27
|
||||
s.d $f28, 32($sp) # save F28
|
||||
s.d $f29, 40($sp) # save F29
|
||||
s.d $f30, 48($sp) # save F30
|
||||
s.d $f31, 56($sp) # save F31
|
||||
|
||||
# store SP (pointing to old context-data) in v0 as return
|
||||
move $v0, $sp
|
||||
|
||||
# get SP (pointing to new context-data) from a0 param
|
||||
move $sp, $a0
|
||||
|
||||
l.d $f24, 0($sp) # restore F24
|
||||
l.d $f25, 8($sp) # restore F25
|
||||
l.d $f26, 16($sp) # restore F26
|
||||
l.d $f27, 24($sp) # restore F27
|
||||
l.d $f28, 32($sp) # restore F28
|
||||
l.d $f29, 40($sp) # restore F29
|
||||
l.d $f30, 48($sp) # restore F30
|
||||
l.d $f31, 56($sp) # restore F31
|
||||
|
||||
ld $s0, 64($sp) # restore S0
|
||||
ld $s1, 72($sp) # restore S1
|
||||
ld $s2, 80($sp) # restore S2
|
||||
ld $s3, 88($sp) # restore S3
|
||||
ld $s4, 96($sp) # restore S4
|
||||
ld $s5, 104($sp) # restore S5
|
||||
ld $s6, 112($sp) # restore S6
|
||||
ld $s7, 120($sp) # restore S7
|
||||
ld $fp, 128($sp) # restore FP
|
||||
ld $ra, 144($sp) # restore RAa
|
||||
|
||||
# load PC
|
||||
ld $t9, 152($sp)
|
||||
|
||||
# adjust stack
|
||||
daddiu $sp, $sp, 160
|
||||
|
||||
move $a0, $v0 # move old sp from v0 to a0 as param
|
||||
move $v1, $a1 # move *data from a1 to v1 as return
|
||||
|
||||
# jump to context
|
||||
jr $t9
|
||||
.end jump_fcontext
|
||||
.size jump_fcontext, .-jump_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
Copyright Sergue E. Leontiev 2013.
|
||||
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)
|
||||
*/
|
||||
|
||||
// Stub file for universal binary
|
||||
|
||||
#if defined(__ppc__)
|
||||
#include "jump_ppc32_sysv_macho_gas.S"
|
||||
#elif defined(__ppc64__)
|
||||
#include "jump_ppc64_sysv_macho_gas.S"
|
||||
#else
|
||||
#error "No arch's"
|
||||
#endif
|
||||
@@ -1,207 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F14 | F15 | F16 | F17 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F18 | F19 | F20 | F21 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F22 | F23 | F24 | F25 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F26 | F27 | F28 | F29 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F30 | F31 | fpscr | R13 | R14 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R15 | R16 | R17 | R18 | R19 | R20 | R21 | R22 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R23 | R24 | R25 | R26 | R27 | R28 | R29 | R30 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R31 |hiddn| CR | LR | PC |bchai|linkr| FCTX| *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 256 | | *
|
||||
* ------------------------------------------------- *
|
||||
* | DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.file "jump_ppc32_sysv_elf_gas.S"
|
||||
.text
|
||||
.globl jump_fcontext
|
||||
.align 2
|
||||
.type jump_fcontext,@function
|
||||
jump_fcontext:
|
||||
# reserve space on stack
|
||||
subi %r1, %r1, 244
|
||||
|
||||
stfd %f14, 0(%r1) # save F14
|
||||
stfd %f15, 8(%r1) # save F15
|
||||
stfd %f16, 16(%r1) # save F16
|
||||
stfd %f17, 24(%r1) # save F17
|
||||
stfd %f18, 32(%r1) # save F18
|
||||
stfd %f19, 40(%r1) # save F19
|
||||
stfd %f20, 48(%r1) # save F20
|
||||
stfd %f21, 56(%r1) # save F21
|
||||
stfd %f22, 64(%r1) # save F22
|
||||
stfd %f23, 72(%r1) # save F23
|
||||
stfd %f24, 80(%r1) # save F24
|
||||
stfd %f25, 88(%r1) # save F25
|
||||
stfd %f26, 96(%r1) # save F26
|
||||
stfd %f27, 104(%r1) # save F27
|
||||
stfd %f28, 112(%r1) # save F28
|
||||
stfd %f29, 120(%r1) # save F29
|
||||
stfd %f30, 128(%r1) # save F30
|
||||
stfd %f31, 136(%r1) # save F31
|
||||
mffs %f0 # load FPSCR
|
||||
stfd %f0, 144(%r1) # save FPSCR
|
||||
|
||||
stw %r13, 152(%r1) # save R13
|
||||
stw %r14, 156(%r1) # save R14
|
||||
stw %r15, 160(%r1) # save R15
|
||||
stw %r16, 164(%r1) # save R16
|
||||
stw %r17, 168(%r1) # save R17
|
||||
stw %r18, 172(%r1) # save R18
|
||||
stw %r19, 176(%r1) # save R19
|
||||
stw %r20, 180(%r1) # save R20
|
||||
stw %r21, 184(%r1) # save R21
|
||||
stw %r22, 188(%r1) # save R22
|
||||
stw %r23, 192(%r1) # save R23
|
||||
stw %r24, 196(%r1) # save R24
|
||||
stw %r25, 200(%r1) # save R25
|
||||
stw %r26, 204(%r1) # save R26
|
||||
stw %r27, 208(%r1) # save R27
|
||||
stw %r28, 212(%r1) # save R28
|
||||
stw %r29, 216(%r1) # save R29
|
||||
stw %r30, 220(%r1) # save R30
|
||||
stw %r31, 224(%r1) # save R31
|
||||
stw %r3, 228(%r1) # save hidden
|
||||
|
||||
# save CR
|
||||
mfcr %r0
|
||||
stw %r0, 232(%r1)
|
||||
# save LR
|
||||
mflr %r0
|
||||
stw %r0, 236(%r1)
|
||||
# save LR as PC
|
||||
stw %r0, 240(%r1)
|
||||
|
||||
# store RSP (pointing to context-data) in R6
|
||||
mr %r6, %r1
|
||||
|
||||
# restore RSP (pointing to context-data) from R4
|
||||
mr %r1, %r4
|
||||
|
||||
lfd %f14, 0(%r1) # restore F14
|
||||
lfd %f15, 8(%r1) # restore F15
|
||||
lfd %f16, 16(%r1) # restore F16
|
||||
lfd %f17, 24(%r1) # restore F17
|
||||
lfd %f18, 32(%r1) # restore F18
|
||||
lfd %f19, 40(%r1) # restore F19
|
||||
lfd %f20, 48(%r1) # restore F20
|
||||
lfd %f21, 56(%r1) # restore F21
|
||||
lfd %f22, 64(%r1) # restore F22
|
||||
lfd %f23, 72(%r1) # restore F23
|
||||
lfd %f24, 80(%r1) # restore F24
|
||||
lfd %f25, 88(%r1) # restore F25
|
||||
lfd %f26, 96(%r1) # restore F26
|
||||
lfd %f27, 104(%r1) # restore F27
|
||||
lfd %f28, 112(%r1) # restore F28
|
||||
lfd %f29, 120(%r1) # restore F29
|
||||
lfd %f30, 128(%r1) # restore F30
|
||||
lfd %f31, 136(%r1) # restore F31
|
||||
lfd %f0, 144(%r1) # load FPSCR
|
||||
mtfsf 0xff, %f0 # restore FPSCR
|
||||
|
||||
lwz %r13, 152(%r1) # restore R13
|
||||
lwz %r14, 156(%r1) # restore R14
|
||||
lwz %r15, 160(%r1) # restore R15
|
||||
lwz %r16, 164(%r1) # restore R16
|
||||
lwz %r17, 168(%r1) # restore R17
|
||||
lwz %r18, 172(%r1) # restore R18
|
||||
lwz %r19, 176(%r1) # restore R19
|
||||
lwz %r20, 180(%r1) # restore R20
|
||||
lwz %r21, 184(%r1) # restore R21
|
||||
lwz %r22, 188(%r1) # restore R22
|
||||
lwz %r23, 192(%r1) # restore R23
|
||||
lwz %r24, 196(%r1) # restore R24
|
||||
lwz %r25, 200(%r1) # restore R25
|
||||
lwz %r26, 204(%r1) # restore R26
|
||||
lwz %r27, 208(%r1) # restore R27
|
||||
lwz %r28, 212(%r1) # restore R28
|
||||
lwz %r29, 216(%r1) # restore R29
|
||||
lwz %r30, 220(%r1) # restore R30
|
||||
lwz %r31, 224(%r1) # restore R31
|
||||
lwz %r3, 228(%r1) # restore hidden
|
||||
|
||||
# restore CR
|
||||
lwz %r0, 232(%r1)
|
||||
mtcr %r0
|
||||
# restore LR
|
||||
lwz %r0, 236(%r1)
|
||||
mtlr %r0
|
||||
# load PC
|
||||
lwz %r0, 240(%r1)
|
||||
# restore CTR
|
||||
mtctr %r0
|
||||
|
||||
# adjust stack
|
||||
addi %r1, %r1, 244
|
||||
|
||||
# return transfer_t
|
||||
stw %r6, 0(%r3)
|
||||
stw %r5, 4(%r3)
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
.size jump_fcontext, .-jump_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F14 | F15 | F16 | F17 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F18 | F19 | F20 | F21 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F22 | F23 | F24 | F25 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F26 | F27 | F28 | F29 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F30 | F31 | fpscr | R13 | R14 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R15 | R16 | R17 | R18 | R19 | R20 | R21 | R22 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R23 | R24 | R25 | R26 | R27 | R28 | R29 | R30 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R31 |hiddn| CR | LR | PC |bchai|linkr| FCTX| *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 256 | | *
|
||||
* ------------------------------------------------- *
|
||||
* | DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.text
|
||||
.globl _jump_fcontext
|
||||
.align 2
|
||||
_jump_fcontext:
|
||||
; reserve space on stack
|
||||
subi r1, r1, 244
|
||||
|
||||
stfd f14, 0(r1) # save F14
|
||||
stfd f15, 8(r1) # save F15
|
||||
stfd f16, 16(r1) # save F16
|
||||
stfd f17, 24(r1) # save F17
|
||||
stfd f18, 32(r1) # save F18
|
||||
stfd f19, 40(r1) # save F19
|
||||
stfd f20, 48(r1) # save F20
|
||||
stfd f21, 56(r1) # save F21
|
||||
stfd f22, 64(r1) # save F22
|
||||
stfd f23, 72(r1) # save F23
|
||||
stfd f24, 80(r1) # save F24
|
||||
stfd f25, 88(r1) # save F25
|
||||
stfd f26, 96(r1) # save F26
|
||||
stfd f27, 104(r1) # save F27
|
||||
stfd f28, 112(r1) # save F28
|
||||
stfd f29, 120(r1) # save F29
|
||||
stfd f30, 128(r1) # save F30
|
||||
stfd f31, 136(r1) # save F31
|
||||
mffs f0 # load FPSCR
|
||||
stfd f0, 144(r1) # save FPSCR
|
||||
|
||||
stw r13, 152(r1) # save R13
|
||||
stw r14, 156(r1) # save R14
|
||||
stw r15, 160(r1) # save R15
|
||||
stw r16, 164(r1) # save R16
|
||||
stw r17, 168(r1) # save R17
|
||||
stw r18, 172(r1) # save R18
|
||||
stw r19, 176(r1) # save R19
|
||||
stw r20, 180(r1) # save R20
|
||||
stw r21, 184(r1) # save R21
|
||||
stw r22, 188(r1) # save R22
|
||||
stw r23, 192(r1) # save R23
|
||||
stw r24, 196(r1) # save R24
|
||||
stw r25, 200(r1) # save R25
|
||||
stw r26, 204(r1) # save R26
|
||||
stw r27, 208(r1) # save R27
|
||||
stw r28, 212(r1) # save R28
|
||||
stw r29, 216(r1) # save R29
|
||||
stw r30, 220(r1) # save R30
|
||||
stw r31, 224(r1) # save R31
|
||||
stw r3, 228(r1) # save hidden
|
||||
|
||||
# save CR
|
||||
mfcr r0
|
||||
stw r0, 232(r1)
|
||||
# save LR
|
||||
mflr r0
|
||||
stw r0, 236(r1)
|
||||
# save LR as PC
|
||||
stw r0, 240(r1)
|
||||
|
||||
# store RSP (pointing to context-data) in R6
|
||||
mr r6, r1
|
||||
|
||||
# restore RSP (pointing to context-data) from R4
|
||||
mr r1, r4
|
||||
|
||||
lfd f14, 0(r1) # restore F14
|
||||
lfd f15, 8(r1) # restore F15
|
||||
lfd f16, 16(r1) # restore F16
|
||||
lfd f17, 24(r1) # restore F17
|
||||
lfd f18, 32(r1) # restore F18
|
||||
lfd f19, 40(r1) # restore F19
|
||||
lfd f20, 48(r1) # restore F20
|
||||
lfd f21, 56(r1) # restore F21
|
||||
lfd f22, 64(r1) # restore F22
|
||||
lfd f23, 72(r1) # restore F23
|
||||
lfd f24, 80(r1) # restore F24
|
||||
lfd f25, 88(r1) # restore F25
|
||||
lfd f26, 96(r1) # restore F26
|
||||
lfd f27, 104(r1) # restore F27
|
||||
lfd f28, 112(r1) # restore F28
|
||||
lfd f29, 120(r1) # restore F29
|
||||
lfd f30, 128(r1) # restore F30
|
||||
lfd f31, 136(r1) # restore F31
|
||||
lfd f0, 144(r1) # load FPSCR
|
||||
mtfsf 0xff, f0 # restore FPSCR
|
||||
|
||||
lwz r13, 152(r1) # restore R13
|
||||
lwz r14, 156(r1) # restore R14
|
||||
lwz r15, 160(r1) # restore R15
|
||||
lwz r16, 164(r1) # restore R16
|
||||
lwz r17, 168(r1) # restore R17
|
||||
lwz r18, 172(r1) # restore R18
|
||||
lwz r19, 176(r1) # restore R19
|
||||
lwz r20, 180(r1) # restore R20
|
||||
lwz r21, 184(r1) # restore R21
|
||||
lwz r22, 188(r1) # restore R22
|
||||
lwz r23, 192(r1) # restore R23
|
||||
lwz r24, 196(r1) # restore R24
|
||||
lwz r25, 200(r1) # restore R25
|
||||
lwz r26, 204(r1) # restore R26
|
||||
lwz r27, 208(r1) # restore R27
|
||||
lwz r28, 212(r1) # restore R28
|
||||
lwz r29, 216(r1) # restore R29
|
||||
lwz r30, 220(r1) # restore R30
|
||||
lwz r31, 224(r1) # restore R31
|
||||
lwz r3, 228(r1) # restore hidden
|
||||
|
||||
# restore CR
|
||||
lwz r0, 232(r1)
|
||||
mtcr r0
|
||||
# restore LR
|
||||
lwz r0, 236(r1)
|
||||
mtlr r0
|
||||
# load PC
|
||||
lwz r0, 240(r1)
|
||||
# restore CTR
|
||||
mtctr r0
|
||||
|
||||
# adjust stack
|
||||
addi r1, r1, 244
|
||||
|
||||
# return transfer_t
|
||||
stw r6, 0(r3)
|
||||
stw r5, 4(r3)
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F14 | F15 | F16 | F17 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F18 | F19 | F20 | F21 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F22 | F23 | F24 | F25 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F26 | F27 | F28 | F29 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F30 | F31 | fpscr | R13 | R14 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R15 | R16 | R17 | R18 | R19 | R20 | R21 | R22 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R23 | R24 | R25 | R26 | R27 | R28 | R29 | R30 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R31 |hiddn| CR | LR | PC |bchai|linkr| FCTX| *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 256 | | *
|
||||
* ------------------------------------------------- *
|
||||
* | DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
.globl .jump_fcontext
|
||||
.globl jump_fcontext[DS]
|
||||
.align 2
|
||||
.csect jump_fcontext[DS]
|
||||
jump_fcontext:
|
||||
.long .jump_fcontext
|
||||
.jump_fcontext:
|
||||
# reserve space on stack
|
||||
subi r1, r1, 244
|
||||
|
||||
stfd f14, 0(r1) # save F14
|
||||
stfd f15, 8(r1) # save F15
|
||||
stfd f16, 16(r1) # save F16
|
||||
stfd f17, 24(r1) # save F17
|
||||
stfd f18, 32(r1) # save F18
|
||||
stfd f19, 40(r1) # save F19
|
||||
stfd f20, 48(r1) # save F20
|
||||
stfd f21, 56(r1) # save F21
|
||||
stfd f22, 64(r1) # save F22
|
||||
stfd f23, 72(r1) # save F23
|
||||
stfd f24, 80(r1) # save F24
|
||||
stfd f25, 88(r1) # save F25
|
||||
stfd f26, 96(r1) # save F26
|
||||
stfd f27, 104(r1) # save F27
|
||||
stfd f28, 112(r1) # save F28
|
||||
stfd f29, 120(r1) # save F29
|
||||
stfd f30, 128(r1) # save F30
|
||||
stfd f31, 136(r1) # save F31
|
||||
mffs f0 # load FPSCR
|
||||
stfd f0, 144(r1) # save FPSCR
|
||||
|
||||
stw r13, 152(r1) # save R13
|
||||
stw r14, 156(r1) # save R14
|
||||
stw r15, 160(r1) # save R15
|
||||
stw r16, 164(r1) # save R16
|
||||
stw r17, 168(r1) # save R17
|
||||
stw r18, 172(r1) # save R18
|
||||
stw r19, 176(r1) # save R19
|
||||
stw r20, 180(r1) # save R20
|
||||
stw r21, 184(r1) # save R21
|
||||
stw r22, 188(r1) # save R22
|
||||
stw r23, 192(r1) # save R23
|
||||
stw r24, 196(r1) # save R24
|
||||
stw r25, 200(r1) # save R25
|
||||
stw r26, 204(r1) # save R26
|
||||
stw r27, 208(r1) # save R27
|
||||
stw r28, 212(r1) # save R28
|
||||
stw r29, 216(r1) # save R29
|
||||
stw r30, 220(r1) # save R30
|
||||
stw r31, 224(r1) # save R31
|
||||
stw r3, 228(r1) # save hidden
|
||||
|
||||
# save CR
|
||||
mfcr r0
|
||||
stw r0, 232(r1)
|
||||
# save LR
|
||||
mflr r0
|
||||
stw r0, 236(r1)
|
||||
# save LR as PC
|
||||
stw r0, 240(r1)
|
||||
|
||||
# store RSP (pointing to context-data) in R6
|
||||
mr r6, r1
|
||||
|
||||
# restore RSP (pointing to context-data) from R4
|
||||
mr r1, r4
|
||||
|
||||
lfd f14, 0(r1) # restore F14
|
||||
lfd f15, 8(r1) # restore F15
|
||||
lfd f16, 16(r1) # restore F16
|
||||
lfd f17, 24(r1) # restore F17
|
||||
lfd f18, 32(r1) # restore F18
|
||||
lfd f19, 40(r1) # restore F19
|
||||
lfd f20, 48(r1) # restore F20
|
||||
lfd f21, 56(r1) # restore F21
|
||||
lfd f22, 64(r1) # restore F22
|
||||
lfd f23, 72(r1) # restore F23
|
||||
lfd f24, 80(r1) # restore F24
|
||||
lfd f25, 88(r1) # restore F25
|
||||
lfd f26, 96(r1) # restore F26
|
||||
lfd f27, 104(r1) # restore F27
|
||||
lfd f28, 112(r1) # restore F28
|
||||
lfd f29, 120(r1) # restore F29
|
||||
lfd f30, 128(r1) # restore F30
|
||||
lfd f31, 136(r1) # restore F31
|
||||
lfd f0, 144(r1) # load FPSCR
|
||||
mtfsf 0xff, f0 # restore FPSCR
|
||||
|
||||
lwz r13, 152(r1) # restore R13
|
||||
lwz r14, 156(r1) # restore R14
|
||||
lwz r15, 160(r1) # restore R15
|
||||
lwz r16, 164(r1) # restore R16
|
||||
lwz r17, 168(r1) # restore R17
|
||||
lwz r18, 172(r1) # restore R18
|
||||
lwz r19, 176(r1) # restore R19
|
||||
lwz r20, 180(r1) # restore R20
|
||||
lwz r21, 184(r1) # restore R21
|
||||
lwz r22, 188(r1) # restore R22
|
||||
lwz r23, 192(r1) # restore R23
|
||||
lwz r24, 196(r1) # restore R24
|
||||
lwz r25, 200(r1) # restore R25
|
||||
lwz r26, 204(r1) # restore R26
|
||||
lwz r27, 208(r1) # restore R27
|
||||
lwz r28, 212(r1) # restore R28
|
||||
lwz r29, 216(r1) # restore R29
|
||||
lwz r30, 220(r1) # restore R30
|
||||
lwz r31, 224(r1) # restore R31
|
||||
lwz r3, 228(r1) # restore hidden
|
||||
|
||||
# restore CR
|
||||
lwz r0, 232(r1)
|
||||
mtcr r0
|
||||
# restore LR
|
||||
lwz r0, 236(r1)
|
||||
mtlr r0
|
||||
# load PC
|
||||
lwz r0, 240(r1)
|
||||
# restore CTR
|
||||
mtctr r0
|
||||
|
||||
# adjust stack
|
||||
addi r1, r1, 244
|
||||
|
||||
# return transfer_t
|
||||
stw r6, 0(r3)
|
||||
stw r5, 4(r3)
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* | TOC | R14 | R15 | R16 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R17 | R18 | R19 | R20 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R21 | R22 | R23 | R24 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R25 | R26 | R27 | R28 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R29 | R30 | R31 | hidden | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | *
|
||||
* ------------------------------------------------- *
|
||||
* | CR | LR | PC | back-chain| *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | *
|
||||
* ------------------------------------------------- *
|
||||
* | cr saved | lr saved | compiler | linker | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | *
|
||||
* ------------------------------------------------- *
|
||||
* | TOC saved | FCTX | DATA | | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.file "jump_ppc64_sysv_elf_gas.S"
|
||||
.globl jump_fcontext
|
||||
#if _CALL_ELF == 2
|
||||
.text
|
||||
.align 2
|
||||
jump_fcontext:
|
||||
addis %r2, %r12, .TOC.-jump_fcontext@ha
|
||||
addi %r2, %r2, .TOC.-jump_fcontext@l
|
||||
.localentry jump_fcontext, . - jump_fcontext
|
||||
#else
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
jump_fcontext:
|
||||
# ifdef _CALL_LINUX
|
||||
.quad .L.jump_fcontext,.TOC.@tocbase,0
|
||||
.type jump_fcontext,@function
|
||||
.text
|
||||
.align 2
|
||||
.L.jump_fcontext:
|
||||
# else
|
||||
.hidden .jump_fcontext
|
||||
.globl .jump_fcontext
|
||||
.quad .jump_fcontext,.TOC.@tocbase,0
|
||||
.size jump_fcontext,24
|
||||
.type .jump_fcontext,@function
|
||||
.text
|
||||
.align 2
|
||||
.jump_fcontext:
|
||||
# endif
|
||||
#endif
|
||||
# reserve space on stack
|
||||
subi %r1, %r1, 184
|
||||
|
||||
#if _CALL_ELF != 2
|
||||
std %r2, 0(%r1) # save TOC
|
||||
#endif
|
||||
std %r14, 8(%r1) # save R14
|
||||
std %r15, 16(%r1) # save R15
|
||||
std %r16, 24(%r1) # save R16
|
||||
std %r17, 32(%r1) # save R17
|
||||
std %r18, 40(%r1) # save R18
|
||||
std %r19, 48(%r1) # save R19
|
||||
std %r20, 56(%r1) # save R20
|
||||
std %r21, 64(%r1) # save R21
|
||||
std %r22, 72(%r1) # save R22
|
||||
std %r23, 80(%r1) # save R23
|
||||
std %r24, 88(%r1) # save R24
|
||||
std %r25, 96(%r1) # save R25
|
||||
std %r26, 104(%r1) # save R26
|
||||
std %r27, 112(%r1) # save R27
|
||||
std %r28, 120(%r1) # save R28
|
||||
std %r29, 128(%r1) # save R29
|
||||
std %r30, 136(%r1) # save R30
|
||||
std %r31, 144(%r1) # save R31
|
||||
#if _CALL_ELF != 2
|
||||
std %r3, 152(%r1) # save hidden
|
||||
#endif
|
||||
|
||||
# save CR
|
||||
mfcr %r0
|
||||
std %r0, 160(%r1)
|
||||
# save LR
|
||||
mflr %r0
|
||||
std %r0, 168(%r1)
|
||||
# save LR as PC
|
||||
std %r0, 176(%r1)
|
||||
|
||||
# store RSP (pointing to context-data) in R6
|
||||
mr %r6, %r1
|
||||
|
||||
#if _CALL_ELF == 2
|
||||
# restore RSP (pointing to context-data) from R3
|
||||
mr %r1, %r3
|
||||
#else
|
||||
# restore RSP (pointing to context-data) from R4
|
||||
mr %r1, %r4
|
||||
|
||||
ld %r2, 0(%r1) # restore TOC
|
||||
#endif
|
||||
ld %r14, 8(%r1) # restore R14
|
||||
ld %r15, 16(%r1) # restore R15
|
||||
ld %r16, 24(%r1) # restore R16
|
||||
ld %r17, 32(%r1) # restore R17
|
||||
ld %r18, 40(%r1) # restore R18
|
||||
ld %r19, 48(%r1) # restore R19
|
||||
ld %r20, 56(%r1) # restore R20
|
||||
ld %r21, 64(%r1) # restore R21
|
||||
ld %r22, 72(%r1) # restore R22
|
||||
ld %r23, 80(%r1) # restore R23
|
||||
ld %r24, 88(%r1) # restore R24
|
||||
ld %r25, 96(%r1) # restore R25
|
||||
ld %r26, 104(%r1) # restore R26
|
||||
ld %r27, 112(%r1) # restore R27
|
||||
ld %r28, 120(%r1) # restore R28
|
||||
ld %r29, 128(%r1) # restore R29
|
||||
ld %r30, 136(%r1) # restore R30
|
||||
ld %r31, 144(%r1) # restore R31
|
||||
#if _CALL_ELF != 2
|
||||
ld %r3, 152(%r1) # restore hidden
|
||||
#endif
|
||||
|
||||
# restore CR
|
||||
ld %r0, 160(%r1)
|
||||
mtcr %r0
|
||||
# restore LR
|
||||
ld %r0, 168(%r1)
|
||||
mtlr %r0
|
||||
|
||||
# load PC
|
||||
ld %r12, 176(%r1)
|
||||
# restore CTR
|
||||
mtctr %r12
|
||||
|
||||
# adjust stack
|
||||
addi %r1, %r1, 184
|
||||
|
||||
#if _CALL_ELF == 2
|
||||
# copy transfer_t into transfer_fn arg registers
|
||||
mr %r3, %r6
|
||||
# arg pointer already in %r4
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
.size jump_fcontext, .-jump_fcontext
|
||||
#else
|
||||
# zero in r3 indicates first jump to context-function
|
||||
cmpdi %r3, 0
|
||||
beq use_entry_arg
|
||||
|
||||
# return transfer_t
|
||||
std %r6, 0(%r3)
|
||||
std %r5, 8(%r3)
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
|
||||
use_entry_arg:
|
||||
# copy transfer_t into transfer_fn arg registers
|
||||
mr %r3, %r6
|
||||
mr %r4, %r5
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
# ifdef _CALL_LINUX
|
||||
.size .jump_fcontext, .-.L.jump_fcontext
|
||||
# else
|
||||
.size .jump_fcontext, .-.jump_fcontext
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* | TOC | R14 | R15 | R16 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R17 | R18 | R19 | R20 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R21 | R22 | R23 | R24 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R25 | R26 | R27 | R28 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R29 | R30 | R31 | hidden | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | *
|
||||
* ------------------------------------------------- *
|
||||
* | CR | LR | PC | back-chain| *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | *
|
||||
* ------------------------------------------------- *
|
||||
* | cr saved | lr saved | compiler | linker | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | *
|
||||
* ------------------------------------------------- *
|
||||
* | TOC saved | FCTX | DATA | | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _jump_fcontext
|
||||
|
||||
_jump_fcontext:
|
||||
; reserve space on stack
|
||||
subi r1, r1, 184
|
||||
|
||||
std r14, 8(r1) ; save R14
|
||||
std r15, 16(r1) ; save R15
|
||||
std r16, 24(r1) ; save R16
|
||||
std r17, 32(r1) ; save R17
|
||||
std r18, 40(r1) ; save R18
|
||||
std r19, 48(r1) ; save R19
|
||||
std r20, 56(r1) ; save R20
|
||||
std r21, 64(r1) ; save R21
|
||||
std r22, 72(r1) ; save R22
|
||||
std r23, 80(r1) ; save R23
|
||||
std r24, 88(r1) ; save R24
|
||||
std r25, 96(r1) ; save R25
|
||||
std r26, 104(r1) ; save R26
|
||||
std r27, 112(r1) ; save R27
|
||||
std r28, 120(r1) ; save R28
|
||||
std r29, 128(r1) ; save R29
|
||||
std r30, 136(r1) ; save R30
|
||||
std r31, 144(r1) ; save R31
|
||||
std r3, 152(r1) ; save hidden
|
||||
|
||||
; save CR
|
||||
mfcr r0
|
||||
std r0, 160(r1)
|
||||
; save LR
|
||||
mflr r0
|
||||
std r0, 168(r1)
|
||||
; save LR as PC
|
||||
std r0, 176(r1)
|
||||
|
||||
; store RSP (pointing to context-data) in R6
|
||||
mr r6, r1
|
||||
|
||||
; restore RSP (pointing to context-data) from R4
|
||||
mr r1, r4
|
||||
|
||||
ld r14, 8(r1) ; restore R14
|
||||
ld r15, 16(r1) ; restore R15
|
||||
ld r16, 24(r1) ; restore R16
|
||||
ld r17, 32(r1) ; restore R17
|
||||
ld r18, 40(r1) ; restore R18
|
||||
ld r19, 48(r1) ; restore R19
|
||||
ld r20, 56(r1) ; restore R20
|
||||
ld r21, 64(r1) ; restore R21
|
||||
ld r22, 72(r1) ; restore R22
|
||||
ld r23, 80(r1) ; restore R23
|
||||
ld r24, 88(r1) ; restore R24
|
||||
ld r25, 96(r1) ; restore R25
|
||||
ld r26, 104(r1) ; restore R26
|
||||
ld r27, 112(r1) ; restore R27
|
||||
ld r28, 120(r1) ; restore R28
|
||||
ld r29, 128(r1) ; restore R29
|
||||
ld r30, 136(r1) ; restore R30
|
||||
ld r31, 144(r1) ; restore R31
|
||||
ld r3, 152(r1) ; restore hidden
|
||||
|
||||
; restore CR
|
||||
ld r0, 160(r1)
|
||||
mtcr r0
|
||||
; restore LR
|
||||
ld r0, 168(r1)
|
||||
mtlr r0
|
||||
|
||||
; load PC
|
||||
ld r12, 176(r1)
|
||||
# restore CTR
|
||||
mtctr r12
|
||||
|
||||
# adjust stack
|
||||
addi r1, r1, 184
|
||||
|
||||
# zero in r3 indicates first jump to context-function
|
||||
cmpdi r3, 0
|
||||
beq use_entry_arg
|
||||
|
||||
# return transfer_t
|
||||
std r6, 0(r3)
|
||||
std r5, 8(r3)
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
|
||||
use_entry_arg:
|
||||
# copy transfer_t into transfer_fn arg registers
|
||||
mr r3, r6
|
||||
mr r4, r5
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
@@ -1,92 +0,0 @@
|
||||
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
.align 2
|
||||
.globl .jump_fcontext
|
||||
.jump_fcontext:
|
||||
# reserve space on stack
|
||||
subi 1, 1, 184
|
||||
|
||||
std 13, 0(1) # save R13
|
||||
std 14, 8(1) # save R14
|
||||
std 15, 16(1) # save R15
|
||||
std 16, 24(1) # save R16
|
||||
std 17, 32(1) # save R17
|
||||
std 18, 40(1) # save R18
|
||||
std 19, 48(1) # save R19
|
||||
std 20, 56(1) # save R20
|
||||
std 21, 64(1) # save R21
|
||||
std 22, 72(1) # save R22
|
||||
std 23, 80(1) # save R23
|
||||
std 24, 88(1) # save R24
|
||||
std 25, 96(1) # save R25
|
||||
std 26, 104(1) # save R26
|
||||
std 27, 112(1) # save R27
|
||||
std 29, 120(1) # save R28
|
||||
std 29, 128(1) # save R29
|
||||
std 30, 136(1) # save R30
|
||||
std 31, 144(1) # save R31
|
||||
std 3, 152(1) # save hidden
|
||||
|
||||
# save CR
|
||||
mfcr 0
|
||||
std 0, 160(1)
|
||||
# save LR
|
||||
mflr 0
|
||||
std 0, 168(1)
|
||||
# save LR as PC
|
||||
std 0, 176(1)
|
||||
|
||||
# store RSP (pointing to context-data) in R6
|
||||
mr 6, 1
|
||||
|
||||
# restore RSP (pointing to context-data) from R4
|
||||
mr 1, 4
|
||||
|
||||
ld 13, 0(1) # restore R13
|
||||
ld 14, 8(1) # restore R14
|
||||
ld 15, 16(1) # restore R15
|
||||
ld 16, 24(1) # restore R16
|
||||
ld 17, 32(1) # restore R17
|
||||
ld 18, 40(1) # restore R18
|
||||
ld 19, 48(1) # restore R19
|
||||
ld 20, 56(1) # restore R20
|
||||
ld 21, 64(1) # restore R21
|
||||
ld 22, 72(1) # restore R22
|
||||
ld 23, 80(1) # restore R23
|
||||
ld 24, 88(1) # restore R24
|
||||
ld 25, 96(1) # restore R25
|
||||
ld 26, 104(1) # restore R26
|
||||
ld 27, 112(1) # restore R27
|
||||
ld 28, 120(1) # restore R28
|
||||
ld 29, 128(1) # restore R29
|
||||
ld 30, 136(1) # restore R30
|
||||
ld 31, 144(1) # restore R31
|
||||
ld 3, 152(1) # restore hidden
|
||||
|
||||
# restore CR
|
||||
ld 0, 160(1)
|
||||
mtcr 0
|
||||
# restore LR
|
||||
ld 0, 168(1)
|
||||
mtlr 0
|
||||
|
||||
# load PC
|
||||
ld 0, 176(1)
|
||||
# restore CTR
|
||||
mtctr 0
|
||||
|
||||
# adjust stack
|
||||
addi 1, 1, 184
|
||||
|
||||
# return transfer_t
|
||||
std 6, 0(3)
|
||||
std 5, 8(3)
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
Copyright Oliver Kowalke 2009.
|
||||
Copyright Thomas Sailer 2013.
|
||||
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)
|
||||
*/
|
||||
|
||||
/*************************************************************************************
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | SEE registers (XMM6-XMM15) | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | SEE registers (XMM6-XMM15) | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0xe40 | 0x44 | 0x48 | 0x4c | 0x50 | 0x54 | 0x58 | 0x5c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | SEE registers (XMM6-XMM15) | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x60 | 0x64 | 0x68 | 0x6c | 0x70 | 0x74 | 0x78 | 0x7c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | SEE registers (XMM6-XMM15) | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 32 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x80 | 0x84 | 0x88 | 0x8c | 0x90 | 0x94 | 0x98 | 0x9c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | SEE registers (XMM6-XMM15) | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0xa0 | 0xa4 | 0xa8 | 0xac | 0xb0 | 0xb4 | 0xb8 | 0xbc | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | fc_mxcsr|fc_x87_cw| <alignment> | fbr_strg | fc_dealloc | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0xc0 | 0xc4 | 0xc8 | 0xcc | 0xd0 | 0xd4 | 0xd8 | 0xdc | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | limit | base | R12 | R13 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0xe0 | 0xe4 | 0xe8 | 0xec | 0xf0 | 0xf4 | 0xf8 | 0xfc | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | R14 | R15 | RDI | RSI | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x100 | 0x104 | 0x108 | 0x10c | 0x110 | 0x114 | 0x118 | 0x11c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | RBX | RBP | hidden | RIP | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x120 | 0x124 | 0x128 | 0x12c | 0x130 | 0x134 | 0x138 | 0x13c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | parameter area | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x140 | 0x144 | 0x148 | 0x14c | 0x150 | 0x154 | 0x158 | 0x15c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | FCTX | DATA | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
**************************************************************************************/
|
||||
|
||||
.file "jump_x86_64_ms_pe_gas.asm"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
.globl jump_fcontext
|
||||
.def jump_fcontext; .scl 2; .type 32; .endef
|
||||
.seh_proc jump_fcontext
|
||||
jump_fcontext:
|
||||
.seh_endprologue
|
||||
|
||||
leaq -0x118(%rsp), %rsp /* prepare stack */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
/* save XMM storage */
|
||||
movaps %xmm6, 0x0(%rsp)
|
||||
movaps %xmm7, 0x10(%rsp)
|
||||
movaps %xmm8, 0x20(%rsp)
|
||||
movaps %xmm9, 0x30(%rsp)
|
||||
movaps %xmm10, 0x40(%rsp)
|
||||
movaps %xmm11, 0x50(%rsp)
|
||||
movaps %xmm12, 0x60(%rsp)
|
||||
movaps %xmm13, 0x70(%rsp)
|
||||
movaps %xmm14, 0x80(%rsp)
|
||||
movaps %xmm15, 0x90(%rsp)
|
||||
stmxcsr 0xa0(%rsp) /* save MMX control- and status-word */
|
||||
fnstcw 0xa4(%rsp) /* save x87 control-word */
|
||||
#endif
|
||||
|
||||
/* load NT_TIB */
|
||||
movq %gs:(0x30), %r10
|
||||
/* save fiber local storage */
|
||||
movq 0x20(%r10), %rax
|
||||
movq %rax, 0xb0(%rsp)
|
||||
/* save current deallocation stack */
|
||||
movq 0x1478(%r10), %rax
|
||||
movq %rax, 0xb8(%rsp)
|
||||
/* save current stack limit */
|
||||
movq 0x10(%r10), %rax
|
||||
movq %rax, 0xc0(%rsp)
|
||||
/* save current stack base */
|
||||
movq 0x08(%r10), %rax
|
||||
movq %rax, 0xc8(%rsp)
|
||||
|
||||
movq %r12, 0xd0(%rsp) /* save R12 */
|
||||
movq %r13, 0xd8(%rsp) /* save R13 */
|
||||
movq %r14, 0xe0(%rsp) /* save R14 */
|
||||
movq %r15, 0xe8(%rsp) /* save R15 */
|
||||
movq %rdi, 0xf0(%rsp) /* save RDI */
|
||||
movq %rsi, 0xf8(%rsp) /* save RSI */
|
||||
movq %rbx, 0x100(%rsp) /* save RBX */
|
||||
movq %rbp, 0x108(%rsp) /* save RBP */
|
||||
|
||||
movq %rcx, 0x110(%rsp) /* save hidden address of transport_t */
|
||||
|
||||
/* preserve RSP (pointing to context-data) in R9 */
|
||||
movq %rsp, %r9
|
||||
|
||||
/* restore RSP (pointing to context-data) from RDX */
|
||||
movq %rdx, %rsp
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
/* restore XMM storage */
|
||||
movaps 0x0(%rsp), %xmm6
|
||||
movaps 0x10(%rsp), %xmm7
|
||||
movaps 0x20(%rsp), %xmm8
|
||||
movaps 0x30(%rsp), %xmm9
|
||||
movaps 0x40(%rsp), %xmm10
|
||||
movaps 0x50(%rsp), %xmm11
|
||||
movaps 0x60(%rsp), %xmm12
|
||||
movaps 0x70(%rsp), %xmm13
|
||||
movaps 0x80(%rsp), %xmm14
|
||||
movaps 0x90(%rsp), %xmm15
|
||||
ldmxcsr 0xa0(%rsp) /* restore MMX control- and status-word */
|
||||
fldcw 0xa4(%rsp) /* restore x87 control-word */
|
||||
#endif
|
||||
|
||||
/* load NT_TIB */
|
||||
movq %gs:(0x30), %r10
|
||||
/* restore fiber local storage */
|
||||
movq 0xb0(%rsp), %rax
|
||||
movq %rax, 0x20(%r10)
|
||||
/* restore current deallocation stack */
|
||||
movq 0xb8(%rsp), %rax
|
||||
movq %rax, 0x1478(%r10)
|
||||
/* restore current stack limit */
|
||||
movq 0xc0(%rsp), %rax
|
||||
movq %rax, 0x10(%r10)
|
||||
/* restore current stack base */
|
||||
movq 0xc8(%rsp), %rax
|
||||
movq %rax, 0x08(%r10)
|
||||
|
||||
movq 0xd0(%rsp), %r12 /* restore R12 */
|
||||
movq 0xd8(%rsp), %r13 /* restore R13 */
|
||||
movq 0xe0(%rsp), %r14 /* restore R14 */
|
||||
movq 0xe8(%rsp), %r15 /* restore R15 */
|
||||
movq 0xf0(%rsp), %rdi /* restore RDI */
|
||||
movq 0xf8(%rsp), %rsi /* restore RSI */
|
||||
movq 0x100(%rsp), %rbx /* restore RBX */
|
||||
movq 0x108(%rsp), %rbp /* restore RBP */
|
||||
|
||||
movq 0x110(%rsp), %rax /* restore hidden address of transport_t */
|
||||
|
||||
leaq 0x118(%rsp), %rsp /* prepare stack */
|
||||
|
||||
/* restore return-address */
|
||||
popq %r10
|
||||
|
||||
/* transport_t returned in RAX */
|
||||
/* return parent fcontext_t */
|
||||
movq %r9, 0x0(%rax)
|
||||
/* return data */
|
||||
movq %r8, 0x8(%rax)
|
||||
|
||||
/* transport_t as 1.arg of context-function */
|
||||
movq %rax, %rcx
|
||||
|
||||
/* indirect jump to context */
|
||||
jmp *%r10
|
||||
.seh_endproc
|
||||
|
||||
.section .drectve
|
||||
.ascii " -export:\"jump_fcontext\""
|
||||
@@ -1,205 +0,0 @@
|
||||
|
||||
; 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)
|
||||
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | SEE registers (XMM6-XMM15) |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | SEE registers (XMM6-XMM15) |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0xe40 | 0x44 | 0x48 | 0x4c | 0x50 | 0x54 | 0x58 | 0x5c |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | SEE registers (XMM6-XMM15) |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0x60 | 0x64 | 0x68 | 0x6c | 0x70 | 0x74 | 0x78 | 0x7c |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | SEE registers (XMM6-XMM15) |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 32 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0x80 | 0x84 | 0x88 | 0x8c | 0x90 | 0x94 | 0x98 | 0x9c |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | SEE registers (XMM6-XMM15) |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0xa0 | 0xa4 | 0xa8 | 0xac | 0xb0 | 0xb4 | 0xb8 | 0xbc |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | fc_mxcsr|fc_x87_cw| <alignment> | fbr_strg | fc_dealloc |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0xc0 | 0xc4 | 0xc8 | 0xcc | 0xd0 | 0xd4 | 0xd8 | 0xdc |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | limit | base | R12 | R13 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0xe0 | 0xe4 | 0xe8 | 0xec | 0xf0 | 0xf4 | 0xf8 | 0xfc |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | R14 | R15 | RDI | RSI |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0x100 | 0x104 | 0x108 | 0x10c | 0x110 | 0x114 | 0x118 | 0x11c |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | RBX | RBP | hidden | RIP |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0x120 | 0x124 | 0x128 | 0x12c | 0x130 | 0x134 | 0x138 | 0x13c |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | parameter area |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | 0x140 | 0x144 | 0x148 | 0x14c | 0x150 | 0x154 | 0x158 | 0x15c |
|
||||
; ----------------------------------------------------------------------------------
|
||||
; | FCTX | DATA | |
|
||||
; ----------------------------------------------------------------------------------
|
||||
|
||||
.code
|
||||
|
||||
jump_fcontext PROC BOOST_CONTEXT_EXPORT FRAME
|
||||
.endprolog
|
||||
|
||||
; prepare stack
|
||||
lea rsp, [rsp-0118h]
|
||||
|
||||
IFNDEF BOOST_USE_TSX
|
||||
; save XMM storage
|
||||
movaps [rsp], xmm6
|
||||
movaps [rsp+010h], xmm7
|
||||
movaps [rsp+020h], xmm8
|
||||
movaps [rsp+030h], xmm9
|
||||
movaps [rsp+040h], xmm10
|
||||
movaps [rsp+050h], xmm11
|
||||
movaps [rsp+060h], xmm12
|
||||
movaps [rsp+070h], xmm13
|
||||
movaps [rsp+080h], xmm14
|
||||
movaps [rsp+090h], xmm15
|
||||
; save MMX control- and status-word
|
||||
stmxcsr [rsp+0a0h]
|
||||
; save x87 control-word
|
||||
fnstcw [rsp+0a4h]
|
||||
ENDIF
|
||||
|
||||
; load NT_TIB
|
||||
mov r10, gs:[030h]
|
||||
; save fiber local storage
|
||||
mov rax, [r10+020h]
|
||||
mov [rsp+0b0h], rax
|
||||
; save current deallocation stack
|
||||
mov rax, [r10+01478h]
|
||||
mov [rsp+0b8h], rax
|
||||
; save current stack limit
|
||||
mov rax, [r10+010h]
|
||||
mov [rsp+0c0h], rax
|
||||
; save current stack base
|
||||
mov rax, [r10+08h]
|
||||
mov [rsp+0c8h], rax
|
||||
|
||||
mov [rsp+0d0h], r12 ; save R12
|
||||
mov [rsp+0d8h], r13 ; save R13
|
||||
mov [rsp+0e0h], r14 ; save R14
|
||||
mov [rsp+0e8h], r15 ; save R15
|
||||
mov [rsp+0f0h], rdi ; save RDI
|
||||
mov [rsp+0f8h], rsi ; save RSI
|
||||
mov [rsp+0100h], rbx ; save RBX
|
||||
mov [rsp+0108h], rbp ; save RBP
|
||||
|
||||
mov [rsp+0110h], rcx ; save hidden address of transport_t
|
||||
|
||||
; preserve RSP (pointing to context-data) in R9
|
||||
mov r9, rsp
|
||||
|
||||
; restore RSP (pointing to context-data) from RDX
|
||||
mov rsp, rdx
|
||||
|
||||
IFNDEF BOOST_USE_TSX
|
||||
; restore XMM storage
|
||||
movaps xmm6, [rsp]
|
||||
movaps xmm7, [rsp+010h]
|
||||
movaps xmm8, [rsp+020h]
|
||||
movaps xmm9, [rsp+030h]
|
||||
movaps xmm10, [rsp+040h]
|
||||
movaps xmm11, [rsp+050h]
|
||||
movaps xmm12, [rsp+060h]
|
||||
movaps xmm13, [rsp+070h]
|
||||
movaps xmm14, [rsp+080h]
|
||||
movaps xmm15, [rsp+090h]
|
||||
; restore MMX control- and status-word
|
||||
ldmxcsr [rsp+0a0h]
|
||||
; save x87 control-word
|
||||
fldcw [rsp+0a4h]
|
||||
ENDIF
|
||||
|
||||
; load NT_TIB
|
||||
mov r10, gs:[030h]
|
||||
; restore fiber local storage
|
||||
mov rax, [rsp+0b0h]
|
||||
mov [r10+020h], rax
|
||||
; restore current deallocation stack
|
||||
mov rax, [rsp+0b8h]
|
||||
mov [r10+01478h], rax
|
||||
; restore current stack limit
|
||||
mov rax, [rsp+0c0h]
|
||||
mov [r10+010h], rax
|
||||
; restore current stack base
|
||||
mov rax, [rsp+0c8h]
|
||||
mov [r10+08h], rax
|
||||
|
||||
mov r12, [rsp+0d0h] ; restore R12
|
||||
mov r13, [rsp+0d8h] ; restore R13
|
||||
mov r14, [rsp+0e0h] ; restore R14
|
||||
mov r15, [rsp+0e8h] ; restore R15
|
||||
mov rdi, [rsp+0f0h] ; restore RDI
|
||||
mov rsi, [rsp+0f8h] ; restore RSI
|
||||
mov rbx, [rsp+0100h] ; restore RBX
|
||||
mov rbp, [rsp+0108h] ; restore RBP
|
||||
|
||||
mov rax, [rsp+0110h] ; restore hidden address of transport_t
|
||||
|
||||
; prepare stack
|
||||
lea rsp, [rsp+0118h]
|
||||
|
||||
; load return-address
|
||||
pop r10
|
||||
|
||||
; transport_t returned in RAX
|
||||
; return parent fcontext_t
|
||||
mov [rax], r9
|
||||
; return data
|
||||
mov [rax+08h], r8
|
||||
|
||||
; transport_t as 1.arg of context-function
|
||||
mov rcx, rax
|
||||
|
||||
; indirect jump to context
|
||||
jmp r10
|
||||
jump_fcontext ENDP
|
||||
END
|
||||
@@ -30,6 +30,7 @@
|
||||
.type jump_fcontext,@function
|
||||
.align 16
|
||||
jump_fcontext:
|
||||
.cfi_startproc
|
||||
leaq -0x38(%rsp), %rsp /* prepare stack */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
@@ -75,6 +76,7 @@ jump_fcontext:
|
||||
|
||||
/* indirect jump to context */
|
||||
jmp *%r8
|
||||
.cfi_endproc
|
||||
.size jump_fcontext,.-jump_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/****************************************************************************************
|
||||
* *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | fc_mxcsr|fc_x87_cw| R12 | R13 | R14 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | R15 | RBX | RBP | RIP | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* *
|
||||
****************************************************************************************/
|
||||
|
||||
.text
|
||||
.globl _jump_fcontext
|
||||
.align 8
|
||||
_jump_fcontext:
|
||||
leaq -0x38(%rsp), %rsp /* prepare stack */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
stmxcsr (%rsp) /* save MMX control- and status-word */
|
||||
fnstcw 0x4(%rsp) /* save x87 control-word */
|
||||
#endif
|
||||
|
||||
movq %r12, 0x8(%rsp) /* save R12 */
|
||||
movq %r13, 0x10(%rsp) /* save R13 */
|
||||
movq %r14, 0x18(%rsp) /* save R14 */
|
||||
movq %r15, 0x20(%rsp) /* save R15 */
|
||||
movq %rbx, 0x28(%rsp) /* save RBX */
|
||||
movq %rbp, 0x30(%rsp) /* save RBP */
|
||||
|
||||
/* store RSP (pointing to context-data) in RAX */
|
||||
movq %rsp, %rax
|
||||
|
||||
/* restore RSP (pointing to context-data) from RDI */
|
||||
movq %rdi, %rsp
|
||||
|
||||
movq 0x38(%rsp), %r8 /* restore return-address */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
ldmxcsr (%rsp) /* restore MMX control- and status-word */
|
||||
fldcw 0x4(%rsp) /* restore x87 control-word */
|
||||
#endif
|
||||
|
||||
movq 0x8(%rsp), %r12 /* restore R12 */
|
||||
movq 0x10(%rsp), %r13 /* restore R13 */
|
||||
movq 0x18(%rsp), %r14 /* restore R14 */
|
||||
movq 0x20(%rsp), %r15 /* restore R15 */
|
||||
movq 0x28(%rsp), %rbx /* restore RBX */
|
||||
movq 0x30(%rsp), %rbp /* restore RBP */
|
||||
|
||||
leaq 0x40(%rsp), %rsp /* prepare stack */
|
||||
|
||||
/* return transfer_t from jump */
|
||||
/* RAX == fctx, RDX == data */
|
||||
movq %rsi, %rdx
|
||||
/* pass transfer_t as first arg in context function */
|
||||
/* RDI == fctx, RSI == data */
|
||||
movq %rax, %rdi
|
||||
|
||||
/* indirect jump to context */
|
||||
jmp *%r8
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
Copyright Edward Nevill + Oliver Kowalke 2015
|
||||
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)
|
||||
*/
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | d8 | d9 | d10 | d11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | d12 | d13 | d14 | d15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x19 | x20 | x21 | x22 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x23 | x24 | x25 | x26 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x27 | x28 | FP | LR | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0xa0| 0xa4| 0xa8| 0xac| | | *
|
||||
* ------------------------------------------------- *
|
||||
* | PC | align | | | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.file "make_arm64_aapcs_elf_gas.S"
|
||||
.text
|
||||
.align 2
|
||||
.global make_fcontext
|
||||
.type make_fcontext, %function
|
||||
make_fcontext:
|
||||
# shift address in x0 (allocated stack) to lower 16 byte boundary
|
||||
and x0, x0, ~0xF
|
||||
|
||||
# reserve space for context-data on context-stack
|
||||
sub x0, x0, #0xb0
|
||||
|
||||
# third arg of make_fcontext() == address of context-function
|
||||
# store address as a PC to jump in
|
||||
str x2, [x0, #0xa0]
|
||||
|
||||
# save address of finish as return-address for context-function
|
||||
# will be entered after context-function returns (LR register)
|
||||
adr x1, finish
|
||||
str x1, [x0, #0x98]
|
||||
|
||||
ret x30 // return pointer to context-data (x0)
|
||||
|
||||
finish:
|
||||
# exit code is zero
|
||||
mov x0, #0
|
||||
# exit application
|
||||
bl _exit
|
||||
|
||||
.size make_fcontext,.-make_fcontext
|
||||
# Mark that we don't need executable stack.
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
Copyright Edward Nevill + Oliver Kowalke 2015
|
||||
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)
|
||||
*/
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | d8 | d9 | d10 | d11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | d12 | d13 | d14 | d15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x19 | x20 | x21 | x22 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x23 | x24 | x25 | x26 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| *
|
||||
* ------------------------------------------------- *
|
||||
* | x27 | x28 | FP | LR | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0xa0| 0xa4| 0xa8| 0xac| | | *
|
||||
* ------------------------------------------------- *
|
||||
* | PC | align | | | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.text
|
||||
.globl _make_fcontext
|
||||
.balign 16
|
||||
|
||||
_make_fcontext:
|
||||
; shift address in x0 (allocated stack) to lower 16 byte boundary
|
||||
and x0, x0, ~0xF
|
||||
|
||||
; reserve space for context-data on context-stack
|
||||
sub x0, x0, #0xb0
|
||||
|
||||
; third arg of make_fcontext() == address of context-function
|
||||
; store address as a PC to jump in
|
||||
str x2, [x0, #0xa0]
|
||||
|
||||
; compute abs address of label finish
|
||||
; 0x0c = 3 instructions * size (4) before label 'finish'
|
||||
|
||||
; TODO: Numeric offset since llvm still does not support labels in ADR. Fix:
|
||||
; http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140407/212336.html
|
||||
adr x1, 0x0c
|
||||
|
||||
; save address of finish as return-address for context-function
|
||||
; will be entered after context-function returns (LR register)
|
||||
str x1, [x0, #0x98]
|
||||
|
||||
ret lr ; return pointer to context-data (x0)
|
||||
|
||||
finish:
|
||||
; exit code is zero
|
||||
mov x0, #0
|
||||
; exit application
|
||||
bl __exit
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| *
|
||||
* ------------------------------------------------- *
|
||||
* |hiddn| v1 | v2 | v3 | v4 | v5 | v6 | v7 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| *
|
||||
* ------------------------------------------------- *
|
||||
* | v8 | lr | pc | FCTX| DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.file "make_arm_aapcs_elf_gas.S"
|
||||
.text
|
||||
.globl make_fcontext
|
||||
.align 2
|
||||
.type make_fcontext,%function
|
||||
.syntax unified
|
||||
make_fcontext:
|
||||
@ shift address in A1 to lower 16 byte boundary
|
||||
bic a1, a1, #15
|
||||
|
||||
@ reserve space for context-data on context-stack
|
||||
sub a1, a1, #124
|
||||
|
||||
@ third arg of make_fcontext() == address of context-function
|
||||
str a3, [a1, #104]
|
||||
|
||||
@ compute address of returned transfer_t
|
||||
add a2, a1, #108
|
||||
mov a3, a2
|
||||
str a3, [a1, #64]
|
||||
|
||||
@ compute abs address of label finish
|
||||
adr a2, finish
|
||||
@ save address of finish as return-address for context-function
|
||||
@ will be entered after context-function returns
|
||||
str a2, [a1, #100]
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
#endif
|
||||
|
||||
bx lr @ return pointer to context-data
|
||||
|
||||
finish:
|
||||
@ exit code is zero
|
||||
mov a1, #0
|
||||
@ exit application
|
||||
bl _exit@PLT
|
||||
.size make_fcontext,.-make_fcontext
|
||||
|
||||
@ Mark that we don't need executable stack.
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s24 | s25 | s26 | s27 | s28 | s29 | s30 | s31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
* ------------------------------------------------- *
|
||||
* | sjlj|hiddn| v1 | v2 | v3 | v4 | v5 | v6 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | v7 | v8 | lr | pc | FCTX| DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.text
|
||||
.globl _make_fcontext
|
||||
.align 2
|
||||
_make_fcontext:
|
||||
@ shift address in A1 to lower 16 byte boundary
|
||||
bic a1, a1, #15
|
||||
|
||||
@ reserve space for context-data on context-stack
|
||||
sub a1, a1, #124
|
||||
|
||||
@ third arg of make_fcontext() == address of context-function
|
||||
str a3, [a1, #108]
|
||||
|
||||
@ compute address of returned transfer_t
|
||||
add a2, a1, #112
|
||||
mov a3, a2
|
||||
str a3, [a1, #68]
|
||||
|
||||
@ compute abs address of label finish
|
||||
adr a2, finish
|
||||
@ save address of finish as return-address for context-function
|
||||
@ will be entered after context-function returns
|
||||
str a2, [a1, #104]
|
||||
|
||||
bx lr @ return pointer to context-data
|
||||
|
||||
finish:
|
||||
@ exit code is zero
|
||||
mov a1, #0
|
||||
@ exit application
|
||||
bl __exit
|
||||
@@ -1,77 +0,0 @@
|
||||
;/*
|
||||
; 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)
|
||||
;*/
|
||||
|
||||
; *******************************************************
|
||||
; * *
|
||||
; * ------------------------------------------------- *
|
||||
; * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
; * ------------------------------------------------- *
|
||||
; * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| *
|
||||
; * ------------------------------------------------- *
|
||||
; * |deall|limit| base|hiddn| v1 | v2 | v3 | v4 | *
|
||||
; * ------------------------------------------------- *
|
||||
; * ------------------------------------------------- *
|
||||
; * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
; * ------------------------------------------------- *
|
||||
; * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
; * ------------------------------------------------- *
|
||||
; * | v5 | v6 | v7 | v8 | lr | pc | FCTX| DATA| *
|
||||
; * ------------------------------------------------- *
|
||||
; * *
|
||||
; *******************************************************
|
||||
|
||||
|
||||
AREA |.text|, CODE
|
||||
ALIGN 4
|
||||
EXPORT make_fcontext
|
||||
IMPORT _exit
|
||||
|
||||
make_fcontext PROC
|
||||
; first arg of make_fcontext() == top of context-stack
|
||||
; save top of context-stack (base) A4
|
||||
mov a4, a1
|
||||
|
||||
; shift address in A1 to lower 16 byte boundary
|
||||
bic a1, a1, #0x0f
|
||||
|
||||
; reserve space for context-data on context-stack
|
||||
sub a1, a1, #0x48
|
||||
|
||||
; save top address of context_stack as 'base'
|
||||
str a4, [a1, #0x8]
|
||||
; second arg of make_fcontext() == size of context-stack
|
||||
; compute bottom address of context-stack (limit)
|
||||
sub a4, a4, a2
|
||||
; save bottom address of context-stack as 'limit'
|
||||
str a4, [a1, #0x4]
|
||||
; save bottom address of context-stack as 'dealloction stack'
|
||||
str a4, [a1, #0x0]
|
||||
|
||||
; third arg of make_fcontext() == address of context-function
|
||||
str a3, [a1, #0x34]
|
||||
|
||||
; compute address of returned transfer_t
|
||||
add a2, a1, #0x38
|
||||
mov a3, a2
|
||||
str a3, [a1, #0xc]
|
||||
|
||||
; compute abs address of label finish
|
||||
adr a2, finish
|
||||
; save address of finish as return-address for context-function
|
||||
; will be entered after context-function returns
|
||||
str a2, [a1, #0x30]
|
||||
|
||||
bx lr ; return pointer to context-data
|
||||
|
||||
finish
|
||||
; exit code is zero
|
||||
mov a1, #0
|
||||
; exit application
|
||||
bl _exit
|
||||
|
||||
ENDP
|
||||
END
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
Copyright Sergue E. Leontiev 2013.
|
||||
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)
|
||||
*/
|
||||
|
||||
// Stub file for universal binary
|
||||
|
||||
#if defined(__i386__)
|
||||
#include "make_i386_sysv_macho_gas.S"
|
||||
#elif defined(__x86_64__)
|
||||
#include "make_x86_64_sysv_macho_gas.S"
|
||||
#elif defined(__ppc__)
|
||||
#include "make_ppc32_sysv_macho_gas.S"
|
||||
#elif defined(__ppc64__)
|
||||
#include "make_ppc64_sysv_macho_gas.S"
|
||||
#else
|
||||
#error "No arch's"
|
||||
#endif
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
Copyright Oliver Kowalke 2009.
|
||||
Copyright Thomas Sailer 2013.
|
||||
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)
|
||||
*/
|
||||
|
||||
/*************************************************************************************
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | 0h | 04h | 08h | 0ch | 010h | 014h | 018h | 01ch | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo| limit | base | fc_seh | EDI | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | 020h | 024h | 028h | 02ch | 030h | 034h | 038h | 03ch | *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
* | ESI | EBX | EBP | EIP | to | data | EH NXT |SEH HNDLR| *
|
||||
* --------------------------------------------------------------------------------- *
|
||||
**************************************************************************************/
|
||||
|
||||
.file "make_i386_ms_pe_gas.asm"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
.globl _make_fcontext
|
||||
.def _make_fcontext; .scl 2; .type 32; .endef
|
||||
_make_fcontext:
|
||||
/* first arg of make_fcontext() == top of context-stack */
|
||||
movl 0x04(%esp), %eax
|
||||
|
||||
/* reserve space for first argument of context-function */
|
||||
/* EAX might already point to a 16byte border */
|
||||
leal -0x8(%eax), %eax
|
||||
|
||||
/* shift address in EAX to lower 16 byte boundary */
|
||||
andl $-16, %eax
|
||||
|
||||
/* reserve space for context-data on context-stack */
|
||||
/* size for fc_mxcsr .. EIP + return-address for context-function */
|
||||
/* on context-function entry: (ESP -0x4) % 8 == 0 */
|
||||
/* additional space is required for SEH */
|
||||
leal -0x40(%eax), %eax
|
||||
|
||||
/* save MMX control- and status-word */
|
||||
stmxcsr (%eax)
|
||||
/* save x87 control-word */
|
||||
fnstcw 0x4(%eax)
|
||||
|
||||
/* first arg of make_fcontext() == top of context-stack */
|
||||
movl 0x4(%esp), %ecx
|
||||
/* save top address of context stack as 'base' */
|
||||
movl %ecx, 0x14(%eax)
|
||||
/* second arg of make_fcontext() == size of context-stack */
|
||||
movl 0x8(%esp), %edx
|
||||
/* negate stack size for LEA instruction (== substraction) */
|
||||
negl %edx
|
||||
/* compute bottom address of context stack (limit) */
|
||||
leal (%ecx,%edx), %ecx
|
||||
/* save bottom address of context-stack as 'limit' */
|
||||
movl %ecx, 0x10(%eax)
|
||||
/* save bottom address of context-stack as 'dealloction stack' */
|
||||
movl %ecx, 0xc(%eax)
|
||||
/* set fiber-storage to zero */
|
||||
xorl %ecx, %ecx
|
||||
movl %ecx, 0x8(%eax)
|
||||
|
||||
/* third arg of make_fcontext() == address of context-function */
|
||||
/* stored in EBX */
|
||||
movl 0xc(%esp), %ecx
|
||||
movl %ecx, 0x24(%eax)
|
||||
|
||||
/* compute abs address of label trampoline */
|
||||
movl $trampoline, %ecx
|
||||
/* save address of trampoline as return-address for context-function */
|
||||
/* will be entered after calling jump_fcontext() first time */
|
||||
movl %ecx, 0x2c(%eax)
|
||||
|
||||
/* compute abs address of label finish */
|
||||
movl $finish, %ecx
|
||||
/* save address of finish as return-address for context-function */
|
||||
/* will be entered after context-function returns */
|
||||
movl %ecx, 0x28(%eax)
|
||||
|
||||
/* traverse current seh chain to get the last exception handler installed by Windows */
|
||||
/* note that on Windows Server 2008 and 2008 R2, SEHOP is activated by default */
|
||||
/* the exception handler chain is tested for the presence of ntdll.dll!FinalExceptionHandler */
|
||||
/* at its end by RaiseException all seh andlers are disregarded if not present and the */
|
||||
/* program is aborted */
|
||||
/* load NT_TIB into ECX */
|
||||
movl %fs:(0x0), %ecx
|
||||
|
||||
walk:
|
||||
/* load 'next' member of current SEH into EDX */
|
||||
movl (%ecx), %edx
|
||||
/* test if 'next' of current SEH is last (== 0xffffffff) */
|
||||
incl %edx
|
||||
jz found
|
||||
decl %edx
|
||||
/* exchange content; ECX contains address of next SEH */
|
||||
xchgl %ecx, %edx
|
||||
/* inspect next SEH */
|
||||
jmp walk
|
||||
|
||||
found:
|
||||
/* load 'handler' member of SEH == address of last SEH handler installed by Windows */
|
||||
movl 0x04(%ecx), %ecx
|
||||
/* save address in ECX as SEH handler for context */
|
||||
movl %ecx, 0x3c(%eax)
|
||||
/* set ECX to -1 */
|
||||
movl $0xffffffff, %ecx
|
||||
/* save ECX as next SEH item */
|
||||
movl %ecx, 0x38(%eax)
|
||||
/* load address of next SEH item */
|
||||
leal 0x38(%eax), %ecx
|
||||
/* save next SEH */
|
||||
movl %ecx, 0x18(%eax)
|
||||
|
||||
/* return pointer to context-data */
|
||||
ret
|
||||
|
||||
trampoline:
|
||||
/* move transport_t for entering context-function */
|
||||
/* FCTX == EAX, DATA == EDX */
|
||||
movl %eax, (%esp)
|
||||
movl %edx, 0x4(%esp)
|
||||
/* label finish as return-address */
|
||||
pushl %ebp
|
||||
/* jump to context-function */
|
||||
jmp *%ebx
|
||||
|
||||
finish:
|
||||
/* ESP points to same address as ESP on entry of context function + 0x4 */
|
||||
xorl %eax, %eax
|
||||
/* exit code is zero */
|
||||
movl %eax, (%esp)
|
||||
/* exit application */
|
||||
call __exit
|
||||
hlt
|
||||
|
||||
.def __exit; .scl 2; .type 32; .endef /* standard C library function */
|
||||
|
||||
.section .drectve
|
||||
.ascii " -export:\"make_fcontext\""
|
||||
@@ -1,140 +0,0 @@
|
||||
|
||||
; 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)
|
||||
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | 0h | 04h | 08h | 0ch | 010h | 014h | 018h | 01ch |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | fc_mxcsr|fc_x87_cw| fc_strg |fc_deallo| limit | base | fc_seh | EDI |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | 020h | 024h | 028h | 02ch | 030h | 034h | 038h | 03ch |
|
||||
; ---------------------------------------------------------------------------------
|
||||
; | ESI | EBX | EBP | EIP | to | data | EH NXT |SEH HNDLR|
|
||||
; ---------------------------------------------------------------------------------
|
||||
|
||||
.386
|
||||
.XMM
|
||||
.model flat, c
|
||||
; standard C library function
|
||||
_exit PROTO, value:SDWORD
|
||||
.code
|
||||
|
||||
make_fcontext PROC BOOST_CONTEXT_EXPORT
|
||||
; first arg of make_fcontext() == top of context-stack
|
||||
mov eax, [esp+04h]
|
||||
|
||||
; reserve space for first argument of context-function
|
||||
; EAX might already point to a 16byte border
|
||||
lea eax, [eax-08h]
|
||||
|
||||
; shift address in EAX to lower 16 byte boundary
|
||||
and eax, -16
|
||||
|
||||
; reserve space for context-data on context-stack
|
||||
; on context-function entry: (ESP -0x4) % 8 == 0
|
||||
; additional space is required for SEH
|
||||
lea eax, [eax-040h]
|
||||
|
||||
; save MMX control- and status-word
|
||||
stmxcsr [eax]
|
||||
; save x87 control-word
|
||||
fnstcw [eax+04h]
|
||||
|
||||
; first arg of make_fcontext() == top of context-stack
|
||||
mov ecx, [esp+04h]
|
||||
; save top address of context stack as 'base'
|
||||
mov [eax+014h], ecx
|
||||
; second arg of make_fcontext() == size of context-stack
|
||||
mov edx, [esp+08h]
|
||||
; negate stack size for LEA instruction (== substraction)
|
||||
neg edx
|
||||
; compute bottom address of context stack (limit)
|
||||
lea ecx, [ecx+edx]
|
||||
; save bottom address of context-stack as 'limit'
|
||||
mov [eax+010h], ecx
|
||||
; save bottom address of context-stack as 'dealloction stack'
|
||||
mov [eax+0ch], ecx
|
||||
; set fiber-storage to zero
|
||||
xor ecx, ecx
|
||||
mov [eax+08h], ecx
|
||||
|
||||
; third arg of make_fcontext() == address of context-function
|
||||
; stored in EBX
|
||||
mov ecx, [esp+0ch]
|
||||
mov [eax+024h], ecx
|
||||
|
||||
; compute abs address of label trampoline
|
||||
mov ecx, trampoline
|
||||
; save address of trampoline as return-address for context-function
|
||||
; will be entered after calling jump_fcontext() first time
|
||||
mov [eax+02ch], ecx
|
||||
|
||||
; compute abs address of label finish
|
||||
mov ecx, finish
|
||||
; save address of finish as return-address for context-function in EBP
|
||||
; will be entered after context-function returns
|
||||
mov [eax+028h], ecx
|
||||
|
||||
; traverse current seh chain to get the last exception handler installed by Windows
|
||||
; note that on Windows Server 2008 and 2008 R2, SEHOP is activated by default
|
||||
; the exception handler chain is tested for the presence of ntdll.dll!FinalExceptionHandler
|
||||
; at its end by RaiseException all seh-handlers are disregarded if not present and the
|
||||
; program is aborted
|
||||
assume fs:nothing
|
||||
; load NT_TIB into ECX
|
||||
mov ecx, fs:[0h]
|
||||
assume fs:error
|
||||
|
||||
walk:
|
||||
; load 'next' member of current SEH into EDX
|
||||
mov edx, [ecx]
|
||||
; test if 'next' of current SEH is last (== 0xffffffff)
|
||||
inc edx
|
||||
jz found
|
||||
dec edx
|
||||
; exchange content; ECX contains address of next SEH
|
||||
xchg edx, ecx
|
||||
; inspect next SEH
|
||||
jmp walk
|
||||
|
||||
found:
|
||||
; load 'handler' member of SEH == address of last SEH handler installed by Windows
|
||||
mov ecx, [ecx+04h]
|
||||
; save address in ECX as SEH handler for context
|
||||
mov [eax+03ch], ecx
|
||||
; set ECX to -1
|
||||
mov ecx, 0ffffffffh
|
||||
; save ECX as next SEH item
|
||||
mov [eax+038h], ecx
|
||||
; load address of next SEH item
|
||||
lea ecx, [eax+038h]
|
||||
; save next SEH
|
||||
mov [eax+018h], ecx
|
||||
|
||||
ret ; return pointer to context-data
|
||||
|
||||
trampoline:
|
||||
; move transport_t for entering context-function
|
||||
; FCTX == EAX, DATA == EDX
|
||||
mov [esp], eax
|
||||
mov [esp+04h], edx
|
||||
push ebp
|
||||
; jump to context-function
|
||||
jmp ebx
|
||||
|
||||
finish:
|
||||
; exit code is zero
|
||||
xor eax, eax
|
||||
mov [esp], eax
|
||||
; exit application
|
||||
call _exit
|
||||
hlt
|
||||
make_fcontext ENDP
|
||||
END
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/****************************************************************************************
|
||||
* *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | hidden | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x20 | 0x24 | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | to | data | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* *
|
||||
****************************************************************************************/
|
||||
|
||||
.file "make_i386_sysv_elf_gas.S"
|
||||
.text
|
||||
.globl make_fcontext
|
||||
.align 2
|
||||
.type make_fcontext,@function
|
||||
make_fcontext:
|
||||
/* first arg of make_fcontext() == top of context-stack */
|
||||
movl 0x4(%esp), %eax
|
||||
|
||||
/* reserve space for first argument of context-function
|
||||
eax might already point to a 16byte border */
|
||||
leal -0x8(%eax), %eax
|
||||
|
||||
/* shift address in EAX to lower 16 byte boundary */
|
||||
andl $-16, %eax
|
||||
|
||||
/* reserve space for context-data on context-stack */
|
||||
leal -0x28(%eax), %eax
|
||||
|
||||
/* third arg of make_fcontext() == address of context-function */
|
||||
/* stored in EBX */
|
||||
movl 0xc(%esp), %ecx
|
||||
movl %ecx, 0x10(%eax)
|
||||
|
||||
/* save MMX control- and status-word */
|
||||
stmxcsr (%eax)
|
||||
/* save x87 control-word */
|
||||
fnstcw 0x4(%eax)
|
||||
|
||||
/* return transport_t */
|
||||
/* FCTX == EDI, DATA == ESI */
|
||||
leal 0x8(%eax), %ecx
|
||||
movl %ecx, 0x1c(%eax)
|
||||
|
||||
/* compute abs address of label trampoline */
|
||||
call 1f
|
||||
/* address of trampoline 1 */
|
||||
1: popl %ecx
|
||||
/* compute abs address of label trampoline */
|
||||
addl $trampoline-1b, %ecx
|
||||
/* save address of trampoline as return address */
|
||||
/* will be entered after calling jump_fcontext() first time */
|
||||
movl %ecx, 0x18(%eax)
|
||||
|
||||
/* compute abs address of label finish */
|
||||
call 2f
|
||||
/* address of label 2 */
|
||||
2: popl %ecx
|
||||
/* compute abs address of label finish */
|
||||
addl $finish-2b, %ecx
|
||||
/* save address of finish as return-address for context-function */
|
||||
/* will be entered after context-function returns */
|
||||
movl %ecx, 0x14(%eax)
|
||||
|
||||
ret /* return pointer to context-data */
|
||||
|
||||
trampoline:
|
||||
/* move transport_t for entering context-function */
|
||||
movl %edi, (%esp)
|
||||
movl %esi, 0x4(%esp)
|
||||
pushl %ebp
|
||||
/* jump to context-function */
|
||||
jmp *%ebx
|
||||
|
||||
finish:
|
||||
call 3f
|
||||
/* address of label 3 */
|
||||
3: popl %ebx
|
||||
/* compute address of GOT and store it in EBX */
|
||||
addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %ebx
|
||||
|
||||
/* exit code is zero */
|
||||
xorl %eax, %eax
|
||||
movl %eax, (%esp)
|
||||
/* exit application */
|
||||
call _exit@PLT
|
||||
hlt
|
||||
.size make_fcontext,.-make_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/****************************************************************************************
|
||||
* *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | fc_mxcsr|fc_x87_cw| EDI | ESI | EBX | EBP | EIP | to | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | 0x20 | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* | data | | *
|
||||
* ---------------------------------------------------------------------------------- *
|
||||
* *
|
||||
****************************************************************************************/
|
||||
|
||||
.text
|
||||
.globl _make_fcontext
|
||||
.align 2
|
||||
_make_fcontext:
|
||||
/* first arg of make_fcontext() == top of context-stack */
|
||||
movl 0x4(%esp), %eax
|
||||
|
||||
/* reserve space for first argument of context-function
|
||||
eax might already point to a 16byte border */
|
||||
leal -0x8(%eax), %eax
|
||||
|
||||
/* shift address in EAX to lower 16 byte boundary */
|
||||
andl $-16, %eax
|
||||
|
||||
/* reserve space for context-data on context-stack */
|
||||
leal -0x2c(%eax), %eax
|
||||
|
||||
/* third arg of make_fcontext() == address of context-function */
|
||||
/* stored in EBX */
|
||||
movl 0xc(%esp), %ecx
|
||||
movl %ecx, 0x10(%eax)
|
||||
|
||||
/* save MMX control- and status-word */
|
||||
stmxcsr (%eax)
|
||||
/* save x87 control-word */
|
||||
fnstcw 0x4(%eax)
|
||||
|
||||
/* compute abs address of label trampoline */
|
||||
call 1f
|
||||
/* address of trampoline 1 */
|
||||
1: popl %ecx
|
||||
/* compute abs address of label trampoline */
|
||||
addl $trampoline-1b, %ecx
|
||||
/* save address of trampoline as return address */
|
||||
/* will be entered after calling jump_fcontext() first time */
|
||||
movl %ecx, 0x18(%eax)
|
||||
|
||||
/* compute abs address of label finish */
|
||||
call 2f
|
||||
/* address of label 2 */
|
||||
2: popl %ecx
|
||||
/* compute abs address of label finish */
|
||||
addl $finish-2b, %ecx
|
||||
/* save address of finish as return-address for context-function */
|
||||
/* will be entered after context-function returns */
|
||||
movl %ecx, 0x14(%eax)
|
||||
|
||||
ret /* return pointer to context-data */
|
||||
|
||||
trampoline:
|
||||
/* move transport_t for entering context-function */
|
||||
movl %eax, (%esp)
|
||||
movl %edx, 0x4(%esp)
|
||||
pushl %ebp
|
||||
/* jump to context-function */
|
||||
jmp *%ebx
|
||||
|
||||
finish:
|
||||
/* exit code is zero */
|
||||
xorl %eax, %eax
|
||||
movl %eax, (%esp)
|
||||
/* exit application */
|
||||
call __exit
|
||||
hlt
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
Copyright Sergue E. Leontiev 2013.
|
||||
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)
|
||||
*/
|
||||
|
||||
// Stub file for universal binary
|
||||
|
||||
#if defined(__i386__)
|
||||
#include "make_i386_sysv_macho_gas.S"
|
||||
#elif defined(__x86_64__)
|
||||
#include "make_x86_64_sysv_macho_gas.S"
|
||||
#else
|
||||
#error "No arch's"
|
||||
#endif
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F20 | F22 | F24 | F26 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F28 | F30 | S0 | S1 | S2 | S3 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | S4 | S5 | S6 | S7 | FP |hiddn| RA | PC | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | ABI ARGS | GP | FCTX| DATA| | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
* *****************************************************/
|
||||
|
||||
.file "make_mips32_o32_elf_gas.S"
|
||||
.text
|
||||
.globl make_fcontext
|
||||
.align 2
|
||||
.type make_fcontext,@function
|
||||
.ent make_fcontext
|
||||
make_fcontext:
|
||||
#ifdef __PIC__
|
||||
.set noreorder
|
||||
.cpload $t9
|
||||
.set reorder
|
||||
#endif
|
||||
# shift address in A0 to lower 16 byte boundary
|
||||
li $v1, -16 # 0xfffffffffffffff0
|
||||
and $v0, $v1, $a0
|
||||
|
||||
# reserve space for context-data on context-stack
|
||||
# includes an extra 32 bytes for:
|
||||
# - 16-byte incoming argument area required by mips ABI used when
|
||||
# jump_context calls the initial function
|
||||
# - 4 bytes to save our GP register used in finish
|
||||
# - 8 bytes to as space for transfer_t returned to finish
|
||||
# - 4 bytes for alignment
|
||||
addiu $v0, $v0, -128
|
||||
|
||||
# third arg of make_fcontext() == address of context-function
|
||||
sw $a2, 92($v0)
|
||||
# save global pointer in context-data
|
||||
sw $gp, 112($v0)
|
||||
|
||||
# compute address of returned transfer_t
|
||||
addiu $t0, $v0, 116
|
||||
sw $t0, 84($v0)
|
||||
|
||||
# compute abs address of label finish
|
||||
la $t9, finish
|
||||
# save address of finish as return-address for context-function
|
||||
# will be entered after context-function returns
|
||||
sw $t9, 88($v0)
|
||||
|
||||
jr $ra # return pointer to context-data
|
||||
|
||||
finish:
|
||||
# reload our gp register (needed for la)
|
||||
lw $gp, 16($sp)
|
||||
|
||||
# call _exit(0)
|
||||
# the previous function should have left the 16 bytes incoming argument
|
||||
# area on the stack which we reuse for calling _exit
|
||||
la $t9, _exit
|
||||
move $a0, $zero
|
||||
jr $t9
|
||||
.end make_fcontext
|
||||
.size make_fcontext, .-make_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
Copyright Jiaxun Yang 2018.
|
||||
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)
|
||||
*/
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 8 | 16 | 24 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F24 | F25 | F26 | F27 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 40 | 48 | 56 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F28 | F29 | F30 | F31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 72 | 80 | 88 | *
|
||||
* ------------------------------------------------- *
|
||||
* | S0 | S1 | S2 | S3 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | S4 | S5 | S6 | S7 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | FP | GP | RA | PC | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
* *****************************************************/
|
||||
|
||||
.file "make_mips64_n64_elf_gas.S"
|
||||
.text
|
||||
.globl make_fcontext
|
||||
.align 2
|
||||
.type make_fcontext,@function
|
||||
.ent make_fcontext
|
||||
make_fcontext:
|
||||
#ifdef __PIC__
|
||||
.set noreorder
|
||||
.cpload $t9
|
||||
.set reorder
|
||||
#endif
|
||||
# shift address in A0 to lower 16 byte boundary
|
||||
li $v1, 0xfffffffffffffff0
|
||||
and $v0, $v1, $a0
|
||||
|
||||
# reserve space for context-data on context-stack
|
||||
daddiu $v0, $v0, -160
|
||||
|
||||
# third arg of make_fcontext() == address of context-function
|
||||
sd $a2, 152($v0)
|
||||
# save global pointer in context-data
|
||||
sd $gp, 136($v0)
|
||||
|
||||
# psudo instruction compute abs address of label finish based on GP
|
||||
dla $t9, finish
|
||||
|
||||
# save address of finish as return-address for context-function
|
||||
# will be entered after context-function returns
|
||||
sd $t9, 144($v0)
|
||||
|
||||
jr $ra # return pointer to context-data
|
||||
|
||||
finish:
|
||||
# reload our gp register (needed for la)
|
||||
daddiu $t0, $sp, -160
|
||||
ld $gp, 136($t0)
|
||||
|
||||
# call _exit(0)
|
||||
# the previous function should have left the 16 bytes incoming argument
|
||||
# area on the stack which we reuse for calling _exit
|
||||
dla $t9, _exit
|
||||
move $a0, $zero
|
||||
jr $t9
|
||||
.end make_fcontext
|
||||
.size make_fcontext, .-make_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user