mirror of
https://github.com/boostorg/context.git
synced 2026-01-19 04:02:17 +00:00
Merge branch 'develop' into mips
This commit is contained in:
29
.drone.star
Normal file
29
.drone.star
Normal file
@@ -0,0 +1,29 @@
|
||||
# Use, modification, and distribution are
|
||||
# subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE.txt)
|
||||
#
|
||||
# Copyright Rene Rivera 2020.
|
||||
|
||||
# For Drone CI we use the Starlark scripting language to reduce duplication.
|
||||
# As the yaml syntax for Drone CI is rather limited.
|
||||
#
|
||||
#
|
||||
globalenv={}
|
||||
linuxglobalimage="cppalliance/droneubuntu1604:1"
|
||||
windowsglobalimage="cppalliance/dronevs2019"
|
||||
|
||||
def main(ctx):
|
||||
return [
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++ CXXSTD=11 Job 0", "g++", packages="", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++', 'CXXSTD': '11', 'DRONE_JOB_UUID': 'b6589fc6ab'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-5 CXXSTD=11,14,1z Job 1", "g++-5", packages="g++-5", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-5', 'CXXSTD': '11,14,1z', 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-6 CXXSTD=11,14,1z Job 2", "g++-6", packages="g++-6", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-6', 'CXXSTD': '11,14,1z', 'DRONE_JOB_UUID': 'da4b9237ba'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=gcc COMPILER=g++-7 CXXSTD=11,14,17 Job 3", "g++-7", packages="g++-7", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-7', 'CXXSTD': '11,14,17', 'DRONE_JOB_UUID': '77de68daec'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++ CXXSTD=11 Job 4", "clang++", packages="", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', 'DRONE_JOB_UUID': '1b64538924'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=11, Job 5", "clang++-4.0", packages="clang-4.0 libstdc++-6-dev", llvm_os="xenial", llvm_ver="4.0", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-4.0', 'CXXSTD': '11,14,1z', 'DRONE_JOB_UUID': 'ac3478d69a'}, globalenv=globalenv),
|
||||
linux_cxx("TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=11, Job 6", "clang++-5.0", packages="clang-5.0 libstdc++-7-dev", llvm_os="xenial", llvm_ver="5.0", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-5.0', 'CXXSTD': '11,14,1z', 'DRONE_JOB_UUID': 'c1dfd96eea'}, globalenv=globalenv),
|
||||
osx_cxx("TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1 Job 7", "clang++", packages="", buildtype="boost", buildscript="drone", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11,14,1z', 'DRONE_JOB_UUID': '902ba3cda1'}, globalenv=globalenv),
|
||||
osx_cxx("TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1 Job 8", "clang++", packages="", buildtype="boost", buildscript="drone", xcode_version="9.1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11,14,1z', 'DRONE_JOB_UUID': 'fe5dbbcea5'}, globalenv=globalenv),
|
||||
]
|
||||
|
||||
# from https://github.com/boostorg/boost-ci
|
||||
load("@boost_ci//ci/drone/:functions.star", "linux_cxx","windows_cxx","osx_cxx","freebsd_cxx")
|
||||
37
.drone/drone.sh
Executable file
37
.drone/drone.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2020 Rene Rivera, Sam Darwin
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set -e
|
||||
export TRAVIS_BUILD_DIR=$(pwd)
|
||||
export DRONE_BUILD_DIR=$(pwd)
|
||||
export TRAVIS_BRANCH=$DRONE_BRANCH
|
||||
export VCS_COMMIT_ID=$DRONE_COMMIT
|
||||
export GIT_COMMIT=$DRONE_COMMIT
|
||||
export REPO_NAME=$DRONE_REPO
|
||||
export PATH=~/.local/bin:/usr/local/bin:$PATH
|
||||
|
||||
if [ "$DRONE_JOB_BUILDTYPE" == "boost" ]; then
|
||||
|
||||
echo '==================================> INSTALL'
|
||||
|
||||
BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
git submodule update --init tools/build
|
||||
git submodule update --init libs/config
|
||||
git submodule update --init tools/boostdep
|
||||
cp -r $TRAVIS_BUILD_DIR/* libs/context
|
||||
python tools/boostdep/depinst/depinst.py context
|
||||
./bootstrap.sh
|
||||
./b2 headers
|
||||
|
||||
echo '==================================> SCRIPT'
|
||||
|
||||
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
|
||||
./b2 -j 3 libs/context/test toolset=$TOOLSET cxxstd=$CXXSTD
|
||||
|
||||
fi
|
||||
309
.github/workflows/ci.yml
vendored
Normal file
309
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
name: GitHub Actions CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- githubactions*
|
||||
- feature/**
|
||||
- fix/**
|
||||
- pr/**
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: "TOOLSET=gcc COMPILER=g++ CXXSTD=11 Job 0"
|
||||
buildtype: "boost"
|
||||
packages: ""
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-20.04"
|
||||
container: "ubuntu:16.04"
|
||||
cxx: "g++"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
toolset: "gcc"
|
||||
compiler: "g++"
|
||||
cxxstd: "11"
|
||||
- name: "TOOLSET=gcc COMPILER=g++-5 CXXSTD=11,14,1z Job 1"
|
||||
buildtype: "boost"
|
||||
packages: "g++-5"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-20.04"
|
||||
container: "ubuntu:16.04"
|
||||
cxx: "g++-5"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
toolset: "gcc"
|
||||
compiler: "g++-5"
|
||||
cxxstd: "11,14,1z"
|
||||
- name: "TOOLSET=gcc COMPILER=g++-6 CXXSTD=11,14,1z Job 2"
|
||||
buildtype: "boost"
|
||||
packages: "g++-6"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-20.04"
|
||||
container: "ubuntu:16.04"
|
||||
cxx: "g++-6"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
toolset: "gcc"
|
||||
compiler: "g++-6"
|
||||
cxxstd: "11,14,1z"
|
||||
- name: "TOOLSET=gcc COMPILER=g++-7 CXXSTD=11,14,17 Job 3"
|
||||
buildtype: "boost"
|
||||
packages: "g++-7"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-20.04"
|
||||
container: "ubuntu:16.04"
|
||||
cxx: "g++-7"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
toolset: "gcc"
|
||||
compiler: "g++-7"
|
||||
cxxstd: "11,14,17"
|
||||
- name: "TOOLSET=clang COMPILER=clang++ CXXSTD=11 Job 4"
|
||||
buildtype: "boost"
|
||||
packages: ""
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-18.04"
|
||||
cxx: "clang++"
|
||||
sources: ""
|
||||
llvm_os: ""
|
||||
llvm_ver: ""
|
||||
toolset: "clang"
|
||||
compiler: "clang++"
|
||||
cxxstd: "11"
|
||||
- name: "TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=11, Job 5"
|
||||
buildtype: "boost"
|
||||
packages: "clang-4.0 libstdc++-6-dev"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-20.04"
|
||||
container: "ubuntu:16.04"
|
||||
cxx: "clang++-4.0"
|
||||
sources: ""
|
||||
llvm_os: "xenial"
|
||||
llvm_ver: "4.0"
|
||||
toolset: "clang"
|
||||
compiler: "clang++-4.0"
|
||||
cxxstd: "11,14"
|
||||
- name: "TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=11, Job 6"
|
||||
buildtype: "boost"
|
||||
packages: "clang-5.0 libstdc++-7-dev"
|
||||
packages_to_remove: ""
|
||||
os: "ubuntu-20.04"
|
||||
container: "ubuntu:16.04"
|
||||
cxx: "clang++-5.0"
|
||||
sources: ""
|
||||
llvm_os: "xenial"
|
||||
llvm_ver: "5.0"
|
||||
toolset: "clang"
|
||||
compiler: "clang++-5.0"
|
||||
cxxstd: "11,14,1z"
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
|
||||
steps:
|
||||
- name: Check if running in container
|
||||
if: matrix.container != ''
|
||||
run: echo "GHA_CONTAINER=${{ matrix.container }}" >> $GITHUB_ENV
|
||||
- name: If running in container, upgrade packages
|
||||
if: matrix.container != ''
|
||||
run: |
|
||||
apt-get -o Acquire::Retries=3 update && DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata && apt-get -o Acquire::Retries=3 install -y sudo software-properties-common wget curl apt-transport-https make apt-file sudo unzip libssl-dev build-essential autotools-dev autoconf automake g++ libc++-helpers python ruby cpio gcc-multilib g++-multilib pkgconf python3 ccache libpython-dev
|
||||
sudo apt-add-repository ppa:git-core/ppa
|
||||
sudo apt-get -o Acquire::Retries=3 update && apt-get -o Acquire::Retries=3 -y install git
|
||||
python_version=$(python3 -c 'import sys; print("{0.major}.{0.minor}".format(sys.version_info))')
|
||||
sudo wget https://bootstrap.pypa.io/pip/$python_version/get-pip.py
|
||||
sudo python3 get-pip.py
|
||||
sudo /usr/local/bin/pip install cmake
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: linux
|
||||
shell: bash
|
||||
env:
|
||||
CXX: ${{ matrix.cxx }}
|
||||
SOURCES: ${{ matrix.sources }}
|
||||
LLVM_OS: ${{ matrix.llvm_os }}
|
||||
LLVM_VER: ${{ matrix.llvm_ver }}
|
||||
PACKAGES: ${{ matrix.packages }}
|
||||
PACKAGES_TO_REMOVE: ${{ matrix.packages_to_remove }}
|
||||
JOB_BUILDTYPE: ${{ matrix.buildtype }}
|
||||
TOOLSET: ${{ matrix.toolset }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
CXXSTD: ${{ matrix.cxxstd }}
|
||||
TRAVIS_BRANCH: ${{ github.base_ref }}
|
||||
TRAVIS_OS_NAME: "linux"
|
||||
run: |
|
||||
echo '==================================> SETUP'
|
||||
echo '==================================> PACKAGES'
|
||||
set -e
|
||||
if [ -n "$PACKAGES_TO_REMOVE" ]; then sudo apt-get purge -y $PACKAGES_TO_REMOVE; fi
|
||||
echo ">>>>> APT: REPO.."
|
||||
for i in {1..3}; do sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test" && break || sleep 2; done
|
||||
|
||||
if test -n "${LLVM_OS}" ; then
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
if test -n "${LLVM_VER}" ; then
|
||||
sudo -E apt-add-repository "deb http://apt.llvm.org/${LLVM_OS}/ llvm-toolchain-${LLVM_OS}-${LLVM_VER} main"
|
||||
else
|
||||
# Snapshot (i.e. trunk) build of clang
|
||||
sudo -E apt-add-repository "deb http://apt.llvm.org/${LLVM_OS}/ llvm-toolchain-${LLVM_OS} main"
|
||||
fi
|
||||
fi
|
||||
echo ">>>>> APT: UPDATE.."
|
||||
sudo -E apt-get -o Acquire::Retries=3 update
|
||||
if test -n "${SOURCES}" ; then
|
||||
echo ">>>>> APT: INSTALL SOURCES.."
|
||||
for SOURCE in $SOURCES; do
|
||||
sudo -E apt-add-repository ppa:$SOURCE
|
||||
done
|
||||
fi
|
||||
echo ">>>>> APT: INSTALL ${PACKAGES}.."
|
||||
sudo -E DEBIAN_FRONTEND=noninteractive apt-get -o Acquire::Retries=3 -y --no-install-suggests --no-install-recommends install ${PACKAGES}
|
||||
|
||||
echo '==================================> INSTALL AND COMPILE'
|
||||
set -e
|
||||
export TRAVIS_BUILD_DIR=$(pwd)
|
||||
export TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')}
|
||||
export VCS_COMMIT_ID=$GITHUB_SHA
|
||||
export GIT_COMMIT=$GITHUB_SHA
|
||||
export REPO_NAME=$(basename $GITHUB_REPOSITORY)
|
||||
export USER=$(whoami)
|
||||
export CC=${CC:-gcc}
|
||||
export PATH=~/.local/bin:/usr/local/bin:$PATH
|
||||
|
||||
if [ "$JOB_BUILDTYPE" == "boost" ]; then
|
||||
|
||||
echo '==================================> INSTALL'
|
||||
|
||||
BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
git submodule update --init tools/build
|
||||
git submodule update --init libs/config
|
||||
git submodule update --init tools/boostdep
|
||||
cp -r $TRAVIS_BUILD_DIR/* libs/context
|
||||
python tools/boostdep/depinst/depinst.py context
|
||||
./bootstrap.sh
|
||||
./b2 headers
|
||||
|
||||
echo '==================================> SCRIPT'
|
||||
|
||||
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
|
||||
./b2 -j 3 libs/context/test toolset=$TOOLSET cxxstd=$CXXSTD
|
||||
|
||||
fi
|
||||
#
|
||||
# osx:
|
||||
# strategy:
|
||||
# fail-fast: false
|
||||
# matrix:
|
||||
# include:
|
||||
#
|
||||
# Github Actions only supports certain Xcode versions
|
||||
# Change (or delete) the Xcode version for this job.
|
||||
#
|
||||
# - name: "TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1 Job 7"
|
||||
# buildtype: "boost"
|
||||
# packages: ""
|
||||
# os: "macos-10.15"
|
||||
# cxx: "clang++"
|
||||
# sources: ""
|
||||
# llvm_os: ""
|
||||
# llvm_ver: ""
|
||||
# xcode_version: "8.3"
|
||||
# toolset: "clang"
|
||||
# compiler: "clang++"
|
||||
# cxxstd: "11,14,1z"
|
||||
#
|
||||
# Github Actions only supports certain Xcode versions
|
||||
# Change (or delete) the Xcode version for this job.
|
||||
#
|
||||
# - name: "TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1 Job 8"
|
||||
# buildtype: "boost"
|
||||
# packages: ""
|
||||
# os: "macos-10.15"
|
||||
# cxx: "clang++"
|
||||
# sources: ""
|
||||
# llvm_os: ""
|
||||
# llvm_ver: ""
|
||||
# xcode_version: "9.1"
|
||||
# toolset: "clang"
|
||||
# compiler: "clang++"
|
||||
# cxxstd: "11,14,1z"
|
||||
#
|
||||
#
|
||||
# runs-on: ${{ matrix.os }}
|
||||
#
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
#
|
||||
# - name: Set DEVELOPER_DIR
|
||||
# if: matrix.xcode_version != ''
|
||||
# run: echo "DEVELOPER_DIR=/Applications/Xcode_${{ matrix.xcode_version }}.app/Contents/Developer" >> $GITHUB_ENV
|
||||
# - name: Test DEVELOPER_DIR
|
||||
# run: echo $DEVELOPER_DIR
|
||||
#
|
||||
# - name: "osx"
|
||||
# shell: bash
|
||||
# env:
|
||||
# CXX: ${{ matrix.cxx }}
|
||||
# SOURCES: ${{ matrix.sources }}
|
||||
# LLVM_OS: ${{ matrix.llvm_os }}
|
||||
# LLVM_VER: ${{ matrix.llvm_ver }}
|
||||
# PACKAGES: ${{ matrix.packages }}
|
||||
# JOB_BUILDTYPE: ${{ matrix.buildtype }}
|
||||
# TOOLSET: ${{ matrix.toolset }}
|
||||
# COMPILER: ${{ matrix.compiler }}
|
||||
# CXXSTD: ${{ matrix.cxxstd }}
|
||||
# TRAVIS_BRANCH: ${{ github.base_ref }}
|
||||
# TRAVIS_OS_NAME: "osx"
|
||||
# run: |
|
||||
# echo '==================================> SETUP'
|
||||
# set -e
|
||||
# sudo mv /Library/Developer/CommandLineTools /Library/Developer/CommandLineTools.bck
|
||||
# echo '==================================> PACKAGES'
|
||||
# echo '==================================> INSTALL AND COMPILE'
|
||||
# set -e
|
||||
# export TRAVIS_BUILD_DIR=$(pwd)
|
||||
# export TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')}
|
||||
# export VCS_COMMIT_ID=$GITHUB_SHA
|
||||
# export GIT_COMMIT=$GITHUB_SHA
|
||||
# export REPO_NAME=$(basename $GITHUB_REPOSITORY)
|
||||
# export USER=$(whoami)
|
||||
# export CC=${CC:-gcc}
|
||||
# export PATH=~/.local/bin:/usr/local/bin:$PATH
|
||||
#
|
||||
# if [ "$JOB_BUILDTYPE" == "boost" ]; then
|
||||
#
|
||||
# echo '==================================> INSTALL'
|
||||
#
|
||||
# BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
# cd ..
|
||||
# git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
|
||||
# cd boost-root
|
||||
# git submodule update --init tools/build
|
||||
# git submodule update --init libs/config
|
||||
# git submodule update --init tools/boostdep
|
||||
# cp -r $TRAVIS_BUILD_DIR/* libs/context
|
||||
# python tools/boostdep/depinst/depinst.py context
|
||||
# ./bootstrap.sh
|
||||
# ./b2 headers
|
||||
#
|
||||
# echo '==================================> SCRIPT'
|
||||
#
|
||||
# echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
|
||||
# ./b2 -j 3 libs/context/test toolset=$TOOLSET cxxstd=$CXXSTD
|
||||
#
|
||||
# fi
|
||||
202
CMakeLists.txt
Normal file
202
CMakeLists.txt
Normal file
@@ -0,0 +1,202 @@
|
||||
# Copyright 2020, 2021 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.16)
|
||||
|
||||
project(boost_context VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
# Build features
|
||||
|
||||
## Binary format
|
||||
|
||||
if(WIN32)
|
||||
set(_default_binfmt pe)
|
||||
elseif(APPLE)
|
||||
set(_default_binfmt mach-o)
|
||||
else()
|
||||
set(_default_binfmt elf)
|
||||
endif()
|
||||
|
||||
set(BOOST_CONTEXT_BINARY_FORMAT "${_default_binfmt}" CACHE STRING "Boost.Context binary format (elf, mach-o, pe, xcoff)")
|
||||
set_property(CACHE BOOST_CONTEXT_BINARY_FORMAT PROPERTY STRINGS elf mach-o pe xcoff)
|
||||
|
||||
unset(_default_binfmt)
|
||||
|
||||
## ABI
|
||||
|
||||
if(WIN32)
|
||||
set(_default_abi ms)
|
||||
else()
|
||||
set(_default_abi sysv)
|
||||
endif()
|
||||
|
||||
set(BOOST_CONTEXT_ABI "${_default_abi}" CACHE STRING "Boost.Context ABI (aapcs, eabi, ms, n32, n64, o32, o64, sysv, x32)")
|
||||
set_property(CACHE BOOST_CONTEXT_ABI PROPERTY STRINGS aapcs eabi ms n32 n64 o32 o64 sysv x32)
|
||||
|
||||
unset(_default_abi)
|
||||
|
||||
## Arch-and-model
|
||||
|
||||
math(EXPR _bits "${CMAKE_SIZEOF_VOID_P}*8")
|
||||
|
||||
if(_bits EQUAL 32)
|
||||
set(_default_arch i386)
|
||||
else()
|
||||
set(_default_arch x86_64)
|
||||
endif()
|
||||
|
||||
set(BOOST_CONTEXT_ARCHITECTURE "${_default_arch}" CACHE STRING "Boost.Context architecture (arm, arm64, mips32, mips64, ppc32, ppc64, riscv64, s390x, i386, x86_64, combined)")
|
||||
set_property(CACHE BOOST_CONTEXT_ARCHITECTURE PROPERTY STRINGS arm arm64 mips32 mips64 ppc32 ppc64 riscv64 s390x i386 x86_64 combined)
|
||||
|
||||
unset(_bits)
|
||||
unset(_default_arch)
|
||||
|
||||
## Assembler type
|
||||
|
||||
if(MSVC)
|
||||
set(_default_asm masm)
|
||||
else()
|
||||
set(_default_asm gas)
|
||||
endif()
|
||||
|
||||
set(BOOST_CONTEXT_ASSEMBLER "${_default_asm}" CACHE STRING "Boost.Context assembler (masm, gas, armasm)")
|
||||
set_property(CACHE BOOST_CONTEXT_ASSEMBLER PROPERTY STRINGS masm gas armasm)
|
||||
|
||||
unset(_default_asm)
|
||||
|
||||
## Assembler source suffix
|
||||
|
||||
if(BOOST_CONTEXT_BINARY_FORMAT STREQUAL pe)
|
||||
set(_default_ext .asm)
|
||||
elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL gas)
|
||||
set(_default_ext .S)
|
||||
else()
|
||||
set(_default_ext .asm)
|
||||
endif()
|
||||
|
||||
set(BOOST_CONTEXT_ASM_SUFFIX "${_default_ext}" CACHE STRING "Boost.Context assembler source suffix (.asm, .S)")
|
||||
set_property(CACHE BOOST_CONTEXT_ASM_SUFFIX PROPERTY STRINGS .asm .S)
|
||||
|
||||
unset(_default_ext)
|
||||
|
||||
## Implementation
|
||||
|
||||
set(_default_impl fcontext)
|
||||
|
||||
set(BOOST_CONTEXT_IMPLEMENTATION "${_default_impl}" CACHE STRING "Boost.Context implementation (fcontext, ucontext, winfib)")
|
||||
set_property(CACHE BOOST_CONTEXT_IMPLEMENTATION PROPERTY STRINGS fcontext ucontext winfib)
|
||||
|
||||
unset(_default_impl)
|
||||
|
||||
#
|
||||
|
||||
message(STATUS "Boost.Context: "
|
||||
"architecture ${BOOST_CONTEXT_ARCHITECTURE}, "
|
||||
"binary format ${BOOST_CONTEXT_BINARY_FORMAT}, "
|
||||
"ABI ${BOOST_CONTEXT_ABI}, "
|
||||
"assembler ${BOOST_CONTEXT_ASSEMBLER}, "
|
||||
"suffix ${BOOST_CONTEXT_ASM_SUFFIX}, "
|
||||
"implementation ${BOOST_CONTEXT_IMPLEMENTATION}")
|
||||
|
||||
# Enable the right assembler
|
||||
|
||||
if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext")
|
||||
if(BOOST_CONTEXT_ASSEMBLER STREQUAL gas)
|
||||
if(CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin")
|
||||
enable_language(ASM-ATT)
|
||||
else()
|
||||
enable_language(ASM)
|
||||
endif()
|
||||
else()
|
||||
enable_language(ASM_MASM)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Choose .asm sources
|
||||
|
||||
if(BOOST_CONTEXT_BINARY_FORMAT STREQUAL mach-o)
|
||||
set(BOOST_CONTEXT_BINARY_FORMAT macho)
|
||||
endif()
|
||||
|
||||
set(_asm_suffix ${BOOST_CONTEXT_ARCHITECTURE}_${BOOST_CONTEXT_ABI}_${BOOST_CONTEXT_BINARY_FORMAT}_${BOOST_CONTEXT_ASSEMBLER}${BOOST_CONTEXT_ASM_SUFFIX})
|
||||
|
||||
set(ASM_SOURCES
|
||||
src/asm/make_${_asm_suffix}
|
||||
src/asm/jump_${_asm_suffix}
|
||||
src/asm/ontop_${_asm_suffix}
|
||||
)
|
||||
|
||||
unset(_asm_suffix)
|
||||
|
||||
#
|
||||
|
||||
if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext")
|
||||
|
||||
set(IMPL_SOURCES ${ASM_SOURCES})
|
||||
|
||||
if(BOOST_CONTEXT_ASSEMBLER STREQUAL masm AND BOOST_CONTEXT_ARCHITECTURE STREQUAL i386)
|
||||
set_source_files_properties(${ASM_SOURCES} PROPERTIES COMPILE_FLAGS "/safeseh")
|
||||
endif()
|
||||
|
||||
else()
|
||||
set(IMPL_SOURCES
|
||||
src/continuation.cpp
|
||||
src/fiber.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32 AND NOT CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin")
|
||||
set(STACK_TRAITS_SOURCES
|
||||
src/windows/stack_traits.cpp
|
||||
)
|
||||
else()
|
||||
set(STACK_TRAITS_SOURCES
|
||||
src/posix/stack_traits.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(boost_context
|
||||
${IMPL_SOURCES}
|
||||
${STACK_TRAITS_SOURCES}
|
||||
)
|
||||
|
||||
add_library(Boost::context ALIAS boost_context)
|
||||
|
||||
target_include_directories(boost_context PUBLIC include)
|
||||
|
||||
target_link_libraries(boost_context
|
||||
PUBLIC
|
||||
Boost::assert
|
||||
Boost::config
|
||||
Boost::core
|
||||
Boost::mp11
|
||||
Boost::pool
|
||||
Boost::predef
|
||||
Boost::smart_ptr
|
||||
)
|
||||
|
||||
target_compile_definitions(boost_context
|
||||
PUBLIC BOOST_CONTEXT_NO_LIB
|
||||
PRIVATE BOOST_CONTEXT_SOURCE
|
||||
)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(boost_context PUBLIC BOOST_CONTEXT_DYN_LINK BOOST_CONTEXT_EXPORT=EXPORT)
|
||||
else()
|
||||
target_compile_definitions(boost_context PUBLIC BOOST_CONTEXT_STATIC_LINK BOOST_CONTEXT_EXPORT=)
|
||||
endif()
|
||||
|
||||
if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "ucontext")
|
||||
target_compile_definitions(boost_context PUBLIC BOOST_USE_UCONTEXT)
|
||||
endif()
|
||||
|
||||
if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "winfib")
|
||||
target_compile_definitions(boost_context PUBLIC BOOST_USE_WINFIB)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
10
README.md
10
README.md
@@ -8,14 +8,14 @@ instance represents a specific point in the application's execution path. This i
|
||||
higher-level abstractions, like coroutines, cooperative threads (userland threads) or an equivalent to
|
||||
C# keyword yield in C++.
|
||||
|
||||
A execution_context provides the means to suspend the current execution path and to transfer execution control,
|
||||
thereby permitting another execution_context to run on the current thread. This state full transfer mechanism
|
||||
enables a execution_context to suspend execution from within nested functions and, later, to resume from where it
|
||||
was suspended. While the execution path represented by a execution_context only runs on a single thread, it can be
|
||||
A fiber provides the means to suspend the current execution path and to transfer execution control,
|
||||
thereby permitting another fiber to run on the current thread. This state full transfer mechanism
|
||||
enables a fiber to suspend execution from within nested functions and, later, to resume from where it
|
||||
was suspended. While the execution path represented by a fiber only runs on a single thread, it can be
|
||||
migrated to another thread at any given time.
|
||||
|
||||
A context switch between threads requires system calls (involving the OS kernel), which can cost more than
|
||||
thousand CPU cycles on x86 CPUs. By contrast, transferring control among them requires only fewer than
|
||||
thousand CPU cycles on x86 CPUs. By contrast, transferring control among fibers requires only fewer than
|
||||
hundred CPU cycles because it does not involve system calls as it is done within a single thread.
|
||||
|
||||
boost.context requires C++11!
|
||||
|
||||
114
build/Jamfile.v2
114
build/Jamfile.v2
@@ -26,8 +26,8 @@ feature.compose <valgrind>on : <define>BOOST_USE_VALGRIND ;
|
||||
project boost/context
|
||||
: requirements
|
||||
<target-os>windows:<define>_WIN32_WINNT=0x0601
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<target-os>linux,<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<target-os>linux,<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<toolset>gcc,<segmented-stacks>on:<linkflags>"-static-libgcc"
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>clang,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
@@ -38,9 +38,14 @@ project boost/context
|
||||
<toolset>msvc,<link>static:<define>BOOST_CONTEXT_EXPORT=
|
||||
<toolset>clang-win,<link>shared:<define>BOOST_CONTEXT_EXPORT=EXPORT
|
||||
<toolset>clang-win,<link>static:<define>BOOST_CONTEXT_EXPORT=
|
||||
<toolset>embarcadero,<address-model>32,<link>shared:<define>BOOST_CONTEXT_EXPORT=EXPORT
|
||||
<toolset>embarcadero,<address-model>32,<link>static:<define>BOOST_CONTEXT_EXPORT=
|
||||
<toolset>borland,<link>shared:<define>BOOST_CONTEXT_EXPORT=EXPORT
|
||||
<toolset>borland,<link>static:<define>BOOST_CONTEXT_EXPORT=
|
||||
<link>shared:<define>BOOST_CONTEXT_DYN_LINK=1
|
||||
<define>BOOST_CONTEXT_SOURCE
|
||||
<threading>multi
|
||||
<toolset>msvc,<address-model>32:<asmflags>/safeseh
|
||||
: usage-requirements
|
||||
<link>shared:<define>BOOST_CONTEXT_DYN_LINK=1
|
||||
<optimization>speed:<define>BOOST_DISABLE_ASSERTS
|
||||
@@ -75,7 +80,8 @@ local rule default_abi ( )
|
||||
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 ; }
|
||||
else if [ os.platform ] = "MIPS32" { tmp = o32 ; }
|
||||
else if [ os.platform ] = "MIPS64" { tmp = n64 ; }
|
||||
return $(tmp) ;
|
||||
}
|
||||
|
||||
@@ -276,6 +282,7 @@ alias asm_sources
|
||||
: asm/make_ppc32_sysv_elf_gas.S
|
||||
asm/jump_ppc32_sysv_elf_gas.S
|
||||
asm/ontop_ppc32_sysv_elf_gas.S
|
||||
asm/tail_ppc32_sysv_elf_gas.cpp
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>power
|
||||
@@ -287,6 +294,7 @@ alias asm_sources
|
||||
: asm/make_ppc32_sysv_elf_gas.S
|
||||
asm/jump_ppc32_sysv_elf_gas.S
|
||||
asm/ontop_ppc32_sysv_elf_gas.S
|
||||
asm/tail_ppc32_sysv_elf_gas.cpp
|
||||
: <abi>sysv
|
||||
<address-model>32
|
||||
<architecture>power
|
||||
@@ -412,6 +420,32 @@ alias asm_sources
|
||||
<binary-format>mach-o
|
||||
;
|
||||
|
||||
# RISCV64
|
||||
# RISCV64/SYSV/ELF
|
||||
alias asm_sources
|
||||
: asm/make_riscv64_sysv_elf_gas.S
|
||||
asm/jump_riscv64_sysv_elf_gas.S
|
||||
asm/ontop_riscv64_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>riscv
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
# S390X
|
||||
# S390X/SYSV/ELF
|
||||
alias asm_sources
|
||||
: asm/make_s390x_sysv_elf_gas.S
|
||||
asm/jump_s390x_sysv_elf_gas.S
|
||||
asm/ontop_s390x_sysv_elf_gas.S
|
||||
: <abi>sysv
|
||||
<address-model>64
|
||||
<architecture>s390x
|
||||
<binary-format>elf
|
||||
<toolset>gcc
|
||||
;
|
||||
|
||||
# X86
|
||||
# X86/SYSV/ELF
|
||||
alias asm_sources
|
||||
@@ -531,6 +565,40 @@ alias asm_sources
|
||||
<toolset>msvc
|
||||
;
|
||||
|
||||
# Embarcadero on Windows for 32-bits, bcc32x, uses tasm32,
|
||||
# which is masm compatible
|
||||
# This is configured in the embarcadero toolset as using
|
||||
# 'tasm32 /ml'
|
||||
|
||||
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>embarcadero
|
||||
;
|
||||
|
||||
# Borland on Windows for 32-bits, bcc32c, uses tasm32,
|
||||
# which is masm compatible
|
||||
# This is configured in the borland toolset as using
|
||||
# 'tasm32 /ml'
|
||||
|
||||
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>borland
|
||||
;
|
||||
|
||||
# X86_64
|
||||
# X86_64/SYSV/ELF
|
||||
alias asm_sources
|
||||
@@ -578,6 +646,17 @@ alias asm_sources
|
||||
<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>gcc
|
||||
;
|
||||
|
||||
alias asm_sources
|
||||
: asm/make_x86_64_sysv_macho_gas.S
|
||||
asm/jump_x86_64_sysv_macho_gas.S
|
||||
@@ -660,6 +739,21 @@ alias asm_sources
|
||||
<binary-format>pe
|
||||
<toolset>msvc
|
||||
;
|
||||
|
||||
# Embarcadero on Windows, bcc64, uses the sysv-elf format for 64-bits
|
||||
# This is configured in the embarcadero toolset as using bcc64 with the
|
||||
# command line option '-x assembler-with-cpp'.
|
||||
|
||||
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>ms
|
||||
<address-model>64
|
||||
<architecture>x86
|
||||
<binary-format>pe
|
||||
<toolset>embarcadero
|
||||
;
|
||||
|
||||
# X86_64/SYSV/X32
|
||||
alias asm_sources
|
||||
@@ -767,33 +861,19 @@ alias impl_sources
|
||||
|
||||
explicit impl_sources ;
|
||||
|
||||
obj cxx11_hdr_mutex_check : ../build/cxx11_hdr_mutex.cpp ;
|
||||
explicit cxx11_hdr_mutex_check ;
|
||||
local cxx11_mutex = [ check-target-builds
|
||||
cxx11_hdr_mutex_check "C++11 mutex"
|
||||
:
|
||||
: <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
|
||||
:
|
||||
:
|
||||
: $(cxx11_mutex)
|
||||
;
|
||||
|
||||
explicit stack_traits_sources ;
|
||||
|
||||
lib boost_context
|
||||
: impl_sources
|
||||
execution_context.cpp
|
||||
stack_traits_sources
|
||||
;
|
||||
|
||||
|
||||
@@ -63,6 +63,14 @@ rule deduce-architecture ( properties * )
|
||||
{
|
||||
return <architecture>power ;
|
||||
}
|
||||
else if [ configure.builds /boost/architecture//riscv : $(properties) : riscv ]
|
||||
{
|
||||
return <architecture>riscv ;
|
||||
}
|
||||
else if [ configure.builds /boost/architecture//s390x : $(properties) : s390x ]
|
||||
{
|
||||
return <architecture>s390x ;
|
||||
}
|
||||
else if [ configure.builds /boost/architecture//sparc : $(properties) : sparc ]
|
||||
{
|
||||
return <architecture>sparc ;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright Kohei Takahashi 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 <boost/config.hpp>
|
||||
|
||||
#ifdef BOOST_NO_CXX11_HDR_MUTEX
|
||||
#error "C++11 <mutex> is not available."
|
||||
#endif
|
||||
@@ -11,15 +11,17 @@ __boost_context__, using [link implementation ['fcontext_t]], supports following
|
||||
architectures:
|
||||
|
||||
[table Supported architectures (<ABI|binary format>)
|
||||
[[Architecture] [LINUX (UNIX)] [Windows] [MacOS X] [iOS]]
|
||||
[[arm (aarch32)] [AAPCS|ELF] [AAPCS|PE] [-] [AAPCS|MACH-O]]
|
||||
[[arm (aarch64)] [AAPCS|ELF] [-] [-] [AAPCS|MACH-O]]
|
||||
[[i386] [SYSV|ELF] [MS|PE] [SYSV|MACH-O] [-]]
|
||||
[[mips] [O32,N64|ELF] [-] [-] [-]]
|
||||
[[ppc32] [SYSV|ELF,XCOFF] [-] [SYSV|MACH-O] [-]]
|
||||
[[ppc64] [SYSV|ELF,XCOFF] [-] [SYSV|MACH-O] [-]]
|
||||
[[sparc] [-] [-] [-] [-]]
|
||||
[[x86_64] [SYSV,X32|ELF] [MS|PE] [SYSV|MACH-O] [-]]
|
||||
[[Architecture] [LINUX (UNIX)] [Windows] [MacOS X] [iOS]]
|
||||
[[arm (aarch32)] [AAPCS|ELF] [AAPCS|PE] [-] [AAPCS|MACH-O]]
|
||||
[[arm (aarch64)] [AAPCS|ELF] [-] [AAPCS|MACH-O] [AAPCS|MACH-O]]
|
||||
[[i386] [SYSV|ELF] [MS|PE] [SYSV|MACH-O] [-]]
|
||||
[[mips] [O32|N64|ELF] [-] [-] [-]]
|
||||
[[ppc32] [SYSV|ELF|XCOFF] [-] [SYSV|MACH-O] [-]]
|
||||
[[ppc64] [SYSV|ELF|XCOFF] [-] [SYSV|MACH-O] [-]]
|
||||
[[riscv64] [SYSV|ELF] [-] [SYSV] [-]]
|
||||
[[s390x] [SYSV|ELF] [-] [-] [-]]
|
||||
[[sparc] [-] [-] [-] [-]]
|
||||
[[x86_64] [SYSV,X32|ELF] [MS|PE] [SYSV|MACH-O] [-]]
|
||||
]
|
||||
|
||||
[note If the architecture is not supported but the platform provides
|
||||
|
||||
@@ -149,8 +149,7 @@ If the function executed inside a __context_fn__ emits an exception, the
|
||||
application is terminated by calling `std::terminate()`. `std::exception_ptr`
|
||||
can be used to transfer exceptions between different continuations.
|
||||
|
||||
[important Do not jump from inside a catch block and then re-throw the exception
|
||||
in another continuation.]
|
||||
[important Do not jump from inside a catch block.]
|
||||
|
||||
|
||||
[#cc_ontop]
|
||||
@@ -159,7 +158,7 @@ in another continuation.]
|
||||
Sometimes it is useful to execute a new function on top of a resumed
|
||||
continuation. For this purpose __resume_with__ has to be used.
|
||||
The function passed as argument must accept a rvalue reference to __con__ and
|
||||
return `void`.
|
||||
return __con__.
|
||||
|
||||
namespace ctx=boost::context;
|
||||
int data=0;
|
||||
|
||||
@@ -126,9 +126,6 @@
|
||||
|
||||
[def __cc__ [link cc ['callcc()]]]
|
||||
[def __con__ [link cc ['continuation]]]
|
||||
[def __econtext__ ['execution_context]]
|
||||
[def __ecv1__ [link ecv1 ['execution_context] (v1)]]
|
||||
[def __ecv2__ [link ecv2 ['execution_context] (v2)]]
|
||||
[def __fib__ [link ff ['fiber]]]
|
||||
[def __fcontext__ ['fcontext_t]]
|
||||
[def __forced_unwind__ ['detail::forced_unwind]]
|
||||
@@ -166,8 +163,6 @@
|
||||
[include requirements.qbk]
|
||||
[include fiber.qbk]
|
||||
[include callcc.qbk]
|
||||
[include execution_context_v2.qbk]
|
||||
[include execution_context_v1.qbk]
|
||||
[include stack.qbk]
|
||||
[include preallocated.qbk]
|
||||
[include performance.qbk]
|
||||
|
||||
1853
doc/context.xml
1853
doc/context.xml
File diff suppressed because it is too large
Load Diff
@@ -1,481 +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
|
||||
]
|
||||
|
||||
[#ecv1]
|
||||
[section:ecv1 Class execution_context (version 1)]
|
||||
|
||||
[warning __econtext__ (v1) is deprecated (does not prevent UB).]
|
||||
|
||||
[note __econtext__ (v1) is the reference implementation of C++ proposal
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0099r0.pdf P099R0: A
|
||||
low-level API for stackful context switching].]
|
||||
|
||||
[note __econtext__ (v1) resides in sub-namespace `v1`.]
|
||||
|
||||
[note Segmented stacks (['segmented-stacks=on]), e.g. on demand growing stacks,
|
||||
can be used with __econtext__ (v1).]
|
||||
|
||||
Class __econtext__ encapsulates context switching and manages the associated
|
||||
context' stack (allocation/deallocation).
|
||||
|
||||
__econtext__ allocates the context stack (using its [link stack
|
||||
__stack_allocator__] argument) and creates a control structure on top of it.
|
||||
This structure is responsible for managing context' stack. Instances of
|
||||
__econtext__, associated with a specific context, share the ownership of the
|
||||
control structure. If the last reference goes out of scope, the control
|
||||
structure is destroyed and the stack gets deallocated via the
|
||||
__stack_allocator__.
|
||||
|
||||
__econtext__ is copy-constructible, move-constructible, copy-assignable and
|
||||
move-assignable.
|
||||
|
||||
__econtext__ maintains a static (thread-local) pointer, accessed by
|
||||
__ec_current__, pointing to the active context. On each context switch the
|
||||
pointer is updated.
|
||||
The usage of this global pointer makes the context switch a little bit slower
|
||||
(due access of thread local storage) but has some advantages. It allows to
|
||||
access the control structure of the current active context from arbitrary code
|
||||
paths required in order to support segmented stacks, which require to call
|
||||
certain maintenance functions (like __splitstack_getcontext() etc.) before each
|
||||
context switch (each context switch exchanges the stack).
|
||||
|
||||
__econtext__ expects a function/functor with signature `void(void* vp)` (`vp`
|
||||
is the data passed at the first invocation of
|
||||
[operator_link ecv1 operator_call operator()]).
|
||||
|
||||
|
||||
[heading usage of __econtext__]
|
||||
|
||||
int n=35;
|
||||
boost::context::v1::execution_context sink(boost::context::v1::execution_context::current());
|
||||
boost::context::v1::execution_context source(
|
||||
[n,&sink](void*)mutable{
|
||||
int a=0;
|
||||
int b=1;
|
||||
while(n-->0){
|
||||
sink(&a);
|
||||
auto next=a+b;
|
||||
a=b;
|
||||
b=next;
|
||||
}
|
||||
});
|
||||
for(int i=0;i<10;++i){
|
||||
std::cout<<*(int*)source()<<" ";
|
||||
}
|
||||
|
||||
output:
|
||||
0 1 1 2 3 5 8 13 21 34
|
||||
|
||||
This simple example demonstrates the basic usage of __econtext__. The context
|
||||
`sink`, returned by __ec_current__, represents the ['main]-context (function
|
||||
['main()] running) and is one of the captured parameters in the lambda
|
||||
expression. The lambda that calculates the Fibonacci numbers is executed inside
|
||||
the context represented by `source`. Calculated Fibonacci numbers are
|
||||
transferred between the two context' via expression ['sink(&a)] (and returned by
|
||||
['source()]).
|
||||
|
||||
The locale variables `a`, `b` and ` next` remain their values during each
|
||||
context switch (['yield(a)]). This is possible because `ctx` owns a stack
|
||||
(exchanged by context switch).
|
||||
|
||||
[heading inverting the control flow]
|
||||
|
||||
/*
|
||||
* grammar:
|
||||
* P ---> E '\0'
|
||||
* E ---> T {('+'|'-') T}
|
||||
* T ---> S {('*'|'/') S}
|
||||
* S ---> digit | '(' E ')'
|
||||
*/
|
||||
class Parser{
|
||||
// implementation omitted; see examples directory
|
||||
};
|
||||
|
||||
std::istringstream is("1+1");
|
||||
bool done=false;
|
||||
std::exception_ptr except;
|
||||
|
||||
// create handle to main execution context
|
||||
auto main_ctx(boost::context::v1::execution_context::current());
|
||||
// execute parser in new execution context
|
||||
boost::context::v1::execution_context source(
|
||||
[&sink,&is,&done,&except](void*){
|
||||
// create parser with callback function
|
||||
Parser p(is,
|
||||
[&sink](char ch){
|
||||
// resume main execution context
|
||||
sink(&ch);
|
||||
});
|
||||
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
|
||||
sink();
|
||||
});
|
||||
|
||||
// user-code pulls parsed data from parser
|
||||
// invert control flow
|
||||
void* vp = source();
|
||||
if (except) {
|
||||
std::rethrow_exception(except);
|
||||
}
|
||||
while( ! done) {
|
||||
printf("Parsed: %c\n",* static_cast<char*>(vp));
|
||||
vp = source();
|
||||
if (except) {
|
||||
std::rethrow_exception(except);
|
||||
}
|
||||
}
|
||||
|
||||
output:
|
||||
Parsed: 1
|
||||
Parsed: +
|
||||
Parsed: 1
|
||||
|
||||
|
||||
In this example a recursive descent parser uses a callback to emit a newly
|
||||
passed symbol. Using __econtext__ the control flow can be inverted, e.g. the
|
||||
user-code pulls parsed symbols from the parser - instead to get pushed from the
|
||||
parser (via callback).
|
||||
|
||||
The data (character) is transferred between the two __econtext__.
|
||||
|
||||
If the code executed by __econtext__ emits an exception, the application is
|
||||
terminated. ['std::exception_ptr] can be used to transfer exceptions between
|
||||
different execution contexts.
|
||||
|
||||
[heading stack unwinding]
|
||||
Sometimes it is necessary to unwind the stack of an unfinished context to
|
||||
destroy local stack variables so they can release allocated resources (RAII
|
||||
pattern). The user is responsible for this task.
|
||||
|
||||
[#ecv1_prealloc]
|
||||
[heading allocating control structures on top of stack]
|
||||
Allocating control structures on top of the stack requires to allocated the
|
||||
__stack_context__ and create the control structure with placement new before
|
||||
__econtext__ is created.
|
||||
[note The user is responsible for destructing the control structure at the top
|
||||
of the stack.]
|
||||
|
||||
// stack-allocator used for (de-)allocating stack
|
||||
fixedsize_stack salloc( 4048);
|
||||
// allocate stack space
|
||||
stack_context sctx( salloc.allocate() );
|
||||
// reserve space for control structure on top of the stack
|
||||
void * sp = static_cast< char * >( sctx.sp) - sizeof( my_control_structure);
|
||||
std::size_t size = sctx.size - sizeof( my_control_structure);
|
||||
// placement new creates control structure on reserved space
|
||||
my_control_structure * cs = new ( sp) my_control_structure( sp, size, sctx, salloc);
|
||||
...
|
||||
// destructing the control structure
|
||||
cs->~my_control_structure();
|
||||
...
|
||||
struct my_control_structure {
|
||||
// execution context
|
||||
execution_context ectx;
|
||||
|
||||
template< typename StackAllocator >
|
||||
my_control_structure( void * sp, std::size_t size, stack_context sctx, StackAllocator salloc) :
|
||||
// create execution context
|
||||
ectx( std::allocator_arg, preallocated( sp, size, sctx), salloc, entry_func) {
|
||||
}
|
||||
...
|
||||
};
|
||||
|
||||
[heading exception handling]
|
||||
If the function executed inside a __econtext__ emits ans exception, the
|
||||
application is terminated by calling ['std::terminate()]. ['std::exception_ptr]
|
||||
can be used to transfer exceptions between different execution contexts.
|
||||
|
||||
[important Do not jump from inside a catch block and then re-throw the exception
|
||||
in another execution context.]
|
||||
|
||||
[heading parameter passing]
|
||||
The void pointer argument passed to __ec_op__, in one context, is passed as
|
||||
the last argument of the __context_fn__ if the context is started for the
|
||||
first time.
|
||||
In all following invocations of __ec_op__ the void pointer passed to
|
||||
__ec_op__, in one context, is returned by __ec_op__ in the other context.
|
||||
|
||||
class X {
|
||||
private:
|
||||
std::exception_ptr excptr_;
|
||||
boost::context::v1::execution_context caller_;
|
||||
boost::context::v1::execution_context callee_;
|
||||
|
||||
public:
|
||||
X() :
|
||||
excptr_(),
|
||||
caller_( boost::context::v1::execution_context::current() ),
|
||||
callee_( [=] (void * vp) {
|
||||
try {
|
||||
int i = * static_cast< int * >( vp);
|
||||
std::string str = boost::lexical_cast<std::string>(i);
|
||||
caller_( & str);
|
||||
} catch (std::bad_cast const&) {
|
||||
excptr_=std::current_exception();
|
||||
}
|
||||
})
|
||||
{}
|
||||
|
||||
std::string operator()( int i) {
|
||||
void * ret = callee_( & i);
|
||||
if(excptr_){
|
||||
std::rethrow_exception(excptr_);
|
||||
}
|
||||
return * static_cast< std::string * >( ret);
|
||||
}
|
||||
};
|
||||
|
||||
X x;
|
||||
std::cout << x( 7) << std::endl;
|
||||
|
||||
output:
|
||||
7
|
||||
|
||||
|
||||
[heading Class `execution_context`]
|
||||
|
||||
class execution_context {
|
||||
public:
|
||||
static execution_context current() noexcept;
|
||||
|
||||
template< typename Fn, typename ... Args >
|
||||
execution_context( Fn && fn, Args && ... args);
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Args >
|
||||
execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args);
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Args >
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args);
|
||||
|
||||
execution_context( execution_context const& other) noexcept;
|
||||
execution_context( execution_context && other) noexcept;
|
||||
|
||||
execution_context & operator=( execution_context const& other) noexcept;
|
||||
execution_context & operator=( execution_context && other) noexcept;
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
bool operator!() const noexcept;
|
||||
|
||||
void * operator()( void * vp = nullptr);
|
||||
|
||||
template< typename Fn >
|
||||
void * operator()( exec_ontop_arg_t, Fn && fn, void * vp = nullptr);
|
||||
|
||||
bool operator==( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator!=( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator<( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator>( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator<=( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator>=( execution_context const& other) const noexcept;
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other);
|
||||
};
|
||||
|
||||
[static_member_heading ecv1..current]
|
||||
|
||||
static execution_context current() noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [Returns an instance of excution_context pointing to the active
|
||||
execution context.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[constructor_heading ecv1..constructor]
|
||||
|
||||
template< typename Fn, typename ... Args >
|
||||
execution_context( Fn && fn, Args && ... args);
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Args >
|
||||
execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args);
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Args >
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args);
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Creates a new execution context and prepares the context to execute
|
||||
`fn`. `fixedsize_stack` is used as default stack allocator
|
||||
(stack size == fixedsize_stack::traits::default_size()).
|
||||
The constructor with argument type `preallocated`, is used to create a user
|
||||
defined data [link ecv1_prealloc (for instance additional control structures)] on
|
||||
top of the stack.]]
|
||||
]
|
||||
|
||||
[copy_constructor_heading ecv1..copy constructor]
|
||||
|
||||
execution_context( execution_context const& other) noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Copies `other`, e.g. underlying control structure is shared with
|
||||
`*this`.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[move_constructor_heading ecv1..move constructor]
|
||||
|
||||
execution_context( execution_context && other) noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Moves underlying control structure to `*this`.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[copy_assignment_heading ecv1..copy assignment]
|
||||
|
||||
execution_context & operator=( execution_context const& other) noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Copies the state of `other` to `*this`, control structure is
|
||||
shared.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[move_assignment_heading ecv1..move assignment]
|
||||
|
||||
execution_context & operator=( execution_context && other) noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Moves the control structure of `other` to `*this` using move
|
||||
semantics.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_bool..operator bool]
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` points to a control structure.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_not..operator!]
|
||||
|
||||
bool operator!() const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` does not point to a control structure.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_call..operator()]
|
||||
|
||||
void * operator()( void * vp = nullptr) noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Stores internally the current context data (stack pointer,
|
||||
instruction pointer, and CPU registers) of the current active context and
|
||||
restores the context data from `*this`, which implies jumping to `*this`'s
|
||||
context.
|
||||
The void pointer argument, `vp`, is passed to the current context to be returned
|
||||
by the most recent call to `execution_context::operator()` in the same thread.
|
||||
`fn` is executed with arguments `args` on top of the stack of `this`.]]
|
||||
[[Note:] [The behaviour is undefined if `operator()()` is called while
|
||||
__ec_current__ returns `*this` (e.g. resuming an already running context). If
|
||||
the top-level context function returns, `std::exit()` is called.]]
|
||||
[[Returns:] [The void pointer argument passed to the most recent call to
|
||||
__ec_op__, if any.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_call_ontop..operator(exec_ontop_arg_t)]
|
||||
|
||||
template< typename Fn >
|
||||
void * operator()( exec_ontop_arg_t, Fn && fn, void * vp = nullptr);
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Same as __ec_op__. Additionally, function `fn` is executed with
|
||||
arguments `vp` in the context of `*this` (e.g. the stack frame of `fn` is
|
||||
allocated on stack of `*this`).]]
|
||||
[[Returns:] [The void pointer argument passed to the most recent call to
|
||||
__ec_op__, if any.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_equal..operator==]
|
||||
|
||||
bool operator==( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` and `other` represent the same execution context,
|
||||
`false` otherwise.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_notequal..operator!=]
|
||||
|
||||
bool operator!=( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [[`! (other == * this)]]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_less..operator<]
|
||||
|
||||
bool operator<( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this != other` is true and the
|
||||
implementation-defined total order of `execution_context` values places `*this`
|
||||
before `other`, false otherwise.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_greater..operator>]
|
||||
|
||||
bool operator>( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`other < * this`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_lesseq..operator<=]
|
||||
|
||||
bool operator<=( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`! (other < * this)`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv1..operator_greatereq..operator>=]
|
||||
|
||||
bool operator>=( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`! (* this < other)`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[hding ecv1_..Non-member function [`operator<<()]]
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other);
|
||||
|
||||
[variablelist
|
||||
[[Efects:] [Writes the representation of `other` to stream `os`.]]
|
||||
[[Returns:] [`os`]]
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
@@ -1,677 +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
|
||||
]
|
||||
|
||||
[#ecv2]
|
||||
[section:ecv2 Class execution_context (version 2)]
|
||||
|
||||
[note __econtext__ (v2) is the reference implementation of C++ proposal
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0099r1.pdf P099R1: A
|
||||
low-level API for stackful context switching].]
|
||||
|
||||
[note __econtext__ (v2) resides in the inlined sub-namespace `v2`.]
|
||||
|
||||
[note Segmented stacks (['segmented-stacks=on]), e.g. on demand growing stacks,
|
||||
are not supported by __econtext__ (v2).]
|
||||
|
||||
Class __econtext__ encapsulates context switching and manages the associated
|
||||
context' stack (allocation/deallocation).
|
||||
|
||||
__econtext__ allocates the context stack (using its [link stack
|
||||
__stack_allocator__] argument) and creates a control structure on top of it.
|
||||
This structure is responsible for managing context' stack. The address of the
|
||||
control structure is stored in the first frame of context' stack (e.g. it can
|
||||
not directly accessed from within __econtext__). In contrast to __ecv1__ the
|
||||
ownership of the control structure is not shared (no member variable to control
|
||||
structure in __econtext__). __econtext__ keeps internally a state that is moved
|
||||
by a call of __ec_op__ (`*this` will be invalidated), e.g. after a calling
|
||||
__ec_op__, `*this` can not be used for an additional context switch.
|
||||
|
||||
__econtext__ is only move-constructible and move-assignable.
|
||||
|
||||
The moved state is assigned to a new instance of __econtext__. This object
|
||||
becomes the first argument of the context-function, if the context was resumed
|
||||
the first time, or the first element in a tuple returned by __ec_op__ that has
|
||||
been called in the resumed context.
|
||||
In contrast to __ecv1__, the context switch is faster because no global pointer
|
||||
etc. is involved.
|
||||
|
||||
[important Segmented stacks are not supported by __econtext__ (v2).]
|
||||
|
||||
On return the context-function of the current context has to specify an
|
||||
__econtext__ to which the execution control is transferred after termination
|
||||
of the current context.
|
||||
|
||||
If an instance with valid state goes out of scope and the context-function has
|
||||
not yet returned, the stack is traversed in order to access the control
|
||||
structure (address stored at the first stack frame) and context' stack is
|
||||
deallocated via the __stack_allocator__. The stack walking makes the destruction
|
||||
of __econtext__ slow and should be prevented if possible.
|
||||
|
||||
__econtext__ expects a __context_fn__ with signature
|
||||
`execution_context(execution_context ctx, Args ... args)`. The parameter `ctx`
|
||||
represents the context from which this context was resumed (e.g. that has called
|
||||
__ec_op__ on `*this`) and `args` are the data passed to __ec_op__. The return
|
||||
value represents the execution_context that has to be resumed, after termiantion
|
||||
of this context.
|
||||
|
||||
Benefits of __ecv2__ over __ecv1__ are: faster context switch, type-safety of
|
||||
passed/returned arguments.
|
||||
|
||||
|
||||
[heading usage of __econtext__]
|
||||
|
||||
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)<<" ";
|
||||
}
|
||||
|
||||
output:
|
||||
0 1 1 2 3 5 8 13 21 34
|
||||
|
||||
This simple example demonstrates the basic usage of __econtext__ as a generator.
|
||||
The context `sink` represents the ['main]-context (function ['main()] running).
|
||||
`sink` is generated by the framework (first element of lambda's parameter list).
|
||||
Because the state is invalidated (== changed) by each call of __ec_op__, the new
|
||||
state of the __econtext__, returned by __ec_op__, needs to be assigned to `sink`
|
||||
after each call.
|
||||
|
||||
The lambda that calculates the Fibonacci numbers is executed inside
|
||||
the context represented by `source`. Calculated Fibonacci numbers are
|
||||
transferred between the two context' via expression ['sink(a)] (and returned by
|
||||
['source()]). Note that this example represents a ['generator] thus the value
|
||||
transferred into the lambda via ['source()] is not used. Using
|
||||
['boost::optional<>] as transferred type, might also appropriate to express this
|
||||
fact.
|
||||
|
||||
The locale variables `a`, `b` and ` next` remain their values during each
|
||||
context switch (['yield(a)]). This is possible due `source` has its own stack
|
||||
and the stack is exchanged by each context switch.
|
||||
|
||||
|
||||
[heading parameter passing]
|
||||
With `execution_context<void>` no data will be transferred, only the context
|
||||
switch is executed.
|
||||
|
||||
boost::context::execution_context<void> ctx1([](boost::context::execution_context<void> && ctx2){
|
||||
std::printf("inside ctx1\n");
|
||||
return ctx2();
|
||||
});
|
||||
ctx1();
|
||||
|
||||
output:
|
||||
inside ctx1
|
||||
|
||||
`ctx1()` resumes `ctx1`, e.g. the lambda passed at the constructor of `ctx1` is
|
||||
entered. Argument `ctx2` represents the context that has been suspended with the
|
||||
invocation of `ctx1()`. When the lambda returns `ctx2`, context `ctx1` will be
|
||||
terminated while the context represented by `ctx2` is resumed, hence the control
|
||||
of execution returns from `ctx1()`.
|
||||
|
||||
The arguments passed to __ec_op__, in one context, is passed as the last
|
||||
arguments of the __context_fn__ if the context is started for the first time.
|
||||
In all following invocations of __ec_op__ the arguments passed to __ec_op__, in
|
||||
one context, is returned by __ec_op__ in the other context.
|
||||
|
||||
boost::context::execution_context<int> ctx1([](boost::context::execution_context<int> && ctx2,int j){
|
||||
std::printf("inside ctx1,j==%d\n",j);
|
||||
std::tie(ctx2,j)=ctx2(j+1);
|
||||
return std::move(ctx2);
|
||||
});
|
||||
int i=1;
|
||||
std::tie(ctx1,i)=ctx1(i);
|
||||
std::printf("i==%d\n",i);
|
||||
|
||||
output:
|
||||
inside ctx1,j==1
|
||||
i==2
|
||||
|
||||
`ctx1(i)` enters the lambda in context `ctx1` with argument `j=1`. The
|
||||
expression `ctx2(j+1)` resumes the context represented by `ctx2` and transfers
|
||||
back an integer of `j+1`. On return of `ctx1(i)`, the variable `i` contains the
|
||||
value of `j+1`.
|
||||
|
||||
If more than one argument has to be transferred, the signature of the
|
||||
context-function is simply extended.
|
||||
|
||||
boost::context::execution_context<int,int> ctx1([](boost::context::execution_context<int,int> && ctx2,int i,int j){
|
||||
std::printf("inside ctx1,i==%d,j==%d\n",i,j);
|
||||
std::tie(ctx2,i,j)=ctx2(i+j,i-j);
|
||||
return std::move(ctx2);
|
||||
});
|
||||
int i=2,j=1;
|
||||
std::tie(ctx1,i,j)=ctx1(i,j);
|
||||
std::printf("i==%d,j==%d\n",i,j);
|
||||
|
||||
output:
|
||||
inside ctx1,i==2,j==1
|
||||
i==3,j==1
|
||||
|
||||
For use-cases, that require to transfer data of different type in each
|
||||
direction, ['boost::variant<>] could be used.
|
||||
|
||||
class X{
|
||||
private:
|
||||
std::exception_ptr excptr_;
|
||||
boost::context::execution_context<boost::variant<int,std::string>> ctx_;
|
||||
|
||||
public:
|
||||
X():
|
||||
excptr_(),
|
||||
ctx_([=](boost::context::execution_context<boost::variant<int,std::string>> && ctx,boost::variant<int,std::string> 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){
|
||||
boost::variant<int,std::string> 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);
|
||||
}
|
||||
};
|
||||
|
||||
X x;
|
||||
std::cout << x(7) << std::endl;
|
||||
|
||||
output:
|
||||
7
|
||||
|
||||
In the case of unidirectional transfer of data, ['boost::optional<>] or a
|
||||
pointer are appropriate.
|
||||
|
||||
|
||||
[heading exception handling]
|
||||
If the function executed inside a __econtext__ emits ans exception, the
|
||||
application is terminated by calling ['std::terminate()]. ['std::exception_ptr]
|
||||
can be used to transfer exceptions between different execution contexts.
|
||||
|
||||
[important Do not jump from inside a catch block and then re-throw the exception
|
||||
in another execution context.]
|
||||
|
||||
[#ecv2_ontop]
|
||||
[heading Executing function on top of a context]
|
||||
Sometimes it is useful to execute a new function on top of a resumed context.
|
||||
For this purpose __ec_op__ with first argument `exec_ontop_arg` has to be used.
|
||||
The function passed as argument must return a tuple of execution_context and
|
||||
arguments.
|
||||
|
||||
boost::context::execution_context<int> f1(boost::context::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 data=0;
|
||||
boost::context::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);
|
||||
|
||||
output:
|
||||
f1: entered first time: 1
|
||||
f1: returned first time: 2
|
||||
f1: entered second time: 3
|
||||
f1: returned second time: 4
|
||||
f2: entered: 5
|
||||
f1: entered third time: -1
|
||||
|
||||
The expression `ctx(ctx::exec_ontop_arg,f2,data+1)` executes `f2()` on top of
|
||||
context `ctx`, e.g. an additional stack frame is allocated on top of the context
|
||||
stack (in front of `f1()`). `f2()` returns argument `-1` that will returned by
|
||||
the second invocation of `ctx(data+1)` in `f1()`.
|
||||
[/
|
||||
Another option is to execute a function on top of the context that throws an
|
||||
exception. The thrown exception is catched and re-thrown as nested exception of
|
||||
__ot_error__ from __ec_op__. __ot_error__ gives access to the context that has
|
||||
resumed the current context.
|
||||
|
||||
struct my_exception : public std::runtime_error {
|
||||
my_exception( std::string const& what) :
|
||||
std::runtime_error{ what } {
|
||||
}
|
||||
};
|
||||
|
||||
boost::context::execution_context<void> ctx([](boost::context::execution_context<void> && ctx) {
|
||||
for (;;) {
|
||||
try {
|
||||
std::cout << "entered" << std::endl;
|
||||
ctx = ctx();
|
||||
}
|
||||
} catch ( boost::context::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( boost::context::exec_ontop_arg,[](){ throw my_exception{ "abc" }; });
|
||||
|
||||
output:
|
||||
entered
|
||||
entered
|
||||
my_exception: abc
|
||||
|
||||
In this exception `my_exception` is throw from a function invoked ontop of
|
||||
context `ctx` and catched inside the `for`-loop.
|
||||
|
||||
[heading stack unwinding]
|
||||
On construction of __econtext__ a stack is allocated.
|
||||
If the __context_fn__ returns the stack will be destructed.
|
||||
If the __context_fn__ has not yet returned and the destructor of an valid
|
||||
__econtext__ instance (e.g. ['execution_context::operator bool()] returns
|
||||
`true`) is called, the stack will be destructed too.
|
||||
|
||||
[important Code executed by __context_fn__ must not prevent the propagation of the
|
||||
__forced_unwind__ exception. Absorbing that exception will cause stack
|
||||
unwinding to fail. Thus, any code that catches all exceptions must re-throw any
|
||||
pending __forced_unwind__ exception.]
|
||||
|
||||
|
||||
[#ecv2_prealloc]
|
||||
[heading allocating control structures on top of stack]
|
||||
Allocating control structures on top of the stack requires to allocated the
|
||||
__stack_context__ and create the control structure with placement new before
|
||||
__econtext__ is created.
|
||||
[note The user is responsible for destructing the control structure at the top
|
||||
of the stack.]
|
||||
|
||||
// stack-allocator used for (de-)allocating stack
|
||||
fixedsize_stack salloc(4048);
|
||||
// allocate stack space
|
||||
stack_context sctx(salloc.allocate());
|
||||
// reserve space for control structure on top of the stack
|
||||
void * sp=static_cast<char*>(sctx.sp)-sizeof(my_control_structure);
|
||||
std::size_t size=sctx.size-sizeof(my_control_structure);
|
||||
// placement new creates control structure on reserved space
|
||||
my_control_structure * cs=new(sp)my_control_structure(sp,size,sctx,salloc);
|
||||
...
|
||||
// destructing the control structure
|
||||
cs->~my_control_structure();
|
||||
...
|
||||
struct my_control_structure {
|
||||
// captured context
|
||||
execution_context cctx;
|
||||
|
||||
template< typename StackAllocator >
|
||||
my_control_structure(void * sp,std::size_t size,stack_context sctx,StackAllocator salloc) :
|
||||
// create captured context
|
||||
cctx(std::allocator_arg,preallocated(sp,size,sctx),salloc,entry_func) {
|
||||
}
|
||||
...
|
||||
};
|
||||
|
||||
|
||||
[heading inverting the control flow]
|
||||
|
||||
/*
|
||||
* grammar:
|
||||
* P ---> E '\0'
|
||||
* E ---> T {('+'|'-') T}
|
||||
* T ---> S {('*'|'/') S}
|
||||
* S ---> digit | '(' E ')'
|
||||
*/
|
||||
class Parser{
|
||||
// implementation omitted; see examples directory
|
||||
};
|
||||
|
||||
std::istringstream is("1+1");
|
||||
bool done=false;
|
||||
std::exception_ptr except;
|
||||
|
||||
// execute parser in new execution context
|
||||
boost::context::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);
|
||||
}
|
||||
}
|
||||
|
||||
output:
|
||||
Parsed: 1
|
||||
Parsed: +
|
||||
Parsed: 1
|
||||
|
||||
In this example a recursive descent parser uses a callback to emit a newly
|
||||
passed symbol. Using __econtext__ the control flow can be inverted, e.g. the
|
||||
user-code pulls parsed symbols from the parser - instead to get pushed from the
|
||||
parser (via callback).
|
||||
|
||||
The data (character) is transferred between the two __econtext__.
|
||||
|
||||
If the code executed by __econtext__ emits an exception, the application is
|
||||
terminated. ['std::exception_ptr] can be used to transfer exceptions between
|
||||
different execution contexts.
|
||||
|
||||
Sometimes it is necessary to unwind the stack of an unfinished context to
|
||||
destroy local stack variables so they can release allocated resources (RAII
|
||||
pattern). The user is responsible for this task.
|
||||
|
||||
|
||||
[heading Class `execution_context`]
|
||||
|
||||
struct exec_ontop_arg_t {};
|
||||
const exec_ontop_arg_t exec_ontop_arg{};
|
||||
|
||||
class ontop_error {
|
||||
public:
|
||||
template< typename ... Args >
|
||||
execution_context< Args ... > get_context() const noexcept;
|
||||
}
|
||||
|
||||
template< typename ... Args >
|
||||
class execution_context {
|
||||
public:
|
||||
template< typename Fn, typename ... Params >
|
||||
execution_context( Fn && fn, Params && ... params);
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Params && ... params);
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params);
|
||||
|
||||
template< typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, segemented_stack, Fn && fn, Params && ... params) = delete;
|
||||
|
||||
template< typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, segmented, Fn && fn, Params && ... params)= delete;
|
||||
|
||||
~execution_context();
|
||||
|
||||
execution_context( execution_context && other) noexcept;
|
||||
execution_context & operator=( execution_context && other) noexcept;
|
||||
|
||||
execution_context( execution_context const& other) noexcept = delete;
|
||||
execution_context & operator=( execution_context const& other) noexcept = delete;
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
bool operator!() const noexcept;
|
||||
|
||||
std::tuple< execution_context, Args ... > operator()( Args ... args);
|
||||
|
||||
template< typename Fn >
|
||||
std::tuple< execution_context, Args ... > operator()( exec_ontop_arg_t, Fn && fn, Args ... args);
|
||||
|
||||
bool operator==( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator!=( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator<( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator>( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator<=( execution_context const& other) const noexcept;
|
||||
|
||||
bool operator>=( execution_context const& other) const noexcept;
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other);
|
||||
};
|
||||
|
||||
[constructor_heading ecv2..constructor]
|
||||
|
||||
template< typename Fn, typename ... Params >
|
||||
execution_context( Fn && fn, Params && ... params);
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Params && ... params);
|
||||
|
||||
template< typename StackAlloc, typename Fn, typename ... Params >
|
||||
execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params);
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Creates a new execution context and prepares the context to execute
|
||||
`fn`. `fixedsize_stack` is used as default stack allocator
|
||||
(stack size == fixedsize_stack::traits::default_size()).
|
||||
The constructor with argument type `preallocated`, is used to create a user
|
||||
defined data [link ecv2_prealloc (for instance additional control structures)] on
|
||||
top of the stack.]]
|
||||
]
|
||||
]
|
||||
[destructor_heading ecv2..destructor destructor]
|
||||
|
||||
~execution_context();
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Destructs the associated stack if `*this` is a valid context,
|
||||
e.g. ['execution_context::operator bool()] returns `true`.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[move_constructor_heading ecv2..move constructor]
|
||||
|
||||
execution_context( execution_context && other) noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Moves underlying capture record to `*this`.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[move_assignment_heading ecv2..move assignment]
|
||||
|
||||
execution_context & operator=( execution_context && other) noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Moves the state of `other` to `*this` using move semantics.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_bool..operator bool]
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` points to a capture record.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_not..operator!]
|
||||
|
||||
bool operator!() const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` does not point to a capture record.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_call..operator()]
|
||||
|
||||
std::tuple< execution_context< Args ... >, Args ... > operator()( Args ... args); // member of generic execution_context template
|
||||
|
||||
execution_context< void > operator()(); // member of execution_context< void >
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Stores internally the current context data (stack pointer,
|
||||
instruction pointer, and CPU registers) of the current active context and
|
||||
restores the context data from `*this`, which implies jumping to `*this`'s
|
||||
context.
|
||||
The arguments, `... args`, are passed to the current context to be returned
|
||||
by the most recent call to `execution_context::operator()` in the same thread.]]
|
||||
[[Returns:] [The tuple of execution_context and returned arguments passed to the
|
||||
most recent call to `execution_context::operator()`, if any and a
|
||||
execution_context representing the context that has been suspended.]]
|
||||
[[Note:] [The returned execution_context indicates if the suspended context has
|
||||
terminated (return from context-function) via `bool operator()`. If the returned
|
||||
execution_context has terminated no data are transferred in the returned tuple.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_call_ontop..operator()]
|
||||
|
||||
template< typename Fn >
|
||||
std::tuple< execution_context< Args ... >, Args ... > operator()( exec_ontop_arg_t, Fn && fn, Args ... args); // member of generic execution_context
|
||||
|
||||
template< typename Fn >
|
||||
execution_context< void > operator()( exec_ontop_arg_t, Fn && fn); // member of execution_context< void >
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Same as __ec_op__. Additionally, function `fn` is executed
|
||||
in the context of `*this` (e.g. the stack frame of `fn` is allocated on
|
||||
stack of `*this`).]]
|
||||
[[Returns:] [The tuple of execution_context and returned arguments passed to the
|
||||
most recent call to `execution_context::operator()`, if any and a
|
||||
execution_context representing the context that has been suspended .]]
|
||||
[[Note:] [The tuple of execution_context and returned arguments from `fn` are
|
||||
passed as arguments to the context-function of resumed context (if the context
|
||||
is entered the first time) or those arguments are returned from
|
||||
`execution_context::operator()` within the resumed context.]]
|
||||
[[Note:] [Function `fn` needs to return a tuple of arguments
|
||||
([link ecv2_ontop see description]).]]
|
||||
[[Note:] [The context calling this function must not be destroyed before the
|
||||
arguments, that will be returned from `fn`, are preserved at least in the stack
|
||||
frame of the resumed context.]]
|
||||
[[Note:] [The returned execution_context indicates if the suspended context has
|
||||
terminated (return from context-function) via `bool operator()`. If the returned
|
||||
execution_context has terminated no data are transferred in the returned tuple.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_equal..operator==]
|
||||
|
||||
bool operator==( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` and `other` represent the same execution context,
|
||||
`false` otherwise.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_notequal..operator!=]
|
||||
|
||||
bool operator!=( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [[`! (other == * this)]]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_less..operator<]
|
||||
|
||||
bool operator<( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this != other` is true and the
|
||||
implementation-defined total order of `execution_context` values places `*this`
|
||||
before `other`, false otherwise.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_greater..operator>]
|
||||
|
||||
bool operator>( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`other < * this`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_lesseq..operator<=]
|
||||
|
||||
bool operator<=( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`! (other < * this)`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[operator_heading ecv2..operator_greatereq..operator>=]
|
||||
|
||||
bool operator>=( execution_context const& other) const noexcept;
|
||||
|
||||
[variablelist
|
||||
[[Returns:] [`! (* this < other)`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[hding ecv2_..Non-member function [`operator<<()]]
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other);
|
||||
|
||||
[variablelist
|
||||
[[Efects:] [Writes the representation of `other` to stream `os`.]]
|
||||
[[Returns:] [`os`]]
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
@@ -132,12 +132,11 @@ of `f1.resume()`, the variable `i` has the value of `i+1`.
|
||||
|
||||
[heading Exception handling]
|
||||
|
||||
If the function executed inside a __context_fn__ emits ans exception, the
|
||||
If the function executed inside a __context_fn__ emits an exception, the
|
||||
application is terminated by calling `std::terminate()`. `std::exception_ptr`
|
||||
can be used to transfer exceptions between different fibers.
|
||||
|
||||
[important Do not jump from inside a catch block and then re-throw the exception
|
||||
in another fiber.]
|
||||
[important Do not jump from inside a catch block.]
|
||||
|
||||
|
||||
[#ff_ontop]
|
||||
@@ -146,7 +145,7 @@ in another fiber.]
|
||||
Sometimes it is useful to execute a new function on top of a resumed fiber. For
|
||||
this purpose __resume_with__ has to be used.
|
||||
The function passed as argument must accept a rvalue reference to __fib__ and
|
||||
return `void`.
|
||||
return __fib__.
|
||||
|
||||
namespace ctx=boost::context;
|
||||
int data=0;
|
||||
@@ -166,7 +165,7 @@ return `void`.
|
||||
f1=std::move(f1).resume();
|
||||
std::cout << "f1: returned second time: " << data << std::endl;
|
||||
data+=1;
|
||||
f1=f1.resume_with([&data](ctx::fiber&& f2){
|
||||
f1=std::move(f1).resume_with([&data](ctx::fiber&& f2){
|
||||
std::cout << "f2: entered: " << data << std::endl;
|
||||
data=-1;
|
||||
return std::move(f2);
|
||||
@@ -372,7 +371,7 @@ of the stack.]
|
||||
source=std::move(source).resume();
|
||||
while(!done){
|
||||
printf("Parsed: %c\n",c);
|
||||
source=std::Move(source).resume();
|
||||
source=std::move(source).resume();
|
||||
}
|
||||
|
||||
output:
|
||||
|
||||
@@ -232,6 +232,60 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
riscv64
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
SYSV|ELF
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
-
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
SYSV
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
-
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
s390x
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
SYSV|ELF
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
-
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
-
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
-
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
sparc
|
||||
|
||||
@@ -221,7 +221,7 @@
|
||||
</h4>
|
||||
<p>
|
||||
If the function executed inside a <span class="emphasis"><em>context-function</em></span> emits
|
||||
ans exception, the application is terminated by calling <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span><span class="special">()</span></code>. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>
|
||||
an exception, the application is terminated by calling <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span><span class="special">()</span></code>. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>
|
||||
can be used to transfer exceptions between different continuations.
|
||||
</p>
|
||||
<div class="important"><table border="0" summary="Important">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<link rel="home" href="../../index.html" title="Chapter 1. Context">
|
||||
<link rel="up" href="../cc.html" title="Context switching with call/cc">
|
||||
<link rel="prev" href="implementations__fcontext_t__ucontext_t_and_winfiber.html" title="Implementations: fcontext_t, ucontext_t and WinFiber">
|
||||
<link rel="next" href="../ecv2.html" title="Class execution_context (version 2)">
|
||||
<link rel="next" href="../stack.html" title="Stack allocation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
@@ -20,7 +20,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="implementations__fcontext_t__ucontext_t_and_winfiber.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../cc.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../ecv2.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="implementations__fcontext_t__ucontext_t_and_winfiber.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../cc.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../stack.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
@@ -501,7 +501,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="implementations__fcontext_t__ucontext_t_and_winfiber.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../cc.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../ecv2.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="implementations__fcontext_t__ucontext_t_and_winfiber.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../cc.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../stack.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -280,7 +280,7 @@
|
||||
</h4>
|
||||
<p>
|
||||
If the function executed inside a <span class="emphasis"><em>execution_context</em></span> emits
|
||||
ans exception, the application is terminated by calling <span class="emphasis"><em>std::terminate()</em></span>.
|
||||
an exception, the application is terminated by calling <span class="emphasis"><em>std::terminate()</em></span>.
|
||||
<span class="emphasis"><em>std::exception_ptr</em></span> can be used to transfer exceptions
|
||||
between different execution contexts.
|
||||
</p>
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
</h4>
|
||||
<p>
|
||||
If the function executed inside a <span class="emphasis"><em>execution_context</em></span> emits
|
||||
ans exception, the application is terminated by calling <span class="emphasis"><em>std::terminate()</em></span>.
|
||||
an exception, the application is terminated by calling <span class="emphasis"><em>std::terminate()</em></span>.
|
||||
<span class="emphasis"><em>std::exception_ptr</em></span> can be used to transfer exceptions
|
||||
between different execution contexts.
|
||||
</p>
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
</h4>
|
||||
<p>
|
||||
If the function executed inside a <span class="emphasis"><em>context-function</em></span> emits
|
||||
ans exception, the application is terminated by calling <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span><span class="special">()</span></code>. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>
|
||||
an exception, the application is terminated by calling <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span><span class="special">()</span></code>. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>
|
||||
can be used to transfer exceptions between different fibers.
|
||||
</p>
|
||||
<div class="important"><table border="0" summary="Important">
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
</h4>
|
||||
<p>
|
||||
If the function executed inside a <span class="emphasis"><em>context-function</em></span> emits
|
||||
ans exception, the application is terminated by calling <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span><span class="special">()</span></code>. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>
|
||||
an exception, the application is terminated by calling <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span><span class="special">()</span></code>. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code>
|
||||
can be used to transfer exceptions between different fibers.
|
||||
</p>
|
||||
<div class="important"><table border="0" summary="Important">
|
||||
|
||||
@@ -55,16 +55,6 @@
|
||||
requires only few CPU cycles because it does not involve system calls as it
|
||||
is done within a single thread.
|
||||
</p>
|
||||
<p>
|
||||
In order to use the classes and functions described here, you can either include
|
||||
the specific headers specified by the descriptions of each class or function,
|
||||
or include the master library header:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">context</span><span class="special">/</span><span class="identifier">all</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
</pre>
|
||||
<p>
|
||||
which includes all the other headers in turn.
|
||||
</p>
|
||||
<p>
|
||||
All functions and classes are contained in the namespace <span class="emphasis"><em>boost::context</em></span>.
|
||||
</p>
|
||||
@@ -83,10 +73,10 @@
|
||||
<th align="left">Important</th>
|
||||
</tr>
|
||||
<tr><td align="left" valign="top"><p>
|
||||
Windows: turn off global program optimization (/GL) and change /EHsc (compiler
|
||||
assumes that functions declared as extern "C" never throw a C++
|
||||
exception) to /EHs (tells compiler assumes that functions declared as extern
|
||||
"C" may throw an exception).
|
||||
Windows using fcontext_t: turn off global program optimization (/GL) and
|
||||
change /EHsc (compiler assumes that functions declared as extern "C"
|
||||
never throw a C++ exception) to /EHs (tells compiler assumes that functions
|
||||
declared as extern "C" may throw an exception).
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
</div>
|
||||
|
||||
@@ -71,8 +71,8 @@
|
||||
<th align="left">Important</th>
|
||||
</tr>
|
||||
<tr><td align="left" valign="top"><p>
|
||||
Windows: for safe SEH the property 'asmflags=\safeseh' must be specified
|
||||
at bjam command line.
|
||||
Windows using fcontext_t: for safe SEH the property 'asmflags=\safeseh' must
|
||||
be specified at bjam command line.
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
<div class="important"><table border="0" summary="Important">
|
||||
@@ -81,12 +81,20 @@
|
||||
<th align="left">Important</th>
|
||||
</tr>
|
||||
<tr><td align="left" valign="top"><p>
|
||||
Windows: turn off global program optimization (/GL) and change /EHsc (compiler
|
||||
assumes that functions declared as extern "C" never throw a C++
|
||||
exception) to /EHs (tells compiler assumes that functions declared as extern
|
||||
"C" may throw an exception).
|
||||
Windows using fcontext_t: turn off global program optimization (/GL) and
|
||||
change /EHsc (compiler assumes that functions declared as extern "C"
|
||||
never throw a C++ exception) to /EHs (tells compiler assumes that functions
|
||||
declared as extern "C" may throw an exception).
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
<p>
|
||||
Because this library uses C++11 extensively, it requires a compatible compiler.
|
||||
Known minimum working versions are as follows: Microsoft Visual Studio 2015
|
||||
(msvc-14.0), GCC 4.8 (with -std=c++11), Clang 3.4 (with -std=c++11). Other
|
||||
compilers may work, if they support the following language features: auto declarations,
|
||||
constexpr, defaulted functions, final, hdr thread, hdr tuple, lambdas, noexcept,
|
||||
nullptr, rvalue references, template aliases. thread local, variadic templates.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Context">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Context">
|
||||
<link rel="prev" href="ecv1.html" title="Class execution_context (version 1)">
|
||||
<link rel="prev" href="cc/class__continuation_.html" title="Class continuation">
|
||||
<link rel="next" href="stack/protected_fixedsize.html" title="Class protected_fixedsize">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
@@ -20,7 +20,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="ecv1.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="stack/protected_fixedsize.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="cc/class__continuation_.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="stack/protected_fixedsize.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -35,6 +35,7 @@
|
||||
<dt><span class="section"><a href="stack/stack_traits.html">Class <span class="emphasis"><em>stack_traits</em></span></a></span></dt>
|
||||
<dt><span class="section"><a href="stack/stack_context.html">Class <span class="emphasis"><em>stack_context</em></span></a></span></dt>
|
||||
<dt><span class="section"><a href="stack/valgrind.html">Support for valgrind</a></span></dt>
|
||||
<dt><span class="section"><a href="stack/sanitizers.html">Support for sanitizers</a></span></dt>
|
||||
</dl></div>
|
||||
<p>
|
||||
The memory used by the stack is allocated/deallocated via a <span class="emphasis"><em>StackAllocator</em></span>
|
||||
@@ -154,15 +155,6 @@
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td align="left" valign="top"><p>
|
||||
The stack is not required to be aligned; alignment takes place inside <span class="emphasis"><em>execution_context</em></span>.
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td align="left" valign="top"><p>
|
||||
Depending on the architecture <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code> stores an address from the top of the stack
|
||||
(growing downwards) or the bottom of the stack (growing upwards).
|
||||
@@ -179,7 +171,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="ecv1.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="stack/protected_fixedsize.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="cc/class__continuation_.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="stack/protected_fixedsize.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
49
doc/html/context/stack/sanitizers.html
Normal file
49
doc/html/context/stack/sanitizers.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Support for sanitizers</title>
|
||||
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../../index.html" title="Chapter 1. Context">
|
||||
<link rel="up" href="../stack.html" title="Stack allocation">
|
||||
<link rel="prev" href="valgrind.html" title="Support for valgrind">
|
||||
<link rel="next" href="../struct__preallocated_.html" title="Struct preallocated">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="valgrind.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../struct__preallocated_.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="context.stack.sanitizers"></a><a class="link" href="sanitizers.html" title="Support for sanitizers">Support for sanitizers</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
Sanitizers (GCC/Clang) are confused by the stack switches. The library is
|
||||
required to be compiled with property (b2 command-line) <code class="computeroutput"><span class="identifier">context</span><span class="special">-</span><span class="identifier">impl</span><span class="special">=</span><span class="identifier">ucontext</span></code> and compilers santizer options.
|
||||
Users must define <code class="computeroutput"><span class="identifier">BOOST_USE_ASAN</span></code>
|
||||
before including any Boost.Context headers when linking against Boost binaries.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2014 Oliver Kowalke<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="valgrind.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../struct__preallocated_.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -59,7 +59,6 @@
|
||||
<tr><td align="left" valign="top"><p>
|
||||
Segmented stacks can only be used with <a class="link" href="../cc.html#cc"><span class="emphasis"><em>callcc()</em></span></a>
|
||||
(using <a class="link" href="../ff/implementations__fcontext_t__ucontext_t_and_winfiber.html#implementation"><span class="emphasis"><em>ucontext_t</em></span></a>)
|
||||
and <span class="emphasis"><em>execution_context</em></span> (v1)
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
<p>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<link rel="home" href="../../index.html" title="Chapter 1. Context">
|
||||
<link rel="up" href="../stack.html" title="Stack allocation">
|
||||
<link rel="prev" href="stack_context.html" title="Class stack_context">
|
||||
<link rel="next" href="../struct__preallocated_.html" title="Struct preallocated">
|
||||
<link rel="next" href="sanitizers.html" title="Support for sanitizers">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
@@ -20,7 +20,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="stack_context.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../struct__preallocated_.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="stack_context.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="sanitizers.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
@@ -45,7 +45,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="stack_context.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../struct__preallocated_.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="stack_context.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../stack.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="sanitizers.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Context">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Context">
|
||||
<link rel="prev" href="stack/valgrind.html" title="Support for valgrind">
|
||||
<link rel="prev" href="stack/sanitizers.html" title="Support for sanitizers">
|
||||
<link rel="next" href="performance.html" title="Performance">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
@@ -20,7 +20,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="stack/valgrind.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="performance.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="stack/sanitizers.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="performance.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -60,7 +60,7 @@
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="stack/valgrind.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="performance.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="stack/sanitizers.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="performance.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -7,8 +7,6 @@ context/ff/class__fiber_.html
|
||||
context/cc.html
|
||||
context/cc/implementations__fcontext_t__ucontext_t_and_winfiber.html
|
||||
context/cc/class__continuation_.html
|
||||
context/ecv2.html
|
||||
context/ecv1.html
|
||||
context/stack.html
|
||||
context/stack/protected_fixedsize.html
|
||||
context/stack/pooled_fixedsize.html
|
||||
@@ -17,6 +15,7 @@ context/stack/segmented.html
|
||||
context/stack/stack_traits.html
|
||||
context/stack/stack_context.html
|
||||
context/stack/valgrind.html
|
||||
context/stack/sanitizers.html
|
||||
context/struct__preallocated_.html
|
||||
context/performance.html
|
||||
context/architectures.html
|
||||
|
||||
@@ -50,10 +50,6 @@
|
||||
fcontext_t, ucontext_t and WinFiber</a></span></dt>
|
||||
<dt><span class="section"><a href="context/cc/class__continuation_.html">Class <code class="computeroutput"><span class="identifier">continuation</span></code></a></span></dt>
|
||||
</dl></dd>
|
||||
<dt><span class="section"><a href="context/ecv2.html">Class execution_context
|
||||
(version 2)</a></span></dt>
|
||||
<dt><span class="section"><a href="context/ecv1.html">Class execution_context
|
||||
(version 1)</a></span></dt>
|
||||
<dt><span class="section"><a href="context/stack.html">Stack allocation</a></span></dt>
|
||||
<dd><dl>
|
||||
<dt><span class="section"><a href="context/stack/protected_fixedsize.html">Class <span class="emphasis"><em>protected_fixedsize</em></span></a></span></dt>
|
||||
@@ -64,6 +60,7 @@
|
||||
<dt><span class="section"><a href="context/stack/stack_traits.html">Class <span class="emphasis"><em>stack_traits</em></span></a></span></dt>
|
||||
<dt><span class="section"><a href="context/stack/stack_context.html">Class <span class="emphasis"><em>stack_context</em></span></a></span></dt>
|
||||
<dt><span class="section"><a href="context/stack/valgrind.html">Support for valgrind</a></span></dt>
|
||||
<dt><span class="section"><a href="context/stack/sanitizers.html">Support for sanitizers</a></span></dt>
|
||||
</dl></dd>
|
||||
<dt><span class="section"><a href="context/struct__preallocated_.html">Struct <code class="computeroutput"><span class="identifier">preallocated</span></code></a></span></dt>
|
||||
<dt><span class="section"><a href="context/performance.html">Performance</a></span></dt>
|
||||
@@ -81,7 +78,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: February 15, 2018 at 16:18:36 GMT</small></p></td>
|
||||
<td align="left"><p><small>Last revised: October 02, 2019 at 06:15:46 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
|
||||
@@ -43,9 +43,6 @@ undefined behaviour.]
|
||||
[important Calling `deallocate()` with a `stack_context` not set by `allocate()`
|
||||
results in undefined behaviour.]
|
||||
|
||||
[note The stack is not required to be aligned; alignment takes place inside
|
||||
__econtext__.]
|
||||
|
||||
[note Depending on the architecture `allocate()` stores an address from the
|
||||
top of the stack (growing downwards) or the bottom of the stack (growing
|
||||
upwards).]
|
||||
@@ -216,7 +213,7 @@ property `segmented-stacks`, e.g. [*toolset=gcc segmented-stacks=on] and
|
||||
applying `BOOST_USE_SEGMENTED_STACKS` at b2/bjam command line.]
|
||||
|
||||
[note Segmented stacks can only be used with __cc__ (using
|
||||
[link implementation __ucontext__]) and __econtext__ (v1)].
|
||||
[link implementation __ucontext__])].
|
||||
|
||||
#include <boost/context/segmented_stack.hpp>
|
||||
|
||||
@@ -356,4 +353,15 @@ compiled with `valgrind=on`.
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:sanitizers Support for sanitizers]
|
||||
|
||||
Sanitizers (GCC/Clang) are confused by the stack switches.
|
||||
The library is required to be compiled with property (b2 command-line)
|
||||
`context-impl=ucontext` and compilers santizer options.
|
||||
Users must define `BOOST_USE_ASAN` before including any Boost.Context headers
|
||||
when linking against Boost binaries.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -18,8 +18,8 @@ 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
|
||||
<target-os>linux,<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<target-os>linux,<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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ int main() {
|
||||
c = c.resume_with(
|
||||
[](ctx::continuation && c){
|
||||
throw my_exception(std::move( c), "abc");
|
||||
return std::move( c);
|
||||
return {};
|
||||
});
|
||||
|
||||
std::cout << "main: done" << std::endl;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -18,8 +18,8 @@ import architecture ;
|
||||
project boost/context/example/fiber
|
||||
: requirements
|
||||
<library>/boost/context//boost_context
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<toolset>gcc,<segmented-stacks>on:<cxxflags>-DBOOST_USE_SEGMENTED_STACKS
|
||||
<target-os>linux,<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<target-os>linux,<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
|
||||
|
||||
@@ -80,9 +80,6 @@ void context_entry( transfer_t t) noexcept {
|
||||
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
|
||||
|
||||
@@ -210,19 +210,10 @@ struct BOOST_CONTEXT_DECL 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 >
|
||||
@@ -268,9 +259,6 @@ public:
|
||||
#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;
|
||||
@@ -299,6 +287,8 @@ static activation_record * create_context1( StackAlloc && salloc, Fn && fn) {
|
||||
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");
|
||||
@@ -332,6 +322,8 @@ static activation_record * create_context2( preallocated palloc, StackAlloc && s
|
||||
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");
|
||||
@@ -461,6 +453,8 @@ public:
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
|
||||
@@ -471,11 +465,33 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other);
|
||||
|
||||
#endif
|
||||
|
||||
void swap( continuation & other) noexcept {
|
||||
std::swap( ptr_, other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
inline 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}";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<
|
||||
typename Fn,
|
||||
typename = detail::disable_overload< continuation, Fn >
|
||||
|
||||
@@ -186,19 +186,10 @@ struct BOOST_CONTEXT_DECL 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 >
|
||||
@@ -239,9 +230,6 @@ public:
|
||||
#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;
|
||||
@@ -399,7 +387,9 @@ public:
|
||||
bool operator<( continuation const& other) const noexcept {
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) {
|
||||
@@ -410,11 +400,33 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other);
|
||||
|
||||
#endif
|
||||
|
||||
void swap( continuation & other) noexcept {
|
||||
std::swap( ptr_, other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
inline 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}";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<
|
||||
typename Fn,
|
||||
typename = detail::disable_overload< continuation, Fn >
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
# define BOOST_CONTEXT_DECL
|
||||
#endif
|
||||
|
||||
#if ! defined(BOOST_USE_UCONTEXT) && defined(__CYGWIN__)
|
||||
# define BOOST_USE_UCONTEXT
|
||||
#endif
|
||||
|
||||
#if ! defined(BOOST_CONTEXT_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_CONTEXT_NO_LIB)
|
||||
# define BOOST_LIB_NAME boost_context
|
||||
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTEXT_DYN_LINK)
|
||||
@@ -115,4 +119,18 @@ static constexpr std::size_t cacheline_length{ 64 };
|
||||
static constexpr std::size_t prefetch_stride{ 4 * cacheline_length };
|
||||
#endif
|
||||
|
||||
#if defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||
// GNU libstdc++ 3
|
||||
# define BOOST_CONTEXT_HAS_CXXABI_H
|
||||
#endif
|
||||
|
||||
#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
|
||||
# include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
// stacks need mmap(2) with MAP_STACK
|
||||
# define BOOST_CONTEXT_USE_MAP_STACK
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONTEXT_DETAIL_CONFIG_H
|
||||
|
||||
@@ -22,21 +22,12 @@ 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
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE)
|
||||
#include <boost/mp11/integer_sequence.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
@@ -29,38 +33,12 @@ using make_index_sequence = std::make_index_sequence< I >;
|
||||
template< typename ... T >
|
||||
using index_sequence_for = std::index_sequence_for< T ... >;
|
||||
#else
|
||||
//http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence
|
||||
|
||||
template< std::size_t ... I >
|
||||
struct index_sequence {
|
||||
using type = index_sequence;
|
||||
using value_type = std::size_t;
|
||||
static constexpr std::size_t size() {
|
||||
return sizeof ... (I);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Seq1, typename Seq2 >
|
||||
struct concat_sequence;
|
||||
|
||||
template< std::size_t ... I1, std::size_t ... I2 >
|
||||
struct concat_sequence< index_sequence< I1 ... >, index_sequence< I2 ... > > : public index_sequence< I1 ..., (sizeof ... (I1)+I2) ... > {
|
||||
};
|
||||
|
||||
using index_sequence = mp11::index_sequence< I ... >;
|
||||
template< std::size_t I >
|
||||
struct make_index_sequence : public concat_sequence< typename make_index_sequence< I/2 >::type,
|
||||
typename make_index_sequence< I-I/2 >::type > {
|
||||
};
|
||||
|
||||
template<>
|
||||
struct make_index_sequence< 0 > : public index_sequence<> {
|
||||
};
|
||||
template<>
|
||||
struct make_index_sequence< 1 > : public index_sequence< 0 > {
|
||||
};
|
||||
|
||||
using make_index_sequence = mp11::make_index_sequence< I >;
|
||||
template< typename ... T >
|
||||
using index_sequence_for = make_index_sequence< sizeof ... (T) >;
|
||||
using index_sequence_for = mp11::index_sequence_for< T ... >;
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
#if BOOST_COMP_MSVC
|
||||
#if BOOST_COMP_MSVC && !defined(_M_ARM) && !defined(_M_ARM64)
|
||||
#include <mmintrin.h>
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,7 @@ void prefetch( void * addr) {
|
||||
// L1 cache : hint == _MM_HINT_T0
|
||||
_mm_prefetch( (const char *)addr, _MM_HINT_T0);
|
||||
}
|
||||
#elif BOOST_COMP_MSVC
|
||||
#elif BOOST_COMP_MSVC && !defined(_M_ARM) && !defined(_M_ARM64)
|
||||
#define BOOST_HAS_PREFETCH 1
|
||||
BOOST_FORCEINLINE
|
||||
void prefetch( void * addr) {
|
||||
|
||||
@@ -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,482 +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
|
||||
} 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,307 +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();
|
||||
} 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -80,9 +80,6 @@ void fiber_entry( transfer_t t) noexcept {
|
||||
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
|
||||
@@ -92,12 +89,11 @@ void fiber_entry( transfer_t t) noexcept {
|
||||
|
||||
template< typename Ctx, typename Fn >
|
||||
transfer_t fiber_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);
|
||||
BOOST_ASSERT( nullptr != t.data);
|
||||
auto p = *static_cast< Fn * >( t.data);
|
||||
t.data = nullptr;
|
||||
// execute function, pass fiber via reference
|
||||
Ctx c = fn( Ctx{ t.fctx } );
|
||||
Ctx c = p( Ctx{ t.fctx } );
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
return { exchange( c.fctx_, nullptr), nullptr };
|
||||
#else
|
||||
@@ -292,7 +288,7 @@ public:
|
||||
template< typename Fn >
|
||||
fiber resume_with( Fn && fn) && {
|
||||
BOOST_ASSERT( nullptr != fctx_);
|
||||
auto p = std::make_tuple( std::forward< Fn >( fn) );
|
||||
auto p = std::forward< Fn >( fn);
|
||||
return { detail::ontop_fcontext(
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
detail::exchange( fctx_, nullptr),
|
||||
@@ -300,7 +296,7 @@ public:
|
||||
std::exchange( fctx_, nullptr),
|
||||
#endif
|
||||
& p,
|
||||
detail::fiber_ontop< fiber, Fn >).fctx };
|
||||
detail::fiber_ontop< fiber, decltype(p) >).fctx };
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
@@ -315,6 +311,8 @@ public:
|
||||
return fctx_ < other.fctx_;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) {
|
||||
@@ -325,11 +323,33 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other);
|
||||
|
||||
#endif
|
||||
|
||||
void swap( fiber & other) noexcept {
|
||||
std::swap( fctx_, other.fctx_);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
inline std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) {
|
||||
if ( nullptr != other.fctx_) {
|
||||
return os << other.fctx_;
|
||||
} else {
|
||||
return os << "{not-a-context}";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline
|
||||
void swap( fiber & l, fiber & r) noexcept {
|
||||
l.swap( r);
|
||||
|
||||
@@ -32,6 +32,7 @@ extern "C" {
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/predef.h>
|
||||
|
||||
#include <boost/context/detail/disable_overload.hpp>
|
||||
#if defined(BOOST_NO_CXX14_STD_EXCHANGE)
|
||||
@@ -53,6 +54,10 @@ extern "C" {
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_USE_TSAN
|
||||
#include <sanitizer/tsan_interface.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace context {
|
||||
namespace detail {
|
||||
@@ -82,6 +87,11 @@ struct BOOST_CONTEXT_DECL fiber_activation_record {
|
||||
std::size_t stack_size{ 0 };
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_USE_TSAN)
|
||||
void * tsan_fiber{ nullptr };
|
||||
bool destroy_tsan_fiber{ true };
|
||||
#endif
|
||||
|
||||
static fiber_activation_record *& current() noexcept;
|
||||
|
||||
// used for toplevel-context
|
||||
@@ -92,6 +102,11 @@ struct BOOST_CONTEXT_DECL fiber_activation_record {
|
||||
std::error_code( errno, std::system_category() ),
|
||||
"getcontext() failed");
|
||||
}
|
||||
|
||||
#if defined(BOOST_USE_TSAN)
|
||||
tsan_fiber = __tsan_get_current_fiber();
|
||||
destroy_tsan_fiber = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
fiber_activation_record( stack_context sctx_) noexcept :
|
||||
@@ -100,6 +115,10 @@ struct BOOST_CONTEXT_DECL fiber_activation_record {
|
||||
}
|
||||
|
||||
virtual ~fiber_activation_record() {
|
||||
#if defined(BOOST_USE_TSAN)
|
||||
if (destroy_tsan_fiber)
|
||||
__tsan_destroy_fiber(tsan_fiber);
|
||||
#endif
|
||||
}
|
||||
|
||||
fiber_activation_record( fiber_activation_record const&) = delete;
|
||||
@@ -125,6 +144,9 @@ struct BOOST_CONTEXT_DECL fiber_activation_record {
|
||||
} else {
|
||||
__sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size);
|
||||
}
|
||||
#endif
|
||||
#if defined (BOOST_USE_TSAN)
|
||||
__tsan_switch_to_fiber(tsan_fiber, 0);
|
||||
#endif
|
||||
// context switch from parent context to `this`-context
|
||||
::swapcontext( & from->uctx, & uctx);
|
||||
@@ -184,6 +206,9 @@ struct BOOST_CONTEXT_DECL fiber_activation_record {
|
||||
#endif
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
__sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size);
|
||||
#endif
|
||||
#if defined (BOOST_USE_TSAN)
|
||||
__tsan_switch_to_fiber(tsan_fiber, 0);
|
||||
#endif
|
||||
// context switch from parent context to `this`-context
|
||||
::swapcontext( & from->uctx, & uctx);
|
||||
@@ -210,19 +235,10 @@ struct BOOST_CONTEXT_DECL 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 >
|
||||
@@ -268,9 +284,6 @@ public:
|
||||
#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;
|
||||
@@ -299,11 +312,18 @@ static fiber_activation_record * create_fiber1( StackAlloc && salloc, Fn && fn)
|
||||
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");
|
||||
}
|
||||
#if BOOST_OS_BSD_FREE
|
||||
// because FreeBSD defines stack_t::ss_sp as char *
|
||||
record->uctx.uc_stack.ss_sp = static_cast< char * >( stack_bottom);
|
||||
#else
|
||||
record->uctx.uc_stack.ss_sp = stack_bottom;
|
||||
#endif
|
||||
// 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);
|
||||
@@ -312,6 +332,9 @@ static fiber_activation_record * create_fiber1( StackAlloc && salloc, Fn && fn)
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
record->stack_bottom = record->uctx.uc_stack.ss_sp;
|
||||
record->stack_size = record->uctx.uc_stack.ss_size;
|
||||
#endif
|
||||
#if defined (BOOST_USE_TSAN)
|
||||
record->tsan_fiber = __tsan_create_fiber(0);
|
||||
#endif
|
||||
return record;
|
||||
}
|
||||
@@ -332,11 +355,18 @@ static fiber_activation_record * create_fiber2( preallocated palloc, StackAlloc
|
||||
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");
|
||||
}
|
||||
#if BOOST_OS_BSD_FREE
|
||||
// because FreeBSD defines stack_t::ss_sp as char *
|
||||
record->uctx.uc_stack.ss_sp = static_cast< char * >( stack_bottom);
|
||||
#else
|
||||
record->uctx.uc_stack.ss_sp = stack_bottom;
|
||||
#endif
|
||||
// 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);
|
||||
@@ -345,6 +375,9 @@ static fiber_activation_record * create_fiber2( preallocated palloc, StackAlloc
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
record->stack_bottom = record->uctx.uc_stack.ss_sp;
|
||||
record->stack_size = record->uctx.uc_stack.ss_size;
|
||||
#endif
|
||||
#if defined (BOOST_USE_TSAN)
|
||||
record->tsan_fiber = __tsan_create_fiber(0);
|
||||
#endif
|
||||
return record;
|
||||
}
|
||||
@@ -478,6 +511,8 @@ public:
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) {
|
||||
@@ -488,11 +523,33 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other);
|
||||
|
||||
#endif
|
||||
|
||||
void swap( fiber & other) noexcept {
|
||||
std::swap( ptr_, other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
inline 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}";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline
|
||||
void swap( fiber & l, fiber & r) noexcept {
|
||||
l.swap( r);
|
||||
|
||||
@@ -185,19 +185,10 @@ struct BOOST_CONTEXT_DECL 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 >
|
||||
@@ -238,9 +229,6 @@ public:
|
||||
#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;
|
||||
@@ -410,7 +398,9 @@ public:
|
||||
bool operator<( fiber const& other) const noexcept {
|
||||
return ptr_ < other.ptr_;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) {
|
||||
@@ -421,11 +411,33 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other);
|
||||
|
||||
#endif
|
||||
|
||||
void swap( fiber & other) noexcept {
|
||||
std::swap( ptr_, other.ptr_);
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_EMBTC)
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
inline 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}";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline
|
||||
void swap( fiber & l, fiber & r) noexcept {
|
||||
l.swap( r);
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
#include <boost/context/stack_context.hpp>
|
||||
#include <boost/context/stack_traits.hpp>
|
||||
|
||||
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
|
||||
extern "C" {
|
||||
#include <sys/mman.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_USE_VALGRIND)
|
||||
#include <valgrind/valgrind.h>
|
||||
#endif
|
||||
@@ -42,10 +48,17 @@ public:
|
||||
}
|
||||
|
||||
stack_context allocate() {
|
||||
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
|
||||
void * vp = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
|
||||
if ( vp == MAP_FAILED) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
#else
|
||||
void * vp = std::malloc( size_);
|
||||
if ( ! vp) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
#endif
|
||||
stack_context sctx;
|
||||
sctx.size = size_;
|
||||
sctx.sp = static_cast< char * >( vp) + sctx.size;
|
||||
@@ -62,7 +75,11 @@ public:
|
||||
VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id);
|
||||
#endif
|
||||
void * vp = static_cast< char * >( sctx.sp) - sctx.size;
|
||||
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
|
||||
::munmap( vp, sctx.size);
|
||||
#else
|
||||
std::free( vp);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,13 @@
|
||||
#include <boost/context/stack_context.hpp>
|
||||
#include <boost/context/stack_traits.hpp>
|
||||
|
||||
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
|
||||
extern "C" {
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_USE_VALGRIND)
|
||||
#include <valgrind/valgrind.h>
|
||||
#endif
|
||||
@@ -32,6 +39,31 @@
|
||||
namespace boost {
|
||||
namespace context {
|
||||
|
||||
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
|
||||
namespace detail {
|
||||
template< typename traitsT >
|
||||
struct map_stack_allocator {
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
static char * malloc( const size_type bytes) {
|
||||
void * block;
|
||||
if ( ::posix_memalign( &block, traitsT::page_size(), bytes) != 0) {
|
||||
return 0;
|
||||
}
|
||||
if ( mmap( block, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_STACK, -1, 0) == MAP_FAILED) {
|
||||
std::free( block);
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast< char * >( block);
|
||||
}
|
||||
static void free( char * const block) {
|
||||
std::free( block);
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
template< typename traitsT >
|
||||
class basic_pooled_fixedsize_stack {
|
||||
private:
|
||||
@@ -39,7 +71,11 @@ private:
|
||||
private:
|
||||
std::atomic< std::size_t > use_count_;
|
||||
std::size_t stack_size_;
|
||||
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
|
||||
boost::pool< detail::map_stack_allocator< traitsT > > storage_;
|
||||
#else
|
||||
boost::pool< boost::default_user_allocator_malloc_free > storage_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
storage( std::size_t stack_size, std::size_t next_size, std::size_t max_size) :
|
||||
|
||||
@@ -20,6 +20,7 @@ extern "C" {
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
#include <boost/context/stack_context.hpp>
|
||||
@@ -50,15 +51,13 @@ public:
|
||||
|
||||
stack_context allocate() {
|
||||
// calculate how many pages are required
|
||||
const std::size_t pages(
|
||||
static_cast< std::size_t >(
|
||||
std::ceil(
|
||||
static_cast< float >( size_) / traits_type::page_size() ) ) );
|
||||
const std::size_t pages = (size_ + traits_type::page_size() - 1) / traits_type::page_size();
|
||||
// add one page at bottom that will be used as guard-page
|
||||
const std::size_t size__ = ( pages + 1) * traits_type::page_size();
|
||||
|
||||
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
|
||||
#if defined(MAP_ANON)
|
||||
#if defined(BOOST_CONTEXT_USE_MAP_STACK)
|
||||
void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
|
||||
#elif defined(MAP_ANON)
|
||||
void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
@@ -66,12 +65,9 @@ public:
|
||||
if ( MAP_FAILED == vp) throw std::bad_alloc();
|
||||
|
||||
// conforming to POSIX.1-2001
|
||||
#if defined(BOOST_DISABLE_ASSERTS)
|
||||
::mprotect( vp, traits_type::page_size(), PROT_NONE);
|
||||
#else
|
||||
const int result( ::mprotect( vp, traits_type::page_size(), PROT_NONE) );
|
||||
boost::ignore_unused(result);
|
||||
BOOST_ASSERT( 0 == result);
|
||||
#endif
|
||||
|
||||
stack_context sctx;
|
||||
sctx.size = size__;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace boost {
|
||||
namespace context {
|
||||
|
||||
#if ! defined(BOOST_CONTEXT_NO_CXX11)
|
||||
struct stack_context {
|
||||
struct BOOST_CONTEXT_DECL stack_context {
|
||||
# if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
typedef void * segments_context[BOOST_CONTEXT_SEGMENTS];
|
||||
# endif
|
||||
@@ -36,7 +36,7 @@ struct stack_context {
|
||||
# endif
|
||||
};
|
||||
#else
|
||||
struct stack_context {
|
||||
struct BOOST_CONTEXT_DECL stack_context {
|
||||
# if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
typedef void * segments_context[BOOST_CONTEXT_SEGMENTS];
|
||||
# endif
|
||||
|
||||
@@ -16,6 +16,7 @@ extern "C" {
|
||||
#include <new>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/context/detail/config.hpp>
|
||||
#include <boost/context/stack_context.hpp>
|
||||
@@ -42,10 +43,7 @@ public:
|
||||
|
||||
stack_context allocate() {
|
||||
// calculate how many pages are required
|
||||
const std::size_t pages(
|
||||
static_cast< std::size_t >(
|
||||
std::ceil(
|
||||
static_cast< float >( size_) / traits_type::page_size() ) ) );
|
||||
const std::size_t pages = (size_ + traits_type::page_size() - 1) / traits_type::page_size();
|
||||
// add one page at bottom that will be used as guard-page
|
||||
const std::size_t size__ = ( pages + 1) * traits_type::page_size();
|
||||
|
||||
@@ -53,14 +51,10 @@ public:
|
||||
if ( ! vp) throw std::bad_alloc();
|
||||
|
||||
DWORD old_options;
|
||||
#if defined(BOOST_DISABLE_ASSERTS)
|
||||
::VirtualProtect(
|
||||
vp, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
|
||||
#else
|
||||
const BOOL result = ::VirtualProtect(
|
||||
vp, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
|
||||
boost::ignore_unused(result);
|
||||
BOOST_ASSERT( FALSE != result);
|
||||
#endif
|
||||
|
||||
stack_context sctx;
|
||||
sctx.size = size__;
|
||||
|
||||
@@ -11,5 +11,6 @@
|
||||
],
|
||||
"maintainers": [
|
||||
"Oliver Kowalke <oliver.kowalke -at- gmail.com>"
|
||||
]
|
||||
],
|
||||
"cxxstd": "11"
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ project boost/context/performance/callcc
|
||||
<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
|
||||
<target-os>linux,<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<target-os>linux,<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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -18,8 +18,8 @@ project boost/context/performance/fcontext
|
||||
<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
|
||||
<target-os>linux,<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<target-os>linux,<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
|
||||
|
||||
@@ -18,8 +18,8 @@ project boost/context/performance/fiber
|
||||
<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
|
||||
<target-os>linux,<toolset>gcc,<segmented-stacks>on:<cxxflags>-fsplit-stack
|
||||
<target-os>linux,<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
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
.globl jump_fcontext
|
||||
.align 2
|
||||
.type jump_fcontext,%function
|
||||
.syntax unified
|
||||
jump_fcontext:
|
||||
@ save LR as PC
|
||||
push {lr}
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
#include "jump_ppc32_sysv_macho_gas.S"
|
||||
#elif defined(__ppc64__)
|
||||
#include "jump_ppc64_sysv_macho_gas.S"
|
||||
#elif defined(__arm__)
|
||||
#include "jump_arm_aapcs_macho_gas.S"
|
||||
#elif defined(__arm64__)
|
||||
#include "jump_arm64_aapcs_macho_gas.S"
|
||||
#else
|
||||
#error "No arch's"
|
||||
#endif
|
||||
|
||||
123
src/asm/jump_i386_ms_pe_clang_gas.S
Normal file
123
src/asm/jump_i386_ms_pe_clang_gas.S
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
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_clang_gas.S"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
|
||||
/* mark as using no unregistered SEH handlers */
|
||||
.globl @feat.00
|
||||
.def @feat.00; .scl 3; .type 0; .endef
|
||||
.set @feat.00, 1
|
||||
|
||||
.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\""
|
||||
@@ -26,6 +26,12 @@
|
||||
.file "jump_i386_ms_pe_gas.asm"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
|
||||
/* mark as using no unregistered SEH handlers */
|
||||
.globl @feat.00
|
||||
.def @feat.00; .scl 3; .type 0; .endef
|
||||
.set @feat.00, 1
|
||||
|
||||
.globl _jump_fcontext
|
||||
.def _jump_fcontext; .scl 2; .type 32; .endef
|
||||
_jump_fcontext:
|
||||
|
||||
@@ -54,9 +54,8 @@ _jump_fcontext:
|
||||
|
||||
/* return parent fcontext_t */
|
||||
movl %ecx, %eax
|
||||
/* returned data is stored in EDX */
|
||||
movl %edx, 0x4(%eax)
|
||||
|
||||
/* returned data is stored in EDX */
|
||||
|
||||
movl 0x18(%esp), %ecx /* restore EIP */
|
||||
|
||||
#if !defined(BOOST_USE_TSX)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
.file "jump_mips64_n64_elf_gas.S"
|
||||
.text
|
||||
.globl jump_fcontext
|
||||
.align 2
|
||||
.align 3
|
||||
.type jump_fcontext,@function
|
||||
.ent jump_fcontext
|
||||
jump_fcontext:
|
||||
@@ -67,7 +67,7 @@ jump_fcontext:
|
||||
sd $ra, 144($sp) # save RA
|
||||
sd $ra, 152($sp) # save RA as PC
|
||||
|
||||
|
||||
#if defined(__mips_hard_float)
|
||||
s.d $f24, 0($sp) # save F24
|
||||
s.d $f25, 8($sp) # save F25
|
||||
s.d $f26, 16($sp) # save F26
|
||||
@@ -76,6 +76,7 @@ jump_fcontext:
|
||||
s.d $f29, 40($sp) # save F29
|
||||
s.d $f30, 48($sp) # save F30
|
||||
s.d $f31, 56($sp) # save F31
|
||||
#endif
|
||||
|
||||
# store SP (pointing to old context-data) in v0 as return
|
||||
move $v0, $sp
|
||||
@@ -83,6 +84,7 @@ jump_fcontext:
|
||||
# get SP (pointing to new context-data) from a0 param
|
||||
move $sp, $a0
|
||||
|
||||
#if defined(__mips_hard_float)
|
||||
l.d $f24, 0($sp) # restore F24
|
||||
l.d $f25, 8($sp) # restore F25
|
||||
l.d $f26, 16($sp) # restore F26
|
||||
@@ -91,6 +93,7 @@ jump_fcontext:
|
||||
l.d $f29, 40($sp) # restore F29
|
||||
l.d $f30, 48($sp) # restore F30
|
||||
l.d $f31, 56($sp) # restore F31
|
||||
#endif
|
||||
|
||||
ld $s0, 64($sp) # restore S0
|
||||
ld $s1, 72($sp) # restore S1
|
||||
|
||||
@@ -5,71 +5,48 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
/******************************************************
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* |bchai|hiddn| fpscr | PC | CR | R14 | R15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R16 | R17 | R18 | R19 | R20 | R21 | R22 | R23 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R24 | R25 | R26 | R27 | R28 | R29 | R30 | R31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F14 | F15 | F16 | F17 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F18 | F19 | F20 | F21 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F22 | F23 | F24 | F25 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 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| | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------|------------ *
|
||||
* | 224 | 228 | 232 | 236 | 240 | 244 | *
|
||||
* ------------------------|------------ *
|
||||
* | F30 | F31 |bchai| LR | *
|
||||
* ------------------------|------------ *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
@@ -79,125 +56,142 @@
|
||||
.align 2
|
||||
.type jump_fcontext,@function
|
||||
jump_fcontext:
|
||||
# reserve space on stack
|
||||
subi %r1, %r1, 244
|
||||
# Linux: jump_fcontext( hidden transfer_t * R3, R4, R5)
|
||||
# Other: transfer_t R3:R4 = jump_fcontext( R3, R4)
|
||||
|
||||
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
|
||||
mflr %r0 # return address from LR
|
||||
mffs %f0 # FPSCR
|
||||
mfcr %r8 # condition register
|
||||
|
||||
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
|
||||
stwu %r1, -240(%r1) # allocate stack space, R1 % 16 == 0
|
||||
stw %r0, 244(%r1) # save LR in caller's frame
|
||||
|
||||
# save CR
|
||||
mfcr %r0
|
||||
stw %r0, 232(%r1)
|
||||
# save LR
|
||||
mflr %r0
|
||||
stw %r0, 236(%r1)
|
||||
# save LR as PC
|
||||
stw %r0, 240(%r1)
|
||||
#ifdef __linux__
|
||||
stw %r3, 4(%r1) # hidden pointer
|
||||
#endif
|
||||
|
||||
# store RSP (pointing to context-data) in R6
|
||||
mr %r6, %r1
|
||||
stfd %f0, 8(%r1) # FPSCR
|
||||
stw %r0, 16(%r1) # LR as PC
|
||||
stw %r8, 20(%r1) # CR
|
||||
|
||||
# restore RSP (pointing to context-data) from R4
|
||||
mr %r1, %r4
|
||||
# Save registers R14 to R31.
|
||||
# Don't change R2, the thread-local storage pointer.
|
||||
# Don't change R13, the small data pointer.
|
||||
stw %r14, 24(%r1)
|
||||
stw %r15, 28(%r1)
|
||||
stw %r16, 32(%r1)
|
||||
stw %r17, 36(%r1)
|
||||
stw %r18, 40(%r1)
|
||||
stw %r19, 44(%r1)
|
||||
stw %r20, 48(%r1)
|
||||
stw %r21, 52(%r1)
|
||||
stw %r22, 56(%r1)
|
||||
stw %r23, 60(%r1)
|
||||
stw %r24, 64(%r1)
|
||||
stw %r25, 68(%r1)
|
||||
stw %r26, 72(%r1)
|
||||
stw %r27, 76(%r1)
|
||||
stw %r28, 80(%r1)
|
||||
stw %r29, 84(%r1)
|
||||
stw %r30, 88(%r1)
|
||||
stw %r31, 92(%r1)
|
||||
|
||||
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
|
||||
# Save registers F14 to F31 in slots with 8-byte alignment.
|
||||
# 4-byte alignment may stall the pipeline of some processors.
|
||||
# Less than 4 may cause alignment traps.
|
||||
stfd %f14, 96(%r1)
|
||||
stfd %f15, 104(%r1)
|
||||
stfd %f16, 112(%r1)
|
||||
stfd %f17, 120(%r1)
|
||||
stfd %f18, 128(%r1)
|
||||
stfd %f19, 136(%r1)
|
||||
stfd %f20, 144(%r1)
|
||||
stfd %f21, 152(%r1)
|
||||
stfd %f22, 160(%r1)
|
||||
stfd %f23, 168(%r1)
|
||||
stfd %f24, 176(%r1)
|
||||
stfd %f25, 184(%r1)
|
||||
stfd %f26, 192(%r1)
|
||||
stfd %f27, 200(%r1)
|
||||
stfd %f28, 208(%r1)
|
||||
stfd %f29, 216(%r1)
|
||||
stfd %f30, 224(%r1)
|
||||
stfd %f31, 232(%r1)
|
||||
|
||||
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
|
||||
# store RSP (pointing to context-data) in R7/R6
|
||||
# restore RSP (pointing to context-data) from R4/R3
|
||||
#ifdef __linux__
|
||||
mr %r7, %r1
|
||||
mr %r1, %r4
|
||||
lwz %r3, 4(%r1) # hidden pointer
|
||||
#else
|
||||
mr %r6, %r1
|
||||
mr %r1, %r3
|
||||
#endif
|
||||
|
||||
# restore CR
|
||||
lwz %r0, 232(%r1)
|
||||
mtcr %r0
|
||||
# restore LR
|
||||
lwz %r0, 236(%r1)
|
||||
lfd %f0, 8(%r1) # FPSCR
|
||||
lwz %r0, 16(%r1) # PC
|
||||
lwz %r8, 20(%r1) # CR
|
||||
|
||||
mtfsf 0xff, %f0 # restore FPSCR
|
||||
mtctr %r0 # load CTR with PC
|
||||
mtcr %r8 # restore CR
|
||||
|
||||
# restore R14 to R31
|
||||
lwz %r14, 24(%r1)
|
||||
lwz %r15, 28(%r1)
|
||||
lwz %r16, 32(%r1)
|
||||
lwz %r17, 36(%r1)
|
||||
lwz %r18, 40(%r1)
|
||||
lwz %r19, 44(%r1)
|
||||
lwz %r20, 48(%r1)
|
||||
lwz %r21, 52(%r1)
|
||||
lwz %r22, 56(%r1)
|
||||
lwz %r23, 60(%r1)
|
||||
lwz %r24, 64(%r1)
|
||||
lwz %r25, 68(%r1)
|
||||
lwz %r26, 72(%r1)
|
||||
lwz %r27, 76(%r1)
|
||||
lwz %r28, 80(%r1)
|
||||
lwz %r29, 84(%r1)
|
||||
lwz %r30, 88(%r1)
|
||||
lwz %r31, 92(%r1)
|
||||
|
||||
# restore F14 to F31
|
||||
lfd %f14, 96(%r1)
|
||||
lfd %f15, 104(%r1)
|
||||
lfd %f16, 112(%r1)
|
||||
lfd %f17, 120(%r1)
|
||||
lfd %f18, 128(%r1)
|
||||
lfd %f19, 136(%r1)
|
||||
lfd %f20, 144(%r1)
|
||||
lfd %f21, 152(%r1)
|
||||
lfd %f22, 160(%r1)
|
||||
lfd %f23, 168(%r1)
|
||||
lfd %f24, 176(%r1)
|
||||
lfd %f25, 184(%r1)
|
||||
lfd %f26, 192(%r1)
|
||||
lfd %f27, 200(%r1)
|
||||
lfd %f28, 208(%r1)
|
||||
lfd %f29, 216(%r1)
|
||||
lfd %f30, 224(%r1)
|
||||
lfd %f31, 232(%r1)
|
||||
|
||||
# restore LR from caller's frame
|
||||
lwz %r0, 244(%r1)
|
||||
mtlr %r0
|
||||
# load PC
|
||||
lwz %r0, 240(%r1)
|
||||
# restore CTR
|
||||
mtctr %r0
|
||||
|
||||
# adjust stack
|
||||
addi %r1, %r1, 244
|
||||
addi %r1, %r1, 240
|
||||
|
||||
# return transfer_t
|
||||
stw %r6, 0(%r3)
|
||||
# return transfer_t
|
||||
#ifdef __linux__
|
||||
stw %r7, 0(%r3)
|
||||
stw %r5, 4(%r3)
|
||||
#else
|
||||
mr %r3, %r6
|
||||
# %r4, %r4
|
||||
#endif
|
||||
|
||||
# jump to context
|
||||
bctr
|
||||
|
||||
150
src/asm/jump_riscv64_sysv_elf_gas.S
Normal file
150
src/asm/jump_riscv64_sysv_elf_gas.S
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
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| *
|
||||
* ------------------------------------------------- *
|
||||
* | fs0 | fs1 | fs2 | fs3 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | fs4 | fs5 | fs6 | fs7 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| *
|
||||
* ------------------------------------------------- *
|
||||
* | fs8 | fs9 | fs10 | fs11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s0 | s1 | s2 | s3 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s4 | s5 | s6 | s7 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0xa0| 0xa4| 0xa8| 0xac| 0xb0| 0xb4| 0xb8| 0xbc| *
|
||||
* ------------------------------------------------- *
|
||||
* | s8 | s9 | s10 | s11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 48 | 49 | 50 | 51 | | | | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0xc0| 0xc4| 0xc8| 0xcc| | | | | *
|
||||
* ------------------------------------------------- *
|
||||
* | ra | pc | | | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.file "jump_riscv64_sysv_elf_gas.S"
|
||||
.text
|
||||
.align 1
|
||||
.global jump_fcontext
|
||||
.type jump_fcontext, %function
|
||||
jump_fcontext:
|
||||
# prepare stack for GP + FPU
|
||||
addi sp, sp, -0xd0
|
||||
|
||||
# save fs0 - fs11
|
||||
fsd fs0, 0x00(sp)
|
||||
fsd fs1, 0x08(sp)
|
||||
fsd fs2, 0x10(sp)
|
||||
fsd fs3, 0x18(sp)
|
||||
fsd fs4, 0x20(sp)
|
||||
fsd fs5, 0x28(sp)
|
||||
fsd fs6, 0x30(sp)
|
||||
fsd fs7, 0x38(sp)
|
||||
fsd fs8, 0x40(sp)
|
||||
fsd fs9, 0x48(sp)
|
||||
fsd fs10, 0x50(sp)
|
||||
fsd fs11, 0x58(sp)
|
||||
|
||||
# save s0-s11, ra
|
||||
sd s0, 0x60(sp)
|
||||
sd s1, 0x68(sp)
|
||||
sd s2, 0x70(sp)
|
||||
sd s3, 0x78(sp)
|
||||
sd s4, 0x80(sp)
|
||||
sd s5, 0x88(sp)
|
||||
sd s6, 0x90(sp)
|
||||
sd s7, 0x98(sp)
|
||||
sd s8, 0xa0(sp)
|
||||
sd s9, 0xa8(sp)
|
||||
sd s10, 0xb0(sp)
|
||||
sd s11, 0xb8(sp)
|
||||
sd ra, 0xc0(sp)
|
||||
|
||||
# save RA as PC
|
||||
sd ra, 0xc8(sp)
|
||||
|
||||
# store SP (pointing to context-data) in A2
|
||||
mv a2, sp
|
||||
|
||||
# restore SP (pointing to context-data) from A0
|
||||
mv sp, a0
|
||||
|
||||
# load fs0 - fs11
|
||||
fld fs0, 0x00(sp)
|
||||
fld fs1, 0x08(sp)
|
||||
fld fs2, 0x10(sp)
|
||||
fld fs3, 0x18(sp)
|
||||
fld fs4, 0x20(sp)
|
||||
fld fs5, 0x28(sp)
|
||||
fld fs6, 0x30(sp)
|
||||
fld fs7, 0x38(sp)
|
||||
fld fs8, 0x40(sp)
|
||||
fld fs9, 0x48(sp)
|
||||
fld fs10, 0x50(sp)
|
||||
fld fs11, 0x58(sp)
|
||||
|
||||
# load s0-s11,ra
|
||||
ld s0, 0x60(sp)
|
||||
ld s1, 0x68(sp)
|
||||
ld s2, 0x70(sp)
|
||||
ld s3, 0x78(sp)
|
||||
ld s4, 0x80(sp)
|
||||
ld s5, 0x88(sp)
|
||||
ld s6, 0x90(sp)
|
||||
ld s7, 0x98(sp)
|
||||
ld s8, 0xa0(sp)
|
||||
ld s9, 0xa8(sp)
|
||||
ld s10, 0xb0(sp)
|
||||
ld s11, 0xb8(sp)
|
||||
ld ra, 0xc0(sp)
|
||||
|
||||
# return transfer_t from jump
|
||||
# pass transfer_t as first arg in context function
|
||||
# a0 == FCTX, a1 == DATA
|
||||
mv a0, a2
|
||||
|
||||
# load pc
|
||||
ld a2, 0xc8(sp)
|
||||
|
||||
# restore stack from GP + FPU
|
||||
addi sp, sp, 0xd0
|
||||
|
||||
jr a2
|
||||
.size jump_fcontext,.-jump_fcontext
|
||||
# Mark that we don't need executable stack.
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
156
src/asm/jump_s390x_sysv_elf_gas.S
Normal file
156
src/asm/jump_s390x_sysv_elf_gas.S
Normal file
@@ -0,0 +1,156 @@
|
||||
/*******************************************************
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 8 | 16 | 24 | *
|
||||
* ------------------------------------------------- *
|
||||
* | t.fctx | t.data | r2 | r6 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 40 | 48 | 56 | *
|
||||
* ------------------------------------------------- *
|
||||
* | r7 | r8 | r9 | r10 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 72 | 80 | 88 | *
|
||||
* ------------------------------------------------- *
|
||||
* | r11 | r12 | r13 | r14 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 104 | 112 | 120 | *
|
||||
* ------------------------------------------------- *
|
||||
* | f8 | f9 | f10 | f11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 136 | 144 | 152 | *
|
||||
* ------------------------------------------------- *
|
||||
* | f12 | f13 | f14 | f15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 160 | 168 | 176 | | *
|
||||
* ------------------------------------------------- *
|
||||
* | fpc | pc | | | *
|
||||
* ------------------------------------------------- *
|
||||
*******************************************************/
|
||||
|
||||
.text
|
||||
.align 8
|
||||
.global jump_fcontext
|
||||
.type jump_fcontext, @function
|
||||
|
||||
#define ARG_OFFSET 0
|
||||
#define GR_OFFSET 16
|
||||
#define FP_OFFSET 96
|
||||
#define FPC_OFFSET 160
|
||||
#define PC_OFFSET 168
|
||||
#define CONTEXT_SIZE 176
|
||||
|
||||
#define REG_SAVE_AREA_SIZE 160
|
||||
|
||||
/*
|
||||
|
||||
typedef void* fcontext_t;
|
||||
|
||||
struct transfer_t {
|
||||
fcontext_t fctx;
|
||||
void * data;
|
||||
};
|
||||
|
||||
transfer_t jump_fcontext( fcontext_t const to,
|
||||
void * data);
|
||||
|
||||
Incoming args
|
||||
r2 - Hidden argument to the location where the return transfer_t needs to be returned
|
||||
r3 - Context we want to switch to
|
||||
r4 - Data pointer
|
||||
|
||||
*/
|
||||
|
||||
jump_fcontext:
|
||||
.machine "z10"
|
||||
/* Reserve stack space to store the current context. */
|
||||
aghi %r15,-CONTEXT_SIZE
|
||||
|
||||
/* Save the argument register holding the location of the return value. */
|
||||
stg %r2,GR_OFFSET(%r15)
|
||||
|
||||
/* Save the call-saved general purpose registers. */
|
||||
stmg %r6,%r14,GR_OFFSET+8(%r15)
|
||||
|
||||
/* Save call-saved floating point registers. */
|
||||
std %f8,FP_OFFSET(%r15)
|
||||
std %f9,FP_OFFSET+8(%r15)
|
||||
std %f10,FP_OFFSET+16(%r15)
|
||||
std %f11,FP_OFFSET+24(%r15)
|
||||
std %f12,FP_OFFSET+32(%r15)
|
||||
std %f13,FP_OFFSET+40(%r15)
|
||||
std %f14,FP_OFFSET+48(%r15)
|
||||
std %f15,FP_OFFSET+56(%r15)
|
||||
|
||||
/* Save the return address as current pc. */
|
||||
stg %r14,PC_OFFSET(%r15)
|
||||
|
||||
/* Save the floating point control register. */
|
||||
stfpc FPC_OFFSET(%r15)
|
||||
|
||||
/* Backup the stack pointer pointing to the old context-data into r1. */
|
||||
lgr %r1,%r15
|
||||
|
||||
/* Load the new context pointer as stack pointer. */
|
||||
lgr %r15,%r3
|
||||
|
||||
/* Restore the call-saved GPRs from the new context. */
|
||||
lmg %r6,%r14,GR_OFFSET+8(%r15)
|
||||
|
||||
/* Restore call-saved floating point registers. */
|
||||
ld %f8,FP_OFFSET(%r15)
|
||||
ld %f9,FP_OFFSET+8(%r15)
|
||||
ld %f10,FP_OFFSET+16(%r15)
|
||||
ld %f11,FP_OFFSET+24(%r15)
|
||||
ld %f12,FP_OFFSET+32(%r15)
|
||||
ld %f13,FP_OFFSET+40(%r15)
|
||||
ld %f14,FP_OFFSET+48(%r15)
|
||||
ld %f15,FP_OFFSET+56(%r15)
|
||||
|
||||
/* Load the floating point control register. */
|
||||
lfpc FPC_OFFSET(%r15)
|
||||
|
||||
/* Restore PC - the location where we will jump to at the end. */
|
||||
lg %r5,PC_OFFSET(%r15)
|
||||
|
||||
ltg %r2,GR_OFFSET(%r15)
|
||||
jnz use_return_slot
|
||||
|
||||
/* We restore a make_fcontext context. Use the function
|
||||
argument slot in the context we just saved and allocate the
|
||||
register save area for the target function. */
|
||||
la %r2,ARG_OFFSET(%r1)
|
||||
aghi %r15,-REG_SAVE_AREA_SIZE
|
||||
|
||||
use_return_slot:
|
||||
/* Save the two fields in transfer_t. When calling a
|
||||
make_fcontext function this becomes the function argument of
|
||||
the target function, otherwise it will be the return value of
|
||||
jump_fcontext. */
|
||||
stg %r1,0(%r2)
|
||||
stg %r4,8(%r2)
|
||||
|
||||
/* Free the restored context. */
|
||||
aghi %r15,CONTEXT_SIZE
|
||||
|
||||
/* Jump to the PC loaded from the new context. */
|
||||
br %r5
|
||||
|
||||
|
||||
.size jump_fcontext,.-jump_fcontext
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
209
src/asm/jump_x86_64_ms_pe_clang_gas.S
Normal file
209
src/asm/jump_x86_64_ms_pe_clang_gas.S
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
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_clang_gas.S"
|
||||
.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\""
|
||||
@@ -67,10 +67,20 @@ jump_fcontext:
|
||||
leaq 0x40(%rsp), %rsp /* prepare stack */
|
||||
|
||||
/* return transfer_t from jump */
|
||||
#if !defined(_ILP32)
|
||||
/* RAX == fctx, RDX == data */
|
||||
movq %rsi, %rdx
|
||||
#else
|
||||
/* RAX == data:fctx */
|
||||
salq $32, %rsi
|
||||
orq %rsi, %rax
|
||||
#endif
|
||||
/* pass transfer_t as first arg in context function */
|
||||
#if !defined(_ILP32)
|
||||
/* RDI == fctx, RSI == data */
|
||||
#else
|
||||
/* RDI == data:fctx */
|
||||
#endif
|
||||
movq %rax, %rdi
|
||||
|
||||
/* indirect jump to context */
|
||||
|
||||
@@ -66,12 +66,7 @@ _make_fcontext:
|
||||
; 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
|
||||
adr x1, finish
|
||||
|
||||
; save address of finish as return-address for context-function
|
||||
; will be entered after context-function returns (LR register)
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
.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
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
#include "make_ppc32_sysv_macho_gas.S"
|
||||
#elif defined(__ppc64__)
|
||||
#include "make_ppc64_sysv_macho_gas.S"
|
||||
#elif defined(__arm__)
|
||||
#include "make_arm_aapcs_macho_gas.S"
|
||||
#elif defined(__arm64__)
|
||||
#include "make_arm64_aapcs_macho_gas.S"
|
||||
#else
|
||||
#error "No arch's"
|
||||
#endif
|
||||
|
||||
153
src/asm/make_i386_ms_pe_clang_gas.S
Normal file
153
src/asm/make_i386_ms_pe_clang_gas.S
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
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_clang_gas.S"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
|
||||
/* mark as using no unregistered SEH handlers */
|
||||
.globl @feat.00
|
||||
.def @feat.00; .scl 3; .type 0; .endef
|
||||
.set @feat.00, 1
|
||||
|
||||
.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\""
|
||||
@@ -26,6 +26,12 @@
|
||||
.file "make_i386_ms_pe_gas.asm"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
|
||||
/* mark as using no unregistered SEH handlers */
|
||||
.globl @feat.00
|
||||
.def @feat.00; .scl 3; .type 0; .endef
|
||||
.set @feat.00, 1
|
||||
|
||||
.globl _make_fcontext
|
||||
.def _make_fcontext; .scl 2; .type 32; .endef
|
||||
_make_fcontext:
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
.file "make_mips64_n64_elf_gas.S"
|
||||
.text
|
||||
.globl make_fcontext
|
||||
.align 2
|
||||
.align 3
|
||||
.type make_fcontext,@function
|
||||
.ent make_fcontext
|
||||
make_fcontext:
|
||||
|
||||
@@ -5,71 +5,48 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
/******************************************************
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* |bchai|hiddn| fpscr | PC | CR | R14 | R15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R16 | R17 | R18 | R19 | R20 | R21 | R22 | R23 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R24 | R25 | R26 | R27 | R28 | R29 | R30 | R31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F14 | F15 | F16 | F17 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F18 | F19 | F20 | F21 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F22 | F23 | F24 | F25 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 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| | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------|------------ *
|
||||
* | 224 | 228 | 232 | 236 | 240 | 244 | *
|
||||
* ------------------------|------------ *
|
||||
* | F30 | F31 |bchai| LR | *
|
||||
* ------------------------|------------ *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
@@ -86,58 +63,84 @@ make_fcontext:
|
||||
# shift address in R3 to lower 16 byte boundary
|
||||
clrrwi %r3, %r3, 4
|
||||
|
||||
# reserve space for context-data on context-stack
|
||||
# including 64 byte of linkage + parameter area (R1 % 16 == 0)
|
||||
subi %r3, %r3, 336
|
||||
# reserve space on context-stack, including 16 bytes of linkage
|
||||
# and parameter area + 240 bytes of context-data (R1 % 16 == 0)
|
||||
subi %r3, %r3, 16 + 240
|
||||
|
||||
# third arg of make_fcontext() == address of context-function
|
||||
stw %r5, 240(%r3)
|
||||
#ifdef __linux__
|
||||
# save context-function as PC
|
||||
stw %r5, 16(%r3)
|
||||
#else
|
||||
# save context-function for trampoline
|
||||
stw %r5, 248(%r3)
|
||||
#endif
|
||||
|
||||
# set back-chain to zero
|
||||
li %r0, 0
|
||||
stw %r0, 244(%r3)
|
||||
stw %r0, 240(%r3)
|
||||
|
||||
mffs %f0 # load FPSCR
|
||||
stfd %f0, 144(%r3) # save FPSCR
|
||||
# copy FPSCR to new context
|
||||
mffs %f0
|
||||
stfd %f0, 8(%r3)
|
||||
|
||||
# compute address of returned transfer_t
|
||||
addi %r0, %r3, 252
|
||||
mr %r4, %r0
|
||||
stw %r4, 228(%r3)
|
||||
#ifdef __linux__
|
||||
# set hidden pointer for returning transfer_t
|
||||
la %r0, 248(%r3)
|
||||
stw %r0, 4(%r3)
|
||||
#endif
|
||||
|
||||
# load LR
|
||||
mflr %r0
|
||||
# jump to label 1
|
||||
# load address of label 1 into R4
|
||||
bl 1f
|
||||
1:
|
||||
# load LR into R4
|
||||
mflr %r4
|
||||
1: mflr %r4
|
||||
#ifndef __linux__
|
||||
# compute abs address of trampoline, use as PC
|
||||
addi %r7, %r4, trampoline - 1b
|
||||
stw %r7, 16(%r3)
|
||||
#endif
|
||||
# compute abs address of label finish
|
||||
addi %r4, %r4, finish - 1b
|
||||
# restore LR
|
||||
mtlr %r0
|
||||
# save address of finish as return-address for context-function
|
||||
# will be entered after context-function returns
|
||||
stw %r4, 236(%r3)
|
||||
stw %r4, 244(%r3)
|
||||
|
||||
# restore return address from R6
|
||||
mtlr %r6
|
||||
|
||||
blr # return pointer to context-data
|
||||
|
||||
finish:
|
||||
# save return address into R0
|
||||
mflr %r0
|
||||
# save return address on stack, set up stack frame
|
||||
stw %r0, 4(%r1)
|
||||
# allocate stack space, R1 % 16 == 0
|
||||
stwu %r1, -16(%r1)
|
||||
#ifndef __linux__
|
||||
trampoline:
|
||||
# On systems other than Linux, jump_fcontext is returning the
|
||||
# transfer_t in R3:R4, but we need to pass transfer_t * R3 to
|
||||
# our context-function.
|
||||
lwz %r0, 8(%r1) # address of context-function
|
||||
mtctr %r0
|
||||
stw %r3, 8(%r1)
|
||||
stw %r4, 12(%r1)
|
||||
la %r3, 8(%r1) # address of transfer_t
|
||||
bctr
|
||||
#endif
|
||||
|
||||
# exit code is zero
|
||||
finish:
|
||||
# Use the secure PLT for _exit(0). If we use the insecure BSS PLT
|
||||
# here, then the linker may use the insecure BSS PLT even if the
|
||||
# C++ compiler wanted the secure PLT.
|
||||
|
||||
# set R30 for secure PLT, large model
|
||||
bl 2f
|
||||
2: mflr %r30
|
||||
addis %r30, %r30, .Ltoc - 2b@ha
|
||||
addi %r30, %r30, .Ltoc - 2b@l
|
||||
|
||||
# call _exit(0) with special addend 0x8000 for large model
|
||||
li %r3, 0
|
||||
# exit application
|
||||
bl _exit@plt
|
||||
bl _exit + 0x8000@plt
|
||||
.size make_fcontext, .-make_fcontext
|
||||
|
||||
/* Provide the GOT pointer for secure PLT, large model. */
|
||||
.section .got2,"aw"
|
||||
.Ltoc = . + 0x8000
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
|
||||
91
src/asm/make_riscv64_sysv_elf_gas.S
Normal file
91
src/asm/make_riscv64_sysv_elf_gas.S
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
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| *
|
||||
* ------------------------------------------------- *
|
||||
* | fs0 | fs1 | fs2 | fs3 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| *
|
||||
* ------------------------------------------------- *
|
||||
* | fs4 | fs5 | fs6 | fs7 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| *
|
||||
* ------------------------------------------------- *
|
||||
* | fs8 | fs9 | fs10 | fs11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s0 | s1 | s2 | s3 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| *
|
||||
* ------------------------------------------------- *
|
||||
* | s4 | s5 | s6 | s7 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0xa0| 0xa4| 0xa8| 0xac| 0xb0| 0xb4| 0xb8| 0xbc| *
|
||||
* ------------------------------------------------- *
|
||||
* | s8 | s9 | s10 | s11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 48 | 49 | 50 | 51 | | | | | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0xc0| 0xc4| 0xc8| 0xcc| | | | | *
|
||||
* ------------------------------------------------- *
|
||||
* | ra | pc | | | *
|
||||
* ------------------------------------------------- *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
.file "make_riscv64_sysv_elf_gas.S"
|
||||
.text
|
||||
.align 1
|
||||
.global make_fcontext
|
||||
.type make_fcontext, %function
|
||||
make_fcontext:
|
||||
# shift address in a0 (allocated stack) to lower 16 byte boundary
|
||||
andi a0, a0, ~0xF
|
||||
|
||||
# reserve space for context-data on context-stack
|
||||
addi a0, a0, -0xd0
|
||||
|
||||
# third arg of make_fcontext() == address of context-function
|
||||
# store address as a PC to jump in
|
||||
sd a2, 0xc8(a0)
|
||||
|
||||
# save address of finish as return-address for context-function
|
||||
# will be entered after context-function returns (RA register)
|
||||
lla a4, finish
|
||||
sd a4, 0xc0(a0)
|
||||
|
||||
ret // return pointer to context-data (a0)
|
||||
|
||||
finish:
|
||||
# exit code is zero
|
||||
li a0, 0
|
||||
# exit application
|
||||
tail _exit@plt
|
||||
|
||||
.size make_fcontext,.-make_fcontext
|
||||
# Mark that we don't need executable stack.
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
108
src/asm/make_s390x_sysv_elf_gas.S
Normal file
108
src/asm/make_s390x_sysv_elf_gas.S
Normal file
@@ -0,0 +1,108 @@
|
||||
/*******************************************************
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 8 | 16 | 24 | *
|
||||
* ------------------------------------------------- *
|
||||
* | t.fctx | t.data | r2 | r6 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 40 | 48 | 56 | *
|
||||
* ------------------------------------------------- *
|
||||
* | r7 | r8 | r9 | r10 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 72 | 80 | 88 | *
|
||||
* ------------------------------------------------- *
|
||||
* | r11 | r12 | r13 | r14 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 104 | 112 | 120 | *
|
||||
* ------------------------------------------------- *
|
||||
* | f8 | f9 | f10 | f11 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 128 | 136 | 144 | 152 | *
|
||||
* ------------------------------------------------- *
|
||||
* | f12 | f13 | f14 | f15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 160 | 168 | 176 | | *
|
||||
* ------------------------------------------------- *
|
||||
* | fpc | pc | | | *
|
||||
* ------------------------------------------------- *
|
||||
*******************************************************/
|
||||
|
||||
.text
|
||||
.align 8
|
||||
.global make_fcontext
|
||||
.type make_fcontext, @function
|
||||
|
||||
#define ARG_OFFSET 0
|
||||
#define GR_OFFSET 16
|
||||
#define R14_OFFSET 88
|
||||
#define FP_OFFSET 96
|
||||
#define FPC_OFFSET 160
|
||||
#define PC_OFFSET 168
|
||||
#define CONTEXT_SIZE 176
|
||||
|
||||
/*
|
||||
|
||||
fcontext_t make_fcontext( void * sp, std::size_t size, void (* fn)( transfer_t) );
|
||||
|
||||
Create and return a context below SP to call FN.
|
||||
|
||||
Incoming args
|
||||
r2 - The stack location where to create the context
|
||||
r3 - The size of the context
|
||||
r4 - The address of the context function
|
||||
|
||||
*/
|
||||
|
||||
make_fcontext:
|
||||
.machine "z10"
|
||||
/* Align the stack to an 8 byte boundary. */
|
||||
nill %r2,0xfff0
|
||||
|
||||
/* Allocate stack space for the context. */
|
||||
aghi %r2,-CONTEXT_SIZE
|
||||
|
||||
/* Set the r2 save slot to zero. This indicates jump_fcontext
|
||||
that this is a special context. */
|
||||
mvghi GR_OFFSET(%r2),0
|
||||
|
||||
/* Save the floating point control register. */
|
||||
stfpc FPC_OFFSET(%r2)
|
||||
|
||||
/* Store the address of the target function as new pc. */
|
||||
stg %r4,PC_OFFSET(%r2)
|
||||
|
||||
/* Store a pointer to the finish routine as r14. If a function
|
||||
called via context routines just returns that value will be
|
||||
loaded and used as return address. Hence the program will
|
||||
just exit. */
|
||||
larl %r1,finish
|
||||
stg %r1,R14_OFFSET(%r2)
|
||||
|
||||
/* Return as usual with the new context returned in r2. */
|
||||
br %r14
|
||||
|
||||
finish:
|
||||
/* In finish tasks, you load the exit code and exit the
|
||||
make_fcontext This is called when the context-function is
|
||||
entirely executed. */
|
||||
lghi %r2,0
|
||||
brasl %r14,_exit@PLT
|
||||
|
||||
.size make_fcontext,.-make_fcontext
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
174
src/asm/make_x86_64_ms_pe_clang_gas.S
Normal file
174
src/asm/make_x86_64_ms_pe_clang_gas.S
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
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 "make_x86_64_ms_pe_clang_gas.S"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
.globl make_fcontext
|
||||
.def make_fcontext; .scl 2; .type 32; .endef
|
||||
.seh_proc make_fcontext
|
||||
make_fcontext:
|
||||
.seh_endprologue
|
||||
|
||||
/* first arg of make_fcontext() == top of context-stack */
|
||||
movq %rcx, %rax
|
||||
|
||||
/* shift address in RAX to lower 16 byte boundary */
|
||||
/* == pointer to fcontext_t and address of context stack */
|
||||
andq $-16, %rax
|
||||
|
||||
/* reserve space for context-data on context-stack */
|
||||
/* on context-function entry: (RSP -0x8) % 16 == 0 */
|
||||
leaq -0x150(%rax), %rax
|
||||
|
||||
/* third arg of make_fcontext() == address of context-function */
|
||||
movq %r8, 0x100(%rax)
|
||||
|
||||
/* first arg of make_fcontext() == top of context-stack */
|
||||
/* save top address of context stack as 'base' */
|
||||
movq %rcx, 0xc8(%rax)
|
||||
/* second arg of make_fcontext() == size of context-stack */
|
||||
/* negate stack size for LEA instruction (== substraction) */
|
||||
negq %rdx
|
||||
/* compute bottom address of context stack (limit) */
|
||||
leaq (%rcx,%rdx), %rcx
|
||||
/* save bottom address of context stack as 'limit' */
|
||||
movq %rcx, 0xc0(%rax)
|
||||
/* save address of context stack limit as 'dealloction stack' */
|
||||
movq %rcx, 0xb8(%rax)
|
||||
/* set fiber-storage to zero */
|
||||
xorq %rcx, %rcx
|
||||
movq %rcx, 0xb0(%rax)
|
||||
|
||||
/* save MMX control- and status-word */
|
||||
stmxcsr 0xa0(%rax)
|
||||
/* save x87 control-word */
|
||||
fnstcw 0xa4(%rax)
|
||||
|
||||
/* compute address of transport_t */
|
||||
leaq 0x140(%rax), %rcx
|
||||
/* store address of transport_t in hidden field */
|
||||
movq %rcx, 0x110(%rax)
|
||||
|
||||
/* compute abs address of label trampoline */
|
||||
leaq trampoline(%rip), %rcx
|
||||
/* save address of finish as return-address for context-function */
|
||||
/* will be entered after jump_fcontext() first time */
|
||||
movq %rcx, 0x118(%rax)
|
||||
|
||||
/* compute abs address of label finish */
|
||||
leaq finish(%rip), %rcx
|
||||
/* save address of finish as return-address for context-function */
|
||||
/* will be entered after context-function returns */
|
||||
movq %rcx, 0x108(%rax)
|
||||
|
||||
ret /* return pointer to context-data */
|
||||
|
||||
trampoline:
|
||||
/* store return address on stack */
|
||||
/* fix stack alignment */
|
||||
pushq %rbp
|
||||
/* jump to context-function */
|
||||
jmp *%rbx
|
||||
|
||||
finish:
|
||||
/* 32byte shadow-space for _exit() */
|
||||
andq $-32, %rsp
|
||||
/* 32byte shadow-space for _exit() are */
|
||||
/* already reserved by make_fcontext() */
|
||||
/* exit code is zero */
|
||||
xorq %rcx, %rcx
|
||||
/* exit application */
|
||||
call _exit
|
||||
hlt
|
||||
.seh_endproc
|
||||
|
||||
.def _exit; .scl 2; .type 32; .endef /* standard C library function */
|
||||
|
||||
.section .drectve
|
||||
.ascii " -export:\"make_fcontext\""
|
||||
@@ -43,6 +43,7 @@
|
||||
.globl ontop_fcontext
|
||||
.align 2
|
||||
.type ontop_fcontext,%function
|
||||
.syntax unified
|
||||
ontop_fcontext:
|
||||
@ save LR as PC
|
||||
push {lr}
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
#include "ontop_ppc32_sysv_macho_gas.S"
|
||||
#elif defined(__ppc64__)
|
||||
#include "ontop_ppc64_sysv_macho_gas.S"
|
||||
#elif defined(__arm__)
|
||||
#include "ontop_arm_aapcs_macho_gas.S"
|
||||
#elif defined(__arm64__)
|
||||
#include "ontop_arm64_aapcs_macho_gas.S"
|
||||
#else
|
||||
#error "No arch's"
|
||||
#endif
|
||||
|
||||
131
src/asm/ontop_i386_ms_pe_clang_gas.S
Normal file
131
src/asm/ontop_i386_ms_pe_clang_gas.S
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
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 "ontop_i386_ms_pe_clang_gas.S"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
|
||||
/* mark as using no unregistered SEH handlers */
|
||||
.globl @feat.00
|
||||
.def @feat.00; .scl 3; .type 0; .endef
|
||||
.set @feat.00, 1
|
||||
|
||||
.globl _ontop_fcontext
|
||||
.def _ontop_fcontext; .scl 2; .type 32; .endef
|
||||
_ontop_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 ECX */
|
||||
movl %esp, %ecx
|
||||
|
||||
/* first arg of ontop_fcontext() == fcontext to jump to */
|
||||
movl 0x30(%esp), %eax
|
||||
|
||||
/* pass parent fcontext_t */
|
||||
movl %ecx, 0x30(%eax)
|
||||
|
||||
/* second arg of ontop_fcontext() == data to be transferred */
|
||||
movl 0x34(%esp), %ecx
|
||||
|
||||
/* pass data */
|
||||
movl %ecx, 0x34(%eax)
|
||||
|
||||
/* third arg of ontop_fcontext() == ontop-function */
|
||||
movl 0x38(%esp), %ecx
|
||||
|
||||
/* restore ESP (pointing to context-data) from EDX */
|
||||
movl %eax, %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), %eax
|
||||
movl %eax, 0x10(%edx)
|
||||
/* restore current deallocation stack */
|
||||
movl 0xc(%esp), %eax
|
||||
movl %eax, 0xe0c(%edx)
|
||||
/* restore current stack limit */
|
||||
movl 0x10(%esp), %eax
|
||||
movl %eax, 0x08(%edx)
|
||||
/* restore current stack base */
|
||||
movl 0x14(%esp), %eax
|
||||
movl %eax, 0x04(%edx)
|
||||
/* restore current SEH exception list */
|
||||
movl 0x18(%esp), %eax
|
||||
movl %eax, (%edx)
|
||||
|
||||
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 0x2c(%esp), %esp
|
||||
|
||||
/* keep return-address on stack */
|
||||
|
||||
/* jump to context */
|
||||
jmp *%ecx
|
||||
|
||||
.section .drectve
|
||||
.ascii " -export:\"_ontop_fcontext\""
|
||||
@@ -26,6 +26,12 @@
|
||||
.file "ontop_i386_ms_pe_gas.asm"
|
||||
.text
|
||||
.p2align 4,,15
|
||||
|
||||
/* mark as using no unregistered SEH handlers */
|
||||
.globl @feat.00
|
||||
.def @feat.00; .scl 3; .type 0; .endef
|
||||
.set @feat.00, 1
|
||||
|
||||
.globl _ontop_fcontext
|
||||
.def _ontop_fcontext; .scl 2; .type 32; .endef
|
||||
_ontop_fcontext:
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
.file "ontop_mips64_n64_elf_gas.S"
|
||||
.text
|
||||
.globl ontop_fcontext
|
||||
.align 2
|
||||
.align 3
|
||||
.type ontop_fcontext,@function
|
||||
.ent ontop_fcontext
|
||||
ontop_fcontext:
|
||||
@@ -67,7 +67,7 @@ ontop_fcontext:
|
||||
sd $ra, 144($sp) # save RA
|
||||
sd $ra, 152($sp) # save RA as PC
|
||||
|
||||
|
||||
#if defined(__mips_hard_float)
|
||||
s.d $f24, 0($sp) # save F24
|
||||
s.d $f25, 8($sp) # save F25
|
||||
s.d $f26, 16($sp) # save F26
|
||||
@@ -76,6 +76,7 @@ ontop_fcontext:
|
||||
s.d $f29, 40($sp) # save F29
|
||||
s.d $f30, 48($sp) # save F30
|
||||
s.d $f31, 56($sp) # save F31
|
||||
#endif
|
||||
|
||||
# store SP (pointing to context-data) in t0
|
||||
move $t0, $sp
|
||||
@@ -83,6 +84,7 @@ ontop_fcontext:
|
||||
# restore SP (pointing to context-data) from a0
|
||||
move $sp, $a0
|
||||
|
||||
#if defined(__mips_hard_float)
|
||||
l.d $f24, 0($sp) # restore F24
|
||||
l.d $f25, 8($sp) # restore F25
|
||||
l.d $f26, 16($sp) # restore F26
|
||||
@@ -91,6 +93,7 @@ ontop_fcontext:
|
||||
l.d $f29, 40($sp) # restore F29
|
||||
l.d $f30, 48($sp) # restore F30
|
||||
l.d $f31, 56($sp) # restore F31
|
||||
#endif
|
||||
|
||||
ld $s0, 64($sp) # restore S0
|
||||
ld $s1, 72($sp) # restore S1
|
||||
|
||||
@@ -5,71 +5,48 @@
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
/******************************************************
|
||||
/*******************************************************
|
||||
* *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | *
|
||||
* ------------------------------------------------- *
|
||||
* |bchai|hiddn| fpscr | PC | CR | R14 | R15 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R16 | R17 | R18 | R19 | R20 | R21 | R22 | R23 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* ------------------------------------------------- *
|
||||
* | R24 | R25 | R26 | R27 | R28 | R29 | R30 | R31 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F14 | F15 | F16 | F17 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | *
|
||||
* | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F18 | F19 | F20 | F21 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | *
|
||||
* | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | *
|
||||
* ------------------------------------------------- *
|
||||
* | F22 | F23 | F24 | F25 | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------------------------------- *
|
||||
* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | *
|
||||
* | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | *
|
||||
* ------------------------------------------------- *
|
||||
* | 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| | *
|
||||
* ------------------------------------------------- *
|
||||
* ------------------------|------------ *
|
||||
* | 224 | 228 | 232 | 236 | 240 | 244 | *
|
||||
* ------------------------|------------ *
|
||||
* | F30 | F31 |bchai| LR | *
|
||||
* ------------------------|------------ *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
@@ -79,128 +56,137 @@
|
||||
.align 2
|
||||
.type ontop_fcontext,@function
|
||||
ontop_fcontext:
|
||||
# reserve space on stack
|
||||
subi %r1, %r1, 244
|
||||
# Linux: ontop_fcontext( hidden transfer_t * R3, R4, R5, R6)
|
||||
# Other: transfer_t R3:R4 = jump_fcontext( R3, R4, R5)
|
||||
|
||||
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
|
||||
mflr %r0 # return address from LR
|
||||
mffs %f0 # FPSCR
|
||||
mfcr %r8 # condition register
|
||||
|
||||
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
|
||||
stwu %r1, -240(%r1) # allocate stack space, R1 % 16 == 0
|
||||
stw %r0, 244(%r1) # save LR in caller's frame
|
||||
|
||||
# save CR
|
||||
mfcr %r0
|
||||
stw %r0, 232(%r1)
|
||||
# save LR
|
||||
mflr %r0
|
||||
stw %r0, 236(%r1)
|
||||
# save LR as PC
|
||||
stw %r0, 240(%r1)
|
||||
#ifdef __linux__
|
||||
stw %r3, 4(%r1) # hidden pointer
|
||||
#endif
|
||||
|
||||
# store RSP (pointing to context-data) in R7
|
||||
mr %r7, %r1
|
||||
stfd %f0, 8(%r1) # FPSCR
|
||||
stw %r0, 16(%r1) # LR as PC
|
||||
stw %r8, 20(%r1) # CR
|
||||
|
||||
# restore RSP (pointing to context-data) from R4
|
||||
mr %r1, %r4
|
||||
# Save registers R14 to R31.
|
||||
# Don't change R2, the thread-local storage pointer.
|
||||
# Don't change R13, the small data pointer.
|
||||
stw %r14, 24(%r1)
|
||||
stw %r15, 28(%r1)
|
||||
stw %r16, 32(%r1)
|
||||
stw %r17, 36(%r1)
|
||||
stw %r18, 40(%r1)
|
||||
stw %r19, 44(%r1)
|
||||
stw %r20, 48(%r1)
|
||||
stw %r21, 52(%r1)
|
||||
stw %r22, 56(%r1)
|
||||
stw %r23, 60(%r1)
|
||||
stw %r24, 64(%r1)
|
||||
stw %r25, 68(%r1)
|
||||
stw %r26, 72(%r1)
|
||||
stw %r27, 76(%r1)
|
||||
stw %r28, 80(%r1)
|
||||
stw %r29, 84(%r1)
|
||||
stw %r30, 88(%r1)
|
||||
stw %r31, 92(%r1)
|
||||
|
||||
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
|
||||
# Save registers F14 to F31 in slots with 8-byte alignment.
|
||||
# 4-byte alignment may stall the pipeline of some processors.
|
||||
# Less than 4 may cause alignment traps.
|
||||
stfd %f14, 96(%r1)
|
||||
stfd %f15, 104(%r1)
|
||||
stfd %f16, 112(%r1)
|
||||
stfd %f17, 120(%r1)
|
||||
stfd %f18, 128(%r1)
|
||||
stfd %f19, 136(%r1)
|
||||
stfd %f20, 144(%r1)
|
||||
stfd %f21, 152(%r1)
|
||||
stfd %f22, 160(%r1)
|
||||
stfd %f23, 168(%r1)
|
||||
stfd %f24, 176(%r1)
|
||||
stfd %f25, 184(%r1)
|
||||
stfd %f26, 192(%r1)
|
||||
stfd %f27, 200(%r1)
|
||||
stfd %f28, 208(%r1)
|
||||
stfd %f29, 216(%r1)
|
||||
stfd %f30, 224(%r1)
|
||||
stfd %f31, 232(%r1)
|
||||
|
||||
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 %r4, 228(%r1) # restore hidden
|
||||
# store RSP (pointing to context-data) in R7/R6
|
||||
# restore RSP (pointing to context-data) from R4/R3
|
||||
#ifdef __linux__
|
||||
mr %r7, %r1
|
||||
mr %r1, %r4
|
||||
lwz %r3, 4(%r1) # hidden pointer
|
||||
#else
|
||||
mr %r6, %r1
|
||||
mr %r1, %r3
|
||||
#endif
|
||||
|
||||
# restore CR
|
||||
lwz %r0, 232(%r1)
|
||||
mtcr %r0
|
||||
# restore LR
|
||||
lwz %r0, 236(%r1)
|
||||
# ignore PC at 16(%r1)
|
||||
lfd %f0, 8(%r1) # FPSCR
|
||||
lwz %r8, 20(%r1) # CR
|
||||
|
||||
mtfsf 0xff, %f0 # restore FPSCR
|
||||
mtcr %r8 # restore CR
|
||||
|
||||
# restore R14 to R31
|
||||
lwz %r14, 24(%r1)
|
||||
lwz %r15, 28(%r1)
|
||||
lwz %r16, 32(%r1)
|
||||
lwz %r17, 36(%r1)
|
||||
lwz %r18, 40(%r1)
|
||||
lwz %r19, 44(%r1)
|
||||
lwz %r20, 48(%r1)
|
||||
lwz %r21, 52(%r1)
|
||||
lwz %r22, 56(%r1)
|
||||
lwz %r23, 60(%r1)
|
||||
lwz %r24, 64(%r1)
|
||||
lwz %r25, 68(%r1)
|
||||
lwz %r26, 72(%r1)
|
||||
lwz %r27, 76(%r1)
|
||||
lwz %r28, 80(%r1)
|
||||
lwz %r29, 84(%r1)
|
||||
lwz %r30, 88(%r1)
|
||||
lwz %r31, 92(%r1)
|
||||
|
||||
# restore F14 to F31
|
||||
lfd %f14, 96(%r1)
|
||||
lfd %f15, 104(%r1)
|
||||
lfd %f16, 112(%r1)
|
||||
lfd %f17, 120(%r1)
|
||||
lfd %f18, 128(%r1)
|
||||
lfd %f19, 136(%r1)
|
||||
lfd %f20, 144(%r1)
|
||||
lfd %f21, 152(%r1)
|
||||
lfd %f22, 160(%r1)
|
||||
lfd %f23, 168(%r1)
|
||||
lfd %f24, 176(%r1)
|
||||
lfd %f25, 184(%r1)
|
||||
lfd %f26, 192(%r1)
|
||||
lfd %f27, 200(%r1)
|
||||
lfd %f28, 208(%r1)
|
||||
lfd %f29, 216(%r1)
|
||||
lfd %f30, 224(%r1)
|
||||
lfd %f31, 232(%r1)
|
||||
|
||||
# restore LR from caller's frame
|
||||
lwz %r0, 244(%r1)
|
||||
mtlr %r0
|
||||
# ignore PC
|
||||
|
||||
# adjust stack
|
||||
addi %r1, %r1, 244
|
||||
addi %r1, %r1, 240
|
||||
|
||||
# return transfer_t
|
||||
stw %r7, 0(%r4)
|
||||
stw %r5, 4(%r4)
|
||||
|
||||
# restore CTR
|
||||
mtctr %r6
|
||||
|
||||
# jump to ontop-function
|
||||
bctr
|
||||
# see tail_ppc32_sysv_elf_gas.cpp
|
||||
# Linux: fcontext_ontop_tail( hidden transfer_t * R3, R4, R5, R6, R7)
|
||||
# Other: transfer_t R3:R4 = fcontext_ontop_tail( R3, R4, R5, R6)
|
||||
b ontop_fcontext_tail
|
||||
.size ontop_fcontext, .-ontop_fcontext
|
||||
|
||||
/* Mark that we don't need executable stack. */
|
||||
|
||||
@@ -174,6 +174,9 @@ ontop_fcontext:
|
||||
# restore CTR
|
||||
mtctr %r5
|
||||
|
||||
# store cb entrypoint in %r12, used for TOC calculation
|
||||
mr %r12, %r5
|
||||
|
||||
# copy transfer_t into ontop_fn arg registers
|
||||
mr %r3, %r7
|
||||
# arg pointer already in %r4
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user