diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..431400a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,97 @@ +name: CI + +on: [push, pull_request] + +jobs: + build: + name: ${{ matrix.target }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - target: amd64 + flags: -O3 -fomit-frame-pointer + - target: x86 + flags: -m32 -O3 -fomit-frame-pointer + steps: + - uses: actions/checkout@v3 + - name: Prepare + run: | + sudo apt-get update -q -y + sudo apt-get install -y gcc-multilib g++-multilib valgrind + - name: Build + working-directory: tests + run: make + - name: Test + working-directory: tests + run: make test-all + + build-qemu: + name: ${{ matrix.target }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - target: aarch64 + arch: aarch64 + steps: + - uses: actions/checkout@v3 + - uses: uraimo/run-on-arch-action@v2 + with: + arch: ${{ matrix.arch }} + distro: ubuntu_latest + install: | + apt-get update -q -y + apt-get install -q -y --no-install-recommends build-essential valgrind + env: | + target: ${{ matrix.target }} + run: | + cd tests + make + make test-all + + build-windows: + name: Windows (${{ matrix.arch }}) + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + arch: [amd64, x86] + steps: + - uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.arch }} + - uses: actions/checkout@v3 + - name: Build + working-directory: tests + run: | + cl /I .. testsuite.c + cl /I .. example.c + cl /I .. mt-example.c + cl /I .. simple.c + cl /I .. coro_timing.c + - name: Test + working-directory: tests + run: | + .\testsuite.exe + .\example.exe + .\mt-example.exe + .\simple.exe + .\coro_timing.exe + + sanitizers: + name: Linux full - thread, undefined, leak, address + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v3 + - name: Prepare + run: | + sudo apt-get update -q -y + sudo apt-get install -y gcc-multilib g++-multilib valgrind + - name: Build and run sanitizer tests + working-directory: tests + run: make test-linux-full diff --git a/tests/Makefile b/tests/Makefile index 2aad113..1167905 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -26,7 +26,7 @@ WASMTIME=wasmtime # OUTEXT=.exe # RUNNER= -all: testsuite example mt-example simple benchmark +all: testsuite example mt-example simple benchmark coro_timing test: testsuite $(RUNNER) ./testsuite$(OUTEXT) @@ -34,11 +34,12 @@ test: testsuite test-example: example $(RUNNER) ./example$(OUTEXT) -test-all: testsuite example mt-example simple +test-all: testsuite example mt-example simple coro_timing $(RUNNER) ./testsuite$(OUTEXT) $(RUNNER) ./example$(OUTEXT) $(RUNNER) ./mt-example$(OUTEXT) $(RUNNER) ./simple$(OUTEXT) + $(RUNNER) ./coro_timing$(OUTEXT) bench: benchmark ./benchmark$(OUTEXT) @@ -46,6 +47,9 @@ bench: benchmark testsuite: testsuite.c ../minicoro.h Makefile $(CC) testsuite.c -o testsuite $(EXTRA_CFLAGS) $(CFLAGS) +coro_timing: coro_timing.c ../minicoro.h Makefile + $(CC) coro_timing.c -o coro_timing $(EXTRA_CFLAGS) $(CFLAGS) + example: example.c ../minicoro.h Makefile $(CC) example.c -o example $(EXTRA_CFLAGS) $(CFLAGS) @@ -59,7 +63,7 @@ benchmark: benchmark.c ../minicoro.h Makefile $(CC) benchmark.c -o benchmark $(EXTRA_CFLAGS) $(CFLAGS) $(RELEASE_CFLAGS) -std=c99 clean: - rm -f testsuite$(OUTEXT) example$(OUTEXT) mt-example$(OUTEXT) simple$(OUTEXT) benchmark$(OUTEXT) + rm -f testsuite$(OUTEXT) example$(OUTEXT) mt-example$(OUTEXT) simple$(OUTEXT) benchmark$(OUTEXT) coro_timing$(OUTEXT) test-riscv64: $(MAKE) --no-print-directory CC=riscv64-elf-gcc CFLAGS="-march=rv64gc -mabi=lp64d" RUNNER=qemu-riscv64 clean test test-example diff --git a/tests/coro_timing.c b/tests/coro_timing.c new file mode 100644 index 0000000..f6b7f1e --- /dev/null +++ b/tests/coro_timing.c @@ -0,0 +1,65 @@ +#define MINICORO_IMPL +#define MCO_NO_DEBUG 1 +#include "minicoro.h" +#include +#include +#include +#include + +enum +{ + Iterations = 500000000 +}; + +static int counter; + +void co_timingtest(mco_coro *co) +{ + for (;;) + { + counter++; + mco_yield(co); + } +} + +void sub_timingtest() +{ + counter++; +} + +int main() +{ + printf("context-switching timing test\n\n"); + time_t start, end; + mco_coro *thread_y; + int i, t1, t2; + + start = clock(); + for (counter = 0, i = 0; i < Iterations; i++) + { + sub_timingtest(); + } + end = clock(); + + t1 = (int)difftime(end, start); + printf("%2.3f seconds per 50 million subroutine calls (%d iterations)\n", (float)t1 / CLOCKS_PER_SEC, counter); + + mco_desc desc = mco_desc_init(co_timingtest, 0); + desc.user_data = NULL; + mco_create(&thread_y, &desc); + mco_resume(thread_y); + start = clock(); + for (counter = 0, i = 0; i < Iterations; i++) + { + mco_resume(thread_y); + } + end = clock(); + + mco_destroy(thread_y); + + t2 = (int)difftime(end, start); + printf("%2.3f seconds per 100 million mco_resume calls (%d iterations)\n", (float)t2 / CLOCKS_PER_SEC, counter); + + printf("mco_resume skew = %fx\n\n", (double)t2 / (double)t1); + return 0; +}