From 1253f0c833bd06799528d8282d19fd0513452366 Mon Sep 17 00:00:00 2001 From: uael Date: Thu, 19 Jul 2018 16:06:12 +0200 Subject: [PATCH 1/6] #5 - CMake build system initial implementation Moved includes, sources, bench and tests to separate directories Disabled tutorial 4 & 5 abort until i find a workaround to handle 'must fail test' Added a makefile to wrap the CMake build --- .gitattributes | 6 + .gitignore | 5 + .travis.yml | 168 +++++++++----- CMakeLists.txt | 141 ++++++++++++ Makefile | 114 ++++++++++ bench/CMakeLists.txt | 10 + test_aco_benchmark.c => bench/benchmark.c | 0 cmake/Config.cmake.in | 3 + aco.h => include/aco.h | 0 .../aco_assert_override.h | 0 make.sh | 195 ---------------- aco.c => src/aco.c | 0 acosw.S => src/acosw.S | 0 test.sh | 167 -------------- test/CMakeLists.txt | 36 +++ test_aco_synopsis.c => test/synopsis.c | 0 test/tutorial_0.c | 110 +++++++++ test/tutorial_1.c | 106 +++++++++ test/tutorial_2.c | 162 ++++++++++++++ test/tutorial_3.c | 208 ++++++++++++++++++ test/tutorial_4.c | 117 ++++++++++ test/tutorial_5.c | 125 +++++++++++ test_aco_tutorial_6.c => test/tutorial_6.c | 0 23 files changed, 1257 insertions(+), 416 deletions(-) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 Makefile create mode 100644 bench/CMakeLists.txt rename test_aco_benchmark.c => bench/benchmark.c (100%) create mode 100644 cmake/Config.cmake.in rename aco.h => include/aco.h (100%) rename aco_assert_override.h => include/aco_assert_override.h (100%) delete mode 100644 make.sh rename aco.c => src/aco.c (100%) rename acosw.S => src/acosw.S (100%) delete mode 100644 test.sh create mode 100644 test/CMakeLists.txt rename test_aco_synopsis.c => test/synopsis.c (100%) create mode 100644 test/tutorial_0.c create mode 100644 test/tutorial_1.c create mode 100644 test/tutorial_2.c create mode 100644 test/tutorial_3.c create mode 100644 test/tutorial_4.c create mode 100644 test/tutorial_5.c rename test_aco_tutorial_6.c => test/tutorial_6.c (100%) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b27a87e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +*.h linguist-language=C +*.c linguist-language=C +/test export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.travis.yml export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40bf61e --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +### CMake +cmake-build-*/ + +### Makefile +build/ diff --git a/.travis.yml b/.travis.yml index 6888fda..cd10349 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,61 +1,121 @@ +sudo: false +language: c dist: trusty -sudo: required notifications: email: - - 00hnes@gmail.com - -language: c - -compiler: - - gcc - - clang + - 00hnes@gmail.com install: - - sudo apt-get install -qq -y libreadline-dev libncurses5-dev libpcre3-dev libssl-dev perl make build-essential valgrind gcc-multilib g++-multilib libc6-dbg libc6-dbg:i386 - - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - - sudo apt-get update - - sudo apt-key update - + - mkdir -p build/m32 && cd build/m32 + - cmake -DACO_M32=ON ../.. + - cmake --build . + - cd ../.. + - mkdir -p build/fpenv && cd build/fpenv + - cmake -DACO_SHARE_FPENV=ON ../.. + - cmake --build . + - cd ../.. + - mkdir -p build/m32-fpenv && cd build/m32-fpenv + - cmake -DACO_M32=ON -DACO_SHARE_FPENV=ON ../.. + - cmake --build . + - cd ../.. + script: - - echo $TRAVIS_EVENT_TYPE - - ulimit -c unlimited - - cat /proc/cpuinfo && free -m && uname -a - - cc --version - - gcc --version - - echo $CC - - ls /usr/include - - ls /usr/include/valgrind - - date - - mkdir output - - bash make.sh - - ls output - - ls output | wc -l - - cd output - - bash ../test.sh - - cd .. - - rm -fr output - - mkdir output - - bash make.sh -o no-m32 - - ls output - - ls output | wc -l - - cd output - - bash ../test.sh - - cd .. - - rm -fr output - - mkdir output - - bash make.sh -o no-valgrind - - ls output - - ls output | wc -l - - cd output - - bash ../test.sh - - cd .. - - rm -fr output - - mkdir output - - bash make.sh -o no-valgrind -o no-m32 - - ls output - - ls output | wc -l - - cd output - - bash ../test.sh - - cd .. - - rm -fr output + - cmake --build build/m32 --target check + - cmake --build build/fpenv --target check + - cmake --build build/m32-fpenv --target check + +matrix: + include: + # default + - os: linux + - os: osx + + osx + - os: osx + osx_image: xcode7.3 + compiler: clang + - os: osx + osx_image: xcode8.3 + compiler: clang + + # gcc + - os: linux + compiler: gcc-4.9 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - os: linux + compiler: gcc-5 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-5 + - os: linux + compiler: gcc-6 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-6 + - os: linux + compiler: gcc-7 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-7 + + # clang + - os: linux + compiler: clang-3.5 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.5 + packages: + - clang-3.5 + - os: linux + compiler: clang-3.6 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.6 + packages: + - clang-3.6 + - os: linux + compiler: clang-3.8 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.8 + packages: + - clang-3.8 + - os: linux + compiler: clang-3.9 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.9 + packages: + - clang-3.9 + - os: linux + compiler: clang-4.0 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-4.0 + packages: + - clang-4.0 \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b46e67e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,141 @@ +# Copyright 2018 Sen Han 00hnes@gmail.com +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +project(libaco VERSION 1.2.2 LANGUAGES C ASM) + +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake) + +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +## +# Options +## +option(ACO_CHECK "Enable libaco testing" ON) +option(ACO_BENCH "Enable libaco testing" ON) +option(ACO_SHARE_FPENV "Enable share FPU MXCSR env" OFF) +option(ACO_VALGRIND "Enable the use of valgrind" OFF) +option(ACO_M32 "Enable m32 compilation" OFF) +option(ACO_ASAN "Enable address sanitizer" OFF) +option(ACO_COVERAGE "Enable code coverage" OFF) + +## +# Project directories definition +## +set(__INC_DIR ${CMAKE_CURRENT_LIST_DIR}/include) +set(__SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/src) +set(__TEST_DIR ${CMAKE_CURRENT_LIST_DIR}/test) +set(__BENCH_DIR ${CMAKE_CURRENT_LIST_DIR}/bench) +set(__INC_INSDIR ${CMAKE_INSTALL_INCLUDEDIR}) +set(__LIB_INSDIR ${CMAKE_INSTALL_LIBDIR}) +set(__CONF_INSDIR ${__LIB_INSDIR}/cmake/${PROJECT_NAME}) + +## +# Target +## +set(__TARGET_NAME aco) +set(__TARGET lib${__TARGET_NAME}) + +file(GLOB_RECURSE __HDRS ${__HDRS} ${__INC_DIR}/*.h) + +add_library(${__TARGET} ${__HDRS} + ${__SRC_DIR}/aco.c + ${__SRC_DIR}/acosw.S) +add_library(${PROJECT_NAME}::${__TARGET_NAME} ALIAS ${__TARGET}) +set_target_properties(${__TARGET} PROPERTIES + C_STANDARD 90 OUTPUT_NAME "${__TARGET_NAME}") + +target_include_directories(${__TARGET} + PRIVATE ${__SRC_DIR} + PUBLIC + $ + $ + $) + +install(FILES ${__HDRS} DESTINATION ${__INC_INSDIR}) + +function (aco_target_configure target) + if (MSVC) + target_compile_definitions(${target} PRIVATE _CRT_SECURE_NO_WARNINGS) + target_compile_options(${target} PRIVATE /Oy /W3) + else () + target_compile_definitions(${target} + PRIVATE + $<$:ACO_CONFIG_SHARE_FPU_MXCSR_ENV> + $<$:ACO_USE_VALGRIND>) + target_compile_options(${target} + PRIVATE + -Wall -Werror -Wextra + -fomit-frame-pointer + -Wno-missing-field-initializers + -Wno-type-limits #TODO: fix the code + $<$:-g3 -O0> + $<$:-m32> + $<$:--coverage> + $<$:-fsanitize=address>) + target_link_libraries(${target} + PRIVATE + ${ARGN} + $<$:-m32> + $<$:--coverage> + $<$:-fsanitize=address> + $<$:-fno-omit-frame-pointer>) + endif () +endfunction () + +aco_target_configure(${__TARGET}) + +## +# Testing +## +if (ACO_CHECK AND EXISTS ${__TEST_DIR}) + if (NOT TARGET check) + enable_testing() + add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --timeout 2) + endif () + add_subdirectory(${__TEST_DIR}) +endif () + +## +# Benchmarking +## +if (ACO_BENCH AND EXISTS ${__BENCH_DIR}) + add_subdirectory(${__BENCH_DIR}) +endif () + +## +# Installation +## +install(TARGETS ${__TARGET} EXPORT ${PROJECT_NAME}Targets + LIBRARY DESTINATION ${__LIB_INSDIR} + ARCHIVE DESTINATION ${__LIB_INSDIR}) +install(EXPORT ${PROJECT_NAME}Targets FILE ${PROJECT_NAME}Targets.cmake + NAMESPACE ${PROJECT_NAME}:: + DESTINATION ${__CONF_INSDIR}) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion) +configure_package_config_file( + ${CMAKE_CURRENT_LIST_DIR}/cmake/Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + INSTALL_DESTINATION ${__CONF_INSDIR}) +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION ${__CONF_INSDIR}) +export(EXPORT ${PROJECT_NAME}Targets + FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake + NAMESPACE ${PROJECT_NAME}::) +export(PACKAGE ${PROJECT_NAME}) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cab494c --- /dev/null +++ b/Makefile @@ -0,0 +1,114 @@ +# Copyright 2018 Sen Han 00hnes@gmail.com +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.SILENT: +.DEFAULT_GOAL := all +.PHONY: clean conf debug dev fclean install re reconf san + +BUILD_TYPE ?= Release +BUILD_DIR ?= build/$(BUILD_TYPE) +BUILD_PROJ_DIR = $(BUILD_DIR)/CMakeFiles + +CMAKE ?= cmake +CMAKE_FLAGS += -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) +CMAKE_G_FLAGS ?= -j8 + +ifeq (1,$(VERBOSE)) + CMAKE_FLAGS += -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON + CMAKE_G_FLAGS += VERBOSE=1 +endif + +ifeq (1,$(ACO_CHECK)) + CMAKE_FLAGS += -DACO_CHECK:BOOL=ON +else + ifeq (0,$(ACO_CHECK)) + CMAKE_FLAGS += -DACO_CHECK:BOOL=OFF + endif +endif + +ifeq (1,$(ACO_BENCH)) + CMAKE_FLAGS += -DACO_BENCH:BOOL=ON +else + ifeq (0,$(ACO_BENCH)) + CMAKE_FLAGS += -DACO_BENCH:BOOL=OFF + endif +endif + +ifeq (1,$(ACO_SHARE_FPENV)) + CMAKE_FLAGS += -DACO_SHARE_FPENV:BOOL=ON +else + ifeq (0,$(ACO_SHARE_FPENV)) + CMAKE_FLAGS += -DACO_SHARE_FPENV:BOOL=OFF + endif +endif + +ifeq (1,$(ACO_VALGRIND)) + CMAKE_FLAGS += -DACO_VALGRIND:BOOL=ON +else + ifeq (0,$(ACO_VALGRIND)) + CMAKE_FLAGS += -DACO_VALGRIND:BOOL=OFF + endif +endif + +ifeq (1,$(ACO_M32)) + CMAKE_FLAGS += -DACO_M32:BOOL=ON +else + ifeq (0,$(ACO_M32)) + CMAKE_FLAGS += -DACO_M32:BOOL=OFF + endif +endif + +ifeq (1,$(ACO_ASAN)) + CMAKE_FLAGS += -DACO_ASAN:BOOL=ON +else + ifeq (0,$(ACO_ASAN)) + CMAKE_FLAGS += -DACO_ASAN:BOOL=OFF + endif +endif + +ifeq (1,$(ACO_COVERAGE)) + CMAKE_FLAGS += -DACO_COVERAGE:BOOL=ON +else + ifeq (0,$(ACO_COVERAGE)) + CMAKE_FLAGS += -DACO_COVERAGE:BOOL=OFF + endif +endif + +$(BUILD_DIR) conf: + mkdir -p $(BUILD_DIR); cd $(BUILD_DIR) && $(CMAKE) $(CMAKE_FLAGS) $(CURDIR) + +reconf: mrproper conf + +debug dev: + $(MAKE) BUILD_TYPE=Debug + +san: + $(MAKE) BUILD_TYPE=San + +clean: + [ -d $(BUILD_PROJ_DIR) ] && find $(BUILD_PROJ_DIR) -name "*.o" -delete + +fclean: + [ -d $(BUILD_DIR) ] && find $(BUILD_DIR) -name "*.o" -delete + +mrproper: + $(RM) -rf $(BUILD_DIR) + +re: fclean all + +install: + $(CMAKE) --build $(BUILD_DIR) --target install + +%: $(BUILD_DIR) + $(CMAKE) --build $(BUILD_DIR) --target $@ -- $(CMAKE_G_FLAGS) diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt new file mode 100644 index 0000000..9d1959f --- /dev/null +++ b/bench/CMakeLists.txt @@ -0,0 +1,10 @@ +macro (aco_register_bench bench) + set(name ${bench}) + + add_executable(bench_${name} ${name}.c) + add_dependencies(bench_${name} libaco::aco) + + aco_target_configure(bench_${name} libaco::aco ${ARGN}) +endmacro () + +aco_register_bench(benchmark) diff --git a/test_aco_benchmark.c b/bench/benchmark.c similarity index 100% rename from test_aco_benchmark.c rename to bench/benchmark.c diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in new file mode 100644 index 0000000..e88cce2 --- /dev/null +++ b/cmake/Config.cmake.in @@ -0,0 +1,3 @@ +@PACKAGE_INIT@ + +include(${CMAKE_CURRENT_LIST_DIR}/libacoTargets.cmake) diff --git a/aco.h b/include/aco.h similarity index 100% rename from aco.h rename to include/aco.h diff --git a/aco_assert_override.h b/include/aco_assert_override.h similarity index 100% rename from aco_assert_override.h rename to include/aco_assert_override.h diff --git a/make.sh b/make.sh deleted file mode 100644 index d0ea8f0..0000000 --- a/make.sh +++ /dev/null @@ -1,195 +0,0 @@ -# Copyright 2018 Sen Han 00hnes@gmail.com -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http:#www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -OUTPUT_DIR="./output" -CFLAGS="-g -O2 -Wall -Werror" -EXTRA_CFLAGS="" -OUTPUT_SUFFIX="" -CC="cc" - -app_list=''' -test_aco_tutorial_0 -test_aco_tutorial_1 -test_aco_tutorial_2 -test_aco_tutorial_3 -lpthread -test_aco_tutorial_4 -test_aco_tutorial_5 -test_aco_tutorial_6 -test_aco_synopsis -test_aco_benchmark -''' - -gl_opt_no_m32="" -gl_opt_no_valgrind="" - -OUTPUT_DIR="$OUTPUT_DIR""//file" -OUTPUT_DIR=`dirname "$OUTPUT_DIR"` - -gl_trap_str="" - -function error(){ - echo "error: $*" > /proc/self/fd/2 -} - -function assert(){ - if [ "0" -ne "$?" ] - then - error "$0:""$*" - exit 1 - fi -} - -function tra(){ - gl_trap_str="$gl_trap_str""$1" - trap "$gl_trap_str exit 1;" INT - assert "$LINENO:trap failed:$gl_trap_str:$1" -} - -function untra(){ - trap - INT - assert "$LINENO:untrap failed:$gl_trap_str:$1" -} - -function build_f(){ - declare file - declare cflags - declare build_cmd - declare tmp_ret - declare skip_flag - echo "OUTPUT_DIR: $OUTPUT_DIR" - echo "CFLAGS: $CFLAGS" - echo "EXTRA_CFLAGS: $EXTRA_CFLAGS" - echo "OUTPUT_SUFFIX: $OUTPUT_SUFFIX" - echo "$app_list" | grep -Po '.+$' | while read read_in - do - file=`echo $read_in | grep -Po "^[^\s]+"` - cflags=`echo $read_in | sed -r 's/^\s*([^ ]+)(.*)$/\2/'` - if [ -z "$file" ] - then - continue - fi - #echo "<$file>:<$cflags>:$OUTPUT_DIR:$CFLAGS:$EXTRA_CFLAGS:$OUTPUT_SUFFIX" - build_cmd="$CC $CFLAGS $EXTRA_CFLAGS acosw.S aco.c $file.c $cflags -o $OUTPUT_DIR/$file$OUTPUT_SUFFIX" - skip_flag="" - if [ "$gl_opt_no_m32" ] - then - echo "$OUTPUT_SUFFIX" | grep -P "\bm32\b" &>/dev/null - tmp_ret=$? - if [ "$tmp_ret" -eq "0" ] - then - skip_flag="true" - elif [ "$tmp_ret" -eq "1" ] - then - : - else - error "grep failed: $tmp_ret" - exit $tmp_ret - fi - fi - if [ "$gl_opt_no_valgrind" ] - then - echo "$OUTPUT_SUFFIX" | grep -P "\bvalgrind\b" &>/dev/null - tmp_ret=$? - if [ "$tmp_ret" -eq "0" ] - then - skip_flag="true" - elif [ "$tmp_ret" -eq "1" ] - then - : - else - error "grep failed: $tmp_ret" - exit $tmp_ret - fi - fi - if [ "$skip_flag" ] - then - echo "skip $build_cmd" - else - echo " $build_cmd" - $build_cmd - assert "build fail" - fi - done - assert "exit" -} - -function usage() { - echo "Usage: $0 [-o ] [-h]" 1>&2 - echo ''' -Example: - # default build - bash make.sh - # build without the i386 binary output - bash make.sh -o no-m32 - # build without the valgrind supported binary output - bash make.sh -o no-valgrind - # build without the valgrind supported and i386 binary output - bash make.sh -o no-valgrind -o no-m32 -''' 1>&2 -} - -gl_opt_value="" -while getopts ":o:h" o; do - case "${o}" in - o) - gl_opt_value=${OPTARG} - if [ "$gl_opt_value" = "no-m32" ] - then - gl_opt_no_m32="true" - elif [ "$gl_opt_value" = "no-valgrind" ] - then - gl_opt_no_valgrind="true" - else - usage - error unknow option value of '-o' - exit 1 - fi - ;; - h) - usage - exit 0 - ;; - *) - usage - error unknow option - exit 1 - ;; - esac -done -shift $((OPTIND-1)) - -#echo "o = $gl_opt_value" -#echo "gl_opt_no_valgrind:$gl_opt_no_valgrind" -#echo "gl_opt_no_m32:$gl_opt_no_m32" - -tra "echo;echo build has been interrupted" - -# the matrix of the build config for later testing -# -m32 -DACO_CONFIG_SHARE_FPU_MXCSR_ENV -DACO_USE_VALGRIND -# 0 0 0 -EXTRA_CFLAGS="" OUTPUT_SUFFIX="..no_valgrind.standaloneFPUenv" build_f -# 0 0 1 -EXTRA_CFLAGS="-DACO_USE_VALGRIND" OUTPUT_SUFFIX="..valgrind.standaloneFPUenv" build_f -# 0 1 0 -EXTRA_CFLAGS="-DACO_CONFIG_SHARE_FPU_MXCSR_ENV" OUTPUT_SUFFIX="..no_valgrind.shareFPUenv" build_f -# 0 1 1 -EXTRA_CFLAGS="-DACO_CONFIG_SHARE_FPU_MXCSR_ENV -DACO_USE_VALGRIND" OUTPUT_SUFFIX="..valgrind.shareFPUenv" build_f -# 1 0 0 -EXTRA_CFLAGS="-m32" OUTPUT_SUFFIX="..m32.no_valgrind.standaloneFPUenv" build_f -# 1 0 1 -EXTRA_CFLAGS="-m32 -DACO_USE_VALGRIND" OUTPUT_SUFFIX="..m32.valgrind.standaloneFPUenv" build_f -# 1 1 0 -EXTRA_CFLAGS="-m32 -DACO_CONFIG_SHARE_FPU_MXCSR_ENV" OUTPUT_SUFFIX="..m32.no_valgrind.shareFPUenv" build_f -# 1 1 1 -EXTRA_CFLAGS="-m32 -DACO_CONFIG_SHARE_FPU_MXCSR_ENV -DACO_USE_VALGRIND" OUTPUT_SUFFIX="..m32.valgrind.shareFPUenv" build_f diff --git a/aco.c b/src/aco.c similarity index 100% rename from aco.c rename to src/aco.c diff --git a/acosw.S b/src/acosw.S similarity index 100% rename from acosw.S rename to src/acosw.S diff --git a/test.sh b/test.sh deleted file mode 100644 index 092bc76..0000000 --- a/test.sh +++ /dev/null @@ -1,167 +0,0 @@ -#!/bin/bash - -# Copyright 2018 Sen Han 00hnes@gmail.com -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http:#www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ulimit -c unlimited - -gl_trap_str="" - -function error(){ - echo "$*" > /proc/self/fd/2 -} - -function assert(){ - if [ "0" -ne "$?" ] - then - error "$0:""$*" - exit 1 - fi -} - -function tra(){ - gl_trap_str="$gl_trap_str""$1" - trap "$gl_trap_str exit 1;" INT - assert "$LINENO:trap failed:$gl_trap_str:$1" -} - -function untra(){ - trap - INT - assert "$LINENO:untrap failed:$gl_trap_str:$1" -} - -function test_f_is_exclude_app(){ - declare infile - declare main_name - infile=$1 - main_name=`echo "$infile" | sed -r "s|(.*)\.\.(.*)|\1|"` - if [ -z "$infile" -o -z "$main_name" ] - then - error "$0:""$*" - exit 1 - fi - if [ "$main_name" = "test_aco_benchmark" ] - then - return 0 - else - return 1 - fi -} - -function test_f_handle_exit_code(){ - declare infile - declare errc - declare main_name - declare intended_to_abort - infile=$1 - errc=$2 - if [ -z "$infile" ] - then - error test_f_handle_exit_code illegal input - exit 1 - fi - if [ -z "$errc" -o "$errc" -lt "0" ] - then - error test_f_handle_exit_code illegal input - exit 1 - fi - main_name=`echo "$infile" | sed -r "s|(.*)\.\.(.*)|\1|"` - intended_to_abort="" - if [ "$main_name" = "test_aco_tutorial_4" -o "$main_name" = "test_aco_tutorial_5" ] - then - intended_to_abort="true" - fi - if [ "$intended_to_abort" -a "$errc" -ne "134" ] - then - echo "" - echo test $infile intended to abort failed:$errc - exit $errc - fi - if [ -z "$intended_to_abort" -a "$errc" -ne "0" ] - then - echo "" - echo test $infile failed:$errc - exit $errc - fi - if [ "$intended_to_abort" ] - then - echo test $infile intended to abort success:$errc - else - echo test $infile success - fi -} - -function test_f(){ - declare valgrind_support - declare errc - declare test_ct - declare infile - test_ct=`file * | grep -P "ELF.*executable" | grep -Po '^[^:]+' | wc -l` - file * | grep -P "ELF.*executable" | grep -Po '^[^:]+' | while read infile - do - test_f_is_exclude_app "$infile" - if [ "0" -eq "$?" ] - then - echo "----" $infile is in the exclude app list, bypass its test - echo - continue - fi - valgrind_support=`echo "$infile" | grep -Po '.*\.\.(.*)' | sed -r "s|(.*)\.\.(.*)|\2|" | grep -Po '\bvalgrind\b'` - if [ -z "$valgrind_support" ] - then - echo "----" $infile start":" - time ./$infile - errc="$?" - test_f_handle_exit_code $infile $errc - else - echo "----" $infile memcheck start":" - time valgrind --leak-check=full --error-exitcode=2 --tool=memcheck ./$infile - errc="$?" - test_f_handle_exit_code $infile $errc - fi - echo - done - errc="$?" - if [ "$errc" -ne "0" ] - then - exit "$errc" - fi - if [ "$test_ct" -ne "0" ] - then - echo all the "$test_ct" tests had passed, OK and cheers! - else - echo no test need to do in current directory: "`pwd`" - fi -} - -tra "echo;echo test had been interrupted;exit 0;" - -# test loop -while true -do - echo "---- time:"`date` - test_f - errc="$?" - if [ "$errc" -ne 0 ] - then - exit $errc - fi - if [ "$1" != "loop" ] - then - exit 0 - fi - echo "" - echo "----" start all tests again - sleep 1 -done diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..63d21c6 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright 2018 Sen Han 00hnes@gmail.com +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +macro (aco_register_test test) + set(name ${test}) + + add_executable(test_${name} ${name}.c) + add_test(test_${name} test_${name}) + add_dependencies(check test_${name}) + add_dependencies(test_${name} libaco::aco) + + aco_target_configure(test_${name} libaco::aco ${ARGN}) +endmacro () + +aco_register_test(synopsis) +aco_register_test(tutorial_0) +aco_register_test(tutorial_1) +aco_register_test(tutorial_2) +find_package(Threads QUIET) +if (Threads_FOUND) + aco_register_test(tutorial_3 Threads::Threads) +endif () +aco_register_test(tutorial_4) +aco_register_test(tutorial_5) +aco_register_test(tutorial_6) diff --git a/test_aco_synopsis.c b/test/synopsis.c similarity index 100% rename from test_aco_synopsis.c rename to test/synopsis.c diff --git a/test/tutorial_0.c b/test/tutorial_0.c new file mode 100644 index 0000000..63904bc --- /dev/null +++ b/test/tutorial_0.c @@ -0,0 +1,110 @@ +// Copyright 2018 Sen Han 00hnes@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Hello aco demo. + +#include "aco.h" +#include +#include +#include +#include "aco_assert_override.h" + +void co_fp0() { + // Get co->arg. The caller of `aco_get_arg()` must be a non-main co. + int *iretp = (int *)aco_get_arg(); + // Get current co. The caller of `aco_get_co()` must be a non-main co. + aco_t* this_co = aco_get_co(); + int ct = 0; + while(ct < 6){ + printf( + "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", + this_co, this_co->save_stack.ptr, + this_co->share_stack->ptr, ct + ); + // Yield the execution of current co and resume the execution of + // `co->main_co`. The caller of `aco_yield()` must be a non-main co. + aco_yield(); + (*iretp)++; + ct++; + } + printf( + "co:%p save_stack:%p share_stack:%p co_exit()\n", + this_co, this_co->save_stack.ptr, + this_co->share_stack->ptr + ); + // In addition do the same as `aco_yield()`, `aco_exit()` also set + // `co->is_end` to `1` thus to mark the `co` at the status of "END". + aco_exit(); +} + +int main() { +#ifdef ACO_USE_VALGRIND + if(0){ + printf("%s doesn't have valgrind test yet, " + "so bypass this test right now.\n",__FILE__ + ); + exit(0); + } +#endif + // Initialize the aco environment in the current thread. + aco_thread_init(NULL); + + // Create a main coroutine whose "share stack" is the default stack + // of the current thread. And it doesn't need any private save stack + // since it is definitely a standalone coroutine (which coroutine + // monopolizes it's share stack). + aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); + + // Create a share stack with the default size of 2MB and also with a + // read-only guard page for the detection of stack overflow. + aco_share_stack_t* sstk = aco_share_stack_new(0); + + int co_ct_arg_point_to_me = 0; + // Create a non-main coroutine whose share stack is `sstk` and has a + // default 64 bytes size private save stack. The entry function of the + // coroutine is `co_fp0`. Set `co->arg` to the address of the int + // variable `co_ct_arg_point_to_me`. + aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); + + int ct = 0; + while(ct < 6){ + assert(co->is_end == 0); + // Start or continue the execution of `co`. The caller of this function + // must be main_co. + aco_resume(co); + // Check whether the co has completed the job it promised. + assert(co_ct_arg_point_to_me == ct); + printf("main_co:%p\n", main_co); + ct++; + } + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + // The value of `co->is_end` must be `1` now since it just suspended + // itself by calling `aco_exit()`. + assert(co->is_end); + + printf("main_co:%p\n", main_co); + + // Destroy co and its private save stack. + aco_destroy(co); + co = NULL; + // Destroy the share stack sstk. + aco_share_stack_destroy(sstk); + sstk = NULL; + // Destroy the main_co. + aco_destroy(main_co); + main_co = NULL; + + return 0; +} diff --git a/test/tutorial_1.c b/test/tutorial_1.c new file mode 100644 index 0000000..afa5f17 --- /dev/null +++ b/test/tutorial_1.c @@ -0,0 +1,106 @@ +// Copyright 2018 Sen Han 00hnes@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Some statistics of the coroutine. + +#include "aco.h" +#include +#include +#include +#include "aco_assert_override.h" + +void co_fp0(){ + int *iretp = (int *)aco_get_arg(); + aco_t* this_co = aco_get_co(); + assert(!aco_is_main_co(this_co)); + assert(this_co->fp == (void*)co_fp0); + assert(this_co->is_end == 0); + int ct = 0; + while(ct < 6){ + printf( + "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", + this_co, this_co->save_stack.ptr, + this_co->share_stack->ptr, ct + ); + aco_yield(); + (*iretp)++; + ct++; + } + printf( + "co:%p save_stack:%p share_stack:%p co_exit()\n", + this_co, this_co->save_stack.ptr, + this_co->share_stack->ptr + ); + aco_exit(); + assert(0); +} + +int main() { +#ifdef ACO_USE_VALGRIND + if(0){ + printf("%s doesn't have valgrind test yet, " + "so bypass this test right now.\n",__FILE__ + ); + exit(0); + } +#endif + + aco_thread_init(NULL); + + aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); + assertptr(main_co); + + aco_share_stack_t* sstk = aco_share_stack_new(0); + assertptr(sstk); + + int co_ct_arg_point_to_me = 0; + aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); + assertptr(co); + + int ct = 0; + while(ct < 6){ + assert(co->is_end == 0); + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + printf("main_co:%p\n", main_co); + ct++; + } + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + assert(co->is_end); + + printf("main_co:%p\n", main_co); + + printf( + "\ncopy-stack co:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co, co->save_stack.max_cpsz, + co->save_stack.ct_save, + co->save_stack.ct_restore + ); + printf("\n(Since the share stack used by the co has only one user `co`, " + "so there is no need to save/restore the stack every time during resume &" + " yield execution, thus you can call it a co has 'standalone stack' " + "which just is a very special case of copy-stack.)\n"); + + aco_destroy(co); + co = NULL; + aco_share_stack_destroy(sstk); + sstk = NULL; + aco_destroy(main_co); + main_co = NULL; + + return 0; +} diff --git a/test/tutorial_2.c b/test/tutorial_2.c new file mode 100644 index 0000000..97d0a2c --- /dev/null +++ b/test/tutorial_2.c @@ -0,0 +1,162 @@ +// Copyright 2018 Sen Han 00hnes@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "aco.h" +#include +#include +#include +#include "aco_assert_override.h" + +void foo(int ct){ + printf( + "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", + aco_get_co(), aco_get_co()->save_stack.ptr, + aco_get_co()->share_stack->ptr, ct + ); + aco_yield(); + (*((int*)(aco_get_arg())))++; +} + +void co_fp0() +{ + aco_t* this_co = aco_get_co(); + assert(!aco_is_main_co(this_co)); + assert(this_co->fp == (void*)co_fp0); + assert(this_co->is_end == 0); + int ct = 0; + while(ct < 6){ + foo(ct); + ct++; + } + printf( + "co:%p save_stack:%p share_stack:%p co_exit()\n", + this_co, this_co->save_stack.ptr, + this_co->share_stack->ptr + ); + aco_exit(); + assert(0); +} + +int main() { +#ifdef ACO_USE_VALGRIND + if(1){ + printf("%s doesn't have valgrind test yet, " + "so bypass this test right now.\n",__FILE__ + ); + exit(0); + } +#endif + + aco_thread_init(NULL); + + aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); + assertptr(main_co); + + aco_share_stack_t* sstk = aco_share_stack_new(0); + assertptr(sstk); + aco_share_stack_t* sstk2 = aco_share_stack_new(0); + assertptr(sstk2); + + int co_ct_arg_point_to_me = 0; + int co2_ct_arg_point_to_me = 0; + int co3_ct_arg_point_to_me = 0; + aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); + assertptr(co); + aco_t* co2 = aco_create(main_co, sstk2, 0, co_fp0, &co2_ct_arg_point_to_me); + aco_t* co3 = aco_create(main_co, sstk2, 0, co_fp0, &co3_ct_arg_point_to_me); + assertptr(co2); + assertptr(co3); + + int ct = 0; + while(ct < 6){ + assert(co->is_end == 0); + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + + assert(co2->is_end == 0); + aco_resume(co2); + assert(co2_ct_arg_point_to_me == ct); + + assert(co3->is_end == 0); + aco_resume(co3); + assert(co3_ct_arg_point_to_me == ct); + + printf("main_co:%p\n", main_co); + ct++; + } + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + assert(co->is_end); + + aco_resume(co2); + assert(co2_ct_arg_point_to_me == ct); + assert(co2->is_end); + + aco_resume(co3); + assert(co3_ct_arg_point_to_me == ct); + assert(co3->is_end); + + printf("main_co:%p\n", main_co); + + printf( + "\ncopy-stack co:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co, co->save_stack.max_cpsz, + co->save_stack.ct_save, + co->save_stack.ct_restore + ); + printf("\n(Since the share stack used by the co has only one user `co`, " + "so there is no need to save/restore the stack every time during resume &" + " yield execution, thus you can call it a co has 'standalone stack' " + "which just is a very special case of copy-stack.)\n"); + + printf( + "\ncopy-stack co2:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co2, co2->save_stack.max_cpsz, + co2->save_stack.ct_save, + co2->save_stack.ct_restore + ); + printf( + "\ncopy-stack co3:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co3, co3->save_stack.max_cpsz, + co3->save_stack.ct_save, + co3->save_stack.ct_restore + ); + + printf("\n(The co2 & co3 share the share stack sstk2, thus it is " + "necessary to save/restore the stack every time during resume &" + " yield execution, thus it is a ordinary case of copy-stack.)\n"); + + aco_destroy(co); + co = NULL; + aco_destroy(co2); + co2 = NULL; + aco_destroy(co3); + co3 = NULL; + + aco_share_stack_destroy(sstk); + sstk = NULL; + aco_share_stack_destroy(sstk2); + sstk2 = NULL; + + aco_destroy(main_co); + main_co = NULL; + + return 0; +} diff --git a/test/tutorial_3.c b/test/tutorial_3.c new file mode 100644 index 0000000..a98141b --- /dev/null +++ b/test/tutorial_3.c @@ -0,0 +1,208 @@ +// Copyright 2018 Sen Han 00hnes@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Use aco in multithread. + +#include "aco.h" +#include +#include +#include +#include +#include +#include "aco_assert_override.h" + +uint64_t gl_race_aco_yield_ct = 0; +pthread_mutex_t gl_race_aco_yield_ct_mutex = PTHREAD_MUTEX_INITIALIZER; + +void foo(int ct){ + printf( + "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", + aco_get_co(), aco_get_co()->save_stack.ptr, + aco_get_co()->share_stack->ptr, ct + ); + pthread_mutex_lock(&gl_race_aco_yield_ct_mutex); + gl_race_aco_yield_ct++; + pthread_mutex_unlock(&gl_race_aco_yield_ct_mutex); + aco_yield(); + (*((int*)(aco_get_arg())))++; +} + +void co_fp0() +{ + aco_t* this_co = aco_get_co(); + assert(!aco_is_main_co(this_co)); + assert(this_co->fp == (void*)co_fp0); + assert(this_co->is_end == 0); + int ct = 0; + while(ct < 6){ + foo(ct); + ct++; + } + printf( + "co:%p save_stack:%p share_stack:%p co_exit()\n", + this_co, this_co->save_stack.ptr, + this_co->share_stack->ptr + ); + pthread_mutex_lock(&gl_race_aco_yield_ct_mutex); + gl_race_aco_yield_ct++; + pthread_mutex_unlock(&gl_race_aco_yield_ct_mutex); + aco_exit(); + assert(0); +} + +void* pmain(void* pthread_in_arg) { + pthread_t t = pthread_self(); + size_t idx = 0; + (void)pthread_in_arg; + assert(sizeof(t) > 0); + printf("\ntid:0x"); + while(idx < sizeof(t)){ + printf("%02x", *(((uint8_t*)(&t)) + idx)); + idx++; + } + printf("\n"); + + aco_thread_init(NULL); + + aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); + assertptr(main_co); + + aco_share_stack_t* sstk = aco_share_stack_new(0); + assertptr(sstk); + aco_share_stack_t* sstk2 = aco_share_stack_new(0); + assertptr(sstk2); + + int co_ct_arg_point_to_me = 0; + int co2_ct_arg_point_to_me = 0; + int co3_ct_arg_point_to_me = 0; + aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); + assertptr(co); + aco_t* co2 = aco_create(main_co, sstk2, 0, co_fp0, &co2_ct_arg_point_to_me); + aco_t* co3 = aco_create(main_co, sstk2, 0, co_fp0, &co3_ct_arg_point_to_me); + assertptr(co2); + assertptr(co3); + + int ct = 0; + while(ct < 6){ + assert(co->is_end == 0); + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + + assert(co2->is_end == 0); + aco_resume(co2); + assert(co2_ct_arg_point_to_me == ct); + + assert(co3->is_end == 0); + aco_resume(co3); + assert(co3_ct_arg_point_to_me == ct); + + printf("main_co:%p\n", main_co); + ct++; + } + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + assert(co->is_end); + + aco_resume(co2); + assert(co2_ct_arg_point_to_me == ct); + assert(co2->is_end); + + aco_resume(co3); + assert(co3_ct_arg_point_to_me == ct); + assert(co3->is_end); + + printf("main_co:%p\n", main_co); + + printf( + "\ncopy-stack co:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co, co->save_stack.max_cpsz, + co->save_stack.ct_save, + co->save_stack.ct_restore + ); + printf("\n(Since the share stack used by the co has only one user `co`, " + "so there is no need to save/restore the stack every time during resume &" + " yield execution, thus you can call it a co has 'standalone stack' " + "which just is a very special case of copy-stack.)\n"); + + printf( + "\ncopy-stack co2:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co2, co2->save_stack.max_cpsz, + co2->save_stack.ct_save, + co2->save_stack.ct_restore + ); + printf( + "\ncopy-stack co3:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co3, co3->save_stack.max_cpsz, + co3->save_stack.ct_save, + co3->save_stack.ct_restore + ); + + printf("\n(The co2 & co3 share the share stack sstk2, thus it is " + "necessary to save/restore the stack every time during resume &" + " yield execution, thus it is a ordinary case of copy-stack.)\n"); + + uint64_t tmp_gl_ct; + pthread_mutex_lock(&gl_race_aco_yield_ct_mutex); + tmp_gl_ct = gl_race_aco_yield_ct; + pthread_mutex_unlock(&gl_race_aco_yield_ct_mutex); + printf("\ngl_race_aco_yield_ct:%" PRIu64"\n", tmp_gl_ct); + + aco_destroy(co); + co = NULL; + aco_destroy(co2); + co2 = NULL; + aco_destroy(co3); + co3 = NULL; + + aco_share_stack_destroy(sstk); + sstk = NULL; + aco_share_stack_destroy(sstk2); + sstk2 = NULL; + + aco_destroy(main_co); + main_co = NULL; + + return 0; +} + +int main(){ +#ifdef ACO_USE_VALGRIND + if(1){ + printf("%s doesn't have valgrind test yet, " + "so bypass this test right now.\n",__FILE__ + ); + exit(0); + } +#endif + + pthread_t t1,t2; + + assert(0 == pthread_create( + &t1, NULL, pmain, NULL + )); + assert(0 == pthread_create( + &t2, NULL, pmain, NULL + )); + + assert(0 == pthread_join(t1, NULL)); + assert(0 == pthread_join(t2, NULL)); + + return 0; +} diff --git a/test/tutorial_4.c b/test/tutorial_4.c new file mode 100644 index 0000000..b673b7f --- /dev/null +++ b/test/tutorial_4.c @@ -0,0 +1,117 @@ +// Copyright 2018 Sen Han 00hnes@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "aco.h" +#include +#include +#include +#include "aco_assert_override.h" + +void foo(int ct){ + printf( + "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", + aco_get_co(), aco_get_co()->save_stack.ptr, + aco_get_co()->share_stack->ptr, ct + ); + aco_yield(); + (*((int*)(aco_get_arg())))++; +} + +void co_fp0() +{ + aco_t* this_co = aco_get_co(); + assert(!aco_is_main_co(this_co)); + assert(this_co->fp == (void*)co_fp0); + assert(this_co->is_end == 0); + int ct = 0; + while(ct < 6){ + foo(ct); + ct++; + } + printf( + "co:%p save_stack:%p share_stack:%p !offending return!\n", + this_co, this_co->save_stack.ptr, + this_co->share_stack->ptr + ); + //printf("Intended to Abort to test the aco protector :)\n"); + // the offending `return` here it is + // you should always call `aco_exit()` to finish the execution of a non-main co + // instead of call `return` in the real application + // this is a demo shows how protector works in libaco (intended to abort) + //return; + aco_exit(); + assert(0); +} + +int main() { +#ifdef ACO_USE_VALGRIND + if(0){ + printf("%s doesn't have valgrind test yet, " + "so bypass this test right now.\n",__FILE__ + ); + exit(0); + } +#endif + + aco_thread_init(NULL); + + aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); + assertptr(main_co); + + aco_share_stack_t* sstk = aco_share_stack_new(0); + assertptr(sstk); + + int co_ct_arg_point_to_me = 0; + aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); + assertptr(co); + + int ct = 0; + while(ct < 6){ + assert(co->is_end == 0); + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + + printf("main_co:%p\n", main_co); + ct++; + } + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + assert(co->is_end); + + printf("main_co:%p\n", main_co); + + printf( + "\ncopy-stack co:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co, co->save_stack.max_cpsz, + co->save_stack.ct_save, + co->save_stack.ct_restore + ); + printf("\n(Since the share stack used by the co has only one user `co`, " + "so there is no need to save/restore the stack every time during resume &" + " yield execution, thus you can call it a co has 'standalone stack' " + "which just is a very special case of copy-stack.)\n"); + + aco_destroy(co); + co = NULL; + + aco_share_stack_destroy(sstk); + sstk = NULL; + + aco_destroy(main_co); + main_co = NULL; + + return 0; +} diff --git a/test/tutorial_5.c b/test/tutorial_5.c new file mode 100644 index 0000000..3f9b3f8 --- /dev/null +++ b/test/tutorial_5.c @@ -0,0 +1,125 @@ +// Copyright 2018 Sen Han 00hnes@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Test the customization of aco protector. + +#include "aco.h" +#include +#include +#include + +#include "aco_assert_override.h" + +void foo(int ct){ + printf( + "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", + aco_get_co(), aco_get_co()->save_stack.ptr, + aco_get_co()->share_stack->ptr, ct + ); + aco_yield(); + (*((int*)(aco_get_arg())))++; +} + +void co_fp0() +{ + aco_t* this_co = aco_get_co(); + assert(!aco_is_main_co(this_co)); + assert(this_co->fp == (void*)co_fp0); + assert(this_co->is_end == 0); + int ct = 0; + while(ct < 6){ + foo(ct); + ct++; + } + printf( + "co:%p save_stack:%p share_stack:%p !offending return!\n", + this_co, this_co->save_stack.ptr, + this_co->share_stack->ptr + ); + //printf("Intended to Abort to test the aco protector :)\n"); + //return; + aco_exit(); + assert(0); +} + +static void co_protector_last_word(){ + aco_t* co = aco_get_co(); + // do some log about the offending `co` + fprintf(stderr,"error: customized co_protector_last_word triggered \n"); + fprintf(stderr, "error: co:%p should call `aco_exit(co)` instead of direct " + "`return` in co_fp:%p to finish its execution\n", co, (void*)co->fp); + assert(0); +} + +int main() { +#ifdef ACO_USE_VALGRIND + if(0){ + printf("%s doesn't have valgrind test yet, " + "so bypass this test right now.\n",__FILE__ + ); + exit(0); + } +#endif + + aco_thread_init(co_protector_last_word); + + aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); + assertptr(main_co); + + aco_share_stack_t* sstk = aco_share_stack_new(0); + assertptr(sstk); + + int co_ct_arg_point_to_me = 0; + aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); + assertptr(co); + + int ct = 0; + while(ct < 6){ + assert(co->is_end == 0); + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + + printf("main_co:%p\n", main_co); + ct++; + } + aco_resume(co); + assert(co_ct_arg_point_to_me == ct); + assert(co->is_end); + + printf("main_co:%p\n", main_co); + + printf( + "\ncopy-stack co:%p:\n max stack copy size:%zu\n" + " save (from share stack to save stack) counter of the private save stack:%zu\n" + " restore (from save stack to share stack) counter of the private save stack:%zu\n", + co, co->save_stack.max_cpsz, + co->save_stack.ct_save, + co->save_stack.ct_restore + ); + printf("\n(Since the share stack used by the co has only one user `co`, " + "so there is no need to save/restore the stack every time during resume &" + " yield execution, thus you can call it a co has 'standalone stack' " + "which just is a very special case of copy-stack.)\n"); + + aco_destroy(co); + co = NULL; + + aco_share_stack_destroy(sstk); + sstk = NULL; + + aco_destroy(main_co); + main_co = NULL; + + return 0; +} diff --git a/test_aco_tutorial_6.c b/test/tutorial_6.c similarity index 100% rename from test_aco_tutorial_6.c rename to test/tutorial_6.c From a0255b8f351f4c7f62c661d9c4eca6dd941a80db Mon Sep 17 00:00:00 2001 From: uael Date: Thu, 19 Jul 2018 16:23:42 +0200 Subject: [PATCH 2/6] added /bench to git attributes export-ignore --- .gitattributes | 1 + test_aco_tutorial_0.c | 110 ---------------------- test_aco_tutorial_1.c | 106 --------------------- test_aco_tutorial_2.c | 162 --------------------------------- test_aco_tutorial_3.c | 207 ------------------------------------------ test_aco_tutorial_4.c | 117 ------------------------ test_aco_tutorial_5.c | 125 ------------------------- 7 files changed, 1 insertion(+), 827 deletions(-) delete mode 100644 test_aco_tutorial_0.c delete mode 100644 test_aco_tutorial_1.c delete mode 100644 test_aco_tutorial_2.c delete mode 100644 test_aco_tutorial_3.c delete mode 100644 test_aco_tutorial_4.c delete mode 100644 test_aco_tutorial_5.c diff --git a/.gitattributes b/.gitattributes index b27a87e..221470b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ *.h linguist-language=C *.c linguist-language=C +/bench export-ignore /test export-ignore .gitattributes export-ignore .gitignore export-ignore diff --git a/test_aco_tutorial_0.c b/test_aco_tutorial_0.c deleted file mode 100644 index 63904bc..0000000 --- a/test_aco_tutorial_0.c +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2018 Sen Han 00hnes@gmail.com -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Hello aco demo. - -#include "aco.h" -#include -#include -#include -#include "aco_assert_override.h" - -void co_fp0() { - // Get co->arg. The caller of `aco_get_arg()` must be a non-main co. - int *iretp = (int *)aco_get_arg(); - // Get current co. The caller of `aco_get_co()` must be a non-main co. - aco_t* this_co = aco_get_co(); - int ct = 0; - while(ct < 6){ - printf( - "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", - this_co, this_co->save_stack.ptr, - this_co->share_stack->ptr, ct - ); - // Yield the execution of current co and resume the execution of - // `co->main_co`. The caller of `aco_yield()` must be a non-main co. - aco_yield(); - (*iretp)++; - ct++; - } - printf( - "co:%p save_stack:%p share_stack:%p co_exit()\n", - this_co, this_co->save_stack.ptr, - this_co->share_stack->ptr - ); - // In addition do the same as `aco_yield()`, `aco_exit()` also set - // `co->is_end` to `1` thus to mark the `co` at the status of "END". - aco_exit(); -} - -int main() { -#ifdef ACO_USE_VALGRIND - if(0){ - printf("%s doesn't have valgrind test yet, " - "so bypass this test right now.\n",__FILE__ - ); - exit(0); - } -#endif - // Initialize the aco environment in the current thread. - aco_thread_init(NULL); - - // Create a main coroutine whose "share stack" is the default stack - // of the current thread. And it doesn't need any private save stack - // since it is definitely a standalone coroutine (which coroutine - // monopolizes it's share stack). - aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); - - // Create a share stack with the default size of 2MB and also with a - // read-only guard page for the detection of stack overflow. - aco_share_stack_t* sstk = aco_share_stack_new(0); - - int co_ct_arg_point_to_me = 0; - // Create a non-main coroutine whose share stack is `sstk` and has a - // default 64 bytes size private save stack. The entry function of the - // coroutine is `co_fp0`. Set `co->arg` to the address of the int - // variable `co_ct_arg_point_to_me`. - aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); - - int ct = 0; - while(ct < 6){ - assert(co->is_end == 0); - // Start or continue the execution of `co`. The caller of this function - // must be main_co. - aco_resume(co); - // Check whether the co has completed the job it promised. - assert(co_ct_arg_point_to_me == ct); - printf("main_co:%p\n", main_co); - ct++; - } - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - // The value of `co->is_end` must be `1` now since it just suspended - // itself by calling `aco_exit()`. - assert(co->is_end); - - printf("main_co:%p\n", main_co); - - // Destroy co and its private save stack. - aco_destroy(co); - co = NULL; - // Destroy the share stack sstk. - aco_share_stack_destroy(sstk); - sstk = NULL; - // Destroy the main_co. - aco_destroy(main_co); - main_co = NULL; - - return 0; -} diff --git a/test_aco_tutorial_1.c b/test_aco_tutorial_1.c deleted file mode 100644 index afa5f17..0000000 --- a/test_aco_tutorial_1.c +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2018 Sen Han 00hnes@gmail.com -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Some statistics of the coroutine. - -#include "aco.h" -#include -#include -#include -#include "aco_assert_override.h" - -void co_fp0(){ - int *iretp = (int *)aco_get_arg(); - aco_t* this_co = aco_get_co(); - assert(!aco_is_main_co(this_co)); - assert(this_co->fp == (void*)co_fp0); - assert(this_co->is_end == 0); - int ct = 0; - while(ct < 6){ - printf( - "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", - this_co, this_co->save_stack.ptr, - this_co->share_stack->ptr, ct - ); - aco_yield(); - (*iretp)++; - ct++; - } - printf( - "co:%p save_stack:%p share_stack:%p co_exit()\n", - this_co, this_co->save_stack.ptr, - this_co->share_stack->ptr - ); - aco_exit(); - assert(0); -} - -int main() { -#ifdef ACO_USE_VALGRIND - if(0){ - printf("%s doesn't have valgrind test yet, " - "so bypass this test right now.\n",__FILE__ - ); - exit(0); - } -#endif - - aco_thread_init(NULL); - - aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); - assertptr(main_co); - - aco_share_stack_t* sstk = aco_share_stack_new(0); - assertptr(sstk); - - int co_ct_arg_point_to_me = 0; - aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); - assertptr(co); - - int ct = 0; - while(ct < 6){ - assert(co->is_end == 0); - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - printf("main_co:%p\n", main_co); - ct++; - } - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - assert(co->is_end); - - printf("main_co:%p\n", main_co); - - printf( - "\ncopy-stack co:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co, co->save_stack.max_cpsz, - co->save_stack.ct_save, - co->save_stack.ct_restore - ); - printf("\n(Since the share stack used by the co has only one user `co`, " - "so there is no need to save/restore the stack every time during resume &" - " yield execution, thus you can call it a co has 'standalone stack' " - "which just is a very special case of copy-stack.)\n"); - - aco_destroy(co); - co = NULL; - aco_share_stack_destroy(sstk); - sstk = NULL; - aco_destroy(main_co); - main_co = NULL; - - return 0; -} diff --git a/test_aco_tutorial_2.c b/test_aco_tutorial_2.c deleted file mode 100644 index 97d0a2c..0000000 --- a/test_aco_tutorial_2.c +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2018 Sen Han 00hnes@gmail.com -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "aco.h" -#include -#include -#include -#include "aco_assert_override.h" - -void foo(int ct){ - printf( - "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", - aco_get_co(), aco_get_co()->save_stack.ptr, - aco_get_co()->share_stack->ptr, ct - ); - aco_yield(); - (*((int*)(aco_get_arg())))++; -} - -void co_fp0() -{ - aco_t* this_co = aco_get_co(); - assert(!aco_is_main_co(this_co)); - assert(this_co->fp == (void*)co_fp0); - assert(this_co->is_end == 0); - int ct = 0; - while(ct < 6){ - foo(ct); - ct++; - } - printf( - "co:%p save_stack:%p share_stack:%p co_exit()\n", - this_co, this_co->save_stack.ptr, - this_co->share_stack->ptr - ); - aco_exit(); - assert(0); -} - -int main() { -#ifdef ACO_USE_VALGRIND - if(1){ - printf("%s doesn't have valgrind test yet, " - "so bypass this test right now.\n",__FILE__ - ); - exit(0); - } -#endif - - aco_thread_init(NULL); - - aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); - assertptr(main_co); - - aco_share_stack_t* sstk = aco_share_stack_new(0); - assertptr(sstk); - aco_share_stack_t* sstk2 = aco_share_stack_new(0); - assertptr(sstk2); - - int co_ct_arg_point_to_me = 0; - int co2_ct_arg_point_to_me = 0; - int co3_ct_arg_point_to_me = 0; - aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); - assertptr(co); - aco_t* co2 = aco_create(main_co, sstk2, 0, co_fp0, &co2_ct_arg_point_to_me); - aco_t* co3 = aco_create(main_co, sstk2, 0, co_fp0, &co3_ct_arg_point_to_me); - assertptr(co2); - assertptr(co3); - - int ct = 0; - while(ct < 6){ - assert(co->is_end == 0); - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - - assert(co2->is_end == 0); - aco_resume(co2); - assert(co2_ct_arg_point_to_me == ct); - - assert(co3->is_end == 0); - aco_resume(co3); - assert(co3_ct_arg_point_to_me == ct); - - printf("main_co:%p\n", main_co); - ct++; - } - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - assert(co->is_end); - - aco_resume(co2); - assert(co2_ct_arg_point_to_me == ct); - assert(co2->is_end); - - aco_resume(co3); - assert(co3_ct_arg_point_to_me == ct); - assert(co3->is_end); - - printf("main_co:%p\n", main_co); - - printf( - "\ncopy-stack co:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co, co->save_stack.max_cpsz, - co->save_stack.ct_save, - co->save_stack.ct_restore - ); - printf("\n(Since the share stack used by the co has only one user `co`, " - "so there is no need to save/restore the stack every time during resume &" - " yield execution, thus you can call it a co has 'standalone stack' " - "which just is a very special case of copy-stack.)\n"); - - printf( - "\ncopy-stack co2:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co2, co2->save_stack.max_cpsz, - co2->save_stack.ct_save, - co2->save_stack.ct_restore - ); - printf( - "\ncopy-stack co3:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co3, co3->save_stack.max_cpsz, - co3->save_stack.ct_save, - co3->save_stack.ct_restore - ); - - printf("\n(The co2 & co3 share the share stack sstk2, thus it is " - "necessary to save/restore the stack every time during resume &" - " yield execution, thus it is a ordinary case of copy-stack.)\n"); - - aco_destroy(co); - co = NULL; - aco_destroy(co2); - co2 = NULL; - aco_destroy(co3); - co3 = NULL; - - aco_share_stack_destroy(sstk); - sstk = NULL; - aco_share_stack_destroy(sstk2); - sstk2 = NULL; - - aco_destroy(main_co); - main_co = NULL; - - return 0; -} diff --git a/test_aco_tutorial_3.c b/test_aco_tutorial_3.c deleted file mode 100644 index 293ea51..0000000 --- a/test_aco_tutorial_3.c +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2018 Sen Han 00hnes@gmail.com -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Use aco in multithread. - -#include "aco.h" -#include -#include -#include -#include -#include -#include "aco_assert_override.h" - -uint64_t gl_race_aco_yield_ct = 0; -pthread_mutex_t gl_race_aco_yield_ct_mutex = PTHREAD_MUTEX_INITIALIZER; - -void foo(int ct){ - printf( - "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", - aco_get_co(), aco_get_co()->save_stack.ptr, - aco_get_co()->share_stack->ptr, ct - ); - pthread_mutex_lock(&gl_race_aco_yield_ct_mutex); - gl_race_aco_yield_ct++; - pthread_mutex_unlock(&gl_race_aco_yield_ct_mutex); - aco_yield(); - (*((int*)(aco_get_arg())))++; -} - -void co_fp0() -{ - aco_t* this_co = aco_get_co(); - assert(!aco_is_main_co(this_co)); - assert(this_co->fp == (void*)co_fp0); - assert(this_co->is_end == 0); - int ct = 0; - while(ct < 6){ - foo(ct); - ct++; - } - printf( - "co:%p save_stack:%p share_stack:%p co_exit()\n", - this_co, this_co->save_stack.ptr, - this_co->share_stack->ptr - ); - pthread_mutex_lock(&gl_race_aco_yield_ct_mutex); - gl_race_aco_yield_ct++; - pthread_mutex_unlock(&gl_race_aco_yield_ct_mutex); - aco_exit(); - assert(0); -} - -void* pmain(void* pthread_in_arg) { - pthread_t t = pthread_self(); - size_t idx = 0; - assert(sizeof(t) > 0); - printf("\ntid:0x"); - while(idx < sizeof(t)){ - printf("%02x", *(((uint8_t*)(&t)) + idx)); - idx++; - } - printf("\n"); - - aco_thread_init(NULL); - - aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); - assertptr(main_co); - - aco_share_stack_t* sstk = aco_share_stack_new(0); - assertptr(sstk); - aco_share_stack_t* sstk2 = aco_share_stack_new(0); - assertptr(sstk2); - - int co_ct_arg_point_to_me = 0; - int co2_ct_arg_point_to_me = 0; - int co3_ct_arg_point_to_me = 0; - aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); - assertptr(co); - aco_t* co2 = aco_create(main_co, sstk2, 0, co_fp0, &co2_ct_arg_point_to_me); - aco_t* co3 = aco_create(main_co, sstk2, 0, co_fp0, &co3_ct_arg_point_to_me); - assertptr(co2); - assertptr(co3); - - int ct = 0; - while(ct < 6){ - assert(co->is_end == 0); - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - - assert(co2->is_end == 0); - aco_resume(co2); - assert(co2_ct_arg_point_to_me == ct); - - assert(co3->is_end == 0); - aco_resume(co3); - assert(co3_ct_arg_point_to_me == ct); - - printf("main_co:%p\n", main_co); - ct++; - } - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - assert(co->is_end); - - aco_resume(co2); - assert(co2_ct_arg_point_to_me == ct); - assert(co2->is_end); - - aco_resume(co3); - assert(co3_ct_arg_point_to_me == ct); - assert(co3->is_end); - - printf("main_co:%p\n", main_co); - - printf( - "\ncopy-stack co:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co, co->save_stack.max_cpsz, - co->save_stack.ct_save, - co->save_stack.ct_restore - ); - printf("\n(Since the share stack used by the co has only one user `co`, " - "so there is no need to save/restore the stack every time during resume &" - " yield execution, thus you can call it a co has 'standalone stack' " - "which just is a very special case of copy-stack.)\n"); - - printf( - "\ncopy-stack co2:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co2, co2->save_stack.max_cpsz, - co2->save_stack.ct_save, - co2->save_stack.ct_restore - ); - printf( - "\ncopy-stack co3:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co3, co3->save_stack.max_cpsz, - co3->save_stack.ct_save, - co3->save_stack.ct_restore - ); - - printf("\n(The co2 & co3 share the share stack sstk2, thus it is " - "necessary to save/restore the stack every time during resume &" - " yield execution, thus it is a ordinary case of copy-stack.)\n"); - - uint64_t tmp_gl_ct; - pthread_mutex_lock(&gl_race_aco_yield_ct_mutex); - tmp_gl_ct = gl_race_aco_yield_ct; - pthread_mutex_unlock(&gl_race_aco_yield_ct_mutex); - printf("\ngl_race_aco_yield_ct:%" PRIu64"\n", tmp_gl_ct); - - aco_destroy(co); - co = NULL; - aco_destroy(co2); - co2 = NULL; - aco_destroy(co3); - co3 = NULL; - - aco_share_stack_destroy(sstk); - sstk = NULL; - aco_share_stack_destroy(sstk2); - sstk2 = NULL; - - aco_destroy(main_co); - main_co = NULL; - - return 0; -} - -int main(){ -#ifdef ACO_USE_VALGRIND - if(1){ - printf("%s doesn't have valgrind test yet, " - "so bypass this test right now.\n",__FILE__ - ); - exit(0); - } -#endif - - pthread_t t1,t2; - - assert(0 == pthread_create( - &t1, NULL, pmain, NULL - )); - assert(0 == pthread_create( - &t2, NULL, pmain, NULL - )); - - assert(0 == pthread_join(t1, NULL)); - assert(0 == pthread_join(t2, NULL)); - - return 0; -} diff --git a/test_aco_tutorial_4.c b/test_aco_tutorial_4.c deleted file mode 100644 index 145f68e..0000000 --- a/test_aco_tutorial_4.c +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2018 Sen Han 00hnes@gmail.com -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "aco.h" -#include -#include -#include -#include "aco_assert_override.h" - -void foo(int ct){ - printf( - "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", - aco_get_co(), aco_get_co()->save_stack.ptr, - aco_get_co()->share_stack->ptr, ct - ); - aco_yield(); - (*((int*)(aco_get_arg())))++; -} - -void co_fp0() -{ - aco_t* this_co = aco_get_co(); - assert(!aco_is_main_co(this_co)); - assert(this_co->fp == (void*)co_fp0); - assert(this_co->is_end == 0); - int ct = 0; - while(ct < 6){ - foo(ct); - ct++; - } - printf( - "co:%p save_stack:%p share_stack:%p !offending return!\n", - this_co, this_co->save_stack.ptr, - this_co->share_stack->ptr - ); - printf("Intended to Abort to test the aco protector :)\n"); - // the offending `return` here it is - // you should always call `aco_exit()` to finish the execution of a non-main co - // instead of call `return` in the real application - // this is a demo shows how protector works in libaco (intended to abort) - return; - aco_exit(); - assert(0); -} - -int main() { -#ifdef ACO_USE_VALGRIND - if(0){ - printf("%s doesn't have valgrind test yet, " - "so bypass this test right now.\n",__FILE__ - ); - exit(0); - } -#endif - - aco_thread_init(NULL); - - aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); - assertptr(main_co); - - aco_share_stack_t* sstk = aco_share_stack_new(0); - assertptr(sstk); - - int co_ct_arg_point_to_me = 0; - aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); - assertptr(co); - - int ct = 0; - while(ct < 6){ - assert(co->is_end == 0); - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - - printf("main_co:%p\n", main_co); - ct++; - } - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - assert(co->is_end); - - printf("main_co:%p\n", main_co); - - printf( - "\ncopy-stack co:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co, co->save_stack.max_cpsz, - co->save_stack.ct_save, - co->save_stack.ct_restore - ); - printf("\n(Since the share stack used by the co has only one user `co`, " - "so there is no need to save/restore the stack every time during resume &" - " yield execution, thus you can call it a co has 'standalone stack' " - "which just is a very special case of copy-stack.)\n"); - - aco_destroy(co); - co = NULL; - - aco_share_stack_destroy(sstk); - sstk = NULL; - - aco_destroy(main_co); - main_co = NULL; - - return 0; -} diff --git a/test_aco_tutorial_5.c b/test_aco_tutorial_5.c deleted file mode 100644 index 321bdd8..0000000 --- a/test_aco_tutorial_5.c +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2018 Sen Han 00hnes@gmail.com -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Test the customization of aco protector. - -#include "aco.h" -#include -#include -#include - -#include "aco_assert_override.h" - -void foo(int ct){ - printf( - "co:%p save_stack:%p share_stack:%p yield_ct:%d\n", - aco_get_co(), aco_get_co()->save_stack.ptr, - aco_get_co()->share_stack->ptr, ct - ); - aco_yield(); - (*((int*)(aco_get_arg())))++; -} - -void co_fp0() -{ - aco_t* this_co = aco_get_co(); - assert(!aco_is_main_co(this_co)); - assert(this_co->fp == (void*)co_fp0); - assert(this_co->is_end == 0); - int ct = 0; - while(ct < 6){ - foo(ct); - ct++; - } - printf( - "co:%p save_stack:%p share_stack:%p !offending return!\n", - this_co, this_co->save_stack.ptr, - this_co->share_stack->ptr - ); - printf("Intended to Abort to test the aco protector :)\n"); - return; - aco_exit(); - assert(0); -} - -static void co_protector_last_word(){ - aco_t* co = aco_get_co(); - // do some log about the offending `co` - fprintf(stderr,"error: customized co_protector_last_word triggered \n"); - fprintf(stderr, "error: co:%p should call `aco_exit(co)` instead of direct " - "`return` in co_fp:%p to finish its execution\n", co, (void*)co->fp); - assert(0); -} - -int main() { -#ifdef ACO_USE_VALGRIND - if(0){ - printf("%s doesn't have valgrind test yet, " - "so bypass this test right now.\n",__FILE__ - ); - exit(0); - } -#endif - - aco_thread_init(co_protector_last_word); - - aco_t* main_co = aco_create(NULL, NULL, 0, NULL, NULL); - assertptr(main_co); - - aco_share_stack_t* sstk = aco_share_stack_new(0); - assertptr(sstk); - - int co_ct_arg_point_to_me = 0; - aco_t* co = aco_create(main_co, sstk, 0, co_fp0, &co_ct_arg_point_to_me); - assertptr(co); - - int ct = 0; - while(ct < 6){ - assert(co->is_end == 0); - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - - printf("main_co:%p\n", main_co); - ct++; - } - aco_resume(co); - assert(co_ct_arg_point_to_me == ct); - assert(co->is_end); - - printf("main_co:%p\n", main_co); - - printf( - "\ncopy-stack co:%p:\n max stack copy size:%zu\n" - " save (from share stack to save stack) counter of the private save stack:%zu\n" - " restore (from save stack to share stack) counter of the private save stack:%zu\n", - co, co->save_stack.max_cpsz, - co->save_stack.ct_save, - co->save_stack.ct_restore - ); - printf("\n(Since the share stack used by the co has only one user `co`, " - "so there is no need to save/restore the stack every time during resume &" - " yield execution, thus you can call it a co has 'standalone stack' " - "which just is a very special case of copy-stack.)\n"); - - aco_destroy(co); - co = NULL; - - aco_share_stack_destroy(sstk); - sstk = NULL; - - aco_destroy(main_co); - main_co = NULL; - - return 0; -} From 793b893bcc11da1af70297a5a95a4d8aa7b82c73 Mon Sep 17 00:00:00 2001 From: uael Date: Thu, 19 Jul 2018 16:26:32 +0200 Subject: [PATCH 3/6] updated travis yml --- .travis.yml | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd10349..d62ccf4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ dist: trusty notifications: email: - - 00hnes@gmail.com + - 00hnes@gmail.com install: - mkdir -p build/m32 && cd build/m32 @@ -45,33 +45,33 @@ matrix: addons: apt: sources: - - ubuntu-toolchain-r-test + - ubuntu-toolchain-r-test packages: - - gcc-4.9 + - gcc-4.9 - os: linux compiler: gcc-5 addons: apt: sources: - - ubuntu-toolchain-r-test + - ubuntu-toolchain-r-test packages: - - gcc-5 + - gcc-5 - os: linux compiler: gcc-6 addons: apt: sources: - - ubuntu-toolchain-r-test + - ubuntu-toolchain-r-test packages: - - gcc-6 + - gcc-6 - os: linux compiler: gcc-7 addons: apt: sources: - - ubuntu-toolchain-r-test + - ubuntu-toolchain-r-test packages: - - gcc-7 + - gcc-7 # clang - os: linux @@ -79,43 +79,43 @@ matrix: addons: apt: sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-3.5 + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.5 packages: - - clang-3.5 + - clang-3.5 - os: linux compiler: clang-3.6 addons: apt: sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-3.6 + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.6 packages: - - clang-3.6 + - clang-3.6 - os: linux compiler: clang-3.8 addons: apt: sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-3.8 + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.8 packages: - - clang-3.8 + - clang-3.8 - os: linux compiler: clang-3.9 addons: apt: sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-3.9 + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-3.9 packages: - - clang-3.9 + - clang-3.9 - os: linux compiler: clang-4.0 addons: apt: sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-4.0 + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-4.0 packages: - - clang-4.0 \ No newline at end of file + - clang-4.0 \ No newline at end of file From d1626838346c9aca98fb7df52442d688b143965f Mon Sep 17 00:00:00 2001 From: uael Date: Thu, 19 Jul 2018 16:27:14 +0200 Subject: [PATCH 4/6] updated travis yml (2) --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d62ccf4..7b87d20 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,6 @@ matrix: - os: linux - os: osx - osx - os: osx osx_image: xcode7.3 compiler: clang From 0e5e6eec7d2a72b8365c6b75cbc5fade388da49d Mon Sep 17 00:00:00 2001 From: uael Date: Thu, 19 Jul 2018 16:35:04 +0200 Subject: [PATCH 5/6] travis: run only default build and disabled osx --- .travis.yml | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7b87d20..3d876d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,36 +7,41 @@ notifications: - 00hnes@gmail.com install: - - mkdir -p build/m32 && cd build/m32 - - cmake -DACO_M32=ON ../.. - - cmake --build . - - cd ../.. - - mkdir -p build/fpenv && cd build/fpenv - - cmake -DACO_SHARE_FPENV=ON ../.. - - cmake --build . - - cd ../.. - - mkdir -p build/m32-fpenv && cd build/m32-fpenv - - cmake -DACO_M32=ON -DACO_SHARE_FPENV=ON ../.. + - mkdir -p build/default && cd build/default + - cmake ../.. - cmake --build . - cd ../.. +# - mkdir -p build/m32 && cd build/m32 +# - cmake -DACO_M32=ON ../.. +# - cmake --build . +# - cd ../.. +# - mkdir -p build/fpenv && cd build/fpenv +# - cmake -DACO_SHARE_FPENV=ON ../.. +# - cmake --build . +# - cd ../.. +# - mkdir -p build/m32-fpenv && cd build/m32-fpenv +# - cmake -DACO_M32=ON -DACO_SHARE_FPENV=ON ../.. +# - cmake --build . +# - cd ../.. script: - - cmake --build build/m32 --target check - - cmake --build build/fpenv --target check - - cmake --build build/m32-fpenv --target check + - cmake --build build/default --target check +# - cmake --build build/m32 --target check +# - cmake --build build/fpenv --target check +# - cmake --build build/m32-fpenv --target check matrix: include: # default - os: linux - - os: osx - - - os: osx - osx_image: xcode7.3 - compiler: clang - - os: osx - osx_image: xcode8.3 - compiler: clang +# - os: osx +# +# - os: osx +# osx_image: xcode7.3 +# compiler: clang +# - os: osx +# osx_image: xcode8.3 +# compiler: clang # gcc - os: linux From f0f87a52d7761b90c642f9707253141dc21a186f Mon Sep 17 00:00:00 2001 From: Lucas Abel Date: Sun, 22 Jul 2018 20:28:07 +0200 Subject: [PATCH 6/6] Update Makefile --- Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile b/Makefile index cab494c..a87dd6f 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ .SILENT: .DEFAULT_GOAL := all -.PHONY: clean conf debug dev fclean install re reconf san +.PHONY: clean conf debug dev fclean install re reconf BUILD_TYPE ?= Release BUILD_DIR ?= build/$(BUILD_TYPE) @@ -93,9 +93,6 @@ reconf: mrproper conf debug dev: $(MAKE) BUILD_TYPE=Debug -san: - $(MAKE) BUILD_TYPE=San - clean: [ -d $(BUILD_PROJ_DIR) ] && find $(BUILD_PROJ_DIR) -name "*.o" -delete