Changeset c76bd34
- Timestamp:
- Oct 7, 2020, 4:31:43 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 848439f
- Parents:
- ae2c27a (diff), 597c5d18 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Files:
-
- 54 added
- 3 deleted
- 168 edited
- 121 moved
-
.gitignore (modified) (1 diff)
-
Jenkinsfile (modified) (2 diffs)
-
benchmark/Makefile.am (modified) (12 diffs)
-
benchmark/creation/JavaThread.java (modified) (3 diffs)
-
benchmark/ctxswitch/JavaThread.java (modified) (2 diffs)
-
benchmark/io/http/filecache.cfa (modified) (7 diffs)
-
benchmark/io/http/main.cfa (modified) (5 diffs)
-
benchmark/io/http/options.cfa (modified) (5 diffs)
-
benchmark/io/http/options.hfa (modified) (2 diffs)
-
benchmark/io/http/protocol.cfa (modified) (6 diffs)
-
benchmark/io/http/worker.cfa (modified) (3 diffs)
-
benchmark/io/http/worker.hfa (modified) (3 diffs)
-
benchmark/io/readv.cfa (modified) (2 diffs)
-
benchmark/mutex/JavaThread.java (modified) (3 diffs)
-
benchmark/mutexC/JavaThread.java (modified) (4 diffs)
-
benchmark/readyQ/yield.cfa (modified) (2 diffs)
-
benchmark/schedint/JavaThread.java (modified) (2 diffs)
-
doc/LaTeXmacros/common.tex (modified) (4 diffs)
-
doc/LaTeXmacros/lstlang.sty (modified) (3 diffs)
-
doc/bibliography/pl.bib (modified) (2 diffs)
-
doc/papers/concurrency/Paper.tex (modified) (19 diffs)
-
doc/papers/concurrency/annex/local.bib (modified) (1 diff)
-
doc/papers/concurrency/mail2 (modified) (1 diff)
-
doc/papers/concurrency/response3 (added)
-
doc/proposals/ZeroCostPreemption.md (added)
-
doc/proposals/function_type_change.md (added)
-
doc/refrat/refrat.tex (modified) (3 diffs)
-
doc/theses/andrew_beach_MMath/glossaries.tex (added)
-
doc/theses/andrew_beach_MMath/thesis.tex (modified) (1 diff)
-
doc/theses/fangren_yu_COOP_S20/Makefile (added)
-
doc/theses/fangren_yu_COOP_S20/Report.tex (added)
-
doc/theses/fangren_yu_COOP_S20/cfa_developer_reference.pdf (added)
-
doc/theses/fangren_yu_COOP_S20/figures/DeepNodeSharing.fig (added)
-
doc/theses/fangren_yu_COOP_S20/figures/DeepNodeSharing.fig.bak (added)
-
doc/theses/thierry_delisle_PhD/.gitignore (modified) (1 diff)
-
doc/theses/thierry_delisle_PhD/code/readQ_example/Makefile (added)
-
doc/theses/thierry_delisle_PhD/code/readQ_example/proto-gui/main.cpp (added)
-
doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/Makefile (added)
-
doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/cforall.cpp (added)
-
doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/fibre.cpp (added)
-
doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.cpp (added)
-
doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.cpp (added)
-
doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.hpp (added)
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/Makefile (moved) (moved from doc/theses/thierry_delisle_PhD/code/Makefile )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/assert.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/assert.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/bitbench/select.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/bitbench/select.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/bts.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/bts.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/bts_test.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/bts_test.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/links.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/links.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/prefetch.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/prefetch.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/process.sh (moved) (moved from doc/theses/thierry_delisle_PhD/code/process.sh )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/processor.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/processor.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/processor_list.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/processor_list.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/processor_list_fast.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/processor_list_fast.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/processor_list_good.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/processor_list_good.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/randbit.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/randbit.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/relaxed_list.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/relaxed_list.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/relaxed_list.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/relaxed_list_layout.cpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/relaxed_list_layout.cpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/runperf.sh (moved) (moved from doc/theses/thierry_delisle_PhD/code/runperf.sh )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/scale.sh (moved) (moved from doc/theses/thierry_delisle_PhD/code/scale.sh )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/snzi-packed.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/snzi-packed.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/snzi.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/snzi.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/snzm.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/snzm.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/utils.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/utils.hpp )
-
doc/theses/thierry_delisle_PhD/code/readyQ_proto/work_stealing.hpp (moved) (moved from doc/theses/thierry_delisle_PhD/code/work_stealing.hpp )
-
doc/theses/thierry_delisle_PhD/comp_II/comp_II.tex (modified) (25 diffs)
-
doc/theses/thierry_delisle_PhD/comp_II/img/system.fig (modified) (4 diffs)
-
doc/theses/thierry_delisle_PhD/comp_II/presentation.pdf (deleted)
-
doc/theses/thierry_delisle_PhD/thesis/Makefile (added)
-
doc/theses/thierry_delisle_PhD/thesis/fig/base.fig (added)
-
doc/theses/thierry_delisle_PhD/thesis/fig/empty.fig (added)
-
doc/theses/thierry_delisle_PhD/thesis/fig/emptybit.fig (added)
-
doc/theses/thierry_delisle_PhD/thesis/fig/emptytls.fig (added)
-
doc/theses/thierry_delisle_PhD/thesis/fig/emptytree.fig (added)
-
doc/theses/thierry_delisle_PhD/thesis/fig/resize.fig (added)
-
doc/theses/thierry_delisle_PhD/thesis/fig/system.fig (added)
-
doc/theses/thierry_delisle_PhD/thesis/glossary.tex (added)
-
doc/theses/thierry_delisle_PhD/thesis/text/core.tex (added)
-
doc/theses/thierry_delisle_PhD/thesis/text/front.tex (added)
-
doc/theses/thierry_delisle_PhD/thesis/text/intro.tex (added)
-
doc/theses/thierry_delisle_PhD/thesis/text/io.tex (added)
-
doc/theses/thierry_delisle_PhD/thesis/text/practice.tex (added)
-
doc/theses/thierry_delisle_PhD/thesis/text/runtime.tex (added)
-
doc/theses/thierry_delisle_PhD/thesis/thesis.tex (added)
-
doc/user/Makefile (modified) (1 diff)
-
doc/user/user.tex (modified) (17 diffs)
-
examples/constructors.c (deleted)
-
libcfa/configure.ac (modified) (4 diffs)
-
libcfa/prelude/defines.hfa.in (modified) (3 diffs)
-
libcfa/src/Makefile.am (modified) (4 diffs)
-
libcfa/src/bits/locks.hfa (modified) (6 diffs)
-
libcfa/src/concurrency/CtxSwitch-i386.S (modified) (3 diffs)
-
libcfa/src/concurrency/alarm.cfa (modified) (1 diff)
-
libcfa/src/concurrency/clib/cfathread.cfa (added)
-
libcfa/src/concurrency/clib/cfathread.h (added)
-
libcfa/src/concurrency/coroutine.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/coroutine.hfa (modified) (4 diffs)
-
libcfa/src/concurrency/exception.cfa (modified) (1 diff)
-
libcfa/src/concurrency/exception.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/invoke.h (modified) (4 diffs)
-
libcfa/src/concurrency/io.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/io/call.cfa.in (added)
-
libcfa/src/concurrency/io/setup.cfa (modified) (4 diffs)
-
libcfa/src/concurrency/io/types.hfa (modified) (3 diffs)
-
libcfa/src/concurrency/iofwd.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/kernel.cfa (modified) (14 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (3 diffs)
-
libcfa/src/concurrency/kernel/fwd.hfa (modified) (1 diff)
-
libcfa/src/concurrency/kernel/startup.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/kernel_private.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/monitor.cfa (modified) (15 diffs)
-
libcfa/src/concurrency/monitor.hfa (modified) (1 diff)
-
libcfa/src/concurrency/mutex.cfa (modified) (8 diffs)
-
libcfa/src/concurrency/preemption.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/thread.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/thread.hfa (modified) (2 diffs)
-
libcfa/src/exception.h (modified) (3 diffs)
-
libcfa/src/exception.hfa (modified) (2 diffs)
-
libcfa/src/heap.cfa (modified) (7 diffs)
-
libcfa/src/limits.cfa (modified) (2 diffs)
-
libcfa/src/limits.hfa (modified) (2 diffs)
-
libcfa/src/parseargs.cfa (modified) (1 diff)
-
src/AST/Convert.cpp (modified) (7 diffs)
-
src/AST/Decl.hpp (modified) (1 diff)
-
src/AST/ForallSubstitutor.hpp (modified) (2 diffs)
-
src/AST/Fwd.hpp (modified) (1 diff)
-
src/AST/GenericSubstitution.cpp (modified) (1 diff)
-
src/AST/Node.cpp (modified) (1 diff)
-
src/AST/Pass.hpp (modified) (6 diffs)
-
src/AST/Pass.impl.hpp (modified) (4 diffs)
-
src/AST/Pass.proto.hpp (modified) (2 diffs)
-
src/AST/Print.cpp (modified) (1 diff)
-
src/AST/SymbolTable.cpp (modified) (5 diffs)
-
src/AST/SymbolTable.hpp (modified) (1 diff)
-
src/AST/Type.cpp (modified) (6 diffs)
-
src/AST/Type.hpp (modified) (10 diffs)
-
src/AST/TypeSubstitution.cpp (modified) (1 diff)
-
src/AST/TypeSubstitution.hpp (modified) (1 diff)
-
src/Common/Examine.cc (added)
-
src/Common/Examine.h (added)
-
src/Common/Stats/ResolveTime.cc (added)
-
src/Common/Stats/ResolveTime.h (added)
-
src/Common/Stats/Stats.cc (modified) (2 diffs)
-
src/Common/module.mk (modified) (2 diffs)
-
src/Concurrency/Keywords.cc (modified) (17 diffs)
-
src/GenPoly/InstantiateGeneric.cc (modified) (2 diffs)
-
src/InitTweak/InitTweak.cc (modified) (1 diff)
-
src/Parser/lex.ll (modified) (3 diffs)
-
src/Parser/parser.yy (modified) (9 diffs)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (5 diffs)
-
src/ResolvExpr/ConversionCost.cc (modified) (2 diffs)
-
src/ResolvExpr/ConversionCost.h (modified) (1 diff)
-
src/ResolvExpr/CurrentObject.cc (modified) (5 diffs)
-
src/ResolvExpr/Resolver.cc (modified) (9 diffs)
-
src/ResolvExpr/SatisfyAssertions.cpp (modified) (1 diff)
-
src/ResolvExpr/SpecCost.cc (modified) (1 diff)
-
src/ResolvExpr/Unify.cc (modified) (12 diffs)
-
src/SymTab/Mangler.cc (modified) (2 diffs)
-
src/SymTab/Validate.cc (modified) (6 diffs)
-
src/Virtual/Tables.cc (added)
-
src/Virtual/Tables.h (added)
-
src/Virtual/module.mk (modified) (1 diff)
-
tests/.expect/array.txt (modified) (1 diff)
-
tests/.expect/cast.txt (modified) (1 diff)
-
tests/.expect/enum.txt (modified) (1 diff)
-
tests/.expect/expression.txt (modified) (1 diff)
-
tests/.expect/forall.txt (modified) (1 diff)
-
tests/.expect/heap.txt (modified) (1 diff)
-
tests/.expect/identFuncDeclarator.txt (modified) (1 diff)
-
tests/.expect/identParamDeclarator.txt (modified) (1 diff)
-
tests/.expect/labelledExit.txt (modified) (1 diff)
-
tests/.expect/limits.txt (modified) (1 diff)
-
tests/.expect/maybe.txt (modified) (1 diff)
-
tests/.expect/nested-types.txt (modified) (1 diff)
-
tests/.expect/numericConstants.txt (modified) (1 diff)
-
tests/.expect/operators.txt (modified) (1 diff)
-
tests/.expect/poly-d-cycle.txt (moved) (moved from tests/.expect/poly-cycle.txt )
-
tests/.expect/poly-o-cycle.txt (added)
-
tests/.expect/result.txt (modified) (1 diff)
-
tests/.expect/stdincludes.txt (modified) (1 diff)
-
tests/.expect/switch.txt (modified) (1 diff)
-
tests/.expect/typedefRedef-ERR1.txt (modified) (1 diff)
-
tests/.expect/typedefRedef.txt (modified) (1 diff)
-
tests/.expect/typeof.txt (modified) (1 diff)
-
tests/.expect/variableDeclarator.txt (modified) (1 diff)
-
tests/.expect/voidPtr.txt (modified) (1 diff)
-
tests/Makefile.am (modified) (7 diffs)
-
tests/alloc2.cfa (modified) (9 diffs)
-
tests/array.cfa (modified) (2 diffs)
-
tests/bugs/196.cfa (added)
-
tests/builtins/.expect/sync.txt (modified) (1 diff)
-
tests/builtins/sync.cfa (modified) (2 diffs)
-
tests/cast.cfa (modified) (1 diff)
-
tests/concurrent/.expect/clib.txt (added)
-
tests/concurrent/.expect/cluster.txt (modified) (1 diff)
-
tests/concurrent/.expect/join.txt (added)
-
tests/concurrent/.expect/joinerror.sed (moved) (moved from tests/.expect/smart-pointers.txt )
-
tests/concurrent/clib.c (added)
-
tests/concurrent/cluster.cfa (modified) (1 diff)
-
tests/concurrent/examples/.expect/datingService.txt (modified) (1 diff)
-
tests/concurrent/examples/datingService.cfa (modified) (2 diffs)
-
tests/concurrent/futures/.expect/basic.txt (modified) (1 diff)
-
tests/concurrent/futures/basic.cfa (modified) (1 diff)
-
tests/concurrent/join.cfa (added)
-
tests/concurrent/joinerror.cfa (added)
-
tests/concurrent/park/.expect/force_preempt.txt (modified) (1 diff)
-
tests/concurrent/park/.expect/start_parked.txt (modified) (1 diff)
-
tests/concurrent/park/contention.cfa (modified) (2 diffs)
-
tests/concurrent/park/force_preempt.cfa (modified) (3 diffs)
-
tests/concurrent/park/start_parked.cfa (modified) (1 diff)
-
tests/enum.cfa (modified) (1 diff)
-
tests/exceptions/.expect/virtual-cast.txt (modified) (1 diff)
-
tests/exceptions/.expect/virtual-poly.txt (modified) (1 diff)
-
tests/exceptions/cancel/.expect/coroutine.txt (added)
-
tests/exceptions/cancel/coroutine.cfa (added)
-
tests/exceptions/virtual-cast.cfa (modified) (1 diff)
-
tests/exceptions/virtual-poly.cfa (modified) (1 diff)
-
tests/expression.cfa (modified) (1 diff)
-
tests/forall.cfa (modified) (3 diffs)
-
tests/heap.cfa (modified) (4 diffs)
-
tests/identFuncDeclarator.cfa (modified) (2 diffs)
-
tests/identParamDeclarator.cfa (modified) (2 diffs)
-
tests/labelledExit.cfa (modified) (2 diffs)
-
tests/limits.cfa (modified) (2 diffs)
-
tests/maybe.cfa (modified) (2 diffs)
-
tests/nested-types.cfa (modified) (2 diffs)
-
tests/numericConstants.cfa (modified) (2 diffs)
-
tests/operators.cfa (modified) (1 diff)
-
tests/poly-d-cycle.cfa (added)
-
tests/poly-o-cycle.cfa (moved) (moved from tests/poly-cycle.cfa ) (1 diff)
-
tests/pybin/tools.py (modified) (2 diffs)
-
tests/raii/.expect/ctor-autogen.txt (modified) (1 diff)
-
tests/raii/.expect/init_once.txt (modified) (1 diff)
-
tests/raii/ctor-autogen.cfa (modified) (1 diff)
-
tests/raii/init_once.cfa (modified) (2 diffs)
-
tests/result.cfa (modified) (2 diffs)
-
tests/stdincludes.cfa (modified) (2 diffs)
-
tests/switch.cfa (modified) (2 diffs)
-
tests/test.py (modified) (4 diffs)
-
tests/typedefRedef.cfa (modified) (2 diffs)
-
tests/typeof.cfa (modified) (1 diff)
-
tests/variableDeclarator.cfa (modified) (8 diffs)
-
tests/voidPtr.cfa (modified) (1 diff)
-
tests/warnings/.expect/self-assignment.txt (modified) (1 diff)
-
tests/warnings/self-assignment.cfa (modified) (2 diffs)
-
tests/zombies/ArrayN.c (moved) (moved from examples/ArrayN.c )
-
tests/zombies/Initialization.c (moved) (moved from examples/Initialization.c )
-
tests/zombies/Initialization2.c (moved) (moved from examples/Initialization2.c )
-
tests/zombies/Makefile.example (moved) (moved from examples/Makefile.example )
-
tests/zombies/Members.c (moved) (moved from examples/Members.c )
-
tests/zombies/Misc.c (moved) (moved from examples/Misc.c )
-
tests/zombies/MiscError.c (moved) (moved from examples/MiscError.c )
-
tests/zombies/Rank2.c (moved) (moved from examples/Rank2.c ) (2 diffs)
-
tests/zombies/Tuple.c (moved) (moved from examples/Tuple.c ) (3 diffs)
-
tests/zombies/abstype.c (moved) (moved from examples/abstype.c ) (2 diffs)
-
tests/zombies/constructors.c (added)
-
tests/zombies/forward.c (moved) (moved from examples/forward.c )
-
tests/zombies/gc_no_raii/.gitignore (moved) (moved from examples/gc_no_raii/.gitignore )
-
tests/zombies/gc_no_raii/bug-repro/assert.c (moved) (moved from examples/gc_no_raii/bug-repro/assert.c )
-
tests/zombies/gc_no_raii/bug-repro/blockers.tar.gz (moved) (moved from examples/gc_no_raii/bug-repro/blockers.tar.gz )
-
tests/zombies/gc_no_raii/bug-repro/blockers/explicit_cast.c (moved) (moved from examples/gc_no_raii/bug-repro/blockers/explicit_cast.c )
-
tests/zombies/gc_no_raii/bug-repro/blockers/file_scope.c (moved) (moved from examples/gc_no_raii/bug-repro/blockers/file_scope.c )
-
tests/zombies/gc_no_raii/bug-repro/blockers/recursive_realloc.c (moved) (moved from examples/gc_no_raii/bug-repro/blockers/recursive_realloc.c )
-
tests/zombies/gc_no_raii/bug-repro/crash.c (moved) (moved from examples/gc_no_raii/bug-repro/crash.c )
-
tests/zombies/gc_no_raii/bug-repro/deref.c (moved) (moved from examples/gc_no_raii/bug-repro/deref.c )
-
tests/zombies/gc_no_raii/bug-repro/field.c (moved) (moved from examples/gc_no_raii/bug-repro/field.c )
-
tests/zombies/gc_no_raii/bug-repro/find.c (moved) (moved from examples/gc_no_raii/bug-repro/find.c )
-
tests/zombies/gc_no_raii/bug-repro/inline.c (moved) (moved from examples/gc_no_raii/bug-repro/inline.c )
-
tests/zombies/gc_no_raii/bug-repro/malloc.c (moved) (moved from examples/gc_no_raii/bug-repro/malloc.c )
-
tests/zombies/gc_no_raii/bug-repro/not_equal.c (moved) (moved from examples/gc_no_raii/bug-repro/not_equal.c )
-
tests/zombies/gc_no_raii/bug-repro/oddtype.c (moved) (moved from examples/gc_no_raii/bug-repro/oddtype.c )
-
tests/zombies/gc_no_raii/bug-repro/push_back.c (moved) (moved from examples/gc_no_raii/bug-repro/push_back.c )
-
tests/zombies/gc_no_raii/bug-repro/push_back.h (moved) (moved from examples/gc_no_raii/bug-repro/push_back.h )
-
tests/zombies/gc_no_raii/bug-repro/realloc.c (moved) (moved from examples/gc_no_raii/bug-repro/realloc.c )
-
tests/zombies/gc_no_raii/bug-repro/return.c (moved) (moved from examples/gc_no_raii/bug-repro/return.c )
-
tests/zombies/gc_no_raii/bug-repro/return_template.c (moved) (moved from examples/gc_no_raii/bug-repro/return_template.c )
-
tests/zombies/gc_no_raii/bug-repro/slow_malloc.c (moved) (moved from examples/gc_no_raii/bug-repro/slow_malloc.c )
-
tests/zombies/gc_no_raii/bug-repro/static_const_local.c (moved) (moved from examples/gc_no_raii/bug-repro/static_const_local.c )
-
tests/zombies/gc_no_raii/bug-repro/test-assert.cpp (moved) (moved from examples/gc_no_raii/bug-repro/test-assert.cpp )
-
tests/zombies/gc_no_raii/bug-repro/void_pointer.c (moved) (moved from examples/gc_no_raii/bug-repro/void_pointer.c )
-
tests/zombies/gc_no_raii/bug-repro/while.c (moved) (moved from examples/gc_no_raii/bug-repro/while.c )
-
tests/zombies/gc_no_raii/bug-repro/zero.c (moved) (moved from examples/gc_no_raii/bug-repro/zero.c )
-
tests/zombies/gc_no_raii/pool-alloc/allocate-malign.c (moved) (moved from examples/gc_no_raii/pool-alloc/allocate-malign.c )
-
tests/zombies/gc_no_raii/pool-alloc/allocate-malloc.c (moved) (moved from examples/gc_no_raii/pool-alloc/allocate-malloc.c )
-
tests/zombies/gc_no_raii/pool-alloc/allocate-mmap.c (moved) (moved from examples/gc_no_raii/pool-alloc/allocate-mmap.c )
-
tests/zombies/gc_no_raii/pool-alloc/allocate-win-valloc.c (moved) (moved from examples/gc_no_raii/pool-alloc/allocate-win-valloc.c )
-
tests/zombies/gc_no_raii/premake4.lua (moved) (moved from examples/gc_no_raii/premake4.lua )
-
tests/zombies/gc_no_raii/src/allocate-pool.c (moved) (moved from examples/gc_no_raii/src/allocate-pool.c )
-
tests/zombies/gc_no_raii/src/allocate-pool.h (moved) (moved from examples/gc_no_raii/src/allocate-pool.h )
-
tests/zombies/gc_no_raii/src/gc.h (moved) (moved from examples/gc_no_raii/src/gc.h )
-
tests/zombies/gc_no_raii/src/gcpointers.c (moved) (moved from examples/gc_no_raii/src/gcpointers.c )
-
tests/zombies/gc_no_raii/src/gcpointers.h (moved) (moved from examples/gc_no_raii/src/gcpointers.h )
-
tests/zombies/gc_no_raii/src/internal/card_table.h (moved) (moved from examples/gc_no_raii/src/internal/card_table.h )
-
tests/zombies/gc_no_raii/src/internal/collector.c (moved) (moved from examples/gc_no_raii/src/internal/collector.c )
-
tests/zombies/gc_no_raii/src/internal/collector.h (moved) (moved from examples/gc_no_raii/src/internal/collector.h )
-
tests/zombies/gc_no_raii/src/internal/gc_tools.h (moved) (moved from examples/gc_no_raii/src/internal/gc_tools.h )
-
tests/zombies/gc_no_raii/src/internal/globals.h (moved) (moved from examples/gc_no_raii/src/internal/globals.h )
-
tests/zombies/gc_no_raii/src/internal/memory_pool.c (moved) (moved from examples/gc_no_raii/src/internal/memory_pool.c )
-
tests/zombies/gc_no_raii/src/internal/memory_pool.h (moved) (moved from examples/gc_no_raii/src/internal/memory_pool.h )
-
tests/zombies/gc_no_raii/src/internal/object_header.c (moved) (moved from examples/gc_no_raii/src/internal/object_header.c )
-
tests/zombies/gc_no_raii/src/internal/object_header.h (moved) (moved from examples/gc_no_raii/src/internal/object_header.h )
-
tests/zombies/gc_no_raii/src/internal/state.c (moved) (moved from examples/gc_no_raii/src/internal/state.c )
-
tests/zombies/gc_no_raii/src/internal/state.h (moved) (moved from examples/gc_no_raii/src/internal/state.h )
-
tests/zombies/gc_no_raii/src/test_include.c (moved) (moved from examples/gc_no_raii/src/test_include.c )
-
tests/zombies/gc_no_raii/src/tools.h (moved) (moved from examples/gc_no_raii/src/tools.h )
-
tests/zombies/gc_no_raii/src/tools/checks.h (moved) (moved from examples/gc_no_raii/src/tools/checks.h )
-
tests/zombies/gc_no_raii/src/tools/print.c (moved) (moved from examples/gc_no_raii/src/tools/print.c )
-
tests/zombies/gc_no_raii/src/tools/print.h (moved) (moved from examples/gc_no_raii/src/tools/print.h )
-
tests/zombies/gc_no_raii/src/tools/worklist.h (moved) (moved from examples/gc_no_raii/src/tools/worklist.h )
-
tests/zombies/gc_no_raii/test/badlll.c (moved) (moved from examples/gc_no_raii/test/badlll.c )
-
tests/zombies/gc_no_raii/test/gctest.c (moved) (moved from examples/gc_no_raii/test/gctest.c )
-
tests/zombies/gc_no_raii/test/operators.c (moved) (moved from examples/gc_no_raii/test/operators.c )
-
tests/zombies/hashtable.cfa (moved) (moved from examples/hashtable.cfa )
-
tests/zombies/hashtable2.cfa (moved) (moved from examples/hashtable2.cfa )
-
tests/zombies/huge.c (moved) (moved from examples/huge.c )
-
tests/zombies/includes.c (moved) (moved from examples/includes.c ) (4 diffs)
-
tests/zombies/index.h (moved) (moved from examples/index.h )
-
tests/zombies/io/cat.c (moved) (moved from examples/io/cat.c )
-
tests/zombies/io/filereader.c (moved) (moved from examples/io/filereader.c )
-
tests/zombies/io/simple/client.c (moved) (moved from examples/io/simple/client.c )
-
tests/zombies/io/simple/server.c (moved) (moved from examples/io/simple/server.c )
-
tests/zombies/io/simple/server.cfa (moved) (moved from examples/io/simple/server.cfa )
-
tests/zombies/io/simple/server_epoll.c (moved) (moved from examples/io/simple/server_epoll.c )
-
tests/zombies/io_uring.txt (moved) (moved from examples/io_uring.txt )
-
tests/zombies/it_out.c (moved) (moved from examples/it_out.c )
-
tests/zombies/multicore.c (moved) (moved from examples/multicore.c )
-
tests/zombies/new.c (moved) (moved from examples/new.c )
-
tests/zombies/poly-bench.c (moved) (moved from examples/poly-bench.c )
-
tests/zombies/prolog.c (moved) (moved from examples/prolog.c )
-
tests/zombies/quad.c (moved) (moved from examples/quad.c )
-
tests/zombies/s.c (moved) (moved from examples/s.c )
-
tests/zombies/simplePoly.c (moved) (moved from examples/simplePoly.c )
-
tests/zombies/simpler.c (moved) (moved from examples/simpler.c )
-
tests/zombies/specialize.c (moved) (moved from examples/specialize.c )
-
tests/zombies/square.c (moved) (moved from examples/square.c )
-
tests/zombies/structMember.cfa (modified) (2 diffs)
-
tests/zombies/twice.c (moved) (moved from examples/twice.c )
-
tests/zombies/wrapper/.gitignore (moved) (moved from examples/wrapper/.gitignore )
-
tests/zombies/wrapper/premake4.lua (moved) (moved from examples/wrapper/premake4.lua )
-
tests/zombies/wrapper/src/main.c (moved) (moved from examples/wrapper/src/main.c )
-
tests/zombies/wrapper/src/pointer.h (moved) (moved from examples/wrapper/src/pointer.h )
-
tests/zombies/zero_one.c (moved) (moved from examples/zero_one.c )
-
tools/gdb/utils-gdb.py (modified) (7 diffs)
-
tools/langserver/cfa-ls (deleted)
-
tools/vscode/uwaterloo.cforall-0.1.0/.gitignore (added)
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
rae2c27a rc76bd34 79 79 doc/user/pointer2.tex 80 80 doc/user/EHMHierarchy.tex 81 82 # generated by npm 83 package-lock.json -
Jenkinsfile
rae2c27a rc76bd34 102 102 103 103 echo GitLogMessage() 104 105 // This is a complete hack but it solves problems with automake thinking it needs to regenerate makefiles106 // We fudged automake/missing to handle that but automake stills bakes prints inside the makefiles107 // and these cause more problems.108 sh 'find . -name Makefile.in -exec touch {} +'109 104 } 110 105 } … … 465 460 description: 'Which compiler to use', \ 466 461 name: 'Compiler', \ 467 choices: 'gcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang', \462 choices: 'gcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang', \ 468 463 defaultValue: 'gcc-8', \ 469 464 ], \ -
benchmark/Makefile.am
rae2c27a rc76bd34 113 113 creation_cfa_generator_DURATION = 1000000000 114 114 creation_upp_coroutine_DURATION = ${creation_cfa_coroutine_eager_DURATION} 115 creation_cfa_thread_DURATION = 10000000116 creation_upp_thread_DURATION = ${creation_cfa_thread_DURATION}117 115 creation_DURATION = 10000000 118 116 … … 148 146 149 147 cleancsv: 150 rm -f compile.csv basic.csv ctxswitch.csv mutex.csv sched uling.csv148 rm -f compile.csv basic.csv ctxswitch.csv mutex.csv schedint.csv 151 149 152 150 jenkins$(EXEEXT): cleancsv … … 159 157 +make mutex.csv 160 158 -+make mutex.diff.csv 161 +make sched uling.csv162 -+make sched uling.diff.csv159 +make schedint.csv 160 -+make schedint.diff.csv 163 161 @DOifskipcompile@ 164 162 cat compile.csv … … 169 167 cat mutex.csv 170 168 -cat mutex.diff.csv 171 cat sched uling.csv172 -cat sched uling.diff.csv169 cat schedint.csv 170 -cat schedint.diff.csv 173 171 174 172 compile.csv: … … 200 198 $(srcdir)/fixcsv.sh $@ 201 199 202 sched uling.csv:200 schedint.csv: 203 201 echo "building $@" 204 202 echo "schedint-1,schedint-2,schedext-1,schedext-2" > $@ … … 291 289 ctxswitch-python_coroutine$(EXEEXT): 292 290 $(BENCH_V_PY)echo "#!/bin/sh" > a.out 293 echo "python3 .7 $(srcdir)/ctxswitch/python_cor.py" >> a.out291 echo "python3 $(srcdir)/ctxswitch/python_cor.py \"$$""@\"" >> a.out 294 292 chmod a+x a.out 295 293 296 294 ctxswitch-nodejs_coroutine$(EXEEXT): 297 295 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 298 echo "nodejs $(srcdir)/ctxswitch/node_cor.js " >> a.out296 echo "nodejs $(srcdir)/ctxswitch/node_cor.js \"$$""@\"" >> a.out 299 297 chmod a+x a.out 300 298 301 299 ctxswitch-nodejs_await$(EXEEXT): 302 300 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 303 echo "nodejs $(srcdir)/ctxswitch/node_await.js " >> a.out301 echo "nodejs $(srcdir)/ctxswitch/node_await.js \"$$""@\"" >> a.out 304 302 chmod a+x a.out 305 303 … … 313 311 $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/ctxswitch/JavaThread.java 314 312 echo "#!/bin/sh" > a.out 315 echo "java JavaThread " >> a.out313 echo "java JavaThread \"$$""@\"" >> a.out 316 314 chmod a+x a.out 317 315 … … 355 353 $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/mutex/JavaThread.java 356 354 echo "#!/bin/sh" > a.out 357 echo "java JavaThread " >> a.out355 echo "java JavaThread \"$$""@\"" >> a.out 358 356 chmod a+x a.out 359 357 … … 387 385 $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/schedint/JavaThread.java 388 386 echo "#!/bin/sh" > a.out 389 echo "java JavaThread " >> a.out387 echo "java JavaThread \"$$""@\"" >> a.out 390 388 chmod a+x a.out 391 389 … … 454 452 creation-python_coroutine$(EXEEXT): 455 453 $(BENCH_V_PY)echo "#!/bin/sh" > a.out 456 echo "python3 .7 $(srcdir)/creation/python_cor.py" >> a.out454 echo "python3 $(srcdir)/creation/python_cor.py \"$$""@\"" >> a.out 457 455 chmod a+x a.out 458 456 459 457 creation-nodejs_coroutine$(EXEEXT): 460 458 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 461 echo "nodejs $(srcdir)/creation/node_cor.js " >> a.out459 echo "nodejs $(srcdir)/creation/node_cor.js \"$$""@\"" >> a.out 462 460 chmod a+x a.out 463 461 … … 471 469 $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/creation/JavaThread.java 472 470 echo "#!/bin/sh" > a.out 473 echo "java JavaThread " >> a.out471 echo "java JavaThread \"$$""@\"" >> a.out 474 472 chmod a+x a.out 475 473 … … 492 490 493 491 compile-array$(EXEEXT): 494 $(CFACOMPILE) - fsyntax-only -w $(testdir)/array.cfa492 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/array.cfa 495 493 496 494 compile-attributes$(EXEEXT): 497 $(CFACOMPILE) - fsyntax-only -w $(testdir)/attributes.cfa495 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/attributes.cfa 498 496 499 497 compile-empty$(EXEEXT): 500 $(CFACOMPILE) - fsyntax-only -w $(srcdir)/compile/empty.cfa498 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(srcdir)/compile/empty.cfa 501 499 502 500 compile-expression$(EXEEXT): 503 $(CFACOMPILE) - fsyntax-only -w $(testdir)/expression.cfa501 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/expression.cfa 504 502 505 503 compile-io$(EXEEXT): 506 $(CFACOMPILE) - fsyntax-only -w $(testdir)/io1.cfa504 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/io1.cfa 507 505 508 506 compile-monitor$(EXEEXT): 509 $(CFACOMPILE) - fsyntax-only -w $(testdir)/concurrent/monitor.cfa507 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/monitor.cfa 510 508 511 509 compile-operators$(EXEEXT): 512 $(CFACOMPILE) - fsyntax-only -w $(testdir)/operators.cfa510 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/operators.cfa 513 511 514 512 compile-thread$(EXEEXT): 515 $(CFACOMPILE) - fsyntax-only -w $(testdir)/concurrent/thread.cfa513 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/thread.cfa 516 514 517 515 compile-typeof$(EXEEXT): 518 $(CFACOMPILE) - fsyntax-only -w $(testdir)/typeof.cfa516 $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/typeof.cfa 519 517 520 518 ## ========================================================================================================= -
benchmark/creation/JavaThread.java
rae2c27a rc76bd34 1 1 public class JavaThread { 2 2 // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator. 3 // Bijective 3 // Bijective 4 4 // Cycle length for non-zero values is 4G-1. 5 5 // 0 is absorbing and should be avoided -- fixed point. 6 6 // The returned value is typically masked to produce a positive value. 7 static volatile int Ticket = 0 ; 7 static volatile int Ticket = 0 ; 8 8 9 9 private static int nextRandom (int x) { 10 if (x == 0) { 10 if (x == 0) { 11 11 // reseed the PRNG 12 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 13 // Note that we use a non-atomic racy increment -- the race is rare and benign. 14 // If the race is a concern switch to an AtomicInteger. 15 // In addition accesses to the RW volatile global "Ticket" variable are not 16 // (readily) predictable at compile-time so the JIT will not be able to elide 17 // nextRandom() invocations. 18 x = ++Ticket ; 19 if (x == 0) x = 1 ; 12 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 13 // Note that we use a non-atomic racy increment -- the race is rare and benign. 14 // If the race is a concern switch to an AtomicInteger. 15 // In addition accesses to the RW volatile global "Ticket" variable are not 16 // (readily) predictable at compile-time so the JIT will not be able to elide 17 // nextRandom() invocations. 18 x = ++Ticket ; 19 if (x == 0) x = 1 ; 20 20 } 21 21 x ^= x << 6; 22 22 x ^= x >>> 21; 23 23 x ^= x << 7; 24 return x ; 24 return x ; 25 25 } 26 26 static int x = 2; 27 27 28 static private int times = Integer.parseInt("10000") ;28 static private long times = Long.parseLong("10000") ; 29 29 30 30 public static class MyThread extends Thread { … … 33 33 } 34 34 public static void helper() throws InterruptedException { 35 for( inti = 1; i <= times; i += 1) {35 for(long i = 1; i <= times; i += 1) { 36 36 MyThread m = new MyThread(); 37 37 x = nextRandom( x ); … … 47 47 } 48 48 public static void main(String[] args) throws InterruptedException { 49 if ( args.length > 2) System.exit( 1 );50 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }49 if ( args.length > 1 ) System.exit( 1 ); 50 if ( args.length == 1 ) { times = Long.parseLong(args[0]); } 51 51 52 for (int i = Integer.parseInt("5"); --i >= 0 ; ) { 52 for (int i = Integer.parseInt("5"); --i >= 0 ; ) { 53 53 InnerMain(); 54 54 Thread.sleep(2000); // 2 seconds -
benchmark/ctxswitch/JavaThread.java
rae2c27a rc76bd34 1 1 public class JavaThread { 2 2 // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator. 3 // Bijective 3 // Bijective 4 4 // Cycle length for non-zero values is 4G-1. 5 5 // 0 is absorbing and should be avoided -- fixed point. 6 6 // The returned value is typically masked to produce a positive value. 7 static volatile int Ticket = 0 ; 7 static volatile int Ticket = 0 ; 8 8 9 9 private static int nextRandom (int x) { 10 if (x == 0) { 10 if (x == 0) { 11 11 // reseed the PRNG 12 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 13 // Note that we use a non-atomic racy increment -- the race is rare and benign. 14 // If the race is a concern switch to an AtomicInteger. 15 // In addition accesses to the RW volatile global "Ticket" variable are not 16 // (readily) predictable at compile-time so the JIT will not be able to elide 17 // nextRandom() invocations. 18 x = ++Ticket ; 19 if (x == 0) x = 1 ; 12 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 13 // Note that we use a non-atomic racy increment -- the race is rare and benign. 14 // If the race is a concern switch to an AtomicInteger. 15 // In addition accesses to the RW volatile global "Ticket" variable are not 16 // (readily) predictable at compile-time so the JIT will not be able to elide 17 // nextRandom() invocations. 18 x = ++Ticket ; 19 if (x == 0) x = 1 ; 20 20 } 21 21 x ^= x << 6; 22 22 x ^= x >>> 21; 23 23 x ^= x << 7; 24 return x ; 24 return x ; 25 25 } 26 26 static int x = 2; 27 27 28 static private int times = Integer.parseInt("100000");28 static private long times = Long.parseLong("100000"); 29 29 30 30 public static void helper() { 31 for( inti = 1; i <= times; i += 1) {31 for(long i = 1; i <= times; i += 1) { 32 32 Thread.yield(); 33 33 } … … 40 40 } 41 41 public static void main(String[] args) throws InterruptedException { 42 if ( args.length > 2) System.exit( 1 );43 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }42 if ( args.length > 1 ) System.exit( 1 ); 43 if ( args.length == 1 ) { times = Long.parseLong(args[0]); } 44 44 45 45 for (int i = Integer.parseInt("5"); --i >= 0 ; ) { -
benchmark/io/http/filecache.cfa
rae2c27a rc76bd34 73 73 cache_line * entries; 74 74 size_t size; 75 int * rawfds; 76 int nfds; 75 77 } file_cache; 76 78 … … 98 100 } 99 101 100 int put_file( cache_line & entry ) {102 int put_file( cache_line & entry, int fd ) { 101 103 uint32_t idx = murmur3_32( (const uint8_t *)entry.file, strlen(entry.file), options.file_cache.hash_seed ) % file_cache.size; 102 104 … … 108 110 109 111 file_cache.entries[idx] = entry; 112 file_cache.entries[idx].fd = fd; 110 113 return i > 0 ? 1 : 0; 111 114 } … … 121 124 size_t fcount = 0; 122 125 size_t fsize = 16; 123 cache_line * raw = 0p; 124 raw = alloc(raw, fsize, true); 126 cache_line * raw = alloc(fsize); 125 127 // Step 1 get a dense array of all files 126 128 int walk(const char *fpath, const struct stat *sb, int typeflag) { … … 131 133 if(fcount > fsize) { 132 134 fsize *= 2; 133 raw = alloc( raw, fsize, true);135 raw = alloc(fsize, raw`realloc); 134 136 } 135 137 … … 162 164 file_cache.entries = anew(file_cache.size); 163 165 166 if(options.file_cache.fixed_fds) { 167 file_cache.nfds = fcount; 168 file_cache.rawfds = alloc(fcount); 169 } 170 164 171 // Step 3 fill the cache 165 172 int conflicts = 0; 166 173 for(i; fcount) { 167 conflicts += put_file( raw[i] ); 174 int fd; 175 if(options.file_cache.fixed_fds) { 176 file_cache.rawfds[i] = raw[i].fd; 177 fd = i; 178 } 179 else { 180 fd = raw[i].fd; 181 } 182 conflicts += put_file( raw[i], fd ); 168 183 } 169 184 printf("Filled cache from path \"%s\" with %zu files\n", path, fcount); … … 197 212 } 198 213 199 return [aalloc(extra), 0]; 214 size_t s = file_cache.nfds + extra; 215 int * data = alloc(s, file_cache.rawfds`realloc); 216 return [data, file_cache.nfds]; 200 217 } 201 218 -
benchmark/io/http/main.cfa
rae2c27a rc76bd34 12 12 #include <kernel.hfa> 13 13 #include <stats.hfa> 14 #include <time.hfa> 14 15 #include <thread.hfa> 15 16 16 #include "channel.hfa"17 17 #include "filecache.hfa" 18 18 #include "options.hfa" 19 19 #include "worker.hfa" 20 20 21 extern void register_fixed_files( cluster &, int *, unsigned count ); 22 23 Duration default_preemption() { 24 return 0; 25 } 26 21 27 //============================================================================================= 22 28 // Globals 23 29 //============================================================================================= 24 channel & wait_connect;25 26 30 struct ServerProc { 27 31 processor self; … … 84 88 // Run Server Cluster 85 89 { 86 cluster cl = { "Server Cluster", options.clopts. flags };90 cluster cl = { "Server Cluster", options.clopts.params }; 87 91 #if !defined(__CFA_NO_STATISTICS__) 88 92 print_stats_at_exit( cl, CFA_STATS_READY_Q | CFA_STATS_IO ); 89 93 #endif 90 94 options.clopts.instance = &cl; 91 92 channel chan = { options.clopts.chan_size };93 &wait_connect = &chan;94 95 95 96 int pipe_cnt = options.clopts.nworkers * 2; … … 102 103 } 103 104 105 if(options.file_cache.fixed_fds) { 106 register_fixed_files(cl, fds, pipe_off); 107 } 108 104 109 { 105 110 ServerProc procs[options.clopts.nprocs]; … … 107 112 Worker workers[options.clopts.nworkers]; 108 113 for(i; options.clopts.nworkers) { 109 if( options.file_cache.fixed_fds ) { 110 workers[i].pipe[0] = pipe_off + (i * 2) + 0; 111 workers[i].pipe[1] = pipe_off + (i * 2) + 1; 112 } 113 else { 114 // if( options.file_cache.fixed_fds ) { 115 // workers[i].pipe[0] = pipe_off + (i * 2) + 0; 116 // workers[i].pipe[1] = pipe_off + (i * 2) + 1; 117 // } 118 // else 119 { 114 120 workers[i].pipe[0] = fds[pipe_off + (i * 2) + 0]; 115 121 workers[i].pipe[1] = fds[pipe_off + (i * 2) + 1]; 122 workers[i].sockfd = server_fd; 123 workers[i].addr = (struct sockaddr *)&address; 124 workers[i].addrlen = (socklen_t*)&addrlen; 125 workers[i].flags = 0; 116 126 } 117 unpark( workers[i] __cfaabi_dbg_ctx2);127 unpark( workers[i] ); 118 128 } 119 129 printf("%d workers started on %d processors\n", options.clopts.nworkers, options.clopts.nprocs); 120 130 { 121 Acceptor acceptor = { server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen, 0 };122 123 131 char buffer[128]; 124 132 while(!feof(stdin)) { … … 127 135 128 136 printf("Shutting Down\n"); 129 }130 printf("Acceptor Closed\n");131 132 // Clean-up the workers133 for(options.clopts.nworkers) {134 put( wait_connect, -1 );135 137 } 136 138 } -
benchmark/io/http/options.cfa
rae2c27a rc76bd34 31 31 1, // nworkers; 32 32 0, // flags; 33 10, // chan_size;34 33 false, // procstats 35 34 false, // viewhalts … … 39 38 40 39 const char * parse_options( int argc, char * argv[] ) { 41 bool uthrdpo = false;42 40 bool subthrd = false; 43 41 bool eagrsub = false; … … 52 50 {'t', "threads", "Number of worker threads to use", options.clopts.nworkers}, 53 51 {'b', "accept-backlog", "Maximum number of pending accepts", options.socket.backlog}, 54 {'B', "channel-size", "Maximum number of accepted connection pending", options.clopts.chan_size},55 52 {'r', "request_len", "Maximum number of bytes in the http request, requests with more data will be answered with Http Code 414", options.socket.buflen}, 56 53 {'S', "seed", "seed to use for hashing", options.file_cache.hash_seed }, 57 54 {'C', "cache-size", "Size of the cache to use, if set to small, will uses closes power of 2", options.file_cache.size }, 58 55 {'l', "list-files", "List the files in the specified path and exit", options.file_cache.list, parse_settrue }, 59 {'u', "userthread", "If set, cluster uses user-thread to poll I/O", uthrdpo, parse_settrue },60 56 {'s', "submitthread", "If set, cluster uses polling thread to submit I/O", subthrd, parse_settrue }, 61 57 {'e', "eagersubmit", "If set, cluster submits I/O eagerly but still aggregates submits", eagrsub, parse_settrue}, … … 71 67 parse_args( argc, argv, opt, opt_cnt, "[OPTIONS]... [PATH]\ncforall http server", left ); 72 68 73 if( uthrdpo ) { 74 options.clopts.flags |= CFA_CLUSTER_IO_POLLER_USER_THREAD; 75 } 76 77 if( subthrd ) { 78 options.clopts.flags |= CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS; 79 } 80 81 if( eagrsub ) { 82 options.clopts.flags |= CFA_CLUSTER_IO_EAGER_SUBMITS; 83 } 69 options.clopts.params.poller_submits = subthrd; 70 options.clopts.params.eager_submits = eagrsub; 84 71 85 72 if( fixedfd ) { … … 88 75 89 76 if( sqkpoll ) { 90 options.clopts. flags |= CFA_CLUSTER_IO_KERNEL_POLL_SUBMITS;77 options.clopts.params.poll_submit = true; 91 78 options.file_cache.fixed_fds = true; 92 79 } 93 80 94 81 if( iokpoll ) { 95 options.clopts. flags |= CFA_CLUSTER_IO_KERNEL_POLL_COMPLETES;82 options.clopts.params.poll_complete = true; 96 83 options.file_cache.open_flags |= O_DIRECT; 97 84 } 98 85 99 options.clopts. flags |= (sublen << CFA_CLUSTER_IO_BUFFLEN_OFFSET);86 options.clopts.params.num_ready = sublen; 100 87 101 88 if( left[0] == 0p ) { return "."; } -
benchmark/io/http/options.hfa
rae2c27a rc76bd34 2 2 3 3 #include <stdint.h> 4 5 #include <kernel.hfa> 4 6 5 7 struct cluster; … … 23 25 int nprocs; 24 26 int nworkers; 25 int flags; 26 int chan_size; 27 io_context_params params; 27 28 bool procstats; 28 29 bool viewhalts; -
benchmark/io/http/protocol.cfa
rae2c27a rc76bd34 11 11 extern "C" { 12 12 int snprintf ( char * s, size_t n, const char * format, ... ); 13 #include <linux/io_uring.h> 13 14 } 14 15 #include <string.h> 15 16 16 #include <errno.h> 17 17 18 #include "options.hfa" 18 19 19 20 const char * http_msgs[] = { … … 74 75 READ: 75 76 for() { 76 int ret = cfa_read(fd, it, count);77 if(ret == 0 ) return [OK200, true, 0 p, 0];77 int ret = cfa_read(fd, (void*)it, count, 0, -1`s, 0p, 0p); 78 if(ret == 0 ) return [OK200, true, 0, 0]; 78 79 if(ret < 0 ) { 79 80 if( errno == EAGAIN || errno == EWOULDBLOCK) continue READ; … … 88 89 count -= ret; 89 90 90 if( count < 1 ) return [E414, false, 0 p, 0];91 if( count < 1 ) return [E414, false, 0, 0]; 91 92 } 92 93 … … 95 96 it = buffer; 96 97 int ret = memcmp(it, "GET /", 5); 97 if( ret != 0 ) return [E400, false, 0 p, 0];98 if( ret != 0 ) return [E400, false, 0, 0]; 98 99 it += 5; 99 100 … … 106 107 ssize_t ret; 107 108 SPLICE1: while(count > 0) { 108 ret = cfa_splice(ans_fd, &offset, pipe[1], 0p, count, SPLICE_F_MOVE | SPLICE_F_MORE );109 ret = cfa_splice(ans_fd, &offset, pipe[1], 0p, count, SPLICE_F_MOVE | SPLICE_F_MORE, 0, -1`s, 0p, 0p); 109 110 if( ret < 0 ) { 110 111 if( errno != EAGAIN && errno != EWOULDBLOCK) continue SPLICE1; … … 116 117 size_t in_pipe = ret; 117 118 SPLICE2: while(in_pipe > 0) { 118 ret = cfa_splice(pipe[0], 0p, fd, 0p, in_pipe, SPLICE_F_MOVE | SPLICE_F_MORE );119 ret = cfa_splice(pipe[0], 0p, fd, 0p, in_pipe, SPLICE_F_MOVE | SPLICE_F_MORE, 0, -1`s, 0p, 0p); 119 120 if( ret < 0 ) { 120 121 if( errno != EAGAIN && errno != EWOULDBLOCK) continue SPLICE2; -
benchmark/io/http/worker.cfa
rae2c27a rc76bd34 22 22 23 23 void main( Worker & this ) { 24 park( __cfaabi_dbg_ctx);24 park(); 25 25 /* paranoid */ assert( this.pipe[0] != -1 ); 26 26 /* paranoid */ assert( this.pipe[1] != -1 ); … … 28 28 CONNECTION: 29 29 for() { 30 int fd = take(wait_connect); 31 if (fd < 0) break; 30 int fd = cfa_accept4( this.[sockfd, addr, addrlen, flags], 0, -1`s, 0p, 0p ); 31 if(fd < 0) { 32 if( errno == ECONNABORTED ) break; 33 abort( "accept error: (%d) %s\n", (int)errno, strerror(errno) ); 34 } 32 35 33 36 printf("New connection %d, waiting for requests\n", fd); … … 82 85 } 83 86 } 84 85 //=============================================================================================86 // Acceptor Thread87 //=============================================================================================88 void ?{}( Acceptor & this, int sockfd, struct sockaddr * addr, socklen_t * addrlen, int flags ) {89 ((thread&)this){ "Acceptor Thread", *options.clopts.instance };90 this.sockfd = sockfd;91 this.addr = addr;92 this.addrlen = addrlen;93 this.flags = flags;94 }95 96 void main( Acceptor & this ) {97 for() {98 int ret = cfa_accept4( this.[sockfd, addr, addrlen, flags] );99 if(ret < 0) {100 if( errno == ECONNABORTED ) break;101 abort( "accept error: (%d) %s\n", (int)errno, strerror(errno) );102 }103 104 printf("New connection accepted\n");105 put( wait_connect, ret );106 }107 } -
benchmark/io/http/worker.hfa
rae2c27a rc76bd34 7 7 } 8 8 9 #include "channel.hfa"10 11 extern channel & wait_connect;12 13 9 //============================================================================================= 14 10 // Worker Thread … … 17 13 thread Worker { 18 14 int pipe[2]; 19 };20 void ?{}( Worker & this );21 void main( Worker & );22 23 //=============================================================================================24 // Acceptor Thread25 //=============================================================================================26 thread Acceptor {27 15 int sockfd; 28 16 struct sockaddr * addr; … … 30 18 int flags; 31 19 }; 32 33 void ?{}( Acceptor & this, int sockfd, struct sockaddr * addr, socklen_t * addrlen, int flags ); 34 void main( Acceptor & this ); 20 void ?{}( Worker & this); 21 void main( Worker & ); -
benchmark/io/readv.cfa
rae2c27a rc76bd34 54 54 55 55 void main( Reader & ) { 56 park( __cfaabi_dbg_ctx);56 park(); 57 57 /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) ); 58 58 … … 151 151 152 152 for(i; nthreads) { 153 unpark( threads[i] __cfaabi_dbg_ctx2);153 unpark( threads[i] ); 154 154 } 155 155 wait(duration, start, end, is_tty); -
benchmark/mutex/JavaThread.java
rae2c27a rc76bd34 1 1 public class JavaThread { 2 2 // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator. 3 // Bijective 3 // Bijective 4 4 // Cycle length for non-zero values is 4G-1. 5 5 // 0 is absorbing and should be avoided -- fixed point. 6 6 // The returned value is typically masked to produce a positive value. 7 static volatile int Ticket = 0 ; 7 static volatile int Ticket = 0 ; 8 8 9 9 private static int nextRandom (int x) { 10 if (x == 0) { 10 if (x == 0) { 11 11 // reseed the PRNG 12 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 13 // Note that we use a non-atomic racy increment -- the race is rare and benign. 14 // If the race is a concern switch to an AtomicInteger. 15 // In addition accesses to the RW volatile global "Ticket" variable are not 16 // (readily) predictable at compile-time so the JIT will not be able to elide 17 // nextRandom() invocations. 18 x = ++Ticket ; 19 if (x == 0) x = 1 ; 12 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 13 // Note that we use a non-atomic racy increment -- the race is rare and benign. 14 // If the race is a concern switch to an AtomicInteger. 15 // In addition accesses to the RW volatile global "Ticket" variable are not 16 // (readily) predictable at compile-time so the JIT will not be able to elide 17 // nextRandom() invocations. 18 x = ++Ticket ; 19 if (x == 0) x = 1 ; 20 20 } 21 21 x ^= x << 6; 22 22 x ^= x >>> 21; 23 23 x ^= x << 7; 24 return x ; 24 return x ; 25 25 } 26 26 static int x = 2; 27 27 28 static private int times = Integer.parseInt("100000000");28 static private long times = Long.parseLong("100000000"); 29 29 30 30 public synchronized void noop() { … … 34 34 JavaThread j = new JavaThread(); 35 35 // Inhibit biased locking ... 36 x = (j.hashCode() ^ System.identityHashCode(j)) | 1 ; 37 for( inti = 1; i <= times; i += 1) {36 x = (j.hashCode() ^ System.identityHashCode(j)) | 1 ; 37 for(long i = 1; i <= times; i += 1) { 38 38 x = nextRandom(x); 39 39 j.noop(); … … 47 47 } 48 48 public static void main(String[] args) throws InterruptedException { 49 if ( args.length > 2) System.exit( 1 );50 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }49 if ( args.length > 1 ) System.exit( 1 ); 50 if ( args.length == 1 ) { times = Long.parseLong(args[0]); } 51 51 52 for (int n = Integer.parseInt("5"); --n >= 0 ; ) { 52 for (int n = Integer.parseInt("5"); --n >= 0 ; ) { 53 53 InnerMain(); 54 54 Thread.sleep(2000); // 2 seconds -
benchmark/mutexC/JavaThread.java
rae2c27a rc76bd34 1 1 class Noop { 2 2 // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator. 3 // Bijective 3 // Bijective 4 4 // Cycle length for non-zero values is 4G-1. 5 5 // 0 is absorbing and should be avoided -- fixed point. 6 6 // The returned value is typically masked to produce a positive value. 7 static volatile int Ticket = 0 ; 7 static volatile int Ticket = 0 ; 8 8 9 9 public static int nextRandom( int x ) { 10 if (x == 0) { 10 if (x == 0) { 11 11 // reseed the PRNG 12 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 13 // Note that we use a non-atomic racy increment -- the race is rare and benign. 14 // If the race is a concern switch to an AtomicInteger. 15 // In addition accesses to the RW volatile global "Ticket" variable are not 16 // (readily) predictable at compile-time so the JIT will not be able to elide 17 // nextRandom() invocations. 18 x = ++Ticket ; 19 if (x == 0) x = 1 ; 12 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 13 // Note that we use a non-atomic racy increment -- the race is rare and benign. 14 // If the race is a concern switch to an AtomicInteger. 15 // In addition accesses to the RW volatile global "Ticket" variable are not 16 // (readily) predictable at compile-time so the JIT will not be able to elide 17 // nextRandom() invocations. 18 x = ++Ticket ; 19 if (x == 0) x = 1 ; 20 20 } 21 21 x ^= x << 6; 22 22 x ^= x >>> 21; 23 23 x ^= x << 7; 24 return x ; 24 return x ; 25 25 } 26 26 } … … 47 47 static int x = 2; 48 48 49 static private int times = Integer.parseInt("10000000");49 static private long times = Long.parseLong("10000000"); 50 50 51 51 public static void call( Monitor m ) throws InterruptedException { … … 53 53 m.go = true; 54 54 //while ( ! m.go2 ); 55 for ( inti = 0; i < times; i += 1 ) {55 for ( long i = 0; i < times; i += 1 ) { 56 56 m.call(); 57 57 x = Noop.nextRandom( x ); … … 71 71 public static void main( String[] args ) throws InterruptedException { 72 72 if ( args.length > 2 ) System.exit( 1 ); 73 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }73 if ( args.length == 2 ) { times = Long.parseLong(args[1]); } 74 74 75 if ( args.length > 2 ) System.exit( 1 ); 76 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); } 77 78 for ( int i = Integer.parseInt("5"); --i >= 0 ; ) { 75 for ( int i = Integer.parseInt("5"); --i >= 0 ; ) { 79 76 InnerMain(); 80 77 // Thread.sleep(2000); // 2 seconds -
benchmark/readyQ/yield.cfa
rae2c27a rc76bd34 32 32 33 33 void main( Yielder & this ) { 34 park( __cfaabi_dbg_ctx);34 park(); 35 35 /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) ); 36 36 … … 70 70 71 71 for(i; nthreads) { 72 unpark( threads[i] __cfaabi_dbg_ctx2);72 unpark( threads[i] ); 73 73 } 74 74 wait(duration, start, end, is_tty); -
benchmark/schedint/JavaThread.java
rae2c27a rc76bd34 24 24 public class JavaThread { 25 25 // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator. 26 // Bijective 26 // Bijective 27 27 // Cycle length for non-zero values is 4G-1. 28 28 // 0 is absorbing and should be avoided -- fixed point. 29 29 // The returned value is typically masked to produce a positive value. 30 static volatile int Ticket = 0 ; 30 static volatile int Ticket = 0 ; 31 31 32 32 private static int nextRandom (int x) { 33 if (x == 0) { 33 if (x == 0) { 34 34 // reseed the PRNG 35 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 36 // Note that we use a non-atomic racy increment -- the race is rare and benign. 37 // If the race is a concern switch to an AtomicInteger. 38 // In addition accesses to the RW volatile global "Ticket" variable are not 39 // (readily) predictable at compile-time so the JIT will not be able to elide 40 // nextRandom() invocations. 41 x = ++Ticket ; 42 if (x == 0) x = 1 ; 35 // Ticket is accessed infrequently and does not constitute a coherence hot-spot. 36 // Note that we use a non-atomic racy increment -- the race is rare and benign. 37 // If the race is a concern switch to an AtomicInteger. 38 // In addition accesses to the RW volatile global "Ticket" variable are not 39 // (readily) predictable at compile-time so the JIT will not be able to elide 40 // nextRandom() invocations. 41 x = ++Ticket ; 42 if (x == 0) x = 1 ; 43 43 } 44 44 x ^= x << 6; 45 45 x ^= x >>> 21; 46 46 x ^= x << 7; 47 return x ; 47 return x ; 48 48 } 49 49 static int x = 2; 50 50 51 static private int times = Integer.parseInt("1000000");51 static private long times = Long.parseLong("1000000"); 52 52 53 53 public static void helper( Monitor m ) throws InterruptedException { 54 for( inti = 1; i <= times; i += 1) {54 for(long i = 1; i <= times; i += 1) { 55 55 m.wait(); // relase monitor lock 56 56 m.next = true; … … 75 75 } 76 76 public static void main(String[] args) throws InterruptedException { 77 if ( args.length > 2) System.exit( 1 );78 if ( args.length == 2 ) { times = Integer.parseInt(args[1]); }77 if ( args.length > 1 ) System.exit( 1 ); 78 if ( args.length == 1 ) { times = Long.parseLong(args[0]); } 79 79 80 for (int n = Integer.parseInt("5"); --n >= 0 ; ) { 80 for (int n = Integer.parseInt("5"); --n >= 0 ; ) { 81 81 InnerMain(); 82 82 Thread.sleep(2000); // 2 seconds -
doc/LaTeXmacros/common.tex
rae2c27a rc76bd34 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Fri Sep 4 13:56:52202014 %% Update Count : 38313 %% Last Modified On : Mon Oct 5 09:34:46 2020 14 %% Update Count : 464 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 55 55 \newlength{\parindentlnth} 56 56 \setlength{\parindentlnth}{\parindent} 57 58 \newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}59 \newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}60 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}61 62 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly63 \newlength{\columnposn}64 \setlength{\gcolumnposn}{2.75in}65 \setlength{\columnposn}{\gcolumnposn}66 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}67 \newcommand{\CRT}{\global\columnposn=\gcolumnposn}68 69 % allow escape sequence in lstinline70 %\usepackage{etoolbox}71 %\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}}72 57 73 58 \usepackage{pslatex} % reduce size of san serif font … … 244 229 \usepackage{listings} % format program code 245 230 \usepackage{lstlang} 246 247 \newcommand{\CFADefaults}{% 231 \makeatletter 232 233 \newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}} 234 \newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}} 235 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}} 236 237 \newlength{\gcolumnposn} % temporary hack because lstlisting does not handle tabs correctly 238 \newlength{\columnposn} 239 \setlength{\gcolumnposn}{2.75in} 240 \setlength{\columnposn}{\gcolumnposn} 241 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}} 242 \newcommand{\CRT}{\global\columnposn=\gcolumnposn} 243 244 % allow escape sequence in lstinline 245 %\usepackage{etoolbox} 246 %\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}} 247 248 % allow adding to lst literate 249 \def\addToLiterate#1{\protect\edef\lst@literate{\unexpanded\expandafter{\lst@literate}\unexpanded{#1}}} 250 \lst@Key{add to literate}{}{\addToLiterate{#1}} 251 \makeatother 252 253 \newcommand{\CFAStyle}{% 248 254 \lstset{ 249 language=CFA,250 255 columns=fullflexible, 251 256 basicstyle=\linespread{0.9}\sf, % reduce line spacing and use sanserif font … … 262 267 belowskip=3pt, 263 268 % replace/adjust listing characters that look bad in sanserif 264 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0. 8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1269 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1 265 270 {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1 266 271 {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2, 272 }% lstset 273 }% CFAStyle 274 275 \ifdefined\CFALatin% extra Latin-1 escape characters 276 \lstnewenvironment{cfa}[1][]{ 277 \lstset{ 278 language=CFA, 267 279 moredelim=**[is][\color{red}]{®}{®}, % red highlighting ®...® (registered trademark symbol) emacs: C-q M-. 268 280 moredelim=**[is][\color{blue}]{ß}{ß}, % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_ 269 281 moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-" 270 282 moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ 283 % replace/adjust listing characters that look bad in sanserif 284 add to literate={`}{\ttfamily\upshape\hspace*{-0.1ex}`}1 271 285 }% lstset 272 }% CFADefaults 273 \newcommand{\CFAStyle}{% 274 \CFADefaults 286 \lstset{#1} 287 }{} 275 288 % inline code ©...© (copyright symbol) emacs: C-q M-) 276 289 \lstMakeShortInline© % single-character for \lstinline 277 }% CFAStyle 278 279 \lstnewenvironment{cfa}[1][] 280 {\CFADefaults\lstset{#1}} 281 {} 290 \else% regular ASCI characters 291 \lstnewenvironment{cfa}[1][]{ 292 \lstset{ 293 language=CFA, 294 escapechar=\$, % LaTeX escape in CFA code 295 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 296 }% lstset 297 \lstset{#1} 298 }{} 299 % inline code @...@ (at symbol) 300 \lstMakeShortInline@ % single-character for \lstinline 301 \fi% 282 302 283 303 % Local Variables: % -
doc/LaTeXmacros/lstlang.sty
rae2c27a rc76bd34 8 8 %% Created On : Sat May 13 16:34:42 2017 9 9 %% Last Modified By : Peter A. Buhr 10 %% Last Modified On : Tue Jan 8 14:40:33 201911 %% Update Count : 2 110 %% Last Modified On : Wed Sep 23 22:40:04 2020 11 %% Update Count : 24 12 12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 13 … … 115 115 auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__, 116 116 coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally, 117 __float80, float80, __float128, float128, forall, ftype, _Generic, _Imaginary, __imag, __imag__,117 __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__, 118 118 inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or, 119 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, thread,119 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, thread, 120 120 _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__, 121 121 virtual, __volatile, __volatile__, waitfor, when, with, zero_t, … … 125 125 126 126 % C++ programming language 127 \lstdefinelanguage{C++}[ANSI]{C++}{} 127 \lstdefinelanguage{C++}[ANSI]{C++}{ 128 morekeywords={nullptr,} 129 } 128 130 129 131 % uC++ programming language, based on ANSI C++ -
doc/bibliography/pl.bib
rae2c27a rc76bd34 1005 1005 key = {Cforall Benchmarks}, 1006 1006 author = {{\textsf{C}{$\mathbf{\forall}$} Benchmarks}}, 1007 howpublished= {\href{https:// plg.uwaterloo.ca/~cforall/doc/CforallConcurrentBenchmarks.tar}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-doc/\-CforallConcurrentBenchmarks.tar}},1007 howpublished= {\href{https://github.com/cforall/ConcurrentBenchmarks_SPE20}{https://\-github.com/\-cforall/\-ConcurrentBenchmarks\_SPE20}}, 1008 1008 } 1009 1009 … … 1973 1973 title = {Cooperating Sequential Processes}, 1974 1974 institution = {Technological University}, 1975 address = {Eindhoven, Neth erlands},1975 address = {Eindhoven, Neth.}, 1976 1976 year = 1965, 1977 1977 note = {Reprinted in \cite{Genuys68} pp. 43--112.} -
doc/papers/concurrency/Paper.tex
rae2c27a rc76bd34 224 224 {} 225 225 \lstnewenvironment{C++}[1][] % use C++ style 226 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`} ,#1}\lstset{#1}}226 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}} 227 227 {} 228 228 \lstnewenvironment{uC++}[1][] 229 {\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{`}{`} ,#1}\lstset{#1}}229 {\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}} 230 230 {} 231 231 \lstnewenvironment{Go}[1][] 232 {\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`} ,#1}\lstset{#1}}232 {\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}} 233 233 {} 234 234 \lstnewenvironment{python}[1][] 235 {\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`} ,#1}\lstset{#1}}235 {\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}} 236 236 {} 237 237 \lstnewenvironment{java}[1][] 238 {\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`} ,#1}\lstset{#1}}238 {\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}} 239 239 {} 240 240 … … 284 284 285 285 \begin{document} 286 \linenumbers % comment out to turn off line numbering286 %\linenumbers % comment out to turn off line numbering 287 287 288 288 \maketitle … … 450 450 \hline 451 451 stateful & thread & \multicolumn{1}{c|}{No} & \multicolumn{1}{c}{Yes} \\ 452 \hline 453 \hline 452 \hline 453 \hline 454 454 No & No & \textbf{1}\ \ \ @struct@ & \textbf{2}\ \ \ @mutex@ @struct@ \\ 455 \hline 455 \hline 456 456 Yes (stackless) & No & \textbf{3}\ \ \ @generator@ & \textbf{4}\ \ \ @mutex@ @generator@ \\ 457 \hline 457 \hline 458 458 Yes (stackful) & No & \textbf{5}\ \ \ @coroutine@ & \textbf{6}\ \ \ @mutex@ @coroutine@ \\ 459 \hline 459 \hline 460 460 No & Yes & \textbf{7}\ \ \ {\color{red}rejected} & \textbf{8}\ \ \ {\color{red}rejected} \\ 461 \hline 461 \hline 462 462 Yes (stackless) & Yes & \textbf{9}\ \ \ {\color{red}rejected} & \textbf{10}\ \ \ {\color{red}rejected} \\ 463 \hline 463 \hline 464 464 Yes (stackful) & Yes & \textbf{11}\ \ \ @thread@ & \textbf{12}\ \ @mutex@ @thread@ \\ 465 465 \end{tabular} … … 2896 2896 \label{s:RuntimeStructureCluster} 2897 2897 2898 A \newterm{cluster} is a collection of user and kernel threads, where the kernel threads run the user threads from the cluster's ready queue, and the operating system runs the kernel threads on the processors from its ready queue .2898 A \newterm{cluster} is a collection of user and kernel threads, where the kernel threads run the user threads from the cluster's ready queue, and the operating system runs the kernel threads on the processors from its ready queue~\cite{Buhr90a}. 2899 2899 The term \newterm{virtual processor} is introduced as a synonym for kernel thread to disambiguate between user and kernel thread. 2900 2900 From the language perspective, a virtual processor is an actual processor (core). … … 2992 2992 \end{cfa} 2993 2993 where CPU time in nanoseconds is from the appropriate language clock. 2994 Each benchmark is performed @N@ times, where @N@ is selected so the benchmark runs in the range of 2--20 seconds for the specific programming language. 2994 Each benchmark is performed @N@ times, where @N@ is selected so the benchmark runs in the range of 2--20 seconds for the specific programming language; 2995 each @N@ appears after the experiment name in the following tables. 2995 2996 The total time is divided by @N@ to obtain the average time for a benchmark. 2996 2997 Each benchmark experiment is run 13 times and the average appears in the table. 2998 For languages with a runtime JIT (Java, Node.js, Python), a single half-hour long experiment is run to check stability; 2999 all long-experiment results are statistically equivalent, \ie median/average/standard-deviation correlate with the short-experiment results, indicating the short experiments reached a steady state. 2997 3000 All omitted tests for other languages are functionally identical to the \CFA tests and available online~\cite{CforallConcurrentBenchmarks}. 2998 % tar --exclude-ignore=exclude -cvhf benchmark.tar benchmark2999 % cp -p benchmark.tar /u/cforall/public_html/doc/concurrent_benchmark.tar3000 3001 3001 3002 \paragraph{Creation} … … 3006 3007 3007 3008 \begin{multicols}{2} 3008 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 3009 \begin{cfa} 3010 @coroutine@ MyCoroutine {}; 3009 \begin{cfa}[xleftmargin=0pt] 3010 `coroutine` MyCoroutine {}; 3011 3011 void ?{}( MyCoroutine & this ) { 3012 3012 #ifdef EAGER … … 3016 3016 void main( MyCoroutine & ) {} 3017 3017 int main() { 3018 BENCH( for ( N ) { @MyCoroutine c;@} )3018 BENCH( for ( N ) { `MyCoroutine c;` } ) 3019 3019 sout | result; 3020 3020 } … … 3030 3030 3031 3031 \begin{tabular}[t]{@{}r*{3}{D{.}{.}{5.2}}@{}} 3032 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3033 \CFA generator & 0.6 & 0.6 & 0.0 \\ 3034 \CFA coroutine lazy & 13.4 & 13.1 & 0.5 \\ 3035 \CFA coroutine eager & 144.7 & 143.9 & 1.5 \\ 3036 \CFA thread & 466.4 & 468.0 & 11.3 \\ 3037 \uC coroutine & 155.6 & 155.7 & 1.7 \\ 3038 \uC thread & 523.4 & 523.9 & 7.7 \\ 3039 Python generator & 123.2 & 124.3 & 4.1 \\ 3040 Node.js generator & 33.4 & 33.5 & 0.3 \\ 3041 Goroutine thread & 751.0 & 750.5 & 3.1 \\ 3042 Rust tokio thread & 1860.0 & 1881.1 & 37.6 \\ 3043 Rust thread & 53801.0 & 53896.8 & 274.9 \\ 3044 Java thread & 120274.0 & 120722.9 & 2356.7 \\ 3045 Pthreads thread & 31465.5 & 31419.5 & 140.4 3032 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3033 \CFA generator (1B) & 0.6 & 0.6 & 0.0 \\ 3034 \CFA coroutine lazy (100M) & 13.4 & 13.1 & 0.5 \\ 3035 \CFA coroutine eager (10M) & 144.7 & 143.9 & 1.5 \\ 3036 \CFA thread (10M) & 466.4 & 468.0 & 11.3 \\ 3037 \uC coroutine (10M) & 155.6 & 155.7 & 1.7 \\ 3038 \uC thread (10M) & 523.4 & 523.9 & 7.7 \\ 3039 Python generator (10M) & 123.2 & 124.3 & 4.1 \\ 3040 Node.js generator (10M) & 33.4 & 33.5 & 0.3 \\ 3041 Goroutine thread (10M) & 751.0 & 750.5 & 3.1 \\ 3042 Rust tokio thread (10M) & 1860.0 & 1881.1 & 37.6 \\ 3043 Rust thread (250K) & 53801.0 & 53896.8 & 274.9 \\ 3044 Java thread (250K) & 119256.0 & 119679.2 & 2244.0 \\ 3045 % Java thread (1 000 000) & 123100.0 & 123052.5 & 751.6 \\ 3046 Pthreads thread (250K) & 31465.5 & 31419.5 & 140.4 3046 3047 \end{tabular} 3047 3048 \end{multicols} … … 3052 3053 Internal scheduling is measured using a cycle of two threads signalling and waiting. 3053 3054 Figure~\ref{f:schedint} shows the code for \CFA, with results in Table~\ref{t:schedint}. 3054 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects. 3055 Java scheduling is significantly greater because the benchmark explicitly creates multiple threads in order to prevent the JIT from making the program sequential, \ie removing all locking. 3055 Note, the \CFA incremental cost for bulk acquire is a fixed cost for small numbers of mutex objects. 3056 User-level threading has one kernel thread, eliminating contention between the threads (direct handoff of the kernel thread). 3057 Kernel-level threading has two kernel threads allowing some contention. 3056 3058 3057 3059 \begin{multicols}{2} 3058 \ lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}3059 \begin{cfa} 3060 \setlength{\tabcolsep}{3pt} 3061 \begin{cfa}[xleftmargin=0pt] 3060 3062 volatile int go = 0; 3061 @condition c;@ 3062 @monitor@M {} m1/*, m2, m3, m4*/;3063 void call( M & @mutex p1/*, p2, p3, p4*/@) {3064 @signal( c );@3065 } 3066 void wait( M & @mutex p1/*, p2, p3, p4*/@) {3063 `condition c;` 3064 `monitor` M {} m1/*, m2, m3, m4*/; 3065 void call( M & `mutex p1/*, p2, p3, p4*/` ) { 3066 `signal( c );` 3067 } 3068 void wait( M & `mutex p1/*, p2, p3, p4*/` ) { 3067 3069 go = 1; // continue other thread 3068 for ( N ) { @wait( c );@} );3070 for ( N ) { `wait( c );` } ); 3069 3071 } 3070 3072 thread T {}; … … 3091 3093 3092 3094 \begin{tabular}{@{}r*{3}{D{.}{.}{5.2}}@{}} 3093 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3094 \CFA @signal@, 1 monitor & 364.4 & 364.2 & 4.4 \\ 3095 \CFA @signal@, 2 monitor & 484.4 & 483.9 & 8.8 \\ 3096 \CFA @signal@, 4 monitor & 709.1 & 707.7 & 15.0 \\ 3097 \uC @signal@ monitor & 328.3 & 327.4 & 2.4 \\ 3098 Rust cond. variable & 7514.0 & 7437.4 & 397.2 \\ 3099 Java @notify@ monitor & 9623.0 & 9654.6 & 236.2 \\ 3100 Pthreads cond. variable & 5553.7 & 5576.1 & 345.6 3095 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3096 \CFA @signal@, 1 monitor (10M) & 364.4 & 364.2 & 4.4 \\ 3097 \CFA @signal@, 2 monitor (10M) & 484.4 & 483.9 & 8.8 \\ 3098 \CFA @signal@, 4 monitor (10M) & 709.1 & 707.7 & 15.0 \\ 3099 \uC @signal@ monitor (10M) & 328.3 & 327.4 & 2.4 \\ 3100 Rust cond. variable (1M) & 7514.0 & 7437.4 & 397.2 \\ 3101 Java @notify@ monitor (1M) & 8717.0 & 8774.1 & 471.8 \\ 3102 % Java @notify@ monitor (100 000 000) & 8634.0 & 8683.5 & 330.5 \\ 3103 Pthreads cond. variable (1M) & 5553.7 & 5576.1 & 345.6 3101 3104 \end{tabular} 3102 3105 \end{multicols} … … 3107 3110 External scheduling is measured using a cycle of two threads calling and accepting the call using the @waitfor@ statement. 3108 3111 Figure~\ref{f:schedext} shows the code for \CFA with results in Table~\ref{t:schedext}. 3109 Note, the incremental cost of bulk acquire for \CFA, which is largelya fixed cost for small numbers of mutex objects.3112 Note, the \CFA incremental cost for bulk acquire is a fixed cost for small numbers of mutex objects. 3110 3113 3111 3114 \begin{multicols}{2} 3112 \ lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}3115 \setlength{\tabcolsep}{5pt} 3113 3116 \vspace*{-16pt} 3114 \begin{cfa} 3115 @monitor@M {} m1/*, m2, m3, m4*/;3116 void call( M & @mutex p1/*, p2, p3, p4*/@) {}3117 void wait( M & @mutex p1/*, p2, p3, p4*/@) {3118 for ( N ) { @waitfor( call : p1/*, p2, p3, p4*/ );@}3117 \begin{cfa}[xleftmargin=0pt] 3118 `monitor` M {} m1/*, m2, m3, m4*/; 3119 void call( M & `mutex p1/*, p2, p3, p4*/` ) {} 3120 void wait( M & `mutex p1/*, p2, p3, p4*/` ) { 3121 for ( N ) { `waitfor( call : p1/*, p2, p3, p4*/ );` } 3119 3122 } 3120 3123 thread T {}; … … 3133 3136 \columnbreak 3134 3137 3135 \vspace*{-1 6pt}3138 \vspace*{-18pt} 3136 3139 \captionof{table}{External-scheduling comparison (nanoseconds)} 3137 3140 \label{t:schedext} 3138 3141 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 3139 \multicolumn{1}{@{} c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\3140 \CFA @waitfor@, 1 monitor & 367.1 & 365.3 & 5.0 \\3141 \CFA @waitfor@, 2 monitor & 463.0 & 464.6 & 7.1 \\3142 \CFA @waitfor@, 4 monitor & 689.6 & 696.2 & 21.5 \\3143 \uC \lstinline[language=uC++]|_Accept| monitor & 328.2 & 329.1 & 3.4 \\3144 Go \lstinline[language=Golang]|select| channel & 365.0 & 365.5 & 1.23142 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3143 \CFA @waitfor@, 1 monitor (10M) & 367.1 & 365.3 & 5.0 \\ 3144 \CFA @waitfor@, 2 monitor (10M) & 463.0 & 464.6 & 7.1 \\ 3145 \CFA @waitfor@, 4 monitor (10M) & 689.6 & 696.2 & 21.5 \\ 3146 \uC \lstinline[language=uC++]|_Accept| monitor (10M) & 328.2 & 329.1 & 3.4 \\ 3147 Go \lstinline[language=Golang]|select| channel (10M) & 365.0 & 365.5 & 1.2 3145 3148 \end{tabular} 3146 3149 \end{multicols} … … 3155 3158 3156 3159 \begin{multicols}{2} 3157 \ lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}3158 \begin{cfa} 3159 @monitor@M {} m1/*, m2, m3, m4*/;3160 call( M & @mutex p1/*, p2, p3, p4*/@) {}3160 \setlength{\tabcolsep}{3pt} 3161 \begin{cfa}[xleftmargin=0pt] 3162 `monitor` M {} m1/*, m2, m3, m4*/; 3163 call( M & `mutex p1/*, p2, p3, p4*/` ) {} 3161 3164 int main() { 3162 3165 BENCH( for( N ) call( m1/*, m2, m3, m4*/ ); ) … … 3173 3176 \label{t:mutex} 3174 3177 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 3175 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3176 test-and-test-set lock & 19.1 & 18.9 & 0.4 \\ 3177 \CFA @mutex@ function, 1 arg. & 48.3 & 47.8 & 0.9 \\ 3178 \CFA @mutex@ function, 2 arg. & 86.7 & 87.6 & 1.9 \\ 3179 \CFA @mutex@ function, 4 arg. & 173.4 & 169.4 & 5.9 \\ 3180 \uC @monitor@ member rtn. & 54.8 & 54.8 & 0.1 \\ 3181 Goroutine mutex lock & 34.0 & 34.0 & 0.0 \\ 3182 Rust mutex lock & 33.0 & 33.2 & 0.8 \\ 3183 Java synchronized method & 31.0 & 31.0 & 0.0 \\ 3184 Pthreads mutex Lock & 31.0 & 31.1 & 0.4 3178 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3179 test-and-test-set lock (50M) & 19.1 & 18.9 & 0.4 \\ 3180 \CFA @mutex@ function, 1 arg. (50M) & 48.3 & 47.8 & 0.9 \\ 3181 \CFA @mutex@ function, 2 arg. (50M) & 86.7 & 87.6 & 1.9 \\ 3182 \CFA @mutex@ function, 4 arg. (50M) & 173.4 & 169.4 & 5.9 \\ 3183 \uC @monitor@ member rtn. (50M) & 54.8 & 54.8 & 0.1 \\ 3184 Goroutine mutex lock (50M) & 34.0 & 34.0 & 0.0 \\ 3185 Rust mutex lock (50M) & 33.0 & 33.2 & 0.8 \\ 3186 Java synchronized method (50M) & 31.0 & 30.9 & 0.5 \\ 3187 % Java synchronized method (10 000 000 000) & 31.0 & 30.2 & 0.9 \\ 3188 Pthreads mutex Lock (50M) & 31.0 & 31.1 & 0.4 3185 3189 \end{tabular} 3186 3190 \end{multicols} … … 3201 3205 % To: "Peter A. Buhr" <pabuhr@plg2.cs.uwaterloo.ca> 3202 3206 % Date: Fri, 24 Jan 2020 13:49:18 -0500 3203 % 3207 % 3204 3208 % I can also verify that the previous version, which just tied a bunch of promises together, *does not* go back to the 3205 3209 % event loop at all in the current version of Node. Presumably they're taking advantage of the fact that the ordering of … … 3211 3215 3212 3216 \begin{multicols}{2} 3213 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}} 3214 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 3215 @coroutine@ C {}; 3216 void main( C & ) { for () { @suspend;@ } } 3217 \begin{cfa}[xleftmargin=0pt] 3218 `coroutine` C {}; 3219 void main( C & ) { for () { `suspend;` } } 3217 3220 int main() { // coroutine test 3218 3221 C c; 3219 BENCH( for ( N ) { @resume( c );@} )3222 BENCH( for ( N ) { `resume( c );` } ) 3220 3223 sout | result; 3221 3224 } 3222 3225 int main() { // thread test 3223 BENCH( for ( N ) { @yield();@} )3226 BENCH( for ( N ) { `yield();` } ) 3224 3227 sout | result; 3225 3228 } … … 3234 3237 \label{t:ctx-switch} 3235 3238 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}} 3236 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3237 C function & 1.8 & 1.8 & 0.0 \\ 3238 \CFA generator & 1.8 & 2.0 & 0.3 \\ 3239 \CFA coroutine & 32.5 & 32.9 & 0.8 \\ 3240 \CFA thread & 93.8 & 93.6 & 2.2 \\ 3241 \uC coroutine & 50.3 & 50.3 & 0.2 \\ 3242 \uC thread & 97.3 & 97.4 & 1.0 \\ 3243 Python generator & 40.9 & 41.3 & 1.5 \\ 3244 Node.js await & 1852.2 & 1854.7 & 16.4 \\ 3245 Node.js generator & 33.3 & 33.4 & 0.3 \\ 3246 Goroutine thread & 143.0 & 143.3 & 1.1 \\ 3247 Rust async await & 32.0 & 32.0 & 0.0 \\ 3248 Rust tokio thread & 143.0 & 143.0 & 1.7 \\ 3249 Rust thread & 332.0 & 331.4 & 2.4 \\ 3250 Java thread & 405.0 & 415.0 & 17.6 \\ 3251 Pthreads thread & 334.3 & 335.2 & 3.9 3239 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\ 3240 C function (10B) & 1.8 & 1.8 & 0.0 \\ 3241 \CFA generator (5B) & 1.8 & 2.0 & 0.3 \\ 3242 \CFA coroutine (100M) & 32.5 & 32.9 & 0.8 \\ 3243 \CFA thread (100M) & 93.8 & 93.6 & 2.2 \\ 3244 \uC coroutine (100M) & 50.3 & 50.3 & 0.2 \\ 3245 \uC thread (100M) & 97.3 & 97.4 & 1.0 \\ 3246 Python generator (100M) & 40.9 & 41.3 & 1.5 \\ 3247 Node.js await (5M) & 1852.2 & 1854.7 & 16.4 \\ 3248 Node.js generator (100M) & 33.3 & 33.4 & 0.3 \\ 3249 Goroutine thread (100M) & 143.0 & 143.3 & 1.1 \\ 3250 Rust async await (100M) & 32.0 & 32.0 & 0.0 \\ 3251 Rust tokio thread (100M) & 143.0 & 143.0 & 1.7 \\ 3252 Rust thread (25M) & 332.0 & 331.4 & 2.4 \\ 3253 Java thread (100M) & 405.0 & 415.0 & 17.6 \\ 3254 % Java thread ( 100 000 000) & 413.0 & 414.2 & 6.2 \\ 3255 % Java thread (5 000 000 000) & 415.0 & 415.2 & 6.1 \\ 3256 Pthreads thread (25M) & 334.3 & 335.2 & 3.9 3252 3257 \end{tabular} 3253 3258 \end{multicols} … … 3258 3263 Languages using 1:1 threading based on pthreads can at best meet or exceed, due to language overhead, the pthread results. 3259 3264 Note, pthreads has a fast zero-contention mutex lock checked in user space. 3260 Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions. 3265 Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions (context-switching or locking). 3266 As well, for locking experiments, M:N threading has less contention if only one kernel thread is used. 3261 3267 Languages with stackful coroutines have higher cost than stackless coroutines because of stack allocation and context switching; 3262 3268 however, stackful \uC and \CFA coroutines have approximately the same performance as stackless Python and Node.js generators. 3263 3269 The \CFA stackless generator is approximately 25 times faster for suspend/resume and 200 times faster for creation than stackless Python and Node.js generators. 3270 The Node.js context-switch is costly when asynchronous await must enter the event engine because a promise is not fulfilled. 3271 Finally, the benchmark results correlate across programming languages with and without JIT, indicating the JIT has completed any runtime optimizations. 3264 3272 3265 3273 … … 3319 3327 3320 3328 The authors recognize the design assistance of Aaron Moss, Rob Schluntz, Andrew Beach, and Michael Brooks; David Dice for commenting and helping with the Java benchmarks; and Gregor Richards for helping with the Node.js benchmarks. 3321 This research is funded by a grant fromWaterloo-Huawei (\url{http://www.huawei.com}) Joint Innovation Lab. %, and Peter Buhr is partially funded by the Natural Sciences and Engineering Research Council of Canada.3329 This research is funded by the NSERC/Waterloo-Huawei (\url{http://www.huawei.com}) Joint Innovation Lab. %, and Peter Buhr is partially funded by the Natural Sciences and Engineering Research Council of Canada. 3322 3330 3323 3331 {% -
doc/papers/concurrency/annex/local.bib
rae2c27a rc76bd34 59 59 @manual{Cpp-Transactions, 60 60 keywords = {C++, Transactional Memory}, 61 title = {Tech nical Specificationfor C++ Extensions for Transactional Memory},61 title = {Tech. Spec. for C++ Extensions for Transactional Memory}, 62 62 organization= {International Standard ISO/IEC TS 19841:2015 }, 63 63 publisher = {American National Standards Institute}, -
doc/papers/concurrency/mail2
rae2c27a rc76bd34 959 959 Software: Practice and Experience Editorial Office 960 960 961 962 963 Date: Wed, 2 Sep 2020 20:55:34 +0000 964 From: Richard Jones <onbehalfof@manuscriptcentral.com> 965 Reply-To: R.E.Jones@kent.ac.uk 966 To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca 967 Subject: Software: Practice and Experience - Decision on Manuscript ID 968 SPE-19-0219.R2 969 970 02-Sep-2020 971 972 Dear Dr Buhr, 973 974 Many thanks for submitting SPE-19-0219.R2 entitled "Advanced Control-flow and Concurrency in Cforall" to Software: Practice and Experience. The paper has now been reviewed and the comments of the referees are included at the bottom of this letter. I apologise for the length of time it has taken to get these. 975 976 Both reviewers consider this paper to be close to acceptance. However, before I can accept this paper, I would like you address the comments of Reviewer 2, particularly with regard to the description of the adaptation Java harness to deal with warmup. I would expect to see a convincing argument that the computation has reached a steady state. I would also like you to provide the values for N for each benchmark run. This should be very straightforward for you to do. There are a couple of papers on steady state that you may wish to consult (though I am certainly not pushing my own work). 977 978 1) Barrett, Edd; Bolz-Tereick, Carl Friedrich; Killick, Rebecca; Mount, Sarah and Tratt, Laurence. Virtual Machine Warmup Blows Hot and Cold. OOPSLA 2017. https://doi.org/10.1145/3133876 979 Virtual Machines (VMs) with Just-In-Time (JIT) compilers are traditionally thought to execute programs in two phases: the initial warmup phase determines which parts of a program would most benefit from dynamic compilation, before JIT compiling those parts into machine code; subsequently the program is said to be at a steady state of peak performance. Measurement methodologies almost always discard data collected during the warmup phase such that reported measurements focus entirely on peak performance. We introduce a fully automated statistical approach, based on changepoint analysis, which allows us to determine if a program has reached a steady state and, if so, whether that represents peak performance or not. Using this, we show that even when run in the most controlled of circumstances, small, deterministic, widely studied microbenchmarks often fail to reach a steady state of peak performance on a variety of common VMs. Repeating our experiment on 3 different machines, we found that at most 43.5% of pairs consistently reach a steady state of peak performance. 980 981 2) Kalibera, Tomas and Jones, Richard. Rigorous Benchmarking in Reasonable Time. ISMM 2013. https://doi.org/10.1145/2555670.2464160 982 Experimental evaluation is key to systems research. Because modern systems are complex and non-deterministic, good experimental methodology demands that researchers account for uncertainty. To obtain valid results, they are expected to run many iterations of benchmarks, invoke virtual machines (VMs) several times, or even rebuild VM or benchmark binaries more than once. All this repetition costs time to complete experiments. Currently, many evaluations give up on sufficient repetition or rigorous statistical methods, or even run benchmarks only in training sizes. The results reported often lack proper variation estimates and, when a small difference between two systems is reported, some are simply unreliable.In contrast, we provide a statistically rigorous methodology for repetition and summarising results that makes efficient use of experimentation time. Time efficiency comes from two key observations. First, a given benchmark on a given platform is typically prone to much less non-determinism than the common worst-case of published corner-case studies. Second, repetition is most needed where most uncertainty arises (whether between builds, between executions or between iterations). We capture experimentation cost with a novel mathematical model, which we use to identify the number of repetitions at each level of an experiment necessary and sufficient to obtain a given level of precision.We present our methodology as a cookbook that guides researchers on the number of repetitions they should run to obtain reliable results. We also show how to present results with an effect size confidence interval. As an example, we show how to use our methodology to conduct throughput experiments with the DaCapo and SPEC CPU benchmarks on three recent platforms. 983 984 You have 42 days from the date of this email to submit your revision. If you are unable to complete the revision within this time, please contact me to request a short extension. 985 986 You can upload your revised manuscript and submit it through your Author Center. Log into https://mc.manuscriptcentral.com/spe and enter your Author Center, where you will find your manuscript title listed under "Manuscripts with Decisions". 987 988 When submitting your revised manuscript, you will be able to respond to the comments made by the referee(s) in the space provided. You can use this space to document any changes you make to the original manuscript. 989 990 If you would like help with English language editing, or other article preparation support, Wiley Editing Services offers expert help with English Language Editing, as well as translation, manuscript formatting, and figure formatting at www.wileyauthors.com/eeo/preparation. You can also check out our resources for Preparing Your Article for general guidance about writing and preparing your manuscript at www.wileyauthors.com/eeo/prepresources. 991 992 Once again, thank you for submitting your manuscript to Software: Practice and Experience. I look forward to receiving your revision. 993 994 Sincerely, 995 Richard 996 997 Prof. Richard Jones 998 Editor, Software: Practice and Experience 999 R.E.Jones@kent.ac.uk 1000 1001 Referee(s)' Comments to Author: 1002 1003 Reviewing: 1 1004 1005 Comments to the Author 1006 Overall, I felt that this draft was an improvement on previous drafts and I don't have further changes to request. 1007 1008 I appreciated the new language to clarify the relationship of external and internal scheduling, for example, as well as the new measurements of Rust tokio. Also, while I still believe that the choice between thread/generator/coroutine and so forth could be made crisper and clearer, the current draft of Section 2 did seem adequate to me in terms of specifying the considerations that users would have to take into account to make the choice. 1009 1010 1011 Reviewing: 2 1012 1013 Comments to the Author 1014 First: let me apologise for the delay on this review. I'll blame the global pandemic combined with my institution's senior management's counterproductive decisions for taking up most of my time and all of my energy. 1015 1016 At this point, reading the responses, I think we've been around the course enough times that further iteration is unlikely to really improve the paper any further, so I'm happy to recommend acceptance. My main comments are that there were some good points in the responses to *all* the reviews and I strongly encourage the authors to incorporate those discursive responses into the final paper so they may benefit readers as well as reviewers. I agree with the recommendations of reviewer #2 that the paper could usefully be split in to two, which I think I made to a previous revision, but I'm happy to leave that decision to the Editor. 1017 1018 Finally, the paper needs to describe how the Java harness was adapted to deal with warmup; why the computation has warmed up and reached a steady state - similarly for js and Python. The tables should also give the "N" chosen for each benchmark run. 1019 1020 minor points 1021 * don't start sentences with "However" 1022 * most downloaded isn't an "Award" 1023 1024 1025 1026 Date: Thu, 1 Oct 2020 05:34:29 +0000 1027 From: Richard Jones <onbehalfof@manuscriptcentral.com> 1028 Reply-To: R.E.Jones@kent.ac.uk 1029 To: pabuhr@uwaterloo.ca 1030 Subject: Revision reminder - SPE-19-0219.R2 1031 1032 01-Oct-2020 1033 1034 Dear Dr Buhr 1035 1036 SPE-19-0219.R2 1037 1038 This is a reminder that your opportunity to revise and re-submit your manuscript will expire 14 days from now. If you require more time please contact me directly and I may grant an extension to this deadline, otherwise the option to submit a revision online, will not be available. 1039 1040 If your article is of potential interest to the general public, (which means it must be timely, groundbreaking, interesting and impact on everyday society) then please e-mail ejp@wiley.co.uk explaining the public interest side of the research. Wiley will then investigate the potential for undertaking a global press campaign on the article. 1041 1042 I look forward to receiving your revision. 1043 1044 Sincerely, 1045 1046 Prof. Richard Jones 1047 Editor, Software: Practice and Experience 1048 1049 https://mc.manuscriptcentral.com/spe 1050 1051 1052 1053 Date: Tue, 6 Oct 2020 15:29:41 +0000 1054 From: Mayank Roy Chowdhury <onbehalfof@manuscriptcentral.com> 1055 Reply-To: speoffice@wiley.com 1056 To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca 1057 Subject: SPE-19-0219.R3 successfully submitted 1058 1059 06-Oct-2020 1060 1061 Dear Dr Buhr, 1062 1063 Your manuscript entitled "Advanced Control-flow and Concurrency in Cforall" has been successfully submitted online and is presently being given full consideration for publication in Software: Practice and Experience. 1064 1065 Your manuscript number is SPE-19-0219.R3. Please mention this number in all future correspondence regarding this submission. 1066 1067 You can view the status of your manuscript at any time by checking your Author Center after logging into https://mc.manuscriptcentral.com/spe. If you have difficulty using this site, please click the 'Get Help Now' link at the top right corner of the site. 1068 1069 1070 Thank you for submitting your manuscript to Software: Practice and Experience. 1071 1072 Sincerely, 1073 1074 Software: Practice and Experience Editorial Office 1075 -
doc/refrat/refrat.tex
rae2c27a rc76bd34 11 11 %% Created On : Wed Apr 6 14:52:25 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Wed Jan 31 17:30:23 201814 %% Update Count : 1 0813 %% Last Modified On : Mon Oct 5 09:02:53 2020 14 %% Update Count : 110 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 30 30 \usepackage{upquote} % switch curled `'" to straight 31 31 \usepackage{calc} 32 \usepackage{xspace}33 32 \usepackage{varioref} % extended references 34 \usepackage{listings} % format program code35 33 \usepackage[flushmargin]{footmisc} % support label/reference in footnote 36 34 \usepackage{latexsym} % \Box glyph 37 35 \usepackage{mathptmx} % better math font with "times" 38 36 \usepackage[usenames]{color} 39 \input{common} % common CFA document macros 40 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref} 41 \usepackage{breakurl} 42 \renewcommand{\UrlFont}{\small\sf} 43 44 \usepackage[pagewise]{lineno} 45 \renewcommand{\linenumberfont}{\scriptsize\sffamily} 46 \usepackage[firstpage]{draftwatermark} 47 \SetWatermarkLightness{0.9} 48 49 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore 50 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR 51 % AFTER HYPERREF. 52 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 53 54 \setlength{\topmargin}{-0.45in} % move running title into header 55 \setlength{\headsep}{0.25in} 56 57 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 59 \CFAStyle % use default CFA format-style 60 \lstnewenvironment{C++}[1][] % use C++ style 61 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®}#1}} 62 {} 63 37 \newcommand{\CFALatin}{} 64 38 % inline code ©...© (copyright symbol) emacs: C-q M-) 65 39 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-. … … 69 43 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ 70 44 % math escape $...$ (dollar symbol) 45 \input{common} % common CFA document macros 46 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref} 47 \usepackage{breakurl} 48 \renewcommand{\UrlFont}{\small\sf} 49 50 \usepackage[pagewise]{lineno} 51 \renewcommand{\linenumberfont}{\scriptsize\sffamily} 52 \usepackage[firstpage]{draftwatermark} 53 \SetWatermarkLightness{0.9} 54 55 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore 56 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR 57 % AFTER HYPERREF. 58 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 59 60 \setlength{\topmargin}{-0.45in} % move running title into header 61 \setlength{\headsep}{0.25in} 71 62 72 63 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73 64 65 \CFAStyle % use default CFA format-style 66 \lstnewenvironment{C++}[1][] % use C++ style 67 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}} 68 {} 69 70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 71 74 72 % Names used in the document. 75 \newcommand{\Version}{\input{ ../../version}}73 \newcommand{\Version}{\input{build/version}} 76 74 \newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}} 77 75 \newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}} -
doc/theses/andrew_beach_MMath/thesis.tex
rae2c27a rc76bd34 34 34 \usepackage[toc,abbreviations]{glossaries-extra} 35 35 36 % Main glossary entries -- definitions of relevant terminology 37 \newglossaryentry{computer} 38 { 39 name=computer, 40 description={A programmable machine that receives input data, 41 stores and manipulates the data, and provides 42 formatted output} 43 } 44 45 % Nomenclature glossary entries -- New definitions, or unusual terminology 46 \newglossary*{nomenclature}{Nomenclature} 47 \newglossaryentry{dingledorf} 48 { 49 type=nomenclature, 50 name=dingledorf, 51 description={A person of supposed average intelligence who makes incredibly 52 brainless misjudgments} 53 } 54 55 % List of Abbreviations (abbreviations are from the glossaries-extra package) 56 \newabbreviation{aaaaz}{AAAAZ}{American Association of Amature Astronomers 57 and Zoologists} 58 59 % List of Symbols 60 \newglossary*{symbols}{List of Symbols} 61 \newglossaryentry{rvec} 62 { 63 name={$\mathbf{v}$}, 64 sort={label}, 65 type=symbols, 66 description={Random vector: a location in n-dimensional Cartesian space, where 67 each dimensional component is determined by a random process} 68 } 36 % Define all the glossaries. 37 \input{glossaries} 69 38 70 39 % Generate the glossaries defined above. -
doc/theses/thierry_delisle_PhD/.gitignore
rae2c27a rc76bd34 11 11 comp_II/comp_II.pdf 12 12 comp_II/comp_II.ps 13 comp_II/presentation.pdf 14 15 thesis/build/ 16 thesis/fig/*.fig.bak 17 thesis/thesis.pdf 18 thesis/thesis.ps 13 19 14 20 !Makefile -
doc/theses/thierry_delisle_PhD/comp_II/comp_II.tex
rae2c27a rc76bd34 60 60 \section{Introduction} 61 61 \subsection{\CFA and the \CFA concurrency package} 62 \CFA \cite{Moss18} is a modern, polymorphic, non-object-oriented, concurrent, backwards-compatible extension of the C programming language.62 \CFA~\cite{Moss18} is a modern, polymorphic, non-object-oriented, concurrent, backwards-compatible extension of the C programming language. 63 63 It aims to add high-productivity features while maintaining the predictable performance of C. 64 As such, concurrency in \CFA \cite{Delisle19} aims to offer simple and safe high-level tools while still allowing performant code.65 \CFA concurrent code is written in the synchronous programming paradigm but uses \glspl{uthrd} in orderto achieve the simplicity and maintainability of synchronous programming without sacrificing the efficiency of asynchronous programming.64 As such, concurrency in \CFA~\cite{Delisle19} aims to offer simple and safe high-level tools while still allowing performant code. 65 \CFA concurrent code is written in the synchronous programming paradigm but uses \glspl{uthrd} to achieve the simplicity and maintainability of synchronous programming without sacrificing the efficiency of asynchronous programming. 66 66 As such, the \CFA \newterm{scheduler} is a preemptive user-level scheduler that maps \glspl{uthrd} onto \glspl{kthrd}. 67 67 68 \subsection{Scheduling} 68 69 \newterm{Scheduling} occurs when execution switches from one thread to another, where the second thread is implicitly chosen by the scheduler. 69 This scheduling is an indirect handoff, as opposed to generators and coroutines whichexplicitly switch to the next generator and coroutine respectively.70 This scheduling is an indirect handoff, as opposed to generators and coroutines that explicitly switch to the next generator and coroutine respectively. 70 71 The cost of switching between two threads for an indirect handoff has two components: 71 72 \begin{enumerate} … … 75 76 and the cost of scheduling, \ie deciding which thread to run next among all the threads ready to run. 76 77 \end{enumerate} 77 The first cost is generally constant and fixed\footnote{Affecting the constant context-switch cost is whether it is done in one step, after the scheduling, or in two steps, context-switching to a third fixed thread before scheduling.}, while the scheduling cost can vary based on the system state.78 Adding multiple \glspl{kthrd} does not fundamentally change the scheduler semantics or requirements, it simply adds new correctness requirements, \ie \newterm{linearizability}\footnote{Meaning , however fast the CPU threads run, there is an equivalent sequential order that gives the same result.}, and a new dimension to performance: scalability, where scheduling cost nowalso depends on contention.78 The first cost is generally constant\footnote{Affecting the constant context-switch cost is whether it is done in one step, where the first thread schedules the second, or in two steps, where the first thread context switches to a third scheduler thread.}, while the scheduling cost can vary based on the system state. 79 Adding multiple \glspl{kthrd} does not fundamentally change the scheduler semantics or requirements, it simply adds new correctness requirements, \ie \newterm{linearizability}\footnote{Meaning however fast the CPU threads run, there is an equivalent sequential order that gives the same result.}, and a new dimension to performance: scalability, where scheduling cost also depends on contention. 79 80 The more threads switch, the more the administration cost of scheduling becomes noticeable. 80 81 It is therefore important to build a scheduler with the lowest possible cost and latency. 81 82 Another important consideration is \newterm{fairness}. 82 83 In principle, scheduling should give the illusion of perfect fairness, where all threads ready to run are running \emph{simultaneously}. 84 In practice, there can be advantages to unfair scheduling, similar to the express cash register at a grocery store. 83 85 While the illusion of simultaneity is easier to reason about, it can break down if the scheduler allows too much unfairness. 84 86 Therefore, the scheduler should offer as much fairness as needed to guarantee eventual progress, but use unfairness to help performance. 85 In practice, threads must wait in turn but there can be advantages to unfair scheduling, similar to the express cash register at a grocery store. 86 87 The goal of this research is to produce a scheduler that is simple for programmers to understand and offers good performance.87 88 \subsection{Research Goal} 89 The goal of this research is to produce a scheduler that is simple for programmers to understand and offers good general performance. 88 90 Here understandability does not refer to the API but to how much scheduling concerns programmers need to take into account when writing a \CFA concurrent package. 89 Therefore, the main goal of this proposal is :91 Therefore, the main consequence of this goal is : 90 92 \begin{quote} 91 93 The \CFA scheduler should be \emph{viable} for \emph{any} workload. 92 94 \end{quote} 93 95 94 For a general-purpose scheduler, it is impossible to produce an optimal algorithm as it would requireknowledge of the future behaviour of threads.95 As such, scheduling performance is generally either defined by the best-case scenario, \ie a workload to which the scheduler is tailored, or theworst-case scenario, \ie the scheduler behaves no worse than \emph{X}.96 For a general-purpose scheduler, it is impossible to produce an optimal algorithm as that requires knowledge of the future behaviour of threads. 97 As such, scheduling performance is generally either defined by a best-case scenario, \ie a workload to which the scheduler is tailored, or a worst-case scenario, \ie the scheduler behaves no worse than \emph{X}. 96 98 For this proposal, the performance is evaluated using the second approach to allow \CFA programmers to rely on scheduling performance. 97 99 Because there is no optimal scheduler, ultimately \CFA may allow programmers to write their own scheduler; but that is not the subject of this proposal, which considers only the default scheduler. … … 103 105 \item creating an abstraction layer over the operating system to handle kernel-threads spinning unnecessarily, 104 106 \item scheduling blocking I/O operations, 105 \item and writing sufficient library tools to allow developers to indirectly use the scheduler, either through tuning knobs or replacing the default scheduler.107 \item and writing sufficient library tools to allow developers to indirectly use the scheduler, either through tuning knobs in the default scheduler or replacing the default scheduler. 106 108 \end{enumerate} 107 109 … … 119 121 \paragraph{Performance} The performance of a scheduler can generally be measured in terms of scheduling cost, scalability and latency. 120 122 \newterm{Scheduling cost} is the cost to switch from one thread to another, as mentioned above. 121 For simple applications, where a single kernel thread does most of the scheduling, it is generally the dominating cost. 122 \newterm{Scalability} is the cost of adding multiple kernel threads because it increases the time for context switching because of contention by multiple threads accessing shared resources, \eg the ready queue. 123 For compute-bound concurrent applications with little context switching, the scheduling cost is negligible. 124 For applications with high context-switch rates, scheduling cost can begin to dominating the cost. 125 \newterm{Scalability} is the cost of adding multiple kernel threads. 126 It can increase the time for scheduling because of contention from the multiple threads accessing shared resources, \eg a single ready queue. 123 127 Finally, \newterm{tail latency} is service delay and relates to thread fairness. 124 Specifically, latency measures how long a thread waits to run once scheduled and is evaluated inthe worst case.128 Specifically, latency measures how long a thread waits to run once scheduled and is evaluated by the worst case. 125 129 The \CFA scheduler should offer good performance for all three metrics. 126 130 … … 128 132 \newterm{Eventual progress} guarantees every scheduled thread is eventually run, \ie prevent starvation. 129 133 As a hard requirement, the \CFA scheduler must guarantee eventual progress, otherwise the above-mentioned illusion of simultaneous execution is broken and the scheduler becomes much more complex to reason about. 130 \newterm{Predictability} and \newterm{reliability} mean similar workloads achieve similar performance andprogrammer execution intuition is respected.131 For example, a thread that yields aggressively should not run more often than other t asks.134 \newterm{Predictability} and \newterm{reliability} mean similar workloads achieve similar performance so programmer execution intuition is respected. 135 For example, a thread that yields aggressively should not run more often than other threads. 132 136 While this is intuitive, it does not hold true for many work-stealing or feedback based schedulers. 133 The \CFA scheduler must guarantee eventual progress and should be predictableand offer reliable performance.137 The \CFA scheduler must guarantee eventual progress, should be predictable, and offer reliable performance. 134 138 135 139 \paragraph{Efficiency} Finally, efficient usage of CPU resources is also an important requirement and is discussed in depth towards the end of the proposal. 136 \newterm{Efficiency} means avoiding using CPU cycles when there are no threads to run , and conversely, use all CPUs availablewhen the workload can benefit from it.140 \newterm{Efficiency} means avoiding using CPU cycles when there are no threads to run (to conserve energy), and conversely, using as many available CPU cycles when the workload can benefit from it. 137 141 Balancing these two states is where the complexity lies. 138 142 The \CFA scheduler should be efficient with respect to the underlying (shared) computer. … … 146 150 \begin{enumerate} 147 151 \item Threads live long enough for useful feedback information to be gathered. 148 \item Threads belong to multiple users so fairness across threads is insufficient.152 \item Threads belong to multiple users so fairness across users is important. 149 153 \end{enumerate} 150 154 … … 159 163 In the case of the \CFA scheduler, every thread runs in the same user space and is controlled by the same user. 160 164 Fairness across users is therefore a given and it is then possible to safely ignore the possibility that threads are malevolent. 161 This approach allows for a much simpler fairness metric and in this proposal \emph{fairness} is defined as: when multiple threads are cycling through the system, the total ordering of threads being scheduled, \ie pushed onto the ready queue, should not differ much from the total ordering of threads being executed, \ie popped from the ready queue. 165 This approach allows for a much simpler fairness metric, and in this proposal, \emph{fairness} is defined as: 166 \begin{quote} 167 When multiple threads are cycling through the system, the total ordering of threads being scheduled, \ie pushed onto the ready queue, should not differ much from the total ordering of threads being executed, \ie popped from the ready queue. 168 \end{quote} 162 169 163 170 Since feedback is not necessarily feasible within the lifetime of all threads and a simple fairness metric can be used, the scheduling strategy proposed for the \CFA runtime does not use per-threads feedback. … … 169 176 Threads with equal priority are scheduled using a secondary strategy, often something simple like round robin or FIFO. 170 177 A consequence of priority is that, as long as there is a thread with a higher priority that desires to run, a thread with a lower priority does not run. 171 Th is possible starving of threads can dramatically increaseprogramming complexity since starving threads and priority inversion (prioritizing a lower priority thread) can both lead to serious problems.178 The potential for thread starvation dramatically increases programming complexity since starving threads and priority inversion (prioritizing a lower priority thread) can both lead to serious problems. 172 179 173 180 An important observation is that threads do not need to have explicit priorities for problems to occur. 174 Indeed, any system with multiple ready queues that attempts to exhaust one queue before accessing the other queues, essentially provide implicit priority, which can encounter starvation problems.181 Indeed, any system with multiple ready queues that attempts to exhaust one queue before accessing the other queues, essentially provides implicit priority, which can encounter starvation problems. 175 182 For example, a popular scheduling strategy that suffers from implicit priorities is work stealing. 176 183 \newterm{Work stealing} is generally presented as follows: … … 180 187 \item If a processor's ready queue is empty, attempt to run threads from some other processor's ready queue. 181 188 \end{enumerate} 182 183 189 In a loaded system\footnote{A \newterm{loaded system} is a system where threads are being run at the same rate they are scheduled.}, if a thread does not yield, block, or preempt for an extended period of time, threads on the same processor's list starve if no other processors exhaust their list. 184 190 185 Since priorities can be complex for programmers to incorporate into their execution intuition, the scheduling strategy proposed for the \CFA runtime does not use a strategy with either implicit or explicit threadpriorities.191 Since priorities can be complex for programmers to incorporate into their execution intuition, the \CFA scheduling strategy does not provided explicit priorities and attempts to eliminate implicit priorities. 186 192 187 193 \subsection{Schedulers without feedback or priorities} … … 191 197 Thankfully, strict FIFO is not needed for sufficient fairness. 192 198 Since concurrency is inherently non-deterministic, fairness concerns in scheduling are only a problem if a thread repeatedly runs before another thread can run. 193 Some relaxation is possible because non-determinism means programmers already handle ordering problems to produce correct code and hence rely on weak guarantees, \eg that a specific thread will \emph{eventually} run.199 Some relaxation is possible because non-determinism means programmers already handle ordering problems to produce correct code and hence rely on weak guarantees, \eg that a thread \emph{eventually} runs. 194 200 Since some reordering does not break correctness, the FIFO fairness guarantee can be significantly relaxed without causing problems. 195 201 For this proposal, the target guarantee is that the \CFA scheduler provides \emph{probable} FIFO ordering, which allows reordering but makes it improbable that threads are reordered far from their position in total ordering. 196 202 197 203 The \CFA scheduler fairness is defined as follows: 198 \begin{ itemize}199 \itemGiven two threads $X$ and $Y$, the odds that thread $X$ runs $N$ times \emph{after} thread $Y$ is scheduled but \emph{before} it is run, decreases exponentially with regard to $N$.200 \end{ itemize}204 \begin{quote} 205 Given two threads $X$ and $Y$, the odds that thread $X$ runs $N$ times \emph{after} thread $Y$ is scheduled but \emph{before} it is run, decreases exponentially with regard to $N$. 206 \end{quote} 201 207 While this is not a bounded guarantee, the probability that unfairness persist for long periods of times decreases exponentially, making persisting unfairness virtually impossible. 202 208 … … 210 216 The described queue uses an array of underlying strictly FIFO queues as shown in Figure~\ref{fig:base}\footnote{For this section, the number of underlying queues is assumed to be constant. 211 217 Section~\ref{sec:resize} discusses resizing the array.}. 212 Pushing new data is done by selecting one of the se underlying queues at random, recording a timestamp for the operationand pushing to the selected queue.218 Pushing new data is done by selecting one of the underlying queues at random, recording a timestamp for the operation, and pushing to the selected queue. 213 219 Popping is done by selecting two queues at random and popping from the queue with the oldest timestamp. 214 A higher number of underlying queues lead to less contention on each queue and therefore better performance.215 In a loaded system, it is highly likely the queues are non-empty, \ie several t asks are on each of the underlying queues.216 This means thatselecting a queue at random to pop from is highly likely to yield a queue with available items.220 A higher number of underlying queues leads to less contention on each queue and therefore better performance. 221 In a loaded system, it is highly likely the queues are non-empty, \ie several threads are on each of the underlying queues. 222 For this case, selecting a queue at random to pop from is highly likely to yield a queue with available items. 217 223 In Figure~\ref{fig:base}, ignoring the ellipsis, the chances of getting an empty queue is 2/7 per pick, meaning two random picks yield an item approximately 9 times out of 10. 218 224 … … 221 227 \input{base.pstex_t} 222 228 \end{center} 223 \caption{ Relaxed FIFO list at the base of the scheduler:an array of strictly FIFO lists.224 The timestamp is in all nodes and cell arrays.}229 \caption{Loaded relaxed FIFO list base on an array of strictly FIFO lists. 230 A timestamp appears in each node and array cell.} 225 231 \label{fig:base} 226 232 \end{figure} … … 230 236 \input{empty.pstex_t} 231 237 \end{center} 232 \caption{ ``More empty'' state of the queue:the array contains many empty cells.}238 \caption{Underloaded relaxed FIFO list where the array contains many empty cells.} 233 239 \label{fig:empty} 234 240 \end{figure} 235 241 236 When the ready queue is \emph{more empty}, \ie several of the queues are empty,selecting a random queue for popping is less likely to yield a successful selection and more attempts are needed, resulting in a performance degradation.242 In an underloaded system, several of the queues are empty, so selecting a random queue for popping is less likely to yield a successful selection and more attempts are needed, resulting in a performance degradation. 237 243 Figure~\ref{fig:empty} shows an example with fewer elements, where the chances of getting an empty queue is 5/7 per pick, meaning two random picks yield an item only half the time. 238 244 Since the ready queue is not empty, the pop operation \emph{must} find an element before returning and therefore must retry. … … 262 268 \end{table} 263 269 264 Performance can be improved in case~D (Table~\ref{tab:perfcases})by adding information to help processors find which inner queues are used.270 Performance can be improved in Table~\ref{tab:perfcases} case~D by adding information to help processors find which inner queues are used. 265 271 This addition aims to avoid the cost of retrying the pop operation but does not affect contention on the underlying queues and can incur some management cost for both push and pop operations. 266 272 The approach used to encode this information can vary in density and be either global or local. … … 273 279 With a multi-word bitmask, this maximum limit can be increased arbitrarily, but it is not possible to check if the queue is empty by reading the bitmask atomically. 274 280 275 Finally, a dense bitmap, either single or multi-word, causes additional problems in case C (Table 1), because many processors are continuously scanning the bitmask to find the few available threads.281 Finally, a dense bitmap, either single or multi-word, causes additional problems in Table~\ref{tab:perfcases} case C, because many processors are continuously scanning the bitmask to find the few available threads. 276 282 This increased contention on the bitmask(s) reduces performance because of cache misses after updates and the bitmask is updated more frequently by the scanning processors racing to read and/or update that information. 277 283 This increased update frequency means the information in the bitmask is more often stale before a processor can use it to find an item, \ie mask read says there are available user threads but none on queue. … … 279 285 \begin{figure} 280 286 \begin{center} 281 {\resizebox{0.8\textwidth}{!}{\input{emptybit}}} 282 \end{center} 283 \caption{``More empty'' queue with added bitmask to indicate which array cells have items.} 287 {\resizebox{0.73\textwidth}{!}{\input{emptybit}}} 288 \end{center} 289 \vspace*{-5pt} 290 \caption{Underloaded queue with added bitmask to indicate which array cells have items.} 284 291 \label{fig:emptybit} 292 \begin{center} 293 {\resizebox{0.73\textwidth}{!}{\input{emptytree}}} 294 \end{center} 295 \vspace*{-5pt} 296 \caption{Underloaded queue with added binary search tree indicate which array cells have items.} 297 \label{fig:emptytree} 298 \begin{center} 299 {\resizebox{0.9\textwidth}{!}{\input{emptytls}}} 300 \end{center} 301 \vspace*{-5pt} 302 \caption{Underloaded queue with added per processor bitmask to indicate which array cells have items.} 303 \label{fig:emptytls} 285 304 \end{figure} 286 305 287 Figure~\ref{fig:emptytree} shows another approach using a hierarchical tree data-structure to reduce contention and has been shown to work in similar cases~\cite{ellen2007snzi}\footnote{This particular paper seems to be patented in the US. 288 How does that affect \CFA? Can I use it in my work?}. 289 However, this approach may lead to poorer performance in case~B (Table~\ref{tab:perfcases}) due to the inherent pointer chasing cost and already low contention cost in that case. 290 291 \begin{figure} 292 \begin{center} 293 {\resizebox{0.8\textwidth}{!}{\input{emptytree}}} 294 \end{center} 295 \caption{``More empty'' queue with added binary search tree indicate which array cells have items.} 296 \label{fig:emptytree} 297 \end{figure} 298 299 Finally, a third approach is to use dense information, similar to the bitmap, but have each thread keep its own independent copy of it. 306 Figure~\ref{fig:emptytree} shows an approach using a hierarchical tree data-structure to reduce contention and has been shown to work in similar cases~\cite{ellen2007snzi}. 307 However, this approach may lead to poorer performance in Table~\ref{tab:perfcases} case~B due to the inherent pointer chasing cost and already low contention cost in that case. 308 309 Figure~\ref{fig:emptytls} shows an approach using dense information, similar to the bitmap, but have each thread keep its own independent copy of it. 300 310 While this approach can offer good scalability \emph{and} low latency, the liveliness of the information can become a problem. 301 In the simple cases, local copies of which underlying queues are emptycan become stale and end-up not being useful for the pop operation.311 In the simple cases, local copies can become stale and end-up not being useful for the pop operation. 302 312 A more serious problem is that reliable information is necessary for some parts of this algorithm to be correct. 303 313 As mentioned in this section, processors must know \emph{reliably} whether the list is empty or not to decide if they can return \texttt{NULL} or if they must keep looking during a pop operation. 304 314 Section~\ref{sec:sleep} discusses another case where reliable information is required for the algorithm to be correct. 305 315 306 \begin{figure}307 \begin{center}308 \input{emptytls}309 \end{center}310 \caption{``More empty'' queue with added per processor bitmask to indicate which array cells have items.}311 \label{fig:emptytls}312 \end{figure}313 314 316 There is a fundamental tradeoff among these approach. 315 Dense global information about empty underlying queues helps zero-contention cases at the cost of high-contention case.316 Sparse global information helps high-contention cases but increases latency in zero-contention -cases,to read and ``aggregate'' the information\footnote{Hierarchical structures, \eg binary search tree, effectively aggregate information but follow pointer chains, learning information at each node.317 Dense global information about empty underlying queues helps zero-contention cases at the cost of the high-contention case. 318 Sparse global information helps high-contention cases but increases latency in zero-contention cases to read and ``aggregate'' the information\footnote{Hierarchical structures, \eg binary search tree, effectively aggregate information but follow pointer chains, learning information at each node. 317 319 Similarly, other sparse schemes need to read multiple cachelines to acquire all the information needed.}. 318 Finally, dense local information has both the advantages of low latency in zero-contention cases and scalability in high-contention cases. However the information can become stale making it difficult to use to ensure correctness. 320 Finally, dense local information has both the advantages of low latency in zero-contention cases and scalability in high-contention cases. 321 However, the information can become stale making it difficult to use to ensure correctness. 319 322 The fact that these solutions have these fundamental limits suggest to me a better solution that attempts to combine these properties in an interesting way. 320 323 Also, the lock discussed in Section~\ref{sec:resize} allows for solutions that adapt to the number of processors, which could also prove useful. … … 323 326 324 327 How much scalability is actually needed is highly debatable. 325 \emph{libfibre} \cite{libfibre} has compared favourably to other schedulers in webserver tests\cite{Karsten20} and uses a single atomic counter in its scheduling algorithm similarly to the proposed bitmask.328 \emph{libfibre}~\cite{libfibre} has compared favourably to other schedulers in webserver tests~\cite{Karsten20} and uses a single atomic counter in its scheduling algorithm similarly to the proposed bitmask. 326 329 As such, the single atomic instruction on a shared cacheline may be sufficiently performant. 327 330 328 I have built a prototype of this ready queue in the shape of a data queue, \ie nodes on the queue are structures with a single intrepresenting a thread and intrusive data fields.329 Using this prototype, I ran preliminary performance experiments thatconfirm the expected performance in Table~\ref{tab:perfcases}.330 However, these experiments only offer a hint at the actual performance of the scheduler since threads form more complex operations than simple integer nodes, \eg threads are not independent of each other,when a thread blocks some other thread must intervene to wake it.331 I have built a prototype of this ready queue in the shape of a data queue, \ie nodes on the queue are structures with a single $int$ representing a thread and intrusive data fields. 332 Using this prototype, preliminary performance experiments confirm the expected performance in Table~\ref{tab:perfcases}. 333 However, these experiments only offer a hint at the actual performance of the scheduler since threads are involved in more complex operations, \eg threads are not independent of each other: when a thread blocks some other thread must intervene to wake it. 331 334 332 335 I have also integrated this prototype into the \CFA runtime, but have not yet created performance experiments to compare results, as creating one-to-one comparisons between the prototype and the \CFA runtime will be complex. … … 345 348 Threads on a cluster are always scheduled on one of the processors of the cluster. 346 349 Currently, the runtime handles dynamically adding and removing processors from clusters at any time. 347 Since this is part of the existing design, the proposed scheduler must also support this behaviour.350 Since this feature is part of the existing design, the proposed scheduler must also support this behaviour. 348 351 However, dynamically resizing a cluster is considered a rare event associated with setup, tear down and major configuration changes. 349 352 This assumption is made both in the design of the proposed scheduler as well as in the original design of the \CFA runtime system. 350 353 As such, the proposed scheduler must honour the correctness of this behaviour but does not have any performance objectives with regard to resizing a cluster. 351 How long adding or removing processors takeand how much this disrupts the performance of other threads is considered a secondary concern since it should be amortized over long periods of times.354 That is, the time to add or remove processors and how much this disrupts the performance of other threads is considered a secondary concern since it should be amortized over long periods of times. 352 355 However, as mentioned in Section~\ref{sec:queue}, contention on the underlying queues can have a direct impact on performance. 353 356 The number of underlying queues must therefore be adjusted as the number of processors grows or shrinks. … … 371 374 372 375 There are possible alternatives to the reader-writer lock solution. 373 This problem is effectively a memory reclamation problem and as such there is a large body of research on the subject \cite{michael2004hazard, brown2015reclaiming}.376 This problem is effectively a memory reclamation problem and as such there is a large body of research on the subject~\cite{brown2015reclaiming, michael2004hazard}. 374 377 However, the reader-write lock-solution is simple and can be leveraged to solve other problems (\eg processor ordering and memory reclamation of threads), which makes it an attractive solution. 375 378 … … 401 404 Individual processors always finish scheduling user threads before looking for new work, which means that the last processor to go to sleep cannot miss threads scheduled from inside the cluster (if they do, that demonstrates the ready queue is not linearizable). 402 405 However, this guarantee does not hold if threads are scheduled from outside the cluster, either due to an external event like timers and I/O, or due to a user (or kernel) thread migrating from a different cluster. 403 In this case, missed signals can lead to the cluster deadlocking\footnote{Clusters should only deadlock in cases where a \CFA programmer \emph{actually} write \CFA code that leads to a deadlock.}.406 In this case, missed signals can lead to the cluster deadlocking\footnote{Clusters should only deadlock in cases where a \CFA programmer \emph{actually} writes \CFA code that leads to a deadlock.}. 404 407 Therefore, it is important that the scheduling of threads include a mechanism where signals \emph{cannot} be missed. 405 408 For performance reasons, it can be advantageous to have a secondary mechanism that allows signals to be missed in cases where it cannot lead to a deadlock. 406 To be safe, this process must include a ``handshake'' where it is guaranteed that either~: the sleeping processor notices that a user thread is scheduled after the sleeping processor signalled its intent to block or code scheduling threads sees the intent to sleep before scheduling and be able to wake-up the processor. 409 To be safe, this process must include a ``handshake'' where it is guaranteed that either: 410 \begin{enumerate} 411 \item 412 the sleeping processor notices that a user thread is scheduled after the sleeping processor signalled its intent to block or 413 \item 414 code scheduling threads sees the intent to sleep before scheduling and be able to wake-up the processor. 415 \end{enumerate} 407 416 This matter is complicated by the fact that pthreads and Linux offer few tools to implement this solution and no guarantee of ordering of threads waking up for most of these tools. 408 417 409 418 Another important issue is avoiding kernel threads sleeping and waking frequently because there is a significant operating-system cost. 410 This scenario happens when a program oscillates between high and low activity, needing most and then few erprocessors.419 This scenario happens when a program oscillates between high and low activity, needing most and then few processors. 411 420 A possible partial solution is to order the processors so that the one which most recently went to sleep is woken up. 412 421 This allows other sleeping processors to reach deeper sleep state (when these are available) while keeping ``hot'' processors warmer. … … 417 426 Processors that are unnecessarily unblocked lead to unnecessary contention, CPU usage, and power consumption, while too many sleeping processors can lead to suboptimal throughput. 418 427 Furthermore, transitions from sleeping to awake and vice versa also add unnecessary latency. 419 There is already a wealth of research on the subject \cite{schillings1996engineering, wiki:thunderherd} and I may use an existing approach for the idle-sleep heuristic in this project, \eg\cite{Karsten20}.428 There is already a wealth of research on the subject~\cite{schillings1996engineering, wiki:thunderherd} and I may use an existing approach for the idle-sleep heuristic in this project, \eg~\cite{Karsten20}. 420 429 421 430 \subsection{Asynchronous I/O} … … 432 441 an event-engine to (de)multiplex the operations, 433 442 \item 434 and a synchronous interface for users to use.443 and a synchronous interface for users. 435 444 \end{enumerate} 436 445 None of these components currently exist in \CFA and I will need to build all three for this project. 437 446 438 \paragraph{OS A bstraction}439 One fundamental part for converting blocking I/O operations into non-blocking onesis having an underlying asynchronous I/O interface to direct the I/O operations.447 \paragraph{OS Asynchronous Abstraction} 448 One fundamental part for converting blocking I/O operations into non-blocking is having an underlying asynchronous I/O interface to direct the I/O operations. 440 449 While there exists many different APIs for asynchronous I/O, it is not part of this proposal to create a novel API. 441 450 It is sufficient to make one work in the complex context of the \CFA runtime. 442 \uC uses the $select$ \cite{select} as its interface, which handles ttys, pipes and sockets, but not disk.451 \uC uses the $select$~\cite{select} as its interface, which handles ttys, pipes and sockets, but not disk. 443 452 $select$ entails significant complexity and is being replaced in UNIX operating systems, which make it a less interesting alternative. 444 Another popular interface is $epoll$ \cite{epoll}, which is supposed to be cheaper than $select$.445 However, $epoll$ also does not handle the file system and anecdotal evidence suggest it has problems with Linux pipes and $TTY$s.446 A popular cross-platform alternative is $libuv$ \cite{libuv}, which offers asynchronous sockets and asynchronous file system operations (among other features).453 Another popular interface is $epoll$~\cite{epoll}, which is supposed to be cheaper than $select$. 454 However, $epoll$ also does not handle the file system and anecdotal evidence suggest it has problems with Linux pipes and ttys. 455 A popular cross-platform alternative is $libuv$~\cite{libuv}, which offers asynchronous sockets and asynchronous file system operations (among other features). 447 456 However, as a full-featured library it includes much more than I need and could conflict with other features of \CFA unless significant effort is made to merge them together. 448 A very recent alternative that I am investigating is $io_uring$ \cite{io_uring}.457 A very recent alternative that I am investigating is $io_uring$~\cite{io_uring}. 449 458 It claims to address some of the issues with $epoll$ and my early investigating suggests that the claim is accurate. 450 $io_uring$ uses a much more general approach where system calls are registered to a queue and later executed by the kernel, rather than relying on system calls to return an error instead of blocking and subsequently waiting for changes on file descriptors.451 I believe this approach allows for fewer problems, \eg the manpage for $open$ \cite{open} states:459 $io_uring$ uses a much more general approach where system calls are registered to a queue and later executed by the kernel, rather than relying on system calls to support returning an error instead of blocking. 460 I believe this approach allows for fewer problems, \eg the manpage for $open$~\cite{open} states: 452 461 \begin{quote} 453 462 Note that [the $O_NONBLOCK$ flag] has no effect for regular files and block devices; … … 455 464 Since $O_NONBLOCK$ semantics might eventually be implemented, applications should not depend upon blocking behaviour when specifying this flag for regular files and block devices. 456 465 \end{quote} 457 This makes approach based on $epoll$/$select$ less reliable since they may not work for every file descriptors.458 For this reason, I plan to use $io_uring$ as the OS abstraction for the \CFA runtime unless further work shows problems I haven't encountered yet.459 However, only a small subset of the features are available in Ubuntu as of April 2020 \cite{wiki:ubuntu-linux}, which will limit performance comparisons.466 This makes approaches based on $select$/$epoll$ less reliable since they may not work for every file descriptors. 467 For this reason, I plan to use $io_uring$ as the OS abstraction for the \CFA runtime unless further work encounters a fatal problem. 468 However, only a small subset of the features are available in Ubuntu as of April 2020~\cite{wiki:ubuntu-linux}, which will limit performance comparisons. 460 469 I do not believe this will affect the comparison result. 461 470 462 471 \paragraph{Event Engine} 463 Laying on top of the asynchronous interface layeris the event engine.472 Above the OS asynchronous abstraction is the event engine. 464 473 This engine is responsible for multiplexing (batching) the synchronous I/O requests into asynchronous I/O requests and demultiplexing the results to appropriate blocked user threads. 465 474 This step can be straightforward for simple cases, but becomes quite complex when there are thousands of user threads performing both reads and writes, possibly on overlapping file descriptors. … … 478 487 The interface can be novel but it is preferable to match the existing POSIX interface when possible to be compatible with existing code. 479 488 Matching allows C programs written using this interface to be transparently converted to \CFA with minimal effort. 480 Where new functionality is needed, I will create a novel interfaceto fill gaps and provide advanced features.489 Where new functionality is needed, I will add novel interface extensions to fill gaps and provide advanced features. 481 490 482 491 … … 485 494 \section{Discussion} 486 495 I believe that runtime system and scheduling are still open topics. 487 Many ``state of the art'' production frameworks still use single-threaded event loops because of performance considerations, \eg \cite{nginx-design}, and, to my knowledge, no widely available system language offers modern threading facilities.496 Many ``state of the art'' production frameworks still use single-threaded event loops because of performance considerations, \eg~\cite{nginx-design}, and, to my knowledge, no widely available system language offers modern threading facilities. 488 497 I believe the proposed work offers a novel runtime and scheduling package, where existing work only offers fragments that users must assemble themselves when possible. 489 498 -
doc/theses/thierry_delisle_PhD/comp_II/img/system.fig
rae2c27a rc76bd34 1 #FIG 3.2 Produced by xfig version 3.2. 5c1 #FIG 3.2 Produced by xfig version 3.2.7b 2 2 Landscape 3 3 Center … … 36 36 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4500 3600 15 15 4500 3600 4515 3615 37 37 -6 38 6 3225 4125 4650 442539 6 4350 4200 4650 435040 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4425 4275 15 15 4425 4275 4440 429041 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4500 4275 15 15 4500 4275 4515 429042 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 4575 4275 15 15 4575 4275 4590 429043 -644 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3450 4275 225 150 3450 4275 3675 442545 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4050 4275 225 150 4050 4275 4275 442546 -647 6 6675 4125 7500 442548 6 7200 4200 7500 435049 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7275 4275 15 15 7275 4275 7290 429050 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7350 4275 15 15 7350 4275 7365 429051 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 7425 4275 15 15 7425 4275 7440 429052 -653 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6900 4275 225 150 6900 4275 7125 442554 -655 38 6 6675 3525 8025 3975 56 39 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 1 0 2 … … 79 62 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3975 2850 150 150 3975 2850 4125 2850 80 63 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 7200 2775 150 150 7200 2775 7350 2775 81 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 2250 4830 30 30 2250 4830 2280 48 6064 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 2250 4830 30 30 2250 4830 2280 4830 82 65 1 3 0 1 0 0 0 0 0 0.000 1 0.0000 7200 2775 30 30 7200 2775 7230 2805 83 66 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3525 3600 150 150 3525 3600 3675 3600 84 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3875 4800 100 100 3875 4800 3975 4800 85 1 1 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4650 4800 150 75 4650 4800 4800 4875 67 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4625 4838 100 100 4625 4838 4725 4838 86 68 2 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5 87 69 2400 4200 2400 3750 1950 3750 1950 4200 2400 4200 … … 153 135 1 1 1.00 45.00 90.00 154 136 7875 3750 7875 2325 7200 2325 7200 2550 137 2 2 1 1 -1 -1 0 0 -1 3.000 0 0 0 0 0 5 138 6975 4950 6750 4950 6750 4725 6975 4725 6975 4950 155 139 2 2 0 1 -1 -1 0 0 -1 0.000 0 0 0 0 0 5 156 140 5850 4950 5850 4725 5625 4725 5625 4950 5850 4950 157 2 2 1 1 -1 -1 0 0 -1 3.000 0 0 0 0 0 5 158 6975 4950 6750 4950 6750 4725 6975 4725 6975 4950 159 4 1 -1 0 0 0 10 0.0000 2 105 720 5550 4425 Processors\001 160 4 1 -1 0 0 0 10 0.0000 2 120 1005 4200 3225 Blocked Tasks\001 161 4 1 -1 0 0 0 10 0.0000 2 150 870 4200 3975 Ready Tasks\001 162 4 1 -1 0 0 0 10 0.0000 2 135 1095 7350 1725 Other Cluster(s)\001 163 4 1 -1 0 0 0 10 0.0000 2 105 840 4650 1725 User Cluster\001 164 4 1 -1 0 0 0 10 0.0000 2 150 615 2175 3675 Manager\001 165 4 1 -1 0 0 0 10 0.0000 2 105 990 2175 3525 Discrete-event\001 166 4 1 -1 0 0 0 10 0.0000 2 135 795 2175 4350 preemption\001 167 4 0 -1 0 0 0 10 0.0000 2 150 1290 2325 4875 generator/coroutine\001 168 4 0 -1 0 0 0 10 0.0000 2 120 270 4050 4875 task\001 169 4 0 -1 0 0 0 10 0.0000 2 105 450 7050 4875 cluster\001 170 4 0 -1 0 0 0 10 0.0000 2 105 660 5925 4875 processor\001 171 4 0 -1 0 0 0 10 0.0000 2 105 555 4875 4875 monitor\001 141 4 1 -1 0 0 0 10 0.0000 2 135 900 5550 4425 Processors\001 142 4 1 -1 0 0 0 10 0.0000 2 165 1170 4200 3975 Ready Threads\001 143 4 1 -1 0 0 0 10 0.0000 2 165 1440 7350 1725 Other Cluster(s)\001 144 4 1 -1 0 0 0 10 0.0000 2 135 1080 4650 1725 User Cluster\001 145 4 1 -1 0 0 0 10 0.0000 2 165 630 2175 3675 Manager\001 146 4 1 -1 0 0 0 10 0.0000 2 135 1260 2175 3525 Discrete-event\001 147 4 1 -1 0 0 0 10 0.0000 2 150 900 2175 4350 preemption\001 148 4 0 -1 0 0 0 10 0.0000 2 135 630 7050 4875 cluster\001 149 4 1 -1 0 0 0 10 0.0000 2 135 1350 4200 3225 Blocked Threads\001 150 4 0 -1 0 0 0 10 0.0000 2 135 540 4800 4875 thread\001 151 4 0 -1 0 0 0 10 0.0000 2 120 810 5925 4875 processor\001 152 4 0 -1 0 0 0 10 0.0000 2 165 1710 2325 4875 generator/coroutine\001 -
doc/user/Makefile
rae2c27a rc76bd34 55 55 56 56 ${DOCUMENT} : ${BASE}.ps 57 ps2pdf $<57 ps2pdf -dPDFSETTINGS=/prepress $< 58 58 59 59 ${BASE}.ps : ${BASE}.dvi -
doc/user/user.tex
rae2c27a rc76bd34 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Fri Mar 6 13:34:52202014 %% Update Count : 39 2413 %% Last Modified On : Mon Oct 5 08:57:29 2020 14 %% Update Count : 3998 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 30 30 \usepackage{upquote} % switch curled `'" to straight 31 31 \usepackage{calc} 32 \usepackage{xspace}33 32 \usepackage{varioref} % extended references 34 \usepackage{listings} % format program code 33 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig} 34 \renewcommand{\thesubfigure}{\alph{subfigure})} 35 35 \usepackage[flushmargin]{footmisc} % support label/reference in footnote 36 36 \usepackage{latexsym} % \Box glyph 37 37 \usepackage{mathptmx} % better math font with "times" 38 38 \usepackage[usenames]{color} 39 \input{common} % common CFA document macros 40 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref} 41 \usepackage{breakurl} 42 43 \usepackage[pagewise]{lineno} 44 \renewcommand{\linenumberfont}{\scriptsize\sffamily} 45 \usepackage[firstpage]{draftwatermark} 46 \SetWatermarkLightness{0.9} 47 48 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore 49 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR 50 % AFTER HYPERREF. 51 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 52 53 \setlength{\topmargin}{-0.45in} % move running title into header 54 \setlength{\headsep}{0.25in} 55 56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 57 58 \CFAStyle % use default CFA format-style 59 \lstnewenvironment{C++}[1][] % use C++ style 60 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}} 61 {} 62 39 \newcommand{\CFALatin}{} 63 40 % inline code ©...© (copyright symbol) emacs: C-q M-) 64 41 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-. … … 68 45 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ 69 46 % math escape $...$ (dollar symbol) 47 \input{common} % common CFA document macros 48 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref} 49 \usepackage{breakurl} 50 51 \renewcommand\footnoterule{\kern -3pt\rule{0.3\linewidth}{0.15pt}\kern 2pt} 52 53 \usepackage[pagewise]{lineno} 54 \renewcommand{\linenumberfont}{\scriptsize\sffamily} 55 \usepackage[firstpage]{draftwatermark} 56 \SetWatermarkLightness{0.9} 57 58 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore 59 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR 60 % AFTER HYPERREF. 61 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 62 63 \setlength{\topmargin}{-0.45in} % move running title into header 64 \setlength{\headsep}{0.25in} 65 66 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 67 68 \CFAStyle % use default CFA format-style 69 \lstnewenvironment{C++}[1][] % use C++ style 70 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}} 71 {} 72 73 \newsavebox{\myboxA} 74 \newsavebox{\myboxB} 70 75 71 76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 79 84 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}} 80 85 \newcommand{\KWC}{K-W C\xspace} 81 82 \newsavebox{\LstBox}83 86 84 87 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 253 256 254 257 The signature feature of \CFA is \emph{\Index{overload}able} \Index{parametric-polymorphic} functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a ©forall© clause (giving the language its name): 255 \begin{ lstlisting}258 \begin{cfa} 256 259 ®forall( otype T )® T identity( T val ) { return val; } 257 260 int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§ 258 \end{ lstlisting}261 \end{cfa} 259 262 % extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions. 260 263 \CFA{}\hspace{1pt}'s polymorphism was originally formalized by \Index*{Glen Ditchfield}\index{Ditchfield, Glen}~\cite{Ditchfield92}, and first implemented by \Index*{Richard Bilson}\index{Bilson, Richard}~\cite{Bilson03}. … … 275 278 \begin{comment} 276 279 A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array: 277 \begin{ lstlisting}280 \begin{cfa} 278 281 void * bsearch( const void * key, const void * base, size_t dim, size_t size, 279 282 int (* compar)( const void *, const void * )); … … 284 287 double key = 5.0, vals[10] = { /* 10 sorted floating values */ }; 285 288 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§ 286 \end{ lstlisting}289 \end{cfa} 287 290 which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers: 288 \begin{ lstlisting}291 \begin{cfa} 289 292 forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) { 290 293 int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ } … … 297 300 double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§ 298 301 int posn = bsearch( 5.0, vals, 10 ); 299 \end{ lstlisting}302 \end{cfa} 300 303 The nested function ©comp© provides the hidden interface from typed \CFA to untyped (©void *©) C, plus the cast of the result. 301 304 Providing a hidden ©comp© function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope. … … 305 308 \CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations. 306 309 For example, it is possible to write a type-safe \CFA wrapper ©malloc© based on the C ©malloc©: 307 \begin{ lstlisting}310 \begin{cfa} 308 311 forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); } 309 312 int * ip = malloc(); §\C{// select type and size from left-hand side}§ 310 313 double * dp = malloc(); 311 314 struct S {...} * sp = malloc(); 312 \end{ lstlisting}315 \end{cfa} 313 316 where the return type supplies the type/size of the allocation, which is impossible in most type systems. 314 317 \end{comment} … … 943 946 the same level as a ©case© clause; the target label may be case ©default©, but only associated 944 947 with the current ©switch©/©choose© statement. 945 946 947 \subsection{Loop Control}948 949 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).950 \begin{itemize}951 \item952 The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M.953 \item954 An empty conditional implies comparison value of ©1© (true).955 \item956 A comparison N is implicit up-to exclusive range [0,N©®)®©.957 \item958 A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.959 \item960 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.961 \item962 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.963 \item964 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.965 \item966 The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©.967 \item968 ©0© is the implicit start value;969 \item970 ©1© is the implicit increment value.971 \item972 The up-to range uses operator ©+=© for increment;973 \item974 The down-to range uses operator ©-=© for decrement.975 \item976 ©@© means put nothing in this field.977 \item978 ©:© means start another index.979 \end{itemize}980 948 981 949 \begin{figure} … … 1086 1054 1087 1055 1056 \subsection{Loop Control} 1057 1058 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}). 1059 \begin{itemize} 1060 \item 1061 The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M. 1062 \item 1063 An empty conditional implies comparison value of ©1© (true). 1064 \item 1065 A comparison N is implicit up-to exclusive range [0,N©®)®©. 1066 \item 1067 A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©. 1068 \item 1069 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©. 1070 \item 1071 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©. 1072 \item 1073 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©. 1074 \item 1075 The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©. 1076 \item 1077 ©0© is the implicit start value; 1078 \item 1079 ©1© is the implicit increment value. 1080 \item 1081 The up-to range uses operator ©+=© for increment; 1082 \item 1083 The down-to range uses operator ©-=© for decrement. 1084 \item 1085 ©@© means put nothing in this field. 1086 \item 1087 ©:© means start another index. 1088 \end{itemize} 1089 1090 1088 1091 %\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}} 1089 1092 \subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}} … … 1095 1098 for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement. 1096 1099 \VRef[Figure]{f:MultiLevelExit} shows ©continue© and ©break© indicating the specific control structure, and the corresponding C program using only ©goto© and labels. 1097 The innermost loop has 7exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.1100 The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s. 1098 1101 1099 1102 \begin{figure} 1100 \begin{tabular}{@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 1101 \multicolumn{1}{@{\hspace{\parindentlnth}}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}} \\ 1102 \begin{cfa} 1103 ®LC:® { 1104 ... §declarations§ ... 1105 ®LS:® switch ( ... ) { 1106 case 3: 1107 ®LIF:® if ( ... ) { 1108 ®LF:® for ( ... ) { 1109 ®LW:® while ( ... ) { 1110 ... break ®LC®; ... 1111 ... break ®LS®; ... 1112 ... break ®LIF®; ... 1113 ... continue ®LF;® ... 1114 ... break ®LF®; ... 1115 ... continue ®LW®; ... 1116 ... break ®LW®; ... 1117 } // while 1118 } // for 1119 } else { 1120 ... break ®LIF®; ... 1121 } // if 1122 } // switch 1103 \centering 1104 \begin{lrbox}{\myboxA} 1105 \begin{cfa}[tabsize=3] 1106 ®Compound:® { 1107 ®Try:® try { 1108 ®For:® for ( ... ) { 1109 ®While:® while ( ... ) { 1110 ®Do:® do { 1111 ®If:® if ( ... ) { 1112 ®Switch:® switch ( ... ) { 1113 case 3: 1114 ®break Compound®; 1115 ®break Try®; 1116 ®break For®; /* or */ ®continue For®; 1117 ®break While®; /* or */ ®continue While®; 1118 ®break Do®; /* or */ ®continue Do®; 1119 ®break If®; 1120 ®break Switch®; 1121 } // switch 1122 } else { 1123 ... ®break If®; ... // terminate if 1124 } // if 1125 } while ( ... ); // do 1126 } // while 1127 } // for 1128 } ®finally® { // always executed 1129 } // try 1123 1130 } // compound 1124 1131 \end{cfa} 1125 & 1126 \begin{cfa} 1132 \end{lrbox} 1133 1134 \begin{lrbox}{\myboxB} 1135 \begin{cfa}[tabsize=3] 1127 1136 { 1128 ... §declarations§ ... 1129 switch ( ... ) { 1130 case 3: 1131 if ( ... ) { 1132 for ( ... ) { 1133 while ( ... ) { 1134 ... goto ®LC®; ... 1135 ... goto ®LS®; ... 1136 ... goto ®LIF®; ... 1137 ... goto ®LFC®; ... 1138 ... goto ®LFB®; ... 1139 ... goto ®LWC®; ... 1140 ... goto ®LWB®; ... 1141 ®LWC®: ; } ®LWB:® ; 1142 ®LFC:® ; } ®LFB:® ; 1143 } else { 1144 ... goto ®LIF®; ... 1145 } ®L3:® ; 1146 } ®LS:® ; 1147 } ®LC:® ; 1148 \end{cfa} 1149 & 1150 \begin{cfa} 1151 1152 1153 1154 1155 1156 1157 1158 // terminate compound 1159 // terminate switch 1160 // terminate if 1161 // continue loop 1162 // terminate loop 1163 // continue loop 1164 // terminate loop 1165 1166 1167 1168 // terminate if 1169 1170 1171 1172 \end{cfa} 1173 \end{tabular} 1137 1138 ®ForC:® for ( ... ) { 1139 ®WhileC:® while ( ... ) { 1140 ®DoC:® do { 1141 if ( ... ) { 1142 switch ( ... ) { 1143 case 3: 1144 ®goto Compound®; 1145 ®goto Try®; 1146 ®goto ForB®; /* or */ ®goto ForC®; 1147 ®goto WhileB®; /* or */ ®goto WhileC®; 1148 ®goto DoB®; /* or */ ®goto DoC®; 1149 ®goto If®; 1150 ®goto Switch®; 1151 } ®Switch:® ; 1152 } else { 1153 ... ®goto If®; ... // terminate if 1154 } ®If:®; 1155 } while ( ... ); ®DoB:® ; 1156 } ®WhileB:® ; 1157 } ®ForB:® ; 1158 1159 1160 } ®Compound:® ; 1161 \end{cfa} 1162 \end{lrbox} 1163 1164 \subfloat[\CFA]{\label{f:CFibonacci}\usebox\myboxA} 1165 \hspace{2pt} 1166 \vrule 1167 \hspace{2pt} 1168 \subfloat[C]{\label{f:CFAFibonacciGen}\usebox\myboxB} 1174 1169 \caption{Multi-level Exit} 1175 1170 \label{f:MultiLevelExit} … … 1426 1421 try { 1427 1422 f(...); 1428 } catch( E e ; §boolean-predicate§ ) { §\C [8cm]{// termination handler}§1423 } catch( E e ; §boolean-predicate§ ) { §\C{// termination handler}§ 1429 1424 // recover and continue 1430 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler} \CRT§1425 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§ 1431 1426 // repair and return 1432 1427 } finally { … … 3491 3486 For implicit formatted input, the common case is reading a sequence of values separated by whitespace, where the type of an input constant must match with the type of the input variable. 3492 3487 \begin{cquote} 3493 \begin{lrbox}{\ LstBox}3488 \begin{lrbox}{\myboxA} 3494 3489 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 3495 3490 int x; double y char z; … … 3497 3492 \end{lrbox} 3498 3493 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{3em}}l@{}} 3499 \multicolumn{1}{@{}l@{}}{\usebox\ LstBox} \\3494 \multicolumn{1}{@{}l@{}}{\usebox\myboxA} \\ 3500 3495 \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}} & \multicolumn{1}{c}{\textbf{Python}} \\ 3501 3496 \begin{cfa}[aboveskip=0pt,belowskip=0pt] … … 6672 6667 For example, an initial alignment and fill capability are preserved during a resize copy so the copy has the same alignment and extended storage is filled. 6673 6668 Without sticky properties it is dangerous to use ©realloc©, resulting in an idiom of manually performing the reallocation to maintain correctness. 6669 \begin{cfa} 6670 6671 \end{cfa} 6674 6672 6675 6673 \CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in … … 6721 6719 6722 6720 // §\CFA§ safe general allocation, fill, resize, alignment, array 6723 T * alloc( void );§\indexc{alloc}§ 6724 T * alloc( size_t dim ); 6725 T * alloc( T ptr[], size_t dim ); 6726 T * alloc_set( char fill );§\indexc{alloc_set}§ 6727 T * alloc_set( T fill ); 6728 T * alloc_set( size_t dim, char fill ); 6729 T * alloc_set( size_t dim, T fill ); 6730 T * alloc_set( size_t dim, const T fill[] ); 6731 T * alloc_set( T ptr[], size_t dim, char fill ); 6732 6733 T * alloc_align( size_t align ); 6734 T * alloc_align( size_t align, size_t dim ); 6735 T * alloc_align( T ptr[], size_t align ); // aligned realloc array 6736 T * alloc_align( T ptr[], size_t align, size_t dim ); // aligned realloc array 6737 T * alloc_align_set( size_t align, char fill ); 6738 T * alloc_align_set( size_t align, T fill ); 6739 T * alloc_align_set( size_t align, size_t dim, char fill ); 6740 T * alloc_align_set( size_t align, size_t dim, T fill ); 6741 T * alloc_align_set( size_t align, size_t dim, const T fill[] ); 6742 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); 6721 T * alloc( void );§\indexc{alloc}§ §\C[3.5in]{// variable, T size}§ 6722 T * alloc( size_t dim ); §\C{// array[dim], T size elements}§ 6723 T * alloc( T ptr[], size_t dim ); §\C{// realloc array[dim], T size elements}§ 6724 6725 T * alloc_set( char fill );§\indexc{alloc_set}§ §\C{// variable, T size, fill bytes with value}§ 6726 T * alloc_set( T fill ); §\C{// variable, T size, fill with value}§ 6727 T * alloc_set( size_t dim, char fill ); §\C{// array[dim], T size elements, fill bytes with value}§ 6728 T * alloc_set( size_t dim, T fill ); §\C{// array[dim], T size elements, fill elements with value}§ 6729 T * alloc_set( size_t dim, const T fill[] ); §\C{// array[dim], T size elements, fill elements with array}§ 6730 T * alloc_set( T ptr[], size_t dim, char fill ); §\C{// realloc array[dim], T size elements, fill bytes with value}§ 6731 6732 T * alloc_align( size_t align ); §\C{// aligned variable, T size}§ 6733 T * alloc_align( size_t align, size_t dim ); §\C{// aligned array[dim], T size elements}§ 6734 T * alloc_align( T ptr[], size_t align ); §\C{// realloc new aligned array}§ 6735 T * alloc_align( T ptr[], size_t align, size_t dim ); §\C{// realloc new aligned array[dim]}§ 6736 6737 T * alloc_align_set( size_t align, char fill ); §\C{// aligned variable, T size, fill bytes with value}§ 6738 T * alloc_align_set( size_t align, T fill ); §\C{// aligned variable, T size, fill with value}§ 6739 T * alloc_align_set( size_t align, size_t dim, char fill ); §\C{// aligned array[dim], T size elements, fill bytes with value}§ 6740 T * alloc_align_set( size_t align, size_t dim, T fill ); §\C{// aligned array[dim], T size elements, fill elements with value}§ 6741 T * alloc_align_set( size_t align, size_t dim, const T fill[] ); §\C{// aligned array[dim], T size elements, fill elements with array}§ 6742 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); §\C{// realloc new aligned array[dim], fill new bytes with value}§ 6743 6743 6744 6744 // §\CFA§ safe initialization/copy, i.e., implicit size specification -
libcfa/configure.ac
rae2c27a rc76bd34 166 166 AH_TEMPLATE([CFA_HAVE_IORING_OP_PROVIDE_BUFFERS],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_PROVIDE_BUFFERS.]) 167 167 AH_TEMPLATE([CFA_HAVE_IORING_OP_REMOVE_BUFFER],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_REMOVE_BUFFER.]) 168 AH_TEMPLATE([CFA_HAVE_IORING_OP_TEE],[Defined if io_uring support is present when compiling libcfathread and supports the operation IORING_OP_TEE.]) 168 169 AH_TEMPLATE([CFA_HAVE_IOSQE_FIXED_FILE],[Defined if io_uring support is present when compiling libcfathread and supports the flag FIXED_FILE.]) 169 170 AH_TEMPLATE([CFA_HAVE_IOSQE_IO_DRAIN],[Defined if io_uring support is present when compiling libcfathread and supports the flag IO_DRAIN.]) … … 173 174 AH_TEMPLATE([CFA_HAVE_SPLICE_F_FD_IN_FIXED],[Defined if io_uring support is present when compiling libcfathread and supports the flag SPLICE_F_FD_IN_FIXED.]) 174 175 AH_TEMPLATE([CFA_HAVE_IORING_SETUP_ATTACH_WQ],[Defined if io_uring support is present when compiling libcfathread and supports the flag IORING_SETUP_ATTACH_WQ.]) 175 AH_TEMPLATE([HAVE_PREADV2],[Defined if preadv2 support is present when compiling libcfathread.]) 176 AH_TEMPLATE([HAVE_PWRITEV2],[Defined if pwritev2 support is present when compiling libcfathread.]) 176 AH_TEMPLATE([CFA_HAVE_PREADV2],[Defined if preadv2 support is present when compiling libcfathread.]) 177 AH_TEMPLATE([CFA_HAVE_PWRITEV2],[Defined if pwritev2 support is present when compiling libcfathread.]) 178 AH_TEMPLATE([CFA_HAVE_PWRITEV2],[Defined if pwritev2 support is present when compiling libcfathread.]) 179 AH_TEMPLATE([CFA_HAVE_STATX],[Defined if statx support is present when compiling libcfathread.]) 180 AH_TEMPLATE([CFA_HAVE_OPENAT2],[Defined if openat2 support is present when compiling libcfathread.]) 177 181 AH_TEMPLATE([__CFA_NO_STATISTICS__],[Defined if libcfathread was compiled without support for statistics.]) 178 182 179 define(ioring_ops, [IORING_OP_NOP,IORING_OP_READV,IORING_OP_WRITEV,IORING_OP_FSYNC,IORING_OP_READ_FIXED,IORING_OP_WRITE_FIXED,IORING_OP_POLL_ADD,IORING_OP_POLL_REMOVE,IORING_OP_SYNC_FILE_RANGE,IORING_OP_SENDMSG,IORING_OP_RECVMSG,IORING_OP_TIMEOUT,IORING_OP_TIMEOUT_REMOVE,IORING_OP_ACCEPT,IORING_OP_ASYNC_CANCEL,IORING_OP_LINK_TIMEOUT,IORING_OP_CONNECT,IORING_OP_FALLOCATE,IORING_OP_OPENAT,IORING_OP_CLOSE,IORING_OP_FILES_UPDATE,IORING_OP_STATX,IORING_OP_READ,IORING_OP_WRITE,IORING_OP_FADVISE,IORING_OP_MADVISE,IORING_OP_SEND,IORING_OP_RECV,IORING_OP_OPENAT2,IORING_OP_EPOLL_CTL,IORING_OP_SPLICE,IORING_OP_PROVIDE_BUFFERS,IORING_OP_REMOVE_BUFFER ])183 define(ioring_ops, [IORING_OP_NOP,IORING_OP_READV,IORING_OP_WRITEV,IORING_OP_FSYNC,IORING_OP_READ_FIXED,IORING_OP_WRITE_FIXED,IORING_OP_POLL_ADD,IORING_OP_POLL_REMOVE,IORING_OP_SYNC_FILE_RANGE,IORING_OP_SENDMSG,IORING_OP_RECVMSG,IORING_OP_TIMEOUT,IORING_OP_TIMEOUT_REMOVE,IORING_OP_ACCEPT,IORING_OP_ASYNC_CANCEL,IORING_OP_LINK_TIMEOUT,IORING_OP_CONNECT,IORING_OP_FALLOCATE,IORING_OP_OPENAT,IORING_OP_CLOSE,IORING_OP_FILES_UPDATE,IORING_OP_STATX,IORING_OP_READ,IORING_OP_WRITE,IORING_OP_FADVISE,IORING_OP_MADVISE,IORING_OP_SEND,IORING_OP_RECV,IORING_OP_OPENAT2,IORING_OP_EPOLL_CTL,IORING_OP_SPLICE,IORING_OP_PROVIDE_BUFFERS,IORING_OP_REMOVE_BUFFER,IORING_OP_TEE]) 180 184 define(ioring_flags, [IOSQE_FIXED_FILE,IOSQE_IO_DRAIN,IOSQE_ASYNC,IOSQE_IO_LINK,IOSQE_IO_HARDLINK,SPLICE_F_FD_IN_FIXED,IORING_SETUP_ATTACH_WQ]) 181 185 … … 222 226 ]) 223 227 ]) 224 AC_CHECK_FUNCS([preadv2 pwritev2]) 228 AC_CHECK_FUNC([preadv2], [AC_DEFINE([CFA_HAVE_PREADV2])]) 229 AC_CHECK_FUNC([pwritev2], [AC_DEFINE([CFA_HAVE_PWRITEV2])]) 225 230 226 231 AC_CONFIG_FILES([ … … 229 234 prelude/Makefile 230 235 ]) 236 AC_CONFIG_FILES([src/concurrency/io/call.cfa], [python3 ${srcdir}/src/concurrency/io/call.cfa.in > src/concurrency/io/call.cfa]) 231 237 232 238 AC_CONFIG_HEADERS(prelude/defines.hfa) -
libcfa/prelude/defines.hfa.in
rae2c27a rc76bd34 117 117 118 118 /* Defined if io_uring support is present when compiling libcfathread and 119 supports the operation IORING_OP_TEE. */ 120 #undef CFA_HAVE_IORING_OP_TEE 121 122 /* Defined if io_uring support is present when compiling libcfathread and 119 123 supports the operation IORING_OP_TIMEOUT. */ 120 124 #undef CFA_HAVE_IORING_OP_TIMEOUT … … 163 167 #undef CFA_HAVE_LINUX_IO_URING_H 164 168 169 /* Defined if openat2 support is present when compiling libcfathread. */ 170 #undef CFA_HAVE_OPENAT2 171 172 /* Defined if preadv2 support is present when compiling libcfathread. */ 173 #undef CFA_HAVE_PREADV2 174 175 /* Defined if pwritev2 support is present when compiling libcfathread. */ 176 #undef CFA_HAVE_PWRITEV2 177 165 178 /* Defined if io_uring support is present when compiling libcfathread and 166 179 supports the flag SPLICE_F_FD_IN_FIXED. */ 167 180 #undef CFA_HAVE_SPLICE_F_FD_IN_FIXED 168 181 182 /* Defined if statx support is present when compiling libcfathread. */ 183 #undef CFA_HAVE_STATX 184 169 185 /* Location of include files. */ 170 186 #undef CFA_INCDIR … … 188 204 #undef HAVE_MEMORY_H 189 205 190 /* Define to 1 if you have the `preadv2' function. */191 #undef HAVE_PREADV2192 193 /* Define to 1 if you have the `pwritev2' function. */194 #undef HAVE_PWRITEV2195 196 206 /* Define to 1 if you have the <stdint.h> header file. */ 197 207 #undef HAVE_STDINT_H -
libcfa/src/Makefile.am
rae2c27a rc76bd34 62 62 iterator.hfa \ 63 63 limits.hfa \ 64 memory.hfa \ 64 65 parseargs.hfa \ 65 66 rational.hfa \ … … 87 88 inst_thread_headers_nosrc = \ 88 89 bits/random.hfa \ 90 concurrency/clib/cfathread.h \ 89 91 concurrency/invoke.h \ 90 92 concurrency/kernel/fwd.hfa … … 102 104 concurrency/alarm.cfa \ 103 105 concurrency/alarm.hfa \ 106 concurrency/clib/cfathread.cfa \ 104 107 concurrency/CtxSwitch-@ARCHITECTURE@.S \ 105 108 concurrency/invoke.c \ … … 107 110 concurrency/io/setup.cfa \ 108 111 concurrency/io/types.hfa \ 109 concurrency/io call.cfa \112 concurrency/io/call.cfa \ 110 113 concurrency/iofwd.hfa \ 111 114 concurrency/kernel_private.hfa \ -
libcfa/src/bits/locks.hfa
rae2c27a rc76bd34 164 164 165 165 struct $thread; 166 extern void park( __cfaabi_dbg_ctx_param);167 extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2);166 extern void park( void ); 167 extern void unpark( struct $thread * this ); 168 168 static inline struct $thread * active_thread (); 169 169 … … 191 191 /* paranoid */ verify( expected == 0p ); 192 192 if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 193 park( __cfaabi_dbg_ctx);193 park(); 194 194 return true; 195 195 } … … 210 210 else { 211 211 if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 212 unpark( expected __cfaabi_dbg_ctx2);212 unpark( expected ); 213 213 return true; 214 214 } … … 244 244 /* paranoid */ verify( expected == 0p ); 245 245 if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 246 park( __cfaabi_dbg_ctx);246 park(); 247 247 /* paranoid */ verify( this.ptr == 1p ); 248 248 return true; … … 256 256 struct $thread * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST); 257 257 if( got == 0p ) return false; 258 unpark( got __cfaabi_dbg_ctx2);258 unpark( got ); 259 259 return true; 260 260 } … … 357 357 struct oneshot * expected = this.ptr; 358 358 // was this abandoned? 359 if( expected == 3p ) { free( &this ); return false; } 359 #if defined(__GNUC__) && __GNUC__ >= 7 360 #pragma GCC diagnostic push 361 #pragma GCC diagnostic ignored "-Wfree-nonheap-object" 362 #endif 363 if( expected == 3p ) { free( &this ); return false; } 364 #if defined(__GNUC__) && __GNUC__ >= 7 365 #pragma GCC diagnostic pop 366 #endif 360 367 361 368 /* paranoid */ verify( expected != 1p ); // Future is already fulfilled, should not happen -
libcfa/src/concurrency/CtxSwitch-i386.S
rae2c27a rc76bd34 10 10 // Created On : Tue Dec 6 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Aug 16 08:46:22202013 // Update Count : 412 // Last Modified On : Sun Sep 6 18:23:37 2020 13 // Update Count : 5 14 14 // 15 15 … … 35 35 36 36 // Copy the "from" context argument from the stack to register eax 37 // Return address is at 0(%esp), with parameters following 37 // Return address is at 0(%esp), with parameters following. 38 38 39 39 movl 4(%esp),%eax … … 50 50 movl %ebp,FP_OFFSET(%eax) 51 51 52 // Copy the "to" context argument from the stack to register eax 53 // Having pushed three words (= 12 bytes) on the stack, the54 // argument is now at 8 + 12 = 20(%esp)52 // Copy the "to" context argument from the stack to register eax. Having 53 // pushed 3 words (= 12 bytes) on the stack, the argument is now at 54 // 8 + 12 = 20(%esp). 55 55 56 56 movl 20(%esp),%eax -
libcfa/src/concurrency/alarm.cfa
rae2c27a rc76bd34 130 130 131 131 register_self( &node ); 132 park( __cfaabi_dbg_ctx);132 park(); 133 133 134 134 /* paranoid */ verify( !node.set ); -
libcfa/src/concurrency/coroutine.cfa
rae2c27a rc76bd34 47 47 48 48 //----------------------------------------------------------------------------- 49 FORALL_DATA_INSTANCE(CoroutineCancelled, 50 (dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) 51 52 struct __cfaehm_node { 53 struct _Unwind_Exception unwind_exception; 54 struct __cfaehm_node * next; 55 int handler_index; 56 }; 57 58 forall(dtype T) 59 void mark_exception(CoroutineCancelled(T) *) {} 60 61 forall(dtype T | sized(T)) 62 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) { 63 dst->the_coroutine = src->the_coroutine; 64 dst->the_exception = src->the_exception; 65 } 66 67 forall(dtype T) 68 const char * msg(CoroutineCancelled(T) *) { 69 return "CoroutineCancelled(...)"; 70 } 71 72 // This code should not be inlined. It is the error path on resume. 73 forall(dtype T | is_coroutine(T)) 74 void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ) { 75 verify( desc->cancellation ); 76 desc->state = Cancelled; 77 exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation); 78 79 CoroutineCancelled(T) except; 80 except.the_coroutine = &cor; 81 except.the_exception = except; 82 throwResume except; 83 84 except->virtual_table->free( except ); 85 free( desc->cancellation ); 86 desc->cancellation = 0p; 87 } 88 89 //----------------------------------------------------------------------------- 49 90 // Global state variables 50 91 … … 180 221 this->storage->limit = storage; 181 222 this->storage->base = (void*)((intptr_t)storage + size); 223 this->storage->exception_context.top_resume = 0p; 224 this->storage->exception_context.current_exception = 0p; 182 225 __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage; 183 226 *istorage |= userStack ? 0x1 : 0x0; -
libcfa/src/concurrency/coroutine.hfa
rae2c27a rc76bd34 18 18 #include <assert.h> 19 19 #include "invoke.h" 20 #include "../exception.hfa" 21 22 //----------------------------------------------------------------------------- 23 // Exception thrown from resume when a coroutine stack is cancelled. 24 // Should not have to be be sized (see trac #196). 25 FORALL_DATA_EXCEPTION(CoroutineCancelled, 26 (dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) ( 27 coroutine_t * the_coroutine; 28 exception_t * the_exception; 29 ); 30 31 forall(dtype T) 32 void mark_exception(CoroutineCancelled(T) *); 33 34 forall(dtype T | sized(T)) 35 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src); 36 37 forall(dtype T) 38 const char * msg(CoroutineCancelled(T) *); 20 39 21 40 //----------------------------------------------------------------------------- … … 23 42 // Anything that implements this trait can be resumed. 24 43 // Anything that is resumed is a coroutine. 25 trait is_coroutine(dtype T) { 26 void main(T & this); 27 $coroutine * get_coroutine(T & this); 44 trait is_coroutine(dtype T | sized(T) 45 | is_resumption_exception(CoroutineCancelled(T)) 46 | VTABLE_ASSERTION(CoroutineCancelled, (T))) { 47 void main(T & this); 48 $coroutine * get_coroutine(T & this); 28 49 }; 29 50 … … 112 133 } 113 134 } 135 136 forall(dtype T | is_coroutine(T)) 137 void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ); 114 138 115 139 // Resume implementation inlined for performance … … 145 169 // always done for performance testing 146 170 $ctx_switch( src, dst ); 171 if ( unlikely(dst->cancellation) ) { 172 __cfaehm_cancelled_coroutine( cor, dst ); 173 } 147 174 148 175 return cor; -
libcfa/src/concurrency/exception.cfa
rae2c27a rc76bd34 57 57 58 58 STOP_AT_END_FUNCTION(coroutine_cancelstop, 59 // TODO: Instead pass information to the last resumer. 59 struct $coroutine * src = ($coroutine *)stop_param; 60 struct $coroutine * dst = src->last; 61 62 $ctx_switch( src, dst ); 60 63 abort(); 61 64 ) -
libcfa/src/concurrency/exception.hfa
rae2c27a rc76bd34 18 18 #include "bits/defs.hfa" 19 19 #include "invoke.h" 20 struct _Unwind_Exception;21 22 // It must also be usable as a C header file.23 20 24 21 #ifdef __cforall 25 22 extern "C" { 23 24 #define HIDE_EXPORTS 26 25 #endif 26 #include "unwind.h" 27 27 28 28 struct exception_context_t * this_exception_context(void) OPTIONAL_THREAD; … … 32 32 33 33 #ifdef __cforall 34 #undef HIDE_EXPORTS 34 35 } 35 36 #endif -
libcfa/src/concurrency/invoke.h
rae2c27a rc76bd34 68 68 }; 69 69 70 enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active };70 enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled }; 71 71 72 72 struct $coroutine { … … 93 93 94 94 }; 95 // Wrapper for gdb 96 struct cfathread_coroutine_t { struct $coroutine debug; }; 95 97 96 98 static inline struct __stack_t * __get_stack( struct $coroutine * cor ) { … … 129 131 struct __condition_node_t * dtor_node; 130 132 }; 133 // Wrapper for gdb 134 struct cfathread_monitor_t { struct $monitor debug; }; 131 135 132 136 struct __monitor_group_t { … … 186 190 } node; 187 191 188 #ifdef __CFA_DEBUG__ 189 // previous function to park/unpark the thread 190 const char * park_caller; 191 int park_result; 192 enum __Coroutine_State park_state; 193 bool park_stale; 194 const char * unpark_caller; 195 int unpark_result; 196 enum __Coroutine_State unpark_state; 197 bool unpark_stale; 192 #if defined( __CFA_WITH_VERIFY__ ) 193 unsigned long long canary; 198 194 #endif 199 195 }; 196 // Wrapper for gdb 197 struct cfathread_thread_t { struct $thread debug; }; 200 198 201 199 #ifdef __CFA_DEBUG__ -
libcfa/src/concurrency/io.cfa
rae2c27a rc76bd34 69 69 if( block ) { 70 70 enable_interrupts( __cfaabi_dbg_ctx ); 71 park( __cfaabi_dbg_ctx);71 park(); 72 72 disable_interrupts(); 73 73 } … … 97 97 98 98 if(nextt) { 99 unpark( nextt __cfaabi_dbg_ctx2);99 unpark( nextt ); 100 100 enable_interrupts( __cfaabi_dbg_ctx ); 101 101 return true; … … 159 159 160 160 static inline void process(struct io_uring_cqe & cqe ) { 161 struct __io_user_data_t * data = (struct __io_user_data_t *)(uintptr_t)cqe.user_data; 162 __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", data, cqe.res, data->thrd ); 163 164 data->result = cqe.res; 165 post( data->sem ); 161 struct io_future_t * future = (struct io_future_t *)(uintptr_t)cqe.user_data; 162 __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", future, cqe.res, data->thrd ); 163 164 fulfil( *future, cqe.res ); 166 165 } 167 166 -
libcfa/src/concurrency/io/setup.cfa
rae2c27a rc76bd34 147 147 static void * iopoll_loop( __attribute__((unused)) void * args ) { 148 148 __processor_id_t id; 149 id.full_proc = false; 149 150 id.id = doregister(&id); 150 151 __cfaabi_dbg_print_safe( "Kernel : IO poller thread starting\n" ); … … 246 247 thrd.link.next = 0p; 247 248 thrd.link.prev = 0p; 248 __cfaabi_dbg_debug_do( thrd.unpark_stale = true );249 249 250 250 // Fixup the thread state … … 266 266 267 267 // unpark the fast io_poller 268 unpark( &thrd __cfaabi_dbg_ctx2);268 unpark( &thrd ); 269 269 } 270 270 else { … … 275 275 } 276 276 } else { 277 unpark( &thrd __cfaabi_dbg_ctx2);277 unpark( &thrd ); 278 278 } 279 279 -
libcfa/src/concurrency/io/types.hfa
rae2c27a rc76bd34 16 16 #pragma once 17 17 18 extern "C" { 19 #include <linux/types.h> 20 } 21 22 #include "bits/locks.hfa" 23 18 24 #if defined(CFA_HAVE_LINUX_IO_URING_H) 19 extern "C" {20 #include <linux/types.h>21 }22 23 #include "bits/locks.hfa"24 25 25 #define LEADER_LOCK 26 26 struct __leaderlock_t { … … 101 101 }; 102 102 103 104 //-----------------------------------------------------------------------105 // IO user data106 struct __io_user_data_t {107 __s32 result;108 oneshot sem;109 };110 111 103 //----------------------------------------------------------------------- 112 104 // Misc … … 143 135 void __ioctx_prepare_block($io_ctx_thread & ctx, struct epoll_event & ev); 144 136 #endif 137 138 //----------------------------------------------------------------------- 139 // IO user data 140 struct io_future_t { 141 future_t self; 142 __s32 result; 143 }; 144 145 static inline { 146 bool fulfil( io_future_t & this, __s32 result ) { 147 this.result = result; 148 return fulfil(this.self); 149 } 150 151 // Wait for the future to be fulfilled 152 bool wait( io_future_t & this ) { 153 return wait(this.self); 154 } 155 } -
libcfa/src/concurrency/iofwd.hfa
rae2c27a rc76bd34 40 40 41 41 struct cluster; 42 struct io_future_t; 42 43 struct io_context; 43 44 struct io_cancellation; … … 48 49 struct statx; 49 50 50 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 51 extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 52 extern int cfa_fsync(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 53 extern int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 54 extern ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 55 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 56 extern ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 57 extern ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 58 extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 59 extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 60 extern int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 61 extern int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 62 extern int cfa_madvise(void *addr, size_t length, int advice, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 63 extern int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 64 extern int cfa_close(int fd, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 65 extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 66 extern ssize_t cfa_read(int fd, void *buf, size_t count, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 67 extern ssize_t cfa_write(int fd, void *buf, size_t count, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 68 extern ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 69 extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags = 0, Duration timeout = -1`s, io_cancellation * cancellation = 0p, io_context * context = 0p); 51 //---------- 52 // synchronous calls 53 #if defined(CFA_HAVE_PREADV2) 54 extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 55 #endif 56 #if defined(CFA_HAVE_PWRITEV2) 57 extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 58 #endif 59 extern int cfa_fsync(int fd, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 60 extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 61 extern int cfa_sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 62 extern ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 63 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 64 extern ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 65 extern ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 66 extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 67 extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 68 extern int cfa_fallocate(int fd, int mode, off_t offset, off_t len, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 69 extern int cfa_posix_fadvise(int fd, off_t offset, off_t len, int advice, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 70 extern int cfa_madvise(void *addr, size_t length, int advice, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 71 extern int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 72 #if defined(CFA_HAVE_OPENAT2) 73 extern int cfa_openat2(int dirfd, const char *pathname, struct open_how * how, size_t size, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 74 #endif 75 extern int cfa_close(int fd, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 76 #if defined(CFA_HAVE_STATX) 77 extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 78 #endif 79 extern ssize_t cfa_read(int fd, void * buf, size_t count, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 80 extern ssize_t cfa_write(int fd, void * buf, size_t count, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 81 extern ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 82 extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context); 83 84 //---------- 85 // asynchronous calls 86 #if defined(CFA_HAVE_PREADV2) 87 extern void async_preadv2(io_future_t & future, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 88 #endif 89 #if defined(CFA_HAVE_PWRITEV2) 90 extern void async_pwritev2(io_future_t & future, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 91 #endif 92 extern void async_fsync(io_future_t & future, int fd, int submit_flags, io_cancellation * cancellation, io_context * context); 93 extern void async_epoll_ctl(io_future_t & future, int epfd, int op, int fd, struct epoll_event *event, int submit_flags, io_cancellation * cancellation, io_context * context); 94 extern void async_sync_file_range(io_future_t & future, int fd, off64_t offset, off64_t nbytes, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 95 extern void async_sendmsg(io_future_t & future, int sockfd, const struct msghdr *msg, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 96 extern void async_recvmsg(io_future_t & future, int sockfd, struct msghdr *msg, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 97 extern void async_send(io_future_t & future, int sockfd, const void *buf, size_t len, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 98 extern void async_recv(io_future_t & future, int sockfd, void *buf, size_t len, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 99 extern void async_accept4(io_future_t & future, int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 100 extern void async_connect(io_future_t & future, int sockfd, const struct sockaddr *addr, socklen_t addrlen, int submit_flags, io_cancellation * cancellation, io_context * context); 101 extern void async_fallocate(io_future_t & future, int fd, int mode, off_t offset, off_t len, int submit_flags, io_cancellation * cancellation, io_context * context); 102 extern void async_posix_fadvise(io_future_t & future, int fd, off_t offset, off_t len, int advice, int submit_flags, io_cancellation * cancellation, io_context * context); 103 extern void async_madvise(io_future_t & future, void *addr, size_t length, int advice, int submit_flags, io_cancellation * cancellation, io_context * context); 104 extern void async_openat(io_future_t & future, int dirfd, const char *pathname, int flags, mode_t mode, int submit_flags, io_cancellation * cancellation, io_context * context); 105 #if defined(CFA_HAVE_OPENAT2) 106 extern void async_openat2(io_future_t & future, int dirfd, const char *pathname, struct open_how * how, size_t size, int submit_flags, io_cancellation * cancellation, io_context * context); 107 #endif 108 extern void async_close(io_future_t & future, int fd, int submit_flags, io_cancellation * cancellation, io_context * context); 109 #if defined(CFA_HAVE_STATX) 110 extern void async_statx(io_future_t & future, int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, int submit_flags, io_cancellation * cancellation, io_context * context); 111 #endif 112 void async_read(io_future_t & future, int fd, void * buf, size_t count, int submit_flags, io_cancellation * cancellation, io_context * context); 113 extern void async_write(io_future_t & future, int fd, void * buf, size_t count, int submit_flags, io_cancellation * cancellation, io_context * context); 114 extern void async_splice(io_future_t & future, int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 115 extern void async_tee(io_future_t & future, int fd_in, int fd_out, size_t len, unsigned int flags, int submit_flags, io_cancellation * cancellation, io_context * context); 116 70 117 71 118 //----------------------------------------------------------------------------- -
libcfa/src/concurrency/kernel.cfa
rae2c27a rc76bd34 237 237 $coroutine * proc_cor = get_coroutine(this->runner); 238 238 239 // Update global state240 kernelTLS.this_thread = thrd_dst;241 242 239 // set state of processor coroutine to inactive 243 240 verify(proc_cor->state == Active); … … 249 246 thrd_dst->state = Active; 250 247 251 __cfaabi_dbg_debug_do( 252 thrd_dst->park_stale = true; 253 thrd_dst->unpark_stale = true; 254 ) 248 // Update global state 249 kernelTLS.this_thread = thrd_dst; 255 250 256 251 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 257 252 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 253 /* paranoid */ verify( thrd_dst->context.SP ); 258 254 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor 259 255 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor 256 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary ); 257 258 260 259 261 260 // set context switch to the thread that the processor is executing 262 verify( thrd_dst->context.SP );263 261 __cfactx_switch( &proc_cor->context, &thrd_dst->context ); 264 262 // when __cfactx_switch returns we are back in the processor coroutine 265 263 264 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary ); 266 265 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); 267 266 /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); 267 /* paranoid */ verify( thrd_dst->context.SP ); 268 268 /* paranoid */ verify( kernelTLS.this_thread == thrd_dst ); 269 269 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 270 270 271 // Reset global state 272 kernelTLS.this_thread = 0p; 271 273 272 274 // We just finished running a thread, there are a few things that could have happened. … … 286 288 // The thread has halted, it should never be scheduled/run again 287 289 // We may need to wake someone up here since 288 unpark( this->destroyer __cfaabi_dbg_ctx2);290 unpark( this->destroyer ); 289 291 this->destroyer = 0p; 290 292 break RUNNING; … … 296 298 // set state of processor coroutine to active and the thread to inactive 297 299 int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST); 298 __cfaabi_dbg_debug_do( thrd_dst->park_result = old_ticket; )299 300 switch(old_ticket) { 300 301 case 1: … … 313 314 // Just before returning to the processor, set the processor coroutine to active 314 315 proc_cor->state = Active; 315 kernelTLS.this_thread = 0p;316 316 317 317 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); … … 334 334 __x87_store; 335 335 #endif 336 verify( proc_cor->context.SP ); 336 /* paranoid */ verify( proc_cor->context.SP ); 337 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary ); 337 338 __cfactx_switch( &thrd_src->context, &proc_cor->context ); 339 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary ); 338 340 #if defined( __i386 ) || defined( __x86_64 ) 339 341 __x87_load; … … 367 369 /* paranoid */ #endif 368 370 /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next ); 371 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd->canary ); 372 369 373 370 374 if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready; … … 403 407 404 408 // KERNEL ONLY unpark with out disabling interrupts 405 void __unpark( struct __processor_id_t * id, $thread * thrd __cfaabi_dbg_ctx_param2 ) { 406 // record activity 407 __cfaabi_dbg_record_thrd( *thrd, false, caller ); 408 409 void __unpark( struct __processor_id_t * id, $thread * thrd ) { 409 410 int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST); 410 __cfaabi_dbg_debug_do( thrd->unpark_result = old_ticket; thrd->unpark_state = thrd->state; )411 411 switch(old_ticket) { 412 412 case 1: … … 426 426 } 427 427 428 void unpark( $thread * thrd __cfaabi_dbg_ctx_param2) {428 void unpark( $thread * thrd ) { 429 429 if( !thrd ) return; 430 430 431 431 disable_interrupts(); 432 __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd __cfaabi_dbg_ctx_fwd2);432 __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd ); 433 433 enable_interrupts( __cfaabi_dbg_ctx ); 434 434 } 435 435 436 void park( __cfaabi_dbg_ctx_param) {436 void park( void ) { 437 437 /* paranoid */ verify( kernelTLS.preemption_state.enabled ); 438 438 disable_interrupts(); 439 439 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 440 440 /* paranoid */ verify( kernelTLS.this_thread->preempted == __NO_PREEMPTION ); 441 442 // record activity443 __cfaabi_dbg_record_thrd( *kernelTLS.this_thread, true, caller );444 441 445 442 returnToKernel(); … … 521 518 disable_interrupts(); 522 519 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 523 bool ret =post( this->idle );520 post( this->idle ); 524 521 enable_interrupts( __cfaabi_dbg_ctx ); 525 522 } … … 649 646 // atomically release spin lock and block 650 647 unlock( lock ); 651 park( __cfaabi_dbg_ctx);648 park(); 652 649 return true; 653 650 } … … 670 667 671 668 // make new owner 672 unpark( thrd __cfaabi_dbg_ctx2);669 unpark( thrd ); 673 670 674 671 return thrd != 0p; … … 681 678 count += diff; 682 679 for(release) { 683 unpark( pop_head( waiting ) __cfaabi_dbg_ctx2);680 unpark( pop_head( waiting ) ); 684 681 } 685 682 … … 697 694 this.prev_thrd = kernelTLS.this_thread; 698 695 } 699 700 void __cfaabi_dbg_record_thrd($thread & this, bool park, const char prev_name[]) {701 if(park) {702 this.park_caller = prev_name;703 this.park_stale = false;704 }705 else {706 this.unpark_caller = prev_name;707 this.unpark_stale = false;708 }709 }710 696 } 711 697 ) -
libcfa/src/concurrency/kernel.hfa
rae2c27a rc76bd34 23 23 24 24 extern "C" { 25 #include <bits/pthreadtypes.h> 25 #include <bits/pthreadtypes.h> 26 #include <linux/types.h> 26 27 } 27 28 … … 47 48 // Processor id, required for scheduling threads 48 49 struct __processor_id_t { 49 unsigned id; 50 unsigned id:24; 51 bool full_proc:1; 50 52 51 53 #if !defined(__CFA_NO_STATISTICS__) … … 157 159 158 160 struct io_cancellation { 159 uint32_ttarget;161 __u64 target; 160 162 }; 161 163 -
libcfa/src/concurrency/kernel/fwd.hfa
rae2c27a rc76bd34 118 118 119 119 extern "Cforall" { 120 extern void park( __cfaabi_dbg_ctx_param);121 extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2);120 extern void park( void ); 121 extern void unpark( struct $thread * this ); 122 122 static inline struct $thread * active_thread () { return TL_GET( this_thread ); } 123 123 -
libcfa/src/concurrency/kernel/startup.cfa
rae2c27a rc76bd34 451 451 link.next = 0p; 452 452 link.prev = 0p; 453 #if defined( __CFA_WITH_VERIFY__ ) 454 canary = 0x0D15EA5E0D15EA5E; 455 #endif 453 456 454 457 node.next = 0p; … … 470 473 this.name = name; 471 474 this.cltr = &_cltr; 472 id = -1u;475 full_proc = true; 473 476 destroyer = 0p; 474 477 do_terminate = false; -
libcfa/src/concurrency/kernel_private.hfa
rae2c27a rc76bd34 64 64 65 65 // KERNEL ONLY unpark with out disabling interrupts 66 void __unpark( struct __processor_id_t *, $thread * thrd __cfaabi_dbg_ctx_param2);66 void __unpark( struct __processor_id_t *, $thread * thrd ); 67 67 68 68 static inline bool __post(single_sem & this, struct __processor_id_t * id) { … … 77 77 else { 78 78 if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 79 __unpark( id, expected __cfaabi_dbg_ctx2);79 __unpark( id, expected ); 80 80 return true; 81 81 } -
libcfa/src/concurrency/monitor.cfa
rae2c27a rc76bd34 89 89 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 90 90 91 if( !this->owner ) { 91 if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) { 92 abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this ); 93 } 94 else if( !this->owner ) { 92 95 // No one has the monitor, just take it 93 96 __set_owner( this, thrd ); … … 119 122 120 123 unlock( this->lock ); 121 park( __cfaabi_dbg_ctx);124 park(); 122 125 123 126 __cfaabi_dbg_print_safe( "Kernel : %10p Entered mon %p\n", thrd, this); … … 137 140 } 138 141 139 static void __dtor_enter( $monitor * this, fptr_t func ) {142 static void __dtor_enter( $monitor * this, fptr_t func, bool join ) { 140 143 // Lock the monitor spinlock 141 144 lock( this->lock __cfaabi_dbg_ctx2 ); … … 157 160 return; 158 161 } 159 else if( this->owner == thrd ) {162 else if( this->owner == thrd && !join) { 160 163 // We already have the monitor... but where about to destroy it so the nesting will fail 161 164 // Abort! 162 165 abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd ); 166 } 167 // SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check 168 // to avoid that it sets the owner to the special value thrd | 1p before exiting 169 else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) { 170 // restore the owner and just return 171 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this); 172 173 // No one has the monitor, just take it 174 this->owner = thrd; 175 176 verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 177 178 unlock( this->lock ); 179 return; 163 180 } 164 181 … … 184 201 // Release the next thread 185 202 /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); 186 unpark( urgent->owner->waiting_thread __cfaabi_dbg_ctx2);203 unpark( urgent->owner->waiting_thread ); 187 204 188 205 // Park current thread waiting 189 park( __cfaabi_dbg_ctx);206 park(); 190 207 191 208 // Some one was waiting for us, enter … … 205 222 206 223 // Park current thread waiting 207 park( __cfaabi_dbg_ctx);224 park(); 208 225 209 226 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this ); … … 247 264 //We need to wake-up the thread 248 265 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this ); 249 unpark( new_owner __cfaabi_dbg_ctx2);266 unpark( new_owner ); 250 267 } 251 268 252 269 // Leave single monitor for the last time 253 void __dtor_leave( $monitor * this ) {270 void __dtor_leave( $monitor * this, bool join ) { 254 271 __cfaabi_dbg_debug_do( 255 272 if( TL_GET( this_thread ) != this->owner ) { 256 273 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner); 257 274 } 258 if( this->recursion != 1 ) {275 if( this->recursion != 1 && !join ) { 259 276 abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1); 260 277 } 261 278 ) 279 280 this->owner = ($thread*)(1 | (uintptr_t)this->owner); 262 281 } 263 282 … … 307 326 } 308 327 328 // Join a thread 329 forall( dtype T | is_thread(T) ) 330 T & join( T & this ) { 331 $monitor * m = get_monitor(this); 332 void (*dtor)(T& mutex this) = ^?{}; 333 monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true }; 334 { 335 return this; 336 } 337 } 338 309 339 // Enter multiple monitor 310 340 // relies on the monitor array being sorted … … 366 396 // Ctor for monitor guard 367 397 // Sorts monitors before entering 368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {398 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) { 369 399 // optimization 370 400 $thread * thrd = TL_GET( this_thread ); … … 376 406 this.prev = thrd->monitors; 377 407 408 // Save whether we are in a join or not 409 this.join = join; 410 378 411 // Update thread context (needed for conditions) 379 412 (thrd->monitors){m, 1, func}; 380 413 381 __dtor_enter( this.m, func );414 __dtor_enter( this.m, func, join ); 382 415 } 383 416 … … 385 418 void ^?{}( monitor_dtor_guard_t & this ) { 386 419 // Leave the monitors in order 387 __dtor_leave( this.m );420 __dtor_leave( this.m, this.join ); 388 421 389 422 // Restore thread context … … 460 493 // Wake the threads 461 494 for(int i = 0; i < thread_count; i++) { 462 unpark( threads[i] __cfaabi_dbg_ctx2);495 unpark( threads[i] ); 463 496 } 464 497 465 498 // Everything is ready to go to sleep 466 park( __cfaabi_dbg_ctx);499 park(); 467 500 468 501 // We are back, restore the owners and recursions … … 542 575 543 576 // unpark the thread we signalled 544 unpark( signallee __cfaabi_dbg_ctx2);577 unpark( signallee ); 545 578 546 579 //Everything is ready to go to sleep 547 park( __cfaabi_dbg_ctx);580 park(); 548 581 549 582 … … 646 679 647 680 // unpark the thread we signalled 648 unpark( next __cfaabi_dbg_ctx2);681 unpark( next ); 649 682 650 683 //Everything is ready to go to sleep 651 park( __cfaabi_dbg_ctx);684 park(); 652 685 653 686 // We are back, restore the owners and recursions … … 691 724 692 725 //Everything is ready to go to sleep 693 park( __cfaabi_dbg_ctx);726 park(); 694 727 695 728 -
libcfa/src/concurrency/monitor.hfa
rae2c27a rc76bd34 53 53 $monitor * m; 54 54 __monitor_group_t prev; 55 bool join; 55 56 }; 56 57 57 void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)() );58 void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)(), bool join ); 58 59 void ^?{}( monitor_dtor_guard_t & this ); 59 60 -
libcfa/src/concurrency/mutex.cfa
rae2c27a rc76bd34 42 42 append( blocked_threads, kernelTLS.this_thread ); 43 43 unlock( lock ); 44 park( __cfaabi_dbg_ctx);44 park(); 45 45 } 46 46 else { … … 65 65 this.is_locked = (this.blocked_threads != 0); 66 66 unpark( 67 pop_head( this.blocked_threads ) __cfaabi_dbg_ctx267 pop_head( this.blocked_threads ) 68 68 ); 69 69 unlock( this.lock ); … … 97 97 append( blocked_threads, kernelTLS.this_thread ); 98 98 unlock( lock ); 99 park( __cfaabi_dbg_ctx);99 park(); 100 100 } 101 101 } … … 124 124 owner = thrd; 125 125 recursion_count = (thrd ? 1 : 0); 126 unpark( thrd __cfaabi_dbg_ctx2);126 unpark( thrd ); 127 127 } 128 128 unlock( lock ); … … 142 142 lock( lock __cfaabi_dbg_ctx2 ); 143 143 unpark( 144 pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2144 pop_head( this.blocked_threads ) 145 145 ); 146 146 unlock( lock ); … … 151 151 while(this.blocked_threads) { 152 152 unpark( 153 pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2153 pop_head( this.blocked_threads ) 154 154 ); 155 155 } … … 161 161 append( this.blocked_threads, kernelTLS.this_thread ); 162 162 unlock( this.lock ); 163 park( __cfaabi_dbg_ctx);163 park(); 164 164 } 165 165 … … 170 170 unlock(l); 171 171 unlock(this.lock); 172 park( __cfaabi_dbg_ctx);172 park(); 173 173 lock(l); 174 174 } -
libcfa/src/concurrency/preemption.cfa
rae2c27a rc76bd34 274 274 kernelTLS.this_stats = this->curr_cluster->stats; 275 275 #endif 276 __unpark( id, this __cfaabi_dbg_ctx2);276 __unpark( id, this ); 277 277 } 278 278 … … 411 411 static void * alarm_loop( __attribute__((unused)) void * args ) { 412 412 __processor_id_t id; 413 id.full_proc = false; 413 414 id.id = doregister(&id); 414 415 -
libcfa/src/concurrency/thread.cfa
rae2c27a rc76bd34 39 39 link.prev = 0p; 40 40 link.preferred = -1; 41 #if defined( __CFA_WITH_VERIFY__ ) 42 canary = 0x0D15EA5E0D15EA5E; 43 #endif 41 44 42 45 node.next = 0p; … … 48 51 49 52 void ^?{}($thread& this) with( this ) { 53 #if defined( __CFA_WITH_VERIFY__ ) 54 canary = 0xDEADDEADDEADDEAD; 55 #endif 50 56 unregister(curr_cluster, this); 51 57 ^self_cor{}; -
libcfa/src/concurrency/thread.hfa
rae2c27a rc76bd34 88 88 //---------- 89 89 // Park thread: block until corresponding call to unpark, won't block if unpark is already called 90 void park( __cfaabi_dbg_ctx_param);90 void park( void ); 91 91 92 92 //---------- 93 93 // Unpark a thread, if the thread is already blocked, schedule it 94 94 // if the thread is not yet block, signal that it should rerun immediately 95 void unpark( $thread * this __cfaabi_dbg_ctx_param2);95 void unpark( $thread * this ); 96 96 97 97 forall( dtype T | is_thread(T) ) 98 static inline void unpark( T & this __cfaabi_dbg_ctx_param2 ) { if(!&this) return; unpark( get_thread( this ) __cfaabi_dbg_ctx_fwd2);}98 static inline void unpark( T & this ) { if(!&this) return; unpark( get_thread( this ) );} 99 99 100 100 //---------- … … 106 106 void sleep( Duration duration ); 107 107 108 //---------- 109 // join 110 forall( dtype T | is_thread(T) ) 111 T & join( T & this ); 112 108 113 // Local Variables: // 109 114 // mode: c // -
libcfa/src/exception.h
rae2c27a rc76bd34 76 76 // implemented in the .c file either so they all have to be inline. 77 77 78 trait is_exception(dtype T) {78 trait is_exception(dtype exceptT) { 79 79 /* The first field must be a pointer to a virtual table. 80 80 * That virtual table must be a decendent of the base exception virtual tab$ 81 81 */ 82 void mark_exception( T *);82 void mark_exception(exceptT *); 83 83 // This is never used and should be a no-op. 84 84 }; 85 85 86 trait is_termination_exception(dtype T | is_exception(T)) {87 void defaultTerminationHandler( T &);86 trait is_termination_exception(dtype exceptT | is_exception(exceptT)) { 87 void defaultTerminationHandler(exceptT &); 88 88 }; 89 89 90 trait is_resumption_exception(dtype T | is_exception(T)) {91 void defaultResumptionHandler( T &);90 trait is_resumption_exception(dtype exceptT | is_exception(exceptT)) { 91 void defaultResumptionHandler(exceptT &); 92 92 }; 93 93 94 forall(dtype T | is_termination_exception(T))95 static inline void $throw( T & except) {94 forall(dtype exceptT | is_termination_exception(exceptT)) 95 static inline void $throw(exceptT & except) { 96 96 __cfaehm_throw_terminate( 97 97 (exception_t *)&except, … … 100 100 } 101 101 102 forall(dtype T | is_resumption_exception(T))103 static inline void $throwResume( T & except) {102 forall(dtype exceptT | is_resumption_exception(exceptT)) 103 static inline void $throwResume(exceptT & except) { 104 104 __cfaehm_throw_resume( 105 105 (exception_t *)&except, … … 108 108 } 109 109 110 forall(dtype T | is_exception(T))111 static inline void cancel_stack( T & except) __attribute__((noreturn)) {110 forall(dtype exceptT | is_exception(exceptT)) 111 static inline void cancel_stack(exceptT & except) __attribute__((noreturn)) { 112 112 __cfaehm_cancel_stack( (exception_t *)&except ); 113 113 } 114 114 115 forall(dtype T | is_exception(T))116 static inline void defaultTerminationHandler( T & except) {115 forall(dtype exceptT | is_exception(exceptT)) 116 static inline void defaultTerminationHandler(exceptT & except) { 117 117 return cancel_stack( except ); 118 118 } 119 119 120 forall(dtype T | is_exception(T))121 static inline void defaultResumptionHandler( T & except) {120 forall(dtype exceptT | is_exception(exceptT)) 121 static inline void defaultResumptionHandler(exceptT & except) { 122 122 throw except; 123 123 } -
libcfa/src/exception.hfa
rae2c27a rc76bd34 192 192 size_t size; \ 193 193 void (*copy)(exception_name * this, exception_name * other); \ 194 void (* free)(exception_name & this); \194 void (*^?{})(exception_name & this); \ 195 195 const char * (*msg)(exception_name * this); \ 196 196 _CLOSE … … 213 213 size_t size; \ 214 214 void (*copy)(exception_name parameters * this, exception_name parameters * other); \ 215 void (* free)(exception_name parameters & this); \215 void (*^?{})(exception_name parameters & this); \ 216 216 const char * (*msg)(exception_name parameters * this); \ 217 217 _CLOSE -
libcfa/src/heap.cfa
rae2c27a rc76bd34 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Sep 3 16:22:54202013 // Update Count : 9 4312 // Last Modified On : Mon Sep 7 22:17:46 2020 13 // Update Count : 957 14 14 // 15 15 … … 889 889 size_t bsize, oalign; 890 890 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 891 892 891 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 892 893 893 // same size, DO NOT preserve STICKY PROPERTIES. 894 if ( oalign <= libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size894 if ( oalign == libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 895 895 header->kind.real.blockSize &= -2; // no alignment and turn off 0 fill 896 896 header->kind.real.size = size; // reset allocation size … … 931 931 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 932 932 size_t osize = header->kind.real.size; // old allocation size 933 bool ozfill = (header->kind.real.blockSize & 2) != 0; // old allocation zero filled934 if ( unlikely( size <= odsize ) && size > odsize /2 ) { // allow up to 50% wasted storage933 bool ozfill = (header->kind.real.blockSize & 2); // old allocation zero filled 934 if ( unlikely( size <= odsize ) && odsize <= size * 2 ) { // allow up to 50% wasted storage 935 935 header->kind.real.size = size; // reset allocation size 936 936 if ( unlikely( ozfill ) && size > osize ) { // previous request zero fill and larger ? … … 947 947 948 948 void * naddr; 949 if ( likely( oalign <= libAlign() ) ) { // previous request not aligned ?949 if ( likely( oalign == libAlign() ) ) { // previous request not aligned ? 950 950 naddr = mallocNoStats( size ); // create new area 951 951 } else { … … 1231 1231 } // if 1232 1232 1233 // Attempt to reuse existing storage.1233 // Attempt to reuse existing alignment. 1234 1234 HeapManager.Storage.Header * header = headerAddr( oaddr ); 1235 bool isFakeHeader = header->kind.fake.alignment & 1 == 1;// old fake header ?1236 if ( unlikely ( ( isFakeHeader &&1237 (uintptr_t)oaddr % nalign == 0 && // lucky match ?1238 header->kind.fake.alignment <= nalign && // ok to leave LSB at 11239 nalign <= 128 ) // not too much alignment storage wasted?1240 || ( (!isFakeHeader) && // old real header ( aligned on libAlign ) ?1241 nalign == libAlign() ) ) ) { // new alignment also on libAlign1242 1243 HeapManager.FreeHeader * freeElem;1244 size_t bsize, oalign;1245 headers( "resize", oaddr, header, freeElem, bsize, oalign );1246 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket1247 1248 if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted data storage 1249 if ( isFakeHeader ) {1235 bool isFakeHeader = header->kind.fake.alignment & 1; // old fake header ? 1236 size_t oalign; 1237 if ( isFakeHeader ) { 1238 oalign = header->kind.fake.alignment & -2; // old alignment 1239 if ( (uintptr_t)oaddr % nalign == 0 // lucky match ? 1240 && ( oalign <= nalign // going down 1241 || (oalign >= nalign && oalign <= 256) ) // little alignment storage wasted ? 1242 ) { 1243 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1244 HeapManager.FreeHeader * freeElem; 1245 size_t bsize, oalign; 1246 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 1247 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 1248 1249 if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted data storage 1250 1250 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1251 } 1252 1253 header->kind.real.blockSize &= -2; // turn off 0 fill 1254 header->kind.real.size = size; // reset allocation size 1255 return oaddr; 1256 } // if 1251 1252 header->kind.real.blockSize &= -2; // turn off 0 fill 1253 header->kind.real.size = size; // reset allocation size 1254 return oaddr; 1255 } // if 1256 } // if 1257 } else if ( ! isFakeHeader // old real header (aligned on libAlign) ? 1258 && nalign == libAlign() ) { // new alignment also on libAlign => no fake header needed 1259 return resize( oaddr, size ); // duplicate special case checks 1257 1260 } // if 1258 1261 … … 1284 1287 } // if 1285 1288 1286 HeapManager.Storage.Header * header; 1287 HeapManager.FreeHeader * freeElem; 1288 size_t bsize, oalign; 1289 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 1290 1291 // Attempt to reuse existing storage. 1292 bool isFakeHeader = header->kind.fake.alignment & 1 == 1; // old fake header ? 1293 if ( unlikely ( ( isFakeHeader && 1294 (uintptr_t)oaddr % nalign == 0 && // lucky match ? 1295 header->kind.fake.alignment <= nalign && // ok to leave LSB at 1 1296 nalign <= 128 ) // not too much alignment storage wasted ? 1297 || ( (!isFakeHeader) && // old real header ( aligned on libAlign ) ? 1298 nalign == libAlign() ) ) ) { // new alignment also on libAlign 1299 1300 if ( isFakeHeader ) { 1289 // Attempt to reuse existing alignment. 1290 HeapManager.Storage.Header * header = headerAddr( oaddr ); 1291 bool isFakeHeader = header->kind.fake.alignment & 1; // old fake header ? 1292 size_t oalign; 1293 if ( isFakeHeader ) { 1294 oalign = header->kind.fake.alignment & -2; // old alignment 1295 if ( (uintptr_t)oaddr % nalign == 0 // lucky match ? 1296 && ( oalign <= nalign // going down 1297 || (oalign >= nalign && oalign <= 256) ) // little alignment storage wasted ? 1298 ) { 1301 1299 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1302 } 1303 return realloc( oaddr, size ); 1304 1305 } // if 1306 1307 // change size and copy old content to new storage 1300 return realloc( oaddr, size ); // duplicate alignment and special case checks 1301 } // if 1302 } else if ( ! isFakeHeader // old real header (aligned on libAlign) ? 1303 && nalign == libAlign() ) // new alignment also on libAlign => no fake header needed 1304 return realloc( oaddr, size ); // duplicate alignment and special case checks 1308 1305 1309 1306 #ifdef __STATISTICS__ … … 1312 1309 #endif // __STATISTICS__ 1313 1310 1311 HeapManager.FreeHeader * freeElem; 1312 size_t bsize; 1313 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 1314 1315 // change size and copy old content to new storage 1316 1314 1317 size_t osize = header->kind.real.size; // old allocation size 1315 bool ozfill = (header->kind.real.blockSize & 2) != 0;// old allocation zero filled1318 bool ozfill = (header->kind.real.blockSize & 2); // old allocation zero filled 1316 1319 1317 1320 void * naddr = memalignNoStats( nalign, size ); // create new aligned area -
libcfa/src/limits.cfa
rae2c27a rc76bd34 10 10 // Created On : Wed Apr 6 18:06:52 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 1 16:22:51 201813 // Update Count : 7 412 // Last Modified On : Wed Sep 30 22:56:32 2020 13 // Update Count : 76 14 14 // 15 15 … … 23 23 // Integral Constants 24 24 25 constsigned char MIN = SCHAR_MIN;26 constunsigned char MIN = 0;27 constshort int MIN = SHRT_MIN;28 constunsigned short int MIN = 0;29 constint MIN = INT_MIN;30 constunsigned int MIN = 0;31 constlong int MIN = LONG_MIN;32 constunsigned long int MIN = 0;33 constlong long int MIN = LLONG_MIN;34 constunsigned long long int MIN = 0;25 signed char MIN = SCHAR_MIN; 26 unsigned char MIN = 0; 27 short int MIN = SHRT_MIN; 28 unsigned short int MIN = 0; 29 int MIN = INT_MIN; 30 unsigned int MIN = 0; 31 long int MIN = LONG_MIN; 32 unsigned long int MIN = 0; 33 long long int MIN = LLONG_MIN; 34 unsigned long long int MIN = 0; 35 35 36 constsigned char MAX = SCHAR_MAX;37 constunsigned char MAX = UCHAR_MAX;38 constshort int MAX = SHRT_MAX;39 constunsigned short int MAX = USHRT_MAX;40 constint MAX = INT_MAX;41 constunsigned int MAX = UINT_MAX;42 constlong int MAX = LONG_MAX;43 constunsigned long int MAX = ULONG_MAX;44 constlong long int MAX = LLONG_MAX;45 constunsigned long long int MAX = ULLONG_MAX;36 signed char MAX = SCHAR_MAX; 37 unsigned char MAX = UCHAR_MAX; 38 short int MAX = SHRT_MAX; 39 unsigned short int MAX = USHRT_MAX; 40 int MAX = INT_MAX; 41 unsigned int MAX = UINT_MAX; 42 long int MAX = LONG_MAX; 43 unsigned long int MAX = ULONG_MAX; 44 long long int MAX = LLONG_MAX; 45 unsigned long long int MAX = ULLONG_MAX; 46 46 47 47 // Floating-Point Constants 48 48 49 constfloat MIN = FLT_MIN;50 constdouble MIN = DBL_MIN;51 constlong double MIN = LDBL_MIN;52 constfloat _Complex MIN = __FLT_MIN__ + __FLT_MIN__ * I;53 constdouble _Complex MIN = DBL_MIN + DBL_MIN * I;54 constlong double _Complex MIN = LDBL_MIN + LDBL_MIN * I;49 float MIN = FLT_MIN; 50 double MIN = DBL_MIN; 51 long double MIN = LDBL_MIN; 52 float _Complex MIN = __FLT_MIN__ + __FLT_MIN__ * I; 53 double _Complex MIN = DBL_MIN + DBL_MIN * I; 54 long double _Complex MIN = LDBL_MIN + LDBL_MIN * I; 55 55 56 constfloat MAX = FLT_MAX;57 constdouble MAX = DBL_MAX;58 constlong double MAX = LDBL_MAX;59 constfloat _Complex MAX = FLT_MAX + FLT_MAX * I;60 constdouble _Complex MAX = DBL_MAX + DBL_MAX * I;61 constlong double _Complex MAX = LDBL_MAX + LDBL_MAX * I;56 float MAX = FLT_MAX; 57 double MAX = DBL_MAX; 58 long double MAX = LDBL_MAX; 59 float _Complex MAX = FLT_MAX + FLT_MAX * I; 60 double _Complex MAX = DBL_MAX + DBL_MAX * I; 61 long double _Complex MAX = LDBL_MAX + LDBL_MAX * I; 62 62 63 const float PI = (float)M_PI;// pi64 const float PI_2 = (float)M_PI_2;// pi / 265 const float PI_4 = (float)M_PI_4;// pi / 466 const float _1_PI = (float)M_1_PI;// 1 / pi67 const float _2_PI = (float)M_2_PI;// 2 / pi68 const float _2_SQRT_PI = (float)M_2_SQRTPI;// 2 / sqrt(pi)63 float PI = (float)M_PI; // pi 64 float PI_2 = (float)M_PI_2; // pi / 2 65 float PI_4 = (float)M_PI_4; // pi / 4 66 float _1_PI = (float)M_1_PI; // 1 / pi 67 float _2_PI = (float)M_2_PI; // 2 / pi 68 float _2_SQRT_PI = (float)M_2_SQRTPI; // 2 / sqrt(pi) 69 69 70 const double PI = M_PI;// pi71 const double PI_2 = M_PI_2;// pi / 272 const double PI_4 = M_PI_4;// pi / 473 const double _1_PI = M_1_PI;// 1 / pi74 const double _2_PI = M_2_PI;// 2 / pi75 const double _2_SQRT_PI = M_2_SQRTPI;// 2 / sqrt(pi)70 double PI = M_PI; // pi 71 double PI_2 = M_PI_2; // pi / 2 72 double PI_4 = M_PI_4; // pi / 4 73 double _1_PI = M_1_PI; // 1 / pi 74 double _2_PI = M_2_PI; // 2 / pi 75 double _2_SQRT_PI = M_2_SQRTPI; // 2 / sqrt(pi) 76 76 77 const long double PI = M_PIl;// pi78 const long double PI_2 = M_PI_2l;// pi / 279 const long double PI_4 = M_PI_4l;// pi / 480 const long double _1_PI = M_1_PIl;// 1 / pi81 const long double _2_PI = M_2_PIl;// 2 / pi82 const long double _2_SQRT_PI = M_2_SQRTPIl;// 2 / sqrt(pi)77 long double PI = M_PIl; // pi 78 long double PI_2 = M_PI_2l; // pi / 2 79 long double PI_4 = M_PI_4l; // pi / 4 80 long double _1_PI = M_1_PIl; // 1 / pi 81 long double _2_PI = M_2_PIl; // 2 / pi 82 long double _2_SQRT_PI = M_2_SQRTPIl; // 2 / sqrt(pi) 83 83 84 const float _Complex PI = (float)M_PI + 0.0_iF;// pi85 const float _Complex PI_2 = (float)M_PI_2 + 0.0_iF;// pi / 286 const float _Complex PI_4 = (float)M_PI_4 + 0.0_iF;// pi / 487 const float _Complex _1_PI = (float)M_1_PI + 0.0_iF;// 1 / pi88 const float _Complex _2_PI = (float)M_2_PI + 0.0_iF;// 2 / pi89 constfloat _Complex _2_SQRT_PI = (float)M_2_SQRTPI + 0.0_iF; // 2 / sqrt(pi)84 float _Complex PI = (float)M_PI + 0.0_iF; // pi 85 float _Complex PI_2 = (float)M_PI_2 + 0.0_iF; // pi / 2 86 float _Complex PI_4 = (float)M_PI_4 + 0.0_iF; // pi / 4 87 float _Complex _1_PI = (float)M_1_PI + 0.0_iF; // 1 / pi 88 float _Complex _2_PI = (float)M_2_PI + 0.0_iF; // 2 / pi 89 float _Complex _2_SQRT_PI = (float)M_2_SQRTPI + 0.0_iF; // 2 / sqrt(pi) 90 90 91 const double _Complex PI = M_PI + 0.0_iD;// pi92 const double _Complex PI_2 = M_PI_2 + 0.0_iD;// pi / 293 const double _Complex PI_4 = M_PI_4 + 0.0_iD;// pi / 494 const double _Complex _1_PI = M_1_PI + 0.0_iD;// 1 / pi95 const double _Complex _2_PI = M_2_PI + 0.0_iD;// 2 / pi96 const double _Complex _2_SQRT_PI = M_2_SQRTPI + 0.0_iD;// 2 / sqrt(pi)91 double _Complex PI = M_PI + 0.0_iD; // pi 92 double _Complex PI_2 = M_PI_2 + 0.0_iD; // pi / 2 93 double _Complex PI_4 = M_PI_4 + 0.0_iD; // pi / 4 94 double _Complex _1_PI = M_1_PI + 0.0_iD; // 1 / pi 95 double _Complex _2_PI = M_2_PI + 0.0_iD; // 2 / pi 96 double _Complex _2_SQRT_PI = M_2_SQRTPI + 0.0_iD; // 2 / sqrt(pi) 97 97 98 const long double _Complex PI = M_PIl + 0.0_iL;// pi99 const long double _Complex PI_2 = M_PI_2l + 0.0_iL;// pi / 2100 const long double _Complex PI_4 = M_PI_4l + 0.0_iL;// pi / 4101 const long double _Complex _1_PI = M_1_PIl + 0.0_iL;// 1 / pi102 const long double _Complex _2_PI = M_2_PIl + 0.0_iL;// 2 / pi103 constlong double _Complex _2_SQRT_PI = M_2_SQRTPIl + 0.0_iL; // 2 / sqrt(pi)98 long double _Complex PI = M_PIl + 0.0_iL; // pi 99 long double _Complex PI_2 = M_PI_2l + 0.0_iL; // pi / 2 100 long double _Complex PI_4 = M_PI_4l + 0.0_iL; // pi / 4 101 long double _Complex _1_PI = M_1_PIl + 0.0_iL; // 1 / pi 102 long double _Complex _2_PI = M_2_PIl + 0.0_iL; // 2 / pi 103 long double _Complex _2_SQRT_PI = M_2_SQRTPIl + 0.0_iL; // 2 / sqrt(pi) 104 104 105 const float E = (float)M_E;// e106 const float LOG2_E = (float)M_LOG2E;// log_2(e)107 const float LOG10_E = (float)M_LOG10E;// log_10(e)108 const float LN_2 = (float)M_LN2;// log_e(2)109 const float LN_10 = (float)M_LN10;// log_e(10)110 const float SQRT_2 = (float)M_SQRT2;// sqrt(2)111 const float _1_SQRT_2 = (float)M_SQRT1_2;// 1 / sqrt(2)105 float E = (float)M_E; // e 106 float LOG2_E = (float)M_LOG2E; // log_2(e) 107 float LOG10_E = (float)M_LOG10E; // log_10(e) 108 float LN_2 = (float)M_LN2; // log_e(2) 109 float LN_10 = (float)M_LN10; // log_e(10) 110 float SQRT_2 = (float)M_SQRT2; // sqrt(2) 111 float _1_SQRT_2 = (float)M_SQRT1_2; // 1 / sqrt(2) 112 112 113 const double E = M_E;// e114 const double LOG2_E = M_LOG2E;// log_2(e)115 const double LOG10_E = M_LOG10E;// log_10(e)116 const double LN_2 = M_LN2;// log_e(2)117 const double LN_10 = M_LN10;// log_e(10)118 const double SQRT_2 = M_SQRT2;// sqrt(2)119 const double _1_SQRT_2 = M_SQRT1_2;// 1 / sqrt(2)113 double E = M_E; // e 114 double LOG2_E = M_LOG2E; // log_2(e) 115 double LOG10_E = M_LOG10E; // log_10(e) 116 double LN_2 = M_LN2; // log_e(2) 117 double LN_10 = M_LN10; // log_e(10) 118 double SQRT_2 = M_SQRT2; // sqrt(2) 119 double _1_SQRT_2 = M_SQRT1_2; // 1 / sqrt(2) 120 120 121 const long double E = M_El;// e122 const long double LOG2_E = M_LOG2El;// log_2(e)123 const long double LOG10_E = M_LOG10El;// log_10(e)124 const long double LN_2 = M_LN2l;// log_e(2)125 const long double LN_10 = M_LN10l;// log_e(10)126 const long double SQRT_2 = M_SQRT2l;// sqrt(2)127 const long double _1_SQRT_2 = M_SQRT1_2l;// 1 / sqrt(2)121 long double E = M_El; // e 122 long double LOG2_E = M_LOG2El; // log_2(e) 123 long double LOG10_E = M_LOG10El; // log_10(e) 124 long double LN_2 = M_LN2l; // log_e(2) 125 long double LN_10 = M_LN10l; // log_e(10) 126 long double SQRT_2 = M_SQRT2l; // sqrt(2) 127 long double _1_SQRT_2 = M_SQRT1_2l; // 1 / sqrt(2) 128 128 129 const float _Complex E = M_E + 0.0_iF;// e130 const float _Complex LOG2_E = M_LOG2E + 0.0_iF;// log_2(e)131 const float _Complex LOG10_E = M_LOG10E + 0.0_iF;// log_10(e)132 const float _Complex LN_2 = M_LN2 + 0.0_iF;// log_e(2)133 const float _Complex LN_10 = M_LN10 + 0.0_iF;// log_e(10)134 const float _Complex SQRT_2 = M_SQRT2 + 0.0_iF;// sqrt(2)135 const float _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iF;// 1 / sqrt(2)129 float _Complex E = M_E + 0.0_iF; // e 130 float _Complex LOG2_E = M_LOG2E + 0.0_iF; // log_2(e) 131 float _Complex LOG10_E = M_LOG10E + 0.0_iF; // log_10(e) 132 float _Complex LN_2 = M_LN2 + 0.0_iF; // log_e(2) 133 float _Complex LN_10 = M_LN10 + 0.0_iF; // log_e(10) 134 float _Complex SQRT_2 = M_SQRT2 + 0.0_iF; // sqrt(2) 135 float _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iF; // 1 / sqrt(2) 136 136 137 const double _Complex E = M_E + 0.0_iD;// e138 const double _Complex LOG2_E = M_LOG2E + 0.0_iD;// log_2(e)139 const double _Complex LOG10_E = M_LOG10E + 0.0_iD;// log_10(e)140 const double _Complex LN_2 = M_LN2 + 0.0_iD;// log_e(2)141 const double _Complex LN_10 = M_LN10 + 0.0_iD;// log_e(10)142 const double _Complex SQRT_2 = M_SQRT2 + 0.0_iD;// sqrt(2)143 const double _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iD;// 1 / sqrt(2)137 double _Complex E = M_E + 0.0_iD; // e 138 double _Complex LOG2_E = M_LOG2E + 0.0_iD; // log_2(e) 139 double _Complex LOG10_E = M_LOG10E + 0.0_iD; // log_10(e) 140 double _Complex LN_2 = M_LN2 + 0.0_iD; // log_e(2) 141 double _Complex LN_10 = M_LN10 + 0.0_iD; // log_e(10) 142 double _Complex SQRT_2 = M_SQRT2 + 0.0_iD; // sqrt(2) 143 double _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iD; // 1 / sqrt(2) 144 144 145 const long double _Complex E = M_El + 0.0_iL;// e146 const long double _Complex LOG2_E = M_LOG2El + 0.0_iL;// log_2(e)147 const long double _Complex LOG10_E = M_LOG10El + 0.0_iL;// log_10(e)148 const long double _Complex LN_2 = M_LN2l + 0.0_iL;// log_e(2)149 const long double _Complex LN_10 = M_LN10l + 0.0_iL;// log_e(10)150 const long double _Complex SQRT_2 = M_SQRT2l + 0.0_iL;// sqrt(2)151 const long double _Complex _1_SQRT_2 = M_SQRT1_2l + 0.0_iL;// 1 / sqrt(2)145 long double _Complex E = M_El + 0.0_iL; // e 146 long double _Complex LOG2_E = M_LOG2El + 0.0_iL; // log_2(e) 147 long double _Complex LOG10_E = M_LOG10El + 0.0_iL; // log_10(e) 148 long double _Complex LN_2 = M_LN2l + 0.0_iL; // log_e(2) 149 long double _Complex LN_10 = M_LN10l + 0.0_iL; // log_e(10) 150 long double _Complex SQRT_2 = M_SQRT2l + 0.0_iL; // sqrt(2) 151 long double _Complex _1_SQRT_2 = M_SQRT1_2l + 0.0_iL; // 1 / sqrt(2) 152 152 153 153 // Local Variables: // -
libcfa/src/limits.hfa
rae2c27a rc76bd34 10 10 // Created On : Wed Apr 6 18:06:52 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 1 16:20:54 201813 // Update Count : 1 312 // Last Modified On : Wed Sep 30 22:56:35 2020 13 // Update Count : 15 14 14 // 15 15 … … 18 18 // Integral Constants 19 19 20 extern constsigned char MIN;21 extern constunsigned char MIN;22 extern constshort int MIN;23 extern constunsigned short int MIN;24 extern constint MIN;25 extern constunsigned int MIN;26 extern constlong int MIN;27 extern constunsigned long int MIN;28 extern constlong long int MIN;29 extern constunsigned long long int MIN;20 extern signed char MIN; 21 extern unsigned char MIN; 22 extern short int MIN; 23 extern unsigned short int MIN; 24 extern int MIN; 25 extern unsigned int MIN; 26 extern long int MIN; 27 extern unsigned long int MIN; 28 extern long long int MIN; 29 extern unsigned long long int MIN; 30 30 31 extern constsigned char MAX;32 extern constunsigned char MAX;33 extern constshort int MAX;34 extern constunsigned short int MAX;35 extern constint MAX;36 extern constunsigned int MAX;37 extern constlong int MAX;38 extern constunsigned long int MAX;39 extern constlong long int MAX;40 extern constunsigned long long int MAX;31 extern signed char MAX; 32 extern unsigned char MAX; 33 extern short int MAX; 34 extern unsigned short int MAX; 35 extern int MAX; 36 extern unsigned int MAX; 37 extern long int MAX; 38 extern unsigned long int MAX; 39 extern long long int MAX; 40 extern unsigned long long int MAX; 41 41 42 42 // Floating-Point Constants 43 43 44 extern constfloat MIN;45 extern constdouble MIN;46 extern constlong double MIN;47 extern constfloat _Complex MIN;48 extern constdouble _Complex MIN;49 extern constlong double _Complex MIN;44 extern float MIN; 45 extern double MIN; 46 extern long double MIN; 47 extern float _Complex MIN; 48 extern double _Complex MIN; 49 extern long double _Complex MIN; 50 50 51 extern constfloat MAX;52 extern constdouble MAX;53 extern constlong double MAX;54 extern constfloat _Complex MAX;55 extern constdouble _Complex MAX;56 extern constlong double _Complex MAX;51 extern float MAX; 52 extern double MAX; 53 extern long double MAX; 54 extern float _Complex MAX; 55 extern double _Complex MAX; 56 extern long double _Complex MAX; 57 57 58 extern const float PI;// pi59 extern const float PI_2;// pi / 260 extern const float PI_4;// pi / 461 extern const float _1_PI;// 1 / pi62 extern const float _2_PI;// 2 / pi63 extern const float _2_SQRT_PI;// 2 / sqrt(pi)58 extern float PI; // pi 59 extern float PI_2; // pi / 2 60 extern float PI_4; // pi / 4 61 extern float _1_PI; // 1 / pi 62 extern float _2_PI; // 2 / pi 63 extern float _2_SQRT_PI; // 2 / sqrt(pi) 64 64 65 extern const double PI;// pi66 extern const double PI_2;// pi / 267 extern const double PI_4;// pi / 468 extern const double _1_PI;// 1 / pi69 extern const double _2_PI;// 2 / pi70 extern const double _2_SQRT_PI;// 2 / sqrt(pi)65 extern double PI; // pi 66 extern double PI_2; // pi / 2 67 extern double PI_4; // pi / 4 68 extern double _1_PI; // 1 / pi 69 extern double _2_PI; // 2 / pi 70 extern double _2_SQRT_PI; // 2 / sqrt(pi) 71 71 72 extern const long double PI;// pi73 extern const long double PI_2;// pi / 274 extern const long double PI_4;// pi / 475 extern const long double _1_PI;// 1 / pi76 extern const long double _2_PI;// 2 / pi77 extern const long double _2_SQRT_PI;// 2 / sqrt(pi)72 extern long double PI; // pi 73 extern long double PI_2; // pi / 2 74 extern long double PI_4; // pi / 4 75 extern long double _1_PI; // 1 / pi 76 extern long double _2_PI; // 2 / pi 77 extern long double _2_SQRT_PI; // 2 / sqrt(pi) 78 78 79 extern const float _Complex PI;// pi80 extern const float _Complex PI_2;// pi / 281 extern const float _Complex PI_4;// pi / 482 extern const float _Complex _1_PI;// 1 / pi83 extern const float _Complex _2_PI;// 2 / pi84 extern const float _Complex _2_SQRT_PI;// 2 / sqrt(pi)79 extern float _Complex PI; // pi 80 extern float _Complex PI_2; // pi / 2 81 extern float _Complex PI_4; // pi / 4 82 extern float _Complex _1_PI; // 1 / pi 83 extern float _Complex _2_PI; // 2 / pi 84 extern float _Complex _2_SQRT_PI; // 2 / sqrt(pi) 85 85 86 extern const double _Complex PI;// pi87 extern const double _Complex PI_2;// pi / 288 extern const double _Complex PI_4;// pi / 489 extern const double _Complex _1_PI;// 1 / pi90 extern const double _Complex _2_PI;// 2 / pi91 extern const double _Complex _2_SQRT_PI;// 2 / sqrt(pi)86 extern double _Complex PI; // pi 87 extern double _Complex PI_2; // pi / 2 88 extern double _Complex PI_4; // pi / 4 89 extern double _Complex _1_PI; // 1 / pi 90 extern double _Complex _2_PI; // 2 / pi 91 extern double _Complex _2_SQRT_PI; // 2 / sqrt(pi) 92 92 93 extern const long double _Complex PI;// pi94 extern const long double _Complex PI_2;// pi / 295 extern const long double _Complex PI_4;// pi / 496 extern const long double _Complex _1_PI;// 1 / pi97 extern const long double _Complex _2_PI;// 2 / pi98 extern const long double _Complex _2_SQRT_PI;// 2 / sqrt(pi)93 extern long double _Complex PI; // pi 94 extern long double _Complex PI_2; // pi / 2 95 extern long double _Complex PI_4; // pi / 4 96 extern long double _Complex _1_PI; // 1 / pi 97 extern long double _Complex _2_PI; // 2 / pi 98 extern long double _Complex _2_SQRT_PI; // 2 / sqrt(pi) 99 99 100 extern const float E;// e101 extern const float LOG2_E;// log_2(e)102 extern const float LOG10_E;// log_10(e)103 extern const float LN_2;// log_e(2)104 extern const float LN_10;// log_e(10)105 extern const float SQRT_2;// sqrt(2)106 extern const float _1_SQRT_2;// 1 / sqrt(2)100 extern float E; // e 101 extern float LOG2_E; // log_2(e) 102 extern float LOG10_E; // log_10(e) 103 extern float LN_2; // log_e(2) 104 extern float LN_10; // log_e(10) 105 extern float SQRT_2; // sqrt(2) 106 extern float _1_SQRT_2; // 1 / sqrt(2) 107 107 108 extern const double E;// e109 extern const double LOG2_E;// log_2(e)110 extern const double LOG10_E;// log_10(e)111 extern const double LN_2;// log_e(2)112 extern const double LN_10;// log_e(10)113 extern const double SQRT_2;// sqrt(2)114 extern const double _1_SQRT_2;// 1 / sqrt(2)108 extern double E; // e 109 extern double LOG2_E; // log_2(e) 110 extern double LOG10_E; // log_10(e) 111 extern double LN_2; // log_e(2) 112 extern double LN_10; // log_e(10) 113 extern double SQRT_2; // sqrt(2) 114 extern double _1_SQRT_2; // 1 / sqrt(2) 115 115 116 extern const long double E;// e117 extern const long double LOG2_E;// log_2(e)118 extern const long double LOG10_E;// log_10(e)119 extern const long double LN_2;// log_e(2)120 extern const long double LN_10;// log_e(10)121 extern const long double SQRT_2;// sqrt(2)122 extern const long double _1_SQRT_2;// 1/sqrt(2)116 extern long double E; // e 117 extern long double LOG2_E; // log_2(e) 118 extern long double LOG10_E; // log_10(e) 119 extern long double LN_2; // log_e(2) 120 extern long double LN_10; // log_e(10) 121 extern long double SQRT_2; // sqrt(2) 122 extern long double _1_SQRT_2; // 1/sqrt(2) 123 123 124 extern const float _Complex E;// e125 extern const float _Complex LOG2_E;// log_2(e)126 extern const float _Complex LOG10_E;// log_10(e)127 extern const float _Complex LN_2;// log_e(2)128 extern const float _Complex LN_10;// log_e(10)129 extern const float _Complex SQRT_2;// sqrt(2)130 extern const float _Complex _1_SQRT_2;// 1 / sqrt(2)124 extern float _Complex E; // e 125 extern float _Complex LOG2_E; // log_2(e) 126 extern float _Complex LOG10_E; // log_10(e) 127 extern float _Complex LN_2; // log_e(2) 128 extern float _Complex LN_10; // log_e(10) 129 extern float _Complex SQRT_2; // sqrt(2) 130 extern float _Complex _1_SQRT_2; // 1 / sqrt(2) 131 131 132 extern const double _Complex E;// e133 extern const double _Complex LOG2_E;// log_2(e)134 extern const double _Complex LOG10_E;// log_10(e)135 extern const double _Complex LN_2;// log_e(2)136 extern const double _Complex LN_10;// log_e(10)137 extern const double _Complex SQRT_2;// sqrt(2)138 extern const double _Complex _1_SQRT_2;// 1 / sqrt(2)132 extern double _Complex E; // e 133 extern double _Complex LOG2_E; // log_2(e) 134 extern double _Complex LOG10_E; // log_10(e) 135 extern double _Complex LN_2; // log_e(2) 136 extern double _Complex LN_10; // log_e(10) 137 extern double _Complex SQRT_2; // sqrt(2) 138 extern double _Complex _1_SQRT_2; // 1 / sqrt(2) 139 139 140 extern const long double _Complex E;// e141 extern const long double _Complex LOG2_E;// log_2(e)142 extern const long double _Complex LOG10_E;// log_10(e)143 extern const long double _Complex LN_2;// log_e(2)144 extern const long double _Complex LN_10;// log_e(10)145 extern const long double _Complex SQRT_2;// sqrt(2)146 extern const long double _Complex _1_SQRT_2;// 1 / sqrt(2)140 extern long double _Complex E; // e 141 extern long double _Complex LOG2_E; // log_2(e) 142 extern long double _Complex LOG10_E; // log_10(e) 143 extern long double _Complex LN_2; // log_e(2) 144 extern long double _Complex LN_10; // log_e(10) 145 extern long double _Complex SQRT_2; // sqrt(2) 146 extern long double _Complex _1_SQRT_2; // 1 / sqrt(2) 147 147 148 148 // Local Variables: // -
libcfa/src/parseargs.cfa
rae2c27a rc76bd34 25 25 #include "limits.hfa" 26 26 27 extern int cfa_args_argc ;28 extern char ** cfa_args_argv ;29 extern char ** cfa_args_envp ;27 extern int cfa_args_argc __attribute__((weak)); 28 extern char ** cfa_args_argv __attribute__((weak)); 29 extern char ** cfa_args_envp __attribute__((weak)); 30 30 31 31 static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * usage, FILE * out) __attribute__ ((noreturn)); 32 32 33 33 void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) { 34 parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left ); 34 if( 0p != &cfa_args_argc ) { 35 parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left ); 36 } 37 else { 38 char * temp = ""; 39 parse_args(0, &temp, options, opt_count, usage, left ); 40 } 35 41 } 36 42 -
src/AST/Convert.cpp
rae2c27a rc76bd34 177 177 const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final { 178 178 if ( inCache( node ) ) return nullptr; 179 180 // function decl contains real variables that the type must use. 181 // the structural change means function type in and out of decl 182 // must be handled **differently** on convert back to old. 183 auto ftype = new FunctionType( 184 cv(node->type), 185 (bool)node->type->isVarArgs 186 ); 187 ftype->returnVals = get<DeclarationWithType>().acceptL(node->returns); 188 ftype->parameters = get<DeclarationWithType>().acceptL(node->params); 189 190 ftype->forall = get<TypeDecl>().acceptL( node->type->forall ); 191 192 visitType(node->type, ftype); 193 179 194 auto decl = new FunctionDecl( 180 195 node->name, 181 196 Type::StorageClasses( node->storage.val ), 182 197 LinkageSpec::Spec( node->linkage.val ), 183 get<FunctionType>().accept1( node->type ), 198 ftype, 199 //get<FunctionType>().accept1( node->type ), 184 200 {}, 185 201 get<Attribute>().acceptL( node->attributes ), … … 1152 1168 1153 1169 const ast::Type * visit( const ast::FunctionType * node ) override final { 1170 static std::string dummy_paramvar_prefix = "__param_"; 1171 static std::string dummy_returnvar_prefix = "__retval_"; 1172 1154 1173 auto ty = new FunctionType { 1155 1174 cv( node ), 1156 1175 (bool)node->isVarArgs 1157 1176 }; 1158 ty->returnVals = get<DeclarationWithType>().acceptL( node->returns ); 1159 ty->parameters = get<DeclarationWithType>().acceptL( node->params ); 1177 auto returns = get<Type>().acceptL(node->returns); 1178 auto params = get<Type>().acceptL(node->params); 1179 1180 int ret_index = 0; 1181 for (auto t: returns) { 1182 // xxx - LinkageSpec shouldn't matter but needs to be something 1183 ObjectDecl * dummy = new ObjectDecl(dummy_returnvar_prefix + std::to_string(ret_index++), {}, LinkageSpec::C, nullptr, t, nullptr); 1184 ty->returnVals.push_back(dummy); 1185 } 1186 int param_index = 0; 1187 for (auto t: params) { 1188 ObjectDecl * dummy = new ObjectDecl(dummy_paramvar_prefix + std::to_string(param_index++), {}, LinkageSpec::C, nullptr, t, nullptr); 1189 ty->parameters.push_back(dummy); 1190 } 1191 1192 // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns ); 1193 // ty->parameters = get<DeclarationWithType>().acceptL( node->params ); 1160 1194 ty->forall = get<TypeDecl>().acceptL( node->forall ); 1161 1195 return visitType( node, ty ); 1162 1196 } 1163 1197 1164 const ast::Type * postvisit( const ast:: ReferenceToType * old, ReferenceToType * ty ) {1198 const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) { 1165 1199 ty->forall = get<TypeDecl>().acceptL( old->forall ); 1166 1200 ty->parameters = get<Expression>().acceptL( old->params ); … … 1374 1408 ast::Node * node = nullptr; 1375 1409 /// cache of nodes that might be referenced by readonly<> for de-duplication 1376 std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {}; 1410 /// in case that some nodes are dropped by conversion (due to possible structural change) 1411 /// use smart pointers in cache value to prevent accidental invalidation. 1412 /// at conversion stage, all created nodes are guaranteed to be unique, therefore 1413 /// const_casting out of smart pointers is permitted. 1414 std::unordered_map< const BaseSyntaxNode *, ast::ptr<ast::Node> > cache = {}; 1377 1415 1378 1416 // Local Utilities: … … 1447 1485 auto it = cache.find( old ); 1448 1486 if ( it == cache.end() ) return false; 1449 node = it->second;1487 node = const_cast<ast::Node *>(it->second.get()); 1450 1488 return true; 1451 1489 } … … 1486 1524 virtual void visit( const FunctionDecl * old ) override final { 1487 1525 if ( inCache( old ) ) return; 1526 auto paramVars = GET_ACCEPT_V(type->parameters, DeclWithType); 1527 auto returnVars = GET_ACCEPT_V(type->returnVals, DeclWithType); 1528 auto forall = GET_ACCEPT_V(type->forall, TypeDecl); 1529 1530 // function type is now derived from parameter decls instead of storing them 1531 auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type)); 1532 ftype->params.reserve(paramVars.size()); 1533 ftype->returns.reserve(returnVars.size()); 1534 1535 for (auto & v: paramVars) { 1536 ftype->params.emplace_back(v->get_type()); 1537 } 1538 for (auto & v: returnVars) { 1539 ftype->returns.emplace_back(v->get_type()); 1540 } 1541 ftype->forall = std::move(forall); 1542 visitType(old->type, ftype); 1543 1488 1544 auto decl = new ast::FunctionDecl{ 1489 1545 old->location, 1490 1546 old->name, 1491 GET_ACCEPT_1(type, FunctionType), 1547 // GET_ACCEPT_1(type, FunctionType), 1548 std::move(paramVars), 1549 std::move(returnVars), 1492 1550 {}, 1493 1551 { old->storageClasses.val }, … … 1496 1554 { old->get_funcSpec().val } 1497 1555 }; 1556 1557 decl->type = ftype; 1498 1558 cache.emplace( old, decl ); 1559 1499 1560 decl->withExprs = GET_ACCEPT_V(withExprs, Expr); 1500 1561 decl->stmts = GET_ACCEPT_1(statements, CompoundStmt); … … 2515 2576 cv( old ) 2516 2577 }; 2517 ty->returns = GET_ACCEPT_V( returnVals, DeclWithType ); 2518 ty->params = GET_ACCEPT_V( parameters, DeclWithType ); 2578 auto returnVars = GET_ACCEPT_V(returnVals, DeclWithType); 2579 auto paramVars = GET_ACCEPT_V(parameters, DeclWithType); 2580 // ty->returns = GET_ACCEPT_V( returnVals, DeclWithType ); 2581 // ty->params = GET_ACCEPT_V( parameters, DeclWithType ); 2582 for (auto & v: returnVars) { 2583 ty->returns.emplace_back(v->get_type()); 2584 } 2585 for (auto & v: paramVars) { 2586 ty->params.emplace_back(v->get_type()); 2587 } 2519 2588 ty->forall = GET_ACCEPT_V( forall, TypeDecl ); 2520 2589 visitType( old, ty ); 2521 2590 } 2522 2591 2523 void postvisit( const ReferenceToType * old, ast:: ReferenceToType * ty ) {2592 void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) { 2524 2593 ty->forall = GET_ACCEPT_V( forall, TypeDecl ); 2525 2594 ty->params = GET_ACCEPT_V( parameters, Expr ); -
src/AST/Decl.hpp
rae2c27a rc76bd34 124 124 class FunctionDecl : public DeclWithType { 125 125 public: 126 std::vector<ptr<DeclWithType>> params; 127 std::vector<ptr<DeclWithType>> returns; 128 // declared type, derived from parameter declarations 126 129 ptr<FunctionType> type; 127 130 ptr<CompoundStmt> stmts; 128 131 std::vector< ptr<Expr> > withExprs; 129 132 130 FunctionDecl( const CodeLocation & loc, const std::string & name, FunctionType * type, 133 FunctionDecl( const CodeLocation & loc, const std::string & name, 134 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 131 135 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, 132 136 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}) 133 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type),137 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)), 134 138 stmts( stmts ) {} 135 139 -
src/AST/ForallSubstitutor.hpp
rae2c27a rc76bd34 33 33 } 34 34 35 template<typename node_t > 36 std::vector<ptr<node_t>> operator() (const std::vector<ptr<node_t>> & o) { 37 std::vector<ptr<node_t>> n; 38 n.reserve(o.size()); 39 for (const node_t * d : o) { n.emplace_back(d->accept(*visitor)); } 40 return n; 41 } 42 43 /* 44 35 45 /// Substitute parameter/return type 36 46 std::vector< ptr< DeclWithType > > operator() ( const std::vector< ptr< DeclWithType > > & o ) { … … 48 58 return n; 49 59 } 60 61 */ 50 62 }; 51 63 -
src/AST/Fwd.hpp
rae2c27a rc76bd34 107 107 class QualifiedType; 108 108 class FunctionType; 109 class ReferenceToType;109 class BaseInstType; 110 110 template<typename decl_t> class SueInstType; 111 111 using StructInstType = SueInstType<StructDecl>; -
src/AST/GenericSubstitution.cpp
rae2c27a rc76bd34 42 42 private: 43 43 // make substitution for generic type 44 void makeSub( const ReferenceToType * ty ) {44 void makeSub( const BaseInstType * ty ) { 45 45 visit_children = false; 46 46 const AggregateDecl * aggr = ty->aggr(); -
src/AST/Node.cpp
rae2c27a rc76bd34 266 266 template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::weak >; 267 267 template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::strong >; 268 template class ast::ptr_base< ast:: ReferenceToType, ast::Node::ref_type::weak >;269 template class ast::ptr_base< ast:: ReferenceToType, ast::Node::ref_type::strong >;268 template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::weak >; 269 template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::strong >; 270 270 template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::weak >; 271 271 template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::strong >; -
src/AST/Pass.hpp
rae2c27a rc76bd34 50 50 // | PureVisitor - makes the visitor pure, it never modifies nodes in place and always 51 51 // clones nodes it needs to make changes to 52 // | With TypeSubstitution - provides polymorphic const TypeSubstitution * envfor the52 // | WithConstTypeSubstitution - provides polymorphic const TypeSubstitution * typeSubs for the 53 53 // current expression 54 54 // | WithStmtsToAdd - provides the ability to insert statements before or after the current … … 67 67 // | WithSymbolTable - provides symbol table functionality 68 68 // | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation 69 // 70 // Other Special Members: 71 // | result - Either a method that takes no parameters or a field. If a method (or 72 // callable field) get_result calls it, otherwise the value is returned. 69 73 //------------------------------------------------------------------------------------------------- 70 74 template< typename core_t > … … 89 93 virtual ~Pass() = default; 90 94 95 /// Storage for the actual pass. 96 core_t core; 97 98 /// If the core defines a result, call it if possible, otherwise return it. 99 inline auto get_result() -> decltype( __pass::get_result( core, '0' ) ) { 100 return __pass::get_result( core, '0' ); 101 } 102 91 103 /// Construct and run a pass on a translation unit. 92 104 template< typename... Args > … … 96 108 } 97 109 110 /// Contruct and run a pass on a pointer to extract a value. 111 template< typename node_type, typename... Args > 112 static auto read( node_type const * node, Args&&... args ) { 113 Pass<core_t> visitor( std::forward<Args>( args )... ); 114 node_type const * temp = node->accept( visitor ); 115 assert( temp == node ); 116 return visitor.get_result(); 117 } 118 119 // Versions of the above for older compilers. 98 120 template< typename... Args > 99 121 static void run( std::list< ptr<Decl> > & decls ) { … … 102 124 } 103 125 104 /// Storage for the actual pass 105 core_t core; 126 template< typename node_type, typename... Args > 127 static auto read( node_type const * node ) { 128 Pass<core_t> visitor; 129 node_type const * temp = node->accept( visitor ); 130 assert( temp == node ); 131 return visitor.get_result(); 132 } 106 133 107 134 /// Visit function declarations … … 267 294 //------------------------------------------------------------------------------------------------- 268 295 269 /// Keep track of the polymorphic const TypeSubstitution * env for the current expression270 271 296 /// If used the visitor will always clone nodes. 272 297 struct PureVisitor {}; 273 298 299 /// Keep track of the polymorphic const TypeSubstitution * typeSubs for the current expression. 274 300 struct WithConstTypeSubstitution { 275 const TypeSubstitution * env= nullptr;301 const TypeSubstitution * typeSubs = nullptr; 276 302 }; 277 303 -
src/AST/Pass.impl.hpp
rae2c27a rc76bd34 154 154 __pedantic_pass_assert( expr ); 155 155 156 const ast::TypeSubstitution ** env_ptr = __pass::env( core, 0);157 if ( env_ptr && expr->env ) {158 * env_ptr = expr->env;156 const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 ); 157 if ( typeSubs_ptr && expr->env ) { 158 *typeSubs_ptr = expr->env; 159 159 } 160 160 … … 177 177 178 178 // These may be modified by subnode but most be restored once we exit this statemnet. 179 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass:: env( core, 0) );179 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::typeSubs( core, 0 ) ); 180 180 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 181 181 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); … … 465 465 __pass::symtab::addId( core, 0, func ); 466 466 VISIT( 467 // parameter declarations are now directly here 468 maybe_accept( node, &FunctionDecl::params ); 469 maybe_accept( node, &FunctionDecl::returns ); 470 // foralls are still in function type 467 471 maybe_accept( node, &FunctionDecl::type ); 468 472 // function body needs to have the same scope as parameters - CompoundStmt will not enter … … 1488 1492 1489 1493 // These may be modified by subnode but most be restored once we exit this statemnet. 1490 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass:: env( core, 0) );1494 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::typeSubs( core, 0 ) ); 1491 1495 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 1492 1496 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); -
src/AST/Pass.proto.hpp
rae2c27a rc76bd34 236 236 237 237 // List of fields and their expected types 238 FIELD_PTR( env, const ast::TypeSubstitution * )238 FIELD_PTR( typeSubs, const ast::TypeSubstitution * ) 239 239 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 240 240 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) … … 421 421 422 422 } // namespace forall 423 424 template<typename core_t> 425 static inline auto get_result( core_t & core, char ) -> decltype( core.result() ) { 426 return core.result(); 427 } 428 429 template<typename core_t> 430 static inline auto get_result( core_t & core, int ) -> decltype( core.result ) { 431 return core.result; 432 } 433 434 template<typename core_t> 435 static inline void get_result( core_t &, long ) {} 423 436 } // namespace __pass 424 437 } // namespace ast -
src/AST/Print.cpp
rae2c27a rc76bd34 270 270 } 271 271 272 void preprint( const ast:: ReferenceToType * node ) {272 void preprint( const ast::BaseInstType * node ) { 273 273 print( node->forall ); 274 274 print( node->attributes ); -
src/AST/SymbolTable.cpp
rae2c27a rc76bd34 313 313 if ( ! expr->result ) continue; 314 314 const Type * resTy = expr->result->stripReferences(); 315 auto aggrType = dynamic_cast< const ReferenceToType * >( resTy );315 auto aggrType = dynamic_cast< const BaseInstType * >( resTy ); 316 316 assertf( aggrType, "WithStmt expr has non-aggregate type: %s", 317 317 toString( expr->result ).c_str() ); … … 335 335 } 336 336 337 /* 337 338 void SymbolTable::addFunctionType( const FunctionType * ftype ) { 338 339 addTypes( ftype->forall ); … … 340 341 addIds( ftype->params ); 341 342 } 343 */ 342 344 343 345 void SymbolTable::lazyInitScope() { … … 368 370 assert( ! params.empty() ); 369 371 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 370 const Type * base = InitTweak::getPointerBase( params.front() ->get_type());372 const Type * base = InitTweak::getPointerBase( params.front() ); 371 373 assert( base ); 372 374 return Mangle::mangle( base ); … … 654 656 if ( dwt->name == "" ) { 655 657 const Type * t = dwt->get_type()->stripReferences(); 656 if ( auto rty = dynamic_cast<const ReferenceToType *>( t ) ) {658 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) { 657 659 if ( ! dynamic_cast<const StructInstType *>(rty) 658 660 && ! dynamic_cast<const UnionInstType *>(rty) ) continue; -
src/AST/SymbolTable.hpp
rae2c27a rc76bd34 145 145 146 146 /// convenience function for adding all of the declarations in a function type to the indexer 147 void addFunctionType( const FunctionType * ftype );147 // void addFunctionType( const FunctionType * ftype ); 148 148 149 149 private: -
src/AST/Type.cpp
rae2c27a rc76bd34 102 102 // --- FunctionType 103 103 104 104 105 FunctionType::FunctionType( const FunctionType & o ) 105 106 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(), … … 112 113 113 114 namespace { 114 bool containsTtype( const std::vector<ptr< DeclWithType>> & l ) {115 bool containsTtype( const std::vector<ptr<Type>> & l ) { 115 116 if ( ! l.empty() ) { 116 return Tuples::isTtype( l.back() ->get_type());117 return Tuples::isTtype( l.back() ); 117 118 } 118 119 return false; … … 124 125 } 125 126 126 // --- ReferenceToType127 128 void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {127 // --- BaseInstType 128 129 void BaseInstType::initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ) { 129 130 ParameterizedType::initWithSub( o, sub ); // initialize substitution 130 131 params = sub.core( o.params ); // apply to parameters 131 132 } 132 133 133 ReferenceToType::ReferenceToType( const ReferenceToType & o )134 BaseInstType::BaseInstType( const BaseInstType & o ) 134 135 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ), 135 136 hoistType( o.hoistType ) { … … 138 139 } 139 140 140 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {141 std::vector<readonly<Decl>> BaseInstType::lookup( const std::string& name ) const { 141 142 assertf( aggr(), "Must have aggregate to perform lookup" ); 142 143 … … 153 154 SueInstType<decl_t>::SueInstType( 154 155 const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as ) 155 : ReferenceToType( b->name, q, move(as) ), base( b ) {}156 : BaseInstType( b->name, q, move(as) ), base( b ) {} 156 157 157 158 template<typename decl_t> … … 168 169 TraitInstType::TraitInstType( 169 170 const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as ) 170 : ReferenceToType( b->name, q, move(as) ), base( b ) {}171 : BaseInstType( b->name, q, move(as) ), base( b ) {} 171 172 172 173 // --- TypeInstType 173 174 174 175 TypeInstType::TypeInstType( const TypeInstType & o ) 175 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {176 : BaseInstType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) { 176 177 Pass< ForallSubstitutor > sub; 177 178 initWithSub( o, sub ); // initialize substitution -
src/AST/Type.hpp
rae2c27a rc76bd34 302 302 class FunctionType final : public ParameterizedType { 303 303 public: 304 std::vector<ptr<DeclWithType>> returns; 305 std::vector<ptr<DeclWithType>> params; 304 // std::vector<ptr<DeclWithType>> returns; 305 // std::vector<ptr<DeclWithType>> params; 306 307 std::vector<ptr<Type>> returns; 308 std::vector<ptr<Type>> params; 306 309 307 310 /// Does the function accept a variable number of arguments following the arguments specified … … 329 332 330 333 /// base class for types that refer to types declared elsewhere (aggregates and typedefs) 331 class ReferenceToType : public ParameterizedType {334 class BaseInstType : public ParameterizedType { 332 335 protected: 333 336 /// Initializes forall and parameters based on substitutor 334 void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );337 void initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ); 335 338 public: 336 339 std::vector<ptr<Expr>> params; … … 338 341 bool hoistType = false; 339 342 340 ReferenceToType(343 BaseInstType( 341 344 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 342 345 : ParameterizedType(q, std::move(as)), params(), name(n) {} 343 346 344 ReferenceToType( const ReferenceToType & o );347 BaseInstType( const BaseInstType & o ); 345 348 346 349 /// Gets aggregate declaration this type refers to … … 350 353 351 354 private: 352 virtual ReferenceToType * clone() const override = 0;355 virtual BaseInstType * clone() const override = 0; 353 356 MUTATE_FRIEND 354 357 }; … … 356 359 // Common implementation for the SUE instance types. Not to be used directly. 357 360 template<typename decl_t> 358 class SueInstType final : public ReferenceToType {361 class SueInstType final : public BaseInstType { 359 362 public: 360 363 using base_type = decl_t; … … 363 366 SueInstType( 364 367 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 365 : ReferenceToType( n, q, std::move(as) ), base() {}368 : BaseInstType( n, q, std::move(as) ), base() {} 366 369 367 370 SueInstType( … … 388 391 389 392 /// An instance of a trait type. 390 class TraitInstType final : public ReferenceToType {393 class TraitInstType final : public BaseInstType { 391 394 public: 392 395 readonly<TraitDecl> base; … … 394 397 TraitInstType( 395 398 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 396 : ReferenceToType( n, q, std::move(as) ), base() {}399 : BaseInstType( n, q, std::move(as) ), base() {} 397 400 398 401 TraitInstType( … … 411 414 412 415 /// instance of named type alias (typedef or variable) 413 class TypeInstType final : public ReferenceToType {416 class TypeInstType final : public BaseInstType { 414 417 public: 415 418 readonly<TypeDecl> base; … … 419 422 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 420 423 std::vector<ptr<Attribute>> && as = {} ) 421 : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}424 : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {} 422 425 TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {}, 423 426 std::vector<ptr<Attribute>> && as = {} ) 424 : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}427 : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {} 425 428 426 429 TypeInstType( const TypeInstType & o ); -
src/AST/TypeSubstitution.cpp
rae2c27a rc76bd34 176 176 } 177 177 178 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {178 void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) { 179 179 GuardValue( boundVars ); 180 180 // bind type variables from forall-qualifiers -
src/AST/TypeSubstitution.hpp
rae2c27a rc76bd34 169 169 void previsit( const ParameterizedType * type ); 170 170 /// Records type variable bindings from forall-statements and instantiations of generic types 171 void handleAggregateType( const ReferenceToType * type );171 void handleAggregateType( const BaseInstType * type ); 172 172 173 173 void previsit( const StructInstType * aggregateUseType ); -
src/Common/Stats/Stats.cc
rae2c27a rc76bd34 35 35 } 36 36 37 namespace ResolveTime { 38 bool enabled = false; 39 } 40 37 41 struct { 38 42 const char * const opt; … … 43 47 { "heap" , Heap::enabled }, 44 48 { "time" , Time::enabled }, 49 { "resolve" , ResolveTime::enabled }, 45 50 }; 46 51 -
src/Common/module.mk
rae2c27a rc76bd34 22 22 Common/ErrorObjects.h \ 23 23 Common/Eval.cc \ 24 Common/Examine.cc \ 25 Common/Examine.h \ 24 26 Common/FilterCombos.h \ 25 27 Common/Indenter.h \ … … 38 40 Common/Stats/Heap.cc \ 39 41 Common/Stats/Heap.h \ 42 Common/Stats/ResolveTime.cc \ 43 Common/Stats/ResolveTime.h \ 40 44 Common/Stats/Stats.cc \ 41 45 Common/Stats/Time.cc \ -
src/Concurrency/Keywords.cc
rae2c27a rc76bd34 19 19 #include <string> // for string, operator== 20 20 21 #include <iostream> 22 23 #include "Common/Examine.h" // for isMainFor 21 24 #include "Common/PassVisitor.h" // for PassVisitor 22 25 #include "Common/SemanticError.h" // for SemanticError … … 34 37 #include "SynTree/Type.h" // for StructInstType, Type, PointerType 35 38 #include "SynTree/Visitor.h" // for Visitor, acceptAll 39 #include "Virtual/Tables.h" 36 40 37 41 class Attribute; 38 42 39 43 namespace Concurrency { 44 inline static std::string getVTableName( std::string const & exception_name ) { 45 return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name); 46 } 47 40 48 //============================================================================================= 41 49 // Pass declarations … … 54 62 public: 55 63 56 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, AggregateDecl::Aggregate cast_target ) : 57 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ), cast_target( cast_target ) {} 64 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, 65 std::string&& getter_name, std::string&& context_error, std::string&& exception_name, 66 bool needs_main, AggregateDecl::Aggregate cast_target ) : 67 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), 68 context_error( context_error ), vtable_name( getVTableName( exception_name ) ), 69 needs_main( needs_main ), cast_target( cast_target ) {} 58 70 59 71 virtual ~ConcurrentSueKeyword() {} … … 63 75 64 76 void handle( StructDecl * ); 77 void addVtableForward( StructDecl * ); 65 78 FunctionDecl * forwardDeclare( StructDecl * ); 66 79 ObjectDecl * addField( StructDecl * ); … … 76 89 const std::string getter_name; 77 90 const std::string context_error; 91 const std::string vtable_name; 78 92 bool needs_main; 79 93 AggregateDecl::Aggregate cast_target; … … 81 95 StructDecl * type_decl = nullptr; 82 96 FunctionDecl * dtor_decl = nullptr; 97 StructDecl * vtable_decl = nullptr; 83 98 }; 84 99 … … 101 116 "get_thread", 102 117 "thread keyword requires threads to be in scope, add #include <thread.hfa>\n", 118 "", 103 119 true, 104 120 AggregateDecl::Thread … … 133 149 "get_coroutine", 134 150 "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n", 151 "CoroutineCancelled", 135 152 true, 136 153 AggregateDecl::Coroutine … … 167 184 "get_monitor", 168 185 "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n", 186 "", 169 187 false, 170 188 AggregateDecl::Monitor … … 198 216 "get_generator", 199 217 "Unable to find builtin type $generator\n", 218 "", 200 219 true, 201 220 AggregateDecl::Generator … … 231 250 232 251 private: 233 DeclarationWithType * is_main( FunctionDecl * );234 252 bool is_real_suspend( FunctionDecl * ); 235 253 … … 359 377 handle( decl ); 360 378 } 379 else if ( !vtable_decl && vtable_name == decl->name && decl->body ) { 380 vtable_decl = decl; 381 } 382 // Might be able to get ride of is target. 383 assert( is_target(decl) == (cast_target == decl->kind) ); 361 384 return decl; 362 385 } 363 386 364 387 DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) { 365 if( !type_decl ) return decl; 366 if( !CodeGen::isDestructor( decl->name ) ) return decl; 367 368 auto params = decl->type->parameters; 369 if( params.size() != 1 ) return decl; 370 371 auto type = dynamic_cast<ReferenceType*>( params.front()->get_type() ); 372 if( !type ) return decl; 373 374 auto stype = dynamic_cast<StructInstType*>( type->base ); 375 if( !stype ) return decl; 376 if( stype->baseStruct != type_decl ) return decl; 377 378 if( !dtor_decl ) dtor_decl = decl; 388 if ( type_decl && isDestructorFor( decl, type_decl ) ) 389 dtor_decl = decl; 390 else if ( vtable_name.empty() ) 391 ; 392 else if ( auto param = isMainFor( decl, cast_target ) ) { 393 // This should never trigger. 394 assert( vtable_decl ); 395 // Should be safe because of isMainFor. 396 StructInstType * struct_type = static_cast<StructInstType *>( 397 static_cast<ReferenceType *>( param->get_type() )->base ); 398 assert( struct_type ); 399 400 declsToAddAfter.push_back( Virtual::makeVtableInstance( vtable_decl, { 401 new TypeExpr( struct_type->clone() ), 402 }, struct_type, nullptr ) ); 403 } 404 379 405 return decl; 380 406 } … … 400 426 if( !dtor_decl ) SemanticError( decl, context_error ); 401 427 428 addVtableForward( decl ); 402 429 FunctionDecl * func = forwardDeclare( decl ); 403 430 ObjectDecl * field = addField( decl ); 404 431 addRoutines( field, func ); 432 } 433 434 void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) { 435 if ( vtable_decl ) { 436 declsToAddBefore.push_back( Virtual::makeVtableForward( vtable_decl, { 437 new TypeExpr( new StructInstType( noQualifiers, decl ) ), 438 } ) ); 439 // Its only an error if we want a vtable and don't have one. 440 } else if ( ! vtable_name.empty() ) { 441 SemanticError( decl, context_error ); 442 } 405 443 } 406 444 … … 528 566 // Suspend keyword implementation 529 567 //============================================================================================= 530 DeclarationWithType * SuspendKeyword::is_main( FunctionDecl * func) {531 if(func->name != "main") return nullptr;532 if(func->type->parameters.size() != 1) return nullptr;533 534 auto param = func->type->parameters.front();535 536 auto type = dynamic_cast<ReferenceType * >(param->get_type());537 if(!type) return nullptr;538 539 auto obj = dynamic_cast<StructInstType *>(type->base);540 if(!obj) return nullptr;541 542 if(!obj->baseStruct->is_generator()) return nullptr;543 544 return param;545 }546 547 568 bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) { 548 569 if(isMangled(func->linkage)) return false; // the real suspend isn't mangled … … 565 586 566 587 // Is this the main of a generator? 567 auto param = is _main( func);588 auto param = isMainFor( func, AggregateDecl::Aggregate::Generator ); 568 589 if(!param) return; 569 590 … … 910 931 { 911 932 new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ), 912 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ) 933 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ), 934 new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) ) 913 935 }, 914 936 noDesignators, … … 1033 1055 // tab-width: 4 // 1034 1056 // End: // 1057 -
src/GenPoly/InstantiateGeneric.cc
rae2c27a rc76bd34 172 172 InstantiationMap< AggregateDecl, AggregateDecl > instantiations; 173 173 /// Set of types which are dtype-only generic (and therefore have static layout) 174 ScopedSet< AggregateDecl*> dtypeStatics;174 std::set<AggregateDecl *> dtypeStatics; 175 175 /// Namer for concrete types 176 176 UniqueName typeNamer; … … 505 505 void GenericInstantiator::beginScope() { 506 506 instantiations.beginScope(); 507 dtypeStatics.beginScope();508 507 } 509 508 510 509 void GenericInstantiator::endScope() { 511 510 instantiations.endScope(); 512 dtypeStatics.endScope();513 511 } 514 512 -
src/InitTweak/InitTweak.cc
rae2c27a rc76bd34 1026 1026 if ( ftype->params.size() != 2 ) return false; 1027 1027 1028 const ast::Type * t1 = getPointerBase( ftype->params.front() ->get_type());1028 const ast::Type * t1 = getPointerBase( ftype->params.front() ); 1029 1029 if ( ! t1 ) return false; 1030 const ast::Type * t2 = ftype->params.back() ->get_type();1030 const ast::Type * t2 = ftype->params.back(); 1031 1031 1032 1032 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} ); -
src/Parser/lex.ll
rae2c27a rc76bd34 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : Sat Feb 15 11:05:50202013 * Update Count : 7 3712 * Last Modified On : Tue Oct 6 18:15:41 2020 13 * Update Count : 743 14 14 */ 15 15 … … 62 62 #define IDENTIFIER_RETURN() RETURN_VAL( typedefTable.isKind( yytext ) ) 63 63 64 #ifdef HAVE_KEYWORDS_FLOATXX // GCC >= 7 => keyword, otherwise typedef64 #ifdef HAVE_KEYWORDS_FLOATXX // GCC >= 7 => keyword, otherwise typedef 65 65 #define FLOATXX(v) KEYWORD_RETURN(v); 66 66 #else … … 292 292 __restrict__ { KEYWORD_RETURN(RESTRICT); } // GCC 293 293 return { KEYWORD_RETURN(RETURN); } 294 /* resume { KEYWORD_RETURN(RESUME); } // CFA */294 /* resume { KEYWORD_RETURN(RESUME); } // CFA */ 295 295 short { KEYWORD_RETURN(SHORT); } 296 296 signed { KEYWORD_RETURN(SIGNED); } -
src/Parser/parser.yy
rae2c27a rc76bd34 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu May 28 12:11:45202013 // Update Count : 4 50012 // Last Modified On : Tue Oct 6 18:24:18 2020 13 // Update Count : 4610 14 14 // 15 15 … … 278 278 %token OTYPE FTYPE DTYPE TTYPE TRAIT // CFA 279 279 %token SIZEOF OFFSETOF 280 // %token RESUME // CFA281 %token SUSPEND // CFA280 // %token RESUME // CFA 281 %token SUSPEND // CFA 282 282 %token ATTRIBUTE EXTENSION // GCC 283 283 %token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN … … 329 329 %type<en> conditional_expression constant_expression assignment_expression assignment_expression_opt 330 330 %type<en> comma_expression comma_expression_opt 331 %type<en> argument_expression_list_opt argument_expression default_initialize_opt331 %type<en> argument_expression_list_opt argument_expression default_initialize_opt 332 332 %type<ifctl> if_control_expression 333 333 %type<fctl> for_control_expression for_control_expression_list … … 370 370 %type<decl> assertion assertion_list assertion_list_opt 371 371 372 %type<en> bit_subrange_size_opt bit_subrange_size372 %type<en> bit_subrange_size_opt bit_subrange_size 373 373 374 374 %type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type … … 793 793 | '(' aggregate_control '&' ')' cast_expression // CFA 794 794 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); } 795 // VIRTUAL cannot be opt because of look ahead issues796 795 | '(' VIRTUAL ')' cast_expression // CFA 797 796 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild< Expression >( $4 ), maybeMoveBuildType( nullptr ) ) ); } … … 920 919 | unary_expression assignment_operator assignment_expression 921 920 { 922 if ( $2 == OperKinds::AtAssn ) {923 SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;924 } else {921 // if ( $2 == OperKinds::AtAssn ) { 922 // SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr; 923 // } else { 925 924 $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); 926 } // if925 // } // if 927 926 } 928 927 | unary_expression '=' '{' initializer_list_opt comma_opt '}' … … 1676 1675 1677 1676 typedef_expression: 1678 // GCC, naming expression type: typedef name = exp; gives a name to the type of an expression1677 // deprecated GCC, naming expression type: typedef name = exp; gives a name to the type of an expression 1679 1678 TYPEDEF identifier '=' assignment_expression 1680 1679 { 1681 // $$ = DeclarationNode::newName( 0 ); // unimplemented 1682 SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr; 1680 SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr; 1683 1681 } 1684 1682 | typedef_expression pop ',' push identifier '=' assignment_expression 1685 1683 { 1686 // $$ = DeclarationNode::newName( 0 ); // unimplemented 1687 SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr; 1688 } 1689 ; 1690 1691 //c_declaration: 1692 // declaring_list pop ';' 1693 // | typedef_declaration pop ';' 1694 // | typedef_expression pop ';' // GCC, naming expression type 1695 // | sue_declaration_specifier pop ';' 1696 // ; 1697 // 1698 //declaring_list: 1699 // // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static 1700 // // storage-class 1701 // declarator asm_name_opt initializer_opt 1702 // { 1703 // typedefTable.addToEnclosingScope( IDENTIFIER ); 1704 // $$ = ( $2->addType( $1 ))->addAsmName( $3 )->addInitializer( $4 ); 1705 // } 1706 // | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt 1707 // { 1708 // typedefTable.addToEnclosingScope( IDENTIFIER ); 1709 // $$ = $1->appendList( $1->cloneBaseType( $4->addAsmName( $5 )->addInitializer( $6 ) ) ); 1710 // } 1711 // ; 1684 SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr; 1685 } 1686 ; 1712 1687 1713 1688 c_declaration: … … 1715 1690 { $$ = distAttr( $1, $2 ); } 1716 1691 | typedef_declaration 1717 | typedef_expression // GCC, naming expression type1692 | typedef_expression // deprecated GCC, naming expression type 1718 1693 | sue_declaration_specifier 1719 1694 ; … … 2094 2069 { yyy = true; $$ = AggregateDecl::Union; } 2095 2070 | EXCEPTION // CFA 2096 { yyy = true; $$ = AggregateDecl::Exception; } 2071 // { yyy = true; $$ = AggregateDecl::Exception; } 2072 { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2097 2073 ; 2098 2074 -
src/ResolvExpr/CandidateFinder.cpp
rae2c27a rc76bd34 188 188 189 189 // mark conversion cost and also specialization cost of param type 190 const ast::Type * paramType = (*param)->get_type();190 // const ast::Type * paramType = (*param)->get_type(); 191 191 cand->expr = ast::mutate_field_index( 192 192 appExpr, &ast::ApplicationExpr::args, i, 193 193 computeExpressionConversionCost( 194 args[i], paramType, symtab, cand->env, convCost ) );195 convCost.decSpec( specCost( paramType) );194 args[i], *param, symtab, cand->env, convCost ) ); 195 convCost.decSpec( specCost( *param ) ); 196 196 ++param; // can't be in for-loop update because of the continue 197 197 } … … 698 698 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) { 699 699 // attempt to narrow based on expected target type 700 const ast::Type * returnType = funcType->returns.front() ->get_type();700 const ast::Type * returnType = funcType->returns.front(); 701 701 if ( ! unify( 702 702 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) … … 712 712 std::size_t genStart = 0; 713 713 714 for ( const ast::DeclWithType * param : funcType->params ) { 715 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param ); 714 // xxx - how to handle default arg after change to ftype representation? 715 if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) { 716 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) { 717 // function may have default args only if directly calling by name 718 // must use types on candidate however, due to RenameVars substitution 719 auto nParams = funcType->params.size(); 720 721 for (size_t i=0; i<nParams; ++i) { 722 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 723 if (!instantiateArgument( 724 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 725 } 726 goto endMatch; 727 } 728 } 729 for ( const auto & param : funcType->params ) { 716 730 // Try adding the arguments corresponding to the current parameter to the existing 717 731 // matches 732 // no default args for indirect calls 718 733 if ( ! instantiateArgument( 719 obj->type, obj->init, args, results, genStart, symtab ) ) return; 720 } 721 734 param, nullptr, args, results, genStart, symtab ) ) return; 735 } 736 737 endMatch: 722 738 if ( funcType->isVarArgs ) { 723 739 // append any unused arguments to vararg pack … … 816 832 /// Adds aggregate member interpretations 817 833 void addAggMembers( 818 const ast:: ReferenceToType * aggrInst, const ast::Expr * expr,834 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 819 835 const Candidate & cand, const Cost & addedCost, const std::string & name 820 836 ) { … … 1263 1279 1264 1280 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) { 1265 const ast:: ReferenceToType * aggInst;1281 const ast::BaseInstType * aggInst; 1266 1282 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ; 1267 1283 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ; -
src/ResolvExpr/ConversionCost.cc
rae2c27a rc76bd34 520 520 return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable ); 521 521 } else { 522 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost ); 523 src->accept( converter ); 524 return converter.core.cost; 522 return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost ); 525 523 } 526 524 } … … 563 561 } 564 562 } else { 565 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost ); 566 src->accept( converter ); 567 return converter.core.cost; 563 return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost ); 568 564 } 569 565 } else { -
src/ResolvExpr/ConversionCost.h
rae2c27a rc76bd34 88 88 static size_t traceId; 89 89 Cost cost; 90 Cost result() { return cost; } 90 91 91 92 ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab, -
src/ResolvExpr/CurrentObject.cc
rae2c27a rc76bd34 594 594 class SimpleIterator final : public MemberIterator { 595 595 CodeLocation location; 596 readonly< Type >type = nullptr;596 const Type * type = nullptr; 597 597 public: 598 598 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {} … … 630 630 class ArrayIterator final : public MemberIterator { 631 631 CodeLocation location; 632 readonly< ArrayType >array = nullptr;633 readonly< Type >base = nullptr;632 const ArrayType * array = nullptr; 633 const Type * base = nullptr; 634 634 size_t index = 0; 635 635 size_t size = 0; … … 923 923 924 924 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) { 925 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {925 if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) { 926 926 if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) { 927 927 return new StructIterator{ loc, sit }; … … 932 932 dynamic_cast< const EnumInstType * >( type ) 933 933 || dynamic_cast< const TypeInstType * >( type ), 934 "Encountered unhandled ReferenceToType in createMemberIterator: %s",934 "Encountered unhandled BaseInstType in createMemberIterator: %s", 935 935 toString( type ).c_str() ); 936 936 return new SimpleIterator{ loc, type }; … … 965 965 DesignatorChain & d = *dit; 966 966 PRINT( std::cerr << "____actual: " << t << std::endl; ) 967 if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {967 if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) { 968 968 // concatenate identical field names 969 969 for ( const Decl * mem : refType->lookup( nexpr->name ) ) { -
src/ResolvExpr/Resolver.cc
rae2c27a rc76bd34 38 38 #include "Common/PassVisitor.h" // for PassVisitor 39 39 #include "Common/SemanticError.h" // for SemanticError 40 #include "Common/Stats/ResolveTime.h" // for ResolveTime::start(), ResolveTime::stop() 40 41 #include "Common/utility.h" // for ValueGuard, group_iterate 41 42 #include "InitTweak/GenInit.h" … … 965 966 /// Finds deleted expressions in an expression tree 966 967 struct DeleteFinder_new final : public ast::WithShortCircuiting { 967 const ast::DeletedExpr * delExpr= nullptr;968 const ast::DeletedExpr * result = nullptr; 968 969 969 970 void previsit( const ast::DeletedExpr * expr ) { 970 if ( delExpr) { visit_children = false; }971 else { delExpr= expr; }971 if ( result ) { visit_children = false; } 972 else { result = expr; } 972 973 } 973 974 974 975 void previsit( const ast::Expr * ) { 975 if ( delExpr) { visit_children = false; }976 if ( result ) { visit_children = false; } 976 977 } 977 978 }; … … 980 981 /// Check if this expression is or includes a deleted expression 981 982 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 982 ast::Pass<DeleteFinder_new> finder; 983 expr->accept( finder ); 984 return finder.core.delExpr; 983 return ast::Pass<DeleteFinder_new>::read( expr ); 985 984 } 986 985 … … 1171 1170 const ast::Expr * untyped, const ast::SymbolTable & symtab 1172 1171 ) { 1173 return findKindExpression( untyped, symtab ); 1172 Stats::ResolveTime::start( untyped ); 1173 auto res = findKindExpression( untyped, symtab ); 1174 Stats::ResolveTime::stop(); 1175 return res; 1174 1176 } 1175 1177 } // anonymous namespace … … 1221 1223 template<typename Iter> 1222 1224 inline bool nextMutex( Iter & it, const Iter & end ) { 1223 while ( it != end && ! (*it)-> get_type()->is_mutex() ) { ++it; }1225 while ( it != end && ! (*it)->is_mutex() ) { ++it; } 1224 1226 return it != end; 1225 1227 } … … 1261 1263 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 1262 1264 const ast::CatchStmt * previsit( const ast::CatchStmt * ); 1265 const ast::CatchStmt * postvisit( const ast::CatchStmt * ); 1263 1266 const ast::WaitForStmt * previsit( const ast::WaitForStmt * ); 1264 1267 … … 1493 1496 1494 1497 const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) { 1495 // TODO: This will need a fix for the decl/cond scoping problem. 1498 // Until we are very sure this invarent (ifs that move between passes have thenPart) 1499 // holds, check it. This allows a check for when to decode the mangling. 1500 if ( auto ifStmt = catchStmt->body.as<ast::IfStmt>() ) { 1501 assert( ifStmt->thenPart ); 1502 } 1503 // Encode the catchStmt so the condition can see the declaration. 1496 1504 if ( catchStmt->cond ) { 1497 ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool }; 1498 catchStmt = ast::mutate_field( 1499 catchStmt, &ast::CatchStmt::cond, 1500 findSingleExpression( catchStmt->cond, boolType, symtab ) ); 1505 ast::CatchStmt * stmt = mutate( catchStmt ); 1506 stmt->body = new ast::IfStmt( stmt->location, stmt->cond, nullptr, stmt->body ); 1507 stmt->cond = nullptr; 1508 return stmt; 1509 } 1510 return catchStmt; 1511 } 1512 1513 const ast::CatchStmt * Resolver_new::postvisit( const ast::CatchStmt * catchStmt ) { 1514 // Decode the catchStmt so everything is stored properly. 1515 const ast::IfStmt * ifStmt = catchStmt->body.as<ast::IfStmt>(); 1516 if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) { 1517 assert( ifStmt->cond ); 1518 assert( ifStmt->elsePart ); 1519 ast::CatchStmt * stmt = ast::mutate( catchStmt ); 1520 stmt->cond = ifStmt->cond; 1521 stmt->body = ifStmt->elsePart; 1522 // ifStmt should be implicately deleted here. 1523 return stmt; 1501 1524 } 1502 1525 return catchStmt; … … 1615 1638 // Check if the argument matches the parameter type in the current 1616 1639 // scope 1617 ast::ptr< ast::Type > paramType = (*param)->get_type();1640 // ast::ptr< ast::Type > paramType = (*param)->get_type(); 1618 1641 if ( 1619 1642 ! unify( 1620 arg->expr->result, paramType, resultEnv, need, have, open,1643 arg->expr->result, *param, resultEnv, need, have, open, 1621 1644 symtab ) 1622 1645 ) { … … 1625 1648 ss << "candidate function not viable: no known conversion " 1626 1649 "from '"; 1627 ast::print( ss, (*param)->get_type());1650 ast::print( ss, *param ); 1628 1651 ss << "' to '"; 1629 1652 ast::print( ss, arg->expr->result ); -
src/ResolvExpr/SatisfyAssertions.cpp
rae2c27a rc76bd34 318 318 if ( ! func ) continue; 319 319 320 for ( const a st::DeclWithType *param : func->params ) {321 cost.decSpec( specCost( param ->get_type()) );320 for ( const auto & param : func->params ) { 321 cost.decSpec( specCost( param ) ); 322 322 } 323 323 -
src/ResolvExpr/SpecCost.cc
rae2c27a rc76bd34 178 178 void previsit( const ast::FunctionType * fty ) { 179 179 int minCount = std::numeric_limits<int>::max(); 180 updateMinimumPresent( minCount, fty->params, decl_type);181 updateMinimumPresent( minCount, fty->returns, decl_type);180 updateMinimumPresent( minCount, fty->params, type_deref ); 181 updateMinimumPresent( minCount, fty->returns, type_deref ); 182 182 // Add another level to minCount if set. 183 183 count = toNoneOrInc( minCount ); -
src/ResolvExpr/Unify.cc
rae2c27a rc76bd34 395 395 396 396 template< typename Iterator1, typename Iterator2 > 397 bool unify DeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {397 bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 398 398 auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); }; 399 399 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { … … 489 489 || flatOther->isTtype() 490 490 ) { 491 if ( unify DeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {492 if ( unify DeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {491 if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 492 if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 493 493 494 494 // the original types must be used in mark assertions, since pointer comparisons are used … … 784 784 785 785 /// returns flattened version of `src` 786 static std::vector< ast::ptr< ast:: DeclWithType > > flattenList(787 const std::vector< ast::ptr< ast:: DeclWithType > > & src, ast::TypeEnvironment & env786 static std::vector< ast::ptr< ast::Type > > flattenList( 787 const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env 788 788 ) { 789 std::vector< ast::ptr< ast:: DeclWithType > > dst;789 std::vector< ast::ptr< ast::Type > > dst; 790 790 dst.reserve( src.size() ); 791 for ( const a st::DeclWithType *d : src ) {791 for ( const auto & d : src ) { 792 792 ast::Pass<TtypeExpander_new> expander{ env }; 793 793 // TtypeExpander pass is impure (may mutate nodes in place) 794 794 // need to make nodes shared to prevent accidental mutation 795 ast::ptr<ast:: DeclWithType> dc = d->accept(expander);796 auto types = flatten( dc ->get_type());795 ast::ptr<ast::Type> dc = d->accept(expander); 796 auto types = flatten( dc ); 797 797 for ( ast::ptr< ast::Type > & t : types ) { 798 798 // outermost const, volatile, _Atomic qualifiers in parameters should not play … … 803 803 // requirements than a non-mutex function 804 804 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 805 dst.emplace_back( new ast::ObjectDecl{ dc->location, "", t });805 dst.emplace_back( t ); 806 806 } 807 807 } … … 811 811 /// Creates a tuple type based on a list of DeclWithType 812 812 template< typename Iter > 813 static ast::ptr< ast::Type > tupleFrom Decls( Iter crnt, Iter end ) {813 static ast::ptr< ast::Type > tupleFromTypes( Iter crnt, Iter end ) { 814 814 std::vector< ast::ptr< ast::Type > > types; 815 815 while ( crnt != end ) { 816 816 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 817 817 // that this results in a flat tuple 818 flatten( (*crnt)->get_type(), types );818 flatten( *crnt, types ); 819 819 820 820 ++crnt; … … 825 825 826 826 template< typename Iter > 827 static bool unify DeclList(827 static bool unifyTypeList( 828 828 Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env, 829 829 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, … … 831 831 ) { 832 832 while ( crnt1 != end1 && crnt2 != end2 ) { 833 const ast::Type * t1 = (*crnt1)->get_type();834 const ast::Type * t2 = (*crnt2)->get_type();833 const ast::Type * t1 = *crnt1; 834 const ast::Type * t2 = *crnt2; 835 835 bool isTuple1 = Tuples::isTtype( t1 ); 836 836 bool isTuple2 = Tuples::isTtype( t2 ); … … 840 840 // combine remainder of list2, then unify 841 841 return unifyExact( 842 t1, tupleFrom Decls( crnt2, end2 ), env, need, have, open,842 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open, 843 843 noWiden(), symtab ); 844 844 } else if ( ! isTuple1 && isTuple2 ) { 845 845 // combine remainder of list1, then unify 846 846 return unifyExact( 847 tupleFrom Decls( crnt1, end1 ), t2, env, need, have, open,847 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open, 848 848 noWiden(), symtab ); 849 849 } … … 860 860 if ( crnt1 != end1 ) { 861 861 // try unifying empty tuple with ttype 862 const ast::Type * t1 = (*crnt1)->get_type();862 const ast::Type * t1 = *crnt1; 863 863 if ( ! Tuples::isTtype( t1 ) ) return false; 864 864 return unifyExact( 865 t1, tupleFrom Decls( crnt2, end2 ), env, need, have, open,865 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open, 866 866 noWiden(), symtab ); 867 867 } else if ( crnt2 != end2 ) { 868 868 // try unifying empty tuple with ttype 869 const ast::Type * t2 = (*crnt2)->get_type();869 const ast::Type * t2 = *crnt2; 870 870 if ( ! Tuples::isTtype( t2 ) ) return false; 871 871 return unifyExact( 872 tupleFrom Decls( crnt1, end1 ), t2, env, need, have, open,872 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open, 873 873 noWiden(), symtab ); 874 874 } … … 877 877 } 878 878 879 static bool unify DeclList(880 const std::vector< ast::ptr< ast:: DeclWithType > > & list1,881 const std::vector< ast::ptr< ast:: DeclWithType > > & list2,879 static bool unifyTypeList( 880 const std::vector< ast::ptr< ast::Type > > & list1, 881 const std::vector< ast::ptr< ast::Type > > & list2, 882 882 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 883 883 const ast::OpenVarSet & open, const ast::SymbolTable & symtab 884 884 ) { 885 return unify DeclList(885 return unifyTypeList( 886 886 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open, 887 887 symtab ); … … 928 928 ) return; 929 929 930 if ( ! unify DeclList( params, params2, tenv, need, have, open, symtab ) ) return;931 if ( ! unify DeclList(930 if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return; 931 if ( ! unifyTypeList( 932 932 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return; 933 933 … … 1232 1232 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) { 1233 1233 if ( func->returns.empty() ) return new ast::VoidType{}; 1234 if ( func->returns.size() == 1 ) return func->returns[0] ->get_type();1234 if ( func->returns.size() == 1 ) return func->returns[0]; 1235 1235 1236 1236 std::vector<ast::ptr<ast::Type>> tys; 1237 for ( const a st::DeclWithType *decl : func->returns ) {1238 tys.emplace_back( decl ->get_type());1237 for ( const auto & decl : func->returns ) { 1238 tys.emplace_back( decl ); 1239 1239 } 1240 1240 return new ast::TupleType{ std::move(tys) }; -
src/SymTab/Mangler.cc
rae2c27a rc76bd34 437 437 private: 438 438 void mangleDecl( const ast::DeclWithType *declaration ); 439 void mangleRef( const ast:: ReferenceToType *refType, std::string prefix );439 void mangleRef( const ast::BaseInstType *refType, std::string prefix ); 440 440 441 441 void printQualifiers( const ast::Type *type ); … … 551 551 GuardValue( inFunctionType ); 552 552 inFunctionType = true; 553 std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns ); 554 if (returnTypes.empty()) mangleName << Encoding::void_t; 555 else accept_each( returnTypes, *visitor ); 553 if (functionType->returns.empty()) mangleName << Encoding::void_t; 554 else accept_each( functionType->returns, *visitor ); 556 555 mangleName << "_"; 557 std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params ); 558 accept_each( paramTypes, *visitor ); 556 accept_each( functionType->params, *visitor ); 559 557 mangleName << "_"; 560 558 } 561 559 562 void Mangler_new::mangleRef( const ast:: ReferenceToType * refType, std::string prefix ) {560 void Mangler_new::mangleRef( const ast::BaseInstType * refType, std::string prefix ) { 563 561 printQualifiers( refType ); 564 562 -
src/SymTab/Validate.cc
rae2c27a rc76bd34 960 960 } 961 961 962 static bool isNonParameterAttribute( Attribute * attr ) { 963 static const std::vector<std::string> bad_names = { 964 "aligned", "__aligned__", 965 }; 966 for ( auto name : bad_names ) { 967 if ( name == attr->name ) { 968 return true; 969 } 970 } 971 return false; 972 } 973 962 974 Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) { 963 975 // instances of typedef types will come here. If it is an instance … … 968 980 ret->location = typeInst->location; 969 981 ret->get_qualifiers() |= typeInst->get_qualifiers(); 970 // attributes are not carried over from typedef to function parameters/return values 971 if ( ! inFunctionType ) { 972 ret->attributes.splice( ret->attributes.end(), typeInst->attributes ); 973 } else { 974 deleteAll( ret->attributes ); 975 ret->attributes.clear(); 976 } 982 // GCC ignores certain attributes if they arrive by typedef, this mimics that. 983 if ( inFunctionType ) { 984 ret->attributes.remove_if( isNonParameterAttribute ); 985 } 986 ret->attributes.splice( ret->attributes.end(), typeInst->attributes ); 977 987 // place instance parameters on the typedef'd type 978 988 if ( ! typeInst->parameters.empty() ) { … … 1374 1384 /// Replaces enum types by int, and function/array types in function parameter and return 1375 1385 /// lists by appropriate pointers 1386 /* 1376 1387 struct EnumAndPointerDecay_new { 1377 1388 const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) { … … 1424 1435 } 1425 1436 }; 1437 */ 1426 1438 1427 1439 /// expand assertions from a trait instance, performing appropriate type variable substitutions … … 1508 1520 } 1509 1521 1510 void checkGenericParameters( const ast:: ReferenceToType * inst ) {1522 void checkGenericParameters( const ast::BaseInstType * inst ) { 1511 1523 for ( const ast::Expr * param : inst->params ) { 1512 1524 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) { … … 1827 1839 const ast::Type * validateType( 1828 1840 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) { 1829 ast::Pass< EnumAndPointerDecay_new > epc;1841 // ast::Pass< EnumAndPointerDecay_new > epc; 1830 1842 ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab }; 1831 1843 ast::Pass< ForallPointerDecay_new > fpd{ loc }; 1832 1844 1833 return type->accept( epc )->accept(lrt )->accept( fpd );1845 return type->accept( lrt )->accept( fpd ); 1834 1846 } 1835 1847 -
src/Virtual/module.mk
rae2c27a rc76bd34 15 15 ############################################################################### 16 16 17 SRC += Virtual/ExpandCasts.cc Virtual/ExpandCasts.h 17 SRC += Virtual/ExpandCasts.cc Virtual/ExpandCasts.h \ 18 Virtual/Tables.cc Virtual/Tables.h 19 20 SRCDEMANGLE += Virtual/Tables.cc -
tests/.expect/array.txt
rae2c27a rc76bd34 1 array.cfa: In function '_X4mainFi___1': 2 array.cfa:55:9: note: #pragma message: Compiled -
tests/.expect/cast.txt
rae2c27a rc76bd34 1 cast.cfa: In function '_X4mainFi_iPPKc__1': 2 cast.cfa:18:9: note: #pragma message: Compiled -
tests/.expect/enum.txt
rae2c27a rc76bd34 1 done -
tests/.expect/expression.txt
rae2c27a rc76bd34 1 expression.cfa: In function '_X4mainFi___1': 2 expression.cfa:89:9: note: #pragma message: Compiled -
tests/.expect/forall.txt
rae2c27a rc76bd34 1 forall.cfa: In function '_X4mainFi___1': 2 forall.cfa:218:9: note: #pragma message: Compiled -
tests/.expect/heap.txt
rae2c27a rc76bd34 1 done -
tests/.expect/identFuncDeclarator.txt
rae2c27a rc76bd34 1 identFuncDeclarator.cfa: In function '_X4mainFi___1': 2 identFuncDeclarator.cfa:116:9: note: #pragma message: Compiled -
tests/.expect/identParamDeclarator.txt
rae2c27a rc76bd34 1 done -
tests/.expect/labelledExit.txt
rae2c27a rc76bd34 1 labelledExit.cfa: In function '_X4mainFi_iPPKc__1': 2 labelledExit.cfa:183:9: note: #pragma message: Compiled -
tests/.expect/limits.txt
rae2c27a rc76bd34 1 limits.cfa: In function '_X4mainFi_iPPKc__1': 2 limits.cfa:151:9: note: #pragma message: Compiled -
tests/.expect/maybe.txt
rae2c27a rc76bd34 1 done -
tests/.expect/nested-types.txt
rae2c27a rc76bd34 1 nested-types.cfa: In function '_X4mainFi___1': 2 nested-types.cfa:102:9: note: #pragma message: Compiled -
tests/.expect/numericConstants.txt
rae2c27a rc76bd34 1 numericConstants.cfa: In function '_X4mainFi___1': 2 numericConstants.cfa:68:9: note: #pragma message: Compiled -
tests/.expect/operators.txt
rae2c27a rc76bd34 1 done -
tests/.expect/result.txt
rae2c27a rc76bd34 1 done -
tests/.expect/stdincludes.txt
rae2c27a rc76bd34 1 stdincludes.cfa: In function '_X4mainFi___1': 2 stdincludes.cfa:52:9: note: #pragma message: Compiled -
tests/.expect/switch.txt
rae2c27a rc76bd34 1 switch.cfa: In function '_X4mainFi___1': 2 switch.cfa:105:9: note: #pragma message: Compiled -
tests/.expect/typedefRedef-ERR1.txt
rae2c27a rc76bd34 1 1 typedefRedef.cfa:4:1 error: Cannot redefine typedef: Foo 2 typedefRedef.cfa: 60:1 error: Cannot redefine typedef: ARR2 typedefRedef.cfa:59:1 error: Cannot redefine typedef: ARR -
tests/.expect/typedefRedef.txt
rae2c27a rc76bd34 1 typedefRedef.cfa: In function '_X4mainFi___1': 2 typedefRedef.cfa:71:9: note: #pragma message: Compiled -
tests/.expect/typeof.txt
rae2c27a rc76bd34 1 done -
tests/.expect/variableDeclarator.txt
rae2c27a rc76bd34 1 variableDeclarator.cfa: In function '_X4mainFi_iPPKc__1': 2 variableDeclarator.cfa:182:9: note: #pragma message: Compiled -
tests/.expect/voidPtr.txt
rae2c27a rc76bd34 1 done -
tests/Makefile.am
rae2c27a rc76bd34 11 11 ## Created On : Sun May 31 09:08:15 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Tue Nov 20 11:18:51 201814 ## Update Count : 6813 ## Last Modified On : Sun Sep 27 19:01:41 2020 14 ## Update Count : 84 15 15 ############################################################################### 16 16 … … 38 38 # since automake doesn't have support for CFA we have to 39 39 AM_CFLAGS = $(if $(test), 2> $(test), ) \ 40 -fdebug-prefix-map=$(abspath ${abs_srcdir})= \ 41 -fdebug-prefix-map=/tmp= \ 42 -fno-diagnostics-show-caret \ 40 43 -g \ 41 44 -Wall \ … … 50 53 51 54 # adjust CC to current flags 52 CC = $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})55 CC = LC_ALL=C $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS}) 53 56 CFACC = $(CC) 54 57 … … 58 61 # adjusted CC but without the actual distcc call 59 62 CFACCLOCAL = $(if $(DISTCC_CFA_PATH),$(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS}) 63 CFACCLINK = $(CFACCLOCAL) -quiet $(if $(test), 2> $(test), ) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) 60 64 61 65 PRETTY_PATH=mkdir -p $(dir $(abspath ${@})) && cd ${srcdir} && … … 110 114 % : %.cfa $(CFACCBIN) 111 115 $(CFACOMPILETEST) -c -o $(abspath ${@}).o 112 $(CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@}) 116 $(CFACCLINK) ${@}.o -o $(abspath ${@}) 117 rm $(abspath ${@}).o 113 118 114 119 # implicit rule for c++ test … … 129 134 $(CFACOMPILETEST) -CFA -XCFA -p -c -fsyntax-only -o $(abspath ${@}) 130 135 131 # Use for tests where the make command is expected to succeed but the expected.txt should be compared to stderr132 EXPECT_STDERR = builtins/sync warnings/self-assignment133 $(EXPECT_STDERR): % : %.cfa $(CFACCBIN)134 $(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@})135 136 136 #------------------------------------------------------------------------------ 137 137 # CUSTOM TARGET 138 138 #------------------------------------------------------------------------------ 139 # tests that just validate syntax and compiler output should be compared to stderr 140 CFACOMPILE_SYNTAX = $(CFACOMPILETEST) -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o $(abspath ${@}) 141 142 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator forall \ 143 limits nested-types stdincludes cast labelledExit array builtins/sync warnings/self-assignment 144 $(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN) 145 $(CFACOMPILE_SYNTAX) 146 $(if $(test), cp $(test) $(abspath ${@}), ) 147 139 148 # expected failures 140 # use custom target since they require a custom define and custom dependencies149 # use custom target since they require a custom define *and* have a name that doesn't match the file 141 150 alloc-ERROR : alloc.cfa $(CFACCBIN) 142 $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@}) 151 $(CFACOMPILE_SYNTAX) -DERR1 152 -cp $(test) $(abspath ${@}) 143 153 144 154 typedefRedef-ERR1 : typedefRedef.cfa $(CFACCBIN) 145 $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@}) 155 $(CFACOMPILE_SYNTAX) -DERR1 156 -cp $(test) $(abspath ${@}) 146 157 147 158 nested-types-ERR1 : nested-types.cfa $(CFACCBIN) 148 $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@}) 159 $(CFACOMPILE_SYNTAX) -DERR1 160 -cp $(test) $(abspath ${@}) 149 161 150 162 nested-types-ERR2 : nested-types.cfa $(CFACCBIN) 151 $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@}) 163 $(CFACOMPILE_SYNTAX) -DERR2 164 -cp $(test) $(abspath ${@}) 152 165 153 166 raii/memberCtors-ERR1 : raii/memberCtors.cfa $(CFACCBIN) 154 $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@}) 167 $(CFACOMPILE_SYNTAX) -DERR1 168 -cp $(test) $(abspath ${@}) 155 169 156 170 raii/ctor-autogen-ERR1 : raii/ctor-autogen.cfa $(CFACCBIN) 157 $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@}) 171 $(CFACOMPILE_SYNTAX) -DERR1 172 -cp $(test) $(abspath ${@}) 158 173 159 174 raii/dtor-early-exit-ERR1 : raii/dtor-early-exit.cfa $(CFACCBIN) 160 $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@}) 175 $(CFACOMPILE_SYNTAX) -DERR1 176 -cp $(test) $(abspath ${@}) 161 177 162 178 raii/dtor-early-exit-ERR2 : raii/dtor-early-exit.cfa $(CFACCBIN) 163 $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@}) 179 $(CFACOMPILE_SYNTAX) -DERR2 180 -cp $(test) $(abspath ${@}) 164 181 165 182 # Exception Tests … … 170 187 $(CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@}) 171 188 189 # Linking tests 190 # Meta tests to make sure we see linking errors (can't compile with -O2 since it may multiply number of calls) 191 linking/linkerror : linking/linkerror.cfa $(CFACCBIN) 192 $(CFACOMPILETEST) -O0 -c -o $(abspath ${@}).o 193 $(CFACCLINK) -O0 ${@}.o -o $(abspath ${@}) 194 rm $(abspath ${@}).o 195 172 196 #------------------------------------------------------------------------------ 173 197 # Other targets -
tests/alloc2.cfa
rae2c27a rc76bd34 13 13 void test_base( void * ip, size_t size, size_t align) { 14 14 tests_total += 1; 15 // printf("DEBUG: starting test %d\n", tests_total); 15 16 bool passed = (malloc_size(ip) == size) && (malloc_usable_size(ip) >= size) && (malloc_alignment(ip) == align) && ((uintptr_t)ip % align == 0); 16 17 if (!passed) { … … 18 19 tests_failed += 1; 19 20 } 21 // printf("DEBUG: done test %d\n", tests_total); 20 22 } 21 23 22 24 void test_fill( void * ip_, size_t start, size_t end, char fill) { 23 25 tests_total += 1; 26 // printf("DEBUG: starting test %d\n", tests_total); 24 27 bool passed = true; 25 28 char * ip = (char *) ip_; … … 29 32 tests_failed += 1; 30 33 } 34 // printf("DEBUG: done test %d\n", tests_total); 31 35 } 32 36 33 37 void test_fill( void * ip_, size_t start, size_t end, int fill) { 34 38 tests_total += 1; 39 // printf("DEBUG: starting test %d\n", tests_total); 35 40 bool passed = true; 36 41 int * ip = (int *) ip_; … … 40 45 tests_failed += 1; 41 46 } 47 // printf("DEBUG: done test %d\n", tests_total); 42 48 } 43 49 44 50 void test_fill( void * ip_, size_t start, size_t end, int * fill) { 45 51 tests_total += 1; 52 // printf("DEBUG: starting test %d\n", tests_total); 46 53 bool passed = (memcmp((void*)((uintptr_t)ip_ + start), (void*)fill, end) == 0); 47 54 if (!passed) { … … 49 56 tests_failed += 1; 50 57 } 58 // printf("DEBUG: done test %d\n", tests_total); 51 59 } 52 60 53 61 void test_fill( void * ip_, size_t start, size_t end, T1 fill) { 54 62 tests_total += 1; 63 // printf("DEBUG: starting test %d\n", tests_total); 55 64 bool passed = true; 56 65 T1 * ip = (T1 *) ip_; … … 60 69 tests_failed += 1; 61 70 } 71 // printf("DEBUG: done test %d\n", tests_total); 62 72 } 63 73 64 74 void test_fill( void * ip_, size_t start, size_t end, T1 * fill) { 65 75 tests_total += 1; 76 // printf("DEBUG: starting test %d\n", tests_total); 66 77 bool passed = (memcmp((void*)((uintptr_t)ip_ + start), (void*)fill, end) == 0); 67 78 if (!passed) { … … 69 80 tests_failed += 1; 70 81 } 82 // printf("DEBUG: done test %d\n", tests_total); 71 83 } 72 84 73 85 void test_use( int * ip, size_t dim) { 74 86 tests_total += 1; 87 // printf("DEBUG: starting test %d\n", tests_total); 75 88 bool passed = true; 76 89 for (i; 0 ~ dim) ip[i] = 0xdeadbeef; … … 80 93 tests_failed += 1; 81 94 } 95 // printf("DEBUG: done test %d\n", tests_total); 82 96 } 83 97 84 98 void test_use( T1 * ip, size_t dim) { 85 99 tests_total += 1; 100 // printf("DEBUG: starting test %d\n", tests_total); 86 101 bool passed = true; 87 102 for (i; 0 ~ dim) ip[i].data = 0xdeadbeef; … … 91 106 tests_failed += 1; 92 107 } 108 // printf("DEBUG: done test %d\n", tests_total); 93 109 } 94 110 -
tests/array.cfa
rae2c27a rc76bd34 1 // -*- Mode: C -*- 2 // 1 // -*- Mode: C -*- 2 // 3 3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo 4 4 // 5 5 // The contents of this file are covered under the licence agreement in the 6 6 // file "LICENCE" distributed with Cforall. 7 // 7 // 8 8 // array.cfa -- test array declarations 9 // 9 // 10 10 // Author : Peter A. Buhr 11 11 // Created On : Tue Feb 19 21:18:06 2019 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Tue Feb 19 21:18:46 201914 // Update Count : 115 // 13 // Last Modified On : Sun Sep 27 09:05:40 2020 14 // Update Count : 4 15 // 16 16 17 int a1[ ];17 int a1[0]; 18 18 //int a2[*]; 19 19 //double a4[3.0]; 20 20 21 int m1[ ][3];21 int m1[0][3]; 22 22 //int m2[*][*]; 23 23 int m4[3][3]; … … 49 49 } 50 50 51 int main() {} 51 int main() { 52 #if !defined(NO_COMPILED_PRAGMA) 53 #pragma message( "Compiled" ) // force non-empty .expect file 54 #endif 55 } 52 56 53 57 // Local Variables: // -
tests/builtins/.expect/sync.txt
rae2c27a rc76bd34 1 builtins/sync.cfa: In function '_X4mainFi___1': 2 builtins/sync.cfa:358:9: note: #pragma message: Compiled -
tests/builtins/sync.cfa
rae2c27a rc76bd34 66 66 #if defined(__SIZEOF_INT128__) 67 67 { __int128 ret; ret = __sync_fetch_and_nand(vplll, vlll); } 68 { __int128 ret; ret = __sync_fetch_and_nand_16(vplll, vlll); }69 68 #endif 70 69 … … 355 354 356 355 int main() { 357 return 0;356 #pragma message( "Compiled" ) // force non-empty .expect file 358 357 } -
tests/cast.cfa
rae2c27a rc76bd34 13 13 14 14 //Dummy main 15 int main(int argc, char const *argv[]) 16 { 17 return 0; 15 int main( int argc, char const * argv[] ) { 16 #pragma message( "Compiled" ) // force non-empty .expect file 18 17 } -
tests/concurrent/.expect/cluster.txt
rae2c27a rc76bd34 1 done -
tests/concurrent/cluster.cfa
rae2c27a rc76bd34 32 32 } 33 33 } 34 return 0;34 printf( "done\n" ); // non-empty .expect file 35 35 } -
tests/concurrent/examples/.expect/datingService.txt
rae2c27a rc76bd34 1 done -
tests/concurrent/examples/datingService.cfa
rae2c27a rc76bd34 10 10 // Created On : Mon Oct 30 12:56:20 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jun 21 11:32:34 201913 // Update Count : 3812 // Last Modified On : Sun Sep 27 15:42:25 2020 13 // Update Count : 40 14 14 // 15 15 … … 108 108 if ( girlck[ boyck[i] ] != boyck[ girlck[i] ] ) abort(); 109 109 } // for 110 111 printf( "done\n" ); // non-empty .expect file 110 112 } // main 111 113 -
tests/concurrent/futures/.expect/basic.txt
rae2c27a rc76bd34 1 done -
tests/concurrent/futures/basic.cfa
rae2c27a rc76bd34 91 91 } 92 92 } 93 printf( "done\n" ); // non-empty .expect file 94 93 95 } -
tests/concurrent/park/.expect/force_preempt.txt
rae2c27a rc76bd34 1 done -
tests/concurrent/park/.expect/start_parked.txt
rae2c27a rc76bd34 1 done -
tests/concurrent/park/contention.cfa
rae2c27a rc76bd34 21 21 if(blocked[idx]) { 22 22 Thread * thrd = __atomic_exchange_n(&blocked[idx], 0p, __ATOMIC_SEQ_CST); 23 unpark( *thrd __cfaabi_dbg_ctx2);23 unpark( *thrd ); 24 24 } else { 25 25 Thread * thrd = __atomic_exchange_n(&blocked[idx], &this, __ATOMIC_SEQ_CST); 26 unpark( *thrd __cfaabi_dbg_ctx2);27 park( __cfaabi_dbg_ctx);26 unpark( *thrd ); 27 park(); 28 28 } 29 29 } … … 41 41 int idx = myrand() % blocked_size; 42 42 Thread * thrd = __atomic_exchange_n(&blocked[idx], 0p, __ATOMIC_SEQ_CST); 43 unpark( *thrd __cfaabi_dbg_ctx2);43 unpark( *thrd ); 44 44 yield( myrand() % 20 ); 45 45 } -
tests/concurrent/park/force_preempt.cfa
rae2c27a rc76bd34 30 30 31 31 // Unpark this thread, don't force a yield 32 unpark( this __cfaabi_dbg_ctx2);32 unpark( this ); 33 33 assert(mask == 0xCAFEBABA); 34 34 … … 43 43 // Park this thread, 44 44 assert(mask == (id_hash ^ 0xCAFEBABA)); 45 park( __cfaabi_dbg_ctx);45 park(); 46 46 assert(mask == (id_hash ^ 0xCAFEBABA)); 47 47 … … 57 57 Waiter waiters[5]; 58 58 } 59 printf( "done\n" ); // non-empty .expect file 59 60 } -
tests/concurrent/park/start_parked.cfa
rae2c27a rc76bd34 3 3 thread Parker {}; 4 4 void main( Parker & ) { 5 park( __cfaabi_dbg_ctx);5 park(); 6 6 } 7 7 8 8 int main() { 9 for(1000) { 10 Parker parker; 11 unpark( parker __cfaabi_dbg_ctx2 ); 12 } 9 for(1000) { 10 Parker parker; 11 unpark( parker ); 12 } 13 printf( "done\n" ); // non-empty .expect file 13 14 } -
tests/enum.cfa
rae2c27a rc76bd34 26 26 //Dummy main 27 27 int main(int argc, char const *argv[]) { 28 printf( "done\n" ); // non-empty .expect file 28 29 } -
tests/exceptions/.expect/virtual-cast.txt
rae2c27a rc76bd34 1 done -
tests/exceptions/.expect/virtual-poly.txt
rae2c27a rc76bd34 1 done -
tests/exceptions/virtual-cast.cfa
rae2c27a rc76bd34 74 74 free(tri); 75 75 free(top); 76 printf( "done\n" ); // non-empty .expect file 76 77 } -
tests/exceptions/virtual-poly.cfa
rae2c27a rc76bd34 77 77 mono_poly_test(); 78 78 poly_poly_test(); 79 printf( "done\n" ); // non-empty .expect file 79 80 } -
tests/expression.cfa
rae2c27a rc76bd34 8 8 9 9 int main() { 10 int a[3] = { 0, 0, 0 };11 S s = { 3 }, * ps = &s;12 [int] t = { 3 };13 * [int] pt = &t;14 int i = 1, j = 2;10 int a[3] = { 0, 0, 0 }; 11 S s = { 3 }, * ps = &s; 12 [int] t = { 3 }; 13 * [int] pt = &t; 14 int i = 1, j = 2; 15 15 16 // operators16 // operators 17 17 18 !i;19 ~i;20 +i;21 -i;22 *ps;23 ++ps;24 --ps;25 ps++;26 ps--;18 !i; 19 ~i; 20 +i; 21 -i; 22 *ps; 23 ++ps; 24 --ps; 25 ps++; 26 ps--; 27 27 28 i + j;29 i - j;30 i * j;28 i + j; 29 i - j; 30 i * j; 31 31 32 i / j;33 i % j;34 i ^ j;35 i & j;36 i | j;37 i < j;38 i > j;39 i = j;32 i / j; 33 i % j; 34 i ^ j; 35 i & j; 36 i | j; 37 i < j; 38 i > j; 39 i = j; 40 40 41 i == j;42 i != j;43 i << j;44 i >> j;45 i <= j;46 i >= j;47 i && j;48 i || j;49 ps->i;41 i == j; 42 i != j; 43 i << j; 44 i >> j; 45 i <= j; 46 i >= j; 47 i && j; 48 i || j; 49 ps->i; 50 50 51 i *= j;52 i /= j;53 i %= j;54 i += j;55 i -= j;56 i &= j;57 i |= j;58 i ^= j;59 i <<= j;60 i >>= j;51 i *= j; 52 i /= j; 53 i %= j; 54 i += j; 55 i -= j; 56 i &= j; 57 i |= j; 58 i ^= j; 59 i <<= j; 60 i >>= j; 61 61 62 i ? i : j;62 i ? i : j; 63 63 64 // postfix function call64 // postfix function call 65 65 66 (3 + 4)`mary; 67 ({3 + 4;})`mary; 68 [3, 4]`mary; 69 3`mary; 70 a[0]`mary; 71 a[0]`mary`mary; 72 s{0}`mary; 73 a[3]`jane++; 74 jack(3)`mary; 75 s.i`mary; 76 t.0`mary; 77 s.[i]`mary; 78 ps->i`mary; 79 pt->0`mary; 80 ps->[i]`mary; 81 i++`mary; 82 i--`mary; 83 (S){2}`mary; 84 (S)@{2}`mary; 66 (3 + 4)`mary; 67 ({3 + 4;})`mary; 68 [3, 4]`mary; 69 3`mary; 70 a[0]`mary; 71 a[0]`mary`mary; 72 s{0}`mary; 73 a[3]`jane++; 74 jack(3)`mary; 75 s.i`mary; 76 t.0`mary; 77 s.[i]`mary; 78 ps->i`mary; 79 pt->0`mary; 80 ps->[i]`mary; 81 i++`mary; 82 i--`mary; 83 (S){2}`mary; 84 (S)@{2}`mary; 85 86 #if !defined(NO_COMPILED_PRAGMA) 87 #pragma message( "Compiled" ) // force non-empty .expect file 88 #endif 85 89 } // main -
tests/forall.cfa
rae2c27a rc76bd34 10 10 // Created On : Wed May 9 08:48:15 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Mar 19 08:29:38 201913 // Update Count : 3 212 // Last Modified On : Sun Sep 27 08:43:20 2020 13 // Update Count : 35 14 14 // 15 15 … … 158 158 } 159 159 forall( otype T ) inline static { 160 int RT9( T ) { T t; }160 int RT9( T ) { T t; return 3; } 161 161 } 162 162 … … 213 213 // w3 g3; 214 214 215 int main( void ) {} 215 int main( void ) { 216 #pragma message( "Compiled" ) // force non-empty .expect file 217 } 216 218 217 219 // Local Variables: // -
tests/heap.cfa
rae2c27a rc76bd34 10 10 // Created On : Tue Nov 6 17:54:56 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Aug 9 08:05:16202013 // Update Count : 5712 // Last Modified On : Fri Sep 25 15:21:52 2020 13 // Update Count : 73 14 14 // 15 15 … … 205 205 free( area ); 206 206 } // for 207 } // for 208 209 // check malloc/resize/free (sbrk) 210 211 for ( i; 2 ~ NoOfAllocs ~ 12 ) { 212 // initial N byte allocation 213 char * area = (char *)malloc( i ); 214 area[0] = '\345'; area[i - 1] = '\345'; // fill first/penultimate byte 215 216 // Do not start this loop index at 0 because resize of 0 bytes frees the storage. 217 int prev = i; 218 for ( s; i ~ 256 * 1024 ~ 26 ) { // start at initial memory request 219 if ( area[0] != '\345' || area[prev - 1] != '\345' ) abort( "malloc/resize/free corrupt storage" ); 220 area = (char *)resize( area, s ); // attempt to reuse storage 221 area[0] = area[s - 1] = '\345'; // fill last byte 222 prev = s; 223 } // for 224 free( area ); 225 } // for 226 227 // check malloc/resize/free (mmap) 228 229 for ( i; 2 ~ NoOfAllocs ~ 12 ) { 230 // initial N byte allocation 231 size_t s = i + default_mmap_start(); // cross over point 232 char * area = (char *)malloc( s ); 233 area[0] = '\345'; area[s - 1] = '\345'; // fill first/penultimate byte 234 235 // Do not start this loop index at 0 because resize of 0 bytes frees the storage. 236 int prev = s; 237 for ( r; s ~ 256 * 1024 ~ 26 ) { // start at initial memory request 238 if ( area[0] != '\345' || area[prev - 1] != '\345' ) abort( "malloc/resize/free corrupt storage" ); 239 area = (char *)resize( area, s ); // attempt to reuse storage 240 area[0] = area[r - 1] = '\345'; // fill last byte 241 prev = r; 242 } // for 243 free( area ); 244 } // for 245 246 // check malloc/realloc/free (sbrk) 247 248 for ( i; 2 ~ NoOfAllocs ~ 12 ) { 249 // initial N byte allocation 250 char * area = (char *)malloc( i ); 251 area[0] = '\345'; area[i - 1] = '\345'; // fill first/penultimate byte 252 253 // Do not start this loop index at 0 because realloc of 0 bytes frees the storage. 254 int prev = i; 255 for ( s; i ~ 256 * 1024 ~ 26 ) { // start at initial memory request 256 if ( area[0] != '\345' || area[prev - 1] != '\345' ) abort( "malloc/realloc/free corrupt storage" ); 257 area = (char *)realloc( area, s ); // attempt to reuse storage 258 area[s - 1] = '\345'; // fill last byte 259 prev = s; 260 } // for 261 free( area ); 262 } // for 263 264 // check malloc/realloc/free (mmap) 265 266 for ( i; 2 ~ NoOfAllocs ~ 12 ) { 267 // initial N byte allocation 268 size_t s = i + default_mmap_start(); // cross over point 269 char * area = (char *)malloc( s ); 270 area[0] = '\345'; area[s - 1] = '\345'; // fill first/penultimate byte 271 272 // Do not start this loop index at 0 because realloc of 0 bytes frees the storage. 273 int prev = s; 274 for ( r; s ~ 256 * 1024 ~ 26 ) { // start at initial memory request 275 if ( area[0] != '\345' || area[prev - 1] != '\345' ) abort( "malloc/realloc/free corrupt storage" ); 276 area = (char *)realloc( area, s ); // attempt to reuse storage 277 area[r - 1] = '\345'; // fill last byte 278 prev = r; 279 } // for 280 free( area ); 207 281 } // for 208 282 … … 320 394 } // for 321 395 396 // check memalign/resize with align/free 397 398 amount = 2; 399 for ( a; libAlign() ~= limit ~ a ) { // generate powers of 2 400 // initial N byte allocation 401 char * area = (char *)memalign( a, amount ); // aligned N-byte allocation 402 //sout | alignments[a] | area | endl; 403 if ( (size_t)area % a != 0 || malloc_alignment( area ) != a ) { // check for initial alignment 404 abort( "memalign/resize with align/free bad alignment : memalign(%d,%d) = %p", (int)a, (int)amount, area ); 405 } // if 406 area[0] = '\345'; area[amount - 2] = '\345'; // fill first/penultimate byte 407 408 // Do not start this loop index at 0 because resize of 0 bytes frees the storage. 409 for ( s; amount ~ 256 * 1024 ) { // start at initial memory request 410 area = (char *)resize( area, a * 2, s ); // attempt to reuse storage 411 //sout | i | area | endl; 412 if ( (size_t)area % a * 2 != 0 ) { // check for initial alignment 413 abort( "memalign/resize with align/free bad alignment %p", area ); 414 } // if 415 area[s - 1] = '\345'; // fill last byte 416 } // for 417 free( area ); 418 } // for 419 322 420 // check memalign/realloc with align/free 323 421 … … 387 485 // checkFreeOn(); 388 486 // malloc_stats(); 487 printf( "done\n" ); // non-empty .expect file 389 488 } 390 489 -
tests/identFuncDeclarator.cfa
rae2c27a rc76bd34 10 10 // Created On : Wed Aug 17 08:36:34 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Nov 6 17:56:33 201813 // Update Count : 312 // Last Modified On : Sun Sep 27 08:20:46 2020 13 // Update Count : 5 14 14 // 15 15 … … 111 111 int (* (* const f80)(int))(); 112 112 int (* const(* const f81)(int))(); 113 114 #pragma message( "Compiled" ) // force non-empty .expect file 113 115 } 114 116 -
tests/identParamDeclarator.cfa
rae2c27a rc76bd34 10 10 // Created On : Wed Aug 17 08:37:56 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Nov 6 17:56:44 201813 // Update Count : 312 // Last Modified On : Fri Sep 25 14:31:08 2020 13 // Update Count : 4 14 14 // 15 15 … … 158 158 159 159 int main( int argc, char const *argv[] ) { // dummy main 160 return 0;160 printf( "done\n" ); // non-empty .expect file 161 161 } 162 162 -
tests/labelledExit.cfa
rae2c27a rc76bd34 10 10 // Created On : Wed Aug 10 07:29:39 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 5 16:49:48202013 // Update Count : 912 // Last Modified On : Sun Sep 27 09:01:34 2020 13 // Update Count : 12 14 14 // 15 15 … … 179 179 180 180 int main( int argc, char const *argv[] ) { 181 /* code */181 #pragma message( "Compiled" ) // force non-empty .expect file 182 182 } 183 183 -
tests/limits.cfa
rae2c27a rc76bd34 10 10 // Created On : Tue May 10 20:44:20 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Nov 6 17:57:55 201813 // Update Count : 812 // Last Modified On : Sun Sep 27 08:45:43 2020 13 // Update Count : 10 14 14 // 15 15 … … 147 147 148 148 int main(int argc, char const *argv[]) { 149 //DUMMY 150 return 0; 149 #pragma message( "Compiled" ) // force non-empty .expect file 151 150 } 152 151 -
tests/maybe.cfa
rae2c27a rc76bd34 10 10 // Created On : Thr May 25 16:02:00 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jul 20 15:24:07 201713 // Update Count : 112 // Last Modified On : Fri Sep 25 15:13:28 2020 13 // Update Count : 2 14 14 // 15 15 … … 65 65 //checkNamedConstructors(); 66 66 checkSetters(); 67 printf( "done\n" ); // non-empty .expect file 67 68 } -
tests/nested-types.cfa
rae2c27a rc76bd34 10 10 // Created On : Mon Jul 9 10:20:03 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 12 18:21:15202013 // Update Count : 312 // Last Modified On : Sun Sep 27 08:48:59 2020 13 // Update Count : 6 14 14 // 15 15 16 16 typedef int N; 17 17 struct A { 18 forall(otype T)19 struct N {20 T x;21 };18 forall(otype T) 19 struct N { 20 T x; 21 }; 22 22 }; 23 23 24 24 struct S { 25 struct T {26 int i;27 typedef int Bar;28 };29 T x;25 struct T { 26 int i; 27 typedef int Bar; 28 }; 29 T x; 30 30 31 // struct U;32 typedef T Bar;33 typedef int Baz;31 // struct U; 32 typedef T Bar; 33 typedef int Baz; 34 34 }; 35 35 … … 65 65 66 66 int main() { 67 // access nested struct68 S.T x;67 // access nested struct 68 S.T x; 69 69 70 {71 struct S {72 int i;73 struct Z {74 double d;75 };76 };70 { 71 struct S { 72 int i; 73 struct Z { 74 double d; 75 }; 76 }; 77 77 78 S.Z z;// gets local S79 .S.T y;// lookup at global scope only78 S.Z z; // gets local S 79 .S.T y; // lookup at global scope only 80 80 81 const volatile .S.T q;81 const volatile .S.T q; 82 82 #if ERR1 83 T err1;// error: no T in scope83 T err1; // error: no T in scope 84 84 #endif 85 85 #if ERR2 86 .Z err2;// error: no Z in global scope87 .S.Baz.Bar err3;// error: .S.Baz => int, int is not aggregate and should not appear left of the dot88 .S.Z err4;// error: no Z in global S86 .Z err2; // error: no Z in global scope 87 .S.Baz.Bar err3; // error: .S.Baz => int, int is not aggregate and should not appear left of the dot 88 .S.Z err4; // error: no Z in global S 89 89 #endif 90 }90 } 91 91 92 // U.S un;92 // U.S un; 93 93 94 S.Bar y;95 S.Baz x;96 S.T.Bar z;94 S.Bar y; 95 S.Baz x; 96 S.T.Bar z; 97 97 98 // A.N(int) x; // xxx - should not be an error, but currently is. 98 // A.N(int) x; // xxx - should not be an error, but currently is. 99 100 #pragma message( "Compiled" ) // force non-empty .expect file 99 101 } 100 102 -
tests/numericConstants.cfa
rae2c27a rc76bd34 10 10 // Created On : Wed May 24 22:10:36 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 5 08:58:16 201913 // Update Count : 512 // Last Modified On : Sun Sep 27 07:55:22 2020 13 // Update Count : 7 14 14 // 15 15 … … 63 63 0x_ff.ffp0; // hex real 64 64 0x_1.ffff_ffff_p_128_l; 65 66 #pragma message( "Compiled" ) // force non-empty .expect file 65 67 } // main 66 68 -
tests/operators.cfa
rae2c27a rc76bd34 31 31 int main(int argc, char const *argv[]) { 32 32 /* code */ 33 return 0;33 printf( "done\n" ); // non-empty .expect file 34 34 } 35 35 -
tests/poly-o-cycle.cfa
rae2c27a rc76bd34 1 // Check that a cycle of polymorphic datastructures can be instancated.1 // Check that a cycle of polymorphic otype structures can be instancated. 2 2 3 3 #include <stdio.h> -
tests/pybin/tools.py
rae2c27a rc76bd34 88 88 raise 89 89 90 def is_empty(fname): 91 if not os.path.isfile(fname): 92 return True 93 94 if os.stat(fname).st_size == 0: 95 return True 96 97 return False 98 90 99 def is_ascii(fname): 91 100 if settings.dry_run: 92 101 print("is_ascii: %s" % fname) 93 return True102 return (True, "") 94 103 95 104 if not os.path.isfile(fname): 96 return False97 98 code, out = sh("file %s" %fname, output_file=subprocess.PIPE)105 return (False, "No file") 106 107 code, out = sh("file", fname, output_file=subprocess.PIPE) 99 108 if code != 0: 100 return False109 return (False, "'file EXPECT' failed with code {}".format(code)) 101 110 102 111 match = re.search(".*: (.*)", out) 103 112 104 113 if not match: 105 return False 106 107 return match.group(1).startswith("ASCII text") 114 return (False, "Unreadable file type: '{}'".format(out)) 115 116 if "ASCII text" in match.group(1): 117 return (True, "") 118 119 return (False, "File type should be 'ASCII text', was '{}'".format(match.group(1))) 108 120 109 121 def is_exe(fname): … … 120 132 return None 121 133 122 file = open(file, mode )134 file = open(file, mode, encoding="latin-1") # use latin-1 so all chars mean something. 123 135 exitstack.push(file) 124 136 return file -
tests/raii/.expect/ctor-autogen.txt
rae2c27a rc76bd34 1 done -
tests/raii/.expect/init_once.txt
rae2c27a rc76bd34 1 done -
tests/raii/ctor-autogen.cfa
rae2c27a rc76bd34 151 151 identity(gcs); 152 152 identity(gcu); 153 printf( "done\n" ); // non-empty .expect file 153 154 } -
tests/raii/init_once.cfa
rae2c27a rc76bd34 10 10 // Created On : Tue Jun 14 15:43:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Mar 22 13:41:26 201913 // Update Count : 412 // Last Modified On : Fri Sep 25 15:36:39 2020 13 // Update Count : 5 14 14 // 15 15 … … 188 188 static_variable(); 189 189 } 190 printf( "done\n" ); // non-empty .expect file 190 191 } 191 192 -
tests/result.cfa
rae2c27a rc76bd34 10 10 // Created On : Thr May 25 16:50:00 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jul 20 15:24:12 201713 // Update Count : 112 // Last Modified On : Fri Sep 25 15:22:59 2020 13 // Update Count : 2 14 14 // 15 15 … … 66 66 checkGetters(); 67 67 checkSetters(); 68 printf( "done\n" ); // non-empty .expect file 68 69 } -
tests/stdincludes.cfa
rae2c27a rc76bd34 10 10 // Created On : Tue Aug 29 08:26:14 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Nov 6 18:00:53 201813 // Update Count : 612 // Last Modified On : Sun Sep 27 08:51:38 2020 13 // Update Count : 8 14 14 // 15 15 … … 47 47 #include <wctype.h> 48 48 49 int main() {} 49 int main() { 50 #pragma message( "Compiled" ) // force non-empty .expect file 51 } 50 52 51 53 // Local Variables: // -
tests/switch.cfa
rae2c27a rc76bd34 10 10 // Created On : Tue Jul 12 06:50:22 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Nov 6 18:01:34 201813 // Update Count : 3712 // Last Modified On : Sun Sep 27 08:35:02 2020 13 // Update Count : 43 14 14 // 15 15 … … 100 100 j = 5; 101 101 } // choose 102 103 #pragma message( "Compiled" ) // force non-empty .expect file 102 104 } // main 103 105 -
tests/test.py
rae2c27a rc76bd34 173 173 test.prepare() 174 174 175 # ---------- 176 # MAKE 177 # ---------- 175 178 # build, skipping to next test on error 176 179 with Timed() as comp_dur: 177 180 make_ret, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file ) 178 181 182 # ---------- 183 # RUN 184 # ---------- 185 # run everything in a temp directory to make sure core file are handled properly 179 186 run_dur = None 180 # run everything in a temp directory to make sure core file are handled properly181 187 with tempdir(): 182 188 # if the make command succeeds continue otherwise skip to diff … … 207 213 else: 208 214 if os.stat(out_file).st_size < 1048576: 209 with open (out_file, "r" ) as myfile:215 with open (out_file, "r", encoding='latin-1') as myfile: # use latin-1 so all chars mean something. 210 216 error = myfile.read() 211 217 else: … … 256 262 make('clean', output_file=subprocess.DEVNULL, error=subprocess.DEVNULL) 257 263 258 # since python prints stacks by default on a interrupt, redo the interrupt handling to be silent 259 def worker_init(): 260 def sig_int(signal_num, frame): 261 pass 262 263 signal.signal(signal.SIGINT, sig_int) 264 265 # create the executor for our jobs and handle the signal properly 266 pool = multiprocessing.Pool(jobs, worker_init) 264 # create the executor for our jobs 265 pool = multiprocessing.Pool(jobs) 267 266 268 267 failed = False 269 270 def stop(x, y):271 print("Tests interrupted by user", file=sys.stderr)272 sys.exit(1)273 signal.signal(signal.SIGINT, stop)274 268 275 269 # for each test to run … … 360 354 failed = 0 361 355 356 # check if the expected files aren't empty 357 if not options.regenerate_expected: 358 for t in tests: 359 if is_empty(t.expect()): 360 print('WARNING: test "{}" has empty .expect file'.format(t.target()), file=sys.stderr) 361 362 362 # for each build configurations, run the test 363 363 with Timed() as total_dur: -
tests/typedefRedef.cfa
rae2c27a rc76bd34 27 27 typedef int ARR[]; 28 28 typedef int ARR[]; 29 // #ifdef ERR1 30 // if a typedef has an array dimension, 31 // it can only be redefined to the same dimension 29 #ifdef ERR1 30 // if a typedef has an array dimension, it can only be redefined to the same dimension 32 31 typedef int ARR[2]; 33 //#endif32 #endif 34 33 35 34 typedef int X; … … 54 53 55 54 int main() { 56 typedef int ARR[sz];55 typedef int ARR[sz]; 57 56 58 // can't redefine typedef which is VLA57 // can't redefine typedef which is VLA 59 58 #if ERR1 60 typedef int ARR[sz];59 typedef int ARR[sz]; 61 60 #endif 62 61 63 Foo *x;62 Foo * x; 64 63 65 typedef struct Bar Foo;66 Foo *y;64 typedef struct Bar Foo; 65 Foo * y; 67 66 68 typedef int *** pt; 67 typedef int *** pt; 68 69 #pragma message( "Compiled" ) // force non-empty .expect file 69 70 } -
tests/typeof.cfa
rae2c27a rc76bd34 1 1 int main() { 2 int *v1; 3 typeof(v1) v2; 4 typeof(*v1) v3[4]; 5 char *v4[4]; 6 typeof(typeof(char *)[4]) v5; 7 typeof (int *) v6; 8 typeof( int ( int, int p ) ) *v7; 9 typeof( [int] ( int, int p ) ) *v8; 10 (typeof(v1)) v2; // cast with typeof 2 int *v1; 3 typeof(v1) v2; 4 typeof(*v1) v3[4]; 5 char *v4[4]; 6 typeof(typeof(char *)[4]) v5; 7 typeof (int *) v6; 8 typeof( int ( int, int p ) ) *v7; 9 typeof( [int] ( int, int p ) ) *v8; 10 (typeof(v1)) v2; // cast with typeof 11 printf( "done\n" ); // non-empty .expect file 11 12 } -
tests/variableDeclarator.cfa
rae2c27a rc76bd34 10 10 // Created On : Wed Aug 17 08:41:42 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Nov 6 18:02:16 201813 // Update Count : 212 // Last Modified On : Sun Sep 27 07:46:17 2020 13 // Update Count : 13 14 14 // 15 15 … … 18 18 int (f2); 19 19 20 int * f3;21 int ** f4;22 int * const * f5;20 int * f3; 21 int ** f4; 22 int * const * f5; 23 23 int * const * const f6; 24 24 25 int * (f7);26 int ** (f8);27 int * const * (f9);25 int * (f7); 26 int ** (f8); 27 int * const * (f9); 28 28 int * const * const (f10); 29 29 30 int (* f11);31 int (** f12);32 int (* const * f13);30 int (* f11); 31 int (** f12); 32 int (* const * f13); 33 33 int (* const * const f14); 34 34 35 int f15[ ];35 int f15[0]; 36 36 int f16[10]; 37 int (f17[ ]);37 int (f17[0]); 38 38 int (f18[10]); 39 39 40 int * f19[];41 int * f20[10];42 int ** f21[];43 int ** f22[10];44 int * const * f23[];45 int * const * f24[10];46 int * const * const f25[ ];40 int * f19[0]; 41 int * f20[10]; 42 int ** f21[0]; 43 int ** f22[10]; 44 int * const * f23[0]; 45 int * const * f24[10]; 46 int * const * const f25[0]; 47 47 int * const * const f26[10]; 48 48 49 int *(f27[ ]);49 int *(f27[0]); 50 50 int *(f28[10]); 51 int **(f29[ ]);51 int **(f29[0]); 52 52 int **(f30[10]); 53 int * const *(f31[ ]);53 int * const *(f31[0]); 54 54 int * const *(f32[10]); 55 int * const * const (f33[ ]);55 int * const * const (f33[0]); 56 56 int * const * const (f34[10]); 57 57 58 int (* f35)[];59 int (* f36)[10];60 int (** f37)[];61 int (** f38)[10];62 int (* const * f39)[];63 int (* const * f40)[10];58 int (* f35)[]; 59 int (* f36)[10]; 60 int (** f37)[]; 61 int (** f38)[10]; 62 int (* const * f39)[]; 63 int (* const * f40)[10]; 64 64 int (* const * const f41)[]; 65 65 int (* const * const f42)[10]; 66 66 67 int f43[ ][3];67 int f43[0][3]; 68 68 int f44[3][3]; 69 int (f45[ ])[3];69 int (f45[0])[3]; 70 70 int (f46[3])[3]; 71 int ((f47[ ]))[3];71 int ((f47[0]))[3]; 72 72 int ((f48[3]))[3]; 73 73 74 int * f49[][3];75 int * f50[3][3];76 int ** f51[][3];77 int ** f52[3][3];78 int * const * f53[][3];79 int * const * f54[3][3];80 int * const * const f55[ ][3];74 int * f49[0][3]; 75 int * f50[3][3]; 76 int ** f51[0][3]; 77 int ** f52[3][3]; 78 int * const * f53[0][3]; 79 int * const * f54[3][3]; 80 int * const * const f55[0][3]; 81 81 int * const * const f56[3][3]; 82 82 83 int (* f57[][3]);84 int (* f58[3][3]);85 int (** f59[][3]);86 int (** f60[3][3]);87 int (* const * f61[][3]);88 int (* const * f62[3][3]);89 int (* const * const f63[ ][3]);83 int (* f57[0][3]); 84 int (* f58[3][3]); 85 int (** f59[0][3]); 86 int (** f60[3][3]); 87 int (* const * f61[0][3]); 88 int (* const * f62[3][3]); 89 int (* const * const f63[0][3]); 90 90 int (* const * const f64[3][3]); 91 91 … … 93 93 int (f66)(int); 94 94 95 int * f67(int);96 int ** f68(int);97 int * const * f69(int);95 int * f67(int); 96 int ** f68(int); 97 int * const * f69(int); 98 98 int * const * const f70(int); 99 99 … … 104 104 int * const * const (f74)(int); 105 105 106 int (* f75)(int);107 int (** f76)(int);108 int (* const * f77)(int);106 int (* f75)(int); 107 int (** f76)(int); 108 int (* const * f77)(int); 109 109 int (* const * const f78)(int); 110 110 111 int (*(* f79)(int))();111 int (*(* f79)(int))(); 112 112 int (*(* const f80)(int))(); 113 113 int (* const(* const f81)(int))(); … … 119 119 //int fe2()[]; // returning an array 120 120 //int fe3()(); // returning a function 121 //int (* fe4)()(); // returning a function122 //int ((* fe5())())[]; // returning an array121 //int (* fe4)()(); // returning a function 122 //int ((* fe5())())[]; // returning an array 123 123 124 #ifdef __CFA__ 124 125 // Cforall extensions 125 126 … … 129 130 const * const * int cf6; 130 131 131 [ ] int cf15;132 [0] int cf15; 132 133 [10] int cf16; 133 134 134 [ ] * int cf19;135 [0] * int cf19; 135 136 [10] * int cf20; 136 int ** cf21[];137 int ** cf21[0]; 137 138 [10] * * int cf22; 138 [ ] * const * int cf23;139 [0] * const * int cf23; 139 140 [10] * const * int cf24; 140 [ ] const * const * int cf25;141 [0] const * const * int cf25; 141 142 [10] const * const * int cf26; 142 143 … … 150 151 const * const * [10] int cf42; 151 152 152 [ ][3] int cf43;153 [0][3] int cf43; 153 154 [3][3] int cf44; 154 155 155 [ ][3] * int cf49;156 [0][3] * int cf49; 156 157 [3][3] * int cf50; 157 [ ][3] * * int cf51;158 [0][3] * * int cf51; 158 159 [3][3] * * int cf52; 159 [ ][3] const * int cf53;160 [0][3] const * int cf53; 160 161 [3][3] * const * int cf54; 161 [ ][3] const * const * int cf55;162 [0][3] const * const * int cf55; 162 163 [3][3] const * const * int cf56; 163 164 … … 173 174 174 175 *[]*[]* [ *[]*[] int ]( *[]*[] int, *[]*[] int ) v3; 176 #endif // __CFA__ 175 177 176 178 //Dummy main 177 int main(int argc, char const *argv[]) 178 { 179 return 0; 179 int main( int argc, char const * argv[] ) { 180 #pragma message( "Compiled" ) // force non-empty .expect file 180 181 } 181 182 -
tests/voidPtr.cfa
rae2c27a rc76bd34 13 13 if ( ! a ) { 14 14 abort(); 15 } 15 } 16 printf( "done\n" ); // non-empty .expect file 16 17 } 17 18 -
tests/warnings/.expect/self-assignment.txt
rae2c27a rc76bd34 24 24 ... to: 25 25 reference to signed int 26 warnings/self-assignment.cfa: In function '_X4mainFi___1': 27 warnings/self-assignment.cfa:36:9: note: #pragma message: Compiled -
tests/warnings/self-assignment.cfa
rae2c27a rc76bd34 10 10 // Created On : Thu Mar 1 13:53:57 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 20 07:56:17 201913 // Update Count : 312 // Last Modified On : Sun Sep 27 09:24:34 2020 13 // Update Count : 6 14 14 // 15 15 … … 31 31 s.i = s.i; 32 32 t.s.i = t.s.i; 33 34 #pragma message( "Compiled" ) // force non-empty .expect file 33 35 } 34 36 35 37 // Local Variables: // 36 38 // tab-width: 4 // 37 // compile-command: "cfa dtor-early-exit" //39 // compile-command: "cfa self-assignment.cfa" // 38 40 // End: // -
tests/zombies/Rank2.c
rae2c27a rc76bd34 1 int ?=?( int *, int );2 forall(dtype DT) DT * ?=?( DT * *, DT * );1 int ?=?( int &, int ); 2 forall(dtype DT) DT * ?=?( DT *&, DT * ); 3 3 4 4 void a() { … … 11 11 void h( int *null ); 12 12 forall( otype T ) T id( T ); 13 forall( dtype T ) T *0;14 int 0;13 // forall( dtype T ) T *0; 14 // int 0; 15 15 h( id( id( id( 0 ) ) ) ); 16 16 } -
tests/zombies/Tuple.c
rae2c27a rc76bd34 46 46 [ 3, 5 ]; 47 47 [ a, b ] = 3; 48 //[ a, b ] = [ 4.6 ];48 [ a, b ] = [ 4.6 ]; 49 49 [ a, b ] = 4.6; 50 50 [ a, b ] = [ c, d ] = [ 3, 5 ]; … … 59 59 [ a, b ] = t1 = [ c, d ]; 60 60 [ a, b ] = t1 = t2 = [ c, d ]; 61 //t1 = [ 3, 4 ] = [ 3, 4 ] = t1 = [ 3, 4 ];61 t1 = [ 3, 4 ] = [ 3, 4 ] = t1 = [ 3, 4 ]; 62 62 63 63 s.[ f1, i.[ f2, f3 ], f4 ] = [ 11, 12, 13, 3.14159 ]; … … 65 65 // [ a, , b, ] = h( 3, 3, 0, "abc" ); /* ignore some results */ 66 66 sp->[ f4, f1 ] = sp->[ f1, f4 ]; 67 printf( "expecting 3, 17, 23, 4; got % d, %d, %d, %d\n", s.[ f4, i.[ f3, f2 ], f1 ] );67 printf( "expecting 3, 17, 23, 4; got %g, %d, %d, %d\n", s.[ f4, i.[ f3, f2 ], f1 ] ); 68 68 rc = 0; 69 69 } -
tests/zombies/abstype.c
rae2c27a rc76bd34 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jun 14 14:27:48 201613 // Update Count : 912 // Last Modified On : Wed Sep 30 13:55:47 2020 13 // Update Count : 10 14 14 // 15 15 … … 21 21 } 22 22 23 forall( otype T ) lvalueT *?( T * );23 forall( otype T ) T *?( T * ); 24 24 int ?++( int * ); 25 25 int ?=?( int *, int ); -
tests/zombies/includes.c
rae2c27a rc76bd34 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Nov 15 23:06:24 201713 // Update Count : 59 712 // Last Modified On : Wed Sep 30 13:59:18 2020 13 // Update Count : 598 14 14 // 15 15 … … 24 24 #if 1 25 25 #define _GNU_SOURCE 26 #include <a.out.h> 27 #include <aio.h> 28 #include <aliases.h> 29 #include <alloca.h> 30 #include <ansidecl.h> 31 #include <ar.h> 32 #include <argp.h> 33 #include <argz.h> 34 #include <assert.h> 35 //#include <bfd.h> 36 // #include <bfdlink.h> // keyword with 37 #include <byteswap.h> 38 #include <bzlib.h> 39 #include <cblas.h> 40 #include <cblas_f77.h> 41 #include <complex.h> 42 #include <com_err.h> 43 #include <cpio.h> 44 #include <crypt.h> 45 #include <ctype.h> 46 #include <curses.h> 47 #include <dialog.h> 48 #include <dirent.h> 49 #include <dis-asm.h> 50 #include <dlfcn.h> 51 #include <dlg_colors.h> 52 #include <dlg_config.h> 53 #include <dlg_keys.h> 54 #include <elf.h> 55 #include <endian.h> 56 #include <envz.h> 57 #include <err.h> 58 #include <errno.h> 59 #include <error.h> 60 #include <eti.h> 61 #include <evdns.h> 62 #include <event.h> 26 // #include <a.out.h> 27 // #include <aio.h> 28 // #include <aliases.h> 29 // #include <alloca.h> 30 // #include <ansidecl.h> 31 // #include <ar.h> 32 // #include <argp.h> 33 // #include <argz.h> 34 // #include <assert.h> 35 // #include <bfd.h> 36 // #include <bfdlink.h> // keyword with 37 // #include <byteswap.h> 38 // #include <bzlib.h> 39 // #include <cblas.h> 40 // #include <cblas_f77.h> 41 // #include <complex.h> 42 // #include <com_err.h> 43 // #include <cpio.h> 44 45 // #include <crypt.h> 46 // #include <ctype.h> 47 // #include <curses.h> 48 // #include <dialog.h> 49 // #include <dirent.h> 50 // #include <dis-asm.h> 51 // #include <dlfcn.h> 52 // #include <dlg_colors.h> 53 // #include <dlg_config.h> 54 // #include <dlg_keys.h> 55 // #include <elf.h> 56 // #include <endian.h> 57 // #include <envz.h> 58 // #include <err.h> 59 // #include <errno.h> 60 // #include <error.h> 61 // #include <eti.h> 62 // #include <evdns.h> 63 // #include <event.h> 63 64 64 65 // #include <evhttp.h> 65 66 // #include <sys/queue.h> 66 // #include <evrpc.h> // evrpc.h depends on sys/queue.h67 // #include <evrpc.h> // evrpc.h depends on sys/queue.h 67 68 // #include <evutil.h> 68 69 // #include <execinfo.h> … … 80 81 // #include <fts.h> 81 82 // #include <ftw.h> 83 82 84 // #include <gconv.h> 83 85 // #include <getopt.h> … … 89 91 // #include <gshadow.h> 90 92 // #include <gssapi.h> 91 // #include <hwloc.h>// keyword thread (setjmp)93 #include <hwloc.h> // keyword thread (setjmp) 92 94 // #include <iconv.h> 93 95 // #include <idna.h> -
tests/zombies/structMember.cfa
rae2c27a rc76bd34 53 53 // C useless declarations 54 54 55 #ifdef ERROR 55 56 int; 56 57 TD; … … 70 71 W(int); 71 72 W(int).X; 73 #endif // ERROR 72 74 }; 73 75 -
tools/gdb/utils-gdb.py
rae2c27a rc76bd34 44 44 STACK = [] 45 45 46 # A global variable to keep all system task name47 SysTask_Name = ["uLocalDebuggerReader", "uLocalDebugger", "uProcessorTask", "uBootTask", "uSystemTask",48 "uProcessorTask", "uPthread", "uProfiler"]49 50 46 not_supported_error_msg = "Not a supported command for this language" 51 47 … … 101 97 return cluster_root 102 98 99 def get_sched_lock(): 100 """ 101 Return: gdb.Value of __scheduler_lock 102 """ 103 lock = gdb.parse_and_eval('_X16__scheduler_lockPS20__scheduler_RWLock_t_1') 104 if lock.address == 0x0: 105 print('No scheduler lock, program terminated') 106 return lock 107 108 def all_clusters(): 109 if not is_cforall(): 110 return None 111 112 cluster_root = get_cluster_root() 113 if cluster_root.address == 0x0: 114 return 115 116 curr = cluster_root 117 ret = [curr] 118 119 while True: 120 curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1'] 121 if curr == cluster_root: 122 break 123 124 ret.append(curr) 125 126 return ret 127 128 def all_processors(): 129 if not is_cforall(): 130 return None 131 132 cfa_t = get_cfa_types() 133 134 # get processors from registration to the RWlock 135 lock = get_sched_lock() 136 137 #get number of elements 138 count = lock['_X5readyVj_1'] 139 140 #find all the procs 141 raw_procs = [lock['_X4dataPS21__scheduler_lock_id_t_1'][i]['_X6handleVPS16__processor_id_t_1'] for i in range(count)] 142 143 # pre cast full procs 144 procs = [p.cast(cfa_t.processor_ptr) for p in raw_procs if p['_X9full_procb_1']] 145 146 # sort procs by clusters 147 return sorted(procs, key=lambda p: p['_X4cltrPS7cluster_1']) 148 149 def tls_for_pthread(pthrd): 150 prev = gdb.selected_thread() 151 inf = gdb.selected_inferior() 152 153 thrd = inf.thread_from_thread_handle( pthrd ) 154 thrd.switch() 155 tls = gdb.parse_and_eval('&_X9kernelTLSS16KernelThreadData_1') 156 157 prev.switch() 158 return tls 159 160 def tls_for_proc(proc): 161 return tls_for_pthread(proc['_X13kernel_threadm_1']) 162 163 def thread_for_pthread(pthrd): 164 return tls_for_pthread(pthrd)['_X11this_threadVPS7$thread_1'] 165 166 def thread_for_proc(proc): 167 return tls_for_proc(proc)['_X11this_threadVPS7$thread_1'] 168 169 170 103 171 def find_curr_thread(): 104 172 # btstr = gdb.execute('bt', to_string = True).splitlines() … … 108 176 # return btstr[0].split('this=',1)[1].split(',')[0].split(')')[0] 109 177 return None 110 111 def all_clusters():112 if not is_cforall():113 return None114 115 cluster_root = get_cluster_root()116 if cluster_root.address == 0x0:117 return118 119 curr = cluster_root120 ret = [curr]121 122 while True:123 curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1']124 if curr == cluster_root:125 break126 127 ret.append(curr)128 129 return ret130 131 178 132 179 def lookup_cluster(name = None): … … 239 286 """Cforall: Display currently known processors 240 287 Usage: 241 info processors : print out all the processors in the Main Cluster 242 info processors all : print out all processors in all clusters 288 info processors : print out all the processors 243 289 info processors <cluster_name> : print out all processors in a given cluster 244 290 """ … … 247 293 super(Processors, self).__init__('info processors', gdb.COMMAND_USER) 248 294 249 def print_processor(self, name, status, pending, address): 250 print('{:>20} {:>11} {:>13} {:>20}'.format(name, status, pending, address)) 251 252 def iterate_procs(self, root, active): 253 if root == 0x0: 254 return 255 256 cfa_t = get_cfa_types() 257 curr = root 258 259 while True: 260 processor = curr 261 should_stop = processor['_X12do_terminateVb_1'] 295 def print_processor(self, processor): 296 should_stop = processor['_X12do_terminateVb_1'] 297 if not should_stop: 298 midle = processor['_X6$linksS7$dlinks_S9processor__1']['_X4nextS9$mgd_link_Y13__tE_generic___1']['_X4elemPY13__tE_generic__1'] != 0x0 299 end = processor['_X6$linksS7$dlinks_S9processor__1']['_X4nextS9$mgd_link_Y13__tE_generic___1']['_X10terminatorPv_1'] != 0x0 300 301 status = 'Idle' if midle or end else 'Active' 302 else: 262 303 stop_count = processor['_X10terminatedS9semaphore_1']['_X5counti_1'] 263 if not should_stop: 264 status = 'Active' if active else 'Idle' 265 else: 266 status_str = 'Last Thread' if stop_count >= 0 else 'Terminating' 267 status = '{}({},{})'.format(status_str, should_stop, stop_count) 268 269 self.print_processor(processor['_X4namePKc_1'].string(), 270 status, str(processor['_X18pending_preemptionb_1']), str(processor) 271 ) 272 273 curr = curr['_X4nodeS28__processor____dbg_node_proc_1']['_X4nextPS9processor_1'] 274 275 if curr == root or curr == 0x0: 276 break 304 status_str = 'Last Thread' if stop_count >= 0 else 'Terminating' 305 status = '{}({},{})'.format(status_str, should_stop, stop_count) 306 307 print('{:>20} {:>11} {:<7} {:<}'.format( 308 processor['_X4namePKc_1'].string(), 309 status, 310 str(processor['_X18pending_preemptionb_1']), 311 str(processor) 312 )) 313 tls = tls_for_proc( processor ) 314 thrd = tls['_X11this_threadVPS7$thread_1'] 315 if thrd != 0x0: 316 tname = '{} {}'.format(thrd['self_cor']['name'].string(), str(thrd)) 317 else: 318 tname = None 319 320 print('{:>20} {}'.format('Thread', tname)) 321 print('{:>20} {}'.format('TLS', tls)) 277 322 278 323 #entry point from gdb … … 282 327 283 328 if not arg: 284 clusters = [lookup_cluster(None)]285 elif arg == "all":286 329 clusters = all_clusters() 287 330 else: … … 292 335 return 293 336 294 cfa_t = get_cfa_types() 295 for cluster in clusters: 296 print('Cluster: "{}"({})'.format(cluster['_X4namePKc_1'].string(), cluster.cast(cfa_t.cluster_ptr))) 297 298 active_root = cluster.cast(cfa_t.cluster_ptr) \ 299 ['_X5procsS8__dllist_S9processor__1'] \ 300 ['_X4headPY15__TYPE_generic__1'] \ 301 .cast(cfa_t.processor_ptr) 302 303 idle_root = cluster.cast(cfa_t.cluster_ptr) \ 304 ['_X5idlesS8__dllist_S9processor__1'] \ 305 ['_X4headPY15__TYPE_generic__1'] \ 306 .cast(cfa_t.processor_ptr) 307 308 if idle_root != 0x0 or active_root != 0x0: 309 self.print_processor('Name', 'Status', 'Pending Yield', 'Address') 310 self.iterate_procs(active_root, True) 311 self.iterate_procs(idle_root, False) 312 else: 313 print("No processors on cluster") 337 procs = all_processors() 338 339 print('{:>20} {:>11} {:<7} {}'.format('Processor', '', 'Pending', 'Object')) 340 print('{:>20} {:>11} {:<7} {}'.format('Name', 'Status', 'Yield', 'Address')) 341 cl = None 342 for p in procs: 343 # if this is a different cluster print it 344 if cl != p['_X4cltrPS7cluster_1']: 345 if cl: 346 print() 347 cl = p['_X4cltrPS7cluster_1'] 348 print('Cluster {}'.format(cl['_X4namePKc_1'].string())) 349 350 # print the processor information 351 self.print_processor(p) 314 352 315 353 print()
Note:
See TracChangeset
for help on using the changeset viewer.