From 44e8eabc8f7a0ab23c29037a770463d8a2de7b4a Mon Sep 17 00:00:00 2001 From: bdemsky Date: Fri, 21 Aug 2015 11:40:52 -0700 Subject: [PATCH] Commit state of repository at time of OOPSLA 2015 submission. --- .dir-locals.el | 1 + .gitignore | 14 + COPYING | 339 + DEBUGGINGNOTES.txt | 8 + Doxyfile | 1801 ++ Makefile | 94 + benchmarks/.gitignore | 4 + benchmarks/cdschecker/dekker/bench.sh | 10 + .../cdschecker/dekker/dekker-fences.cc.in | 88 + benchmarks/cdschecker/linuxlock/bench.sh | 10 + .../cdschecker/linuxlock/linuxlocks.c.in | 54 + benchmarks/cdschecker/linuxrwlock/bench.sh | 10 + .../cdschecker/linuxrwlock/linuxrwlocks.c.in | 56 + benchmarks/cdschecker/msqueue/bench.sh | 10 + .../cdschecker/msqueue/ms-queue_simple.c.in | 107 + .../cdschecker/msqueue/ms-queue_simple.h | 15 + benchmarks/cdschecker/path.sh | 1 + benchmarks/cdschecker/seqlock/bench.sh | 10 + benchmarks/cdschecker/seqlock/seqlock.c.in | 77 + benchmarks/checkfence/dekker/bench.sh | 14 + benchmarks/checkfence/dekker/clean.sh | 8 + .../checkfence/dekker/dekker-fences.c.in | 75 + benchmarks/checkfence/dekker/dekkertests.lsl | 1 + benchmarks/checkfence/linuxlock/bench.sh | 14 + benchmarks/checkfence/linuxlock/clean.sh | 8 + benchmarks/checkfence/linuxlock/lin_harness.c | 18 + .../checkfence/linuxlock/linuxrwlocksbig.c.in | 38 + benchmarks/checkfence/linuxlock/locktests.lsl | 1 + .../checkfence/linuxrwlock/add_harness.c | 18 + benchmarks/checkfence/linuxrwlock/bench.sh | 26 + benchmarks/checkfence/linuxrwlock/clean.sh | 8 + benchmarks/checkfence/linuxrwlock/llock.c.in | 53 + .../checkfence/linuxrwlock/locktests.lsl | 1 + benchmarks/checkfence/msqueue/bench.sh | 15 + benchmarks/checkfence/msqueue/clean.sh | 8 + benchmarks/checkfence/msqueue/msn.c | 72 + .../checkfence/msqueue/msn_harness.c.in | 21 + benchmarks/checkfence/msqueue/tests.lsl | 1 + benchmarks/checkfence/paths.sh | 4 + benchmarks/checkfence/seqlock/bench.sh | 11 + benchmarks/checkfence/seqlock/clean.sh | 8 + benchmarks/checkfence/seqlock/seqlock.c.in | 62 + benchmarks/checkfence/seqlock/seqtests.lsl | 1 + benchmarks/compilesat | 8 + benchmarks/nidhugg/dekker/bench.sh | 9 + benchmarks/nidhugg/dekker/benchtso.sh | 11 + benchmarks/nidhugg/dekker/dekker-fences.cc.in | 93 + benchmarks/nidhugg/linuxlock/bench.sh | 10 + benchmarks/nidhugg/linuxlock/benchtso.sh | 10 + benchmarks/nidhugg/linuxlock/linuxlocks.c.in | 55 + benchmarks/nidhugg/linuxrwlock/bench.sh | 9 + benchmarks/nidhugg/linuxrwlock/benchtso.sh | 9 + .../nidhugg/linuxrwlock/linuxrwlocks.c.in | 51 + benchmarks/nidhugg/msqueue/bench.sh | 10 + benchmarks/nidhugg/msqueue/benchtso.sh | 10 + .../nidhugg/msqueue/ms-queue_simple.c.in | 105 + benchmarks/nidhugg/msqueue/ms-queue_simple.h | 15 + benchmarks/nidhugg/path.sh | 1 + benchmarks/nidhugg/seqlock/bench.sh | 10 + benchmarks/nidhugg/seqlock/benchtso.sh | 10 + benchmarks/nidhugg/seqlock/seqlock.c.in | 73 + benchmarks/nidhugg/transform.java | 29 + benchmarks/runcds | 14 + benchmarks/runcf | 15 + benchmarks/runnidd | 20 + benchmarks/runsat | 13 + benchmarks/runtsosat | 13 + .../satcheck-precompiled/dekker/.gitignore | 3 + .../satcheck-precompiled/dekker/bench.sh | 16 + .../dekker/benchmark-config.sh | 5 + .../satcheck-precompiled/dekker/benchtso.sh | 16 + .../satcheck-precompiled/dekker/clean.sh | 2 + .../dekker/dekker-fences.c | 199 + .../dekker/dekker-fences_unannotated.c | 134 + .../satcheck-precompiled/dekker/diff.sh | 3 + .../satcheck-precompiled/linuxlock/.gitignore | 3 + .../satcheck-precompiled/linuxlock/bench.sh | 16 + .../linuxlock/benchmark-config.sh | 5 + .../linuxlock/benchtso.sh | 16 + .../satcheck-precompiled/linuxlock/clean.sh | 2 + .../satcheck-precompiled/linuxlock/diff.sh | 4 + .../linuxlock/linuxlocks.c | 78 + .../linuxlock/linuxlocks_unannotated.c | 59 + .../linuxrwlock/.gitignore | 4 + .../satcheck-precompiled/linuxrwlock/bench.sh | 16 + .../linuxrwlock/benchmark-config.sh | 5 + .../linuxrwlock/benchtso.sh | 16 + .../satcheck-precompiled/linuxrwlock/clean.sh | 2 + .../satcheck-precompiled/linuxrwlock/diff.sh | 4 + .../linuxrwlock/linuxrwlocks.c | 201 + .../linuxrwlock/linuxrwlocks_unannotated.c | 128 + .../msqueueoffset/.gitignore | 3 + .../msqueueoffset/bench.sh | 16 + .../msqueueoffset/benchmark-config.sh | 5 + .../msqueueoffset/benchtso.sh | 16 + .../msqueueoffset/clean.sh | 2 + .../msqueueoffset/diff.sh | 4 + .../msqueueoffset/ms-queue-simple.c | 225 + .../msqueueoffset/ms-queue-simple.h | 15 + .../ms-queue-simple_unannotated.c | 137 + .../satcheck-precompiled/seqlock/.gitignore | 3 + .../satcheck-precompiled/seqlock/bench.sh | 16 + .../seqlock/benchmark-config.sh | 5 + .../satcheck-precompiled/seqlock/benchtso.sh | 16 + .../satcheck-precompiled/seqlock/clean.sh | 2 + .../satcheck-precompiled/seqlock/diff.sh | 4 + .../satcheck-precompiled/seqlock/seqlock.cc | 149 + .../seqlock/seqlock_unannotated.cc | 95 + benchmarks/satcheck/dekker/.gitignore | 4 + benchmarks/satcheck/dekker/bench.sh | 16 + .../satcheck/dekker/benchmark-config.sh | 5 + benchmarks/satcheck/dekker/benchtso.sh | 16 + benchmarks/satcheck/dekker/clean.sh | 2 + benchmarks/satcheck/dekker/compile.sh | 5 + .../dekker/dekker-fences_unannotated.c | 127 + benchmarks/satcheck/dekker/diff.sh | 3 + benchmarks/satcheck/linuxlock/.gitignore | 4 + benchmarks/satcheck/linuxlock/bench.sh | 16 + .../satcheck/linuxlock/benchmark-config.sh | 5 + benchmarks/satcheck/linuxlock/benchtso.sh | 16 + benchmarks/satcheck/linuxlock/clean.sh | 2 + benchmarks/satcheck/linuxlock/compile.sh | 5 + benchmarks/satcheck/linuxlock/diff.sh | 4 + .../linuxlock/linuxlocks_unannotated.c | 61 + benchmarks/satcheck/linuxrwlock/.gitignore | 5 + benchmarks/satcheck/linuxrwlock/bench.sh | 16 + .../satcheck/linuxrwlock/benchmark-config.sh | 5 + benchmarks/satcheck/linuxrwlock/benchtso.sh | 16 + benchmarks/satcheck/linuxrwlock/clean.sh | 2 + benchmarks/satcheck/linuxrwlock/compile.sh | 5 + benchmarks/satcheck/linuxrwlock/diff.sh | 4 + .../linuxrwlock/linuxrwlocks_unannotated.c | 128 + benchmarks/satcheck/msqueueoffset/.gitignore | 6 + benchmarks/satcheck/msqueueoffset/bench.sh | 16 + .../msqueueoffset/benchmark-config.sh | 5 + benchmarks/satcheck/msqueueoffset/benchtso.sh | 16 + benchmarks/satcheck/msqueueoffset/clean.sh | 2 + benchmarks/satcheck/msqueueoffset/compile.sh | 5 + benchmarks/satcheck/msqueueoffset/diff.sh | 4 + .../satcheck/msqueueoffset/ms-queue-simple.h | 15 + .../ms-queue-simple_unannotated.c | 137 + benchmarks/satcheck/seqlock/.gitignore | 4 + benchmarks/satcheck/seqlock/bench.sh | 16 + .../satcheck/seqlock/benchmark-config.sh | 5 + benchmarks/satcheck/seqlock/benchtso.sh | 16 + benchmarks/satcheck/seqlock/clean.sh | 2 + benchmarks/satcheck/seqlock/compile.sh | 5 + benchmarks/satcheck/seqlock/diff.sh | 4 + .../satcheck/seqlock/seqlock_unannotated.cc | 95 + benchmarks/verifycompilesat | 4 + bin/annotate | 7 + branchrecord.cc | 59 + branchrecord.h | 33 + cgoal.cc | 61 + cgoal.h | 44 + change.cc | 38 + change.h | 42 + clang/.gitignore | 4 + clang/COPYING | 14 + clang/Makefile | 92 + clang/README.md | 55 + clang/multi-dep.txt | 9 + clang/src/add_mc2_annotations.cpp | 1534 ++ clang/test/apr_1_unannotated.c | 13826 +++++++++++++++ clang/test/apr_2_unannotated.c | 13827 ++++++++++++++++ clang/test/bitops.c | 137 + clang/test/bitops_unannotated.c | 89 + clang/test/linuxrwlocks.c | 191 + clang/test/linuxrwlocks_unannotated.c | 125 + clang/test/mcs-lock_unannotated.cc | 139 + clang/test/minimal-no-braces-if.c | 108 + clang/test/minimal-no-braces-if_unannotated.c | 77 + clang/test/ms-queue-simple-offset.c | 209 + .../test/ms-queue-simple-offset_unannotated.c | 133 + clang/test/ms-queue-simple.c | 223 + clang/test/ms-queue-simple.h | 15 + clang/test/ms-queue-simple_manual.c | 201 + clang/test/ms-queue-simple_unannotated.c | 131 + clang/test/ms-queue_unannotated.c | 132 + clang/test/seqlock.c | 135 + clang/test/seqlock_raw_unannotated.c | 74 + clang/test/seqlock_unannotated.c | 82 + clang/test/spsc-queue_unannotated.cc | 91 + clang/test/userprog2_unannotated.c | 61 + clang/test/userprog_unannotated.c | 55 + clang/test/various-loads.c | 54 + clang/test/various-loads_unannotated.c | 30 + classlist.h | 56 + cmodelint.cc | 46 + common.cc | 180 + common.h | 54 + common.mk | 17 + config.h | 76 + constgen.cc | 1897 +++ constgen.h | 182 + constraint.cc | 423 + constraint.h | 59 + context.cc | 36 + context.h | 33 + eprecord.cc | 236 + eprecord.h | 110 + epvalue.cc | 39 + epvalue.h | 51 + equalsrecord.cc | 28 + equalsrecord.h | 26 + execpoint.cc | 176 + execpoint.h | 54 + functionrecord.cc | 66 + functionrecord.h | 27 + hashset.h | 218 + hashtable.h | 370 + inc_solver.cc | 164 + inc_solver.h | 50 + include/atomic | 11 + include/cmodelint.h | 28 + include/condition_variable | 24 + include/cstdatomic | 7 + include/impatomic.h | 3923 +++++ include/libinterface.h | 72 + include/memoryorder.h | 28 + include/model-assert.h | 17 + include/modeltypes.h | 28 + include/mutex | 31 + include/stdatomic.h | 72 + include/threads.h | 37 + libinterface.cc | 186 + libthreads.cc | 41 + loadrf.cc | 115 + loadrf.h | 26 + main.cc | 133 + malloc.c | 6252 +++++++ mcexecution.cc | 1012 ++ mcexecution.h | 158 + mcschedule.cc | 244 + mcschedule.h | 61 + mcutil.h | 34 + model.cc | 60 + model.h | 44 + mymemory.cc | 315 + mymemory.h | 288 + notes | 20 + output.h | 29 + params.h | 34 + planner.cc | 422 + planner.h | 65 + run.sh | 27 + schedulebuilder.cc | 219 + schedulebuilder.h | 35 + snapshot-interface.cc | 198 + snapshot-interface.h | 29 + snapshot.cc | 495 + snapshot.h | 29 + solver_interface.h | 23 + stacktrace.h | 94 + stl-model.h | 85 + storeloadset.cc | 130 + storeloadset.h | 48 + test/Makefile | 23 + test/dekker-fences.c | 148 + test/function_microbenchmarks.c | 58 + test/linuxlock.c | 69 + test/load_in_if_cond.c | 28 + test/mcs-lock.cc | 193 + test/ms-queue-freelist.c | 237 + test/ms-queue-freelist.h | 29 + test/ms-queue.c | 213 + test/ms-queue.h | 20 + test/reference/README.md | 1 + test/reference/ms-queue-atomics.c | 165 + test/seqlock.c | 121 + test/seqlock2.cc | 143 + test/spsc-queue.cc | 111 + test/userprog.c | 76 + test/userprog2.c | 89 + test/userprog_pointers.c | 44 + threads-model.h | 147 + threads.cc | 196 + valuerecord.cc | 67 + valuerecord.h | 26 + 279 files changed, 60521 insertions(+) create mode 100644 .dir-locals.el create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 DEBUGGINGNOTES.txt create mode 100644 Doxyfile create mode 100644 Makefile create mode 100644 benchmarks/.gitignore create mode 100755 benchmarks/cdschecker/dekker/bench.sh create mode 100644 benchmarks/cdschecker/dekker/dekker-fences.cc.in create mode 100755 benchmarks/cdschecker/linuxlock/bench.sh create mode 100644 benchmarks/cdschecker/linuxlock/linuxlocks.c.in create mode 100755 benchmarks/cdschecker/linuxrwlock/bench.sh create mode 100644 benchmarks/cdschecker/linuxrwlock/linuxrwlocks.c.in create mode 100755 benchmarks/cdschecker/msqueue/bench.sh create mode 100644 benchmarks/cdschecker/msqueue/ms-queue_simple.c.in create mode 100644 benchmarks/cdschecker/msqueue/ms-queue_simple.h create mode 100755 benchmarks/cdschecker/path.sh create mode 100755 benchmarks/cdschecker/seqlock/bench.sh create mode 100644 benchmarks/cdschecker/seqlock/seqlock.c.in create mode 100755 benchmarks/checkfence/dekker/bench.sh create mode 100755 benchmarks/checkfence/dekker/clean.sh create mode 100644 benchmarks/checkfence/dekker/dekker-fences.c.in create mode 100644 benchmarks/checkfence/dekker/dekkertests.lsl create mode 100755 benchmarks/checkfence/linuxlock/bench.sh create mode 100755 benchmarks/checkfence/linuxlock/clean.sh create mode 100755 benchmarks/checkfence/linuxlock/lin_harness.c create mode 100644 benchmarks/checkfence/linuxlock/linuxrwlocksbig.c.in create mode 100644 benchmarks/checkfence/linuxlock/locktests.lsl create mode 100755 benchmarks/checkfence/linuxrwlock/add_harness.c create mode 100755 benchmarks/checkfence/linuxrwlock/bench.sh create mode 100755 benchmarks/checkfence/linuxrwlock/clean.sh create mode 100644 benchmarks/checkfence/linuxrwlock/llock.c.in create mode 100644 benchmarks/checkfence/linuxrwlock/locktests.lsl create mode 100755 benchmarks/checkfence/msqueue/bench.sh create mode 100755 benchmarks/checkfence/msqueue/clean.sh create mode 100755 benchmarks/checkfence/msqueue/msn.c create mode 100755 benchmarks/checkfence/msqueue/msn_harness.c.in create mode 100644 benchmarks/checkfence/msqueue/tests.lsl create mode 100644 benchmarks/checkfence/paths.sh create mode 100755 benchmarks/checkfence/seqlock/bench.sh create mode 100755 benchmarks/checkfence/seqlock/clean.sh create mode 100644 benchmarks/checkfence/seqlock/seqlock.c.in create mode 100644 benchmarks/checkfence/seqlock/seqtests.lsl create mode 100755 benchmarks/compilesat create mode 100755 benchmarks/nidhugg/dekker/bench.sh create mode 100755 benchmarks/nidhugg/dekker/benchtso.sh create mode 100644 benchmarks/nidhugg/dekker/dekker-fences.cc.in create mode 100755 benchmarks/nidhugg/linuxlock/bench.sh create mode 100755 benchmarks/nidhugg/linuxlock/benchtso.sh create mode 100644 benchmarks/nidhugg/linuxlock/linuxlocks.c.in create mode 100755 benchmarks/nidhugg/linuxrwlock/bench.sh create mode 100755 benchmarks/nidhugg/linuxrwlock/benchtso.sh create mode 100644 benchmarks/nidhugg/linuxrwlock/linuxrwlocks.c.in create mode 100755 benchmarks/nidhugg/msqueue/bench.sh create mode 100755 benchmarks/nidhugg/msqueue/benchtso.sh create mode 100644 benchmarks/nidhugg/msqueue/ms-queue_simple.c.in create mode 100644 benchmarks/nidhugg/msqueue/ms-queue_simple.h create mode 100755 benchmarks/nidhugg/path.sh create mode 100755 benchmarks/nidhugg/seqlock/bench.sh create mode 100755 benchmarks/nidhugg/seqlock/benchtso.sh create mode 100644 benchmarks/nidhugg/seqlock/seqlock.c.in create mode 100644 benchmarks/nidhugg/transform.java create mode 100755 benchmarks/runcds create mode 100755 benchmarks/runcf create mode 100755 benchmarks/runnidd create mode 100755 benchmarks/runsat create mode 100755 benchmarks/runtsosat create mode 100644 benchmarks/satcheck-precompiled/dekker/.gitignore create mode 100755 benchmarks/satcheck-precompiled/dekker/bench.sh create mode 100644 benchmarks/satcheck-precompiled/dekker/benchmark-config.sh create mode 100755 benchmarks/satcheck-precompiled/dekker/benchtso.sh create mode 100755 benchmarks/satcheck-precompiled/dekker/clean.sh create mode 100644 benchmarks/satcheck-precompiled/dekker/dekker-fences.c create mode 100644 benchmarks/satcheck-precompiled/dekker/dekker-fences_unannotated.c create mode 100755 benchmarks/satcheck-precompiled/dekker/diff.sh create mode 100644 benchmarks/satcheck-precompiled/linuxlock/.gitignore create mode 100755 benchmarks/satcheck-precompiled/linuxlock/bench.sh create mode 100644 benchmarks/satcheck-precompiled/linuxlock/benchmark-config.sh create mode 100755 benchmarks/satcheck-precompiled/linuxlock/benchtso.sh create mode 100755 benchmarks/satcheck-precompiled/linuxlock/clean.sh create mode 100755 benchmarks/satcheck-precompiled/linuxlock/diff.sh create mode 100644 benchmarks/satcheck-precompiled/linuxlock/linuxlocks.c create mode 100644 benchmarks/satcheck-precompiled/linuxlock/linuxlocks_unannotated.c create mode 100644 benchmarks/satcheck-precompiled/linuxrwlock/.gitignore create mode 100755 benchmarks/satcheck-precompiled/linuxrwlock/bench.sh create mode 100644 benchmarks/satcheck-precompiled/linuxrwlock/benchmark-config.sh create mode 100755 benchmarks/satcheck-precompiled/linuxrwlock/benchtso.sh create mode 100755 benchmarks/satcheck-precompiled/linuxrwlock/clean.sh create mode 100755 benchmarks/satcheck-precompiled/linuxrwlock/diff.sh create mode 100644 benchmarks/satcheck-precompiled/linuxrwlock/linuxrwlocks.c create mode 100644 benchmarks/satcheck-precompiled/linuxrwlock/linuxrwlocks_unannotated.c create mode 100644 benchmarks/satcheck-precompiled/msqueueoffset/.gitignore create mode 100755 benchmarks/satcheck-precompiled/msqueueoffset/bench.sh create mode 100644 benchmarks/satcheck-precompiled/msqueueoffset/benchmark-config.sh create mode 100755 benchmarks/satcheck-precompiled/msqueueoffset/benchtso.sh create mode 100755 benchmarks/satcheck-precompiled/msqueueoffset/clean.sh create mode 100755 benchmarks/satcheck-precompiled/msqueueoffset/diff.sh create mode 100644 benchmarks/satcheck-precompiled/msqueueoffset/ms-queue-simple.c create mode 100644 benchmarks/satcheck-precompiled/msqueueoffset/ms-queue-simple.h create mode 100644 benchmarks/satcheck-precompiled/msqueueoffset/ms-queue-simple_unannotated.c create mode 100644 benchmarks/satcheck-precompiled/seqlock/.gitignore create mode 100755 benchmarks/satcheck-precompiled/seqlock/bench.sh create mode 100644 benchmarks/satcheck-precompiled/seqlock/benchmark-config.sh create mode 100755 benchmarks/satcheck-precompiled/seqlock/benchtso.sh create mode 100755 benchmarks/satcheck-precompiled/seqlock/clean.sh create mode 100755 benchmarks/satcheck-precompiled/seqlock/diff.sh create mode 100644 benchmarks/satcheck-precompiled/seqlock/seqlock.cc create mode 100644 benchmarks/satcheck-precompiled/seqlock/seqlock_unannotated.cc create mode 100644 benchmarks/satcheck/dekker/.gitignore create mode 100755 benchmarks/satcheck/dekker/bench.sh create mode 100644 benchmarks/satcheck/dekker/benchmark-config.sh create mode 100755 benchmarks/satcheck/dekker/benchtso.sh create mode 100755 benchmarks/satcheck/dekker/clean.sh create mode 100755 benchmarks/satcheck/dekker/compile.sh create mode 100644 benchmarks/satcheck/dekker/dekker-fences_unannotated.c create mode 100755 benchmarks/satcheck/dekker/diff.sh create mode 100644 benchmarks/satcheck/linuxlock/.gitignore create mode 100755 benchmarks/satcheck/linuxlock/bench.sh create mode 100644 benchmarks/satcheck/linuxlock/benchmark-config.sh create mode 100755 benchmarks/satcheck/linuxlock/benchtso.sh create mode 100755 benchmarks/satcheck/linuxlock/clean.sh create mode 100755 benchmarks/satcheck/linuxlock/compile.sh create mode 100755 benchmarks/satcheck/linuxlock/diff.sh create mode 100644 benchmarks/satcheck/linuxlock/linuxlocks_unannotated.c create mode 100644 benchmarks/satcheck/linuxrwlock/.gitignore create mode 100755 benchmarks/satcheck/linuxrwlock/bench.sh create mode 100644 benchmarks/satcheck/linuxrwlock/benchmark-config.sh create mode 100755 benchmarks/satcheck/linuxrwlock/benchtso.sh create mode 100755 benchmarks/satcheck/linuxrwlock/clean.sh create mode 100755 benchmarks/satcheck/linuxrwlock/compile.sh create mode 100755 benchmarks/satcheck/linuxrwlock/diff.sh create mode 100644 benchmarks/satcheck/linuxrwlock/linuxrwlocks_unannotated.c create mode 100644 benchmarks/satcheck/msqueueoffset/.gitignore create mode 100755 benchmarks/satcheck/msqueueoffset/bench.sh create mode 100644 benchmarks/satcheck/msqueueoffset/benchmark-config.sh create mode 100755 benchmarks/satcheck/msqueueoffset/benchtso.sh create mode 100755 benchmarks/satcheck/msqueueoffset/clean.sh create mode 100755 benchmarks/satcheck/msqueueoffset/compile.sh create mode 100755 benchmarks/satcheck/msqueueoffset/diff.sh create mode 100644 benchmarks/satcheck/msqueueoffset/ms-queue-simple.h create mode 100644 benchmarks/satcheck/msqueueoffset/ms-queue-simple_unannotated.c create mode 100644 benchmarks/satcheck/seqlock/.gitignore create mode 100755 benchmarks/satcheck/seqlock/bench.sh create mode 100644 benchmarks/satcheck/seqlock/benchmark-config.sh create mode 100755 benchmarks/satcheck/seqlock/benchtso.sh create mode 100755 benchmarks/satcheck/seqlock/clean.sh create mode 100755 benchmarks/satcheck/seqlock/compile.sh create mode 100755 benchmarks/satcheck/seqlock/diff.sh create mode 100644 benchmarks/satcheck/seqlock/seqlock_unannotated.cc create mode 100755 benchmarks/verifycompilesat create mode 100755 bin/annotate create mode 100644 branchrecord.cc create mode 100644 branchrecord.h create mode 100644 cgoal.cc create mode 100644 cgoal.h create mode 100644 change.cc create mode 100644 change.h create mode 100644 clang/.gitignore create mode 100644 clang/COPYING create mode 100644 clang/Makefile create mode 100644 clang/README.md create mode 100644 clang/multi-dep.txt create mode 100644 clang/src/add_mc2_annotations.cpp create mode 100644 clang/test/apr_1_unannotated.c create mode 100644 clang/test/apr_2_unannotated.c create mode 100644 clang/test/bitops.c create mode 100644 clang/test/bitops_unannotated.c create mode 100644 clang/test/linuxrwlocks.c create mode 100644 clang/test/linuxrwlocks_unannotated.c create mode 100644 clang/test/mcs-lock_unannotated.cc create mode 100644 clang/test/minimal-no-braces-if.c create mode 100644 clang/test/minimal-no-braces-if_unannotated.c create mode 100644 clang/test/ms-queue-simple-offset.c create mode 100644 clang/test/ms-queue-simple-offset_unannotated.c create mode 100644 clang/test/ms-queue-simple.c create mode 100644 clang/test/ms-queue-simple.h create mode 100644 clang/test/ms-queue-simple_manual.c create mode 100644 clang/test/ms-queue-simple_unannotated.c create mode 100644 clang/test/ms-queue_unannotated.c create mode 100644 clang/test/seqlock.c create mode 100644 clang/test/seqlock_raw_unannotated.c create mode 100644 clang/test/seqlock_unannotated.c create mode 100644 clang/test/spsc-queue_unannotated.cc create mode 100644 clang/test/userprog2_unannotated.c create mode 100644 clang/test/userprog_unannotated.c create mode 100644 clang/test/various-loads.c create mode 100644 clang/test/various-loads_unannotated.c create mode 100644 classlist.h create mode 100644 cmodelint.cc create mode 100644 common.cc create mode 100644 common.h create mode 100644 common.mk create mode 100644 config.h create mode 100644 constgen.cc create mode 100644 constgen.h create mode 100644 constraint.cc create mode 100644 constraint.h create mode 100644 context.cc create mode 100644 context.h create mode 100644 eprecord.cc create mode 100644 eprecord.h create mode 100644 epvalue.cc create mode 100644 epvalue.h create mode 100644 equalsrecord.cc create mode 100644 equalsrecord.h create mode 100644 execpoint.cc create mode 100644 execpoint.h create mode 100644 functionrecord.cc create mode 100644 functionrecord.h create mode 100644 hashset.h create mode 100644 hashtable.h create mode 100644 inc_solver.cc create mode 100644 inc_solver.h create mode 100644 include/atomic create mode 100644 include/cmodelint.h create mode 100644 include/condition_variable create mode 100644 include/cstdatomic create mode 100644 include/impatomic.h create mode 100644 include/libinterface.h create mode 100644 include/memoryorder.h create mode 100644 include/model-assert.h create mode 100644 include/modeltypes.h create mode 100644 include/mutex create mode 100644 include/stdatomic.h create mode 100644 include/threads.h create mode 100644 libinterface.cc create mode 100644 libthreads.cc create mode 100644 loadrf.cc create mode 100644 loadrf.h create mode 100644 main.cc create mode 100644 malloc.c create mode 100644 mcexecution.cc create mode 100644 mcexecution.h create mode 100644 mcschedule.cc create mode 100644 mcschedule.h create mode 100644 mcutil.h create mode 100644 model.cc create mode 100644 model.h create mode 100644 mymemory.cc create mode 100644 mymemory.h create mode 100644 notes create mode 100644 output.h create mode 100644 params.h create mode 100644 planner.cc create mode 100644 planner.h create mode 100755 run.sh create mode 100644 schedulebuilder.cc create mode 100644 schedulebuilder.h create mode 100644 snapshot-interface.cc create mode 100644 snapshot-interface.h create mode 100644 snapshot.cc create mode 100644 snapshot.h create mode 100644 solver_interface.h create mode 100644 stacktrace.h create mode 100644 stl-model.h create mode 100644 storeloadset.cc create mode 100644 storeloadset.h create mode 100644 test/Makefile create mode 100644 test/dekker-fences.c create mode 100644 test/function_microbenchmarks.c create mode 100644 test/linuxlock.c create mode 100644 test/load_in_if_cond.c create mode 100644 test/mcs-lock.cc create mode 100644 test/ms-queue-freelist.c create mode 100644 test/ms-queue-freelist.h create mode 100644 test/ms-queue.c create mode 100644 test/ms-queue.h create mode 100644 test/reference/README.md create mode 100644 test/reference/ms-queue-atomics.c create mode 100644 test/seqlock.c create mode 100644 test/seqlock2.cc create mode 100644 test/spsc-queue.cc create mode 100644 test/userprog.c create mode 100644 test/userprog2.c create mode 100644 test/userprog_pointers.c create mode 100644 threads-model.h create mode 100644 threads.cc create mode 100644 valuerecord.cc create mode 100644 valuerecord.h diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..ce85e5f --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1 @@ +((nil . ((indent-tabs-mode . t)))) \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..293af41 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# generic types +*.o +*.swp +*.swo +*.so +*~ +*.dot +.*.d +*.pdf + +# files in this directory +/tags +/doc/docs +/README.html diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/DEBUGGINGNOTES.txt b/DEBUGGINGNOTES.txt new file mode 100644 index 0000000..12c3eda --- /dev/null +++ b/DEBUGGINGNOTES.txt @@ -0,0 +1,8 @@ +To run inside MacOS under gdb you need: +set dont-handle-bad-access 1 +handle SIGBUS nostop noprint + +To run in Linux under gdb, use: +handle SIGSEGV nostop noprint + + diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..65c02c8 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,1801 @@ +# Doxyfile 1.8.0 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "MC2: A Model Checker for SC" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 5 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . include/ include/atomic include/condition_variable include/cstdatomic include/mutex + + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = malloc.c + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = . + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = docs + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..639f51a --- /dev/null +++ b/Makefile @@ -0,0 +1,94 @@ +include common.mk + +PHONY += directories +MKDIR_P = mkdir -p +TSO_DIR = build_tso +SC_DIR = build_sc + +CPP_SOURCES := mymemory.cc context.cc snapshot.cc snapshot-interface.cc libinterface.cc execpoint.cc main.cc cmodelint.cc eprecord.cc epvalue.cc mcexecution.cc model.cc libthreads.cc mcschedule.cc common.cc threads.cc planner.cc cgoal.cc change.cc constgen.cc constraint.cc branchrecord.cc valuerecord.cc storeloadset.cc functionrecord.cc loadrf.cc schedulebuilder.cc equalsrecord.cc inc_solver.cc +C_SOURCES := malloc.c + +TSO_OBJECTS := $(CPP_SOURCES:%.cc=$(TSO_DIR)/%.o) $(C_SOURCES:%.c=$(TSO_DIR)/%.o) +SC_OBJECTS := $(CPP_SOURCES:%.cc=$(SC_DIR)/%.o) $(C_SOURCES:%.c=$(SC_DIR)/%.o) + +CPPFLAGS += -Iinclude -I. +LDFLAGS := -ldl -lrt -rdynamic +SHARED := -shared + +# Mac OSX options +ifeq ($(UNAME), Darwin) +LDFLAGS := -ldl +SHARED := -Wl,-undefined,dynamic_lookup -dynamiclib +endif + +TESTS_DIR := test + +MARKDOWN := doc/Markdown/Markdown.pl + +all: directories $(TSO_LIB_SO) $(SC_LIB_SO) + +directories: ${TSO_DIR} ${SC_DIR} + +${TSO_DIR}: + ${MKDIR_P} ${TSO_DIR} + +${SC_DIR}: + ${MKDIR_P} ${SC_DIR} + +debug: CPPFLAGS += -DCONFIG_DEBUG +debug: all + +PHONY += docs +docs: *.c *.cc *.h + doxygen + +$(TSO_LIB_SO): $(TSO_OBJECTS) + $(CXX) -g $(SHARED) -o $(TSO_LIB_SO) $+ $(LDFLAGS) + +$(SC_LIB_SO): $(SC_OBJECTS) + $(CXX) -g $(SHARED) -o $(SC_LIB_SO) $+ $(LDFLAGS) + +${TSO_DIR}/%.o: %.c + $(CC) -fPIC -c $< -o $@ -DTSO -DMSPACES -DONLY_MSPACES -DHAVE_MMAP=0 $(CPPFLAGS) -Wno-unused-variable + +${TSO_DIR}/%.o: %.cc + $(CXX) -MMD -DTSO -MF $@.d -o $@ -fPIC -c $< $(CPPFLAGS) + +${SC_DIR}/%.o: %.c + $(CC) -fPIC -c $< -o $@ -DMSPACES -DONLY_MSPACES -DHAVE_MMAP=0 $(CPPFLAGS) -Wno-unused-variable + +${SC_DIR}/%.o: %.cc + $(CXX) -MMD -MF $@.d -fPIC -o $@ -c $< $(CPPFLAGS) + +%.pdf: %.dot + dot -Tpdf $< -o $@ + +-include $(TSO_OBJECTS:%=$TSO_DIR/.%.d) +-include $(SC_OBJECTS:%=$SC_DIR/.%.d) + +PHONY += clean +clean: + rm -f *.o *.so *.pdf *.dot dimacs.cnf dimacs.out + rm -rf $(TSO_DIR) $(SC_DIR) + $(MAKE) -C $(TESTS_DIR) clean + +PHONY += mrclean +mrclean: clean + rm -rf docs + +PHONY += tags +tags: + ctags -R + +PHONE += tests +tests: $(LIB_SO) + $(MAKE) -C $(TESTS_DIR) + +PHONY += pdfs +pdfs: $(patsubst %.dot,%.pdf,$(wildcard *.dot)) + +.PHONY: $(PHONY) + +# A 1-inch margin PDF generated by 'pandoc' +%.pdf: %.md + pandoc -o $@ $< -V header-includes='\usepackage[margin=1in]{geometry}' diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore new file mode 100644 index 0000000..114a7ac --- /dev/null +++ b/benchmarks/.gitignore @@ -0,0 +1,4 @@ +log +logall + + diff --git a/benchmarks/cdschecker/dekker/bench.sh b/benchmarks/cdschecker/dekker/bench.sh new file mode 100755 index 0000000..79f6f7a --- /dev/null +++ b/benchmarks/cdschecker/dekker/bench.sh @@ -0,0 +1,10 @@ +#!/bin/bash +source ../path.sh +for i in 1 2 3 4 5 6 +do +echo size= $i +cat dekker-fences.cc.in | sed s/PROBLEMSIZE/$i/ > dekker-fences.cc +g++ dekker-fences.cc -O3 -I$CDSCHECKERDIR/include -L$CDSCHECKERDIR -lmodel -o dekker-fences.o +export LD_LIBRARY_PATH=$CDSCHECKERDIR +time ./dekker-fences.o -Y +done diff --git a/benchmarks/cdschecker/dekker/dekker-fences.cc.in b/benchmarks/cdschecker/dekker/dekker-fences.cc.in new file mode 100644 index 0000000..72c30a9 --- /dev/null +++ b/benchmarks/cdschecker/dekker/dekker-fences.cc.in @@ -0,0 +1,88 @@ +/* + * Dekker's critical section algorithm, implemented with fences. + * + * URL: + * http://www.justsoftwaresolutions.co.uk/threading/ + */ + +#include +#include + +#include "librace.h" + +std::atomic flag0, flag1; +std::atomic turn; +std::atomic var; + +void p0() { + flag0.store(true); + + while (flag1.load()) { + if (turn.load() !=0) + { + flag0.store(false); + while (turn.load() != 0) { + thrd_yield(); + } + flag0.store(true); + } else + thrd_yield(); + } + + // critical section + var.store(1); + + turn.store(1); + flag0.store(false); +} + +void p1() { + flag1.store(true); + + while (flag0.load()) { + if (turn.load() != 1) { + flag1.store(false); + while (turn.load() != 1) { + thrd_yield(); + } + flag1.store(true); + } else + thrd_yield(); + } + + // critical section + var.store(2); + + turn.store(0); + flag1.store(false); +} + +void p0l(void *arg) { + int i; + for(i=0;i linuxlocks.c +gcc linuxlocks.c -O3 -I$CDSCHECKERDIR/include -L$CDSCHECKERDIR -lmodel -o linuxlocks.o +export LD_LIBRARY_PATH=$CDSCHECKERDIR +time ./linuxlocks.o +done \ No newline at end of file diff --git a/benchmarks/cdschecker/linuxlock/linuxlocks.c.in b/benchmarks/cdschecker/linuxlock/linuxlocks.c.in new file mode 100644 index 0000000..3b62f4b --- /dev/null +++ b/benchmarks/cdschecker/linuxlock/linuxlocks.c.in @@ -0,0 +1,54 @@ +#include +#include +#include + + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + atomic_int lock; +} lock_t; + +static inline bool write_trylock(lock_t *rw) { + int oldvalue=0; + return atomic_compare_exchange_strong(&rw->lock, &oldvalue, 1); +} + + +static inline void write_unlock(lock_t *rw) +{ + atomic_store(&rw->lock, 0); +} + +lock_t mylock; +int shareddata; + +static void foo() { + bool flag=write_trylock(&mylock); + if (flag) { + write_unlock(&mylock); + } +} + +static void a(void *obj) +{ + int i; + for(i=0;i linuxrwlocks.c +gcc linuxrwlocks.c -O3 -I$CDSCHECKERDIR/include -L$CDSCHECKERDIR -lmodel -o linuxrwlocks.o +export LD_LIBRARY_PATH=$CDSCHECKERDIR +time ./linuxrwlocks.o +done \ No newline at end of file diff --git a/benchmarks/cdschecker/linuxrwlock/linuxrwlocks.c.in b/benchmarks/cdschecker/linuxrwlock/linuxrwlocks.c.in new file mode 100644 index 0000000..5fa4a08 --- /dev/null +++ b/benchmarks/cdschecker/linuxrwlock/linuxrwlocks.c.in @@ -0,0 +1,56 @@ +#include +#include +#include + +#include "librace.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + atomic_int lock; +} rwlock_t; + +static inline int write_trylock(rwlock_t *rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_seq_cst); + if (priorvalue == RW_LOCK_BIAS) + return 1; + + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_seq_cst); + return 0; +} + +static inline void write_unlock(rwlock_t *rw) +{ + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_seq_cst); +} + +rwlock_t mylock; +int shareddata; + +static void a(void *obj) { + int i; + for(i = 0; i < PROBLEMSIZE; i++) { + if (write_trylock(&mylock)) { + write_unlock(&mylock); + } + } +} + +int user_main(int argc, char **argv) +{ + thrd_t t1, t2; + atomic_init(&mylock.lock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} diff --git a/benchmarks/cdschecker/msqueue/bench.sh b/benchmarks/cdschecker/msqueue/bench.sh new file mode 100755 index 0000000..790d8c7 --- /dev/null +++ b/benchmarks/cdschecker/msqueue/bench.sh @@ -0,0 +1,10 @@ +#!/bin/bash +source ../path.sh +for i in 1 2 3 4 5 6 7 8 +do +echo size= $i +cat ms-queue_simple.c.in | sed s/PROBLEMSIZE/$i/ > ms-queue_simple.c +gcc ms-queue_simple.c -O3 -I$CDSCHECKERDIR/include -L$CDSCHECKERDIR -lmodel -o ms-queue_simple.o +export LD_LIBRARY_PATH=$CDSCHECKERDIR +time ./ms-queue_simple.o +done diff --git a/benchmarks/cdschecker/msqueue/ms-queue_simple.c.in b/benchmarks/cdschecker/msqueue/ms-queue_simple.c.in new file mode 100644 index 0000000..8e0e463 --- /dev/null +++ b/benchmarks/cdschecker/msqueue/ms-queue_simple.c.in @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#define true 1 +#define false 0 + + +#include "ms-queue_simple.h" + +queue_t queue; +void init_queue(queue_t *q, int num_threads); +void enqueue(queue_t *q, unsigned int val); +bool dequeue(queue_t *q, unsigned int *retVal); + +void init_queue(queue_t *q, int num_threads) { + struct node *newnode=malloc(sizeof (struct node)); + atomic_store(&newnode->value, 0); + + atomic_store(&newnode->next, (uintptr_t) NULL); + /* initialize queue */ + atomic_store(&q->head, newnode); + + atomic_store(&q->tail, newnode); +} + +void enqueue(queue_t *q, unsigned int val) { + struct node *tail; + struct node * node_ptr = malloc(sizeof(struct node)); + atomic_store(&node_ptr->value, val); + + atomic_store(&node_ptr->next, NULL); + + while (true) { + tail = (struct node *) atomic_load(&q->tail); + + struct node * next = (struct node *) atomic_load( &tail->next); + + struct node * qtail = (struct node *) atomic_load(&q->tail); + if (tail == qtail) { + + if (next == NULL) { + if (atomic_compare_exchange_strong( & tail->next,& next, node_ptr)) + break; + } + } + struct node * new_tailptr = (struct node *)atomic_load( &tail->next); + atomic_compare_exchange_strong(&q->tail, & tail, new_tailptr); + thrd_yield(); + } + atomic_compare_exchange_strong(&q->tail, & tail, node_ptr); +} + +bool dequeue(queue_t *q, unsigned int *retVal) { + while (true) { + struct node * head = (struct node *) atomic_load(&q->head); + struct node * tail = (struct node *) atomic_load(&q->tail); + struct node * next = (struct node *) atomic_load(&head->next); + + int t = ((struct node *) atomic_load(&q->head)) == head; + if (t) { + if (head == tail) { + + if (next == NULL) { + return false; // NULL + } + atomic_compare_exchange_strong(&q->tail, & tail, next); + thrd_yield(); + } else { + *retVal = atomic_load(&next->value); + if (atomic_compare_exchange_strong(&q->head,& head, next)) { + return true; + } else { + thrd_yield(); + } + } + } + } +} + +static void e(void *param) +{ + int i; + for(i=0;i seqlock.c +gcc seqlock.c -O3 -I$CDSCHECKERDIR/include -L$CDSCHECKERDIR -lmodel -o seqlock.o +export LD_LIBRARY_PATH=$CDSCHECKERDIR +time ./seqlock.o -Y +done \ No newline at end of file diff --git a/benchmarks/cdschecker/seqlock/seqlock.c.in b/benchmarks/cdschecker/seqlock/seqlock.c.in new file mode 100644 index 0000000..52e4d8d --- /dev/null +++ b/benchmarks/cdschecker/seqlock/seqlock.c.in @@ -0,0 +1,77 @@ +#include +#include +#include +#include "threads.h" + +atomic_int _seq; +atomic_int _data; + +void seqlock_init() { + atomic_store(&_seq, 0); + atomic_store(&_data, 0); +} + +int seqlock_read() { + int old_seq = atomic_load(&_seq); + + int c0 = (old_seq % 2 == 1); + if (!c0) { + int res = atomic_load(&_data); + int seq = atomic_load(&_seq); + + int c1; + c1 = seq == old_seq; + if (c1) { // relaxed + return res; + } + } + return -1; +} + +int seqlock_write(int new_data) { + int old_seq = atomic_load(&_seq); + int c2 = (old_seq % 2 == 1); + if (!c2) { + int new_seq = old_seq + 1; + if (atomic_compare_exchange_strong(&_seq, &old_seq, new_seq)) { + atomic_store(&_data, new_data); + atomic_fetch_add(&_seq, 1); + return true; + } + } + return false; +} + +static void a(void *obj) { + int i; + for(i=0;i dekker-fences.c +c2lsl.exe dekker-fences.c dekker-fences.lsl +time checkfence -i -a memmodel=sc dekker-fences.lsl dekkertests.lsl >> runlog +echo With loop bounds +time checkfence -a memmodel=sc dekker-fences.lsl dekkertests.lsl T0.prn >> runlog +done + + diff --git a/benchmarks/checkfence/dekker/clean.sh b/benchmarks/checkfence/dekker/clean.sh new file mode 100755 index 0000000..1e76a49 --- /dev/null +++ b/benchmarks/checkfence/dekker/clean.sh @@ -0,0 +1,8 @@ +#!/bin/bash +rm T0.*.htm +rm T0.bsc* +rm T0.prn +rm dekker-fences.c +rm dekker-fences.i +rm dekker-fences.lsl +rm runlog diff --git a/benchmarks/checkfence/dekker/dekker-fences.c.in b/benchmarks/checkfence/dekker/dekker-fences.c.in new file mode 100644 index 0000000..877856a --- /dev/null +++ b/benchmarks/checkfence/dekker/dekker-fences.c.in @@ -0,0 +1,75 @@ +#include "lsl_protos.h" +/* + * Dekker's critical section algorithm, implemented with fences. + * + * URL: + * http://www.justsoftwaresolutions.co.uk/threading/ + */ + + +int flag0, flag1; +int turn; + +int var = 0; + +void p0() { + flag0 = 1; + + while (flag1) { + if (turn != 0) { + flag0=0; + while (turn != 0) { + lsl_assume(false); + } + flag0=1; + } else { + lsl_assume(false); + } + } + + // critical section + var=1; + + turn=1; + flag0=0; +} + +void p1() { + flag1=1; + + while (flag0) { + if (turn != 1) { + flag1=0; + while (turn!=1) { + lsl_assume(false); + } + flag1=1; + } else { + lsl_assume(false); + } + } + // critical section + var=2; + turn=0; + flag1=0; +} + +void init() { + flag0=0; + flag1=0; + turn=0; +} + +void p0l() { + int i; + for(i=0;i linuxrwlocksbig.c +c2lsl.exe lin_harness.c lin_harness.lsl +time checkfence -i -a memmodel=sc lin_harness.lsl locktests.lsl >> runlog +echo With loop bounds +time checkfence -a memmodel=sc lin_harness.lsl locktests.lsl T0.prn >> runlog +done + + diff --git a/benchmarks/checkfence/linuxlock/clean.sh b/benchmarks/checkfence/linuxlock/clean.sh new file mode 100755 index 0000000..e431fb1 --- /dev/null +++ b/benchmarks/checkfence/linuxlock/clean.sh @@ -0,0 +1,8 @@ +#!/bin/bash +rm T0.*.htm +rm T0.bsc* +rm T0.prn +rm lin_harness.i +rm lin_harness.lsl +rm linuxrwlocksbig.c +rm runlog \ No newline at end of file diff --git a/benchmarks/checkfence/linuxlock/lin_harness.c b/benchmarks/checkfence/linuxlock/lin_harness.c new file mode 100755 index 0000000..592dc31 --- /dev/null +++ b/benchmarks/checkfence/linuxlock/lin_harness.c @@ -0,0 +1,18 @@ +#include "linuxrwlocksbig.c" + +/* ---- harness for queue ---- */ + +rwlock_t mylock; + +void i() +{ + lock_init(&mylock); +} +void e() +{ + bar(&mylock); +} +void d() +{ + bar(&mylock); +} diff --git a/benchmarks/checkfence/linuxlock/linuxrwlocksbig.c.in b/benchmarks/checkfence/linuxlock/linuxrwlocksbig.c.in new file mode 100644 index 0000000..3e3cf11 --- /dev/null +++ b/benchmarks/checkfence/linuxlock/linuxrwlocksbig.c.in @@ -0,0 +1,38 @@ +#include "lsl_protos.h" + + +#define RW_LOCK_BIAS 0x001000 + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef struct rwlock { + int lock; +} rwlock_t; + + +void lock_init(rwlock_t *lock) { + lock->lock=0; +} + +int write_trylock(rwlock_t *rw) { + return lsl_cas_32(&rw->lock, 0, 1); +} + + +void write_unlock(rwlock_t *rw) { + rw->lock=0; +} + +void foo(rwlock_t *mylock) { + int flag=write_trylock(mylock); + if (flag) { + write_unlock(mylock); + } +} + +void bar(rwlock_t *mylock) +{ + for(int i=0;i llock.c +#c2lsl.exe add_harness.c add_harness.lsl +#time checkfence -i -a memmodel=sc add_harness.lsl locktests.lsl >> runlog +#echo Hard loop bounds +#time checkfence -a memmodel=sc add_harness.lsl locktests.lsl T0.prn >> runlog +#done + + +for i in 1 2 3 4 5 6 7 8 9 10 15 20 30 +do +echo bias set to 100 +echo size=$i +cat llock.c.in | sed s/PROBLEMSIZE/$i/ |sed s/TUNELOCK/100/ > llock.c +c2lsl.exe add_harness.c add_harness.lsl +time checkfence -i -a memmodel=sc add_harness.lsl locktests.lsl >> runlog +echo Hard loop bounds +time checkfence -a memmodel=sc add_harness.lsl locktests.lsl T0.prn >> runlog +done diff --git a/benchmarks/checkfence/linuxrwlock/clean.sh b/benchmarks/checkfence/linuxrwlock/clean.sh new file mode 100755 index 0000000..fdb1b8e --- /dev/null +++ b/benchmarks/checkfence/linuxrwlock/clean.sh @@ -0,0 +1,8 @@ +#!/bin/bash +rm T0.*.htm +rm T0.bsc* +rm T0.prn +rm add_harness.i +rm add_harness.lsl +rm llock.c +rm runlog \ No newline at end of file diff --git a/benchmarks/checkfence/linuxrwlock/llock.c.in b/benchmarks/checkfence/linuxrwlock/llock.c.in new file mode 100644 index 0000000..dd44768 --- /dev/null +++ b/benchmarks/checkfence/linuxrwlock/llock.c.in @@ -0,0 +1,53 @@ +#include "lsl_protos.h" + + +#define RW_LOCK_BIAS TUNELOCK + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef struct rwlock { + int lock; +} rwlock_t; + + +void lock_init(rwlock_t *lock) { + lock->lock=RW_LOCK_BIAS; +} + +int add(int * ptr, int val) { + return lsl_add_32(ptr, val); +} + +int sub(int * ptr, int val) { + return lsl_add_32(ptr, -val); +} + +int write_trylock(rwlock_t *rw) { + int priorvalue=sub(&rw->lock, RW_LOCK_BIAS); + + int flag=priorvalue != RW_LOCK_BIAS; + + if (!flag) { + add(&rw->lock, RW_LOCK_BIAS); + } + + return flag; +} + + +void write_unlock(rwlock_t *rw) { + add(&rw->lock, RW_LOCK_BIAS); +} + +void foo(rwlock_t *mylock) { + int flag=write_trylock(mylock); + if (flag) { + write_unlock(mylock); + } +} + +void bar(rwlock_t *mylock) { + for(int i=0;i msn_harness.c +c2lsl.exe msn_harness.c msn_harness.lsl +time checkfence -i -a memmodel=sc msn_harness.lsl tests.lsl >> runlog +echo With loop bounds +time checkfence -a memmodel=sc msn_harness.lsl tests.lsl T0.prn >> runlog +done + + + diff --git a/benchmarks/checkfence/msqueue/clean.sh b/benchmarks/checkfence/msqueue/clean.sh new file mode 100755 index 0000000..442a691 --- /dev/null +++ b/benchmarks/checkfence/msqueue/clean.sh @@ -0,0 +1,8 @@ +#!/bin/bash +rm T0.*.htm +rm T0.bsc* +rm T0.prn +rm msn_harness.i +rm msn_harness.lsl +rm msn_harness.c +rm runlog \ No newline at end of file diff --git a/benchmarks/checkfence/msqueue/msn.c b/benchmarks/checkfence/msqueue/msn.c new file mode 100755 index 0000000..252e9fc --- /dev/null +++ b/benchmarks/checkfence/msqueue/msn.c @@ -0,0 +1,72 @@ +#include "lsl_protos.h" + +/* ---- data types ---- */ + +typedef int value_t; + +typedef struct node { + struct node *next; + value_t value; +} node_t; + +typedef struct queue { + node_t *head; + node_t *tail; +} queue_t; + +/* ---- operations ---- */ + +void init_queue(queue_t *queue) +{ + node_t *node = lsl_malloc_noreuse(sizeof(node_t)); + node->next = 0; + queue->head = queue->tail = node; +} + +void enqueue(queue_t *queue, value_t value) +{ + node_t *node; + node_t *tail; + node_t *next; + + node = lsl_malloc_noreuse(sizeof(node_t)); + node->value = value; + node->next = 0; + while (true) { + tail = queue->tail; + next = tail->next; + if (tail == queue->tail) + if (next == 0) { + if (lsl_cas_64(&tail->next, next, node)) + break; + } else + lsl_cas_ptr(&queue->tail, tail, next); + } + lsl_cas_ptr(&queue->tail, tail, node); +} + +boolean_t dequeue(queue_t *queue, value_t *pvalue) +{ + node_t *head; + node_t *tail; + node_t *next; + + while (true) { + head = queue->head; + tail = queue->tail; + next = head->next; + if (head == queue->head) { + if (head == tail) { + if (next == 0) + return false; + lsl_cas_ptr(&queue->tail, tail, next); + } else { + *pvalue = next->value; + if (lsl_cas_ptr(&queue->head, head, next)) + break; + } + } + } + lsl_free_noreuse(head); + return true; +} diff --git a/benchmarks/checkfence/msqueue/msn_harness.c.in b/benchmarks/checkfence/msqueue/msn_harness.c.in new file mode 100755 index 0000000..69310eb --- /dev/null +++ b/benchmarks/checkfence/msqueue/msn_harness.c.in @@ -0,0 +1,21 @@ +#include "msn.c" + +queue_t queue; + +void i() +{ + init_queue(&queue); +} +void e() +{ + value_t val = 1; + for(int i=0;i seqlock.c +c2lsl.exe seqlock.c seqlock.lsl +time checkfence -i -a memmodel=sc seqlock.lsl seqtests.lsl >> runlog +echo Hard coded loop bound +time checkfence -a memmodel=sc seqlock.lsl seqtests.lsl T0.prn >> runlog +done diff --git a/benchmarks/checkfence/seqlock/clean.sh b/benchmarks/checkfence/seqlock/clean.sh new file mode 100755 index 0000000..368ffa9 --- /dev/null +++ b/benchmarks/checkfence/seqlock/clean.sh @@ -0,0 +1,8 @@ +#!/bin/bash +rm T0.*.htm +rm T0.bsc* +rm T0.prn +rm seqlock.c +rm seqlock.lsl +rm seqlock.i +rm runlog \ No newline at end of file diff --git a/benchmarks/checkfence/seqlock/seqlock.c.in b/benchmarks/checkfence/seqlock/seqlock.c.in new file mode 100644 index 0000000..e9690b9 --- /dev/null +++ b/benchmarks/checkfence/seqlock/seqlock.c.in @@ -0,0 +1,62 @@ +#include "lsl_protos.h" + +int _seq; +int _data; + +void seqlock_init() { + _seq=0; + _data=0; +} + +int seqlock_read() { + int old_seq = _seq; + + int c0 = (old_seq % 2 == 1); + if (!c0) { + int res = _data; + int seq = _seq; + + int c1; + c1 = seq == old_seq; + if (c1) { // relaxed + return res; + } + } + return -1; +} + + +int seqlock_write(int new_data) { + int old_seq = _seq; + int c2 = (old_seq % 2 == 1); + if (!c2) { + int new_seq = old_seq + 1; + if (lsl_cas_32(&_seq, old_seq, new_seq)) { + _data = new_data; + lsl_add_32(&_seq, 1); + return 1; + } + } + return 0; +} + +void a() { + for(int i=0;i +#include + +std::atomic flag0, flag1; +std::atomic turn; +std::atomic var; + +extern "C" { +void __VERIFIER_assume(int b); +} + +void p0() { + flag0.store(true, std::memory_order_relaxed); + + while (flag1.load()) { + if (turn.load() !=0) + { + flag0.store(false, std::memory_order_relaxed); + while (turn.load() != 0) { + __VERIFIER_assume(0); + //pthread_yield(); + } + flag0.store(true, std::memory_order_relaxed); + } else + __VERIFIER_assume(0); + ; + // pthread_yield(); + } + + // critical section + var.store(1, std::memory_order_relaxed); + + turn.store(1, std::memory_order_relaxed); + flag0.store(false, std::memory_order_relaxed); +} + +void p1() { + flag1.store(true, std::memory_order_relaxed); + + while (flag0.load()) { + if (turn.load() != 1) { + flag1.store(false, std::memory_order_relaxed); + while (turn.load() != 1) { + __VERIFIER_assume(0); + //pthread_yield(); + } + flag1.store(true, std::memory_order_relaxed); + } else + __VERIFIER_assume(0); + ;//pthread_yield(); + } + + // critical section + var.store(2, std::memory_order_relaxed); + + turn.store(0, std::memory_order_relaxed); + flag1.store(false, std::memory_order_relaxed); +} + +void * p0l(void *arg) { +problemsize p0(); + return NULL; +} + +void * p1l(void *arg) { +problemsize p1(); + return NULL; +} + +int main(int argc, char **argv) +{ + pthread_t a, b; + + flag0 = false; + flag1 = false; + turn = 0; + var=0; + + pthread_create(&a, 0, p0l, NULL); + pthread_create(&b, 0, p1l, NULL); + + pthread_join(a, 0); + pthread_join(b, 0); + + return 0; +} diff --git a/benchmarks/nidhugg/linuxlock/bench.sh b/benchmarks/nidhugg/linuxlock/bench.sh new file mode 100755 index 0000000..8c9404b --- /dev/null +++ b/benchmarks/nidhugg/linuxlock/bench.sh @@ -0,0 +1,10 @@ +#!/bin/bash +source ../path.sh +export PATH=$PATH:$NIDHUGG/bin/ + +for i in 1 2 3 4 5 6 7 8 9 +do +echo size= $i +java -cp .. transform $i linuxlocks.c.in linuxlocks.cc +time nidhuggc -O3 -std=c++11 -- -sc ./linuxlocks.cc +done diff --git a/benchmarks/nidhugg/linuxlock/benchtso.sh b/benchmarks/nidhugg/linuxlock/benchtso.sh new file mode 100755 index 0000000..a92b517 --- /dev/null +++ b/benchmarks/nidhugg/linuxlock/benchtso.sh @@ -0,0 +1,10 @@ +#!/bin/bash +source ../path.sh +export PATH=$PATH:$NIDHUGG/bin/ + +for i in 1 2 3 4 5 6 7 8 9 +do +echo size= $i +java -cp .. transform $i linuxlocks.c.in linuxlocks.cc +time nidhuggc -O3 -std=c++11 -- -tso ./linuxlocks.cc +done diff --git a/benchmarks/nidhugg/linuxlock/linuxlocks.c.in b/benchmarks/nidhugg/linuxlock/linuxlocks.c.in new file mode 100644 index 0000000..3929127 --- /dev/null +++ b/benchmarks/nidhugg/linuxlock/linuxlocks.c.in @@ -0,0 +1,55 @@ +#include +#include +#include + + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + std::atomic lock; +} lock_t; + +static inline bool write_trylock(lock_t *rw) { + int oldvalue=0; + // return std::atomic_compare_exchange_strong(&rw->lock, &oldvalue, 1); + return rw->lock.compare_exchange_strong(oldvalue, 1); +} + + +static inline void write_unlock(lock_t *rw) +{ + atomic_store_explicit(&rw->lock, 0, std::memory_order_release); +} + +lock_t mylock; +int shareddata; + +static void foo() { + bool flag=write_trylock(&mylock); + if (flag) { + write_unlock(&mylock); + } +} + +void * a(void *obj) +{ + int i; +problemsize foo(); + return NULL; +} + +int main(int argc, char **argv) +{ + pthread_t t1, t2; + mylock.lock=0; + + + pthread_create(&t1, 0, a, NULL); + pthread_create(&t2, 0, a, NULL); + + pthread_join(t1, 0); + pthread_join(t2, 0); + + return 0; +} diff --git a/benchmarks/nidhugg/linuxrwlock/bench.sh b/benchmarks/nidhugg/linuxrwlock/bench.sh new file mode 100755 index 0000000..5b70978 --- /dev/null +++ b/benchmarks/nidhugg/linuxrwlock/bench.sh @@ -0,0 +1,9 @@ +#!/bin/bash +source ../path.sh +export PATH=$PATH:$NIDHUGG/bin/ +for i in 1 2 3 4 5 6 7 +do +echo size= $i +java -cp .. transform $i linuxrwlocks.c.in linuxrwlocks.cc +time nidhuggc -O3 -std=c++11 -- -sc ./linuxrwlocks.cc +done diff --git a/benchmarks/nidhugg/linuxrwlock/benchtso.sh b/benchmarks/nidhugg/linuxrwlock/benchtso.sh new file mode 100755 index 0000000..14c6cb2 --- /dev/null +++ b/benchmarks/nidhugg/linuxrwlock/benchtso.sh @@ -0,0 +1,9 @@ +#!/bin/bash +source ../path.sh +export PATH=$PATH:$NIDHUGG/bin/ +for i in 1 2 3 4 5 6 7 +do +echo size= $i +java -cp .. transform $i linuxrwlocks.c.in linuxrwlocks.cc +time nidhuggc -O3 -std=c++11 -- -tso ./linuxrwlocks.cc +done diff --git a/benchmarks/nidhugg/linuxrwlock/linuxrwlocks.c.in b/benchmarks/nidhugg/linuxrwlock/linuxrwlocks.c.in new file mode 100644 index 0000000..78c9423 --- /dev/null +++ b/benchmarks/nidhugg/linuxrwlock/linuxrwlocks.c.in @@ -0,0 +1,51 @@ +#include +#include +#include + + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + std::atomic lock; +} rwlock_t; + +static inline int write_trylock(rwlock_t *rw) +{ + int priorvalue = atomic_fetch_sub(&rw->lock, RW_LOCK_BIAS); + if (priorvalue == RW_LOCK_BIAS) + return 1; + + atomic_fetch_add(&rw->lock, RW_LOCK_BIAS); + return 0; +} + +static inline void write_unlock(rwlock_t *rw) +{ + atomic_fetch_add(&rw->lock, RW_LOCK_BIAS); +} + +rwlock_t mylock; +int shareddata; + +void * a(void *obj) { +problemsize if (write_trylock(&mylock)) {write_unlock(&mylock);} + return NULL; +} + +int main(int argc, char **argv) +{ + pthread_t t1, t2; + mylock.lock = RW_LOCK_BIAS; + + pthread_create(&t1, 0, &a, NULL); + pthread_create(&t2, 0, &a, NULL); + + pthread_join(t1, 0); + pthread_join(t2, 0); + + return 0; +} diff --git a/benchmarks/nidhugg/msqueue/bench.sh b/benchmarks/nidhugg/msqueue/bench.sh new file mode 100755 index 0000000..0cd404c --- /dev/null +++ b/benchmarks/nidhugg/msqueue/bench.sh @@ -0,0 +1,10 @@ +#!/bin/bash +source ../path.sh +export PATH=$PATH:$NIDHUGG/bin/ + +for i in 1 2 3 4 5 6 7 8 +do +echo size= $i +java -cp .. transform $i ms-queue_simple.c.in ms-queue_simple.cc +time nidhuggc -O3 -std=c++11 -- -sc ./ms-queue_simple.cc +done diff --git a/benchmarks/nidhugg/msqueue/benchtso.sh b/benchmarks/nidhugg/msqueue/benchtso.sh new file mode 100755 index 0000000..14e688b --- /dev/null +++ b/benchmarks/nidhugg/msqueue/benchtso.sh @@ -0,0 +1,10 @@ +#!/bin/bash +source ../path.sh +export PATH=$PATH:$NIDHUGG/bin/ + +for i in 1 2 3 4 5 6 7 8 +do +echo size= $i +java -cp .. transform $i ms-queue_simple.c.in ms-queue_simple.cc +time nidhuggc -O3 -std=c++11 -- -tso ./ms-queue_simple.cc +done diff --git a/benchmarks/nidhugg/msqueue/ms-queue_simple.c.in b/benchmarks/nidhugg/msqueue/ms-queue_simple.c.in new file mode 100644 index 0000000..384e581 --- /dev/null +++ b/benchmarks/nidhugg/msqueue/ms-queue_simple.c.in @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#define true 1 +#define false 0 + + +#include "ms-queue_simple.h" + +queue_t queue; +void init_queue(queue_t *q, int num_threads); +void enqueue(queue_t *q, int val); +bool dequeue(queue_t *q, int *retVal); + +void init_queue(queue_t *q, int num_threads) { + struct node *newnode=(struct node *) malloc(sizeof (struct node)); + atomic_store_explicit(&newnode->value, 0, std::memory_order_release); + + newnode->next.store(NULL, std::memory_order_release); + /* initialize queue */ + q->head.store(newnode, std::memory_order_release); + + q->tail.store( newnode, std::memory_order_release); +} + +void enqueue(queue_t *q, int val) { + struct node *tail; + struct node * node_ptr = (struct node *) malloc(sizeof(struct node)); + atomic_store_explicit(&node_ptr->value, val, std::memory_order_release); + + node_ptr->next.store(NULL, std::memory_order_release); + + while (true) { + tail = (struct node *) atomic_load(&q->tail); + + struct node * next = (struct node *) atomic_load( &tail->next); + + struct node * qtail = (struct node *) atomic_load(&q->tail); + if (tail == qtail) { + + if (next == NULL) { + if (atomic_compare_exchange_strong( & tail->next,& next, node_ptr)) + break; + } + } + struct node * new_tailptr = (struct node *)atomic_load( &tail->next); + atomic_compare_exchange_strong(&q->tail, & tail, new_tailptr); + //thrd_yield(); + } + atomic_compare_exchange_strong(&q->tail, & tail, node_ptr); +} + +bool dequeue(queue_t *q, int *retVal) { + while (true) { + struct node * head = (struct node *) atomic_load(&q->head); + struct node * tail = (struct node *) atomic_load(&q->tail); + struct node * next = (struct node *) atomic_load(&head->next); + + int t = ((struct node *) atomic_load(&q->head)) == head; + if (t) { + if (head == tail) { + + if (next == NULL) { + return false; // NULL + } + atomic_compare_exchange_strong(&q->tail, & tail, next); + //thrd_yield(); + } else { + *retVal = atomic_load(&next->value); + if (atomic_compare_exchange_strong(&q->head,& head, next)) { + return true; + } else { + ;//thrd_yield(); + } + } + } + } +} + +void * e(void *param) +{ + problemsize enqueue(&queue, 1); + return NULL; +} + +void * d(void *param) { + int val; + problemsize dequeue(&queue, &val); + return NULL; +} + +int main(int argc, char **argv) +{ + // MODEL_ASSERT(queue); + + init_queue(&queue, 2); + + pthread_t t1,t2; + pthread_create(&t1, 0, e, NULL); + pthread_create(&t2, 0, d, NULL); + + + return 0; +} diff --git a/benchmarks/nidhugg/msqueue/ms-queue_simple.h b/benchmarks/nidhugg/msqueue/ms-queue_simple.h new file mode 100644 index 0000000..f768163 --- /dev/null +++ b/benchmarks/nidhugg/msqueue/ms-queue_simple.h @@ -0,0 +1,15 @@ +typedef struct node { + std::atomic value; + std::atomic next; +} node_t; + +typedef struct { + std::atomic head; + std::atomic tail; +} queue_t; + +//void init_queue(queue_t *q, int num_threads); +//void enqueue(queue_t *q, unsigned int val); +//bool dequeue(queue_t *q, unsigned int *retVal); +int get_thread_num(); + diff --git a/benchmarks/nidhugg/path.sh b/benchmarks/nidhugg/path.sh new file mode 100755 index 0000000..6c9a176 --- /dev/null +++ b/benchmarks/nidhugg/path.sh @@ -0,0 +1 @@ +NIDHUGG=~/nidhugg/ diff --git a/benchmarks/nidhugg/seqlock/bench.sh b/benchmarks/nidhugg/seqlock/bench.sh new file mode 100755 index 0000000..020ab1e --- /dev/null +++ b/benchmarks/nidhugg/seqlock/bench.sh @@ -0,0 +1,10 @@ +#!/bin/bash +source ../path.sh +export PATH=$PATH:$NIDHUGG/bin/ + +for i in 1 2 3 +do +echo size= $i +java -cp .. transform $i seqlock.c.in seqlock.cc +time nidhuggc -O3 -std=c++11 -- -sc ./seqlock.cc +done diff --git a/benchmarks/nidhugg/seqlock/benchtso.sh b/benchmarks/nidhugg/seqlock/benchtso.sh new file mode 100755 index 0000000..da2381b --- /dev/null +++ b/benchmarks/nidhugg/seqlock/benchtso.sh @@ -0,0 +1,10 @@ +0#!/bin/bash +source ../path.sh +export PATH=$PATH:$NIDHUGG/bin/ + +for i in 1 2 3 +do +echo size= $i +java -cp .. transform $i seqlock.c.in seqlock.cc +time nidhuggc -O3 -std=c++11 -- -tso ./seqlock.cc +done diff --git a/benchmarks/nidhugg/seqlock/seqlock.c.in b/benchmarks/nidhugg/seqlock/seqlock.c.in new file mode 100644 index 0000000..da76713 --- /dev/null +++ b/benchmarks/nidhugg/seqlock/seqlock.c.in @@ -0,0 +1,73 @@ +#include +#include +#include + +std::atomic _seq; +std::atomic _data; + +void seqlock_init() { + atomic_store_explicit(&_seq, 0, std::memory_order_release); + atomic_store_explicit(&_data, 0, std::memory_order_release); +} + +int seqlock_read() { + int old_seq = atomic_load(&_seq); + + int c0 = (old_seq % 2 == 1); + if (!c0) { + int res = atomic_load(&_data); + int seq = atomic_load(&_seq); + + int c1; + c1 = seq == old_seq; + if (c1) { // relaxed + return res; + } + } + return -1; +} + +int seqlock_write(int new_data) { + int old_seq = atomic_load(&_seq); + int c2 = (old_seq % 2 == 1); + if (!c2) { + int new_seq = old_seq + 1; + if (atomic_compare_exchange_strong(&_seq, &old_seq, new_seq)) { + atomic_store_explicit(&_data, new_data, std::memory_order_release); + atomic_fetch_add(&_seq, 1); + return true; + } + } + return false; +} + +void * a(void *obj) { +problemsize seqlock_write(3); + return NULL; +} + +void * b(void *obj) { + int r1; +problemsize r1=seqlock_read(); + return NULL; +} + +void * c(void *obj) { + int r1; +problemsize r1=seqlock_read(); + return NULL; +} + +int main(int argc, char **argv) { + pthread_t t1, t2, t3; + seqlock_init(); + + pthread_create(&t1, 0,&a, NULL); + pthread_create(&t2, 0,&b, NULL); + pthread_create(&t3, 0,&c, NULL); + + pthread_join(t1,0); + pthread_join(t2,0); + pthread_join(t3,0); + return 0; +} diff --git a/benchmarks/nidhugg/transform.java b/benchmarks/nidhugg/transform.java new file mode 100644 index 0000000..d65e384 --- /dev/null +++ b/benchmarks/nidhugg/transform.java @@ -0,0 +1,29 @@ +import java.io.*; + +public class transform { + public static void main(String args[]) throws Exception { + int num=Integer.parseInt(args[0]); + String inputfile=args[1]; + String output=args[2]; + BufferedReader br=new BufferedReader(new FileReader(inputfile)); + FileWriter fw=new FileWriter(output); + while(true) { + String input=br.readLine(); + if (input==null) + break; + if (input.indexOf("problemsize")!=-1) { + int index=input.indexOf("problemsize"); + String str=input.substring(index+12); + fw.write("{\nint index;\n"); + fw.write("for (index=0;index<"+num+";index++) {\n"); + fw.write(str+"\n"); + fw.write("}\n}\n"); + } else + fw.write(input+"\n"); + } + br.close(); + fw.close(); + + } + +} diff --git a/benchmarks/runcds b/benchmarks/runcds new file mode 100755 index 0000000..847c39e --- /dev/null +++ b/benchmarks/runcds @@ -0,0 +1,14 @@ +#!/bin/bash +DIR=`pwd` + +echo cdschecker +for i in cdschecker/* +do +echo $i +cd $i +./bench.sh +cd $DIR +done + + + diff --git a/benchmarks/runcf b/benchmarks/runcf new file mode 100755 index 0000000..608fa75 --- /dev/null +++ b/benchmarks/runcf @@ -0,0 +1,15 @@ +#!/bin/bash +DIR=`pwd` + + + +echo checkfence +for i in checkfence/* +do +echo $i +cd $i +./bench.sh +cd $DIR +done + + diff --git a/benchmarks/runnidd b/benchmarks/runnidd new file mode 100755 index 0000000..702d8fb --- /dev/null +++ b/benchmarks/runnidd @@ -0,0 +1,20 @@ +#!/bin/bash +DIR=`pwd` + +echo nidhugg_sc +for i in nidhugg/* +do +echo $i +cd $i +./bench.sh +cd $DIR +done + +echo nidhugg_tso +for i in nidhugg/* +do +echo $i +cd $i +./benchtso.sh +cd $DIR +done diff --git a/benchmarks/runsat b/benchmarks/runsat new file mode 100755 index 0000000..ec62696 --- /dev/null +++ b/benchmarks/runsat @@ -0,0 +1,13 @@ +#!/bin/bash +DIR=`pwd` +BENCHMARKS="dekker linuxlock linuxrwlock msqueueoffset seqlock" + +for i in $BENCHMARKS +do +echo [SC SATCheck]: Running benchmark $i +cd satcheck/$i +echo satcheck > log +echo $i >> log +./bench.sh +cd $DIR +done diff --git a/benchmarks/runtsosat b/benchmarks/runtsosat new file mode 100755 index 0000000..8b2c903 --- /dev/null +++ b/benchmarks/runtsosat @@ -0,0 +1,13 @@ +#!/bin/bash +DIR=`pwd` +BENCHMARKS="dekker linuxlock linuxrwlock msqueueoffset seqlock" + +for i in $BENCHMARKS +do +echo [TSO SATCheck]: Running benchmark $i +cd satcheck/$i +echo satcheck > log +echo $i >> log +./benchtso.sh +cd $DIR +done diff --git a/benchmarks/satcheck-precompiled/dekker/.gitignore b/benchmarks/satcheck-precompiled/dekker/.gitignore new file mode 100644 index 0000000..ce592b6 --- /dev/null +++ b/benchmarks/satcheck-precompiled/dekker/.gitignore @@ -0,0 +1,3 @@ +dekker-fences +log_file +logall diff --git a/benchmarks/satcheck-precompiled/dekker/bench.sh b/benchmarks/satcheck-precompiled/dekker/bench.sh new file mode 100755 index 0000000..2471a37 --- /dev/null +++ b/benchmarks/satcheck-precompiled/dekker/bench.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_SC ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/dekker/benchmark-config.sh b/benchmarks/satcheck-precompiled/dekker/benchmark-config.sh new file mode 100644 index 0000000..25b2e93 --- /dev/null +++ b/benchmarks/satcheck-precompiled/dekker/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=dekker-fences +SIZES_SC="1 2 3 4 5 6 7 8 9 10 15 20 30" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 15 20 30 40" +RUN_FRONTEND=false +RUNTIME_FLAGS=-Y diff --git a/benchmarks/satcheck-precompiled/dekker/benchtso.sh b/benchmarks/satcheck-precompiled/dekker/benchtso.sh new file mode 100755 index 0000000..bf5af51 --- /dev/null +++ b/benchmarks/satcheck-precompiled/dekker/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/dekker/clean.sh b/benchmarks/satcheck-precompiled/dekker/clean.sh new file mode 100755 index 0000000..a1255ac --- /dev/null +++ b/benchmarks/satcheck-precompiled/dekker/clean.sh @@ -0,0 +1,2 @@ +#!/bin/sh +rm -f dekker-fences dekker-fences.c dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck-precompiled/dekker/dekker-fences.c b/benchmarks/satcheck-precompiled/dekker/dekker-fences.c new file mode 100644 index 0000000..c531933 --- /dev/null +++ b/benchmarks/satcheck-precompiled/dekker/dekker-fences.c @@ -0,0 +1,199 @@ +/* + * Dekker's critical section algorithm, implemented with fences. + * Translated to C by Patrick Lam + * + * URL: + * http://www.justsoftwaresolutions.co.uk/threading/ + */ + +#include +#include +#include "libinterface.h" + +/* atomic */ int flag0, flag1; +/* atomic */ int turn; + +#define true 1 +#define false 0 +#define NULL 0 + +/* uint32_t */ int var = 0; + +void p0() { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag0, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + + MCID _mf1; int f1; + MC2_enterLoop(); + while (true) + { + _mf1=MC2_nextOpLoad(MCID_NODEP), f1 = load_32(&flag1); + MCID _br0; + + int _cond0 = !f1; + MCID _cond0_m = MC2_function_id(1, 1, sizeof(_cond0), _cond0, _mf1); + if (_cond0) { + _br0 = MC2_branchUsesID(_cond0_m, 1, 2, true); + break; + } + + else { _br0 = MC2_branchUsesID(_cond0_m, 0, 2, true); MC2_merge(_br0); + } MCID _br1; + MCID _m_cond1_m=MC2_nextOpLoad(MCID_NODEP); + int _cond1 = load_32(&turn); + MCID _cond1_m = MC2_function_id(2, 1, sizeof(_cond1), _cond1, _m_cond1_m); + if (_cond1) { + _br1 = MC2_branchUsesID(_cond1_m, 1, 2, true); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag0, false); + MC2_enterLoop(); + while(1) { + MCID _br2; + MCID _m_cond2_m=MC2_nextOpLoad(MCID_NODEP); + int _cond2 = !load_32(&turn); + MCID _cond2_m = MC2_function_id(3, 1, sizeof(_cond2), _cond2, _m_cond2_m); + if (_cond2) { + _br2 = MC2_branchUsesID(_cond2_m, 1, 2, true); + break; + } + else { _br2 = MC2_branchUsesID(_cond2_m, 0, 2, true); MC2_merge(_br2); + } + MC2_yield(); + } +MC2_exitLoop(); + + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag0, true); + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_cond1_m, 0, 2, true); + MC2_yield(); + MC2_merge(_br1); + } + } +MC2_exitLoop(); + + + // std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&var, 1); + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&turn, 1); + // std::atomic_thread_fence(std::memory_order_release); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag0, false); +} + +void p1() { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + + int f0; + MC2_enterLoop(); + while (true) { + MCID _mf0; _mf0=MC2_nextOpLoad(MCID_NODEP); int f0 = load_32(&flag0); + MCID _br3; + + int _cond3 = !f0; + MCID _cond3_m = MC2_function_id(4, 1, sizeof(_cond3), _cond3, _mf0); + if (_cond3) { + _br3 = MC2_branchUsesID(_cond3_m, 1, 2, true); + break; + } + else { _br3 = MC2_branchUsesID(_cond3_m, 0, 2, true); MC2_merge(_br3); + } + MCID _br4; + MCID _m_cond4_m=MC2_nextOpLoad(MCID_NODEP); + int _cond4 = !load_32(&turn); + MCID _cond4_m = MC2_function_id(5, 1, sizeof(_cond4), _cond4, _m_cond4_m); + if (_cond4) { + _br4 = MC2_branchUsesID(_cond4_m, 1, 2, true); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, false); + MC2_enterLoop(); + while (1) { + MCID _br5; + MCID _m_cond5_m=MC2_nextOpLoad(MCID_NODEP); + int _cond5 = load_32(&turn); + MCID _cond5_m = MC2_function_id(6, 1, sizeof(_cond5), _cond5, _m_cond5_m); + if (_cond5) + {_br5 = MC2_branchUsesID(_cond5_m, 1, 2, true); + break; +} else { _br5 = MC2_branchUsesID(_cond5_m, 0, 2, true); MC2_merge(_br5); + } MC2_yield(); + } +MC2_exitLoop(); + + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + MC2_merge(_br4); + } + else { _br4 = MC2_branchUsesID(_cond4_m, 0, 2, true); MC2_merge(_br4); + } } +MC2_exitLoop(); + + + // std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&var, 2); + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&turn, 0); + // std::atomic_thread_fence(std::memory_order_release); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, false); +} + +void p0l(void *a) { + int i; + MC2_enterLoop(); + for(i=0;i + * + * URL: + * http://www.justsoftwaresolutions.co.uk/threading/ + */ + +#include +#include +#include "libinterface.h" + +/* atomic */ int flag0, flag1; +/* atomic */ int turn; + +#define true 1 +#define false 0 +#define NULL 0 + +/* uint32_t */ int var = 0; + +void p0() { + store_32(&flag0, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + + int f1, t; + while (true) + { + f1 = load_32(&flag1); + if (!f1) { + break; + } + + + t = load_32(&turn); + + if (t) { + store_32(&flag0, false); + while(1) { + t = load_32(&turn); + if (!t) { + break; + } + + MC2_yield(); + } + + store_32(&flag0, true); + } else { + MC2_yield(); + } + } + + // std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + store_32(&var, 1); + + store_32(&turn, 1); + // std::atomic_thread_fence(std::memory_order_release); + store_32(&flag0, false); +} + +void p1() { + store_32(&flag1, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + + int f0, t; + while (true) { + int f0 = load_32(&flag0); + if (!f0) { + break; + } + + t = load_32(&turn); + + if (!t) { + store_32(&flag1, false); + while (1) { + t = load_32(&turn); + if (t) + break; + MC2_yield(); + } + + store_32(&flag1, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + } + } + + // std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + store_32(&var, 2); + + store_32(&turn, 0); + // std::atomic_thread_fence(std::memory_order_release); + store_32(&flag1, false); +} + +void p0l(void *a) { + int i; + for(i=0;i> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/linuxlock/benchmark-config.sh b/benchmarks/satcheck-precompiled/linuxlock/benchmark-config.sh new file mode 100644 index 0000000..698c3be --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxlock/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=linuxlocks +SIZES_SC="1 2 3 4 5 6 7 8 9 10 15 20 30 40 50 60 70 80 90 100 150 200 250" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 15 20 30 40 50 60 70 80 90 100" +RUN_FRONTEND=false +RUNTIME_FLAGS= diff --git a/benchmarks/satcheck-precompiled/linuxlock/benchtso.sh b/benchmarks/satcheck-precompiled/linuxlock/benchtso.sh new file mode 100755 index 0000000..bf5af51 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxlock/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/linuxlock/clean.sh b/benchmarks/satcheck-precompiled/linuxlock/clean.sh new file mode 100755 index 0000000..9a90971 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxlock/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +rm -f linuxlocks.c linuxlocks dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck-precompiled/linuxlock/diff.sh b/benchmarks/satcheck-precompiled/linuxlock/diff.sh new file mode 100755 index 0000000..b3563be --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxlock/diff.sh @@ -0,0 +1,4 @@ +#!/bin/sh +NAME=linuxlock +diff -ub ../../satcheck/$NAME/linuxlocks.c.in linuxlocks.c + diff --git a/benchmarks/satcheck-precompiled/linuxlock/linuxlocks.c b/benchmarks/satcheck-precompiled/linuxlock/linuxlocks.c new file mode 100644 index 0000000..db75025 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxlock/linuxlocks.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include "libinterface.h" + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline bool write_trylock(MCID _mrw, rwlock_t *rw, MCID * retval) +{ + MCID _rmw0 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + int priorvalue=rmw_32(CAS, &rw->lock, 0, 1); + *retval = _rmw0; + return priorvalue; +} + +static inline void write_unlock(MCID _mrw, rwlock_t *rw) +{ + MC2_nextOpStoreOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP); + store_32(&rw->lock, 0); +} + +MCID _fn0; rwlock_t * mylock; + +static void foo() { + MCID _rv0; + int flag=write_trylock(MCID_NODEP, mylock, &_rv0); + MCID _br0; + + int _cond0 = flag; + MCID _cond0_m = MC2_function_id(1, 1, sizeof(_cond0), _cond0, _rv0); + if (_cond0) {_br0 = MC2_branchUsesID(_rv0, 1, 2, true); + + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_rv0, 0, 2, true); + write_unlock(MCID_NODEP, mylock); + MC2_merge(_br0); + } +} + +static void a(void *obj) +{ + int i; + MC2_enterLoop(); + for(i=0;ilock, 0); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + //thrd_create(&t3, (thrd_start_t)&a, NULL); + //thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + //thrd_join(t3); + //thrd_join(t4); + + + + return 0; +} diff --git a/benchmarks/satcheck-precompiled/linuxlock/linuxlocks_unannotated.c b/benchmarks/satcheck-precompiled/linuxlock/linuxlocks_unannotated.c new file mode 100644 index 0000000..926e0e7 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxlock/linuxlocks_unannotated.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include "libinterface.h" + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline bool write_trylock(rwlock_t *rw) +{ + int priorvalue=rmw_32(CAS, &rw->lock, 0, 1); + return priorvalue; +} + +static inline void write_unlock(rwlock_t *rw) +{ + store_32(&rw->lock, 0); +} + +rwlock_t * mylock; + +static void foo() { + int flag=write_trylock(mylock); + if (flag) { + } else { + write_unlock(mylock); + } +} + +static void a(void *obj) +{ + int i; + for(i=0;ilock, 0); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + //thrd_create(&t3, (thrd_start_t)&a, NULL); + //thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + //thrd_join(t3); + //thrd_join(t4); + + return 0; +} diff --git a/benchmarks/satcheck-precompiled/linuxrwlock/.gitignore b/benchmarks/satcheck-precompiled/linuxrwlock/.gitignore new file mode 100644 index 0000000..2bb93ae --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxrwlock/.gitignore @@ -0,0 +1,4 @@ +linuxrwlocks +log_file +logall +linuxrwlocks diff --git a/benchmarks/satcheck-precompiled/linuxrwlock/bench.sh b/benchmarks/satcheck-precompiled/linuxrwlock/bench.sh new file mode 100755 index 0000000..2471a37 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxrwlock/bench.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_SC ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/linuxrwlock/benchmark-config.sh b/benchmarks/satcheck-precompiled/linuxrwlock/benchmark-config.sh new file mode 100644 index 0000000..c9aa599 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxrwlock/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=linuxrwlocks +SIZES_SC="1 2 3 4 5 6 7 8 9 10 15 20" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 15 20" +RUN_FRONTEND=false +RUNTIME_FLAGS= diff --git a/benchmarks/satcheck-precompiled/linuxrwlock/benchtso.sh b/benchmarks/satcheck-precompiled/linuxrwlock/benchtso.sh new file mode 100755 index 0000000..bf5af51 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxrwlock/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/linuxrwlock/clean.sh b/benchmarks/satcheck-precompiled/linuxrwlock/clean.sh new file mode 100755 index 0000000..3a12299 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxrwlock/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +rm -f linuxrwlocks.cc linuxrwlocks dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck-precompiled/linuxrwlock/diff.sh b/benchmarks/satcheck-precompiled/linuxrwlock/diff.sh new file mode 100755 index 0000000..c878fd3 --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxrwlock/diff.sh @@ -0,0 +1,4 @@ +#!/bin/sh +NAME=linuxrwlock +diff -ub ../../satcheck/$NAME/linuxrwlocks.c.in linuxrwlocks.c + diff --git a/benchmarks/satcheck-precompiled/linuxrwlock/linuxrwlocks.c b/benchmarks/satcheck-precompiled/linuxrwlock/linuxrwlocks.c new file mode 100644 index 0000000..150b68a --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxrwlock/linuxrwlocks.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include + +#include "libinterface.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline void read_lock(MCID _mrw, rwlock_t *rw) +{ + MCID _rmw0 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + + MC2_enterLoop(); + while (true) { + MCID _br0; + + int _cond0 = priorvalue <= 0; + MCID _cond0_m = MC2_function_id(1, 1, sizeof(_cond0), _cond0, _rmw0); + if (_cond0) {_br0 = MC2_branchUsesID(_cond0_m, 1, 2, true); + + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_cond0_m, 0, 2, true); + break; + } + + MCID _rmw1 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); + + MC2_enterLoop(); + while (true) { + MCID _mstatus; _mstatus=MC2_nextOpLoadOffset(_mrw, MC2_OFFSET(rwlock_t *, lock)); int status = load_32(&rw->lock); + MCID _br1; + + int _cond1 = status > 0; + MCID _cond1_m = MC2_function_id(2, 1, sizeof(_cond1), _cond1, _mstatus); + if (_cond1) {_br1 = MC2_branchUsesID(_cond1_m, 1, 2, true); + + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_cond1_m, 0, 2, true); + break; + } + MC2_yield(); + } +MC2_exitLoop(); + + + + MCID _rmw2 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + } +MC2_exitLoop(); + +} + +static inline void write_lock(MCID _mrw, rwlock_t *rw) +{ + MCID _rmw3 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + MC2_enterLoop(); + while(true) { + MCID _br2; + + int _cond2 = priorvalue != 1048576; + MCID _cond2_m = MC2_function_id(3, 1, sizeof(_cond2), _cond2, _rmw3); + if (_cond2) {_br2 = MC2_branchUsesID(_cond2_m, 1, 2, true); + + MC2_merge(_br2); + } else { + _br2 = MC2_branchUsesID(_cond2_m, 0, 2, true); + break; + } + + MCID _rmw4 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + + MC2_enterLoop(); + while (true) { + MCID _mstatus; _mstatus=MC2_nextOpLoadOffset(_mrw, MC2_OFFSET(rwlock_t *, lock)); int status = load_32(&rw->lock); + MCID _br3; + + int _cond3 = status != 1048576; + MCID _cond3_m = MC2_function_id(4, 1, sizeof(_cond3), _cond3, _mstatus); + if (_cond3) {_br3 = MC2_branchUsesID(_cond3_m, 1, 2, true); + + MC2_merge(_br3); + } else { + _br3 = MC2_branchUsesID(_cond3_m, 0, 2, true); + break; + } + MC2_yield(); + } +MC2_exitLoop(); + + + MCID _rmw5 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + } +MC2_exitLoop(); + +} + +static inline bool write_trylock(MCID _mrw, rwlock_t *rw, MCID * retval) +{ + MCID _rmw6 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + + MCID _fn0; int flag = priorvalue != RW_LOCK_BIAS; + _fn0 = MC2_function_id(7, 1, sizeof (flag), (uint64_t)flag, _rmw6); + MCID _br4; + + int _cond4 = !flag; + MCID _cond4_m = MC2_function_id(5, 1, sizeof(_cond4), _cond4, _fn0); + if (_cond4) { + _br4 = MC2_branchUsesID(_cond4_m, 1, 2, true); + MCID _rmw7 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + MC2_merge(_br4); + } + else { _br4 = MC2_branchUsesID(_cond4_m, 0, 2, true); MC2_merge(_br4); + } + *retval = _fn0; + return flag; +} + +static inline void read_unlock(MCID _mrw, rwlock_t *rw) +{ + MCID _rmw8 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); +} + +static inline void write_unlock(MCID _mrw, rwlock_t *rw) +{ + MCID _rmw9 = MC2_nextRMWOffset(_mrw, MC2_OFFSET(rwlock_t *, lock), MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); +} + +MCID _fn1; rwlock_t * mylock; +int shareddata; + +static void foo() { + MCID _rv0; + int res = write_trylock(MCID_NODEP, mylock, &_rv0); + MCID _br5; + + int _cond5 = res; + MCID _cond5_m = MC2_function_id(6, 1, sizeof(_cond5), _cond5, _rv0); + if (_cond5) { + _br5 = MC2_branchUsesID(_rv0, 1, 2, true); + write_unlock(MCID_NODEP, mylock); + MC2_merge(_br5); + } else {_br5 = MC2_branchUsesID(_rv0, 0, 2, true); + + MC2_merge(_br5); + } +} + +static void a(void *obj) +{ + int i; + MC2_enterLoop(); + for(i=0;ilock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + // thrd_create(&t3, (thrd_start_t)&a, NULL); + // thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + // thrd_join(t3); + // thrd_join(t4); + free(mylock); + + return 0; +} diff --git a/benchmarks/satcheck-precompiled/linuxrwlock/linuxrwlocks_unannotated.c b/benchmarks/satcheck-precompiled/linuxrwlock/linuxrwlocks_unannotated.c new file mode 100644 index 0000000..10496dc --- /dev/null +++ b/benchmarks/satcheck-precompiled/linuxrwlock/linuxrwlocks_unannotated.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include + +#include "libinterface.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline void read_lock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + + while (true) { + if (priorvalue <= 0) { + } else { + break; + } + + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); + + while (true) { + int status = load_32(&rw->lock); + if (status > 0) { + } else { + break; + } + MC2_yield(); + } + + + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + } +} + +static inline void write_lock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + while(true) { + if (priorvalue != RW_LOCK_BIAS) { + } else { + break; + } + + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + + while (true) { + int status = load_32(&rw->lock); + if (status != RW_LOCK_BIAS) { + } else { + break; + } + MC2_yield(); + } + + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + } +} + +static inline bool write_trylock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + + int flag = priorvalue != RW_LOCK_BIAS; + if (!flag) { + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + } + + return flag; +} + +static inline void read_unlock(rwlock_t *rw) +{ + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); +} + +static inline void write_unlock(rwlock_t *rw) +{ + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); +} + +rwlock_t * mylock; +int shareddata; + +static void foo() { + int res = write_trylock(mylock); + if (res) { + write_unlock(mylock); + } else { + } +} + +static void a(void *obj) +{ + int i; + for(i=0;ilock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + // thrd_create(&t3, (thrd_start_t)&a, NULL); + // thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + // thrd_join(t3); + // thrd_join(t4); + free(mylock); + + return 0; +} diff --git a/benchmarks/satcheck-precompiled/msqueueoffset/.gitignore b/benchmarks/satcheck-precompiled/msqueueoffset/.gitignore new file mode 100644 index 0000000..af514b3 --- /dev/null +++ b/benchmarks/satcheck-precompiled/msqueueoffset/.gitignore @@ -0,0 +1,3 @@ +logall +ms-queue-simple +log_file diff --git a/benchmarks/satcheck-precompiled/msqueueoffset/bench.sh b/benchmarks/satcheck-precompiled/msqueueoffset/bench.sh new file mode 100755 index 0000000..2471a37 --- /dev/null +++ b/benchmarks/satcheck-precompiled/msqueueoffset/bench.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_SC ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/msqueueoffset/benchmark-config.sh b/benchmarks/satcheck-precompiled/msqueueoffset/benchmark-config.sh new file mode 100644 index 0000000..a7c1cfc --- /dev/null +++ b/benchmarks/satcheck-precompiled/msqueueoffset/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=ms-queue-simple +SIZES_SC="1 2 3 4 5 6 7 8 9 10 11 12 13" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 11 12 13" +RUN_FRONTEND=false +RUNTIME_FLAGS= diff --git a/benchmarks/satcheck-precompiled/msqueueoffset/benchtso.sh b/benchmarks/satcheck-precompiled/msqueueoffset/benchtso.sh new file mode 100755 index 0000000..bf5af51 --- /dev/null +++ b/benchmarks/satcheck-precompiled/msqueueoffset/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/msqueueoffset/clean.sh b/benchmarks/satcheck-precompiled/msqueueoffset/clean.sh new file mode 100755 index 0000000..3a12299 --- /dev/null +++ b/benchmarks/satcheck-precompiled/msqueueoffset/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +rm -f linuxrwlocks.cc linuxrwlocks dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck-precompiled/msqueueoffset/diff.sh b/benchmarks/satcheck-precompiled/msqueueoffset/diff.sh new file mode 100755 index 0000000..d7117e7 --- /dev/null +++ b/benchmarks/satcheck-precompiled/msqueueoffset/diff.sh @@ -0,0 +1,4 @@ +#!/bin/sh +NAME=msqueueoffset +diff -ub ../../satcheck/$NAME/ms-queue-simple.c.in ms-queue-simple.c + diff --git a/benchmarks/satcheck-precompiled/msqueueoffset/ms-queue-simple.c b/benchmarks/satcheck-precompiled/msqueueoffset/ms-queue-simple.c new file mode 100644 index 0000000..e819eb7 --- /dev/null +++ b/benchmarks/satcheck-precompiled/msqueueoffset/ms-queue-simple.c @@ -0,0 +1,225 @@ +#include +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue-simple.h" +#include "libinterface.h" + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads); +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val); +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal, MCID * retval); + +queue_t queue; + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads) { + MCID _fn0; struct node *newnode=(struct node *)malloc(sizeof (struct node)); + _fn0 = MC2_function_id(0, 0, sizeof (newnode), (uint64_t)newnode); + + MC2_nextOpStoreOffset(_fn0, MC2_OFFSET(struct node *, value), MCID_NODEP); + store_32(&newnode->value, 0); + + + MC2_nextOpStoreOffset(_fn0, MC2_OFFSET(struct node *, next), MCID_NODEP); + store_64(&newnode->next, (uintptr_t) NULL); + /* initialize queue */ + + MC2_nextOpStoreOffset(_mq, MC2_OFFSET(queue_t *, head), _fn0); + store_64(&q->head, (uintptr_t) newnode); + + + MC2_nextOpStoreOffset(_mq, MC2_OFFSET(queue_t *, tail), _fn0); + store_64(&q->tail, (uintptr_t) newnode); +} + +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val) { + MCID _mtail; struct node *tail; + MCID _fn1; struct node * node_ptr; node_ptr = (struct node *)malloc(sizeof(struct node)); + _fn1 = MC2_function_id(0, 1, sizeof (node_ptr), (uint64_t)node_ptr, _fn1); + + MC2_nextOpStoreOffset(_fn1, MC2_OFFSET(struct node *, value), _mval); + store_32(&node_ptr->value, val); + + + MC2_nextOpStoreOffset(_fn1, MC2_OFFSET(struct node *, next), MCID_NODEP); + store_64(&node_ptr->next, (uintptr_t) NULL); + + MC2_enterLoop(); + while (true) { + + _mtail=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, tail)), tail = (struct node *) load_64(&q->tail); + + MCID _mnext; _mnext=MC2_nextOpLoadOffset(_mtail, MC2_OFFSET(struct node *, next)); struct node * next = (struct node *) load_64(&tail->next); + + MCID _mqtail; _mqtail=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, tail)); struct node * qtail = (struct node *) load_64(&q->tail); + + MCID _br0; + + MCID _cond0_m; + + int _cond0 = MC2_equals(_mtail, (uint64_t)tail, _mqtail, (uint64_t)qtail, &_cond0_m); + if (_cond0) { + MCID _br1; + _br0 = MC2_branchUsesID(_cond0_m, 1, 2, true); + + int _cond1 = next; + MCID _cond1_m = MC2_function_id(1, 1, sizeof(_cond1), _cond1, _mnext); + if (_cond1) { + _br1 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_yield(); + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_mnext, 0, 2, true); + MCID _rmw0 = MC2_nextRMWOffset(_mtail, MC2_OFFSET(struct node *, next), _mnext, _fn1); + struct node * valread = (struct node *) rmw_64(CAS, &tail->next, (uintptr_t) next, (uintptr_t) node_ptr); + + MCID _br2; + + MCID _cond2_m; + + int _cond2 = MC2_equals(_mnext, (uint64_t)next, _rmw0, (uint64_t)valread, &_cond2_m); + if (_cond2) { + _br2 = MC2_branchUsesID(_cond2_m, 1, 2, true); + break; + } else {_br2 = MC2_branchUsesID(_cond2_m, 0, 2, true); + + MC2_merge(_br2); + } + MC2_merge(_br1); + } + MCID _mnew_tailptr; _mnew_tailptr=MC2_nextOpLoadOffset(_mtail, MC2_OFFSET(struct node *, next)); struct node * new_tailptr = (struct node *)load_64(&tail->next); + MCID _rmw1 = MC2_nextRMWOffset(_mq, MC2_OFFSET(queue_t *, tail), _mtail, _mnew_tailptr); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) new_tailptr); + MC2_yield(); + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_cond0_m, 0, 2, true); + MC2_yield(); + MC2_merge(_br0); + } + } +MC2_exitLoop(); + + + MCID _rmw2 = MC2_nextRMWOffset(_mq, MC2_OFFSET(queue_t *, tail), _mtail, _fn1); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) node_ptr); +} + +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal, MCID * retval) { + MC2_enterLoop(); + while (true) { + MCID _mhead; _mhead=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, head)); struct node * head = (struct node *) load_64(&q->head); + MCID _mtail; _mtail=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, tail)); struct node * tail = (struct node *) load_64(&q->tail); + MCID _mnext; _mnext=MC2_nextOpLoadOffset(_mhead, MC2_OFFSET(struct node *, next)); struct node * next = (struct node *) load_64(&head->next); + + MCID _mheadr; _mheadr=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, head)); struct node * headr = (struct node *) load_64(&q->head); + + MCID _br3; + + MCID _cond3_m; + + int _cond3 = MC2_equals(_mhead, (uint64_t)head, _mheadr, (uint64_t)headr, &_cond3_m); + if (_cond3) { + MCID _br4; + _br3 = MC2_branchUsesID(_cond3_m, 1, 2, true); + + MCID _cond4_m; + + int _cond4 = MC2_equals(_mhead, (uint64_t)head, _mtail, (uint64_t)tail, &_cond4_m); + if (_cond4) { + MCID _br5; + _br4 = MC2_branchUsesID(_cond4_m, 1, 2, true); + + int _cond5 = next; + MCID _cond5_m = MC2_function_id(2, 1, sizeof(_cond5), _cond5, _mnext); + if (_cond5) { + _br5 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_yield(); + MC2_merge(_br5); + } else { + *retval = MCID_NODEP; + _br5 = MC2_branchUsesID(_mnext, 0, 2, true); + MC2_exitLoop(); + return false; // NULL + } + MCID _rmw3 = MC2_nextRMWOffset(_mq, MC2_OFFSET(queue_t *, tail), _mtail, _mnext); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) next); + MC2_yield(); + MC2_merge(_br4); + } else { + _br4 = MC2_branchUsesID(_cond4_m, 0, 2, true); + _mretVal=MC2_nextOpLoadOffset(_mnext, MC2_OFFSET(struct node *, value)), *retVal = load_32(&next->value); + MCID _rmw4 = MC2_nextRMWOffset(_mq, MC2_OFFSET(queue_t *, head), _mhead, _mnext); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) next); + + MCID _br6; + + MCID _cond6_m; + + int _cond6 = MC2_equals(_mhead, (uint64_t)head, _rmw4, (uint64_t)old_head, &_cond6_m); + if (_cond6) { + *retval = MCID_NODEP; + _br6 = MC2_branchUsesID(_cond6_m, 1, 2, true); + MC2_exitLoop(); + return true; + } else { + _br6 = MC2_branchUsesID(_cond6_m, 0, 2, true); + MC2_yield(); + MC2_merge(_br6); + } + MC2_merge(_br4); + } + MC2_merge(_br3); + } else { + _br3 = MC2_branchUsesID(_cond3_m, 0, 2, true); + MC2_yield(); + MC2_merge(_br3); + } + } +MC2_exitLoop(); + +} + +/* ms-queue-main */ +bool succ1, succ2; + +static void e(void *p) { + int i; + MC2_enterLoop(); + for(i=0;i +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue-simple.h" +#include "libinterface.h" + +void init_queue(queue_t *q, int num_threads); +void enqueue(queue_t *q, unsigned int val); +bool dequeue(queue_t *q, unsigned int *retVal); + +queue_t queue; + +void init_queue(queue_t *q, int num_threads) { + struct node *newnode=(struct node *)malloc(sizeof (struct node)); + + store_32(&newnode->value, 0); + + + store_64(&newnode->next, (uintptr_t) NULL); + /* initialize queue */ + + store_64(&q->head, (uintptr_t) newnode); + + + store_64(&q->tail, (uintptr_t) newnode); +} + +void enqueue(queue_t *q, unsigned int val) { + struct node *tail; + struct node * node_ptr; node_ptr = (struct node *)malloc(sizeof(struct node)); + + store_32(&node_ptr->value, val); + + + store_64(&node_ptr->next, (uintptr_t) NULL); + + while (true) { + + tail = (struct node *) load_64(&q->tail); + + struct node * next = (struct node *) load_64(&tail->next); + + struct node * qtail = (struct node *) load_64(&q->tail); + + if (tail == qtail) { + if (next) { + MC2_yield(); + } else { + struct node * valread = (struct node *) rmw_64(CAS, &tail->next, (uintptr_t) next, (uintptr_t) node_ptr); + + if (next == valread) { + break; + } else { + } + } + struct node * new_tailptr = (struct node *)load_64(&tail->next); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) new_tailptr); + MC2_yield(); + } else { + MC2_yield(); + } + } + + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) node_ptr); +} + +bool dequeue(queue_t *q, unsigned int *retVal) { + while (true) { + struct node * head = (struct node *) load_64(&q->head); + struct node * tail = (struct node *) load_64(&q->tail); + struct node * next = (struct node *) load_64(&head->next); + + struct node * headr = (struct node *) load_64(&q->head); + + if (head == headr) { + if (head == tail) { + if (next) { + MC2_yield(); + } else { + return false; // NULL + } + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) next); + MC2_yield(); + } else { + *retVal = load_32(&next->value); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) next); + + if (head == old_head) { + return true; + } else { + MC2_yield(); + } + } + } else { + MC2_yield(); + } + } +} + +/* ms-queue-main */ +bool succ1, succ2; + +static void e(void *p) { + int i; + for(i=0;i> log +gcc ${NAME}.cc -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/seqlock/benchmark-config.sh b/benchmarks/satcheck-precompiled/seqlock/benchmark-config.sh new file mode 100644 index 0000000..a737bcf --- /dev/null +++ b/benchmarks/satcheck-precompiled/seqlock/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=seqlock +SIZES_SC="1 2 3 4 5 6 7 8 9 10 15 20 25 30 35 40 50 60" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 15 20 25 30 35 40 50 60" +RUN_FRONTEND=false +RUNTIME_FLAGS=-Y diff --git a/benchmarks/satcheck-precompiled/seqlock/benchtso.sh b/benchmarks/satcheck-precompiled/seqlock/benchtso.sh new file mode 100755 index 0000000..3c52574 --- /dev/null +++ b/benchmarks/satcheck-precompiled/seqlock/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.cc -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck-precompiled/seqlock/clean.sh b/benchmarks/satcheck-precompiled/seqlock/clean.sh new file mode 100755 index 0000000..325db38 --- /dev/null +++ b/benchmarks/satcheck-precompiled/seqlock/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +rm -f seqlock.cc seqlock dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck-precompiled/seqlock/diff.sh b/benchmarks/satcheck-precompiled/seqlock/diff.sh new file mode 100755 index 0000000..a95a91b --- /dev/null +++ b/benchmarks/satcheck-precompiled/seqlock/diff.sh @@ -0,0 +1,4 @@ +#!/bin/sh +NAME=seqlock +diff -ub ../../satcheck/$NAME/seqlock.cc.in seqlock.cc + diff --git a/benchmarks/satcheck-precompiled/seqlock/seqlock.cc b/benchmarks/satcheck-precompiled/seqlock/seqlock.cc new file mode 100644 index 0000000..1af11a4 --- /dev/null +++ b/benchmarks/satcheck-precompiled/seqlock/seqlock.cc @@ -0,0 +1,149 @@ +#include +#include +#include + +#include "libinterface.h" + +// Sequence for reader consistency check +/*atomic_*/ int _seq; +// It needs to be atomic to avoid data races +/*atomic_*/ int _data; + +void seqlock_init() { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_seq, 0); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_data, 10); +} + +int seqlock_read(MCID * retval) { + MCID _mres; int res; + MCID _mold_seq; _mold_seq=MC2_nextOpLoad(MCID_NODEP); int old_seq = load_32(&_seq); // acquire + + MCID _br30; + + int _cond30 = old_seq % 2 == 1; + MCID _cond30_m = MC2_function_id(31, 1, sizeof(_cond30), _cond30, _mold_seq); + if (_cond30) { + _br30 = MC2_branchUsesID(_cond30_m, 1, 2, true); + res = -1; + MC2_merge(_br30); + } else { + _br30 = MC2_branchUsesID(_cond30_m, 0, 2, true); + _mres=MC2_nextOpLoad(MCID_NODEP), res = load_32(&_data); + MCID _mseq; _mseq=MC2_nextOpLoad(MCID_NODEP); int seq = load_32(&_seq); + + MCID _br31; + + MCID _cond31_m; + + int _cond31 = MC2_equals(_mseq, (uint64_t)seq, _mold_seq, (uint64_t)old_seq, &_cond31_m); + if (_cond31) {_br31 = MC2_branchUsesID(_cond31_m, 1, 2, true); + + MC2_merge(_br31); + } else { + _br31 = MC2_branchUsesID(_cond31_m, 0, 2, true); + res = -1; + MC2_merge(_br31); + } + MC2_merge(_br30); + } + *retval = _mres; + return res; +} + +int seqlock_write(MCID _mnew_data, int new_data, MCID * retval) { + MCID _mold_seq; _mold_seq=MC2_nextOpLoad(MCID_NODEP); int old_seq = load_32(&_seq); + int res; + + MCID _br32; + + int _cond32 = old_seq % 2 == 1; + MCID _cond32_m = MC2_function_id(32, 1, sizeof(_cond32), _cond32, _mold_seq); + if (_cond32) { + _br32 = MC2_branchUsesID(_cond32_m, 1, 2, true); + res = 0; + MC2_merge(_br32); + } else { + MCID _fn0; _br32 = MC2_branchUsesID(_cond32_m, 0, 2, true); + int new_seq = old_seq + 1; + _fn0 = MC2_function_id(33, 1, sizeof (new_seq), (uint64_t)new_seq, _mold_seq); + MCID _rmw0 = MC2_nextRMW(MCID_NODEP, _mold_seq, _fn0); + int cas_value = rmw_32(CAS, &_seq, old_seq, new_seq); + + MCID _br33; + + MCID _cond33_m; + + int _cond33 = MC2_equals(_rmw0, (uint64_t)cas_value, _mold_seq, (uint64_t)old_seq, &_cond33_m); + if (_cond33) { + // Update the data + _br33 = MC2_branchUsesID(_cond33_m, 1, 2, true); + MC2_nextOpStore(MCID_NODEP, _mnew_data); + store_32(&_data, new_data); + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &_seq, /* dummy */0, 1); + res = 1; + MC2_merge(_br33); + } else { + _br33 = MC2_branchUsesID(_cond33_m, 0, 2, true); + res = 0; + MC2_merge(_br33); + } + MC2_merge(_br32); + } + *retval = MCID_NODEP; + return res; +} + +static void a(void *obj) { + int q; + MC2_enterLoop(); + for (int i = 0; i < PROBLEMSIZE; i++) { + MCID _rv0; + q = seqlock_write(MCID_NODEP, 30, &_rv0); + } +MC2_exitLoop(); + + +} + +static void b(void *obj) { + int r1; + MC2_enterLoop(); + for (int i = 0; i < PROBLEMSIZE; i++) { + MCID _rv1; + r1 = seqlock_read(&_rv1); + } +MC2_exitLoop(); + + +} + +static void c(void *obj) { + int r1; + MC2_enterLoop(); + for (int i = 0; i < PROBLEMSIZE; i++) { + MCID _rv2; + r1 = seqlock_read(&_rv2); + } +MC2_exitLoop(); + + +} + +int user_main(int argc, char **argv) { + thrd_t t1; thrd_t t2; thrd_t t3; + seqlock_init(); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + thrd_create(&t3, (thrd_start_t)&c, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + + + return 0; +} diff --git a/benchmarks/satcheck-precompiled/seqlock/seqlock_unannotated.cc b/benchmarks/satcheck-precompiled/seqlock/seqlock_unannotated.cc new file mode 100644 index 0000000..e380a2e --- /dev/null +++ b/benchmarks/satcheck-precompiled/seqlock/seqlock_unannotated.cc @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "libinterface.h" + +// Sequence for reader consistency check +/*atomic_*/ int _seq; +// It needs to be atomic to avoid data races +/*atomic_*/ int _data; + +void seqlock_init() { + store_32(&_seq, 0); + store_32(&_data, 10); +} + +int seqlock_read() { + int res; + int old_seq = load_32(&_seq); // acquire + + if (old_seq % 2 == 1) { + res = -1; + } else { + res = load_32(&_data); + int seq = load_32(&_seq); + + if (seq == old_seq) { + } else { + res = -1; + } + } + return res; +} + +int seqlock_write(int new_data) { + int old_seq = load_32(&_seq); + int res; + + if (old_seq % 2 == 1) { + res = 0; + } else { + int new_seq = old_seq + 1; + int cas_value = rmw_32(CAS, &_seq, old_seq, new_seq); + + if (cas_value == old_seq) { + // Update the data + store_32(&_data, new_data); + rmw_32(ADD, &_seq, /* dummy */0, 1); + res = 1; + } else { + res = 0; + } + } + return res; +} + +static void a(void *obj) { + int q; + for (int i = 0; i < PROBLEMSIZE; i++) { + q = seqlock_write(30); + } + +} + +static void b(void *obj) { + int r1; + for (int i = 0; i < PROBLEMSIZE; i++) { + r1 = seqlock_read(); + } + +} + +static void c(void *obj) { + int r1; + for (int i = 0; i < PROBLEMSIZE; i++) { + r1 = seqlock_read(); + } + +} + +int user_main(int argc, char **argv) { + thrd_t t1; thrd_t t2; thrd_t t3; + seqlock_init(); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + thrd_create(&t3, (thrd_start_t)&c, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + + + return 0; +} diff --git a/benchmarks/satcheck/dekker/.gitignore b/benchmarks/satcheck/dekker/.gitignore new file mode 100644 index 0000000..dead37e --- /dev/null +++ b/benchmarks/satcheck/dekker/.gitignore @@ -0,0 +1,4 @@ +dekker-fences +dekker-fences.c +log_file +logall diff --git a/benchmarks/satcheck/dekker/bench.sh b/benchmarks/satcheck/dekker/bench.sh new file mode 100755 index 0000000..2471a37 --- /dev/null +++ b/benchmarks/satcheck/dekker/bench.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_SC ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/dekker/benchmark-config.sh b/benchmarks/satcheck/dekker/benchmark-config.sh new file mode 100644 index 0000000..195bcbc --- /dev/null +++ b/benchmarks/satcheck/dekker/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=dekker-fences +SIZES_SC="1 2 3 4 5 6 7 8 9 10 15 20 30" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 15 20 30 40" +RUN_FRONTEND=true +RUNTIME_FLAGS=-Y diff --git a/benchmarks/satcheck/dekker/benchtso.sh b/benchmarks/satcheck/dekker/benchtso.sh new file mode 100755 index 0000000..bf5af51 --- /dev/null +++ b/benchmarks/satcheck/dekker/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/dekker/clean.sh b/benchmarks/satcheck/dekker/clean.sh new file mode 100755 index 0000000..a1255ac --- /dev/null +++ b/benchmarks/satcheck/dekker/clean.sh @@ -0,0 +1,2 @@ +#!/bin/sh +rm -f dekker-fences dekker-fences.c dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck/dekker/compile.sh b/benchmarks/satcheck/dekker/compile.sh new file mode 100755 index 0000000..5da0c11 --- /dev/null +++ b/benchmarks/satcheck/dekker/compile.sh @@ -0,0 +1,5 @@ +#!/bin/sh +. ../path.sh +. ./benchmark-config.sh +echo $MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.c -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include +$MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.c -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include > ${NAME}.c diff --git a/benchmarks/satcheck/dekker/dekker-fences_unannotated.c b/benchmarks/satcheck/dekker/dekker-fences_unannotated.c new file mode 100644 index 0000000..68ebc84 --- /dev/null +++ b/benchmarks/satcheck/dekker/dekker-fences_unannotated.c @@ -0,0 +1,127 @@ +/* + * Dekker's critical section algorithm, implemented with fences. + * Translated to C by Patrick Lam + * + * URL: + * http://www.justsoftwaresolutions.co.uk/threading/ + */ + +#include +#include +#include "libinterface.h" + +/* atomic */ int flag0, flag1; +/* atomic */ int turn; + +#define true 1 +#define false 0 +#define NULL 0 + +/* uint32_t */ int var = 0; + +void p0() { + store_32(&flag0, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + + int f1; + while (true) + { + f1 = load_32(&flag1); + if (!f1) { + break; + } + + if (load_32(&turn)) { + store_32(&flag0, false); + while(1) { + if (!load_32(&turn)) { + break; + } + + MC2_yield(); + } + + store_32(&flag0, true); + } else { + MC2_yield(); + } + } + + // std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + store_32(&var, 1); + + store_32(&turn, 1); + // std::atomic_thread_fence(std::memory_order_release); + store_32(&flag0, false); +} + +void p1() { + store_32(&flag1, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + + int f0; + while (true) { + int f0 = load_32(&flag0); + if (!f0) { + break; + } + + if (!load_32(&turn)) { + store_32(&flag1, false); + while (1) { + if (load_32(&turn)) + break; + MC2_yield(); + } + + store_32(&flag1, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + } + } + + // std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + store_32(&var, 2); + + store_32(&turn, 0); + // std::atomic_thread_fence(std::memory_order_release); + store_32(&flag1, false); +} + +void p0l(void *a) { + int i; + for(i=0;i> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/linuxlock/benchmark-config.sh b/benchmarks/satcheck/linuxlock/benchmark-config.sh new file mode 100644 index 0000000..a372bfe --- /dev/null +++ b/benchmarks/satcheck/linuxlock/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=linuxlocks +SIZES_SC="1 2 3 4 5 6 7 8 9 10 15 20 30 40 50 60 70 80 90 100 150 200 250" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 15 20 30 40 50 60 70 80 90 100" +RUN_FRONTEND=true +RUNTIME_FLAGS= diff --git a/benchmarks/satcheck/linuxlock/benchtso.sh b/benchmarks/satcheck/linuxlock/benchtso.sh new file mode 100755 index 0000000..bf5af51 --- /dev/null +++ b/benchmarks/satcheck/linuxlock/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/linuxlock/clean.sh b/benchmarks/satcheck/linuxlock/clean.sh new file mode 100755 index 0000000..9a90971 --- /dev/null +++ b/benchmarks/satcheck/linuxlock/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +rm -f linuxlocks.c linuxlocks dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck/linuxlock/compile.sh b/benchmarks/satcheck/linuxlock/compile.sh new file mode 100755 index 0000000..5da0c11 --- /dev/null +++ b/benchmarks/satcheck/linuxlock/compile.sh @@ -0,0 +1,5 @@ +#!/bin/sh +. ../path.sh +. ./benchmark-config.sh +echo $MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.c -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include +$MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.c -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include > ${NAME}.c diff --git a/benchmarks/satcheck/linuxlock/diff.sh b/benchmarks/satcheck/linuxlock/diff.sh new file mode 100755 index 0000000..7c3e7be --- /dev/null +++ b/benchmarks/satcheck/linuxlock/diff.sh @@ -0,0 +1,4 @@ +#!/bin/sh +NAME=linuxlock +diff -ub ../../satcheck-precompiled/$NAME/linuxlocks.c linuxlocks.c + diff --git a/benchmarks/satcheck/linuxlock/linuxlocks_unannotated.c b/benchmarks/satcheck/linuxlock/linuxlocks_unannotated.c new file mode 100644 index 0000000..362080a --- /dev/null +++ b/benchmarks/satcheck/linuxlock/linuxlocks_unannotated.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include "libinterface.h" + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline bool write_trylock(rwlock_t *rw) +{ + int priorvalue=rmw_32(CAS, &rw->lock, 0, 1); + return priorvalue; +} + +static inline void write_unlock(rwlock_t *rw) +{ + store_32(&rw->lock, 0); +} + +rwlock_t * mylock; + +static void foo() { + int flag=write_trylock(mylock); + if (flag) { + } else { + write_unlock(mylock); + } +} + +static void a(void *obj) +{ + int i; + for(i=0;ilock, 0); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + //thrd_create(&t3, (thrd_start_t)&a, NULL); + //thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + //thrd_join(t3); + //thrd_join(t4); + + + + return 0; +} diff --git a/benchmarks/satcheck/linuxrwlock/.gitignore b/benchmarks/satcheck/linuxrwlock/.gitignore new file mode 100644 index 0000000..6f9d7ac --- /dev/null +++ b/benchmarks/satcheck/linuxrwlock/.gitignore @@ -0,0 +1,5 @@ +linuxrwlocks.c +llinuxrwlocks +log_file +logall +linuxrwlocks diff --git a/benchmarks/satcheck/linuxrwlock/bench.sh b/benchmarks/satcheck/linuxrwlock/bench.sh new file mode 100755 index 0000000..2471a37 --- /dev/null +++ b/benchmarks/satcheck/linuxrwlock/bench.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_SC ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/linuxrwlock/benchmark-config.sh b/benchmarks/satcheck/linuxrwlock/benchmark-config.sh new file mode 100644 index 0000000..f2d4907 --- /dev/null +++ b/benchmarks/satcheck/linuxrwlock/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=linuxrwlocks +SIZES_SC="1 2 3 4 5 6 7 8 9 10 15 20" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 15 20" +RUN_FRONTEND=true +RUNTIME_FLAGS= diff --git a/benchmarks/satcheck/linuxrwlock/benchtso.sh b/benchmarks/satcheck/linuxrwlock/benchtso.sh new file mode 100755 index 0000000..bf5af51 --- /dev/null +++ b/benchmarks/satcheck/linuxrwlock/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/linuxrwlock/clean.sh b/benchmarks/satcheck/linuxrwlock/clean.sh new file mode 100755 index 0000000..3a12299 --- /dev/null +++ b/benchmarks/satcheck/linuxrwlock/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +rm -f linuxrwlocks.cc linuxrwlocks dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck/linuxrwlock/compile.sh b/benchmarks/satcheck/linuxrwlock/compile.sh new file mode 100755 index 0000000..5da0c11 --- /dev/null +++ b/benchmarks/satcheck/linuxrwlock/compile.sh @@ -0,0 +1,5 @@ +#!/bin/sh +. ../path.sh +. ./benchmark-config.sh +echo $MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.c -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include +$MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.c -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include > ${NAME}.c diff --git a/benchmarks/satcheck/linuxrwlock/diff.sh b/benchmarks/satcheck/linuxrwlock/diff.sh new file mode 100755 index 0000000..32e6fad --- /dev/null +++ b/benchmarks/satcheck/linuxrwlock/diff.sh @@ -0,0 +1,4 @@ +#!/bin/sh +NAME=linuxrwlock +diff -ub ../../satcheck-precompiled/$NAME/linuxrwlocks.c linuxrwlocks.c + diff --git a/benchmarks/satcheck/linuxrwlock/linuxrwlocks_unannotated.c b/benchmarks/satcheck/linuxrwlock/linuxrwlocks_unannotated.c new file mode 100644 index 0000000..10496dc --- /dev/null +++ b/benchmarks/satcheck/linuxrwlock/linuxrwlocks_unannotated.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include + +#include "libinterface.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline void read_lock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + + while (true) { + if (priorvalue <= 0) { + } else { + break; + } + + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); + + while (true) { + int status = load_32(&rw->lock); + if (status > 0) { + } else { + break; + } + MC2_yield(); + } + + + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + } +} + +static inline void write_lock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + while(true) { + if (priorvalue != RW_LOCK_BIAS) { + } else { + break; + } + + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + + while (true) { + int status = load_32(&rw->lock); + if (status != RW_LOCK_BIAS) { + } else { + break; + } + MC2_yield(); + } + + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + } +} + +static inline bool write_trylock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + + int flag = priorvalue != RW_LOCK_BIAS; + if (!flag) { + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + } + + return flag; +} + +static inline void read_unlock(rwlock_t *rw) +{ + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); +} + +static inline void write_unlock(rwlock_t *rw) +{ + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); +} + +rwlock_t * mylock; +int shareddata; + +static void foo() { + int res = write_trylock(mylock); + if (res) { + write_unlock(mylock); + } else { + } +} + +static void a(void *obj) +{ + int i; + for(i=0;ilock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + // thrd_create(&t3, (thrd_start_t)&a, NULL); + // thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + // thrd_join(t3); + // thrd_join(t4); + free(mylock); + + return 0; +} diff --git a/benchmarks/satcheck/msqueueoffset/.gitignore b/benchmarks/satcheck/msqueueoffset/.gitignore new file mode 100644 index 0000000..44bf736 --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/.gitignore @@ -0,0 +1,6 @@ +ms-queue-simple.c +logall + + +ms-queue-simple +log_file diff --git a/benchmarks/satcheck/msqueueoffset/bench.sh b/benchmarks/satcheck/msqueueoffset/bench.sh new file mode 100755 index 0000000..2471a37 --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/bench.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_SC ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/msqueueoffset/benchmark-config.sh b/benchmarks/satcheck/msqueueoffset/benchmark-config.sh new file mode 100644 index 0000000..96dc596 --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=ms-queue-simple +SIZES_SC="1 2 3 4 5 6 7 8 9 10 11 12 13" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 11 12 13" +RUN_FRONTEND=true +RUNTIME_FLAGS= diff --git a/benchmarks/satcheck/msqueueoffset/benchtso.sh b/benchmarks/satcheck/msqueueoffset/benchtso.sh new file mode 100755 index 0000000..bf5af51 --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.c -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/msqueueoffset/clean.sh b/benchmarks/satcheck/msqueueoffset/clean.sh new file mode 100755 index 0000000..3a12299 --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +rm -f linuxrwlocks.cc linuxrwlocks dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck/msqueueoffset/compile.sh b/benchmarks/satcheck/msqueueoffset/compile.sh new file mode 100755 index 0000000..5da0c11 --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/compile.sh @@ -0,0 +1,5 @@ +#!/bin/sh +. ../path.sh +. ./benchmark-config.sh +echo $MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.c -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include +$MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.c -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include > ${NAME}.c diff --git a/benchmarks/satcheck/msqueueoffset/diff.sh b/benchmarks/satcheck/msqueueoffset/diff.sh new file mode 100755 index 0000000..a835192 --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/diff.sh @@ -0,0 +1,4 @@ +#!/bin/sh +NAME=msqueueoffset +diff -ub ../../satcheck-precompiled/$NAME/ms-queue-simple.c ms-queue-simple.c + diff --git a/benchmarks/satcheck/msqueueoffset/ms-queue-simple.h b/benchmarks/satcheck/msqueueoffset/ms-queue-simple.h new file mode 100644 index 0000000..9f7f11c --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/ms-queue-simple.h @@ -0,0 +1,15 @@ +typedef struct node { + unsigned int value; + struct node * next; +} node_t; + +typedef struct { + struct node * head; + struct node * tail; +} queue_t; + +//void init_queue(queue_t *q, int num_threads); +//void enqueue(queue_t *q, unsigned int val); +//bool dequeue(queue_t *q, unsigned int *retVal); +int get_thread_num(); + diff --git a/benchmarks/satcheck/msqueueoffset/ms-queue-simple_unannotated.c b/benchmarks/satcheck/msqueueoffset/ms-queue-simple_unannotated.c new file mode 100644 index 0000000..6fc7d7f --- /dev/null +++ b/benchmarks/satcheck/msqueueoffset/ms-queue-simple_unannotated.c @@ -0,0 +1,137 @@ +#include +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue-simple.h" +#include "libinterface.h" + +void init_queue(queue_t *q, int num_threads); +void enqueue(queue_t *q, unsigned int val); +bool dequeue(queue_t *q, unsigned int *retVal); + +queue_t queue; + +void init_queue(queue_t *q, int num_threads) { + struct node *newnode=(struct node *)malloc(sizeof (struct node)); + + store_32(&newnode->value, 0); + + + store_64(&newnode->next, (uintptr_t) NULL); + /* initialize queue */ + + store_64(&q->head, (uintptr_t) newnode); + + + store_64(&q->tail, (uintptr_t) newnode); +} + +void enqueue(queue_t *q, unsigned int val) { + struct node *tail; + struct node * node_ptr; node_ptr = (struct node *)malloc(sizeof(struct node)); + + store_32(&node_ptr->value, val); + + + store_64(&node_ptr->next, (uintptr_t) NULL); + + while (true) { + + tail = (struct node *) load_64(&q->tail); + + struct node * next = (struct node *) load_64(&tail->next); + + struct node * qtail = (struct node *) load_64(&q->tail); + + if (tail == qtail) { + if (next) { + MC2_yield(); + } else { + struct node * valread = (struct node *) rmw_64(CAS, &tail->next, (uintptr_t) next, (uintptr_t) node_ptr); + + if (next == valread) { + break; + } else { + } + } + struct node * new_tailptr = (struct node *)load_64(&tail->next); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) new_tailptr); + MC2_yield(); + } else { + MC2_yield(); + } + } + + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) node_ptr); +} + +bool dequeue(queue_t *q, unsigned int *retVal) { + while (true) { + struct node * head = (struct node *) load_64(&q->head); + struct node * tail = (struct node *) load_64(&q->tail); + struct node * next = (struct node *) load_64(&head->next); + + struct node * headr = (struct node *) load_64(&q->head); + + if (head == headr) { + if (head == tail) { + if (next) { + MC2_yield(); + } else { + return false; // NULL + } + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) next); + MC2_yield(); + } else { + *retVal = load_32(&next->value); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) next); + + if (head == old_head) { + return true; + } else { + MC2_yield(); + } + } + } else { + MC2_yield(); + } + } +} + +/* ms-queue-main */ +bool succ1, succ2; + +static void e(void *p) { + int i; + for(i=0;i> log +gcc ${NAME}.cc -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -lsc_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/seqlock/benchmark-config.sh b/benchmarks/satcheck/seqlock/benchmark-config.sh new file mode 100644 index 0000000..ffd0c5f --- /dev/null +++ b/benchmarks/satcheck/seqlock/benchmark-config.sh @@ -0,0 +1,5 @@ +NAME=seqlock +SIZES_SC="1 2 3 4 5 6 7 8 9 10 15 20 25 30 35 40 50 60" +SIZES_TSO="1 2 3 4 5 6 7 8 9 10 15 20 25 30 35 40 50 60" +RUN_FRONTEND=true +RUNTIME_FLAGS=-Y diff --git a/benchmarks/satcheck/seqlock/benchtso.sh b/benchmarks/satcheck/seqlock/benchtso.sh new file mode 100755 index 0000000..3c52574 --- /dev/null +++ b/benchmarks/satcheck/seqlock/benchtso.sh @@ -0,0 +1,16 @@ +#!/bin/bash +source ../path.sh +source benchmark-config.sh +export PATH=$MC2DIR:$PATH +/bin/rm -f log logall +if [ $RUN_FRONTEND == true ]; then + ./compile.sh +fi +for i in $SIZES_TSO ; +do +echo size= $i >> log +gcc ${NAME}.cc -DPROBLEMSIZE=$i -O3 -I$MC2DIR/include -L$MC2DIR -ltso_model -o ${NAME} +export LD_LIBRARY_PATH=$MC2DIR +export DYLD_LIBRARY_PATH=$MC2DIR +(time ./${NAME} ${RUNTIME_FLAGS}) >> logall 2>> log +done diff --git a/benchmarks/satcheck/seqlock/clean.sh b/benchmarks/satcheck/seqlock/clean.sh new file mode 100755 index 0000000..325db38 --- /dev/null +++ b/benchmarks/satcheck/seqlock/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +rm -f seqlock.cc seqlock dimacs.out dimacs.cnf logall log_file diff --git a/benchmarks/satcheck/seqlock/compile.sh b/benchmarks/satcheck/seqlock/compile.sh new file mode 100755 index 0000000..469e6e3 --- /dev/null +++ b/benchmarks/satcheck/seqlock/compile.sh @@ -0,0 +1,5 @@ +#!/bin/sh +. ../path.sh +. ./benchmark-config.sh +echo $MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.cc -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include +$MC2DIR/clang/build/add_mc2_annotations ${NAME}_unannotated.cc -- -DPROBLEMSIZE=1 -I/usr/include -I$CLANG_INCLUDE_DIR -I$MC2DIR/include > ${NAME}.cc diff --git a/benchmarks/satcheck/seqlock/diff.sh b/benchmarks/satcheck/seqlock/diff.sh new file mode 100755 index 0000000..7f89e87 --- /dev/null +++ b/benchmarks/satcheck/seqlock/diff.sh @@ -0,0 +1,4 @@ +#!/bin/sh +NAME=seqlock +diff -ub ../../satcheck-precompiled/$NAME/seqlock.cc seqlock.cc + diff --git a/benchmarks/satcheck/seqlock/seqlock_unannotated.cc b/benchmarks/satcheck/seqlock/seqlock_unannotated.cc new file mode 100644 index 0000000..e380a2e --- /dev/null +++ b/benchmarks/satcheck/seqlock/seqlock_unannotated.cc @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "libinterface.h" + +// Sequence for reader consistency check +/*atomic_*/ int _seq; +// It needs to be atomic to avoid data races +/*atomic_*/ int _data; + +void seqlock_init() { + store_32(&_seq, 0); + store_32(&_data, 10); +} + +int seqlock_read() { + int res; + int old_seq = load_32(&_seq); // acquire + + if (old_seq % 2 == 1) { + res = -1; + } else { + res = load_32(&_data); + int seq = load_32(&_seq); + + if (seq == old_seq) { + } else { + res = -1; + } + } + return res; +} + +int seqlock_write(int new_data) { + int old_seq = load_32(&_seq); + int res; + + if (old_seq % 2 == 1) { + res = 0; + } else { + int new_seq = old_seq + 1; + int cas_value = rmw_32(CAS, &_seq, old_seq, new_seq); + + if (cas_value == old_seq) { + // Update the data + store_32(&_data, new_data); + rmw_32(ADD, &_seq, /* dummy */0, 1); + res = 1; + } else { + res = 0; + } + } + return res; +} + +static void a(void *obj) { + int q; + for (int i = 0; i < PROBLEMSIZE; i++) { + q = seqlock_write(30); + } + +} + +static void b(void *obj) { + int r1; + for (int i = 0; i < PROBLEMSIZE; i++) { + r1 = seqlock_read(); + } + +} + +static void c(void *obj) { + int r1; + for (int i = 0; i < PROBLEMSIZE; i++) { + r1 = seqlock_read(); + } + +} + +int user_main(int argc, char **argv) { + thrd_t t1; thrd_t t2; thrd_t t3; + seqlock_init(); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + thrd_create(&t3, (thrd_start_t)&c, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + + + return 0; +} diff --git a/benchmarks/verifycompilesat b/benchmarks/verifycompilesat new file mode 100755 index 0000000..6227066 --- /dev/null +++ b/benchmarks/verifycompilesat @@ -0,0 +1,4 @@ +#!/bin/bash +# note: should do something about seqlock, which is .cc not .c +for c in dekker linuxlock linuxrwlock msqueueoffset ; do (. satcheck/$c/benchmark-config.sh; diff -u satcheck-precompiled/$c/$NAME.c satcheck/$c/$NAME.c) done +for c in seqlock ; do (. satcheck/$c/benchmark-config.sh; diff -u satcheck-precompiled/$c/$NAME.cc satcheck/$c/$NAME.cc) done diff --git a/bin/annotate b/bin/annotate new file mode 100755 index 0000000..d60ffa5 --- /dev/null +++ b/bin/annotate @@ -0,0 +1,7 @@ +#!/bin/bash +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +MC2DIR=`dirname $DIR` +CLANG_INCLUDE_DIR=/usr/lib/llvm-3.7/lib/clang/3.7.0/include + +$MC2DIR/clang/build/add_mc2_annotations $1 -- -DPROBLEMSIZE=1 -I/usr/include -I$MC2DIR/include -I$CLANG_INCLUDE_DIR + diff --git a/branchrecord.cc b/branchrecord.cc new file mode 100644 index 0000000..e55aa24 --- /dev/null +++ b/branchrecord.cc @@ -0,0 +1,59 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "branchrecord.h" +#include "mymemory.h" +#include "constraint.h" +#include "eprecord.h" + +BranchRecord::BranchRecord(EPRecord *r, uint nvars, Constraint **cvars, bool isalwaysexecuted) : + branch(r), + hasNext(r->getNextRecord()!=NULL), + numvars(nvars), + numdirections(r->numValues()), + alwaysexecuted(isalwaysexecuted), + vars((Constraint **)model_malloc(sizeof(Constraint *)*nvars)) { + memcpy(vars, cvars, sizeof(Constraint *)*nvars); +} + +BranchRecord::~BranchRecord() { + model_free(vars); +} + +Constraint * BranchRecord::getAnyBranch() { + if (alwaysexecuted) + return &ctrue; + else + return new Constraint(OR, numvars, vars); +} + +Constraint * BranchRecord::getNewBranch() { + return new Constraint(AND, numvars, vars); +} + +Constraint * BranchRecord::getBranch(EPValue *val) { + int index=branch->getIndex(val); + ASSERT(index>=0); + if (!alwaysexecuted) + index++; + return generateConstraint(numvars, vars, index); +} + +int BranchRecord::getBranchValue(bool * array) { + uint value=0; + for(int j=numvars-1;j>=0;j--) { + value=value<<1; + if (array[vars[j]->getVar()]) + value|=1; + } + if (!alwaysexecuted) + value--; + + return value; +} diff --git a/branchrecord.h b/branchrecord.h new file mode 100644 index 0000000..aa5e4a2 --- /dev/null +++ b/branchrecord.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef BRANCHRECORD_H +#define BRANCHRECORD_H +#include "classlist.h" + +class BranchRecord { + public: + BranchRecord(EPRecord *record, uint numvars, Constraint **vars, bool isalwaysexecuted); + ~BranchRecord(); + Constraint * getAnyBranch(); + Constraint * getBranch(EPValue *val); + Constraint * getNewBranch(); + int getBranchValue(bool *array); + int numDirections() {return numdirections;} + bool hasNextRecord() {return hasNext;} + MEMALLOC; + private: + EPRecord *branch; + bool hasNext; + uint numvars; + uint numdirections; + bool alwaysexecuted; + Constraint **vars; +}; +#endif diff --git a/cgoal.cc b/cgoal.cc new file mode 100644 index 0000000..95c26ab --- /dev/null +++ b/cgoal.cc @@ -0,0 +1,61 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "cgoal.h" +#include "execpoint.h" +#include "eprecord.h" + +CGoal::CGoal(unsigned int _num, uint64_t *vals) : + outputvalue(0), + num(_num), + hash(_num) +{ + valarray=(uint64_t *)model_malloc(sizeof(uint64_t)*num); + for(unsigned int i=0;ihash!=cg2->hash|| + cg1->num!=cg2->num) + return false; + if (cg1->valarray) { + for(unsigned int i=0;inum;i++) { + if (cg1->valarray[i]!=cg2->valarray[i]) + return false; + } + } + + return true; +} + +unsigned int CGoalHash(CGoal *cg) { + return cg->hash; +} + diff --git a/cgoal.h b/cgoal.h new file mode 100644 index 0000000..3374062 --- /dev/null +++ b/cgoal.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef C_GOAL_H +#define C_GOAL_H +#include "classlist.h" +#include "mymemory.h" +#include "hashset.h" +#include + +class CGoal { + public: + CGoal(unsigned int num, uint64_t *vals); + ~CGoal(); + unsigned int getNum() {return num;} + uint64_t getValue(unsigned int i) {return valarray[i];} + void setOutput(uint64_t _output) { outputvalue=_output;} + uint64_t getOutput() {return outputvalue;} + void print(); + + MEMALLOC; + private: + uint64_t * valarray; + uint64_t outputvalue; + unsigned int num; + unsigned int hash; + + friend bool CGoalEquals(CGoal *cg1, CGoal *cg2); + friend unsigned int CGoalHash(CGoal *cg); +}; + +bool CGoalEquals(CGoal *cg1, CGoal *cg2); +unsigned int CGoalHash(CGoal *cg); + +typedef HashSet CGoalSet; +typedef HSIterator CGoalIterator; + +#endif diff --git a/change.cc b/change.cc new file mode 100644 index 0000000..86de570 --- /dev/null +++ b/change.cc @@ -0,0 +1,38 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "change.h" + +MCChange::MCChange(EPRecord * _record, uint64_t _val, unsigned int _index) : + record(_record), + val(_val), + index(_index) +{ + ASSERT(record->getType()!=BRANCHDIR); +} + +MCChange::~MCChange() { +} + +void MCChange::print() { + record->print(); + model_print("("); + model_print("index=%u, val=%lu)\n", index, val); +} + +bool MCChangeEquals(MCChange *mcc1, MCChange *mcc2) { + if (mcc1==NULL) + return mcc1==mcc2; + return (mcc1->record==mcc2->record) && (mcc1->val==mcc2->val) && (mcc1->index == mcc2->index); +} + +unsigned int MCChangeHash(MCChange *mcc) { + return ((unsigned int)((uintptr_t)mcc->record))^((unsigned int)mcc->val)^mcc->index; +} + diff --git a/change.h b/change.h new file mode 100644 index 0000000..f2e0bef --- /dev/null +++ b/change.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef CHANGE_H +#define CHANGE_H +#include "classlist.h" +#include "mymemory.h" +#include +#include "eprecord.h" + +class MCChange { + public: + MCChange(EPRecord *record, uint64_t _val, unsigned int _index); + ~MCChange(); + EPRecord *getRecord() {return record;} + int getIndex() {return index;} + uint64_t getValue() {return val;} + bool isRMW() {return record->getType()==RMW;} + bool isFunction() {return record->getType()==FUNCTION;} + bool isEquals() {return record->getType()==EQUALS;} + bool isLoad() {return record->getType()==LOAD;} + bool isStore() {return record->getType()==STORE;} + void print(); + MEMALLOC; + + private: + EPRecord *record; + uint64_t val; + unsigned int index; + friend bool MCChangeEquals(MCChange *mcc1, MCChange *mcc2); + friend unsigned int MCChangeHash(MCChange *mcc); +}; + +bool MCChangeEquals(MCChange *mcc1, MCChange *mcc2); +unsigned int MCChangeHash(MCChange *mcc); +#endif diff --git a/clang/.gitignore b/clang/.gitignore new file mode 100644 index 0000000..2928847 --- /dev/null +++ b/clang/.gitignore @@ -0,0 +1,4 @@ +build +*~ + + diff --git a/clang/COPYING b/clang/COPYING new file mode 100644 index 0000000..b3dcc98 --- /dev/null +++ b/clang/COPYING @@ -0,0 +1,14 @@ +Copyright (c) 2015 Patrick Lam +All rights reserved. + +Developed by: Patrick Lam + University of Waterloo + http://patricklam.ca + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. + Neither the names of the University of Waterloo, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. \ No newline at end of file diff --git a/clang/Makefile b/clang/Makefile new file mode 100644 index 0000000..5b8ed2d --- /dev/null +++ b/clang/Makefile @@ -0,0 +1,92 @@ +#------------------------------------------------------------------------------- +# Sample makefile for building the code samples. Read inline comments for +# documentation. +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- + +# The following variables will likely need to be customized, depending on where +# and how you built LLVM & Clang. They can be overridden by setting them on the +# make command line: "make VARNAME=VALUE", etc. + +LLVM_VERSION := -3.8 + +# CXX has to be a fairly modern C++ compiler that supports C++11. gcc 4.8 and +# higher or Clang 3.2 and higher are recommended. Best of all, if you build LLVM +# from sources, use the same compiler you built LLVM with. +CXX := clang++$(LLVM_VERSION) +CXXFLAGS := -fno-rtti -g +PLUGIN_CXXFLAGS := -fpic + +LLVM_CXXFLAGS := `llvm-config$(LLVM_VERSION) --cxxflags` +LLVM_LDFLAGS := `llvm-config$(LLVM_VERSION) --ldflags --libs --system-libs` + +# Plugins shouldn't link LLVM and Clang libs statically, because they are +# already linked into the main executable (opt or clang). LLVM doesn't like its +# libs to be linked more than once because it uses globals for configuration +# and plugin registration, and these trample over each other. +LLVM_LDFLAGS_NOLIBS := `llvm-config$(LLVM_VERSION) --ldflags` +PLUGIN_LDFLAGS := -shared + +CLANG_INCLUDES := -I/usr/lib/llvm$(LLVM_VERSION)/include + +# List of Clang libraries to link. The proper -L will be provided by the +# call to llvm-config +# Note that I'm using -Wl,--{start|end}-group around the Clang libs; this is +# because there are circular dependencies that make the correct order difficult +# to specify and maintain. The linker group options make the linking somewhat +# slower, but IMHO they're still perfectly fine for tools that link with Clang. +CLANG_LIBS := \ + -Wl,--start-group \ + -lclangAST \ + -lclangAnalysis \ + -lclangBasic \ + -lclangDriver \ + -lclangEdit \ + -lclangFrontend \ + -lclangFrontendTool \ + -lclangLex \ + -lclangParse \ + -lclangSema \ + -lclangEdit \ + -lclangASTMatchers \ + -lclangRewrite \ + -lclangRewriteFrontend \ + -lclangStaticAnalyzerFrontend \ + -lclangStaticAnalyzerCheckers \ + -lclangStaticAnalyzerCore \ + -lclangSerialization \ + -lclangToolingCore \ + -lclangTooling \ + -Wl,--end-group + +# Internal paths in this project: where to find sources, and where to put +# build artifacts. +SRC_DIR := src +BUILDDIR := build + +.PHONY: all +all: make_builddir \ + emit_build_config \ + $(BUILDDIR)/add_mc2_annotations + +.PHONY: test +test: emit_build_config + python3 test/all_tests.py + +.PHONY: emit_build_config +emit_build_config: make_builddir + @echo $(LLVM_BIN_PATH) > $(BUILDDIR)/_build_config + +.PHONY: make_builddir +make_builddir: + @test -d $(BUILDDIR) || mkdir $(BUILDDIR) + +$(BUILDDIR)/add_mc2_annotations: $(SRC_DIR)/add_mc2_annotations.cpp + $(CXX) $(CXXFLAGS) $(LLVM_CXXFLAGS) $(CLANG_INCLUDES) $^ \ + $(CLANG_LIBS) $(LLVM_LDFLAGS) -o $@ + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* *.dot test/*.pyc test/__pycache__ diff --git a/clang/README.md b/clang/README.md new file mode 100644 index 0000000..91e70ff --- /dev/null +++ b/clang/README.md @@ -0,0 +1,55 @@ +Contains a Clang extension which generates MC2 calls based on calls already in the code. + +* To compile this code, you need to modify the build paths in +the Makefile; point them at your LLVM build. Then running 'make' should work. + +* To run the code, you can specify the include directories explicitly: + +build/add_mc2_annotations ../test/userprog_unannotated.c -- -I/usr/include -I../../llvm/tools/clang/lib/Headers -I../include + +I can't figure out how to make Clang's compilation database work for me. + +* Currently, the tool will fail if it tries to rewrite any code that uses macros. +One example of a macro is "bool". + +The following StackOverflow link explains how to overcome that problem. + +http://stackoverflow.com/questions/24062989/clang-fails-replacing-a-statement-if-it-contains-a-macro + +It's on the TODO list. + +* The tool won't deal properly with a malloc hidden behind a cast, +e.g. (struct node *) malloc(sizeof(struct node *)). You don't need to +cast the malloc. Ignoring the cast is on the TODO list, but not done yet. + +* Naked loads aren't allowed, e.g. Load_32(&x) without y = Load.... + +This is especially relevant in the context of a loop, e.g. while (Load_32(&x)). + +> for (int i = 0; i < PROBLEMSIZE; i++) +> r1 = seqlock_read(); + +* for loops with a non-CompoundStmt body can generate wrong code +* if you throw away the return value (just "seqlock_read()"), then the rewriter won't work right either + + +linuxlock, linuxrwlock. +* I changed the global 'mylock' variable so that it's allocated on the heap, not +as a global variable. +* Should I look into the fact that linuxlock now generates nextOpStoreOffset rather than nextOpStore +as in the golden master? That is probably actually correct. + +----- + +1. variables of union type which are allocated as global variable and then nextOpStoreOffset'd cause a problem +2. boolean types are handled as macros and so there's no source position +3. if statements with conds like "if (write_trylock(mylock))" don't work. +4. malloc on vardecl (e.g. struct node * node_ptr = (struct node *)malloc) don't always get mc2_function generated for them [ms-queue-simple] +5. nextOpLoadOffset not generated in following case: + + MCID _fn1; struct node ** tail_ptr_next= & tail->next; + _fn1 = MC2_function_id(2, 1, sizeof (tail_ptr_next), (uint64_t)tail_ptr_next, _mtail); + + MCID _mnext; _mnext=MC2_nextOpLoadOffset(_fn1, MC2_OFFSET(struct node *, next)); struct node * next = (struct node *) load_64(tail_ptr_next); + +currently we generate nextOpLoad. diff --git a/clang/multi-dep.txt b/clang/multi-dep.txt new file mode 100644 index 0000000..61328f3 --- /dev/null +++ b/clang/multi-dep.txt @@ -0,0 +1,9 @@ +do we properly handle this case? + +lv1 = load_64(&x); + +lv2 = lv1 + 5; + +if (lv2) + +--- lv2 should also be mc-visible diff --git a/clang/src/add_mc2_annotations.cpp b/clang/src/add_mc2_annotations.cpp new file mode 100644 index 0000000..1b7c926 --- /dev/null +++ b/clang/src/add_mc2_annotations.cpp @@ -0,0 +1,1534 @@ +// -*- indent-tabs-mode:nil; -*- +//------------------------------------------------------------------------------ +// Add MC2 annotations to C code. +// Copyright 2015 Patrick Lam +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal with the Software without +// restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimers. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimers in +// the documentation and/or other materials provided with the +// distribution. +// +// Neither the names of the University of Waterloo, nor the names of +// its contributors may be used to endorse or promote products derived +// from this Software without specific prior written permission. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS WITH THE SOFTWARE. +// +// Patrick Lam (prof.lam@gmail.com) +// +// Base code: +// Eli Bendersky (eliben@gmail.com) +// +//------------------------------------------------------------------------------ +#include +#include +#include +#include + +#include "clang/AST/AST.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Frontend/ASTConsumers.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Lex/Lexer.h" +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Tooling.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/STLExtras.h" + +using namespace clang; +using namespace clang::ast_matchers; +using namespace clang::driver; +using namespace clang::tooling; +using namespace llvm; + +static LangOptions LangOpts; +static llvm::cl::OptionCategory AddMC2AnnotationsCategory("Add MC2 Annotations"); + +static std::string encode(std::string varName) { + std::stringstream nn; + nn << "_m" << varName; + return nn.str(); +} + +static int fnCount; +static std::string encodeFn(int num) { + std::stringstream nn; + nn << "_fn" << num; + return nn.str(); +}; + +static int ptrCount; +static std::string encodePtr(int num) { + std::stringstream nn; + nn << "_p" << num; + return nn.str(); +}; + +static int rmwCount; +static std::string encodeRMW(int num) { + std::stringstream nn; + nn << "_rmw" << num; + return nn.str(); +}; + +static int branchCount; +static std::string encodeBranch(int num) { + std::stringstream nn; + nn << "_br" << num; + return nn.str(); +}; + +static int condCount; +static std::string encodeCond(int num) { + std::stringstream nn; + nn << "_cond" << num; + return nn.str(); +}; + +static int rvCount; +static std::string encodeRV(int num) { + std::stringstream nn; + nn << "_rv" << num; + return nn.str(); +}; + +static int funcCount; + +struct ProvisionalName { + int index, length; + const DeclRefExpr * pname; + bool enabled; + + ProvisionalName(int index, const DeclRefExpr * pname) : index(index), pname(pname), length(encode(pname->getNameInfo().getName().getAsString()).length()), enabled(true) {} + ProvisionalName(int index, const DeclRefExpr * pname, int length) : index(index), pname(pname), length(length), enabled(true) {} +}; + +struct Update { + SourceLocation loc; + std::string update; + std::vector * pnames; + + Update(SourceLocation loc, std::string update, std::vector * pnames) : + loc(loc), update(update), pnames(pnames) {} + + ~Update() { + for (auto pname : *pnames) delete pname; + delete pnames; + } +}; + +void updateProvisionalName(std::vector &DeferredUpdates, const ValueDecl * now_known, std::string mcVar) { + for (Update * u : DeferredUpdates) { + for (int i = 0; i < u->pnames->size(); i++) { + ProvisionalName * v = (*(u->pnames))[i]; + if (!v->enabled) continue; + if (now_known == v->pname->getDecl()) { + v->enabled = false; + std::string oldName = encode(v->pname->getNameInfo().getName().getAsString()); + + u->update.replace(v->index, v->length, mcVar); + for (int j = i+1; j < u->pnames->size(); j++) { + ProvisionalName * vv = (*(u->pnames))[j]; + if (vv->index > v->index) + vv->index -= v->length - mcVar.length(); + } + } + } + } +} + +static const VarDecl * retrieveSingleDecl(const DeclStmt * s) { + // XXX iterate through all decls defined in s, not just the first one + assert(s->isSingleDecl() && isa(s->getSingleDecl()) && "unsupported form of decl"); + if (s->isSingleDecl() && isa(s->getSingleDecl())) { + return cast(s->getSingleDecl()); + } else return NULL; +} + +class FindCallArgVisitor : public RecursiveASTVisitor { +public: + FindCallArgVisitor() : DE(NULL), UnaryOp(NULL) {} + + bool VisitStmt(Stmt * s) { + if (!UnaryOp) { + if (UnaryOperator * uo = dyn_cast(s)) { + if (uo->getOpcode() == UnaryOperatorKind::UO_AddrOf || + uo->getOpcode() == UnaryOperatorKind::UO_Deref) + UnaryOp = uo; + } + } + + if (!DE && (DE = dyn_cast(s))) + ; + return true; + } + + void Clear() { + UnaryOp = NULL; DE = NULL; + } + + const UnaryOperator * RetrieveUnaryOp() { + if (UnaryOp) { + bool found = false; + const Stmt * s = UnaryOp; + while (s != NULL) { + if (s == DE) { + found = true; break; + } + + if (const UnaryOperator * op = dyn_cast(s)) + s = op->getSubExpr(); + else if (const CastExpr * op = dyn_cast(s)) + s = op->getSubExpr(); + else if (const MemberExpr * op = dyn_cast(s)) + s = op->getBase(); + else + s = NULL; + } + if (found) + return UnaryOp; + } + return NULL; + } + + const DeclRefExpr * RetrieveDeclRefExpr() { + return DE; + } + +private: + const UnaryOperator * UnaryOp; + const DeclRefExpr * DE; +}; + +class FindLocalsVisitor : public RecursiveASTVisitor { +public: + FindLocalsVisitor() : Vars() {} + + bool VisitDeclRefExpr(DeclRefExpr * de) { + Vars.push_back(de->getDecl()); + return true; + } + + void Clear() { + Vars.clear(); + } + + const TinyPtrVector RetrieveVars() { + return Vars; + } + +private: + TinyPtrVector Vars; +}; + + +class MallocHandler : public MatchFinder::MatchCallback { +public: + MallocHandler(std::set & MallocExprs) : + MallocExprs(MallocExprs) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + const CallExpr * ce = Result.Nodes.getNodeAs("callExpr"); + + MallocExprs.insert(ce); + } + + private: + std::set &MallocExprs; +}; + +static void generateMC2Function(Rewriter & Rewrite, + const Expr * e, + SourceLocation loc, + std::string tmpname, + std::string tmpFn, + const DeclRefExpr * lhs, + std::string lhsName, + std::vector * vars1, + std::vector & DeferredUpdates) { + // prettyprint the LHS (&newnode->value) + // e.g. int * _tmp0 = &newnode->value; + std::string SStr; + llvm::raw_string_ostream S(SStr); + e->printPretty(S, nullptr, Rewrite.getLangOpts()); + const std::string &Str = S.str(); + + std::stringstream prel; + prel << "\nvoid * " << tmpname << " = " << Str << ";\n"; + + // MCID _p0 = MC2_function(1, MC2_PTR_LENGTH, _tmp0, _fn0); + prel << "MCID " << tmpFn << " = MC2_function_id(" << ++funcCount << ", 1, MC2_PTR_LENGTH, " << tmpname << ", "; + if (lhs) { + // XXX generate casts when they'd eliminate warnings + ProvisionalName * v = new ProvisionalName(prel.tellp(), lhs); + vars1->push_back(v); + } + prel << encode(lhsName) << "); "; + + Update * u = new Update(loc, prel.str(), vars1); + DeferredUpdates.push_back(u); +} + +class LoadHandler : public MatchFinder::MatchCallback { +public: + LoadHandler(Rewriter &Rewrite, + std::set & DeclsRead, + std::set & DeclsNeedingMC, + std::map &DeclToMCVar, + std::map &ExprToMCVar, + std::set & StmtsHandled, + std::map &Redirector, + std::vector & DeferredUpdates) : + Rewrite(Rewrite), DeclsRead(DeclsRead), DeclsNeedingMC(DeclsNeedingMC), DeclToMCVar(DeclToMCVar), + ExprToMCVar(ExprToMCVar), + StmtsHandled(StmtsHandled), Redirector(Redirector), DeferredUpdates(DeferredUpdates) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + std::vector * vars = new std::vector(); + CallExpr * ce = const_cast(Result.Nodes.getNodeAs("callExpr")); + const VarDecl * d = Result.Nodes.getNodeAs("decl"); + const Stmt * s = Result.Nodes.getNodeAs("containingStmt"); + const Expr * lhs = NULL; + if (s && isa(s)) lhs = cast(s)->getLHS(); + if (!s) s = ce; + + const DeclRefExpr * rhs = NULL; + MemberExpr * ml = NULL; + bool isAddrOfR = false, isAddrMemberR = false; + + StmtsHandled.insert(s); + + std::string n, n_decl; + if (lhs) { + FindCallArgVisitor fcaVisitor; + fcaVisitor.Clear(); + fcaVisitor.TraverseStmt(ce->getArg(0)); + rhs = cast(fcaVisitor.RetrieveDeclRefExpr()->IgnoreParens()); + const UnaryOperator * ruop = fcaVisitor.RetrieveUnaryOp(); + isAddrOfR = ruop && ruop->getOpcode() == UnaryOperatorKind::UO_AddrOf; + isAddrMemberR = ruop && isa(ruop->getSubExpr()); + if (isAddrMemberR) + ml = dyn_cast(ruop->getSubExpr()); + + FindLocalsVisitor flv; + flv.Clear(); + flv.TraverseStmt(const_cast(cast(lhs))); + for (auto & d : flv.RetrieveVars()) { + const VarDecl * dd = cast(d); + n = dd->getName(); + // XXX todo rhs for non-decl stmts + if (!isa(dd)) + DeclsNeedingMC.insert(dd); + DeclsRead.insert(d); + DeclToMCVar[dd] = encode(n); + } + } else { + FindCallArgVisitor fcaVisitor; + fcaVisitor.Clear(); + fcaVisitor.TraverseStmt(ce->getArg(0)); + rhs = cast(fcaVisitor.RetrieveDeclRefExpr()->IgnoreParens()); + const UnaryOperator * ruop = fcaVisitor.RetrieveUnaryOp(); + isAddrOfR = ruop && ruop->getOpcode() == UnaryOperatorKind::UO_AddrOf; + isAddrMemberR = ruop && isa(ruop->getSubExpr()); + if (isAddrMemberR) + ml = dyn_cast(ruop->getSubExpr()); + + if (d) { + n = d->getName(); + DeclsNeedingMC.insert(d); + DeclsRead.insert(d); + DeclToMCVar[d] = encode(n); + } else { + n = ExprToMCVar[ce]; + fcaVisitor.Clear(); + fcaVisitor.TraverseStmt(ce); + const DeclRefExpr * dd = cast(fcaVisitor.RetrieveDeclRefExpr()->IgnoreParens()); + updateProvisionalName(DeferredUpdates, dd->getDecl(), encode(n)); + DeclToMCVar[dd->getDecl()] = encode(n); + n_decl = "MCID "; + } + } + + std::stringstream nol; + + if (lhs && isa(lhs)) { + const DeclRefExpr * ll = cast(lhs); + ProvisionalName * v = new ProvisionalName(nol.tellp(), ll); + vars->push_back(v); + } + + if (rhs) { + if (isAddrMemberR) { + if (!n.empty()) + nol << n_decl << encode(n) << "="; + nol << "MC2_nextOpLoadOffset("; + + ProvisionalName * v = new ProvisionalName(nol.tellp(), rhs); + vars->push_back(v); + nol << encode(rhs->getNameInfo().getName().getAsString()); + + nol << ", MC2_OFFSET("; + nol << ml->getBase()->getType().getAsString(); + nol << ", "; + nol << ml->getMemberDecl()->getName().str(); + nol << ")"; + } else if (!isAddrOfR) { + if (!n.empty()) + nol << n_decl << encode(n) << "="; + nol << "MC2_nextOpLoad("; + ProvisionalName * v = new ProvisionalName(nol.tellp(), rhs); + vars->push_back(v); + nol << encode(rhs->getNameInfo().getName().getAsString()); + } else { + if (!n.empty()) + nol << n_decl << encode(n) << "="; + nol << "MC2_nextOpLoad("; + nol << "MCID_NODEP"; + } + } else { + if (!n.empty()) + nol << n_decl << encode(n) << "="; + nol << "MC2_nextOpLoad("; + nol << "MCID_NODEP"; + } + + if (lhs) + nol << "), "; + else + nol << "); "; + SourceLocation ss = s->getLocStart(); + // eek gross hack: + // if the load appears as its own stmt and is the 1st stmt, containingStmt may be the containing CompoundStmt; + // move over 1 so that we get the right location. + if (isa(s)) ss = ss.getLocWithOffset(1); + const Expr * e = dyn_cast(s); + if (e && Redirector.count(e) > 0) + ss = Redirector[e]; + Update * u = new Update(ss, nol.str(), vars); + DeferredUpdates.insert(DeferredUpdates.begin(), u); + } + + private: + Rewriter &Rewrite; + std::set & DeclsRead; + std::set & DeclsNeedingMC; + std::map &ExprToMCVar; + std::map &DeclToMCVar; + std::set &StmtsHandled; + std::vector &DeferredUpdates; + std::map &Redirector; +}; + +class StoreHandler : public MatchFinder::MatchCallback { +public: + StoreHandler(Rewriter &Rewrite, + std::set & DeclsRead, + std::set &DeclsNeedingMC, + std::vector & DeferredUpdates) : + Rewrite(Rewrite), DeclsRead(DeclsRead), DeclsNeedingMC(DeclsNeedingMC), DeferredUpdates(DeferredUpdates) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + std::vector * vars = new std::vector(); + CallExpr * ce = const_cast(Result.Nodes.getNodeAs("callExpr")); + + fcaVisitor.Clear(); + fcaVisitor.TraverseStmt(ce->getArg(0)); + const DeclRefExpr * lhs = fcaVisitor.RetrieveDeclRefExpr(); + const UnaryOperator * luop = fcaVisitor.RetrieveUnaryOp(); + + std::stringstream nol; + + bool isAddrMemberL; + bool isAddrOfL; + + if (luop && luop->getOpcode() == UnaryOperatorKind::UO_AddrOf) { + isAddrMemberL = isa(luop->getSubExpr()); + isAddrOfL = !isa(luop->getSubExpr()); + } + + if (lhs) { + if (isAddrOfL) { + nol << "MC2_nextOpStore("; + nol << "MCID_NODEP"; + } else { + if (isAddrMemberL) { + MemberExpr * ml = cast(luop->getSubExpr()); + + nol << "MC2_nextOpStoreOffset("; + + ProvisionalName * v = new ProvisionalName(nol.tellp(), lhs); + vars->push_back(v); + + nol << encode(lhs->getNameInfo().getName().getAsString()); + if (!isa(lhs->getDecl())) + DeclsNeedingMC.insert(cast(lhs->getDecl())); + + nol << ", MC2_OFFSET("; + nol << ml->getBase()->getType().getAsString(); + nol << ", "; + nol << ml->getMemberDecl()->getName().str(); + nol << ")"; + } else { + nol << "MC2_nextOpStore("; + ProvisionalName * v = new ProvisionalName(nol.tellp(), lhs); + vars->push_back(v); + + nol << encode(lhs->getNameInfo().getName().getAsString()); + } + } + } + else { + nol << "MC2_nextOpStore("; + nol << "MCID_NODEP"; + } + + nol << ", "; + + fcaVisitor.Clear(); + fcaVisitor.TraverseStmt(ce->getArg(1)); + const DeclRefExpr * rhs = fcaVisitor.RetrieveDeclRefExpr(); + const UnaryOperator * ruop = fcaVisitor.RetrieveUnaryOp(); + + bool isAddrOfR = ruop && ruop->getOpcode() == UnaryOperatorKind::UO_AddrOf; + bool isDerefR = ruop && ruop->getOpcode() == UnaryOperatorKind::UO_Deref; + + if (rhs && !isAddrOfR) { + assert (!isDerefR && "Must use atomic load for dereferences!"); + ProvisionalName * v = new ProvisionalName(nol.tellp(), rhs); + vars->push_back(v); + + nol << encode(rhs->getNameInfo().getName().getAsString()); + DeclsRead.insert(rhs->getDecl()); + } + else + nol << "MCID_NODEP"; + + nol << ");\n"; + Update * u = new Update(ce->getLocStart(), nol.str(), vars); + DeferredUpdates.push_back(u); + } + + private: + Rewriter &Rewrite; + FindCallArgVisitor fcaVisitor; + std::set & DeclsRead; + std::set & DeclsNeedingMC; + std::vector &DeferredUpdates; +}; + +class RMWHandler : public MatchFinder::MatchCallback { +public: + RMWHandler(Rewriter &rewrite, + std::set & DeclsRead, + std::set & DeclsInCond, + std::map &DeclToMCVar, + std::map &ExprToMCVar, + std::set & StmtsHandled, + std::map &Redirector, + std::vector & DeferredUpdates) : + rewrite(rewrite), DeclsRead(DeclsRead), DeclsInCond(DeclsInCond), DeclToMCVar(DeclToMCVar), + ExprToMCVar(ExprToMCVar), + StmtsHandled(StmtsHandled), Redirector(Redirector), DeferredUpdates(DeferredUpdates) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + CallExpr * ce = const_cast(Result.Nodes.getNodeAs("callExpr")); + const Stmt * s = Result.Nodes.getNodeAs("containingStmt"); + std::vector * vars = new std::vector(); + + std::stringstream nol; + + std::string rmwMCVar; + rmwMCVar = encodeRMW(rmwCount++); + + const VarDecl * rmw_lhs; + if (s) { + StmtsHandled.insert(s); + assert (isa(s) || isa(s) && "unknown RMW format: not declrefexpr, not binaryoperator"); + const DeclStmt * ds; + if ((ds = dyn_cast(s))) { + rmw_lhs = retrieveSingleDecl(ds); + } else { + const Expr * e = cast(s)->getLHS(); + assert (isa(e)); + rmw_lhs = cast(cast(e)->getDecl()); + } + DeclToMCVar[rmw_lhs] = rmwMCVar; + } + + // retrieve effective LHS of the RMW + fcaVisitor.Clear(); + fcaVisitor.TraverseStmt(ce->getArg(1)); + const DeclRefExpr * elhs = fcaVisitor.RetrieveDeclRefExpr(); + const UnaryOperator * eluop = fcaVisitor.RetrieveUnaryOp(); + bool isAddrMemberL = false; + + if (eluop && eluop->getOpcode() == UnaryOperatorKind::UO_AddrOf) { + isAddrMemberL = isa(eluop->getSubExpr()); + } + + nol << "MCID " << rmwMCVar; + if (isAddrMemberL) { + MemberExpr * ml = cast(eluop->getSubExpr()); + + nol << " = MC2_nextRMWOffset("; + + ProvisionalName * v = new ProvisionalName(nol.tellp(), elhs); + vars->push_back(v); + + nol << encode(elhs->getNameInfo().getName().getAsString()); + + nol << ", MC2_OFFSET("; + nol << ml->getBase()->getType().getAsString(); + nol << ", "; + nol << ml->getMemberDecl()->getName().str(); + nol << ")"; + } else { + nol << " = MC2_nextRMW("; + bool isAddrOfL = eluop && eluop->getOpcode() == UnaryOperatorKind::UO_AddrOf; + + if (elhs) { + if (isAddrOfL) + nol << "MCID_NODEP"; + else { + ProvisionalName * v = new ProvisionalName(nol.tellp(), elhs); + vars->push_back(v); + + std::string elhsName = encode(elhs->getNameInfo().getName().getAsString()); + nol << elhsName; + } + } + else + nol << "MCID_NODEP"; + } + nol << ", "; + + // handle both RHS ops + int outputted = 0; + for (int arg = 2; arg < 4; arg++) { + fcaVisitor.Clear(); + fcaVisitor.TraverseStmt(ce->getArg(arg)); + const DeclRefExpr * a = fcaVisitor.RetrieveDeclRefExpr(); + const UnaryOperator * op = fcaVisitor.RetrieveUnaryOp(); + + bool isAddrOfR = op && op->getOpcode() == UnaryOperatorKind::UO_AddrOf; + bool isDerefR = op && op->getOpcode() == UnaryOperatorKind::UO_Deref; + + if (a && !isAddrOfR) { + assert (!isDerefR && "Must use atomic load for dereferences!"); + + DeclsInCond.insert(a->getDecl()); + + if (outputted > 0) nol << ", "; + outputted++; + + bool alreadyMCVar = false; + if (DeclToMCVar.find(a->getDecl()) != DeclToMCVar.end()) { + alreadyMCVar = true; + nol << DeclToMCVar[a->getDecl()]; + } + else { + std::string an = "MCID_NODEP"; + ProvisionalName * v = new ProvisionalName(nol.tellp(), a, an.length()); + nol << an; + vars->push_back(v); + } + + DeclsRead.insert(a->getDecl()); + } + else { + if (outputted > 0) nol << ", "; + outputted++; + + nol << "MCID_NODEP"; + } + } + nol << ");\n"; + + SourceLocation place = s ? s->getLocStart() : ce->getLocStart(); + const Expr * e = s ? dyn_cast(s) : ce; + if (e && Redirector.count(e) > 0) + place = Redirector[e]; + Update * u = new Update(place, nol.str(), vars); + DeferredUpdates.insert(DeferredUpdates.begin(), u); + } + + private: + Rewriter &rewrite; + FindCallArgVisitor fcaVisitor; + std::set &DeclsRead; + std::set &DeclsInCond; + std::map &DeclToMCVar; + std::map &ExprToMCVar; + std::set &StmtsHandled; + std::vector &DeferredUpdates; + std::map &Redirector; +}; + +class FindReturnsBreaksVisitor : public RecursiveASTVisitor { +public: + FindReturnsBreaksVisitor() : Returns(), Breaks() {} + + bool VisitStmt(Stmt * s) { + if (isa(s)) + Returns.push_back(cast(s)); + + if (isa(s)) + Breaks.push_back(cast(s)); + return true; + } + + void Clear() { + Returns.clear(); Breaks.clear(); + } + + const std::vector RetrieveReturns() { + return Returns; + } + + const std::vector RetrieveBreaks() { + return Breaks; + } + +private: + std::vector Returns; + std::vector Breaks; +}; + +class LoopHandler : public MatchFinder::MatchCallback { +public: + LoopHandler(Rewriter &rewrite) : rewrite(rewrite) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + const Stmt * s = Result.Nodes.getNodeAs("s"); + + rewrite.InsertText(s->getLocStart(), "MC2_enterLoop();\n", true, true); + + // annotate all returns with MC2_exitLoop() + // annotate all breaks that aren't further nested with MC2_exitLoop(). + FindReturnsBreaksVisitor frbv; + if (isa(s)) + frbv.TraverseStmt(const_cast(cast(s)->getBody())); + if (isa(s)) + frbv.TraverseStmt(const_cast(cast(s)->getBody())); + if (isa(s)) + frbv.TraverseStmt(const_cast(cast(s)->getBody())); + + for (auto & r : frbv.RetrieveReturns()) { + rewrite.InsertText(r->getLocStart(), "MC2_exitLoop();\n", true, true); + } + + // need to find all breaks and returns embedded inside the loop + + rewrite.InsertTextAfterToken(s->getLocEnd().getLocWithOffset(1), "\nMC2_exitLoop();\n"); + } + +private: + Rewriter &rewrite; +}; + +/* Inserts MC2_function for any variables which are subsequently used by the model checker, as long as they depend on MC-visible [currently: read] state. */ +class AssignHandler : public MatchFinder::MatchCallback { +public: + AssignHandler(Rewriter &rewrite, std::set &DeclsRead, + std::set &DeclsInCond, + std::set &DeclsNeedingMC, + std::map &DeclToMCVar, + std::set &StmtsHandled, + std::set &MallocExprs, + std::vector &DeferredUpdates) : + rewrite(rewrite), + DeclsRead(DeclsRead), + DeclsInCond(DeclsInCond), + DeclsNeedingMC(DeclsNeedingMC), + DeclToMCVar(DeclToMCVar), + StmtsHandled(StmtsHandled), + MallocExprs(MallocExprs), + DeferredUpdates(DeferredUpdates) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + BinaryOperator * op = const_cast(Result.Nodes.getNodeAs("op")); + const Stmt * s = Result.Nodes.getNodeAs("containingStmt"); + FindLocalsVisitor flv; + + const VarDecl * lhs = NULL; + const Expr * rhs = NULL; + const DeclStmt * ds; + + if (s && (ds = dyn_cast(s))) { + // long term goal: refactor the run() method to deal with one assignment at a time + // for now, if there is only declarations and no rhs's, we'll ignore this stmt + if (!ds->isSingleDecl()) { + for (auto & d : ds->decls()) { + VarDecl * vd = dyn_cast(d); + if (!d || vd->hasInit()) + assert(0 && "unsupported form of decl"); + } + return; + } + + lhs = retrieveSingleDecl(ds); + } + + if (StmtsHandled.find(ds) != StmtsHandled.end() || StmtsHandled.find(op) != StmtsHandled.end()) + return; + + if (lhs) { + if (lhs->hasInit()) { + rhs = lhs->getInit(); + if (rhs) { + rhs = rhs->IgnoreCasts(); + } + } + else + return; + } + std::set mcState; + + bool lhsTooComplicated = false; + if (op) { + flv.TraverseStmt(op); + + DeclRefExpr * vd; + if ((vd = dyn_cast(op->getLHS()))) + lhs = dyn_cast(vd->getDecl()); + else { + // kick the can along... + lhsTooComplicated = true; + } + + rhs = op->getRHS(); + if (rhs) + rhs = rhs->IgnoreCasts(); + } + else if (lhs) { + // rhs must be MC-active state, i.e. in declsread + // lhs must be subsequently used in (1) store/load or (2) branch condition or (3) other functions and (3a) uses values from other functions or (3b) uses values from loads, stores, or phi functions + flv.TraverseStmt(const_cast(cast(rhs))); + } + + if (DeclsInCond.find(lhs) != DeclsInCond.end()) { + for (auto & d : flv.RetrieveVars()) { + if (DeclToMCVar.count(d) > 0) + mcState.insert(DeclToMCVar[d]); + else if (DeclsRead.find(d) != DeclsRead.end()) + mcState.insert(encode(d->getName().str())); + } + } + + if (mcState.size() > 0 || MallocExprs.find(rhs) != MallocExprs.end()) { + if (lhsTooComplicated) + assert(0 && "couldn't find LHS of = operator"); + + std::stringstream nol; + std::string _lhsStr, lhsStr; + std::string mcVar = encodeFn(fnCount++); + if (lhs) { + lhsStr = lhs->getName().str(); + _lhsStr = encode(lhsStr); + DeclToMCVar[lhs] = mcVar; + DeclsNeedingMC.insert(cast(lhs)); + } + int function_id = 0; + if (!(MallocExprs.find(rhs) != MallocExprs.end())) + function_id = ++funcCount; + nol << "\n" << mcVar << " = MC2_function_id(" << function_id << ", " << mcState.size(); + if (lhs) + nol << ", sizeof (" << lhsStr << "), (uint64_t)" << lhsStr; + else + nol << ", MC2_PTR_LENGTH"; + for (auto & d : mcState) { + nol << ", "; + if (_lhsStr == d) + nol << mcVar; + else + nol << d; + } + nol << "); "; + SourceLocation place; + if (op) + place = op->getLocEnd().getLocWithOffset(1); + else + place = s->getLocEnd(); + rewrite.InsertText(place.getLocWithOffset(1), nol.str(), true, true); + + updateProvisionalName(DeferredUpdates, lhs, mcVar); + } + } + + private: + Rewriter &rewrite; + std::set &DeclsRead, &DeclsInCond; + std::set &DeclsNeedingMC; + std::map &DeclToMCVar; + std::set &StmtsHandled; + std::set &MallocExprs; + std::vector &DeferredUpdates; +}; + +// record vars used in conditions +class BranchConditionRefactoringHandler : public MatchFinder::MatchCallback { +public: + BranchConditionRefactoringHandler(Rewriter &Rewrite, + std::set & DeclsInCond, + std::map &DeclToMCVar, + std::map &ExprToMCVar, + std::map &Redirector, + std::vector &DeferredUpdates) : + Rewrite(Rewrite), DeclsInCond(DeclsInCond), DeclToMCVar(DeclToMCVar), + ExprToMCVar(ExprToMCVar), Redirector(Redirector), DeferredUpdates(DeferredUpdates) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + IfStmt * is = const_cast(Result.Nodes.getNodeAs("if")); + Expr * cond = is->getCond(); + + // refactor out complicated conditions + FindCallArgVisitor flv; + flv.TraverseStmt(cond); + std::string mcVar; + + BinaryOperator * bc = const_cast(Result.Nodes.getNodeAs("bc")); + if (bc) { + std::string condVar = encodeCond(condCount++); + std::stringstream condVarEncoded; + condVarEncoded << condVar << "_m"; + + // prettyprint the binary op + // e.g. int _cond0 = x == y; + std::string SStr; + llvm::raw_string_ostream S(SStr); + bc->printPretty(S, nullptr, Rewrite.getLangOpts()); + const std::string &Str = S.str(); + + std::stringstream prel; + + bool is_equality = false; + // handle equality tests + if (bc->getOpcode() == BO_EQ) { + Expr * lhs = bc->getLHS()->IgnoreCasts(), * rhs = bc->getRHS()->IgnoreCasts(); + if (isa(lhs) && isa(rhs)) { + DeclRefExpr * l = dyn_cast(lhs), *r = dyn_cast(rhs); + is_equality = true; + prel << "\nMCID " << condVarEncoded.str() << ";\n"; + std::string ld = DeclToMCVar.find(l->getDecl())->second, + rd = DeclToMCVar.find(r->getDecl())->second; + + prel << "\nint " << condVar << " = MC2_equals(" << + ld << ", (uint64_t)" << l->getNameInfo().getName().getAsString() << ", " << + rd << ", (uint64_t)" << r->getNameInfo().getName().getAsString() << ", " << + "&" << condVarEncoded.str() << ");\n"; + } + } + + if (!is_equality) { + prel << "\nint " << condVar << " = " << Str << ";"; + prel << "\nMCID " << condVarEncoded.str() << " = MC2_function_id(" << ++funcCount << ", 1, sizeof(" << condVar << "), " << condVar; + const DeclRefExpr * d = flv.RetrieveDeclRefExpr(); + if (DeclToMCVar.find(d->getDecl()) != DeclToMCVar.end()) { + prel << ", " << DeclToMCVar[d->getDecl()]; + } + prel << ");\n"; + } + + ExprToMCVar[cond] = condVarEncoded.str(); + Rewrite.InsertText(is->getLocStart(), prel.str(), false, true); + + // rewrite the binary op with the newly-inserted var + Expr * RO = bc->getRHS(); // used for location only + + int cl = Lexer::MeasureTokenLength(RO->getLocStart(), Rewrite.getSourceMgr(), Rewrite.getLangOpts()); + SourceRange SR(cond->getLocStart(), Rewrite.getSourceMgr().getExpansionLoc(RO->getLocStart()).getLocWithOffset(cl-1)); + Rewrite.ReplaceText(SR, condVar); + } else { + std::string condVar = encodeCond(condCount++); + std::stringstream condVarEncoded; + condVarEncoded << condVar << "_m"; + + std::string SStr; + llvm::raw_string_ostream S(SStr); + cond->printPretty(S, nullptr, Rewrite.getLangOpts()); + const std::string &Str = S.str(); + + std::stringstream prel; + prel << "\nint " << condVar << " = " << Str << ";"; + prel << "\nMCID " << condVarEncoded.str() << " = MC2_function_id(" << ++funcCount << ", 1, sizeof(" << condVar << "), " << condVar; + std::vector * vars = new std::vector(); + const DeclRefExpr * d = flv.RetrieveDeclRefExpr(); + if (isa(d->getDecl()) && DeclToMCVar.find(d->getDecl()) != DeclToMCVar.end()) { + prel << ", " << DeclToMCVar[d->getDecl()]; + } else { + prel << ", "; + ProvisionalName * v = new ProvisionalName(prel.tellp(), d, 0); + vars->push_back(v); + } + prel << ");\n"; + + ExprToMCVar[cond] = condVarEncoded.str(); + // gross hack; should look for any callexprs in cond + // but right now, if it's a unaryop, just manually traverse + if (isa(cond)) { + Expr * e = dyn_cast(cond)->getSubExpr(); + ExprToMCVar[e] = condVarEncoded.str(); + } + Update * u = new Update(is->getLocStart(), prel.str(), vars); + DeferredUpdates.push_back(u); + + // rewrite the call op with the newly-inserted var + SourceRange SR(cond->getLocStart(), cond->getLocEnd()); + Redirector[cond] = is->getLocStart(); + Rewrite.ReplaceText(SR, condVar); + } + + std::deque q; + const NamedDecl * d = flv.RetrieveDeclRefExpr()->getDecl(); + q.push_back(d); + while (!q.empty()) { + const Decl * d = q.back(); + q.pop_back(); + if (isa(d)) + DeclsInCond.insert(cast(d)); + + const VarDecl * vd; + if ((vd = dyn_cast(d))) { + if (vd->hasInit()) { + const Expr * e = vd->getInit(); + flv.Clear(); + flv.TraverseStmt(const_cast(e)); + const NamedDecl * d = flv.RetrieveDeclRefExpr()->getDecl(); + q.push_back(d); + } + } + } + } + +private: + Rewriter &Rewrite; + std::set & DeclsInCond; + std::map &DeclToMCVar; + std::map &ExprToMCVar; + std::map &Redirector; + std::vector &DeferredUpdates; +}; + +class BranchAnnotationHandler : public MatchFinder::MatchCallback { +public: + BranchAnnotationHandler(Rewriter &rewrite, + std::map & DeclToMCVar, + std::map & ExprToMCVar) + : Rewrite(rewrite), + DeclToMCVar(DeclToMCVar), + ExprToMCVar(ExprToMCVar){} + virtual void run(const MatchFinder::MatchResult &Result) { + IfStmt * is = const_cast(Result.Nodes.getNodeAs("if")); + + // if the branch condition is interesting: + // (but right now, not too interesting) + Expr * cond = is->getCond()->IgnoreCasts(); + + FindLocalsVisitor flv; + flv.TraverseStmt(cond); + if (flv.RetrieveVars().size() == 0) return; + + const NamedDecl * condVar = flv.RetrieveVars()[0]; + + std::string mCondVar; + if (ExprToMCVar.count(cond) > 0) + mCondVar = ExprToMCVar[cond]; + else if (DeclToMCVar.count(condVar) > 0) + mCondVar = DeclToMCVar[condVar]; + else + mCondVar = encode(condVar->getName()); + std::string brVar = encodeBranch(branchCount++); + + std::stringstream brline; + brline << "MCID " << brVar << ";\n"; + Rewrite.InsertText(is->getLocStart(), brline.str(), false, true); + + Stmt * ts = is->getThen(), * es = is->getElse(); + bool tHasChild = hasChild(ts); + SourceLocation tfl; + if (tHasChild) { + if (isa(ts)) + tfl = getFirstChild(ts)->getLocStart(); + else + tfl = ts->getLocStart(); + } else + tfl = ts->getLocStart().getLocWithOffset(1); + SourceLocation tsl = ts->getLocEnd().getLocWithOffset(-1); + + std::stringstream tlineStart, mergeStmt, eline; + + UnaryOperator * uop = dyn_cast(cond); + tlineStart << brVar << " = MC2_branchUsesID(" << mCondVar << ", " << "1" << ", 2, true);\n"; + eline << brVar << " = MC2_branchUsesID(" << mCondVar << ", " << "0" << ", 2, true);"; + + mergeStmt << "\tMC2_merge(" << brVar << ");\n"; + + Rewrite.InsertText(tfl, tlineStart.str(), false, true); + + Stmt * tls = NULL; + int extra_else_offset = 0; + + if (tHasChild) { tls = getLastChild(ts); } + if (tls) extra_else_offset = 2; else extra_else_offset = 1; + + if (!tHasChild || (!isa(tls) && !isa(tls))) { + extra_else_offset = 0; + Rewrite.InsertText(tsl.getLocWithOffset(1), mergeStmt.str(), true, true); + } + if (tHasChild && !isa(ts)) { + Rewrite.InsertText(tls->getLocStart(), "{", false, true); + SourceLocation tend = Lexer::getLocForEndOfToken(tls->getLocStart(), 0, Rewrite.getSourceMgr(), Rewrite.getLangOpts()); + Rewrite.InsertText(tend.getLocWithOffset(2), "}", true, true); + extra_else_offset++; + } + if (tHasChild && isa(ts)) extra_else_offset++; + + if (es) { + SourceLocation esl = es->getLocEnd().getLocWithOffset(-1); + bool eHasChild = hasChild(es); + Stmt * els = NULL; + if (eHasChild) els = getLastChild(es); else els = es; + + eline << "\n"; + + SourceLocation el; + if (eHasChild) { + if (isa(es)) + el = getFirstChild(es)->getLocStart(); + else { + el = es->getLocStart(); + } + } else + el = es->getLocStart().getLocWithOffset(1); + Rewrite.InsertText(el, eline.str(), false, true); + + if (eHasChild && !isa(es)) { + Rewrite.InsertText(el, "{", false, true); + Rewrite.InsertText(es->getLocEnd().getLocWithOffset(1), "}", true, true); + } + + if (!eHasChild || (!isa(els) && !isa(els))) + Rewrite.InsertText(esl.getLocWithOffset(1), mergeStmt.str(), true, true); + } + else { + std::stringstream eCompoundLine; + eCompoundLine << " else { " << eline.str() << mergeStmt.str() << " }"; + SourceLocation tend = Lexer::getLocForEndOfToken(ts->getLocEnd(), 0, Rewrite.getSourceMgr(), Rewrite.getLangOpts()); + Rewrite.InsertText(tend.getLocWithOffset(extra_else_offset), + eCompoundLine.str(), false, true); + } + } +private: + + bool hasChild(Stmt * s) { + if (!isa(s)) return true; + return (!cast(s)->body_empty()); + } + + Stmt * getFirstChild(Stmt * s) { + assert(isa(s) && "haven't yet added code to rewrite then/elsestmt to CompoundStmt"); + assert(!cast(s)->body_empty()); + return *(cast(s)->body_begin()); + } + + Stmt * getLastChild(Stmt * s) { + CompoundStmt * cs; + if ((cs = dyn_cast(s))) { + assert (!cs->body_empty()); + return cs->body_back(); + } + return s; + } + + Rewriter &Rewrite; + std::map &DeclToMCVar; + std::map &ExprToMCVar; +}; + +class FunctionCallHandler : public MatchFinder::MatchCallback { +public: + FunctionCallHandler(Rewriter &rewrite, + std::map &DeclToMCVar, + std::set &ThreadMains) + : rewrite(rewrite), DeclToMCVar(DeclToMCVar), ThreadMains(ThreadMains) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + CallExpr * ce = const_cast(Result.Nodes.getNodeAs("callExpr")); + Decl * d = ce->getCalleeDecl(); + NamedDecl * nd = dyn_cast(d); + const Stmt * s = Result.Nodes.getNodeAs("containingStmt"); + ASTContext *Context = Result.Context; + + if (nd->getName() == "thrd_create") { + Expr * callee0 = ce->getArg(1)->IgnoreCasts(); + UnaryOperator * callee1; + if ((callee1 = dyn_cast(callee0))) { + if (callee1->getOpcode() == UnaryOperatorKind::UO_AddrOf) + callee0 = callee1->getSubExpr(); + } + DeclRefExpr * callee = dyn_cast(callee0); + if (!callee) return; + FunctionDecl * fd = dyn_cast(callee->getDecl()); + ThreadMains.insert(fd); + return; + } + + if (!d->hasBody()) + return; + + if (s && !ce->getCallReturnType(*Context)->isVoidType()) { + // TODO check that the type is mc-visible also? + const DeclStmt * ds; + const VarDecl * lhs = NULL; + std::string mc_rv = encodeRV(rvCount++); + + std::stringstream brline; + brline << "MCID " << mc_rv << ";\n"; + rewrite.InsertText(s->getLocStart(), brline.str(), false, true); + + std::stringstream nol; + if (ce->getNumArgs() > 0) nol << ", "; + nol << "&" << mc_rv; + rewrite.InsertTextBefore(ce->getRParenLoc(), nol.str()); + + if (s && (ds = dyn_cast(s))) { + if (!ds->isSingleDecl()) { + for (auto & d : ds->decls()) { + VarDecl * vd = dyn_cast(d); + if (!d || vd->hasInit()) + assert(0 && "unsupported form of decl"); + } + return; + } + + lhs = retrieveSingleDecl(ds); + } + + DeclToMCVar[lhs] = mc_rv; + } + + for (const auto & a : ce->arguments()) { + std::stringstream nol; + + std::string aa = "MCID_NODEP"; + + Expr * e = a->IgnoreCasts(); + DeclRefExpr * dr = dyn_cast(e); + if (dr) { + NamedDecl * d = dr->getDecl(); + if (DeclToMCVar.find(d) != DeclToMCVar.end()) + aa = DeclToMCVar[d]; + } + + nol << aa << ", "; + + if (a->getLocEnd().isValid()) + rewrite.InsertTextBefore(a->getLocStart(), nol.str()); + } + } + +private: + Rewriter &rewrite; + std::map &DeclToMCVar; + std::set &ThreadMains; +}; + +class ReturnHandler : public MatchFinder::MatchCallback { +public: + ReturnHandler(Rewriter &rewrite, + std::map &DeclToMCVar, + std::set &ThreadMains) + : rewrite(rewrite), DeclToMCVar(DeclToMCVar), ThreadMains(ThreadMains) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + const FunctionDecl * fd = Result.Nodes.getNodeAs("containingFunction"); + ReturnStmt * rs = const_cast(Result.Nodes.getNodeAs("returnStmt")); + Expr * rv = const_cast(rs->getRetValue()); + + if (!rv) return; + if (ThreadMains.find(fd) != ThreadMains.end()) return; + // not sure why this is explicitly needed, but crashes without it + if (!fd->getIdentifier() || fd->getName() == "user_main") return; + + FindLocalsVisitor flv; + flv.TraverseStmt(rv); + std::string mrv = "MCID_NODEP"; + + if (flv.RetrieveVars().size() > 0) { + const NamedDecl * returnVar = flv.RetrieveVars()[0]; + if (DeclToMCVar.find(returnVar) != DeclToMCVar.end()) { + mrv = DeclToMCVar[returnVar]; + } + } + std::stringstream nol; + nol << "*retval = " << mrv << ";\n"; + rewrite.InsertText(rs->getLocStart(), nol.str(), false, true); + } + +private: + Rewriter &rewrite; + std::map &DeclToMCVar; + std::set &ThreadMains; +}; + +class VarDeclHandler : public MatchFinder::MatchCallback { +public: + VarDeclHandler(Rewriter &rewrite, + std::map &DeclToMCVar, + std::set &DeclsNeedingMC) + : rewrite(rewrite), DeclToMCVar(DeclToMCVar), DeclsNeedingMC(DeclsNeedingMC) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + VarDecl * d = const_cast(Result.Nodes.getNodeAs("d")); + std::stringstream nol; + + if (DeclsNeedingMC.find(d) == DeclsNeedingMC.end()) return; + + std::string dn; + if (DeclToMCVar.find(d) != DeclToMCVar.end()) + dn = DeclToMCVar[d]; + else + dn = encode(d->getName().str()); + + nol << "MCID " << dn << "; "; + + if (d->getLocStart().isValid()) + rewrite.InsertTextBefore(d->getLocStart(), nol.str()); + } + +private: + Rewriter &rewrite; + std::map &DeclToMCVar; + std::set &DeclsNeedingMC; +}; + +class FunctionDeclHandler : public MatchFinder::MatchCallback { +public: + FunctionDeclHandler(Rewriter &rewrite, + std::set &ThreadMains) + : rewrite(rewrite), ThreadMains(ThreadMains) {} + + virtual void run(const MatchFinder::MatchResult &Result) { + FunctionDecl * fd = const_cast(Result.Nodes.getNodeAs("fd")); + + if (!fd->getIdentifier()) return; + + if (fd->getName() == "user_main") { ThreadMains.insert(fd); return; } + + if (ThreadMains.find(fd) != ThreadMains.end()) return; + + SourceLocation LastParam = fd->getNameInfo().getLocStart().getLocWithOffset(fd->getName().size()).getLocWithOffset(1); + for (auto & p : fd->params()) { + std::stringstream nol; + nol << "MCID " << encode(p->getName()) << ", "; + if (p->getLocStart().isValid()) + rewrite.InsertText(p->getLocStart(), nol.str(), false); + if (p->getLocEnd().isValid()) + LastParam = p->getLocEnd().getLocWithOffset(p->getName().size()); + } + + if (!fd->getReturnType()->isVoidType()) { + std::stringstream nol; + if (fd->param_size() > 0) nol << ", "; + nol << "MCID * retval"; + rewrite.InsertText(LastParam, nol.str(), false); + } + } + +private: + Rewriter &rewrite; + std::set &ThreadMains; +}; + +class BailHandler : public MatchFinder::MatchCallback { +public: + BailHandler() {} + virtual void run(const MatchFinder::MatchResult &Result) { + assert(0 && "we don't handle goto statements"); + } +}; + +class MyASTConsumer : public ASTConsumer { +public: + MyASTConsumer(Rewriter &R) : R(R), + DeclsRead(), + DeclsInCond(), + DeclToMCVar(), + HandlerMalloc(MallocExprs), + HandlerLoad(R, DeclsRead, DeclsNeedingMC, DeclToMCVar, ExprToMCVar, StmtsHandled, Redirector, DeferredUpdates), + HandlerStore(R, DeclsRead, DeclsNeedingMC, DeferredUpdates), + HandlerRMW(R, DeclsRead, DeclsInCond, DeclToMCVar, ExprToMCVar, StmtsHandled, Redirector, DeferredUpdates), + HandlerLoop(R), + HandlerBranchConditionRefactoring(R, DeclsInCond, DeclToMCVar, ExprToMCVar, Redirector, DeferredUpdates), + HandlerAssign(R, DeclsRead, DeclsInCond, DeclsNeedingMC, DeclToMCVar, StmtsHandled, MallocExprs, DeferredUpdates), + HandlerAnnotateBranch(R, DeclToMCVar, ExprToMCVar), + HandlerFunctionDecl(R, ThreadMains), + HandlerFunctionCall(R, DeclToMCVar, ThreadMains), + HandlerReturn(R, DeclToMCVar, ThreadMains), + HandlerVarDecl(R, DeclToMCVar, DeclsNeedingMC), + HandlerBail() { + MatcherFunctionCall.addMatcher(callExpr(anyOf(hasParent(compoundStmt()), + hasAncestor(varDecl(hasParent(stmt().bind("containingStmt")))), + hasAncestor(binaryOperator(hasOperatorName("=")).bind("containingStmt")))).bind("callExpr"), + &HandlerFunctionCall); + MatcherLoadStore.addMatcher + (callExpr(callee(functionDecl(anyOf(hasName("malloc"), hasName("calloc"))))).bind("callExpr"), + &HandlerMalloc); + + MatcherLoadStore.addMatcher + (callExpr(callee(functionDecl(anyOf(hasName("load_32"), hasName("load_64")))), + anyOf(hasAncestor(varDecl(hasParent(stmt().bind("containingStmt"))).bind("decl")), + hasAncestor(binaryOperator(hasOperatorName("=")).bind("containingStmt")), + hasParent(stmt().bind("containingStmt")))) + .bind("callExpr"), + &HandlerLoad); + + MatcherLoadStore.addMatcher(callExpr(callee(functionDecl(anyOf(hasName("store_32"), hasName("store_64"))))).bind("callExpr"), + &HandlerStore); + + MatcherLoadStore.addMatcher + (callExpr(callee(functionDecl(anyOf(hasName("rmw_32"), hasName("rmw_64")))), + anyOf(hasAncestor(varDecl(hasParent(stmt().bind("containingStmt"))).bind("decl")), + hasAncestor(binaryOperator(hasOperatorName("="), + hasLHS(declRefExpr().bind("lhs"))).bind("containingStmt")), + anything())) + .bind("callExpr"), + &HandlerRMW); + + MatcherLoadStore.addMatcher(ifStmt(hasCondition + (anyOf(binaryOperator().bind("bc"), + hasDescendant(callExpr(callee(functionDecl(anyOf(hasName("load_32"), hasName("load_64"))))).bind("callExpr")), + hasDescendant(callExpr(callee(functionDecl(anyOf(hasName("store_32"), hasName("store_64"))))).bind("callExpr")), + hasDescendant(callExpr(callee(functionDecl(anyOf(hasName("rmw_32"), hasName("rmw_64"))))).bind("callExpr")), + anything()))).bind("if"), + &HandlerBranchConditionRefactoring); + + MatcherLoadStore.addMatcher(forStmt().bind("s"), + &HandlerLoop); + MatcherLoadStore.addMatcher(whileStmt().bind("s"), + &HandlerLoop); + MatcherLoadStore.addMatcher(doStmt().bind("s"), + &HandlerLoop); + + MatcherFunction.addMatcher(binaryOperator(anyOf(hasAncestor(declStmt().bind("containingStmt")), + hasParent(compoundStmt())), + hasOperatorName("=")).bind("op"), + &HandlerAssign); + MatcherFunction.addMatcher(declStmt().bind("containingStmt"), &HandlerAssign); + + MatcherFunction.addMatcher(ifStmt().bind("if"), + &HandlerAnnotateBranch); + + MatcherFunctionDecl.addMatcher(functionDecl().bind("fd"), + &HandlerFunctionDecl); + MatcherFunctionDecl.addMatcher(varDecl().bind("d"), &HandlerVarDecl); + MatcherFunctionDecl.addMatcher(returnStmt(hasAncestor(functionDecl().bind("containingFunction"))).bind("returnStmt"), + &HandlerReturn); + + MatcherSanity.addMatcher(gotoStmt(), &HandlerBail); + } + + // Override the method that gets called for each parsed top-level + // declaration. + void HandleTranslationUnit(ASTContext &Context) override { + LangOpts = Context.getLangOpts(); + + MatcherFunctionCall.matchAST(Context); + MatcherLoadStore.matchAST(Context); + MatcherFunction.matchAST(Context); + MatcherFunctionDecl.matchAST(Context); + MatcherSanity.matchAST(Context); + + for (auto & u : DeferredUpdates) { + R.InsertText(u->loc, u->update, true, true); + delete u; + } + DeferredUpdates.clear(); + } + +private: + /* DeclsRead contains all local variables 'x' which: + * 1) appear in 'x = load_32(...); + * 2) appear in 'y = store_32(x); */ + std::set DeclsRead, DeclsInCond; + std::map DeclToMCVar; + std::map ExprToMCVar; + std::set DeclsNeedingMC; + std::set ThreadMains; + std::set StmtsHandled; + std::set MallocExprs; + std::map Redirector; + std::vector DeferredUpdates; + + Rewriter &R; + + MallocHandler HandlerMalloc; + LoadHandler HandlerLoad; + StoreHandler HandlerStore; + RMWHandler HandlerRMW; + LoopHandler HandlerLoop; + BranchConditionRefactoringHandler HandlerBranchConditionRefactoring; + BranchAnnotationHandler HandlerAnnotateBranch; + AssignHandler HandlerAssign; + FunctionDeclHandler HandlerFunctionDecl; + FunctionCallHandler HandlerFunctionCall; + ReturnHandler HandlerReturn; + VarDeclHandler HandlerVarDecl; + BailHandler HandlerBail; + MatchFinder MatcherLoadStore, MatcherFunction, MatcherFunctionDecl, MatcherFunctionCall, MatcherSanity; +}; + +// For each source file provided to the tool, a new FrontendAction is created. +class MyFrontendAction : public ASTFrontendAction { +public: + MyFrontendAction() {} + void EndSourceFileAction() override { + SourceManager &SM = TheRewriter.getSourceMgr(); + llvm::errs() << "** EndSourceFileAction for: " + << SM.getFileEntryForID(SM.getMainFileID())->getName() << "\n"; + + // Now emit the rewritten buffer. + TheRewriter.getEditBuffer(SM.getMainFileID()).write(llvm::outs()); + } + + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef file) override { + llvm::errs() << "** Creating AST consumer for: " << file << "\n"; + TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); + return llvm::make_unique(TheRewriter); + } + +private: + Rewriter TheRewriter; +}; + +int main(int argc, const char **argv) { + CommonOptionsParser op(argc, argv, AddMC2AnnotationsCategory); + ClangTool Tool(op.getCompilations(), op.getSourcePathList()); + + return Tool.run(newFrontendActionFactory().get()); +} diff --git a/clang/test/apr_1_unannotated.c b/clang/test/apr_1_unannotated.c new file mode 100644 index 0000000..d7b35cc --- /dev/null +++ b/clang/test/apr_1_unannotated.c @@ -0,0 +1,13826 @@ +/* Adapted from the sources of the Apache Portable Runtime library version 1.5.1: + * https://apr.apache.org/ + */ + +/* BOUND 5 */ +# 1 "main1.c" +# 1 "" 1 +# 1 "" 3 +# 312 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "main1.c" 2 + +# 1 "/usr/include/assert.h" 1 3 4 +# 35 "/usr/include/assert.h" 3 4 +# 1 "/usr/include/features.h" 1 3 4 +# 352 "/usr/include/features.h" 3 4 +# 1 "/usr/include/stdc-predef.h" 1 3 4 +# 353 "/usr/include/features.h" 2 3 4 +# 374 "/usr/include/features.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4 +# 385 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 386 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4 +# 375 "/usr/include/features.h" 2 3 4 +# 398 "/usr/include/features.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4 +# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4 +# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4 +# 399 "/usr/include/features.h" 2 3 4 +# 36 "/usr/include/assert.h" 2 3 4 +# 69 "/usr/include/assert.h" 3 4 +extern void __assert_fail (const char *__assertion, const char *__file, + unsigned int __line, const char *__function) + __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); + + +extern void __assert_perror_fail (int __errnum, const char *__file, + unsigned int __line, const char *__function) + __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); + + + + +extern void __assert (const char *__assertion, const char *__file, int __line) + __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); +# 3 "main1.c" 2 + + + + +# 1 "./../test/abts.h" 1 +# 21 "./../test/abts.h" +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdarg.h" 1 3 +# 30 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdarg.h" 3 +typedef __builtin_va_list va_list; +# 50 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdarg.h" 3 +typedef __builtin_va_list __gnuc_va_list; +# 22 "./../test/abts.h" 2 +# 1 "/usr/include/stdio.h" 1 3 4 +# 33 "/usr/include/stdio.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 58 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 3 4 +typedef long unsigned int size_t; +# 34 "/usr/include/stdio.h" 2 3 4 + +# 1 "/usr/include/x86_64-linux-gnu/bits/types.h" 1 3 4 +# 27 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 + + +typedef unsigned char __u_char; +typedef unsigned short int __u_short; +typedef unsigned int __u_int; +typedef unsigned long int __u_long; + + +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef signed short int __int16_t; +typedef unsigned short int __uint16_t; +typedef signed int __int32_t; +typedef unsigned int __uint32_t; + +typedef signed long int __int64_t; +typedef unsigned long int __uint64_t; + + + + + + + +typedef long int __quad_t; +typedef unsigned long int __u_quad_t; +# 121 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/typesizes.h" 1 3 4 +# 122 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 + + +typedef unsigned long int __dev_t; +typedef unsigned int __uid_t; +typedef unsigned int __gid_t; +typedef unsigned long int __ino_t; +typedef unsigned long int __ino64_t; +typedef unsigned int __mode_t; +typedef unsigned long int __nlink_t; +typedef long int __off_t; +typedef long int __off64_t; +typedef int __pid_t; +typedef struct { int __val[2]; } __fsid_t; +typedef long int __clock_t; +typedef unsigned long int __rlim_t; +typedef unsigned long int __rlim64_t; +typedef unsigned int __id_t; +typedef long int __time_t; +typedef unsigned int __useconds_t; +typedef long int __suseconds_t; + +typedef int __daddr_t; +typedef int __key_t; + + +typedef int __clockid_t; + + +typedef void * __timer_t; + + +typedef long int __blksize_t; + + + + +typedef long int __blkcnt_t; +typedef long int __blkcnt64_t; + + +typedef unsigned long int __fsblkcnt_t; +typedef unsigned long int __fsblkcnt64_t; + + +typedef unsigned long int __fsfilcnt_t; +typedef unsigned long int __fsfilcnt64_t; + + +typedef long int __fsword_t; + +typedef long int __ssize_t; + + +typedef long int __syscall_slong_t; + +typedef unsigned long int __syscall_ulong_t; + + + +typedef __off64_t __loff_t; +typedef __quad_t *__qaddr_t; +typedef char *__caddr_t; + + +typedef long int __intptr_t; + + +typedef unsigned int __socklen_t; +# 36 "/usr/include/stdio.h" 2 3 4 + + + + + + + + +struct _IO_FILE; + + + +typedef struct _IO_FILE FILE; +# 64 "/usr/include/stdio.h" 3 4 +typedef struct _IO_FILE __FILE; +# 74 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/libio.h" 1 3 4 +# 31 "/usr/include/libio.h" 3 4 +# 1 "/usr/include/_G_config.h" 1 3 4 +# 15 "/usr/include/_G_config.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 16 "/usr/include/_G_config.h" 2 3 4 + + + + +# 1 "/usr/include/wchar.h" 1 3 4 +# 82 "/usr/include/wchar.h" 3 4 +typedef struct +{ + int __count; + union + { + + unsigned int __wch; + + + + char __wchb[4]; + } __value; +} __mbstate_t; +# 21 "/usr/include/_G_config.h" 2 3 4 +typedef struct +{ + __off_t __pos; + __mbstate_t __state; +} _G_fpos_t; +typedef struct +{ + __off64_t __pos; + __mbstate_t __state; +} _G_fpos64_t; +# 32 "/usr/include/libio.h" 2 3 4 +# 144 "/usr/include/libio.h" 3 4 +struct _IO_jump_t; struct _IO_FILE; +# 154 "/usr/include/libio.h" 3 4 +typedef void _IO_lock_t; + + + + + +struct _IO_marker { + struct _IO_marker *_next; + struct _IO_FILE *_sbuf; + + + + int _pos; +# 177 "/usr/include/libio.h" 3 4 +}; + + +enum __codecvt_result +{ + __codecvt_ok, + __codecvt_partial, + __codecvt_error, + __codecvt_noconv +}; +# 245 "/usr/include/libio.h" 3 4 +struct _IO_FILE { + int _flags; + + + + + char* _IO_read_ptr; + char* _IO_read_end; + char* _IO_read_base; + char* _IO_write_base; + char* _IO_write_ptr; + char* _IO_write_end; + char* _IO_buf_base; + char* _IO_buf_end; + + char *_IO_save_base; + char *_IO_backup_base; + char *_IO_save_end; + + struct _IO_marker *_markers; + + struct _IO_FILE *_chain; + + int _fileno; + + + + int _flags2; + + __off_t _old_offset; + + + + unsigned short _cur_column; + signed char _vtable_offset; + char _shortbuf[1]; + + + + _IO_lock_t *_lock; +# 293 "/usr/include/libio.h" 3 4 + __off64_t _offset; +# 302 "/usr/include/libio.h" 3 4 + void *__pad1; + void *__pad2; + void *__pad3; + void *__pad4; + size_t __pad5; + + int _mode; + + char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]; + +}; + + +typedef struct _IO_FILE _IO_FILE; + + +struct _IO_FILE_plus; + +extern struct _IO_FILE_plus _IO_2_1_stdin_; +extern struct _IO_FILE_plus _IO_2_1_stdout_; +extern struct _IO_FILE_plus _IO_2_1_stderr_; +# 338 "/usr/include/libio.h" 3 4 +typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes); + + + + + + + +typedef __ssize_t __io_write_fn (void *__cookie, const char *__buf, + size_t __n); + + + + + + + +typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w); + + +typedef int __io_close_fn (void *__cookie); +# 390 "/usr/include/libio.h" 3 4 +extern int __underflow (_IO_FILE *); +extern int __uflow (_IO_FILE *); +extern int __overflow (_IO_FILE *, int); +# 434 "/usr/include/libio.h" 3 4 +extern int _IO_getc (_IO_FILE *__fp); +extern int _IO_putc (int __c, _IO_FILE *__fp); +extern int _IO_feof (_IO_FILE *__fp) __attribute__ ((__nothrow__ )); +extern int _IO_ferror (_IO_FILE *__fp) __attribute__ ((__nothrow__ )); + +extern int _IO_peekc_locked (_IO_FILE *__fp); + + + + + +extern void _IO_flockfile (_IO_FILE *) __attribute__ ((__nothrow__ )); +extern void _IO_funlockfile (_IO_FILE *) __attribute__ ((__nothrow__ )); +extern int _IO_ftrylockfile (_IO_FILE *) __attribute__ ((__nothrow__ )); +# 464 "/usr/include/libio.h" 3 4 +extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict, + __gnuc_va_list, int *__restrict); +extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict, + __gnuc_va_list); +extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t); +extern size_t _IO_sgetn (_IO_FILE *, void *, size_t); + +extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t, int, int); +extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t, int); + +extern void _IO_free_backup_area (_IO_FILE *) __attribute__ ((__nothrow__ )); +# 75 "/usr/include/stdio.h" 2 3 4 + + + + +typedef __gnuc_va_list va_list; +# 90 "/usr/include/stdio.h" 3 4 +typedef __off_t off_t; +# 102 "/usr/include/stdio.h" 3 4 +typedef __ssize_t ssize_t; + + + + + + + +typedef _G_fpos_t fpos_t; +# 164 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/stdio_lim.h" 1 3 4 +# 165 "/usr/include/stdio.h" 2 3 4 + + + +extern struct _IO_FILE *stdin; +extern struct _IO_FILE *stdout; +extern struct _IO_FILE *stderr; + + + + + + + +extern int remove (const char *__filename) __attribute__ ((__nothrow__ )); + +extern int rename (const char *__old, const char *__new) __attribute__ ((__nothrow__ )); + + + + +extern int renameat (int __oldfd, const char *__old, int __newfd, + const char *__new) __attribute__ ((__nothrow__ )); +# 195 "/usr/include/stdio.h" 3 4 +extern FILE *tmpfile (void) ; +# 209 "/usr/include/stdio.h" 3 4 +extern char *tmpnam (char *__s) __attribute__ ((__nothrow__ )) ; + + + + + +extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__ )) ; +# 227 "/usr/include/stdio.h" 3 4 +extern char *tempnam (const char *__dir, const char *__pfx) + __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ; +# 237 "/usr/include/stdio.h" 3 4 +extern int fclose (FILE *__stream); + + + + +extern int fflush (FILE *__stream); +# 252 "/usr/include/stdio.h" 3 4 +extern int fflush_unlocked (FILE *__stream); +# 272 "/usr/include/stdio.h" 3 4 +extern FILE *fopen (const char *__restrict __filename, + const char *__restrict __modes) ; + + + + +extern FILE *freopen (const char *__restrict __filename, + const char *__restrict __modes, + FILE *__restrict __stream) ; +# 306 "/usr/include/stdio.h" 3 4 +extern FILE *fdopen (int __fd, const char *__modes) __attribute__ ((__nothrow__ )) ; +# 319 "/usr/include/stdio.h" 3 4 +extern FILE *fmemopen (void *__s, size_t __len, const char *__modes) + __attribute__ ((__nothrow__ )) ; + + + + +extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__ )) ; + + + + + + +extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__ )); + + + +extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf, + int __modes, size_t __n) __attribute__ ((__nothrow__ )); + + + + + +extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf, + size_t __size) __attribute__ ((__nothrow__ )); + + +extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__ )); +# 356 "/usr/include/stdio.h" 3 4 +extern int fprintf (FILE *__restrict __stream, + const char *__restrict __format, ...); + + + + +extern int printf (const char *__restrict __format, ...); + +extern int sprintf (char *__restrict __s, + const char *__restrict __format, ...) __attribute__ ((__nothrow__)); + + + + + +extern int vfprintf (FILE *__restrict __s, const char *__restrict __format, + __gnuc_va_list __arg); + + + + +extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg); + +extern int vsprintf (char *__restrict __s, const char *__restrict __format, + __gnuc_va_list __arg) __attribute__ ((__nothrow__)); + + + + + +extern int snprintf (char *__restrict __s, size_t __maxlen, + const char *__restrict __format, ...) + __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4))); + +extern int vsnprintf (char *__restrict __s, size_t __maxlen, + const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0))); +# 412 "/usr/include/stdio.h" 3 4 +extern int vdprintf (int __fd, const char *__restrict __fmt, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__printf__, 2, 0))); +extern int dprintf (int __fd, const char *__restrict __fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +# 425 "/usr/include/stdio.h" 3 4 +extern int fscanf (FILE *__restrict __stream, + const char *__restrict __format, ...) ; + + + + +extern int scanf (const char *__restrict __format, ...) ; + +extern int sscanf (const char *__restrict __s, + const char *__restrict __format, ...) __attribute__ ((__nothrow__ )); +# 443 "/usr/include/stdio.h" 3 4 +extern int fscanf (FILE *__restrict __stream, const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf") ; + + +extern int scanf (const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf") ; + +extern int sscanf (const char *__restrict __s, const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__ )); +# 471 "/usr/include/stdio.h" 3 4 +extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 2, 0))) ; + + + + + +extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 1, 0))) ; + + +extern int vsscanf (const char *__restrict __s, + const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__nothrow__ )) __attribute__ ((__format__ (__scanf__, 2, 0))); +# 494 "/usr/include/stdio.h" 3 4 +extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf") + + + + __attribute__ ((__format__ (__scanf__, 2, 0))) ; +extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf") + + __attribute__ ((__format__ (__scanf__, 1, 0))) ; +extern int vsscanf (const char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf") __attribute__ ((__nothrow__ )) + + + + __attribute__ ((__format__ (__scanf__, 2, 0))); +# 531 "/usr/include/stdio.h" 3 4 +extern int fgetc (FILE *__stream); +extern int getc (FILE *__stream); + + + + + +extern int getchar (void); +# 550 "/usr/include/stdio.h" 3 4 +extern int getc_unlocked (FILE *__stream); +extern int getchar_unlocked (void); +# 561 "/usr/include/stdio.h" 3 4 +extern int fgetc_unlocked (FILE *__stream); +# 573 "/usr/include/stdio.h" 3 4 +extern int fputc (int __c, FILE *__stream); +extern int putc (int __c, FILE *__stream); + + + + + +extern int putchar (int __c); +# 594 "/usr/include/stdio.h" 3 4 +extern int fputc_unlocked (int __c, FILE *__stream); + + + + + + + +extern int putc_unlocked (int __c, FILE *__stream); +extern int putchar_unlocked (int __c); + + + + + + +extern int getw (FILE *__stream); + + +extern int putw (int __w, FILE *__stream); +# 622 "/usr/include/stdio.h" 3 4 +extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) + ; +# 638 "/usr/include/stdio.h" 3 4 +extern char *gets (char *__s) __attribute__ ((__deprecated__)); +# 665 "/usr/include/stdio.h" 3 4 +extern __ssize_t __getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) ; +extern __ssize_t getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) ; + + + + + + + +extern __ssize_t getline (char **__restrict __lineptr, + size_t *__restrict __n, + FILE *__restrict __stream) ; +# 689 "/usr/include/stdio.h" 3 4 +extern int fputs (const char *__restrict __s, FILE *__restrict __stream); + + + + + +extern int puts (const char *__s); + + + + + + +extern int ungetc (int __c, FILE *__stream); + + + + + + +extern size_t fread (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) ; + + + + +extern size_t fwrite (const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __s); +# 737 "/usr/include/stdio.h" 3 4 +extern size_t fread_unlocked (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) ; +extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream); +# 749 "/usr/include/stdio.h" 3 4 +extern int fseek (FILE *__stream, long int __off, int __whence); + + + + +extern long int ftell (FILE *__stream) ; + + + + +extern void rewind (FILE *__stream); +# 773 "/usr/include/stdio.h" 3 4 +extern int fseeko (FILE *__stream, __off_t __off, int __whence); + + + + +extern __off_t ftello (FILE *__stream) ; +# 798 "/usr/include/stdio.h" 3 4 +extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos); + + + + +extern int fsetpos (FILE *__stream, const fpos_t *__pos); +# 826 "/usr/include/stdio.h" 3 4 +extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__ )); + +extern int feof (FILE *__stream) __attribute__ ((__nothrow__ )) ; + +extern int ferror (FILE *__stream) __attribute__ ((__nothrow__ )) ; + + + + +extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__ )); +extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__ )) ; +extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__ )) ; +# 846 "/usr/include/stdio.h" 3 4 +extern void perror (const char *__s); + + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 3 4 +extern int sys_nerr; +extern const char *const sys_errlist[]; +# 854 "/usr/include/stdio.h" 2 3 4 + + + + +extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ )) ; + + + + +extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ )) ; +# 873 "/usr/include/stdio.h" 3 4 +extern FILE *popen (const char *__command, const char *__modes) ; + + + + + +extern int pclose (FILE *__stream); + + + + + +extern char *ctermid (char *__s) __attribute__ ((__nothrow__ )); +# 913 "/usr/include/stdio.h" 3 4 +extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ )); + + + +extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ )) ; + + +extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ )); +# 23 "./../test/abts.h" 2 +# 1 "/usr/include/stdlib.h" 1 3 4 +# 32 "/usr/include/stdlib.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 86 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 3 4 +typedef int wchar_t; +# 33 "/usr/include/stdlib.h" 2 3 4 + + + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/waitflags.h" 1 3 4 +# 50 "/usr/include/x86_64-linux-gnu/bits/waitflags.h" 3 4 +typedef enum +{ + P_ALL, + P_PID, + P_PGID +} idtype_t; +# 42 "/usr/include/stdlib.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/waitstatus.h" 1 3 4 +# 64 "/usr/include/x86_64-linux-gnu/bits/waitstatus.h" 3 4 +# 1 "/usr/include/endian.h" 1 3 4 +# 36 "/usr/include/endian.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/endian.h" 1 3 4 +# 37 "/usr/include/endian.h" 2 3 4 +# 60 "/usr/include/endian.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 2 3 4 + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/byteswap-16.h" 1 3 4 +# 36 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 2 3 4 +# 61 "/usr/include/endian.h" 2 3 4 +# 65 "/usr/include/x86_64-linux-gnu/bits/waitstatus.h" 2 3 4 + +union wait + { + int w_status; + struct + { + + unsigned int __w_termsig:7; + unsigned int __w_coredump:1; + unsigned int __w_retcode:8; + unsigned int:16; + + + + + + + + } __wait_terminated; + struct + { + + unsigned int __w_stopval:8; + unsigned int __w_stopsig:8; + unsigned int:16; + + + + + + + } __wait_stopped; + }; +# 43 "/usr/include/stdlib.h" 2 3 4 +# 67 "/usr/include/stdlib.h" 3 4 +typedef union + { + union wait *__uptr; + int *__iptr; + } __WAIT_STATUS __attribute__ ((__transparent_union__)); +# 97 "/usr/include/stdlib.h" 3 4 +typedef struct + { + int quot; + int rem; + } div_t; + + + +typedef struct + { + long int quot; + long int rem; + } ldiv_t; + + + + + + + +__extension__ typedef struct + { + long long int quot; + long long int rem; + } lldiv_t; +# 139 "/usr/include/stdlib.h" 3 4 +extern size_t __ctype_get_mb_cur_max (void) __attribute__ ((__nothrow__ )) ; + + + + +extern double atof (const char *__nptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + +extern int atoi (const char *__nptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + +extern long int atol (const char *__nptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + + + + + +__extension__ extern long long int atoll (const char *__nptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + + + + + +extern double strtod (const char *__restrict __nptr, + char **__restrict __endptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern float strtof (const char *__restrict __nptr, + char **__restrict __endptr) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + +extern long double strtold (const char *__restrict __nptr, + char **__restrict __endptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern long int strtol (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + +extern unsigned long int strtoul (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + +__extension__ +extern long long int strtoq (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + +__extension__ +extern unsigned long long int strtouq (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +__extension__ +extern long long int strtoll (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + +__extension__ +extern unsigned long long int strtoull (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 305 "/usr/include/stdlib.h" 3 4 +extern char *l64a (long int __n) __attribute__ ((__nothrow__ )) ; + + +extern long int a64l (const char *__s) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + + + + + +# 1 "/usr/include/x86_64-linux-gnu/sys/types.h" 1 3 4 +# 33 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef __u_char u_char; +typedef __u_short u_short; +typedef __u_int u_int; +typedef __u_long u_long; +typedef __quad_t quad_t; +typedef __u_quad_t u_quad_t; +typedef __fsid_t fsid_t; + + + + +typedef __loff_t loff_t; + + + +typedef __ino_t ino_t; +# 60 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef __dev_t dev_t; + + + + +typedef __gid_t gid_t; + + + + +typedef __mode_t mode_t; + + + + +typedef __nlink_t nlink_t; + + + + +typedef __uid_t uid_t; +# 98 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef __pid_t pid_t; + + + + + +typedef __id_t id_t; +# 115 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef __daddr_t daddr_t; +typedef __caddr_t caddr_t; + + + + + +typedef __key_t key_t; +# 132 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 59 "/usr/include/time.h" 3 4 +typedef __clock_t clock_t; +# 75 "/usr/include/time.h" 3 4 +typedef __time_t time_t; +# 91 "/usr/include/time.h" 3 4 +typedef __clockid_t clockid_t; +# 103 "/usr/include/time.h" 3 4 +typedef __timer_t timer_t; +# 133 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 +# 146 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 147 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 + + + +typedef unsigned long int ulong; +typedef unsigned short int ushort; +typedef unsigned int uint; +# 194 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef int int8_t __attribute__ ((__mode__ (__QI__))); +typedef int int16_t __attribute__ ((__mode__ (__HI__))); +typedef int int32_t __attribute__ ((__mode__ (__SI__))); +typedef int int64_t __attribute__ ((__mode__ (__DI__))); + + +typedef unsigned int u_int8_t __attribute__ ((__mode__ (__QI__))); +typedef unsigned int u_int16_t __attribute__ ((__mode__ (__HI__))); +typedef unsigned int u_int32_t __attribute__ ((__mode__ (__SI__))); +typedef unsigned int u_int64_t __attribute__ ((__mode__ (__DI__))); + +typedef int register_t __attribute__ ((__mode__ (__word__))); +# 219 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/sys/select.h" 1 3 4 +# 30 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/select.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/select.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/bits/select.h" 2 3 4 +# 31 "/usr/include/x86_64-linux-gnu/sys/select.h" 2 3 4 + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sigset.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/sigset.h" 3 4 +typedef int __sig_atomic_t; + + + + +typedef struct + { + unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))]; + } __sigset_t; +# 34 "/usr/include/x86_64-linux-gnu/sys/select.h" 2 3 4 + + + +typedef __sigset_t sigset_t; + + + + + + +# 1 "/usr/include/time.h" 1 3 4 +# 120 "/usr/include/time.h" 3 4 +struct timespec + { + __time_t tv_sec; + __syscall_slong_t tv_nsec; + }; +# 44 "/usr/include/x86_64-linux-gnu/sys/select.h" 2 3 4 + +# 1 "/usr/include/x86_64-linux-gnu/bits/time.h" 1 3 4 +# 30 "/usr/include/x86_64-linux-gnu/bits/time.h" 3 4 +struct timeval + { + __time_t tv_sec; + __suseconds_t tv_usec; + }; +# 46 "/usr/include/x86_64-linux-gnu/sys/select.h" 2 3 4 + + +typedef __suseconds_t suseconds_t; + + + + + +typedef long int __fd_mask; +# 64 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4 +typedef struct + { + + + + + + + __fd_mask __fds_bits[1024 / (8 * (int) sizeof (__fd_mask))]; + + + } fd_set; + + + + + + +typedef __fd_mask fd_mask; +# 106 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4 +extern int select (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + struct timeval *__restrict __timeout); +# 118 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4 +extern int pselect (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + const struct timespec *__restrict __timeout, + const __sigset_t *__restrict __sigmask); +# 220 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 + + +# 1 "/usr/include/x86_64-linux-gnu/sys/sysmacros.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/sys/sysmacros.h" 3 4 +__extension__ +extern unsigned int gnu_dev_major (unsigned long long int __dev) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +__extension__ +extern unsigned int gnu_dev_minor (unsigned long long int __dev) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +__extension__ +extern unsigned long long int gnu_dev_makedev (unsigned int __major, + unsigned int __minor) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 223 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 + + + + + +typedef __blksize_t blksize_t; + + + + + + +typedef __blkcnt_t blkcnt_t; + + + +typedef __fsblkcnt_t fsblkcnt_t; + + + +typedef __fsfilcnt_t fsfilcnt_t; +# 270 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 1 3 4 +# 21 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 2 3 4 +# 60 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 +typedef unsigned long int pthread_t; + + +union pthread_attr_t +{ + char __size[56]; + long int __align; +}; + +typedef union pthread_attr_t pthread_attr_t; + + + + + +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +# 90 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + + unsigned int __nusers; + + + + int __kind; + + short __spins; + short __elision; + __pthread_list_t __list; +# 124 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 + } __data; + char __size[40]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[4]; + int __align; +} pthread_mutexattr_t; + + + + +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[48]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[4]; + int __align; +} pthread_condattr_t; + + + +typedef unsigned int pthread_key_t; + + + +typedef int pthread_once_t; + + + + + +typedef union +{ + + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + + + unsigned int __flags; + + } __data; +# 211 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 + char __size[56]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[8]; + long int __align; +} pthread_rwlockattr_t; + + + + + +typedef volatile int pthread_spinlock_t; + + + + +typedef union +{ + char __size[32]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[4]; + int __align; +} pthread_barrierattr_t; +# 271 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 +# 315 "/usr/include/stdlib.h" 2 3 4 + + + + + + +extern long int random (void) __attribute__ ((__nothrow__ )); + + +extern void srandom (unsigned int __seed) __attribute__ ((__nothrow__ )); + + + + + +extern char *initstate (unsigned int __seed, char *__statebuf, + size_t __statelen) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + +extern char *setstate (char *__statebuf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + + +struct random_data + { + int32_t *fptr; + int32_t *rptr; + int32_t *state; + int rand_type; + int rand_deg; + int rand_sep; + int32_t *end_ptr; + }; + +extern int random_r (struct random_data *__restrict __buf, + int32_t *__restrict __result) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + +extern int srandom_r (unsigned int __seed, struct random_data *__buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + +extern int initstate_r (unsigned int __seed, char *__restrict __statebuf, + size_t __statelen, + struct random_data *__restrict __buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))); + +extern int setstate_r (char *__restrict __statebuf, + struct random_data *__restrict __buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + + + +extern int rand (void) __attribute__ ((__nothrow__ )); + +extern void srand (unsigned int __seed) __attribute__ ((__nothrow__ )); + + + + +extern int rand_r (unsigned int *__seed) __attribute__ ((__nothrow__ )); + + + + + + + +extern double drand48 (void) __attribute__ ((__nothrow__ )); +extern double erand48 (unsigned short int __xsubi[3]) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern long int lrand48 (void) __attribute__ ((__nothrow__ )); +extern long int nrand48 (unsigned short int __xsubi[3]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern long int mrand48 (void) __attribute__ ((__nothrow__ )); +extern long int jrand48 (unsigned short int __xsubi[3]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern void srand48 (long int __seedval) __attribute__ ((__nothrow__ )); +extern unsigned short int *seed48 (unsigned short int __seed16v[3]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +extern void lcong48 (unsigned short int __param[7]) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +struct drand48_data + { + unsigned short int __x[3]; + unsigned short int __old_x[3]; + unsigned short int __c; + unsigned short int __init; + __extension__ unsigned long long int __a; + + }; + + +extern int drand48_r (struct drand48_data *__restrict __buffer, + double *__restrict __result) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern int erand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + double *__restrict __result) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int lrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern int nrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int mrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern int jrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int srand48_r (long int __seedval, struct drand48_data *__buffer) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + +extern int seed48_r (unsigned short int __seed16v[3], + struct drand48_data *__buffer) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + +extern int lcong48_r (unsigned short int __param[7], + struct drand48_data *__buffer) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +# 466 "/usr/include/stdlib.h" 3 4 +extern void *malloc (size_t __size) __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ; + +extern void *calloc (size_t __nmemb, size_t __size) + __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ; +# 480 "/usr/include/stdlib.h" 3 4 +extern void *realloc (void *__ptr, size_t __size) + __attribute__ ((__nothrow__ )) __attribute__ ((__warn_unused_result__)); + +extern void free (void *__ptr) __attribute__ ((__nothrow__ )); + + + + +extern void cfree (void *__ptr) __attribute__ ((__nothrow__ )); + + + + +# 1 "/usr/include/alloca.h" 1 3 4 +# 24 "/usr/include/alloca.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 25 "/usr/include/alloca.h" 2 3 4 + + + + + + + +extern void *alloca (size_t __size) __attribute__ ((__nothrow__ )); +# 493 "/usr/include/stdlib.h" 2 3 4 + + + + + +extern void *valloc (size_t __size) __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ; + + + + +extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 515 "/usr/include/stdlib.h" 3 4 +extern void abort (void) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); + + + +extern int atexit (void (*__func) (void)) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 535 "/usr/include/stdlib.h" 3 4 +extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + +extern void exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); +# 557 "/usr/include/stdlib.h" 3 4 +extern void _Exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); + + + + + + +extern char *getenv (const char *__name) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 578 "/usr/include/stdlib.h" 3 4 +extern int putenv (char *__string) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int setenv (const char *__name, const char *__value, int __replace) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + +extern int unsetenv (const char *__name) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int clearenv (void) __attribute__ ((__nothrow__ )); +# 606 "/usr/include/stdlib.h" 3 4 +extern char *mktemp (char *__template) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 620 "/usr/include/stdlib.h" 3 4 +extern int mkstemp (char *__template) __attribute__ ((__nonnull__ (1))) ; +# 642 "/usr/include/stdlib.h" 3 4 +extern int mkstemps (char *__template, int __suffixlen) __attribute__ ((__nonnull__ (1))) ; +# 663 "/usr/include/stdlib.h" 3 4 +extern char *mkdtemp (char *__template) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 717 "/usr/include/stdlib.h" 3 4 +extern int system (const char *__command) ; +# 734 "/usr/include/stdlib.h" 3 4 +extern char *realpath (const char *__restrict __name, + char *__restrict __resolved) __attribute__ ((__nothrow__ )) ; + + + + + + +typedef int (*__compar_fn_t) (const void *, const void *); +# 755 "/usr/include/stdlib.h" 3 4 +extern void *bsearch (const void *__key, const void *__base, + size_t __nmemb, size_t __size, __compar_fn_t __compar) + __attribute__ ((__nonnull__ (1, 2, 5))) ; + + + + + + + +extern void qsort (void *__base, size_t __nmemb, size_t __size, + __compar_fn_t __compar) __attribute__ ((__nonnull__ (1, 4))); +# 775 "/usr/include/stdlib.h" 3 4 +extern int abs (int __x) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; +extern long int labs (long int __x) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; + + + +__extension__ extern long long int llabs (long long int __x) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; + + + + + + + +extern div_t div (int __numer, int __denom) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; +extern ldiv_t ldiv (long int __numer, long int __denom) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; + + + + +__extension__ extern lldiv_t lldiv (long long int __numer, + long long int __denom) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; +# 812 "/usr/include/stdlib.h" 3 4 +extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))) ; + + + + +extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))) ; + + + + +extern char *gcvt (double __value, int __ndigit, char *__buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3))) ; + + + + +extern char *qecvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))) ; +extern char *qfcvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))) ; +extern char *qgcvt (long double __value, int __ndigit, char *__buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3))) ; + + + + +extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4, 5))); +extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4, 5))); + +extern int qecvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4, 5))); +extern int qfcvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4, 5))); + + + + + + +extern int mblen (const char *__s, size_t __n) __attribute__ ((__nothrow__ )); + + +extern int mbtowc (wchar_t *__restrict __pwc, + const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ )); + + +extern int wctomb (char *__s, wchar_t __wchar) __attribute__ ((__nothrow__ )); + + + +extern size_t mbstowcs (wchar_t *__restrict __pwcs, + const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ )); + +extern size_t wcstombs (char *__restrict __s, + const wchar_t *__restrict __pwcs, size_t __n) + __attribute__ ((__nothrow__ )); +# 888 "/usr/include/stdlib.h" 3 4 +extern int rpmatch (const char *__response) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 899 "/usr/include/stdlib.h" 3 4 +extern int getsubopt (char **__restrict __optionp, + char *const *__restrict __tokens, + char **__restrict __valuep) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2, 3))) ; +# 951 "/usr/include/stdlib.h" 3 4 +extern int getloadavg (double __loadavg[], int __nelem) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/stdlib-float.h" 1 3 4 +# 956 "/usr/include/stdlib.h" 2 3 4 +# 24 "./../test/abts.h" 2 +# 1 "/usr/include/string.h" 1 3 4 +# 32 "/usr/include/string.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 33 "/usr/include/string.h" 2 3 4 +# 46 "/usr/include/string.h" 3 4 +extern void *memcpy (void *__restrict __dest, const void *__restrict __src, + size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern void *memmove (void *__dest, const void *__src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + + + +extern void *memccpy (void *__restrict __dest, const void *__restrict __src, + int __c, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + + +extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int memcmp (const void *__s1, const void *__s2, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 96 "/usr/include/string.h" 3 4 +extern void *memchr (const void *__s, int __c, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +# 129 "/usr/include/string.h" 3 4 +extern char *strcpy (char *__restrict __dest, const char *__restrict __src) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + +extern char *strncpy (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern char *strcat (char *__restrict __dest, const char *__restrict __src) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + +extern char *strncat (char *__restrict __dest, const char *__restrict __src, + size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int strcmp (const char *__s1, const char *__s2) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + +extern int strncmp (const char *__s1, const char *__s2, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + + +extern int strcoll (const char *__s1, const char *__s2) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + +extern size_t strxfrm (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + + + + +# 1 "/usr/include/xlocale.h" 1 3 4 +# 27 "/usr/include/xlocale.h" 3 4 +typedef struct __locale_struct +{ + + struct __locale_data *__locales[13]; + + + const unsigned short int *__ctype_b; + const int *__ctype_tolower; + const int *__ctype_toupper; + + + const char *__names[13]; +} *__locale_t; + + +typedef __locale_t locale_t; +# 164 "/usr/include/string.h" 2 3 4 + + +extern int strcoll_l (const char *__s1, const char *__s2, __locale_t __l) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 3))); + +extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n, + __locale_t __l) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))); + + + + + +extern char *strdup (const char *__s) + __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1))); + + + + + + +extern char *strndup (const char *__string, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1))); +# 236 "/usr/include/string.h" 3 4 +extern char *strchr (const char *__s, int __c) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +# 263 "/usr/include/string.h" 3 4 +extern char *strrchr (const char *__s, int __c) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +# 285 "/usr/include/string.h" 3 4 +extern size_t strcspn (const char *__s, const char *__reject) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + + +extern size_t strspn (const char *__s, const char *__accept) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 315 "/usr/include/string.h" 3 4 +extern char *strpbrk (const char *__s, const char *__accept) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 342 "/usr/include/string.h" 3 4 +extern char *strstr (const char *__haystack, const char *__needle) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern char *strtok (char *__restrict __s, const char *__restrict __delim) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + +extern char *__strtok_r (char *__restrict __s, + const char *__restrict __delim, + char **__restrict __save_ptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); + +extern char *strtok_r (char *__restrict __s, const char *__restrict __delim, + char **__restrict __save_ptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); +# 399 "/usr/include/string.h" 3 4 +extern size_t strlen (const char *__s) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); + + + + + +extern size_t strnlen (const char *__string, size_t __maxlen) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); + + + + + +extern char *strerror (int __errnum) __attribute__ ((__nothrow__ )); +# 427 "/usr/include/string.h" 3 4 +extern int strerror_r (int __errnum, char *__buf, size_t __buflen) __asm__ ("" "__xpg_strerror_r") __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); +# 445 "/usr/include/string.h" 3 4 +extern char *strerror_l (int __errnum, __locale_t __l) __attribute__ ((__nothrow__ )); + + + + + +extern void __bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern void bcopy (const void *__src, void *__dest, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern void bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int bcmp (const void *__s1, const void *__s2, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 489 "/usr/include/string.h" 3 4 +extern char *index (const char *__s, int __c) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +# 517 "/usr/include/string.h" 3 4 +extern char *rindex (const char *__s, int __c) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); + + + + +extern int ffs (int __i) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 534 "/usr/include/string.h" 3 4 +extern int strcasecmp (const char *__s1, const char *__s2) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + + +extern int strncasecmp (const char *__s1, const char *__s2, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 557 "/usr/include/string.h" 3 4 +extern char *strsep (char **__restrict __stringp, + const char *__restrict __delim) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern char *strsignal (int __sig) __attribute__ ((__nothrow__ )); + + +extern char *__stpcpy (char *__restrict __dest, const char *__restrict __src) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern char *stpcpy (char *__restrict __dest, const char *__restrict __src) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern char *__stpncpy (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern char *stpncpy (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +# 25 "./../test/abts.h" 2 + + + +# 1 "/usr/include/unistd.h" 1 3 4 +# 202 "/usr/include/unistd.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/posix_opt.h" 1 3 4 +# 203 "/usr/include/unistd.h" 2 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/environments.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/environments.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/bits/environments.h" 2 3 4 +# 207 "/usr/include/unistd.h" 2 3 4 +# 226 "/usr/include/unistd.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 227 "/usr/include/unistd.h" 2 3 4 +# 255 "/usr/include/unistd.h" 3 4 +typedef __useconds_t useconds_t; +# 267 "/usr/include/unistd.h" 3 4 +typedef __intptr_t intptr_t; + + + + + + +typedef __socklen_t socklen_t; +# 287 "/usr/include/unistd.h" 3 4 +extern int access (const char *__name, int __type) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 304 "/usr/include/unistd.h" 3 4 +extern int faccessat (int __fd, const char *__file, int __type, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))) ; +# 334 "/usr/include/unistd.h" 3 4 +extern __off_t lseek (int __fd, __off_t __offset, int __whence) __attribute__ ((__nothrow__ )); +# 353 "/usr/include/unistd.h" 3 4 +extern int close (int __fd); + + + + + + +extern ssize_t read (int __fd, void *__buf, size_t __nbytes) ; + + + + + +extern ssize_t write (int __fd, const void *__buf, size_t __n) ; +# 376 "/usr/include/unistd.h" 3 4 +extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, + __off_t __offset) ; + + + + + + +extern ssize_t pwrite (int __fd, const void *__buf, size_t __n, + __off_t __offset) ; +# 417 "/usr/include/unistd.h" 3 4 +extern int pipe (int __pipedes[2]) __attribute__ ((__nothrow__ )) ; +# 432 "/usr/include/unistd.h" 3 4 +extern unsigned int alarm (unsigned int __seconds) __attribute__ ((__nothrow__ )); +# 444 "/usr/include/unistd.h" 3 4 +extern unsigned int sleep (unsigned int __seconds); + + + + + + + +extern __useconds_t ualarm (__useconds_t __value, __useconds_t __interval) + __attribute__ ((__nothrow__ )); + + + + + + +extern int usleep (__useconds_t __useconds); +# 469 "/usr/include/unistd.h" 3 4 +extern int pause (void); + + + +extern int chown (const char *__file, __uid_t __owner, __gid_t __group) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + +extern int fchown (int __fd, __uid_t __owner, __gid_t __group) __attribute__ ((__nothrow__ )) ; + + + + +extern int lchown (const char *__file, __uid_t __owner, __gid_t __group) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + + + + +extern int fchownat (int __fd, const char *__file, __uid_t __owner, + __gid_t __group, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))) ; + + + +extern int chdir (const char *__path) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + +extern int fchdir (int __fd) __attribute__ ((__nothrow__ )) ; +# 511 "/usr/include/unistd.h" 3 4 +extern char *getcwd (char *__buf, size_t __size) __attribute__ ((__nothrow__ )) ; +# 525 "/usr/include/unistd.h" 3 4 +extern char *getwd (char *__buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) __attribute__ ((__deprecated__)) ; + + + + +extern int dup (int __fd) __attribute__ ((__nothrow__ )) ; + + +extern int dup2 (int __fd, int __fd2) __attribute__ ((__nothrow__ )); +# 543 "/usr/include/unistd.h" 3 4 +extern char **__environ; + + + + + + + +extern int execve (const char *__path, char *const __argv[], + char *const __envp[]) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern int fexecve (int __fd, char *const __argv[], char *const __envp[]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + +extern int execv (const char *__path, char *const __argv[]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int execle (const char *__path, const char *__arg, ...) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int execl (const char *__path, const char *__arg, ...) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int execvp (const char *__file, char *const __argv[]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern int execlp (const char *__file, const char *__arg, ...) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +# 598 "/usr/include/unistd.h" 3 4 +extern int nice (int __inc) __attribute__ ((__nothrow__ )) ; + + + + +extern void _exit (int __status) __attribute__ ((__noreturn__)); + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/confname.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/confname.h" 3 4 +enum + { + _PC_LINK_MAX, + + _PC_MAX_CANON, + + _PC_MAX_INPUT, + + _PC_NAME_MAX, + + _PC_PATH_MAX, + + _PC_PIPE_BUF, + + _PC_CHOWN_RESTRICTED, + + _PC_NO_TRUNC, + + _PC_VDISABLE, + + _PC_SYNC_IO, + + _PC_ASYNC_IO, + + _PC_PRIO_IO, + + _PC_SOCK_MAXBUF, + + _PC_FILESIZEBITS, + + _PC_REC_INCR_XFER_SIZE, + + _PC_REC_MAX_XFER_SIZE, + + _PC_REC_MIN_XFER_SIZE, + + _PC_REC_XFER_ALIGN, + + _PC_ALLOC_SIZE_MIN, + + _PC_SYMLINK_MAX, + + _PC_2_SYMLINKS + + }; + + +enum + { + _SC_ARG_MAX, + + _SC_CHILD_MAX, + + _SC_CLK_TCK, + + _SC_NGROUPS_MAX, + + _SC_OPEN_MAX, + + _SC_STREAM_MAX, + + _SC_TZNAME_MAX, + + _SC_JOB_CONTROL, + + _SC_SAVED_IDS, + + _SC_REALTIME_SIGNALS, + + _SC_PRIORITY_SCHEDULING, + + _SC_TIMERS, + + _SC_ASYNCHRONOUS_IO, + + _SC_PRIORITIZED_IO, + + _SC_SYNCHRONIZED_IO, + + _SC_FSYNC, + + _SC_MAPPED_FILES, + + _SC_MEMLOCK, + + _SC_MEMLOCK_RANGE, + + _SC_MEMORY_PROTECTION, + + _SC_MESSAGE_PASSING, + + _SC_SEMAPHORES, + + _SC_SHARED_MEMORY_OBJECTS, + + _SC_AIO_LISTIO_MAX, + + _SC_AIO_MAX, + + _SC_AIO_PRIO_DELTA_MAX, + + _SC_DELAYTIMER_MAX, + + _SC_MQ_OPEN_MAX, + + _SC_MQ_PRIO_MAX, + + _SC_VERSION, + + _SC_PAGESIZE, + + + _SC_RTSIG_MAX, + + _SC_SEM_NSEMS_MAX, + + _SC_SEM_VALUE_MAX, + + _SC_SIGQUEUE_MAX, + + _SC_TIMER_MAX, + + + + + _SC_BC_BASE_MAX, + + _SC_BC_DIM_MAX, + + _SC_BC_SCALE_MAX, + + _SC_BC_STRING_MAX, + + _SC_COLL_WEIGHTS_MAX, + + _SC_EQUIV_CLASS_MAX, + + _SC_EXPR_NEST_MAX, + + _SC_LINE_MAX, + + _SC_RE_DUP_MAX, + + _SC_CHARCLASS_NAME_MAX, + + + _SC_2_VERSION, + + _SC_2_C_BIND, + + _SC_2_C_DEV, + + _SC_2_FORT_DEV, + + _SC_2_FORT_RUN, + + _SC_2_SW_DEV, + + _SC_2_LOCALEDEF, + + + _SC_PII, + + _SC_PII_XTI, + + _SC_PII_SOCKET, + + _SC_PII_INTERNET, + + _SC_PII_OSI, + + _SC_POLL, + + _SC_SELECT, + + _SC_UIO_MAXIOV, + + _SC_IOV_MAX = _SC_UIO_MAXIOV, + + _SC_PII_INTERNET_STREAM, + + _SC_PII_INTERNET_DGRAM, + + _SC_PII_OSI_COTS, + + _SC_PII_OSI_CLTS, + + _SC_PII_OSI_M, + + _SC_T_IOV_MAX, + + + + _SC_THREADS, + + _SC_THREAD_SAFE_FUNCTIONS, + + _SC_GETGR_R_SIZE_MAX, + + _SC_GETPW_R_SIZE_MAX, + + _SC_LOGIN_NAME_MAX, + + _SC_TTY_NAME_MAX, + + _SC_THREAD_DESTRUCTOR_ITERATIONS, + + _SC_THREAD_KEYS_MAX, + + _SC_THREAD_STACK_MIN, + + _SC_THREAD_THREADS_MAX, + + _SC_THREAD_ATTR_STACKADDR, + + _SC_THREAD_ATTR_STACKSIZE, + + _SC_THREAD_PRIORITY_SCHEDULING, + + _SC_THREAD_PRIO_INHERIT, + + _SC_THREAD_PRIO_PROTECT, + + _SC_THREAD_PROCESS_SHARED, + + + _SC_NPROCESSORS_CONF, + + _SC_NPROCESSORS_ONLN, + + _SC_PHYS_PAGES, + + _SC_AVPHYS_PAGES, + + _SC_ATEXIT_MAX, + + _SC_PASS_MAX, + + + _SC_XOPEN_VERSION, + + _SC_XOPEN_XCU_VERSION, + + _SC_XOPEN_UNIX, + + _SC_XOPEN_CRYPT, + + _SC_XOPEN_ENH_I18N, + + _SC_XOPEN_SHM, + + + _SC_2_CHAR_TERM, + + _SC_2_C_VERSION, + + _SC_2_UPE, + + + _SC_XOPEN_XPG2, + + _SC_XOPEN_XPG3, + + _SC_XOPEN_XPG4, + + + _SC_CHAR_BIT, + + _SC_CHAR_MAX, + + _SC_CHAR_MIN, + + _SC_INT_MAX, + + _SC_INT_MIN, + + _SC_LONG_BIT, + + _SC_WORD_BIT, + + _SC_MB_LEN_MAX, + + _SC_NZERO, + + _SC_SSIZE_MAX, + + _SC_SCHAR_MAX, + + _SC_SCHAR_MIN, + + _SC_SHRT_MAX, + + _SC_SHRT_MIN, + + _SC_UCHAR_MAX, + + _SC_UINT_MAX, + + _SC_ULONG_MAX, + + _SC_USHRT_MAX, + + + _SC_NL_ARGMAX, + + _SC_NL_LANGMAX, + + _SC_NL_MSGMAX, + + _SC_NL_NMAX, + + _SC_NL_SETMAX, + + _SC_NL_TEXTMAX, + + + _SC_XBS5_ILP32_OFF32, + + _SC_XBS5_ILP32_OFFBIG, + + _SC_XBS5_LP64_OFF64, + + _SC_XBS5_LPBIG_OFFBIG, + + + _SC_XOPEN_LEGACY, + + _SC_XOPEN_REALTIME, + + _SC_XOPEN_REALTIME_THREADS, + + + _SC_ADVISORY_INFO, + + _SC_BARRIERS, + + _SC_BASE, + + _SC_C_LANG_SUPPORT, + + _SC_C_LANG_SUPPORT_R, + + _SC_CLOCK_SELECTION, + + _SC_CPUTIME, + + _SC_THREAD_CPUTIME, + + _SC_DEVICE_IO, + + _SC_DEVICE_SPECIFIC, + + _SC_DEVICE_SPECIFIC_R, + + _SC_FD_MGMT, + + _SC_FIFO, + + _SC_PIPE, + + _SC_FILE_ATTRIBUTES, + + _SC_FILE_LOCKING, + + _SC_FILE_SYSTEM, + + _SC_MONOTONIC_CLOCK, + + _SC_MULTI_PROCESS, + + _SC_SINGLE_PROCESS, + + _SC_NETWORKING, + + _SC_READER_WRITER_LOCKS, + + _SC_SPIN_LOCKS, + + _SC_REGEXP, + + _SC_REGEX_VERSION, + + _SC_SHELL, + + _SC_SIGNALS, + + _SC_SPAWN, + + _SC_SPORADIC_SERVER, + + _SC_THREAD_SPORADIC_SERVER, + + _SC_SYSTEM_DATABASE, + + _SC_SYSTEM_DATABASE_R, + + _SC_TIMEOUTS, + + _SC_TYPED_MEMORY_OBJECTS, + + _SC_USER_GROUPS, + + _SC_USER_GROUPS_R, + + _SC_2_PBS, + + _SC_2_PBS_ACCOUNTING, + + _SC_2_PBS_LOCATE, + + _SC_2_PBS_MESSAGE, + + _SC_2_PBS_TRACK, + + _SC_SYMLOOP_MAX, + + _SC_STREAMS, + + _SC_2_PBS_CHECKPOINT, + + + _SC_V6_ILP32_OFF32, + + _SC_V6_ILP32_OFFBIG, + + _SC_V6_LP64_OFF64, + + _SC_V6_LPBIG_OFFBIG, + + + _SC_HOST_NAME_MAX, + + _SC_TRACE, + + _SC_TRACE_EVENT_FILTER, + + _SC_TRACE_INHERIT, + + _SC_TRACE_LOG, + + + _SC_LEVEL1_ICACHE_SIZE, + + _SC_LEVEL1_ICACHE_ASSOC, + + _SC_LEVEL1_ICACHE_LINESIZE, + + _SC_LEVEL1_DCACHE_SIZE, + + _SC_LEVEL1_DCACHE_ASSOC, + + _SC_LEVEL1_DCACHE_LINESIZE, + + _SC_LEVEL2_CACHE_SIZE, + + _SC_LEVEL2_CACHE_ASSOC, + + _SC_LEVEL2_CACHE_LINESIZE, + + _SC_LEVEL3_CACHE_SIZE, + + _SC_LEVEL3_CACHE_ASSOC, + + _SC_LEVEL3_CACHE_LINESIZE, + + _SC_LEVEL4_CACHE_SIZE, + + _SC_LEVEL4_CACHE_ASSOC, + + _SC_LEVEL4_CACHE_LINESIZE, + + + + _SC_IPV6 = _SC_LEVEL1_ICACHE_SIZE + 50, + + _SC_RAW_SOCKETS, + + + _SC_V7_ILP32_OFF32, + + _SC_V7_ILP32_OFFBIG, + + _SC_V7_LP64_OFF64, + + _SC_V7_LPBIG_OFFBIG, + + + _SC_SS_REPL_MAX, + + + _SC_TRACE_EVENT_NAME_MAX, + + _SC_TRACE_NAME_MAX, + + _SC_TRACE_SYS_MAX, + + _SC_TRACE_USER_EVENT_MAX, + + + _SC_XOPEN_STREAMS, + + + _SC_THREAD_ROBUST_PRIO_INHERIT, + + _SC_THREAD_ROBUST_PRIO_PROTECT + + }; + + +enum + { + _CS_PATH, + + + _CS_V6_WIDTH_RESTRICTED_ENVS, + + + + _CS_GNU_LIBC_VERSION, + + _CS_GNU_LIBPTHREAD_VERSION, + + + _CS_V5_WIDTH_RESTRICTED_ENVS, + + + + _CS_V7_WIDTH_RESTRICTED_ENVS, + + + + _CS_LFS_CFLAGS = 1000, + + _CS_LFS_LDFLAGS, + + _CS_LFS_LIBS, + + _CS_LFS_LINTFLAGS, + + _CS_LFS64_CFLAGS, + + _CS_LFS64_LDFLAGS, + + _CS_LFS64_LIBS, + + _CS_LFS64_LINTFLAGS, + + + _CS_XBS5_ILP32_OFF32_CFLAGS = 1100, + + _CS_XBS5_ILP32_OFF32_LDFLAGS, + + _CS_XBS5_ILP32_OFF32_LIBS, + + _CS_XBS5_ILP32_OFF32_LINTFLAGS, + + _CS_XBS5_ILP32_OFFBIG_CFLAGS, + + _CS_XBS5_ILP32_OFFBIG_LDFLAGS, + + _CS_XBS5_ILP32_OFFBIG_LIBS, + + _CS_XBS5_ILP32_OFFBIG_LINTFLAGS, + + _CS_XBS5_LP64_OFF64_CFLAGS, + + _CS_XBS5_LP64_OFF64_LDFLAGS, + + _CS_XBS5_LP64_OFF64_LIBS, + + _CS_XBS5_LP64_OFF64_LINTFLAGS, + + _CS_XBS5_LPBIG_OFFBIG_CFLAGS, + + _CS_XBS5_LPBIG_OFFBIG_LDFLAGS, + + _CS_XBS5_LPBIG_OFFBIG_LIBS, + + _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS, + + + _CS_POSIX_V6_ILP32_OFF32_CFLAGS, + + _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, + + _CS_POSIX_V6_ILP32_OFF32_LIBS, + + _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS, + + _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS, + + _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS, + + _CS_POSIX_V6_ILP32_OFFBIG_LIBS, + + _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS, + + _CS_POSIX_V6_LP64_OFF64_CFLAGS, + + _CS_POSIX_V6_LP64_OFF64_LDFLAGS, + + _CS_POSIX_V6_LP64_OFF64_LIBS, + + _CS_POSIX_V6_LP64_OFF64_LINTFLAGS, + + _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS, + + _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, + + _CS_POSIX_V6_LPBIG_OFFBIG_LIBS, + + _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS, + + + _CS_POSIX_V7_ILP32_OFF32_CFLAGS, + + _CS_POSIX_V7_ILP32_OFF32_LDFLAGS, + + _CS_POSIX_V7_ILP32_OFF32_LIBS, + + _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS, + + _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS, + + _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS, + + _CS_POSIX_V7_ILP32_OFFBIG_LIBS, + + _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS, + + _CS_POSIX_V7_LP64_OFF64_CFLAGS, + + _CS_POSIX_V7_LP64_OFF64_LDFLAGS, + + _CS_POSIX_V7_LP64_OFF64_LIBS, + + _CS_POSIX_V7_LP64_OFF64_LINTFLAGS, + + _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS, + + _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS, + + _CS_POSIX_V7_LPBIG_OFFBIG_LIBS, + + _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS, + + + _CS_V6_ENV, + + _CS_V7_ENV + + }; +# 610 "/usr/include/unistd.h" 2 3 4 + + +extern long int pathconf (const char *__path, int __name) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern long int fpathconf (int __fd, int __name) __attribute__ ((__nothrow__ )); + + +extern long int sysconf (int __name) __attribute__ ((__nothrow__ )); + + + +extern size_t confstr (int __name, char *__buf, size_t __len) __attribute__ ((__nothrow__ )); + + + + +extern __pid_t getpid (void) __attribute__ ((__nothrow__ )); + + +extern __pid_t getppid (void) __attribute__ ((__nothrow__ )); + + +extern __pid_t getpgrp (void) __attribute__ ((__nothrow__ )); + + +extern __pid_t __getpgid (__pid_t __pid) __attribute__ ((__nothrow__ )); + +extern __pid_t getpgid (__pid_t __pid) __attribute__ ((__nothrow__ )); + + + + + + +extern int setpgid (__pid_t __pid, __pid_t __pgid) __attribute__ ((__nothrow__ )); +# 660 "/usr/include/unistd.h" 3 4 +extern int setpgrp (void) __attribute__ ((__nothrow__ )); + + + + + + +extern __pid_t setsid (void) __attribute__ ((__nothrow__ )); + + + +extern __pid_t getsid (__pid_t __pid) __attribute__ ((__nothrow__ )); + + + +extern __uid_t getuid (void) __attribute__ ((__nothrow__ )); + + +extern __uid_t geteuid (void) __attribute__ ((__nothrow__ )); + + +extern __gid_t getgid (void) __attribute__ ((__nothrow__ )); + + +extern __gid_t getegid (void) __attribute__ ((__nothrow__ )); + + + + +extern int getgroups (int __size, __gid_t __list[]) __attribute__ ((__nothrow__ )) ; +# 700 "/usr/include/unistd.h" 3 4 +extern int setuid (__uid_t __uid) __attribute__ ((__nothrow__ )) ; + + + + +extern int setreuid (__uid_t __ruid, __uid_t __euid) __attribute__ ((__nothrow__ )) ; + + + + +extern int seteuid (__uid_t __uid) __attribute__ ((__nothrow__ )) ; + + + + + + +extern int setgid (__gid_t __gid) __attribute__ ((__nothrow__ )) ; + + + + +extern int setregid (__gid_t __rgid, __gid_t __egid) __attribute__ ((__nothrow__ )) ; + + + + +extern int setegid (__gid_t __gid) __attribute__ ((__nothrow__ )) ; +# 756 "/usr/include/unistd.h" 3 4 +extern __pid_t fork (void) __attribute__ ((__nothrow__)); + + + + + + + +extern __pid_t vfork (void) __attribute__ ((__nothrow__ )); + + + + + +extern char *ttyname (int __fd) __attribute__ ((__nothrow__ )); + + + +extern int ttyname_r (int __fd, char *__buf, size_t __buflen) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))) ; + + + +extern int isatty (int __fd) __attribute__ ((__nothrow__ )); + + + + + +extern int ttyslot (void) __attribute__ ((__nothrow__ )); + + + + +extern int link (const char *__from, const char *__to) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))) ; + + + + +extern int linkat (int __fromfd, const char *__from, int __tofd, + const char *__to, int __flags) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))) ; + + + + +extern int symlink (const char *__from, const char *__to) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))) ; + + + + +extern ssize_t readlink (const char *__restrict __path, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))) ; + + + + +extern int symlinkat (const char *__from, int __tofd, + const char *__to) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 3))) ; + + +extern ssize_t readlinkat (int __fd, const char *__restrict __path, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))) ; + + + +extern int unlink (const char *__name) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int unlinkat (int __fd, const char *__name, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + +extern int rmdir (const char *__path) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern __pid_t tcgetpgrp (int __fd) __attribute__ ((__nothrow__ )); + + +extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) __attribute__ ((__nothrow__ )); + + + + + + +extern char *getlogin (void); + + + + + + + +extern int getlogin_r (char *__name, size_t __name_len) __attribute__ ((__nonnull__ (1))); + + + + +extern int setlogin (const char *__name) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 871 "/usr/include/unistd.h" 3 4 +# 1 "/usr/include/getopt.h" 1 3 4 +# 57 "/usr/include/getopt.h" 3 4 +extern char *optarg; +# 71 "/usr/include/getopt.h" 3 4 +extern int optind; + + + + +extern int opterr; + + + +extern int optopt; +# 150 "/usr/include/getopt.h" 3 4 +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __attribute__ ((__nothrow__ )); +# 872 "/usr/include/unistd.h" 2 3 4 + + + + + + + +extern int gethostname (char *__name, size_t __len) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int sethostname (const char *__name, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + +extern int sethostid (long int __id) __attribute__ ((__nothrow__ )) ; + + + + + +extern int getdomainname (char *__name, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +extern int setdomainname (const char *__name, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + + + +extern int vhangup (void) __attribute__ ((__nothrow__ )); + + +extern int revoke (const char *__file) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + + + + + +extern int profil (unsigned short int *__sample_buffer, size_t __size, + size_t __offset, unsigned int __scale) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int acct (const char *__name) __attribute__ ((__nothrow__ )); + + + +extern char *getusershell (void) __attribute__ ((__nothrow__ )); +extern void endusershell (void) __attribute__ ((__nothrow__ )); +extern void setusershell (void) __attribute__ ((__nothrow__ )); + + + + + +extern int daemon (int __nochdir, int __noclose) __attribute__ ((__nothrow__ )) ; + + + + + + +extern int chroot (const char *__path) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + +extern char *getpass (const char *__prompt) __attribute__ ((__nonnull__ (1))); + + + + + + + +extern int fsync (int __fd); +# 969 "/usr/include/unistd.h" 3 4 +extern long int gethostid (void); + + +extern void sync (void) __attribute__ ((__nothrow__ )); + + + + + +extern int getpagesize (void) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + + + +extern int getdtablesize (void) __attribute__ ((__nothrow__ )); +# 993 "/usr/include/unistd.h" 3 4 +extern int truncate (const char *__file, __off_t __length) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 1016 "/usr/include/unistd.h" 3 4 +extern int ftruncate (int __fd, __off_t __length) __attribute__ ((__nothrow__ )) ; +# 1037 "/usr/include/unistd.h" 3 4 +extern int brk (void *__addr) __attribute__ ((__nothrow__ )) ; + + + + + +extern void *sbrk (intptr_t __delta) __attribute__ ((__nothrow__ )); +# 1058 "/usr/include/unistd.h" 3 4 +extern long int syscall (long int __sysno, ...) __attribute__ ((__nothrow__ )); +# 1081 "/usr/include/unistd.h" 3 4 +extern int lockf (int __fd, int __cmd, __off_t __len) ; +# 1112 "/usr/include/unistd.h" 3 4 +extern int fdatasync (int __fildes); +# 29 "./../test/abts.h" 2 +# 41 "./../test/abts.h" +struct sub_suite { + const char *name; + int num_test; + int failed; + int not_run; + int not_impl; + struct sub_suite *next; +}; +typedef struct sub_suite sub_suite; + +struct abts_suite { + sub_suite *head; + sub_suite *tail; +}; +typedef struct abts_suite abts_suite; + +struct abts_case { + int failed; + sub_suite *suite; +}; +typedef struct abts_case abts_case; + +typedef void (*test_func)(abts_case *tc, void *data); + + + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name); +void abts_run_test(abts_suite *ts, test_func f, void *value); +void abts_log_message(const char *fmt, ...); + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno); +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno); +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno); +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno); +void abts_true(abts_case *tc, int condition, int lineno); +void abts_fail(abts_case *tc, const char *message, int lineno); +void abts_not_impl(abts_case *tc, const char *message, int lineno); +void abts_assert(abts_case *tc, const char *message, int condition, int lineno); +void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno); +# 99 "./../test/abts.h" +abts_suite *run_tests(abts_suite *suite); +abts_suite *run_tests1(abts_suite *suite); +# 8 "main1.c" 2 +# 1 "./../test/testutil.h" 1 +# 17 "./../test/testutil.h" +# 1 "../include/apr_pools.h" 1 +# 43 "../include/apr_pools.h" +# 1 "../include/apr.h" 1 +# 168 "../include/apr.h" +# 1 "/usr/include/x86_64-linux-gnu/sys/socket.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/sys/uio.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/uio.h" 1 3 4 +# 43 "/usr/include/x86_64-linux-gnu/bits/uio.h" 3 4 +struct iovec + { + void *iov_base; + size_t iov_len; + }; +# 29 "/usr/include/x86_64-linux-gnu/sys/uio.h" 2 3 4 +# 39 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +extern ssize_t readv (int __fd, const struct iovec *__iovec, int __count) + ; +# 50 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +extern ssize_t writev (int __fd, const struct iovec *__iovec, int __count) + ; +# 65 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +extern ssize_t preadv (int __fd, const struct iovec *__iovec, int __count, + __off_t __offset) ; +# 77 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +extern ssize_t pwritev (int __fd, const struct iovec *__iovec, int __count, + __off_t __offset) ; +# 27 "/usr/include/x86_64-linux-gnu/sys/socket.h" 2 3 4 + +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/sys/socket.h" 2 3 4 +# 38 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/socket.h" 1 3 4 +# 27 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/socket.h" 2 3 4 +# 38 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/socket_type.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/socket_type.h" 3 4 +enum __socket_type +{ + SOCK_STREAM = 1, + + + SOCK_DGRAM = 2, + + + SOCK_RAW = 3, + + SOCK_RDM = 4, + + SOCK_SEQPACKET = 5, + + + SOCK_DCCP = 6, + + SOCK_PACKET = 10, + + + + + + + + SOCK_CLOEXEC = 02000000, + + + SOCK_NONBLOCK = 00004000 + + +}; +# 39 "/usr/include/x86_64-linux-gnu/bits/socket.h" 2 3 4 +# 146 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/sockaddr.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/sockaddr.h" 3 4 +typedef unsigned short int sa_family_t; +# 147 "/usr/include/x86_64-linux-gnu/bits/socket.h" 2 3 4 + + +struct sockaddr + { + sa_family_t sa_family; + char sa_data[14]; + }; +# 162 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +struct sockaddr_storage + { + sa_family_t ss_family; + unsigned long int __ss_align; + char __ss_padding[(128 - (2 * sizeof (unsigned long int)))]; + }; + + + +enum + { + MSG_OOB = 0x01, + + MSG_PEEK = 0x02, + + MSG_DONTROUTE = 0x04, + + + + + + + MSG_CTRUNC = 0x08, + + MSG_PROXY = 0x10, + + MSG_TRUNC = 0x20, + + MSG_DONTWAIT = 0x40, + + MSG_EOR = 0x80, + + MSG_WAITALL = 0x100, + + MSG_FIN = 0x200, + + MSG_SYN = 0x400, + + MSG_CONFIRM = 0x800, + + MSG_RST = 0x1000, + + MSG_ERRQUEUE = 0x2000, + + MSG_NOSIGNAL = 0x4000, + + MSG_MORE = 0x8000, + + MSG_WAITFORONE = 0x10000, + + MSG_FASTOPEN = 0x20000000, + + + MSG_CMSG_CLOEXEC = 0x40000000 + + + + }; + + + + +struct msghdr + { + void *msg_name; + socklen_t msg_namelen; + + struct iovec *msg_iov; + size_t msg_iovlen; + + void *msg_control; + size_t msg_controllen; + + + + + int msg_flags; + }; + + +struct cmsghdr + { + size_t cmsg_len; + + + + + int cmsg_level; + int cmsg_type; + + __extension__ unsigned char __cmsg_data []; + + }; +# 272 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __attribute__ ((__nothrow__ )); +# 299 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +enum + { + SCM_RIGHTS = 0x01 + + + + + + }; +# 345 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/asm/socket.h" 1 3 4 +# 1 "/usr/include/asm-generic/socket.h" 1 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/asm/sockios.h" 1 3 4 +# 1 "/usr/include/asm-generic/sockios.h" 1 3 4 +# 2 "/usr/include/x86_64-linux-gnu/asm/sockios.h" 2 3 4 +# 5 "/usr/include/asm-generic/socket.h" 2 3 4 +# 2 "/usr/include/x86_64-linux-gnu/asm/socket.h" 2 3 4 +# 346 "/usr/include/x86_64-linux-gnu/bits/socket.h" 2 3 4 +# 379 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +struct linger + { + int l_onoff; + int l_linger; + }; +# 39 "/usr/include/x86_64-linux-gnu/sys/socket.h" 2 3 4 + + + + +struct osockaddr + { + unsigned short int sa_family; + unsigned char sa_data[14]; + }; + + + + +enum +{ + SHUT_RD = 0, + + SHUT_WR, + + SHUT_RDWR + +}; +# 113 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int socket (int __domain, int __type, int __protocol) __attribute__ ((__nothrow__ )); + + + + + +extern int socketpair (int __domain, int __type, int __protocol, + int __fds[2]) __attribute__ ((__nothrow__ )); + + +extern int bind (int __fd, const struct sockaddr * __addr, socklen_t __len) + __attribute__ ((__nothrow__ )); + + +extern int getsockname (int __fd, struct sockaddr *__restrict __addr, + socklen_t *__restrict __len) __attribute__ ((__nothrow__ )); +# 137 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int connect (int __fd, const struct sockaddr * __addr, socklen_t __len); + + + +extern int getpeername (int __fd, struct sockaddr *__restrict __addr, + socklen_t *__restrict __len) __attribute__ ((__nothrow__ )); + + + + + + +extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); + + + + + + +extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); + + + + + + +extern ssize_t sendto (int __fd, const void *__buf, size_t __n, + int __flags, const struct sockaddr * __addr, + socklen_t __addr_len); +# 174 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n, + int __flags, struct sockaddr *__restrict __addr, + socklen_t *__restrict __addr_len); + + + + + + + +extern ssize_t sendmsg (int __fd, const struct msghdr *__message, + int __flags); +# 202 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags); +# 219 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int getsockopt (int __fd, int __level, int __optname, + void *__restrict __optval, + socklen_t *__restrict __optlen) __attribute__ ((__nothrow__ )); + + + + +extern int setsockopt (int __fd, int __level, int __optname, + const void *__optval, socklen_t __optlen) __attribute__ ((__nothrow__ )); + + + + + +extern int listen (int __fd, int __n) __attribute__ ((__nothrow__ )); +# 243 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int accept (int __fd, struct sockaddr *__restrict __addr, + socklen_t *__restrict __addr_len); +# 261 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int shutdown (int __fd, int __how) __attribute__ ((__nothrow__ )); + + + + +extern int sockatmark (int __fd) __attribute__ ((__nothrow__ )); + + + + + + + +extern int isfdtype (int __fd, int __fdtype) __attribute__ ((__nothrow__ )); +# 169 "../include/apr.h" 2 +# 178 "../include/apr.h" +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdint.h" 1 3 +# 61 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdint.h" 3 +# 1 "/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include/stdint.h" 1 3 4 + + + + + + + + +# 1 "/usr/include/stdint.h" 1 3 4 +# 26 "/usr/include/stdint.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wchar.h" 1 3 4 +# 27 "/usr/include/stdint.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 28 "/usr/include/stdint.h" 2 3 4 +# 48 "/usr/include/stdint.h" 3 4 +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; + +typedef unsigned int uint32_t; + + + +typedef unsigned long int uint64_t; +# 65 "/usr/include/stdint.h" 3 4 +typedef signed char int_least8_t; +typedef short int int_least16_t; +typedef int int_least32_t; + +typedef long int int_least64_t; + + + + + + +typedef unsigned char uint_least8_t; +typedef unsigned short int uint_least16_t; +typedef unsigned int uint_least32_t; + +typedef unsigned long int uint_least64_t; +# 90 "/usr/include/stdint.h" 3 4 +typedef signed char int_fast8_t; + +typedef long int int_fast16_t; +typedef long int int_fast32_t; +typedef long int int_fast64_t; +# 103 "/usr/include/stdint.h" 3 4 +typedef unsigned char uint_fast8_t; + +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; +typedef unsigned long int uint_fast64_t; +# 122 "/usr/include/stdint.h" 3 4 +typedef unsigned long int uintptr_t; +# 134 "/usr/include/stdint.h" 3 4 +typedef long int intmax_t; +typedef unsigned long int uintmax_t; +# 10 "/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include/stdint.h" 2 3 4 +# 62 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdint.h" 2 3 +# 179 "../include/apr.h" 2 + + + +# 1 "/usr/include/x86_64-linux-gnu/sys/wait.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +# 1 "/usr/include/signal.h" 1 3 4 +# 32 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/sigset.h" 1 3 4 +# 102 "/usr/include/x86_64-linux-gnu/bits/sigset.h" 3 4 +extern int __sigismember (const __sigset_t *, int); +extern int __sigaddset (__sigset_t *, int); +extern int __sigdelset (__sigset_t *, int); +# 33 "/usr/include/signal.h" 2 3 4 + + + + + + + +typedef __sig_atomic_t sig_atomic_t; +# 57 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/signum.h" 1 3 4 +# 58 "/usr/include/signal.h" 2 3 4 +# 75 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 76 "/usr/include/signal.h" 2 3 4 + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 2 3 4 + + + + + + + +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +# 58 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +typedef __clock_t __sigchld_clock_t; + + + +typedef struct + { + int si_signo; + int si_errno; + + int si_code; + + union + { + int _pad[((128 / sizeof (int)) - 4)]; + + + struct + { + __pid_t si_pid; + __uid_t si_uid; + } _kill; + + + struct + { + int si_tid; + int si_overrun; + sigval_t si_sigval; + } _timer; + + + struct + { + __pid_t si_pid; + __uid_t si_uid; + sigval_t si_sigval; + } _rt; + + + struct + { + __pid_t si_pid; + __uid_t si_uid; + int si_status; + __sigchld_clock_t si_utime; + __sigchld_clock_t si_stime; + } _sigchld; + + + struct + { + void *si_addr; + short int si_addr_lsb; + } _sigfault; + + + struct + { + long int si_band; + int si_fd; + } _sigpoll; + + + struct + { + void *_call_addr; + int _syscall; + unsigned int _arch; + } _sigsys; + } _sifields; + } siginfo_t ; +# 153 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +enum +{ + SI_ASYNCNL = -60, + + SI_TKILL = -6, + + SI_SIGIO, + + SI_ASYNCIO, + + SI_MESGQ, + + SI_TIMER, + + SI_QUEUE, + + SI_USER, + + SI_KERNEL = 0x80 + +}; + + + +enum +{ + ILL_ILLOPC = 1, + + ILL_ILLOPN, + + ILL_ILLADR, + + ILL_ILLTRP, + + ILL_PRVOPC, + + ILL_PRVREG, + + ILL_COPROC, + + ILL_BADSTK + +}; + + +enum +{ + FPE_INTDIV = 1, + + FPE_INTOVF, + + FPE_FLTDIV, + + FPE_FLTOVF, + + FPE_FLTUND, + + FPE_FLTRES, + + FPE_FLTINV, + + FPE_FLTSUB + +}; + + +enum +{ + SEGV_MAPERR = 1, + + SEGV_ACCERR + +}; + + +enum +{ + BUS_ADRALN = 1, + + BUS_ADRERR, + + BUS_OBJERR, + + BUS_MCEERR_AR, + + BUS_MCEERR_AO + +}; + + +enum +{ + TRAP_BRKPT = 1, + + TRAP_TRACE + +}; + + +enum +{ + CLD_EXITED = 1, + + CLD_KILLED, + + CLD_DUMPED, + + CLD_TRAPPED, + + CLD_STOPPED, + + CLD_CONTINUED + +}; + + +enum +{ + POLL_IN = 1, + + POLL_OUT, + + POLL_MSG, + + POLL_ERR, + + POLL_PRI, + + POLL_HUP + +}; +# 307 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[((64 / sizeof (int)) - 4)]; + + + + __pid_t _tid; + + struct + { + void (*_function) (sigval_t); + pthread_attr_t *_attribute; + } _sigev_thread; + } _sigev_un; + } sigevent_t; + + + + + + +enum +{ + SIGEV_SIGNAL = 0, + + SIGEV_NONE, + + SIGEV_THREAD, + + + SIGEV_THREAD_ID = 4 + +}; +# 81 "/usr/include/signal.h" 2 3 4 + + + + +typedef void (*__sighandler_t) (int); + + + + +extern __sighandler_t __sysv_signal (int __sig, __sighandler_t __handler) + __attribute__ ((__nothrow__ )); +# 102 "/usr/include/signal.h" 3 4 +extern __sighandler_t signal (int __sig, __sighandler_t __handler) + __attribute__ ((__nothrow__ )); +# 127 "/usr/include/signal.h" 3 4 +extern int kill (__pid_t __pid, int __sig) __attribute__ ((__nothrow__ )); + + + + + + +extern int killpg (__pid_t __pgrp, int __sig) __attribute__ ((__nothrow__ )); + + + + +extern int raise (int __sig) __attribute__ ((__nothrow__ )); + + + + +extern __sighandler_t ssignal (int __sig, __sighandler_t __handler) + __attribute__ ((__nothrow__ )); +extern int gsignal (int __sig) __attribute__ ((__nothrow__ )); + + + + +extern void psignal (int __sig, const char *__s); + + + + +extern void psiginfo (const siginfo_t *__pinfo, const char *__s); +# 167 "/usr/include/signal.h" 3 4 +extern int __sigpause (int __sig_or_mask, int __is_sig); +# 189 "/usr/include/signal.h" 3 4 +extern int sigblock (int __mask) __attribute__ ((__nothrow__ )) __attribute__ ((__deprecated__)); + + +extern int sigsetmask (int __mask) __attribute__ ((__nothrow__ )) __attribute__ ((__deprecated__)); + + +extern int siggetmask (void) __attribute__ ((__nothrow__ )) __attribute__ ((__deprecated__)); +# 209 "/usr/include/signal.h" 3 4 +typedef __sighandler_t sig_t; + + + + + +extern int sigemptyset (sigset_t *__set) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int sigfillset (sigset_t *__set) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int sigaddset (sigset_t *__set, int __signo) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int sigdelset (sigset_t *__set, int __signo) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int sigismember (const sigset_t *__set, int __signo) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 245 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/sigaction.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/sigaction.h" 3 4 +struct sigaction + { + + + union + { + + __sighandler_t sa_handler; + + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; + + + + + + + + __sigset_t sa_mask; + + + int sa_flags; + + + void (*sa_restorer) (void); + }; +# 246 "/usr/include/signal.h" 2 3 4 + + +extern int sigprocmask (int __how, const sigset_t *__restrict __set, + sigset_t *__restrict __oset) __attribute__ ((__nothrow__ )); + + + + + + +extern int sigsuspend (const sigset_t *__set) __attribute__ ((__nonnull__ (1))); + + +extern int sigaction (int __sig, const struct sigaction *__restrict __act, + struct sigaction *__restrict __oact) __attribute__ ((__nothrow__ )); + + +extern int sigpending (sigset_t *__set) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int sigwait (const sigset_t *__restrict __set, int *__restrict __sig) + __attribute__ ((__nonnull__ (1, 2))); + + + + + + +extern int sigwaitinfo (const sigset_t *__restrict __set, + siginfo_t *__restrict __info) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int sigtimedwait (const sigset_t *__restrict __set, + siginfo_t *__restrict __info, + const struct timespec *__restrict __timeout) + __attribute__ ((__nonnull__ (1))); + + + +extern int sigqueue (__pid_t __pid, int __sig, const union sigval __val) + __attribute__ ((__nothrow__ )); +# 303 "/usr/include/signal.h" 3 4 +extern const char *const _sys_siglist[65]; +extern const char *const sys_siglist[65]; + + +struct sigvec + { + __sighandler_t sv_handler; + int sv_mask; + + int sv_flags; + + }; +# 327 "/usr/include/signal.h" 3 4 +extern int sigvec (int __sig, const struct sigvec *__vec, + struct sigvec *__ovec) __attribute__ ((__nothrow__ )); + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sigcontext.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/bits/sigcontext.h" 3 4 +struct _fpx_sw_bytes +{ + __uint32_t magic1; + __uint32_t extended_size; + __uint64_t xstate_bv; + __uint32_t xstate_size; + __uint32_t padding[7]; +}; + +struct _fpreg +{ + unsigned short significand[4]; + unsigned short exponent; +}; + +struct _fpxreg +{ + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _xmmreg +{ + __uint32_t element[4]; +}; +# 121 "/usr/include/x86_64-linux-gnu/bits/sigcontext.h" 3 4 +struct _fpstate +{ + + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + struct _fpxreg _st[8]; + struct _xmmreg _xmm[16]; + __uint32_t padding[24]; +}; + +struct sigcontext +{ + __uint64_t r8; + __uint64_t r9; + __uint64_t r10; + __uint64_t r11; + __uint64_t r12; + __uint64_t r13; + __uint64_t r14; + __uint64_t r15; + __uint64_t rdi; + __uint64_t rsi; + __uint64_t rbp; + __uint64_t rbx; + __uint64_t rdx; + __uint64_t rax; + __uint64_t rcx; + __uint64_t rsp; + __uint64_t rip; + __uint64_t eflags; + unsigned short cs; + unsigned short gs; + unsigned short fs; + unsigned short __pad0; + __uint64_t err; + __uint64_t trapno; + __uint64_t oldmask; + __uint64_t cr2; + __extension__ union + { + struct _fpstate * fpstate; + __uint64_t __fpstate_word; + }; + __uint64_t __reserved1 [8]; +}; + + + +struct _xsave_hdr +{ + __uint64_t xstate_bv; + __uint64_t reserved1[2]; + __uint64_t reserved2[5]; +}; + +struct _ymmh_state +{ + __uint32_t ymmh_space[64]; +}; + +struct _xstate +{ + struct _fpstate fpstate; + struct _xsave_hdr xstate_hdr; + struct _ymmh_state ymmh; +}; +# 333 "/usr/include/signal.h" 2 3 4 + + +extern int sigreturn (struct sigcontext *__scp) __attribute__ ((__nothrow__ )); + + + + + + + +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 343 "/usr/include/signal.h" 2 3 4 + + + + +extern int siginterrupt (int __sig, int __interrupt) __attribute__ ((__nothrow__ )); + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sigstack.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/bits/sigstack.h" 3 4 +struct sigstack + { + void *ss_sp; + int ss_onstack; + }; + + + +enum +{ + SS_ONSTACK = 1, + + SS_DISABLE + +}; +# 49 "/usr/include/x86_64-linux-gnu/bits/sigstack.h" 3 4 +typedef struct sigaltstack + { + void *ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; +# 350 "/usr/include/signal.h" 2 3 4 + + +# 1 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 3 4 +# 1 "/usr/include/signal.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 2 3 4 + + + + + + + + +__extension__ typedef long long int greg_t; + + + + + +typedef greg_t gregset_t[23]; +# 92 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 3 4 +struct _libc_fpxreg +{ + unsigned short int significand[4]; + unsigned short int exponent; + unsigned short int padding[3]; +}; + +struct _libc_xmmreg +{ + __uint32_t element[4]; +}; + +struct _libc_fpstate +{ + + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + struct _libc_fpxreg _st[8]; + struct _libc_xmmreg _xmm[16]; + __uint32_t padding[24]; +}; + + +typedef struct _libc_fpstate *fpregset_t; + + +typedef struct + { + gregset_t gregs; + + fpregset_t fpregs; + __extension__ unsigned long long __reserved1 [8]; +} mcontext_t; + + +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; + } ucontext_t; +# 353 "/usr/include/signal.h" 2 3 4 + + + + + +extern int sigstack (struct sigstack *__ss, struct sigstack *__oss) + __attribute__ ((__nothrow__ )) __attribute__ ((__deprecated__)); + + + +extern int sigaltstack (const struct sigaltstack *__restrict __ss, + struct sigaltstack *__restrict __oss) __attribute__ ((__nothrow__ )); +# 388 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/sigthread.h" 1 3 4 +# 30 "/usr/include/x86_64-linux-gnu/bits/sigthread.h" 3 4 +extern int pthread_sigmask (int __how, + const __sigset_t *__restrict __newmask, + __sigset_t *__restrict __oldmask)__attribute__ ((__nothrow__ )); + + +extern int pthread_kill (pthread_t __threadid, int __signo) __attribute__ ((__nothrow__ )); +# 389 "/usr/include/signal.h" 2 3 4 + + + + + + +extern int __libc_current_sigrtmin (void) __attribute__ ((__nothrow__ )); + +extern int __libc_current_sigrtmax (void) __attribute__ ((__nothrow__ )); +# 30 "/usr/include/x86_64-linux-gnu/sys/wait.h" 2 3 4 +# 102 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +extern __pid_t wait (__WAIT_STATUS __stat_loc); +# 125 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +extern __pid_t waitpid (__pid_t __pid, int *__stat_loc, int __options); +# 135 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 2 3 4 +# 136 "/usr/include/x86_64-linux-gnu/sys/wait.h" 2 3 4 +# 148 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +extern int waitid (idtype_t __idtype, __id_t __id, siginfo_t *__infop, + int __options); + + + + + +struct rusage; + + + + + + +extern __pid_t wait3 (__WAIT_STATUS __stat_loc, int __options, + struct rusage * __usage) __attribute__ ((__nothrow__)); + + + + +extern __pid_t wait4 (__pid_t __pid, __WAIT_STATUS __stat_loc, int __options, + struct rusage *__usage) __attribute__ ((__nothrow__)); +# 183 "../include/apr.h" 2 +# 193 "../include/apr.h" +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/limits.h" 1 3 +# 37 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/limits.h" 3 +# 1 "/usr/include/limits.h" 1 3 4 +# 143 "/usr/include/limits.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 1 3 4 +# 160 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 1 3 4 +# 38 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 3 4 +# 1 "/usr/include/linux/limits.h" 1 3 4 +# 39 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 2 3 4 +# 161 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 2 3 4 +# 144 "/usr/include/limits.h" 2 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/posix2_lim.h" 1 3 4 +# 148 "/usr/include/limits.h" 2 3 4 +# 38 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/limits.h" 2 3 +# 194 "../include/apr.h" 2 +# 309 "../include/apr.h" +typedef unsigned char apr_byte_t; + +typedef short apr_int16_t; +typedef unsigned short apr_uint16_t; + +typedef int apr_int32_t; +typedef unsigned int apr_uint32_t; +# 352 "../include/apr.h" + typedef long apr_int64_t; + typedef unsigned long apr_uint64_t; + + +typedef size_t apr_size_t; +typedef ssize_t apr_ssize_t; +typedef off_t apr_off_t; +typedef socklen_t apr_socklen_t; +typedef ino_t apr_ino_t; + + +typedef apr_uint64_t apr_uintptr_t; +# 44 "../include/apr_pools.h" 2 +# 1 "../include/apr_errno.h" 1 +# 28 "../include/apr_errno.h" +# 1 "/usr/include/errno.h" 1 3 4 +# 35 "/usr/include/errno.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/errno.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/errno.h" 3 4 +# 1 "/usr/include/linux/errno.h" 1 3 4 +# 1 "/usr/include/x86_64-linux-gnu/asm/errno.h" 1 3 4 +# 1 "/usr/include/asm-generic/errno.h" 1 3 4 + + + +# 1 "/usr/include/asm-generic/errno-base.h" 1 3 4 +# 5 "/usr/include/asm-generic/errno.h" 2 3 4 +# 2 "/usr/include/x86_64-linux-gnu/asm/errno.h" 2 3 4 +# 2 "/usr/include/linux/errno.h" 2 3 4 +# 25 "/usr/include/x86_64-linux-gnu/bits/errno.h" 2 3 4 +# 50 "/usr/include/x86_64-linux-gnu/bits/errno.h" 3 4 +extern int *__errno_location (void) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 36 "/usr/include/errno.h" 2 3 4 +# 29 "../include/apr_errno.h" 2 +# 44 "../include/apr_errno.h" +typedef int apr_status_t; + + + + + + + +char * apr_strerror(apr_status_t statcode, char *buf, + apr_size_t bufsize); +# 45 "../include/apr_pools.h" 2 +# 1 "../include/apr_general.h" 1 +# 29 "../include/apr_general.h" +# 1 "../include/apr_pools.h" 1 +# 30 "../include/apr_general.h" 2 +# 68 "../include/apr_general.h" +typedef int apr_signum_t; +# 177 "../include/apr_general.h" +apr_status_t apr_initialize(void); +# 191 "../include/apr_general.h" +apr_status_t apr_app_initialize(int *argc, + char const * const * *argv, + char const * const * *env); +# 205 "../include/apr_general.h" +void apr_terminate(void); +# 216 "../include/apr_general.h" +void apr_terminate2(void); +# 233 "../include/apr_general.h" +apr_status_t apr_generate_random_bytes(unsigned char * buf, + apr_size_t length); +# 46 "../include/apr_pools.h" 2 + +# 1 "../include/apr_want.h" 1 +# 48 "../include/apr_pools.h" 2 +# 60 "../include/apr_pools.h" +typedef struct apr_pool_t apr_pool_t; +# 148 "../include/apr_pools.h" +typedef int (*apr_abortfunc_t)(int retcode); +# 164 "../include/apr_pools.h" +apr_status_t apr_pool_initialize(void); + + + + + + + +void apr_pool_terminate(void); + + + + + + + +# 1 "../include/apr_allocator.h" 1 +# 28 "../include/apr_allocator.h" +# 1 "../include/apr_want.h" 1 +# 29 "../include/apr_allocator.h" 2 +# 41 "../include/apr_allocator.h" +typedef struct apr_allocator_t apr_allocator_t; + +typedef struct apr_memnode_t apr_memnode_t; +# 54 "../include/apr_allocator.h" +struct apr_memnode_t { + apr_memnode_t *next; + apr_memnode_t **ref; + apr_uint32_t index; + apr_uint32_t free_index; + char *first_avail; + char *endp; +}; +# 74 "../include/apr_allocator.h" +apr_status_t apr_allocator_create(apr_allocator_t **allocator) + __attribute__((nonnull(1))); + + + + + + + +void apr_allocator_destroy(apr_allocator_t *allocator) + __attribute__((nonnull(1))); + + + + + + + +apr_memnode_t * apr_allocator_alloc(apr_allocator_t *allocator, + apr_size_t size) + __attribute__((nonnull(1))); +# 103 "../include/apr_allocator.h" +void apr_allocator_free(apr_allocator_t *allocator, + apr_memnode_t *memnode) + __attribute__((nonnull(1,2))); + + +# 1 "../include/apr_pools.h" 1 +# 108 "../include/apr_allocator.h" 2 +# 120 "../include/apr_allocator.h" +void apr_allocator_owner_set(apr_allocator_t *allocator, + apr_pool_t *pool) + __attribute__((nonnull(1))); + + + + + +apr_pool_t * apr_allocator_owner_get(apr_allocator_t *allocator) + __attribute__((nonnull(1))); + + + + + + + +void apr_allocator_max_free_set(apr_allocator_t *allocator, + apr_size_t size) + __attribute__((nonnull(1))); + + +# 1 "../include/apr_thread_mutex.h" 1 +# 41 "../include/apr_thread_mutex.h" +typedef struct apr_thread_mutex_t apr_thread_mutex_t; + + + + + + + +# 1 "../include/apr_pools.h" 1 +# 49 "../include/apr_thread_mutex.h" 2 +# 65 "../include/apr_thread_mutex.h" +apr_status_t apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool); + + + + + +apr_status_t apr_thread_mutex_lock(apr_thread_mutex_t *mutex); +# 82 "../include/apr_thread_mutex.h" +apr_status_t apr_thread_mutex_trylock(apr_thread_mutex_t *mutex); + + + + + +apr_status_t apr_thread_mutex_unlock(apr_thread_mutex_t *mutex); + + + + + +apr_status_t apr_thread_mutex_destroy(apr_thread_mutex_t *mutex); + + + + + +apr_pool_t * apr_thread_mutex_pool_get (const apr_thread_mutex_t *thethread_mutex); +# 142 "../include/apr_allocator.h" 2 + + + + + + + +void apr_allocator_mutex_set(apr_allocator_t *allocator, + apr_thread_mutex_t *mutex) + __attribute__((nonnull(1))); + + + + + +apr_thread_mutex_t * apr_allocator_mutex_get( + apr_allocator_t *allocator) + __attribute__((nonnull(1))); +# 180 "../include/apr_pools.h" 2 +# 196 "../include/apr_pools.h" +apr_status_t apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) + __attribute__((nonnull(1))); + + + + + +apr_status_t apr_pool_create_core_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator); +# 226 "../include/apr_pools.h" +apr_status_t apr_pool_create_unmanaged_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) + __attribute__((nonnull(1))); +# 247 "../include/apr_pools.h" +apr_status_t apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) + __attribute__((nonnull(1))); +# 264 "../include/apr_pools.h" +apr_status_t apr_pool_create_core_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line); +# 284 "../include/apr_pools.h" +apr_status_t apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) + __attribute__((nonnull(1))); +# 354 "../include/apr_pools.h" +apr_allocator_t * apr_pool_allocator_get(apr_pool_t *pool) + __attribute__((nonnull(1))); +# 365 "../include/apr_pools.h" +void apr_pool_clear(apr_pool_t *p) __attribute__((nonnull(1))); +# 380 "../include/apr_pools.h" +void apr_pool_clear_debug(apr_pool_t *p, + const char *file_line) + __attribute__((nonnull(1))); +# 395 "../include/apr_pools.h" +void apr_pool_destroy(apr_pool_t *p) __attribute__((nonnull(1))); +# 410 "../include/apr_pools.h" +void apr_pool_destroy_debug(apr_pool_t *p, + const char *file_line) + __attribute__((nonnull(1))); +# 430 "../include/apr_pools.h" +void * apr_palloc(apr_pool_t *p, apr_size_t size) + + + + __attribute__((nonnull(1))); +# 444 "../include/apr_pools.h" +void * apr_palloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line) + + + + __attribute__((nonnull(1))); +# 476 "../include/apr_pools.h" +void * apr_pcalloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line) + __attribute__((nonnull(1))); +# 498 "../include/apr_pools.h" +void apr_pool_abort_set(apr_abortfunc_t abortfunc, + apr_pool_t *pool) + __attribute__((nonnull(2))); + + + + + + +apr_abortfunc_t apr_pool_abort_get(apr_pool_t *pool) + __attribute__((nonnull(1))); + + + + + + +apr_pool_t * apr_pool_parent_get(apr_pool_t *pool) + __attribute__((nonnull(1))); +# 529 "../include/apr_pools.h" +int apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b); + + + + + + +void apr_pool_tag(apr_pool_t *pool, const char *tag) + __attribute__((nonnull(1))); +# 563 "../include/apr_pools.h" +apr_status_t apr_pool_userdata_set(const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) + __attribute__((nonnull(2,4))); +# 588 "../include/apr_pools.h" +apr_status_t apr_pool_userdata_setn( + const void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) + __attribute__((nonnull(2,4))); + + + + + + + +apr_status_t apr_pool_userdata_get(void **data, const char *key, + apr_pool_t *pool) + __attribute__((nonnull(1,2,3))); +# 628 "../include/apr_pools.h" +void apr_pool_cleanup_register( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)) + __attribute__((nonnull(3,4))); +# 646 "../include/apr_pools.h" +void apr_pool_pre_cleanup_register( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *)) + __attribute__((nonnull(3))); +# 663 "../include/apr_pools.h" +void apr_pool_cleanup_kill(apr_pool_t *p, const void *data, + apr_status_t (*cleanup)(void *)) + __attribute__((nonnull(3))); +# 679 "../include/apr_pools.h" +void apr_pool_child_cleanup_set( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)) + __attribute__((nonnull(3,4))); +# 696 "../include/apr_pools.h" +apr_status_t apr_pool_cleanup_run(apr_pool_t *p, void *data, + apr_status_t (*cleanup)(void *)) + __attribute__((nonnull(3))); +# 707 "../include/apr_pools.h" +apr_status_t apr_pool_cleanup_null(void *data); + + + + + + + +void apr_pool_cleanup_for_exec(void); +# 18 "./../test/testutil.h" 2 + +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 52 "./../test/testutil.h" +extern apr_pool_t *p; + + + +void apr_assert_success(abts_case* tc, const char *context, + apr_status_t rv, int lineno); + + + +void initialize(void); + +abts_suite *testatomic(abts_suite *suite); +abts_suite *testdir(abts_suite *suite); +abts_suite *testdso(abts_suite *suite); +abts_suite *testdup(abts_suite *suite); +abts_suite *testescape(abts_suite *suite); +abts_suite *testenv(abts_suite *suite); +abts_suite *testfile(abts_suite *suite); +abts_suite *testfilecopy(abts_suite *suite); +abts_suite *testfileinfo(abts_suite *suite); +abts_suite *testflock(abts_suite *suite); +abts_suite *testfmt(abts_suite *suite); +abts_suite *testfnmatch(abts_suite *suite); +abts_suite *testgetopt(abts_suite *suite); +abts_suite *testglobalmutex(abts_suite *suite); +abts_suite *testhash(abts_suite *suite); +abts_suite *testipsub(abts_suite *suite); +abts_suite *testlock(abts_suite *suite); +abts_suite *testcond(abts_suite *suite); +abts_suite *testlfs(abts_suite *suite); +abts_suite *testmmap(abts_suite *suite); +abts_suite *testnames(abts_suite *suite); +abts_suite *testoc(abts_suite *suite); +abts_suite *testpath(abts_suite *suite); +abts_suite *testpipe(abts_suite *suite); +abts_suite *testpoll(abts_suite *suite); +abts_suite *testpool(abts_suite *suite); +abts_suite *testproc(abts_suite *suite); +abts_suite *testprocmutex(abts_suite *suite); +abts_suite *testrand(abts_suite *suite); +abts_suite *testsleep(abts_suite *suite); +abts_suite *testshm(abts_suite *suite); +abts_suite *testsock(abts_suite *suite); +abts_suite *testsockets(abts_suite *suite); +abts_suite *testsockopt(abts_suite *suite); +abts_suite *teststr(abts_suite *suite); +abts_suite *teststrnatcmp(abts_suite *suite); +abts_suite *testtable(abts_suite *suite); +abts_suite *testtemp(abts_suite *suite); +abts_suite *testthread(abts_suite *suite); +abts_suite *testtime(abts_suite *suite); +abts_suite *testud(abts_suite *suite); +abts_suite *testuser(abts_suite *suite); +abts_suite *testvsn(abts_suite *suite); +# 9 "main1.c" 2 + +# 1 "./../test/testatomic.c" 1 +# 17 "./../test/testatomic.c" +# 1 "./../test/testutil.h" 1 +# 19 "./../test/testutil.h" +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 18 "./../test/testatomic.c" 2 +# 1 "../include/apr_strings.h" 1 +# 52 "../include/apr_strings.h" +# 1 "../include/apr_want.h" 1 +# 53 "../include/apr_strings.h" 2 +# 76 "../include/apr_strings.h" +int apr_strnatcmp(char const *a, char const *b); +# 87 "../include/apr_strings.h" +int apr_strnatcasecmp(char const *a, char const *b); + + + + + + + +char * apr_pstrdup(apr_pool_t *p, const char *s); +# 109 "../include/apr_strings.h" +char * apr_pstrmemdup(apr_pool_t *p, const char *s, apr_size_t n) + + + + ; +# 125 "../include/apr_strings.h" +char * apr_pstrndup(apr_pool_t *p, const char *s, apr_size_t n); +# 135 "../include/apr_strings.h" +void * apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n) + + + + ; + + + + + + + +char * apr_pstrcat(apr_pool_t *p, ...) + + __attribute__((sentinel)) + + ; +# 161 "../include/apr_strings.h" +char * apr_pstrcatv(apr_pool_t *p, const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes); +# 172 "../include/apr_strings.h" +char * apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap); +# 182 "../include/apr_strings.h" +char * apr_psprintf(apr_pool_t *p, const char *fmt, ...) + __attribute__((format(printf,2,3))); +# 207 "../include/apr_strings.h" +char * apr_cpystrn(char *dst, const char *src, + apr_size_t dst_size); +# 217 "../include/apr_strings.h" +char * apr_collapse_spaces(char *dest, const char *src); +# 226 "../include/apr_strings.h" +apr_status_t apr_tokenize_to_argv(const char *arg_str, + char ***argv_out, + apr_pool_t *token_context); +# 247 "../include/apr_strings.h" +char * apr_strtok(char *str, const char *sep, char **last); +# 279 "../include/apr_strings.h" +int apr_snprintf(char *buf, apr_size_t len, + const char *format, ...) + __attribute__((format(printf,3,4))); +# 291 "../include/apr_strings.h" +int apr_vsnprintf(char *buf, apr_size_t len, const char *format, + va_list ap); +# 301 "../include/apr_strings.h" +char * apr_itoa(apr_pool_t *p, int n); + + + + + + + +char * apr_ltoa(apr_pool_t *p, long n); + + + + + + + +char * apr_off_t_toa(apr_pool_t *p, apr_off_t n); +# 335 "../include/apr_strings.h" +apr_status_t apr_strtoff(apr_off_t *offset, const char *buf, + char **end, int base); +# 353 "../include/apr_strings.h" +apr_int64_t apr_strtoi64(const char *buf, char **end, int base); +# 362 "../include/apr_strings.h" +apr_int64_t apr_atoi64(const char *buf); +# 372 "../include/apr_strings.h" +char * apr_strfsize(apr_off_t size, char *buf); +# 19 "./../test/testatomic.c" 2 +# 1 "../include/apr_thread_proc.h" 1 +# 26 "../include/apr_thread_proc.h" +# 1 "../include/apr_file_io.h" 1 +# 27 "../include/apr_file_io.h" +# 1 "../include/apr_time.h" 1 +# 40 "../include/apr_time.h" + extern const char apr_month_snames[12][4]; + + extern const char apr_day_snames[7][4]; + + + +typedef apr_int64_t apr_time_t; +# 56 "../include/apr_time.h" +typedef apr_int64_t apr_interval_time_t; + +typedef apr_int32_t apr_short_interval_time_t; +# 88 "../include/apr_time.h" +apr_time_t apr_time_now(void); + + +typedef struct apr_time_exp_t apr_time_exp_t; + + + + + + +struct apr_time_exp_t { + + apr_int32_t tm_usec; + + apr_int32_t tm_sec; + + apr_int32_t tm_min; + + apr_int32_t tm_hour; + + apr_int32_t tm_mday; + + apr_int32_t tm_mon; + + apr_int32_t tm_year; + + apr_int32_t tm_wday; + + apr_int32_t tm_yday; + + apr_int32_t tm_isdst; + + apr_int32_t tm_gmtoff; +}; + + + + + + +apr_status_t apr_time_ansi_put(apr_time_t *result, + time_t input); +# 138 "../include/apr_time.h" +apr_status_t apr_time_exp_tz(apr_time_exp_t *result, + apr_time_t input, + apr_int32_t offs); + + + + + + +apr_status_t apr_time_exp_gmt(apr_time_exp_t *result, + apr_time_t input); + + + + + + +apr_status_t apr_time_exp_lt(apr_time_exp_t *result, + apr_time_t input); + + + + + + + +apr_status_t apr_time_exp_get(apr_time_t *result, + apr_time_exp_t *input); + + + + + + + +apr_status_t apr_time_exp_gmt_get(apr_time_t *result, + apr_time_exp_t *input); + + + + + + +void apr_sleep(apr_interval_time_t t); +# 193 "../include/apr_time.h" +apr_status_t apr_rfc822_date(char *date_str, apr_time_t t); +# 207 "../include/apr_time.h" +apr_status_t apr_ctime(char *date_str, apr_time_t t); +# 217 "../include/apr_time.h" +apr_status_t apr_strftime(char *s, apr_size_t *retsize, + apr_size_t max, const char *format, + apr_time_exp_t *tm); + + + + + + + +void apr_time_clock_hires(apr_pool_t *p); +# 28 "../include/apr_file_io.h" 2 + +# 1 "../include/apr_file_info.h" 1 +# 26 "../include/apr_file_info.h" +# 1 "../include/apr_user.h" 1 +# 45 "../include/apr_user.h" +typedef uid_t apr_uid_t; +# 54 "../include/apr_user.h" +typedef gid_t apr_gid_t; +# 66 "../include/apr_user.h" +apr_status_t apr_uid_current(apr_uid_t *userid, + apr_gid_t *groupid, + apr_pool_t *p); +# 77 "../include/apr_user.h" +apr_status_t apr_uid_name_get(char **username, apr_uid_t userid, + apr_pool_t *p); +# 88 "../include/apr_user.h" +apr_status_t apr_uid_get(apr_uid_t *userid, apr_gid_t *groupid, + const char *username, apr_pool_t *p); +# 98 "../include/apr_user.h" +apr_status_t apr_uid_homepath_get(char **dirname, + const char *username, + apr_pool_t *p); +# 123 "../include/apr_user.h" +apr_status_t apr_gid_name_get(char **groupname, + apr_gid_t groupid, apr_pool_t *p); +# 133 "../include/apr_user.h" +apr_status_t apr_gid_get(apr_gid_t *groupid, + const char *groupname, apr_pool_t *p); +# 27 "../include/apr_file_info.h" 2 + +# 1 "../include/apr_tables.h" 1 +# 56 "../include/apr_tables.h" +typedef struct apr_table_t apr_table_t; + + +typedef struct apr_array_header_t apr_array_header_t; + + +struct apr_array_header_t { + + apr_pool_t *pool; + + int elt_size; + + int nelts; + + int nalloc; + + char *elts; +}; + + + + +typedef struct apr_table_entry_t apr_table_entry_t; + + +struct apr_table_entry_t { + + char *key; + + + + char *val; + + + apr_uint32_t key_checksum; +}; + + + + + + +const apr_array_header_t * apr_table_elts(const apr_table_t *t); + + + + + + +int apr_is_empty_table(const apr_table_t *t); + + + + + + +int apr_is_empty_array(const apr_array_header_t *a); +# 121 "../include/apr_tables.h" +apr_array_header_t * apr_array_make(apr_pool_t *p, + int nelts, int elt_size); +# 131 "../include/apr_tables.h" +void * apr_array_push(apr_array_header_t *arr); +# 158 "../include/apr_tables.h" +void * apr_array_pop(apr_array_header_t *arr); + + + + + + + +void apr_array_clear(apr_array_header_t *arr); + + + + + + + +void apr_array_cat(apr_array_header_t *dst, + const apr_array_header_t *src); +# 186 "../include/apr_tables.h" +apr_array_header_t * apr_array_copy(apr_pool_t *p, + const apr_array_header_t *arr); +# 196 "../include/apr_tables.h" +apr_array_header_t * apr_array_copy_hdr(apr_pool_t *p, + const apr_array_header_t *arr); +# 206 "../include/apr_tables.h" +apr_array_header_t * apr_array_append(apr_pool_t *p, + const apr_array_header_t *first, + const apr_array_header_t *second); +# 221 "../include/apr_tables.h" +char * apr_array_pstrcat(apr_pool_t *p, + const apr_array_header_t *arr, + const char sep); +# 232 "../include/apr_tables.h" +apr_table_t * apr_table_make(apr_pool_t *p, int nelts); +# 241 "../include/apr_tables.h" +apr_table_t * apr_table_copy(apr_pool_t *p, + const apr_table_t *t); +# 252 "../include/apr_tables.h" +apr_table_t * apr_table_clone(apr_pool_t *p, + const apr_table_t *t); + + + + + +void apr_table_clear(apr_table_t *t); +# 268 "../include/apr_tables.h" +const char * apr_table_get(const apr_table_t *t, const char *key); +# 279 "../include/apr_tables.h" +const char * apr_table_getm(apr_pool_t *p, const apr_table_t *t, + const char *key); +# 291 "../include/apr_tables.h" +void apr_table_set(apr_table_t *t, const char *key, + const char *val); +# 304 "../include/apr_tables.h" +void apr_table_setn(apr_table_t *t, const char *key, + const char *val); + + + + + + +void apr_table_unset(apr_table_t *t, const char *key); +# 323 "../include/apr_tables.h" +void apr_table_merge(apr_table_t *t, const char *key, + const char *val); +# 335 "../include/apr_tables.h" +void apr_table_mergen(apr_table_t *t, const char *key, + const char *val); +# 347 "../include/apr_tables.h" +void apr_table_add(apr_table_t *t, const char *key, + const char *val); +# 360 "../include/apr_tables.h" +void apr_table_addn(apr_table_t *t, const char *key, + const char *val); +# 370 "../include/apr_tables.h" +apr_table_t * apr_table_overlay(apr_pool_t *p, + const apr_table_t *overlay, + const apr_table_t *base); +# 384 "../include/apr_tables.h" +typedef int (apr_table_do_callback_fn_t)(void *rec, const char *key, + const char *value); +# 406 "../include/apr_tables.h" +int apr_table_do(apr_table_do_callback_fn_t *comp, + void *rec, const apr_table_t *t, ...) + + __attribute__((sentinel)) + + ; +# 432 "../include/apr_tables.h" +int apr_table_vdo(apr_table_do_callback_fn_t *comp, + void *rec, const apr_table_t *t, va_list vp); +# 478 "../include/apr_tables.h" +void apr_table_overlap(apr_table_t *a, const apr_table_t *b, + unsigned flags); +# 491 "../include/apr_tables.h" +void apr_table_compress(apr_table_t *t, unsigned flags); +# 29 "../include/apr_file_info.h" 2 +# 62 "../include/apr_file_info.h" +typedef enum { + APR_NOFILE = 0, + APR_REG, + APR_DIR, + APR_CHR, + APR_BLK, + APR_PIPE, + APR_LNK, + APR_SOCK, + APR_UNKFILE = 127 +} apr_filetype_e; +# 121 "../include/apr_file_info.h" +typedef struct apr_dir_t apr_dir_t; + + + +typedef apr_int32_t apr_fileperms_t; +# 135 "../include/apr_file_info.h" +typedef dev_t apr_dev_t; + + + + + + + +typedef struct apr_finfo_t apr_finfo_t; +# 174 "../include/apr_file_info.h" +struct apr_finfo_t { + + apr_pool_t *pool; + + + apr_int32_t valid; + + apr_fileperms_t protection; + + + + + apr_filetype_e filetype; + + apr_uid_t user; + + apr_gid_t group; + + apr_ino_t inode; + + apr_dev_t device; + + apr_int32_t nlink; + + apr_off_t size; + + apr_off_t csize; + + apr_time_t atime; + + apr_time_t mtime; + + apr_time_t ctime; + + const char *fname; + + const char *name; + + struct apr_file_t *filehand; +}; +# 229 "../include/apr_file_info.h" +apr_status_t apr_stat(apr_finfo_t *finfo, const char *fname, + apr_int32_t wanted, apr_pool_t *pool); +# 244 "../include/apr_file_info.h" +apr_status_t apr_dir_open(apr_dir_t **new_dir, + const char *dirname, + apr_pool_t *pool); + + + + + +apr_status_t apr_dir_close(apr_dir_t *thedir); +# 267 "../include/apr_file_info.h" +apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, + apr_dir_t *thedir); + + + + + +apr_status_t apr_dir_rewind(apr_dir_t *thedir); +# 336 "../include/apr_file_info.h" +apr_status_t apr_filepath_root(const char **rootpath, + const char **filepath, + apr_int32_t flags, + apr_pool_t *p); +# 354 "../include/apr_file_info.h" +apr_status_t apr_filepath_merge(char **newpath, + const char *rootpath, + const char *addpath, + apr_int32_t flags, + apr_pool_t *p); +# 369 "../include/apr_file_info.h" +apr_status_t apr_filepath_list_split(apr_array_header_t **pathelts, + const char *liststr, + apr_pool_t *p); +# 382 "../include/apr_file_info.h" +apr_status_t apr_filepath_list_merge(char **liststr, + apr_array_header_t *pathelts, + apr_pool_t *p); +# 393 "../include/apr_file_info.h" +apr_status_t apr_filepath_get(char **path, apr_int32_t flags, + apr_pool_t *p); + + + + + + +apr_status_t apr_filepath_set(const char *path, apr_pool_t *p); +# 419 "../include/apr_file_info.h" +apr_status_t apr_filepath_encoding(int *style, apr_pool_t *p); +# 30 "../include/apr_file_io.h" 2 +# 1 "../include/apr_inherit.h" 1 +# 31 "../include/apr_file_io.h" 2 + + + +# 1 "../include/apr_want.h" 1 +# 35 "../include/apr_file_io.h" 2 +# 180 "../include/apr_file_io.h" +typedef apr_uint32_t apr_fileattrs_t; + + +typedef int apr_seek_where_t; + + + + +typedef struct apr_file_t apr_file_t; +# 250 "../include/apr_file_io.h" +apr_status_t apr_file_open(apr_file_t **newf, const char *fname, + apr_int32_t flag, apr_fileperms_t perm, + apr_pool_t *pool); + + + + + +apr_status_t apr_file_close(apr_file_t *file); +# 267 "../include/apr_file_io.h" +apr_status_t apr_file_remove(const char *path, apr_pool_t *pool); +# 278 "../include/apr_file_io.h" +apr_status_t apr_file_rename(const char *from_path, + const char *to_path, + apr_pool_t *pool); + + + + + + + +apr_status_t apr_file_link(const char *from_path, + const char *to_path); +# 303 "../include/apr_file_io.h" +apr_status_t apr_file_copy(const char *from_path, + const char *to_path, + apr_fileperms_t perms, + apr_pool_t *pool); +# 319 "../include/apr_file_io.h" +apr_status_t apr_file_append(const char *from_path, + const char *to_path, + apr_fileperms_t perms, + apr_pool_t *pool); + + + + + + +apr_status_t apr_file_eof(apr_file_t *fptr); +# 346 "../include/apr_file_io.h" +apr_status_t apr_file_open_stderr(apr_file_t **thefile, + apr_pool_t *pool); +# 356 "../include/apr_file_io.h" +apr_status_t apr_file_open_stdout(apr_file_t **thefile, + apr_pool_t *pool); +# 366 "../include/apr_file_io.h" +apr_status_t apr_file_open_stdin(apr_file_t **thefile, + apr_pool_t *pool); +# 386 "../include/apr_file_io.h" +apr_status_t apr_file_open_flags_stderr(apr_file_t **thefile, + apr_int32_t flags, + apr_pool_t *pool); +# 407 "../include/apr_file_io.h" +apr_status_t apr_file_open_flags_stdout(apr_file_t **thefile, + apr_int32_t flags, + apr_pool_t *pool); +# 428 "../include/apr_file_io.h" +apr_status_t apr_file_open_flags_stdin(apr_file_t **thefile, + apr_int32_t flags, + apr_pool_t *pool); +# 449 "../include/apr_file_io.h" +apr_status_t apr_file_read(apr_file_t *thefile, void *buf, + apr_size_t *nbytes); +# 467 "../include/apr_file_io.h" +apr_status_t apr_file_write(apr_file_t *thefile, const void *buf, + apr_size_t *nbytes); +# 485 "../include/apr_file_io.h" +apr_status_t apr_file_writev(apr_file_t *thefile, + const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes); +# 509 "../include/apr_file_io.h" +apr_status_t apr_file_read_full(apr_file_t *thefile, void *buf, + apr_size_t nbytes, + apr_size_t *bytes_read); +# 533 "../include/apr_file_io.h" +apr_status_t apr_file_write_full(apr_file_t *thefile, + const void *buf, + apr_size_t nbytes, + apr_size_t *bytes_written); +# 552 "../include/apr_file_io.h" +apr_status_t apr_file_writev_full(apr_file_t *thefile, + const struct iovec *vec, + apr_size_t nvec, + apr_size_t *nbytes); + + + + + +apr_status_t apr_file_putc(char ch, apr_file_t *thefile); + + + + + + +apr_status_t apr_file_getc(char *ch, apr_file_t *thefile); + + + + + + +apr_status_t apr_file_ungetc(char ch, apr_file_t *thefile); +# 585 "../include/apr_file_io.h" +apr_status_t apr_file_gets(char *str, int len, + apr_file_t *thefile); + + + + + + +apr_status_t apr_file_puts(const char *str, apr_file_t *thefile); + + + + + +apr_status_t apr_file_flush(apr_file_t *thefile); + + + + + +apr_status_t apr_file_sync(apr_file_t *thefile); + + + + + +apr_status_t apr_file_datasync(apr_file_t *thefile); +# 620 "../include/apr_file_io.h" +apr_status_t apr_file_dup(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p); +# 632 "../include/apr_file_io.h" +apr_status_t apr_file_dup2(apr_file_t *new_file, + apr_file_t *old_file, + apr_pool_t *p); +# 647 "../include/apr_file_io.h" +apr_status_t apr_file_setaside(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p); +# 662 "../include/apr_file_io.h" +apr_status_t apr_file_buffer_set(apr_file_t *thefile, + char * buffer, + apr_size_t bufsize); + + + + + +apr_size_t apr_file_buffer_size_get(apr_file_t *thefile); +# 683 "../include/apr_file_io.h" +apr_status_t apr_file_seek(apr_file_t *thefile, + apr_seek_where_t where, + apr_off_t *offset); +# 700 "../include/apr_file_io.h" +apr_status_t apr_file_pipe_create(apr_file_t **in, + apr_file_t **out, + apr_pool_t *pool); +# 723 "../include/apr_file_io.h" +apr_status_t apr_file_pipe_create_ex(apr_file_t **in, + apr_file_t **out, + apr_int32_t blocking, + apr_pool_t *pool); + + + + + + + +apr_status_t apr_file_namedpipe_create(const char *filename, + apr_fileperms_t perm, + apr_pool_t *pool); + + + + + + +apr_status_t apr_file_pipe_timeout_get(apr_file_t *thepipe, + apr_interval_time_t *timeout); + + + + + + + +apr_status_t apr_file_pipe_timeout_set(apr_file_t *thepipe, + apr_interval_time_t timeout); +# 766 "../include/apr_file_io.h" +apr_status_t apr_file_lock(apr_file_t *thefile, int type); + + + + + +apr_status_t apr_file_unlock(apr_file_t *thefile); +# 781 "../include/apr_file_io.h" +apr_status_t apr_file_name_get(const char **new_path, + apr_file_t *thefile); + + + + + + + +apr_status_t apr_file_data_get(void **data, const char *key, + apr_file_t *file); +# 800 "../include/apr_file_io.h" +apr_status_t apr_file_data_set(apr_file_t *file, void *data, + const char *key, + apr_status_t (*cleanup)(void *)); +# 811 "../include/apr_file_io.h" +int apr_file_printf(apr_file_t *fptr, + const char *format, ...) + __attribute__((format(printf,2,3))); +# 827 "../include/apr_file_io.h" +apr_status_t apr_file_perms_set(const char *fname, + apr_fileperms_t perms); +# 846 "../include/apr_file_io.h" +apr_status_t apr_file_attrs_set(const char *fname, + apr_fileattrs_t attributes, + apr_fileattrs_t attr_mask, + apr_pool_t *pool); +# 859 "../include/apr_file_io.h" +apr_status_t apr_file_mtime_set(const char *fname, + apr_time_t mtime, + apr_pool_t *pool); + + + + + + + +apr_status_t apr_dir_make(const char *path, apr_fileperms_t perm, + apr_pool_t *pool); +# 879 "../include/apr_file_io.h" +apr_status_t apr_dir_make_recursive(const char *path, + apr_fileperms_t perm, + apr_pool_t *pool); +# 890 "../include/apr_file_io.h" +apr_status_t apr_dir_remove(const char *path, apr_pool_t *pool); + + + + + + + +apr_status_t apr_file_info_get(apr_finfo_t *finfo, + apr_int32_t wanted, + apr_file_t *thefile); +# 909 "../include/apr_file_io.h" +apr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset); + + + + + + +apr_int32_t apr_file_flags_get(apr_file_t *f); + + + + +apr_pool_t * apr_file_pool_get (const apr_file_t *thefile); + + + + + +apr_status_t apr_file_inherit_set( apr_file_t *thefile); + + + + +apr_status_t apr_file_inherit_unset( apr_file_t *thefile); +# 951 "../include/apr_file_io.h" +apr_status_t apr_file_mktemp(apr_file_t **fp, char *templ, + apr_int32_t flags, apr_pool_t *p); +# 964 "../include/apr_file_io.h" +apr_status_t apr_temp_dir_get(const char **temp_dir, + apr_pool_t *p); +# 27 "../include/apr_thread_proc.h" 2 + + + + +# 1 "/usr/include/x86_64-linux-gnu/sys/time.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/sys/time.h" 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/sys/time.h" 2 3 4 + +# 1 "/usr/include/x86_64-linux-gnu/bits/time.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/sys/time.h" 2 3 4 +# 55 "/usr/include/x86_64-linux-gnu/sys/time.h" 3 4 +struct timezone + { + int tz_minuteswest; + int tz_dsttime; + }; + +typedef struct timezone *__restrict __timezone_ptr_t; +# 71 "/usr/include/x86_64-linux-gnu/sys/time.h" 3 4 +extern int gettimeofday (struct timeval *__restrict __tv, + __timezone_ptr_t __tz) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + +extern int settimeofday (const struct timeval *__tv, + const struct timezone *__tz) + __attribute__ ((__nothrow__ )); + + + + + +extern int adjtime (const struct timeval *__delta, + struct timeval *__olddelta) __attribute__ ((__nothrow__ )); + + + + +enum __itimer_which + { + + ITIMER_REAL = 0, + + + ITIMER_VIRTUAL = 1, + + + + ITIMER_PROF = 2 + + }; + + + +struct itimerval + { + + struct timeval it_interval; + + struct timeval it_value; + }; + + + + + + +typedef int __itimer_which_t; + + + + +extern int getitimer (__itimer_which_t __which, + struct itimerval *__value) __attribute__ ((__nothrow__ )); + + + + +extern int setitimer (__itimer_which_t __which, + const struct itimerval *__restrict __new, + struct itimerval *__restrict __old) __attribute__ ((__nothrow__ )); + + + + +extern int utimes (const char *__file, const struct timeval __tvp[2]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int lutimes (const char *__file, const struct timeval __tvp[2]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int futimes (int __fd, const struct timeval __tvp[2]) __attribute__ ((__nothrow__ )); +# 32 "../include/apr_thread_proc.h" 2 +# 1 "/usr/include/x86_64-linux-gnu/sys/resource.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/sys/resource.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/resource.h" 1 3 4 +# 31 "/usr/include/x86_64-linux-gnu/bits/resource.h" 3 4 +enum __rlimit_resource +{ + + RLIMIT_CPU = 0, + + + + RLIMIT_FSIZE = 1, + + + + RLIMIT_DATA = 2, + + + + RLIMIT_STACK = 3, + + + + RLIMIT_CORE = 4, + + + + + + + __RLIMIT_RSS = 5, + + + + RLIMIT_NOFILE = 7, + __RLIMIT_OFILE = RLIMIT_NOFILE, + + + + + RLIMIT_AS = 9, + + + + __RLIMIT_NPROC = 6, + + + + __RLIMIT_MEMLOCK = 8, + + + + __RLIMIT_LOCKS = 10, + + + + __RLIMIT_SIGPENDING = 11, + + + + __RLIMIT_MSGQUEUE = 12, + + + + + + __RLIMIT_NICE = 13, + + + + + __RLIMIT_RTPRIO = 14, + + + + + + __RLIMIT_RTTIME = 15, + + + __RLIMIT_NLIMITS = 16, + __RLIM_NLIMITS = __RLIMIT_NLIMITS + + +}; +# 131 "/usr/include/x86_64-linux-gnu/bits/resource.h" 3 4 +typedef __rlim_t rlim_t; + + + + + + + +struct rlimit + { + + rlim_t rlim_cur; + + rlim_t rlim_max; + }; +# 158 "/usr/include/x86_64-linux-gnu/bits/resource.h" 3 4 +enum __rusage_who +{ + + RUSAGE_SELF = 0, + + + + RUSAGE_CHILDREN = -1 +# 176 "/usr/include/x86_64-linux-gnu/bits/resource.h" 3 4 +}; + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/time.h" 1 3 4 +# 180 "/usr/include/x86_64-linux-gnu/bits/resource.h" 2 3 4 + + + + + + + +struct rusage + { + + struct timeval ru_utime; + + struct timeval ru_stime; + + __extension__ union + { + long int ru_maxrss; + __syscall_slong_t __ru_maxrss_word; + }; + + + + __extension__ union + { + long int ru_ixrss; + __syscall_slong_t __ru_ixrss_word; + }; + + __extension__ union + { + long int ru_idrss; + __syscall_slong_t __ru_idrss_word; + }; + + __extension__ union + { + long int ru_isrss; + __syscall_slong_t __ru_isrss_word; + }; + + + __extension__ union + { + long int ru_minflt; + __syscall_slong_t __ru_minflt_word; + }; + + __extension__ union + { + long int ru_majflt; + __syscall_slong_t __ru_majflt_word; + }; + + __extension__ union + { + long int ru_nswap; + __syscall_slong_t __ru_nswap_word; + }; + + + __extension__ union + { + long int ru_inblock; + __syscall_slong_t __ru_inblock_word; + }; + + __extension__ union + { + long int ru_oublock; + __syscall_slong_t __ru_oublock_word; + }; + + __extension__ union + { + long int ru_msgsnd; + __syscall_slong_t __ru_msgsnd_word; + }; + + __extension__ union + { + long int ru_msgrcv; + __syscall_slong_t __ru_msgrcv_word; + }; + + __extension__ union + { + long int ru_nsignals; + __syscall_slong_t __ru_nsignals_word; + }; + + + + __extension__ union + { + long int ru_nvcsw; + __syscall_slong_t __ru_nvcsw_word; + }; + + + __extension__ union + { + long int ru_nivcsw; + __syscall_slong_t __ru_nivcsw_word; + }; + }; + + + + + + + +enum __priority_which +{ + PRIO_PROCESS = 0, + + PRIO_PGRP = 1, + + PRIO_USER = 2 + +}; +# 25 "/usr/include/x86_64-linux-gnu/sys/resource.h" 2 3 4 +# 42 "/usr/include/x86_64-linux-gnu/sys/resource.h" 3 4 +typedef int __rlimit_resource_t; +typedef int __rusage_who_t; +typedef int __priority_which_t; + + + + + +extern int getrlimit (__rlimit_resource_t __resource, + struct rlimit *__rlimits) __attribute__ ((__nothrow__ )); +# 69 "/usr/include/x86_64-linux-gnu/sys/resource.h" 3 4 +extern int setrlimit (__rlimit_resource_t __resource, + const struct rlimit *__rlimits) __attribute__ ((__nothrow__ )); +# 87 "/usr/include/x86_64-linux-gnu/sys/resource.h" 3 4 +extern int getrusage (__rusage_who_t __who, struct rusage *__usage) __attribute__ ((__nothrow__ )); + + + + + +extern int getpriority (__priority_which_t __which, id_t __who) __attribute__ ((__nothrow__ )); + + + +extern int setpriority (__priority_which_t __which, id_t __who, int __prio) + __attribute__ ((__nothrow__ )); +# 33 "../include/apr_thread_proc.h" 2 +# 45 "../include/apr_thread_proc.h" +typedef enum { + APR_SHELLCMD, + APR_PROGRAM, + APR_PROGRAM_ENV, + APR_PROGRAM_PATH, + APR_SHELLCMD_ENV + + +} apr_cmdtype_e; + +typedef enum { + APR_WAIT, + APR_NOWAIT +} apr_wait_how_e; + + + + + + +typedef enum { + APR_PROC_EXIT = 1, + APR_PROC_SIGNAL = 2, + APR_PROC_SIGNAL_CORE = 4 +} apr_exit_why_e; +# 133 "../include/apr_thread_proc.h" +typedef struct apr_proc_t { + + pid_t pid; + + apr_file_t *in; + + apr_file_t *out; + + apr_file_t *err; +# 161 "../include/apr_thread_proc.h" +} apr_proc_t; +# 173 "../include/apr_thread_proc.h" +typedef void (apr_child_errfn_t)(apr_pool_t *proc, apr_status_t err, + const char *description); + + +typedef struct apr_thread_t apr_thread_t; + + +typedef struct apr_threadattr_t apr_threadattr_t; + + +typedef struct apr_procattr_t apr_procattr_t; + + +typedef struct apr_thread_once_t apr_thread_once_t; + + +typedef struct apr_threadkey_t apr_threadkey_t; + + +typedef struct apr_other_child_rec_t apr_other_child_rec_t; + + + + +typedef void *( *apr_thread_start_t)(apr_thread_t*, void*); + +typedef enum { + APR_KILL_NEVER, + + + APR_KILL_ALWAYS, + APR_KILL_AFTER_TIMEOUT, + APR_JUST_WAIT, + APR_KILL_ONLY_ONCE +} apr_kill_conditions_e; +# 218 "../include/apr_thread_proc.h" +apr_status_t apr_threadattr_create(apr_threadattr_t **new_attr, + apr_pool_t *cont); + + + + + + +apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr, + apr_int32_t on); + + + + + + + +apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr); + + + + + + +apr_status_t apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize); +# 255 "../include/apr_thread_proc.h" +apr_status_t apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t guardsize); +# 266 "../include/apr_thread_proc.h" +apr_status_t apr_thread_create(apr_thread_t **new_thread, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, apr_pool_t *cont); + + + + + + +apr_status_t apr_thread_exit(apr_thread_t *thd, + apr_status_t retval); + + + + + + +apr_status_t apr_thread_join(apr_status_t *retval, + apr_thread_t *thd); + + + + +void apr_thread_yield(void); + + + + + + + +apr_status_t apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p); +# 310 "../include/apr_thread_proc.h" +apr_status_t apr_thread_once(apr_thread_once_t *control, + void (*func)(void)); + + + + + +apr_status_t apr_thread_detach(apr_thread_t *thd); + + + + + + + +apr_status_t apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread); +# 335 "../include/apr_thread_proc.h" +apr_status_t apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_thread_t *thread); + + + + + + + +apr_status_t apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), + apr_pool_t *cont); + + + + + + +apr_status_t apr_threadkey_private_get(void **new_mem, + apr_threadkey_t *key); + + + + + + +apr_status_t apr_threadkey_private_set(void *priv, + apr_threadkey_t *key); + + + + + +apr_status_t apr_threadkey_private_delete(apr_threadkey_t *key); + + + + + + + +apr_status_t apr_threadkey_data_get(void **data, const char *key, + apr_threadkey_t *threadkey); +# 387 "../include/apr_thread_proc.h" +apr_status_t apr_threadkey_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_threadkey_t *threadkey); +# 398 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_create(apr_procattr_t **new_attr, + apr_pool_t *cont); +# 415 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_io_set(apr_procattr_t *attr, + apr_int32_t in, apr_int32_t out, + apr_int32_t err); +# 434 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_child_in_set(struct apr_procattr_t *attr, + apr_file_t *child_in, + apr_file_t *parent_in); +# 451 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_child_out_set(struct apr_procattr_t *attr, + apr_file_t *child_out, + apr_file_t *parent_out); +# 468 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_child_err_set(struct apr_procattr_t *attr, + apr_file_t *child_err, + apr_file_t *parent_err); +# 479 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_dir_set(apr_procattr_t *attr, + const char *dir); +# 493 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd); + + + + + + +apr_status_t apr_procattr_detach_set(apr_procattr_t *attr, + apr_int32_t detach); +# 517 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_limit_set(apr_procattr_t *attr, + apr_int32_t what, + struct rlimit *limit); +# 533 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn); +# 548 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk); +# 558 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace); +# 569 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password); + + + + + + +apr_status_t apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname); +# 591 "../include/apr_thread_proc.h" +apr_status_t apr_proc_fork(apr_proc_t *proc, apr_pool_t *cont); +# 610 "../include/apr_thread_proc.h" +apr_status_t apr_proc_create(apr_proc_t *new_proc, + const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, + apr_pool_t *pool); +# 643 "../include/apr_thread_proc.h" +apr_status_t apr_proc_wait(apr_proc_t *proc, + int *exitcode, apr_exit_why_e *exitwhy, + apr_wait_how_e waithow); +# 673 "../include/apr_thread_proc.h" +apr_status_t apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p); +# 688 "../include/apr_thread_proc.h" +apr_status_t apr_proc_detach(int daemonize); +# 707 "../include/apr_thread_proc.h" +void apr_proc_other_child_register(apr_proc_t *proc, + void (*maintenance) (int reason, + void *, + int status), + void *data, apr_file_t *write_fd, + apr_pool_t *p); +# 723 "../include/apr_thread_proc.h" +void apr_proc_other_child_unregister(void *data); +# 745 "../include/apr_thread_proc.h" +apr_status_t apr_proc_other_child_alert(apr_proc_t *proc, + int reason, + int status); +# 756 "../include/apr_thread_proc.h" +void apr_proc_other_child_refresh(apr_other_child_rec_t *ocr, + int reason); + + + + + + + +void apr_proc_other_child_refresh_all(int reason); + + + + + + +apr_status_t apr_proc_kill(apr_proc_t *proc, int sig); +# 787 "../include/apr_thread_proc.h" +void apr_pool_note_subprocess(apr_pool_t *a, apr_proc_t *proc, + apr_kill_conditions_e how); +# 798 "../include/apr_thread_proc.h" +apr_status_t apr_setup_signal_thread(void); +# 807 "../include/apr_thread_proc.h" +apr_status_t apr_signal_thread(int(*signal_handler)(int signum)); + + + + + + + +apr_pool_t * apr_thread_pool_get (const apr_thread_t *thethread); +# 20 "./../test/testatomic.c" 2 + + +# 1 "../include/apr_atomic.h" 1 +# 47 "../include/apr_atomic.h" +apr_status_t apr_atomic_init(apr_pool_t *p); +# 59 "../include/apr_atomic.h" +apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem); + + + + + + +void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val); + + + + + + + +apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val); + + + + + + +void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val); + + + + + + +apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem); + + + + + + +int apr_atomic_dec32(volatile apr_uint32_t *mem); +# 105 "../include/apr_atomic.h" +apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, + apr_uint32_t cmp); + + + + + + + +apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val); +# 124 "../include/apr_atomic.h" +void* apr_atomic_casptr(volatile void **mem, void *with, const void *cmp); + + + + + + + +void* apr_atomic_xchgptr(volatile void **mem, void *with); +# 23 "./../test/testatomic.c" 2 +# 37 "./../test/testatomic.c" +static void test_init(abts_case *tc, void *data) +{ + apr_assert_success(tc, "Could not initliaze atomics", apr_atomic_init(p), 39); +} + +static void test_set32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_atomic_set32(&y32, 2); + abts_int_equal(tc, 2, y32, 46); +} + +static void test_read32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_atomic_set32(&y32, 2); + abts_int_equal(tc, 2, apr_atomic_read32(&y32), 53); +} + +static void test_dec32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + int rv; + + apr_atomic_set32(&y32, 2); + + rv = apr_atomic_dec32(&y32); + abts_int_equal(tc, 1, y32, 64); + abts_assert(tc, "atomic_dec returned zero when it shouldn't", rv != 0, 65);; + + rv = apr_atomic_dec32(&y32); + abts_int_equal(tc, 0, y32, 68); + abts_assert(tc, "atomic_dec didn't returned zero when it should", rv == 0, 69);; +} + +static void test_xchg32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 100); + oldval = apr_atomic_xchg32(&y32, 50); + + abts_int_equal(tc, 100, oldval, 80); + abts_int_equal(tc, 50, y32, 81); +} + +static void test_xchgptr(abts_case *tc, void *data) +{ + int a; + void *ref = "little piggy"; + volatile void *target_ptr = ref; + void *old_ptr; + + old_ptr = apr_atomic_xchgptr(&target_ptr, &a); + abts_ptr_equal(tc, ref, old_ptr, 92); + abts_ptr_equal(tc, &a, (void *) target_ptr, 93); +} + +static void test_cas_equal(abts_case *tc, void *data) +{ + apr_uint32_t casval = 0; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 12, 0); + abts_int_equal(tc, 0, oldval, 102); + abts_int_equal(tc, 12, casval, 103); +} + +static void test_cas_equal_nonnull(abts_case *tc, void *data) +{ + apr_uint32_t casval = 12; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 23, 12); + abts_int_equal(tc, 12, oldval, 112); + abts_int_equal(tc, 23, casval, 113); +} + +static void test_cas_notequal(abts_case *tc, void *data) +{ + apr_uint32_t casval = 12; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 23, 2); + abts_int_equal(tc, 12, oldval, 122); + abts_int_equal(tc, 12, casval, 123); +} + +static void test_casptr_equal(abts_case *tc, void *data) +{ + int a; + volatile void *target_ptr = ((void*)0); + void *old_ptr; + + old_ptr = apr_atomic_casptr(&target_ptr, &a, ((void*)0)); + abts_ptr_equal(tc, ((void*)0), old_ptr, 133); + abts_ptr_equal(tc, &a, (void *) target_ptr, 134); +} + +static void test_casptr_equal_nonnull(abts_case *tc, void *data) +{ + int a, b; + volatile void *target_ptr = &a; + void *old_ptr; + + old_ptr = apr_atomic_casptr(&target_ptr, &b, &a); + abts_ptr_equal(tc, &a, old_ptr, 144); + abts_ptr_equal(tc, &b, (void *) target_ptr, 145); +} + +static void test_casptr_notequal(abts_case *tc, void *data) +{ + int a, b; + volatile void *target_ptr = &a; + void *old_ptr; + + old_ptr = apr_atomic_casptr(&target_ptr, &a, &b); + abts_ptr_equal(tc, &a, old_ptr, 155); + abts_ptr_equal(tc, &a, (void *) target_ptr, 156); +} + +static void test_add32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 23); + oldval = apr_atomic_add32(&y32, 4); + abts_int_equal(tc, 23, oldval, 166); + abts_int_equal(tc, 27, y32, 167); +} + +static void test_add32_neg(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 23); + oldval = apr_atomic_add32(&y32, -10); + abts_int_equal(tc, 23, oldval, 177); + abts_int_equal(tc, 13, y32, 178); +} + +static void test_inc32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 23); + oldval = apr_atomic_inc32(&y32); + abts_int_equal(tc, 23, oldval, 188); + abts_int_equal(tc, 24, y32, 189); +} + +static void test_set_add_inc_sub(abts_case *tc, void *data) +{ + apr_uint32_t y32; + + apr_atomic_set32(&y32, 0); + apr_atomic_add32(&y32, 20); + apr_atomic_inc32(&y32); + apr_atomic_sub32(&y32, 10); + + abts_int_equal(tc, 11, y32, 201); +} + +static void test_wrap_zero(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_uint32_t rv; + apr_uint32_t minus1 = -1; + char *str; + + apr_atomic_set32(&y32, 0); + rv = apr_atomic_dec32(&y32); + + abts_assert(tc, "apr_atomic_dec32 on zero returned zero.", rv != 0, 214);; + str = apr_psprintf(p, "zero wrap failed: 0 - 1 = %d", y32); + abts_assert(tc, str, y32 == minus1, 216);; +} + +static void test_inc_neg1(abts_case *tc, void *data) +{ + apr_uint32_t y32 = -1; + apr_uint32_t minus1 = -1; + apr_uint32_t rv; + char *str; + + rv = apr_atomic_inc32(&y32); + + abts_assert(tc, "apr_atomic_inc32 didn't return the old value.", rv == minus1, 228);; + str = apr_psprintf(p, "zero wrap failed: -1 + 1 = %d", y32); + abts_assert(tc, str, y32 == 0, 230);; +} + + + + +void * thread_func_mutex(apr_thread_t *thd, void *data); +void * thread_func_atomic(apr_thread_t *thd, void *data); + +apr_thread_mutex_t *thread_lock; +volatile apr_uint32_t mutex_locks = 0; +volatile apr_uint32_t atomic_ops = 0; +apr_status_t exit_ret_val = 123; + +void * thread_func_mutex(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < 1; i++) { + apr_thread_mutex_lock(thread_lock); + mutex_locks++; + apr_thread_mutex_unlock(thread_lock); + } + apr_thread_exit(thd, exit_ret_val); + return ((void*)0); +} + +void * thread_func_atomic(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < 1 ; i++) { + apr_atomic_inc32(&atomic_ops); + apr_atomic_add32(&atomic_ops, 2); + apr_atomic_dec32(&atomic_ops); + apr_atomic_dec32(&atomic_ops); + } + apr_thread_exit(thd, exit_ret_val); + return ((void*)0); +} + +static void test_atomics_threaded(abts_case *tc, void *data) +{ + apr_thread_t *t1[3]; + apr_thread_t *t2[3]; + apr_status_t rv; + int i; + + + + + + rv = apr_thread_mutex_create(&thread_lock, 0x0, p); + apr_assert_success(tc, "Could not create lock", rv, 283); + + for (i = 0; i < 3; i++) { + apr_status_t r1, r2; + r1 = apr_thread_create(&t1[i], ((void*)0), thread_func_mutex, ((void*)0), p); + r2 = apr_thread_create(&t2[i], ((void*)0), thread_func_atomic, ((void*)0), p); + abts_assert(tc, "Failed creating threads", !r1 && !r2, 289);; + } + + for (i = 0; i < 3; i++) { + apr_status_t s1, s2; + apr_thread_join(&s1, t1[i]); + apr_thread_join(&s2, t2[i]); + + abts_assert(tc, "Invalid return value from thread_join", s1 == exit_ret_val && s2 == exit_ret_val, 298);; + + } + + abts_int_equal(tc, 3 * 1, mutex_locks, 301); + abts_int_equal(tc, 3 * 1, apr_atomic_read32(&atomic_ops), 303); + + + rv = apr_thread_mutex_destroy(thread_lock); + abts_assert(tc, "Failed creating threads", rv == 0, 306);; +} + +typedef struct tbox_t tbox_t; + +struct tbox_t { + abts_case *tc; + apr_uint32_t *mem; + apr_uint32_t preval; + apr_uint32_t postval; + apr_uint32_t loop; + void (*func)(tbox_t *box); +}; + +static __inline__ void busyloop_read32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + val = apr_atomic_read32(tbox->mem); + + if (val != tbox->preval) { + apr_thread_yield(); + } else { + break; + } + } while (1); +} + +static void busyloop_set32(tbox_t *tbox) +{ + do { + busyloop_read32(tbox); + apr_atomic_set32(tbox->mem, tbox->postval); + } while (--tbox->loop); +} + +static void busyloop_add32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + busyloop_read32(tbox); + val = apr_atomic_add32(tbox->mem, tbox->postval); + apr_thread_mutex_lock(thread_lock); + abts_int_equal(tbox->tc, val, tbox->preval, 350); + apr_thread_mutex_unlock(thread_lock); + } while (--tbox->loop); +} + +static void busyloop_sub32(tbox_t *tbox) +{ + do { + busyloop_read32(tbox); + apr_atomic_sub32(tbox->mem, tbox->postval); + } while (--tbox->loop); +} + +static void busyloop_inc32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + busyloop_read32(tbox); + val = apr_atomic_inc32(tbox->mem); + apr_thread_mutex_lock(thread_lock); + abts_int_equal(tbox->tc, val, tbox->preval, 371); + apr_thread_mutex_unlock(thread_lock); + } while (--tbox->loop); +} + +static void busyloop_dec32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + busyloop_read32(tbox); + val = apr_atomic_dec32(tbox->mem); + apr_thread_mutex_lock(thread_lock); + abts_int_nequal(tbox->tc, 0, val, 384); + apr_thread_mutex_unlock(thread_lock); + } while (--tbox->loop); +} + +static void busyloop_cas32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + do { + val = apr_atomic_cas32(tbox->mem, tbox->postval, tbox->preval); + + if (val != tbox->preval) { + apr_thread_yield(); + } else { + break; + } + } while (1); + } while (--tbox->loop); +} + +static void busyloop_xchg32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + busyloop_read32(tbox); + val = apr_atomic_xchg32(tbox->mem, tbox->postval); + apr_thread_mutex_lock(thread_lock); + abts_int_equal(tbox->tc, val, tbox->preval, 413); + apr_thread_mutex_unlock(thread_lock); + } while (--tbox->loop); +} + +static void * thread_func_busyloop(apr_thread_t *thd, void *data) +{ + tbox_t *tbox = data; + + tbox->func(tbox); + + apr_thread_exit(thd, 0); + + return ((void*)0); +} + +static void test_atomics_busyloop_threaded(abts_case *tc, void *data) +{ + unsigned int i; + apr_status_t rv; + apr_uint32_t count = 0; + tbox_t tbox[3]; + apr_thread_t *thread[3]; + + rv = apr_thread_mutex_create(&thread_lock, 0x0, p); + apr_assert_success(tc, "Could not create lock", rv, 438); + + + for (i = 0; i < 3; i++) { + tbox[i].tc = tc; + tbox[i].mem = &count; + tbox[i].loop = 50; + } + + tbox[0].preval = 98; + tbox[0].postval = 3891; + tbox[0].func = busyloop_add32; + + tbox[1].preval = 3989; + tbox[1].postval = 1010; + tbox[1].func = busyloop_sub32; + + tbox[2].preval = 2979; + tbox[2].postval = 0; + tbox[2].func = busyloop_inc32; + + tbox[3].preval = 2980; + tbox[3].postval = 16384; + tbox[3].func = busyloop_set32; + + tbox[4].preval = 16384; + tbox[4].postval = 0; + tbox[4].func = busyloop_dec32; + + tbox[5].preval = 16383; + tbox[5].postval = 1048576; + tbox[5].func = busyloop_cas32; + + tbox[6].preval = 1048576; + tbox[6].postval = 98; + tbox[6].func = busyloop_xchg32; + + + for (i = 0; i < 3; i++) { + rv = apr_thread_create(&thread[i], ((void*)0), thread_func_busyloop, + &tbox[i], p); + abts_assert(tc, "Failed creating thread", rv == 0, 479);; + } + + + apr_atomic_set32(tbox->mem, 98); + + for (i = 0; i < 3; i++) { + apr_status_t retval; + rv = apr_thread_join(&retval, thread[i]); + abts_assert(tc, "Thread join failed", rv == 0, 488);; + abts_assert(tc, "Invalid return value from thread_join", retval == 0, 489);; + } + + abts_int_equal(tbox->tc, 98, count, 492); + + rv = apr_thread_mutex_destroy(thread_lock); + abts_assert(tc, "Failed creating threads", rv == 0, 495);; +} + + + +abts_suite *testatomic(abts_suite *suite) +{ + suite = abts_add_suite(suite, "./../test/testatomic.c"); + + abts_run_test(suite, test_init, ((void*)0)); + abts_run_test(suite, test_set32, ((void*)0)); + abts_run_test(suite, test_read32, ((void*)0)); + abts_run_test(suite, test_dec32, ((void*)0)); + abts_run_test(suite, test_xchg32, ((void*)0)); + abts_run_test(suite, test_xchgptr, ((void*)0)); + abts_run_test(suite, test_cas_equal, ((void*)0)); + abts_run_test(suite, test_cas_equal_nonnull, ((void*)0)); + abts_run_test(suite, test_cas_notequal, ((void*)0)); + abts_run_test(suite, test_casptr_equal, ((void*)0)); + abts_run_test(suite, test_casptr_equal_nonnull, ((void*)0)); + abts_run_test(suite, test_casptr_notequal, ((void*)0)); + abts_run_test(suite, test_add32, ((void*)0)); + abts_run_test(suite, test_add32_neg, ((void*)0)); + abts_run_test(suite, test_inc32, ((void*)0)); + abts_run_test(suite, test_set_add_inc_sub, ((void*)0)); + abts_run_test(suite, test_wrap_zero, ((void*)0)); + abts_run_test(suite, test_inc_neg1, ((void*)0)); + + + abts_run_test(suite, test_atomics_threaded, ((void*)0)); + abts_run_test(suite, test_atomics_busyloop_threaded, ((void*)0)); + + + return suite; +} +# 11 "main1.c" 2 +# 1 "./../test/testutil.c" 1 +# 20 "./../test/testutil.c" +# 1 "./../test/abts.h" 1 +# 21 "./../test/testutil.c" 2 +# 1 "./../test/testutil.h" 1 +# 19 "./../test/testutil.h" +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 22 "./../test/testutil.c" 2 + + +apr_pool_t *p; + +void apr_assert_success(abts_case* tc, const char* context, apr_status_t rv, + int lineno) +{ + if (rv == ((20000 + 50000) + 23)) { + abts_not_impl(tc, context, lineno); + } else if (rv != 0) { + char buf[8096], ebuf[128]; + sprintf(buf, "%s (%d): %s\n", context, rv, + apr_strerror(rv, ebuf, sizeof ebuf)); + abts_fail(tc, buf, lineno); + } +} + +void initialize(void) { + apr_initialize(); + atexit(apr_terminate); + + apr_pool_create_ex(&p, ((void*)0), ((void*)0), ((void*)0)); +} +# 12 "main1.c" 2 +# 1 "./../locks/unix/thread_mutex.c" 1 +# 17 "./../locks/unix/thread_mutex.c" +# 1 "../include/arch/unix/apr_arch_thread_mutex.h" 1 +# 21 "../include/arch/unix/apr_arch_thread_mutex.h" +# 1 "../include/arch/unix/apr_private.h" 1 +# 999 "../include/arch/unix/apr_private.h" +# 1 "../include/arch/unix/../apr_private_common.h" 1 +# 27 "../include/arch/unix/../apr_private_common.h" +apr_status_t apr_filepath_list_split_impl(apr_array_header_t **pathelts, + const char *liststr, + char separator, + apr_pool_t *p); + +apr_status_t apr_filepath_list_merge_impl(char **liststr, + apr_array_header_t *pathelts, + char separator, + apr_pool_t *p); +# 1000 "../include/arch/unix/apr_private.h" 2 +# 22 "../include/arch/unix/apr_arch_thread_mutex.h" 2 + + +# 1 "../include/apr_portable.h" 1 +# 32 "../include/apr_portable.h" +# 1 "../include/apr_network_io.h" 1 +# 31 "../include/apr_network_io.h" +# 1 "/usr/include/netinet/in.h" 1 3 4 +# 22 "/usr/include/netinet/in.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdint.h" 1 3 4 +# 23 "/usr/include/netinet/in.h" 2 3 4 + + + + + + + +typedef uint32_t in_addr_t; +struct in_addr + { + in_addr_t s_addr; + }; + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/in.h" 1 3 4 +# 112 "/usr/include/x86_64-linux-gnu/bits/in.h" 3 4 +struct ip_opts + { + struct in_addr ip_dst; + char ip_opts[40]; + }; + + +struct ip_mreqn + { + struct in_addr imr_multiaddr; + struct in_addr imr_address; + int imr_ifindex; + }; + + +struct in_pktinfo + { + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; + }; +# 38 "/usr/include/netinet/in.h" 2 3 4 + + +enum + { + IPPROTO_IP = 0, + + IPPROTO_ICMP = 1, + + IPPROTO_IGMP = 2, + + IPPROTO_IPIP = 4, + + IPPROTO_TCP = 6, + + IPPROTO_EGP = 8, + + IPPROTO_PUP = 12, + + IPPROTO_UDP = 17, + + IPPROTO_IDP = 22, + + IPPROTO_TP = 29, + + IPPROTO_DCCP = 33, + + IPPROTO_IPV6 = 41, + + IPPROTO_RSVP = 46, + + IPPROTO_GRE = 47, + + IPPROTO_ESP = 50, + + IPPROTO_AH = 51, + + IPPROTO_MTP = 92, + + IPPROTO_BEETPH = 94, + + IPPROTO_ENCAP = 98, + + IPPROTO_PIM = 103, + + IPPROTO_COMP = 108, + + IPPROTO_SCTP = 132, + + IPPROTO_UDPLITE = 136, + + IPPROTO_RAW = 255, + + IPPROTO_MAX + }; + + + + + +enum + { + IPPROTO_HOPOPTS = 0, + + IPPROTO_ROUTING = 43, + + IPPROTO_FRAGMENT = 44, + + IPPROTO_ICMPV6 = 58, + + IPPROTO_NONE = 59, + + IPPROTO_DSTOPTS = 60, + + IPPROTO_MH = 135 + + }; + + + +typedef uint16_t in_port_t; + + +enum + { + IPPORT_ECHO = 7, + IPPORT_DISCARD = 9, + IPPORT_SYSTAT = 11, + IPPORT_DAYTIME = 13, + IPPORT_NETSTAT = 15, + IPPORT_FTP = 21, + IPPORT_TELNET = 23, + IPPORT_SMTP = 25, + IPPORT_TIMESERVER = 37, + IPPORT_NAMESERVER = 42, + IPPORT_WHOIS = 43, + IPPORT_MTP = 57, + + IPPORT_TFTP = 69, + IPPORT_RJE = 77, + IPPORT_FINGER = 79, + IPPORT_TTYLINK = 87, + IPPORT_SUPDUP = 95, + + + IPPORT_EXECSERVER = 512, + IPPORT_LOGINSERVER = 513, + IPPORT_CMDSERVER = 514, + IPPORT_EFSSERVER = 520, + + + IPPORT_BIFFUDP = 512, + IPPORT_WHOSERVER = 513, + IPPORT_ROUTESERVER = 520, + + + IPPORT_RESERVED = 1024, + + + IPPORT_USERRESERVED = 5000 + }; +# 209 "/usr/include/netinet/in.h" 3 4 +struct in6_addr + { + union + { + uint8_t __u6_addr8[16]; + + uint16_t __u6_addr16[8]; + uint32_t __u6_addr32[4]; + + } __in6_u; + + + + + + }; + + +extern const struct in6_addr in6addr_any; +extern const struct in6_addr in6addr_loopback; +# 237 "/usr/include/netinet/in.h" 3 4 +struct sockaddr_in + { + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; + + + unsigned char sin_zero[sizeof (struct sockaddr) - + (sizeof (unsigned short int)) - + sizeof (in_port_t) - + sizeof (struct in_addr)]; + }; + + + +struct sockaddr_in6 + { + sa_family_t sin6_family; + in_port_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; + uint32_t sin6_scope_id; + }; + + + + +struct ip_mreq + { + + struct in_addr imr_multiaddr; + + + struct in_addr imr_interface; + }; + +struct ip_mreq_source + { + + struct in_addr imr_multiaddr; + + + struct in_addr imr_interface; + + + struct in_addr imr_sourceaddr; + }; + + + + +struct ipv6_mreq + { + + struct in6_addr ipv6mr_multiaddr; + + + unsigned int ipv6mr_interface; + }; + + + + +struct group_req + { + + uint32_t gr_interface; + + + struct sockaddr_storage gr_group; + }; + +struct group_source_req + { + + uint32_t gsr_interface; + + + struct sockaddr_storage gsr_group; + + + struct sockaddr_storage gsr_source; + }; + + + +struct ip_msfilter + { + + struct in_addr imsf_multiaddr; + + + struct in_addr imsf_interface; + + + uint32_t imsf_fmode; + + + uint32_t imsf_numsrc; + + struct in_addr imsf_slist[1]; + }; + + + + + +struct group_filter + { + + uint32_t gf_interface; + + + struct sockaddr_storage gf_group; + + + uint32_t gf_fmode; + + + uint32_t gf_numsrc; + + struct sockaddr_storage gf_slist[1]; +}; +# 374 "/usr/include/netinet/in.h" 3 4 +extern uint32_t ntohl (uint32_t __netlong) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern uint16_t ntohs (uint16_t __netshort) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern uint32_t htonl (uint32_t __hostlong) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern uint16_t htons (uint16_t __hostshort) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 1 3 4 +# 386 "/usr/include/netinet/in.h" 2 3 4 +# 501 "/usr/include/netinet/in.h" 3 4 +extern int bindresvport (int __sockfd, struct sockaddr_in *__sock_in) __attribute__ ((__nothrow__ )); + + +extern int bindresvport6 (int __sockfd, struct sockaddr_in6 *__sock_in) + __attribute__ ((__nothrow__ )); +# 32 "../include/apr_network_io.h" 2 +# 108 "../include/apr_network_io.h" +typedef enum { + APR_SHUTDOWN_READ, + APR_SHUTDOWN_WRITE, + APR_SHUTDOWN_READWRITE +} apr_shutdown_how_e; +# 172 "../include/apr_network_io.h" +typedef enum { + APR_LOCAL, + APR_REMOTE +} apr_interface_e; +# 193 "../include/apr_network_io.h" +typedef struct apr_socket_t apr_socket_t; + + + +typedef struct apr_hdtr_t apr_hdtr_t; + +typedef struct in_addr apr_in_addr_t; + +typedef struct apr_ipsubnet_t apr_ipsubnet_t; + + +typedef apr_uint16_t apr_port_t; + + + + +typedef struct apr_sockaddr_t apr_sockaddr_t; + + + +struct apr_sockaddr_t { + + apr_pool_t *pool; + + char *hostname; + + char *servname; + + apr_port_t port; + + apr_int32_t family; + + apr_socklen_t salen; + + int ipaddr_len; + + + int addr_str_len; + + + void *ipaddr_ptr; + + + apr_sockaddr_t *next; + + union { + + struct sockaddr_in sin; + + + struct sockaddr_in6 sin6; + + + + + struct sockaddr_storage sas; + + } sa; +}; +# 263 "../include/apr_network_io.h" +struct apr_hdtr_t { + + struct iovec* headers; + + int numheaders; + + struct iovec* trailers; + + int numtrailers; +}; +# 287 "../include/apr_network_io.h" +apr_status_t apr_socket_create(apr_socket_t **new_sock, + int family, int type, + int protocol, + apr_pool_t *cont); +# 305 "../include/apr_network_io.h" +apr_status_t apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how); + + + + + +apr_status_t apr_socket_close(apr_socket_t *thesocket); +# 321 "../include/apr_network_io.h" +apr_status_t apr_socket_bind(apr_socket_t *sock, + apr_sockaddr_t *sa); +# 331 "../include/apr_network_io.h" +apr_status_t apr_socket_listen(apr_socket_t *sock, + apr_int32_t backlog); +# 345 "../include/apr_network_io.h" +apr_status_t apr_socket_accept(apr_socket_t **new_sock, + apr_socket_t *sock, + apr_pool_t *connection_pool); + + + + + + + +apr_status_t apr_socket_connect(apr_socket_t *sock, + apr_sockaddr_t *sa); +# 370 "../include/apr_network_io.h" +apr_status_t apr_socket_atreadeof(apr_socket_t *sock, + int *atreadeof); +# 396 "../include/apr_network_io.h" +apr_status_t apr_sockaddr_info_get(apr_sockaddr_t **sa, + const char *hostname, + apr_int32_t family, + apr_port_t port, + apr_int32_t flags, + apr_pool_t *p); +# 411 "../include/apr_network_io.h" +apr_status_t apr_getnameinfo(char **hostname, + apr_sockaddr_t *sa, + apr_int32_t flags); +# 445 "../include/apr_network_io.h" +apr_status_t apr_parse_addr_port(char **addr, + char **scope_id, + apr_port_t *port, + const char *str, + apr_pool_t *p); +# 459 "../include/apr_network_io.h" +apr_status_t apr_gethostname(char *buf, int len, apr_pool_t *cont); + + + + + + + +apr_status_t apr_socket_data_get(void **data, const char *key, + apr_socket_t *sock); +# 477 "../include/apr_network_io.h" +apr_status_t apr_socket_data_set(apr_socket_t *sock, void *data, + const char *key, + apr_status_t (*cleanup)(void*)); +# 498 "../include/apr_network_io.h" +apr_status_t apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len); +# 519 "../include/apr_network_io.h" +apr_status_t apr_socket_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len); +# 530 "../include/apr_network_io.h" +apr_status_t apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len); +# 548 "../include/apr_network_io.h" +apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len); +# 573 "../include/apr_network_io.h" +apr_status_t apr_socket_sendfile(apr_socket_t *sock, + apr_file_t *file, + apr_hdtr_t *hdtr, + apr_off_t *offset, + apr_size_t *len, + apr_int32_t flags); +# 601 "../include/apr_network_io.h" +apr_status_t apr_socket_recv(apr_socket_t *sock, + char *buf, apr_size_t *len); +# 626 "../include/apr_network_io.h" +apr_status_t apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on); +# 640 "../include/apr_network_io.h" +apr_status_t apr_socket_timeout_set(apr_socket_t *sock, + apr_interval_time_t t); +# 662 "../include/apr_network_io.h" +apr_status_t apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on); + + + + + + +apr_status_t apr_socket_timeout_get(apr_socket_t *sock, + apr_interval_time_t *t); + + + + + + + +apr_status_t apr_socket_atmark(apr_socket_t *sock, + int *atmark); +# 690 "../include/apr_network_io.h" +apr_status_t apr_socket_addr_get(apr_sockaddr_t **sa, + apr_interface_e which, + apr_socket_t *sock); +# 701 "../include/apr_network_io.h" +apr_status_t apr_sockaddr_ip_get(char **addr, + apr_sockaddr_t *sockaddr); + + + + + + +apr_status_t apr_sockaddr_ip_getbuf(char *buf, apr_size_t buflen, + apr_sockaddr_t *sockaddr); +# 722 "../include/apr_network_io.h" +int apr_sockaddr_equal(const apr_sockaddr_t *addr1, + const apr_sockaddr_t *addr2); +# 733 "../include/apr_network_io.h" +int apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr); + + + + + + +apr_status_t apr_socket_type_get(apr_socket_t *sock, + int *type); + + + + + + +apr_status_t apr_getservbyname(apr_sockaddr_t *sockaddr, + const char *servname); +# 758 "../include/apr_network_io.h" +apr_status_t apr_ipsubnet_create(apr_ipsubnet_t **ipsub, + const char *ipstr, + const char *mask_or_numbits, + apr_pool_t *p); +# 770 "../include/apr_network_io.h" +int apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa); +# 791 "../include/apr_network_io.h" +apr_status_t apr_socket_protocol_get(apr_socket_t *sock, + int *protocol); + + + + +apr_pool_t * apr_socket_pool_get (const apr_socket_t *thesocket); + + + + +apr_status_t apr_socket_inherit_set( apr_socket_t *thesocket); + + + + +apr_status_t apr_socket_inherit_unset( apr_socket_t *thesocket); +# 823 "../include/apr_network_io.h" +apr_status_t apr_mcast_join(apr_socket_t *sock, + apr_sockaddr_t *join, + apr_sockaddr_t *iface, + apr_sockaddr_t *source); +# 838 "../include/apr_network_io.h" +apr_status_t apr_mcast_leave(apr_socket_t *sock, + apr_sockaddr_t *addr, + apr_sockaddr_t *iface, + apr_sockaddr_t *source); +# 850 "../include/apr_network_io.h" +apr_status_t apr_mcast_hops(apr_socket_t *sock, + apr_byte_t ttl); + + + + + + +apr_status_t apr_mcast_loopback(apr_socket_t *sock, + apr_byte_t opt); + + + + + + + +apr_status_t apr_mcast_interface(apr_socket_t *sock, + apr_sockaddr_t *iface); +# 33 "../include/apr_portable.h" 2 + +# 1 "../include/apr_global_mutex.h" 1 +# 26 "../include/apr_global_mutex.h" +# 1 "../include/apr_proc_mutex.h" 1 +# 44 "../include/apr_proc_mutex.h" +typedef enum { + APR_LOCK_FCNTL, + APR_LOCK_FLOCK, + APR_LOCK_SYSVSEM, + APR_LOCK_PROC_PTHREAD, + APR_LOCK_POSIXSEM, + APR_LOCK_DEFAULT +} apr_lockmech_e; + + +typedef struct apr_proc_mutex_t apr_proc_mutex_t; +# 79 "../include/apr_proc_mutex.h" +apr_status_t apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool); +# 95 "../include/apr_proc_mutex.h" +apr_status_t apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool); + + + + + + +apr_status_t apr_proc_mutex_lock(apr_proc_mutex_t *mutex); +# 113 "../include/apr_proc_mutex.h" +apr_status_t apr_proc_mutex_trylock(apr_proc_mutex_t *mutex); + + + + + +apr_status_t apr_proc_mutex_unlock(apr_proc_mutex_t *mutex); + + + + + +apr_status_t apr_proc_mutex_destroy(apr_proc_mutex_t *mutex); + + + + + + + +apr_status_t apr_proc_mutex_cleanup(void *mutex); + + + + + + +const char * apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex); + + + + + + +const char * apr_proc_mutex_name(apr_proc_mutex_t *mutex); + + + + +const char * apr_proc_mutex_defname(void); + + + + + +apr_pool_t * apr_proc_mutex_pool_get (const apr_proc_mutex_t *theproc_mutex); +# 27 "../include/apr_global_mutex.h" 2 +# 46 "../include/apr_global_mutex.h" +typedef struct apr_global_mutex_t apr_global_mutex_t; +# 74 "../include/apr_global_mutex.h" +apr_status_t apr_global_mutex_create(apr_global_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool); +# 90 "../include/apr_global_mutex.h" +apr_status_t apr_global_mutex_child_init( + apr_global_mutex_t **mutex, + const char *fname, + apr_pool_t *pool); + + + + + + +apr_status_t apr_global_mutex_lock(apr_global_mutex_t *mutex); +# 109 "../include/apr_global_mutex.h" +apr_status_t apr_global_mutex_trylock(apr_global_mutex_t *mutex); + + + + + +apr_status_t apr_global_mutex_unlock(apr_global_mutex_t *mutex); + + + + + +apr_status_t apr_global_mutex_destroy(apr_global_mutex_t *mutex); + + + + + +const char * apr_global_mutex_lockfile(apr_global_mutex_t *mutex); + + + + + + + +const char * apr_global_mutex_name(apr_global_mutex_t *mutex); + + + + + +apr_pool_t * apr_global_mutex_pool_get (const apr_global_mutex_t *theglobal_mutex); +# 35 "../include/apr_portable.h" 2 + + +# 1 "../include/apr_dso.h" 1 +# 44 "../include/apr_dso.h" +typedef struct apr_dso_handle_t apr_dso_handle_t; + + + + +typedef void * apr_dso_handle_sym_t; +# 59 "../include/apr_dso.h" +apr_status_t apr_dso_load(apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *ctx); + + + + + +apr_status_t apr_dso_unload(apr_dso_handle_t *handle); + + + + + + + +apr_status_t apr_dso_sym(apr_dso_handle_sym_t *ressym, + apr_dso_handle_t *handle, + const char *symname); + + + + + + + +const char * apr_dso_error(apr_dso_handle_t *dso, char *buf, apr_size_t bufsize); +# 38 "../include/apr_portable.h" 2 +# 1 "../include/apr_shm.h" 1 +# 43 "../include/apr_shm.h" +typedef struct apr_shm_t apr_shm_t; +# 69 "../include/apr_shm.h" +apr_status_t apr_shm_create(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *pool); +# 114 "../include/apr_shm.h" +apr_status_t apr_shm_create_ex(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *pool, + apr_int32_t flags); +# 135 "../include/apr_shm.h" +apr_status_t apr_shm_remove(const char *filename, + apr_pool_t *pool); + + + + + +apr_status_t apr_shm_destroy(apr_shm_t *m); +# 153 "../include/apr_shm.h" +apr_status_t apr_shm_attach(apr_shm_t **m, + const char *filename, + apr_pool_t *pool); +# 167 "../include/apr_shm.h" +apr_status_t apr_shm_attach_ex(apr_shm_t **m, + const char *filename, + apr_pool_t *pool, + apr_int32_t flags); + + + + + + +apr_status_t apr_shm_detach(apr_shm_t *m); +# 188 "../include/apr_shm.h" +void * apr_shm_baseaddr_get(const apr_shm_t *m); + + + + + + +apr_size_t apr_shm_size_get(const apr_shm_t *m); + + + + +apr_pool_t * apr_shm_pool_get (const apr_shm_t *theshm); +# 39 "../include/apr_portable.h" 2 + + +# 1 "/usr/include/dirent.h" 1 3 4 +# 61 "/usr/include/dirent.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/dirent.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/dirent.h" 3 4 +struct dirent + { + + __ino_t d_ino; + __off_t d_off; + + + + + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; + }; +# 62 "/usr/include/dirent.h" 2 3 4 +# 97 "/usr/include/dirent.h" 3 4 +enum + { + DT_UNKNOWN = 0, + + DT_FIFO = 1, + + DT_CHR = 2, + + DT_DIR = 4, + + DT_BLK = 6, + + DT_REG = 8, + + DT_LNK = 10, + + DT_SOCK = 12, + + DT_WHT = 14 + + }; +# 127 "/usr/include/dirent.h" 3 4 +typedef struct __dirstream DIR; + + + + + + +extern DIR *opendir (const char *__name) __attribute__ ((__nonnull__ (1))); + + + + + + +extern DIR *fdopendir (int __fd); + + + + + + + +extern int closedir (DIR *__dirp) __attribute__ ((__nonnull__ (1))); +# 162 "/usr/include/dirent.h" 3 4 +extern struct dirent *readdir (DIR *__dirp) __attribute__ ((__nonnull__ (1))); +# 183 "/usr/include/dirent.h" 3 4 +extern int readdir_r (DIR *__restrict __dirp, + struct dirent *__restrict __entry, + struct dirent **__restrict __result) + __attribute__ ((__nonnull__ (1, 2, 3))); +# 208 "/usr/include/dirent.h" 3 4 +extern void rewinddir (DIR *__dirp) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern void seekdir (DIR *__dirp, long int __pos) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern long int telldir (DIR *__dirp) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int dirfd (DIR *__dirp) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 244 "/usr/include/dirent.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 245 "/usr/include/dirent.h" 2 3 4 +# 254 "/usr/include/dirent.h" 3 4 +extern int scandir (const char *__restrict __dir, + struct dirent ***__restrict __namelist, + int (*__selector) (const struct dirent *), + int (*__cmp) (const struct dirent **, + const struct dirent **)) + __attribute__ ((__nonnull__ (1, 2))); +# 324 "/usr/include/dirent.h" 3 4 +extern int alphasort (const struct dirent **__e1, + const struct dirent **__e2) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 352 "/usr/include/dirent.h" 3 4 +extern __ssize_t getdirentries (int __fd, char *__restrict __buf, + size_t __nbytes, + __off_t *__restrict __basep) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))); +# 42 "../include/apr_portable.h" 2 + + +# 1 "/usr/include/fcntl.h" 1 3 4 +# 35 "/usr/include/fcntl.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/fcntl.h" 1 3 4 +# 35 "/usr/include/x86_64-linux-gnu/bits/fcntl.h" 3 4 +struct flock + { + short int l_type; + short int l_whence; + + __off_t l_start; + __off_t l_len; + + + + + __pid_t l_pid; + }; +# 61 "/usr/include/x86_64-linux-gnu/bits/fcntl.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h" 1 3 4 +# 62 "/usr/include/x86_64-linux-gnu/bits/fcntl.h" 2 3 4 +# 36 "/usr/include/fcntl.h" 2 3 4 +# 67 "/usr/include/fcntl.h" 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 68 "/usr/include/fcntl.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/stat.h" 1 3 4 +# 46 "/usr/include/x86_64-linux-gnu/bits/stat.h" 3 4 +struct stat + { + __dev_t st_dev; + + + + + __ino_t st_ino; + + + + + + + + __nlink_t st_nlink; + __mode_t st_mode; + + __uid_t st_uid; + __gid_t st_gid; + + int __pad0; + + __dev_t st_rdev; + + + + + __off_t st_size; + + + + __blksize_t st_blksize; + + __blkcnt_t st_blocks; +# 91 "/usr/include/x86_64-linux-gnu/bits/stat.h" 3 4 + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +# 106 "/usr/include/x86_64-linux-gnu/bits/stat.h" 3 4 + __syscall_slong_t __glibc_reserved[3]; +# 115 "/usr/include/x86_64-linux-gnu/bits/stat.h" 3 4 + }; +# 69 "/usr/include/fcntl.h" 2 3 4 +# 137 "/usr/include/fcntl.h" 3 4 +extern int fcntl (int __fd, int __cmd, ...); +# 146 "/usr/include/fcntl.h" 3 4 +extern int open (const char *__file, int __oflag, ...) __attribute__ ((__nonnull__ (1))); +# 170 "/usr/include/fcntl.h" 3 4 +extern int openat (int __fd, const char *__file, int __oflag, ...) + __attribute__ ((__nonnull__ (2))); +# 192 "/usr/include/fcntl.h" 3 4 +extern int creat (const char *__file, mode_t __mode) __attribute__ ((__nonnull__ (1))); +# 238 "/usr/include/fcntl.h" 3 4 +extern int posix_fadvise (int __fd, off_t __offset, off_t __len, + int __advise) __attribute__ ((__nothrow__ )); +# 260 "/usr/include/fcntl.h" 3 4 +extern int posix_fallocate (int __fd, off_t __offset, off_t __len); +# 45 "../include/apr_portable.h" 2 + + +# 1 "/usr/include/pthread.h" 1 3 4 +# 23 "/usr/include/pthread.h" 3 4 +# 1 "/usr/include/sched.h" 1 3 4 +# 28 "/usr/include/sched.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 29 "/usr/include/sched.h" 2 3 4 + + + +# 1 "/usr/include/time.h" 1 3 4 +# 33 "/usr/include/sched.h" 2 3 4 + + + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sched.h" 1 3 4 +# 72 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 +struct sched_param + { + int __sched_priority; + }; +# 103 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 +struct __sched_param + { + int __sched_priority; + }; +# 118 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 +typedef unsigned long int __cpu_mask; + + + + + + +typedef struct +{ + __cpu_mask __bits[1024 / (8 * sizeof (__cpu_mask))]; +} cpu_set_t; +# 203 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 +extern int __sched_cpucount (size_t __setsize, const cpu_set_t *__setp) + __attribute__ ((__nothrow__ )); +extern cpu_set_t *__sched_cpualloc (size_t __count) __attribute__ ((__nothrow__ )) ; +extern void __sched_cpufree (cpu_set_t *__set) __attribute__ ((__nothrow__ )); +# 42 "/usr/include/sched.h" 2 3 4 + + + + + + + +extern int sched_setparam (__pid_t __pid, const struct sched_param *__param) + __attribute__ ((__nothrow__ )); + + +extern int sched_getparam (__pid_t __pid, struct sched_param *__param) __attribute__ ((__nothrow__ )); + + +extern int sched_setscheduler (__pid_t __pid, int __policy, + const struct sched_param *__param) __attribute__ ((__nothrow__ )); + + +extern int sched_getscheduler (__pid_t __pid) __attribute__ ((__nothrow__ )); + + +extern int sched_yield (void) __attribute__ ((__nothrow__ )); + + +extern int sched_get_priority_max (int __algorithm) __attribute__ ((__nothrow__ )); + + +extern int sched_get_priority_min (int __algorithm) __attribute__ ((__nothrow__ )); + + +extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __attribute__ ((__nothrow__ )); +# 24 "/usr/include/pthread.h" 2 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 37 "/usr/include/time.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 38 "/usr/include/time.h" 2 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/time.h" 1 3 4 +# 42 "/usr/include/time.h" 2 3 4 +# 133 "/usr/include/time.h" 3 4 +struct tm +{ + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; + + + long int tm_gmtoff; + const char *tm_zone; + + + + +}; +# 161 "/usr/include/time.h" 3 4 +struct itimerspec + { + struct timespec it_interval; + struct timespec it_value; + }; + + +struct sigevent; +# 189 "/usr/include/time.h" 3 4 +extern clock_t clock (void) __attribute__ ((__nothrow__ )); + + +extern time_t time (time_t *__timer) __attribute__ ((__nothrow__ )); + + +extern double difftime (time_t __time1, time_t __time0) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + +extern time_t mktime (struct tm *__tp) __attribute__ ((__nothrow__ )); + + + + + +extern size_t strftime (char *__restrict __s, size_t __maxsize, + const char *__restrict __format, + const struct tm *__restrict __tp) __attribute__ ((__nothrow__ )); +# 223 "/usr/include/time.h" 3 4 +extern size_t strftime_l (char *__restrict __s, size_t __maxsize, + const char *__restrict __format, + const struct tm *__restrict __tp, + __locale_t __loc) __attribute__ ((__nothrow__ )); +# 239 "/usr/include/time.h" 3 4 +extern struct tm *gmtime (const time_t *__timer) __attribute__ ((__nothrow__ )); + + + +extern struct tm *localtime (const time_t *__timer) __attribute__ ((__nothrow__ )); + + + + + +extern struct tm *gmtime_r (const time_t *__restrict __timer, + struct tm *__restrict __tp) __attribute__ ((__nothrow__ )); + + + +extern struct tm *localtime_r (const time_t *__restrict __timer, + struct tm *__restrict __tp) __attribute__ ((__nothrow__ )); + + + + + +extern char *asctime (const struct tm *__tp) __attribute__ ((__nothrow__ )); + + +extern char *ctime (const time_t *__timer) __attribute__ ((__nothrow__ )); + + + + + + + +extern char *asctime_r (const struct tm *__restrict __tp, + char *__restrict __buf) __attribute__ ((__nothrow__ )); + + +extern char *ctime_r (const time_t *__restrict __timer, + char *__restrict __buf) __attribute__ ((__nothrow__ )); + + + + +extern char *__tzname[2]; +extern int __daylight; +extern long int __timezone; + + + + +extern char *tzname[2]; + + + +extern void tzset (void) __attribute__ ((__nothrow__ )); + + + +extern int daylight; +extern long int timezone; + + + + + +extern int stime (const time_t *__when) __attribute__ ((__nothrow__ )); +# 319 "/usr/include/time.h" 3 4 +extern time_t timegm (struct tm *__tp) __attribute__ ((__nothrow__ )); + + +extern time_t timelocal (struct tm *__tp) __attribute__ ((__nothrow__ )); + + +extern int dysize (int __year) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 334 "/usr/include/time.h" 3 4 +extern int nanosleep (const struct timespec *__requested_time, + struct timespec *__remaining); + + + +extern int clock_getres (clockid_t __clock_id, struct timespec *__res) __attribute__ ((__nothrow__ )); + + +extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __attribute__ ((__nothrow__ )); + + +extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp) + __attribute__ ((__nothrow__ )); + + + + + + +extern int clock_nanosleep (clockid_t __clock_id, int __flags, + const struct timespec *__req, + struct timespec *__rem); + + +extern int clock_getcpuclockid (pid_t __pid, clockid_t *__clock_id) __attribute__ ((__nothrow__ )); + + + + +extern int timer_create (clockid_t __clock_id, + struct sigevent *__restrict __evp, + timer_t *__restrict __timerid) __attribute__ ((__nothrow__ )); + + +extern int timer_delete (timer_t __timerid) __attribute__ ((__nothrow__ )); + + +extern int timer_settime (timer_t __timerid, int __flags, + const struct itimerspec *__restrict __value, + struct itimerspec *__restrict __ovalue) __attribute__ ((__nothrow__ )); + + +extern int timer_gettime (timer_t __timerid, struct itimerspec *__value) + __attribute__ ((__nothrow__ )); + + +extern int timer_getoverrun (timer_t __timerid) __attribute__ ((__nothrow__ )); +# 25 "/usr/include/pthread.h" 2 3 4 + + +# 1 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 27 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" 2 3 4 + + + + +typedef long int __jmp_buf[8]; +# 28 "/usr/include/pthread.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 29 "/usr/include/pthread.h" 2 3 4 + + + +enum +{ + PTHREAD_CREATE_JOINABLE, + + PTHREAD_CREATE_DETACHED + +}; + + + +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP + + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL + + + + + +}; + + + + +enum +{ + PTHREAD_MUTEX_STALLED, + PTHREAD_MUTEX_STALLED_NP = PTHREAD_MUTEX_STALLED, + PTHREAD_MUTEX_ROBUST, + PTHREAD_MUTEX_ROBUST_NP = PTHREAD_MUTEX_ROBUST +}; + + + + + +enum +{ + PTHREAD_PRIO_NONE, + PTHREAD_PRIO_INHERIT, + PTHREAD_PRIO_PROTECT +}; +# 125 "/usr/include/pthread.h" 3 4 +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP +}; +# 166 "/usr/include/pthread.h" 3 4 +enum +{ + PTHREAD_INHERIT_SCHED, + + PTHREAD_EXPLICIT_SCHED + +}; + + + +enum +{ + PTHREAD_SCOPE_SYSTEM, + + PTHREAD_SCOPE_PROCESS + +}; + + + +enum +{ + PTHREAD_PROCESS_PRIVATE, + + PTHREAD_PROCESS_SHARED + +}; +# 201 "/usr/include/pthread.h" 3 4 +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); + void *__arg; + int __canceltype; + struct _pthread_cleanup_buffer *__prev; +}; + + +enum +{ + PTHREAD_CANCEL_ENABLE, + + PTHREAD_CANCEL_DISABLE + +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, + + PTHREAD_CANCEL_ASYNCHRONOUS + +}; +# 244 "/usr/include/pthread.h" 3 4 +extern int pthread_create (pthread_t *__restrict __newthread, + const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 3))); + + + + + +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + + + + + + + +extern int pthread_join (pthread_t __th, void **__thread_return); +# 282 "/usr/include/pthread.h" 3 4 +extern int pthread_detach (pthread_t __th) __attribute__ ((__nothrow__ )); + + + +extern pthread_t pthread_self (void) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + + + + + + +extern int pthread_attr_init (pthread_attr_t *__attr) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_attr_destroy (pthread_attr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_attr_getdetachstate (const pthread_attr_t *__attr, + int *__detachstate) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_attr_getguardsize (const pthread_attr_t *__attr, + size_t *__guardsize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict __attr, + struct sched_param *__restrict __param) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + const struct sched_param *__restrict + __param) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_attr_getscope (const pthread_attr_t *__restrict __attr, + int *__restrict __scope) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))) __attribute__ ((__deprecated__)); + + + + + +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) __attribute__ ((__deprecated__)); + + +extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_attr_getstack (const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2, 3))); + + + + +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 440 "/usr/include/pthread.h" 3 4 +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + const struct sched_param *__param) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3))); + + +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); + + +extern int pthread_setschedprio (pthread_t __target_thread, int __prio) + __attribute__ ((__nothrow__ )); +# 505 "/usr/include/pthread.h" 3 4 +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)) __attribute__ ((__nonnull__ (1, 2))); +# 517 "/usr/include/pthread.h" 3 4 +extern int pthread_setcancelstate (int __state, int *__oldstate); + + + +extern int pthread_setcanceltype (int __type, int *__oldtype); + + +extern int pthread_cancel (pthread_t __th); + + + + +extern void pthread_testcancel (void); + + + + +typedef struct +{ + struct + { + __jmp_buf __cancel_jmp_buf; + int __mask_was_saved; + } __cancel_jmp_buf[1]; + void *__pad[4]; +} __pthread_unwind_buf_t __attribute__ ((__aligned__)); +# 551 "/usr/include/pthread.h" 3 4 +struct __pthread_cleanup_frame +{ + void (*__cancel_routine) (void *); + void *__cancel_arg; + int __do_it; + int __cancel_type; +}; +# 691 "/usr/include/pthread.h" 3 4 +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) + ; +# 703 "/usr/include/pthread.h" 3 4 +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) + ; +# 744 "/usr/include/pthread.h" 3 4 +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) + __attribute__ ((__noreturn__)) + + __attribute__ ((__weak__)) + + ; + + + +struct __jmp_buf_tag; +extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__)); + + + + + +extern int pthread_mutex_init (pthread_mutex_t *__mutex, + const pthread_mutexattr_t *__mutexattr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + const struct timespec *__restrict + __abstime) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutex_getprioceiling (const pthread_mutex_t * + __restrict __mutex, + int *__restrict __prioceiling) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict __mutex, + int __prioceiling, + int *__restrict __old_ceiling) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 3))); + + + + +extern int pthread_mutex_consistent (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 817 "/usr/include/pthread.h" 3 4 +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutexattr_getpshared (const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutexattr_gettype (const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutexattr_getprotocol (const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __protocol) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr, + int __protocol) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __prioceiling) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *__attr, + int __prioceiling) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr, + int *__robustness) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + + + + +extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr, + int __robustness) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 899 "/usr/include/pthread.h" 3 4 +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + const pthread_rwlockattr_t *__restrict + __attr) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + const struct timespec *__restrict + __abstime) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + const struct timespec *__restrict + __abstime) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + + + +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pref) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + + +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + const pthread_condattr_t *__restrict __cond_attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_cond_destroy (pthread_cond_t *__cond) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_cond_signal (pthread_cond_t *__cond) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_cond_broadcast (pthread_cond_t *__cond) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex) + __attribute__ ((__nonnull__ (1, 2))); +# 1011 "/usr/include/pthread.h" 3 4 +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + const struct timespec *__restrict __abstime) + __attribute__ ((__nonnull__ (1, 2, 3))); + + + + +extern int pthread_condattr_init (pthread_condattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_condattr_getpshared (const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_condattr_getclock (const pthread_condattr_t * + __restrict __attr, + __clockid_t *__restrict __clock_id) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_condattr_setclock (pthread_condattr_t *__attr, + __clockid_t __clock_id) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 1055 "/usr/include/pthread.h" 3 4 +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_spin_lock (pthread_spinlock_t *__lock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 1122 "/usr/include/pthread.h" 3 4 +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_key_delete (pthread_key_t __key) __attribute__ ((__nothrow__ )); + + +extern void *pthread_getspecific (pthread_key_t __key) __attribute__ ((__nothrow__ )); + + +extern int pthread_setspecific (pthread_key_t __key, + const void *__pointer) __attribute__ ((__nothrow__ )) ; + + + + +extern int pthread_getcpuclockid (pthread_t __thread_id, + __clockid_t *__clock_id) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); +# 1156 "/usr/include/pthread.h" 3 4 +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __attribute__ ((__nothrow__ )); +# 48 "../include/apr_portable.h" 2 +# 127 "../include/apr_portable.h" +struct apr_os_proc_mutex_t { + + + int crossproc; + + + + pthread_mutex_t *pthread_interproc; + + + + + + pthread_mutex_t *intraproc; + + +}; + +typedef int apr_os_file_t; +typedef DIR apr_os_dir_t; +typedef int apr_os_sock_t; +typedef struct apr_os_proc_mutex_t apr_os_proc_mutex_t; + + + +typedef pthread_t apr_os_thread_t; +typedef pthread_key_t apr_os_threadkey_t; + + +typedef pid_t apr_os_proc_t; +typedef struct timeval apr_os_imp_time_t; +typedef struct tm apr_os_exp_time_t; +# 169 "../include/apr_portable.h" +typedef void * apr_os_dso_handle_t; + +typedef void* apr_os_shm_t; +# 183 "../include/apr_portable.h" +struct apr_os_sock_info_t { + apr_os_sock_t *os_sock; + struct sockaddr *local; + struct sockaddr *remote; + int family; + int type; + int protocol; +}; + +typedef struct apr_os_sock_info_t apr_os_sock_info_t; +# 203 "../include/apr_portable.h" + struct apr_os_global_mutex_t { + apr_pool_t *pool; + apr_proc_mutex_t *proc_mutex; + + apr_thread_mutex_t *thread_mutex; + + }; + typedef struct apr_os_global_mutex_t apr_os_global_mutex_t; + +apr_status_t apr_os_global_mutex_get(apr_os_global_mutex_t *ospmutex, + apr_global_mutex_t *pmutex); +# 224 "../include/apr_portable.h" +apr_status_t apr_os_file_get(apr_os_file_t *thefile, + apr_file_t *file); + + + + + + +apr_status_t apr_os_dir_get(apr_os_dir_t **thedir, + apr_dir_t *dir); + + + + + + +apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, + apr_socket_t *sock); + + + + + + +apr_status_t apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex); + + + + + + +apr_status_t apr_os_exp_time_get(apr_os_exp_time_t **ostime, + apr_time_exp_t *aprtime); + + + + + + +apr_status_t apr_os_imp_time_get(apr_os_imp_time_t **ostime, + apr_time_t *aprtime); + + + + + + +apr_status_t apr_os_shm_get(apr_os_shm_t *osshm, + apr_shm_t *shm); +# 285 "../include/apr_portable.h" +apr_status_t apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd); + + + + + + +apr_status_t apr_os_threadkey_get(apr_os_threadkey_t *thekey, + apr_threadkey_t *key); + + + + + + + +apr_status_t apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, + apr_pool_t *cont); + + + +apr_os_thread_t apr_os_thread_current(void); + + + + + + + +int apr_os_thread_equal(apr_os_thread_t tid1, + apr_os_thread_t tid2); +# 341 "../include/apr_portable.h" +apr_status_t apr_os_file_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_int32_t flags, apr_pool_t *cont); +# 353 "../include/apr_portable.h" +apr_status_t apr_os_pipe_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_pool_t *cont); +# 367 "../include/apr_portable.h" +apr_status_t apr_os_pipe_put_ex(apr_file_t **file, + apr_os_file_t *thefile, + int register_cleanup, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_dir_put(apr_dir_t **dir, + apr_os_dir_t *thedir, + apr_pool_t *cont); +# 390 "../include/apr_portable.h" +apr_status_t apr_os_sock_put(apr_socket_t **sock, + apr_os_sock_t *thesock, + apr_pool_t *cont); +# 404 "../include/apr_portable.h" +apr_status_t apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_imp_time_put(apr_time_t *aprtime, + apr_os_imp_time_t **ostime, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_exp_time_put(apr_time_exp_t *aprtime, + apr_os_exp_time_t **ostime, + apr_pool_t *cont); +# 447 "../include/apr_portable.h" +apr_status_t apr_os_shm_put(apr_shm_t **shm, + apr_os_shm_t *osshm, + apr_pool_t *cont); +# 463 "../include/apr_portable.h" +apr_status_t apr_os_dso_handle_put(apr_dso_handle_t **dso, + apr_os_dso_handle_t thedso, + apr_pool_t *pool); + + + + + + +apr_status_t apr_os_dso_handle_get(apr_os_dso_handle_t *dso, + apr_dso_handle_t *aprdso); +# 491 "../include/apr_portable.h" +const char* apr_os_default_encoding(apr_pool_t *pool); +# 500 "../include/apr_portable.h" +const char* apr_os_locale_encoding(apr_pool_t *pool); +# 25 "../include/arch/unix/apr_arch_thread_mutex.h" 2 + + + + + + + +struct apr_thread_mutex_t { + apr_pool_t *pool; + pthread_mutex_t mutex; +}; +# 18 "./../locks/unix/thread_mutex.c" 2 + +# 1 "../include/apr_want.h" 1 +# 20 "./../locks/unix/thread_mutex.c" 2 + + + +static apr_status_t thread_mutex_cleanup(void *data) +{ + apr_thread_mutex_t *mutex = data; + apr_status_t rv; + + rv = pthread_mutex_destroy(&mutex->mutex); + + + + + + return rv; +} + +apr_status_t apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool) +{ + apr_thread_mutex_t *new_mutex; + apr_status_t rv; + + + + + + + + new_mutex = memset(apr_palloc(pool, sizeof(apr_thread_mutex_t)), 0, sizeof(apr_thread_mutex_t)); + new_mutex->pool = pool; + + + if (flags & 0x1) { + pthread_mutexattr_t mattr; + + rv = pthread_mutexattr_init(&mattr); + if (rv) return rv; + + rv = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); + if (rv) { + pthread_mutexattr_destroy(&mattr); + return rv; + } + + rv = pthread_mutex_init(&new_mutex->mutex, &mattr); + + pthread_mutexattr_destroy(&mattr); + } else + + rv = pthread_mutex_init(&new_mutex->mutex, ((void*)0)); + + if (rv) { + + + + return rv; + } + + apr_pool_cleanup_register(new_mutex->pool, + new_mutex, thread_mutex_cleanup, + apr_pool_cleanup_null); + + *mutex = new_mutex; + return 0; +} + +apr_status_t apr_thread_mutex_lock(apr_thread_mutex_t *mutex) +{ + apr_status_t rv; + + rv = pthread_mutex_lock(&mutex->mutex); + + + + + + + return rv; +} + +apr_status_t apr_thread_mutex_trylock(apr_thread_mutex_t *mutex) +{ + apr_status_t rv; + + rv = pthread_mutex_trylock(&mutex->mutex); + if (rv) { + + + + return (rv == 16) ? ((20000 + 50000) + 25) : rv; + } + + return 0; +} + +apr_status_t apr_thread_mutex_unlock(apr_thread_mutex_t *mutex) +{ + apr_status_t status; + + status = pthread_mutex_unlock(&mutex->mutex); + + + + + + + return status; +} + +apr_status_t apr_thread_mutex_destroy(apr_thread_mutex_t *mutex) +{ + return apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup); +} + +apr_pool_t * apr_thread_mutex_pool_get (const apr_thread_mutex_t *thethread_mutex) { return thethread_mutex->pool; } +# 13 "main1.c" 2 +# 1 "./../locks/unix/proc_mutex.c" 1 +# 19 "./../locks/unix/proc_mutex.c" +# 1 "../include/arch/unix/apr_arch_proc_mutex.h" 1 +# 23 "../include/arch/unix/apr_arch_proc_mutex.h" +# 1 "../include/apr_lib.h" 1 +# 32 "../include/apr_lib.h" +# 1 "/usr/include/ctype.h" 1 3 4 +# 46 "/usr/include/ctype.h" 3 4 +enum +{ + _ISupper = ((0) < 8 ? ((1 << (0)) << 8) : ((1 << (0)) >> 8)), + _ISlower = ((1) < 8 ? ((1 << (1)) << 8) : ((1 << (1)) >> 8)), + _ISalpha = ((2) < 8 ? ((1 << (2)) << 8) : ((1 << (2)) >> 8)), + _ISdigit = ((3) < 8 ? ((1 << (3)) << 8) : ((1 << (3)) >> 8)), + _ISxdigit = ((4) < 8 ? ((1 << (4)) << 8) : ((1 << (4)) >> 8)), + _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)), + _ISprint = ((6) < 8 ? ((1 << (6)) << 8) : ((1 << (6)) >> 8)), + _ISgraph = ((7) < 8 ? ((1 << (7)) << 8) : ((1 << (7)) >> 8)), + _ISblank = ((8) < 8 ? ((1 << (8)) << 8) : ((1 << (8)) >> 8)), + _IScntrl = ((9) < 8 ? ((1 << (9)) << 8) : ((1 << (9)) >> 8)), + _ISpunct = ((10) < 8 ? ((1 << (10)) << 8) : ((1 << (10)) >> 8)), + _ISalnum = ((11) < 8 ? ((1 << (11)) << 8) : ((1 << (11)) >> 8)) +}; +# 79 "/usr/include/ctype.h" 3 4 +extern const unsigned short int **__ctype_b_loc (void) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern const __int32_t **__ctype_tolower_loc (void) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern const __int32_t **__ctype_toupper_loc (void) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 110 "/usr/include/ctype.h" 3 4 +extern int isalnum (int) __attribute__ ((__nothrow__ )); +extern int isalpha (int) __attribute__ ((__nothrow__ )); +extern int iscntrl (int) __attribute__ ((__nothrow__ )); +extern int isdigit (int) __attribute__ ((__nothrow__ )); +extern int islower (int) __attribute__ ((__nothrow__ )); +extern int isgraph (int) __attribute__ ((__nothrow__ )); +extern int isprint (int) __attribute__ ((__nothrow__ )); +extern int ispunct (int) __attribute__ ((__nothrow__ )); +extern int isspace (int) __attribute__ ((__nothrow__ )); +extern int isupper (int) __attribute__ ((__nothrow__ )); +extern int isxdigit (int) __attribute__ ((__nothrow__ )); + + + +extern int tolower (int __c) __attribute__ ((__nothrow__ )); + + +extern int toupper (int __c) __attribute__ ((__nothrow__ )); +# 136 "/usr/include/ctype.h" 3 4 +extern int isblank (int) __attribute__ ((__nothrow__ )); +# 150 "/usr/include/ctype.h" 3 4 +extern int isascii (int __c) __attribute__ ((__nothrow__ )); + + + +extern int toascii (int __c) __attribute__ ((__nothrow__ )); + + + +extern int _toupper (int) __attribute__ ((__nothrow__ )); +extern int _tolower (int) __attribute__ ((__nothrow__ )); +# 271 "/usr/include/ctype.h" 3 4 +extern int isalnum_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isalpha_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int iscntrl_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isdigit_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int islower_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isgraph_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isprint_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int ispunct_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isspace_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isupper_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isxdigit_l (int, __locale_t) __attribute__ ((__nothrow__ )); + +extern int isblank_l (int, __locale_t) __attribute__ ((__nothrow__ )); + + + +extern int __tolower_l (int __c, __locale_t __l) __attribute__ ((__nothrow__ )); +extern int tolower_l (int __c, __locale_t __l) __attribute__ ((__nothrow__ )); + + +extern int __toupper_l (int __c, __locale_t __l) __attribute__ ((__nothrow__ )); +extern int toupper_l (int __c, __locale_t __l) __attribute__ ((__nothrow__ )); +# 33 "../include/apr_lib.h" 2 +# 59 "../include/apr_lib.h" +typedef struct apr_vformatter_buff_t apr_vformatter_buff_t; + + + + +struct apr_vformatter_buff_t { + + char *curpos; + + char *endpos; +}; +# 84 "../include/apr_lib.h" +const char * apr_filepath_name_get(const char *pathname); +# 174 "../include/apr_lib.h" +int apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *b), + apr_vformatter_buff_t *c, const char *fmt, + va_list ap); +# 189 "../include/apr_lib.h" +apr_status_t apr_password_get(const char *prompt, char *pwbuf, + apr_size_t *bufsize); +# 24 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + + + +# 1 "../include/arch/unix/apr_arch_file_io.h" 1 +# 41 "../include/arch/unix/apr_arch_file_io.h" +# 1 "/usr/include/errno.h" 1 3 4 +# 42 "../include/arch/unix/apr_arch_file_io.h" 2 + + + + + +# 1 "/usr/include/strings.h" 1 3 4 +# 48 "../include/arch/unix/apr_arch_file_io.h" 2 + + + + + +# 1 "/usr/include/x86_64-linux-gnu/sys/stat.h" 1 3 4 +# 105 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/stat.h" 1 3 4 +# 106 "/usr/include/x86_64-linux-gnu/sys/stat.h" 2 3 4 +# 209 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int stat (const char *__restrict __file, + struct stat *__restrict __buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int fstat (int __fd, struct stat *__buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); +# 238 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int fstatat (int __fd, const char *__restrict __file, + struct stat *__restrict __buf, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); +# 263 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int lstat (const char *__restrict __file, + struct stat *__restrict __buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +# 284 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int chmod (const char *__file, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int lchmod (const char *__file, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + +extern int fchmod (int __fd, __mode_t __mode) __attribute__ ((__nothrow__ )); + + + + + +extern int fchmodat (int __fd, const char *__file, __mode_t __mode, + int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))) ; + + + + + + +extern __mode_t umask (__mode_t __mask) __attribute__ ((__nothrow__ )); +# 321 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int mkdir (const char *__path, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int mkdirat (int __fd, const char *__path, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + + + +extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int mknodat (int __fd, const char *__path, __mode_t __mode, + __dev_t __dev) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + + +extern int mkfifo (const char *__path, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int mkfifoat (int __fd, const char *__path, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + + +extern int utimensat (int __fd, const char *__path, + const struct timespec __times[2], + int __flags) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + +extern int futimens (int __fd, const struct timespec __times[2]) __attribute__ ((__nothrow__ )); +# 399 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int __fxstat (int __ver, int __fildes, struct stat *__stat_buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3))); +extern int __xstat (int __ver, const char *__filename, + struct stat *__stat_buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); +extern int __lxstat (int __ver, const char *__filename, + struct stat *__stat_buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); +extern int __fxstatat (int __ver, int __fildes, const char *__filename, + struct stat *__stat_buf, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))); +# 442 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int __xmknod (int __ver, const char *__path, __mode_t __mode, + __dev_t *__dev) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))); + +extern int __xmknodat (int __ver, int __fd, const char *__path, + __mode_t __mode, __dev_t *__dev) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 5))); +# 54 "../include/arch/unix/apr_arch_file_io.h" 2 +# 75 "../include/arch/unix/apr_arch_file_io.h" +# 1 "/usr/include/x86_64-linux-gnu/sys/param.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/sys/param.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/sys/param.h" 2 3 4 + + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/param.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/param.h" 3 4 +# 1 "/usr/include/linux/param.h" 1 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/asm/param.h" 1 3 4 +# 1 "/usr/include/asm-generic/param.h" 1 3 4 +# 2 "/usr/include/x86_64-linux-gnu/asm/param.h" 2 3 4 +# 5 "/usr/include/linux/param.h" 2 3 4 +# 29 "/usr/include/x86_64-linux-gnu/bits/param.h" 2 3 4 +# 32 "/usr/include/x86_64-linux-gnu/sys/param.h" 2 3 4 +# 76 "../include/arch/unix/apr_arch_file_io.h" 2 +# 93 "../include/arch/unix/apr_arch_file_io.h" +struct apr_file_t { + apr_pool_t *pool; + int filedes; + char *fname; + apr_int32_t flags; + int eof_hit; + int is_pipe; + apr_interval_time_t timeout; + int buffered; + enum {BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking; + int ungetchar; + + + + + + char *buffer; + apr_size_t bufpos; + apr_size_t bufsize; + unsigned long dataRead; + int direction; + apr_off_t filePtr; + + struct apr_thread_mutex_t *thlock; + +}; +# 142 "../include/arch/unix/apr_arch_file_io.h" +typedef struct stat struct_stat; +# 151 "../include/arch/unix/apr_arch_file_io.h" +struct apr_dir_t { + apr_pool_t *pool; + char *dirname; + DIR *dirstruct; + + + + struct dirent *entry; + +}; + +apr_status_t apr_unix_file_cleanup(void *); +apr_status_t apr_unix_child_file_cleanup(void *); + +mode_t apr_unix_perms2mode(apr_fileperms_t perms); +apr_fileperms_t apr_unix_mode2perms(mode_t mode); + +apr_status_t apr_file_flush_locked(apr_file_t *thefile); +apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted, + apr_file_t *thefile); +# 29 "../include/arch/unix/apr_arch_proc_mutex.h" 2 +# 42 "../include/arch/unix/apr_arch_proc_mutex.h" +# 1 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/ipctypes.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/ipctypes.h" 3 4 +typedef int __ipc_pid_t; +# 29 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/ipc.h" 1 3 4 +# 42 "/usr/include/x86_64-linux-gnu/bits/ipc.h" 3 4 +struct ipc_perm + { + __key_t __key; + __uid_t uid; + __gid_t gid; + __uid_t cuid; + __gid_t cgid; + unsigned short int mode; + unsigned short int __pad1; + unsigned short int __seq; + unsigned short int __pad2; + __syscall_ulong_t __glibc_reserved1; + __syscall_ulong_t __glibc_reserved2; + }; +# 30 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 2 3 4 +# 54 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 3 4 +extern key_t ftok (const char *__pathname, int __proj_id) __attribute__ ((__nothrow__ )); +# 43 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + +# 1 "/usr/include/x86_64-linux-gnu/sys/sem.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/sys/sem.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/sys/sem.h" 2 3 4 + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sem.h" 1 3 4 +# 38 "/usr/include/x86_64-linux-gnu/bits/sem.h" 3 4 +struct semid_ds +{ + struct ipc_perm sem_perm; + __time_t sem_otime; + __syscall_ulong_t __glibc_reserved1; + __time_t sem_ctime; + __syscall_ulong_t __glibc_reserved2; + __syscall_ulong_t sem_nsems; + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +# 72 "/usr/include/x86_64-linux-gnu/bits/sem.h" 3 4 +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; +# 31 "/usr/include/x86_64-linux-gnu/sys/sem.h" 2 3 4 +# 41 "/usr/include/x86_64-linux-gnu/sys/sem.h" 3 4 +struct sembuf +{ + unsigned short int sem_num; + short int sem_op; + short int sem_flg; +}; + + + + + +extern int semctl (int __semid, int __semnum, int __cmd, ...) __attribute__ ((__nothrow__ )); + + +extern int semget (key_t __key, int __nsems, int __semflg) __attribute__ ((__nothrow__ )); + + +extern int semop (int __semid, struct sembuf *__sops, size_t __nsops) __attribute__ ((__nothrow__ )); +# 46 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + +# 1 "/usr/include/x86_64-linux-gnu/sys/file.h" 1 3 4 +# 50 "/usr/include/x86_64-linux-gnu/sys/file.h" 3 4 +extern int flock (int __fd, int __operation) __attribute__ ((__nothrow__ )); +# 49 "../include/arch/unix/apr_arch_proc_mutex.h" 2 +# 60 "../include/arch/unix/apr_arch_proc_mutex.h" +# 1 "/usr/include/x86_64-linux-gnu/sys/mman.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/sys/mman.h" 2 3 4 +# 41 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/mman.h" 1 3 4 +# 45 "/usr/include/x86_64-linux-gnu/bits/mman.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/mman-linux.h" 1 3 4 +# 46 "/usr/include/x86_64-linux-gnu/bits/mman.h" 2 3 4 +# 42 "/usr/include/x86_64-linux-gnu/sys/mman.h" 2 3 4 +# 57 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +extern void *mmap (void *__addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset) __attribute__ ((__nothrow__ )); +# 76 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +extern int munmap (void *__addr, size_t __len) __attribute__ ((__nothrow__ )); + + + + +extern int mprotect (void *__addr, size_t __len, int __prot) __attribute__ ((__nothrow__ )); + + + + + + + +extern int msync (void *__addr, size_t __len, int __flags); + + + + +extern int madvise (void *__addr, size_t __len, int __advice) __attribute__ ((__nothrow__ )); + + + +extern int posix_madvise (void *__addr, size_t __len, int __advice) __attribute__ ((__nothrow__ )); + + + + +extern int mlock (const void *__addr, size_t __len) __attribute__ ((__nothrow__ )); + + +extern int munlock (const void *__addr, size_t __len) __attribute__ ((__nothrow__ )); + + + + +extern int mlockall (int __flags) __attribute__ ((__nothrow__ )); + + + +extern int munlockall (void) __attribute__ ((__nothrow__ )); + + + + + + + +extern int mincore (void *__start, size_t __len, unsigned char *__vec) + __attribute__ ((__nothrow__ )); +# 144 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +extern int shm_open (const char *__name, int __oflag, mode_t __mode); + + +extern int shm_unlink (const char *__name); +# 61 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + + + + +# 1 "/usr/include/semaphore.h" 1 3 4 +# 29 "/usr/include/semaphore.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/semaphore.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/bits/semaphore.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/semaphore.h" 2 3 4 +# 36 "/usr/include/x86_64-linux-gnu/bits/semaphore.h" 3 4 +typedef union +{ + char __size[32]; + long int __align; +} sem_t; +# 30 "/usr/include/semaphore.h" 2 3 4 + + + + + + +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) + __attribute__ ((__nothrow__ )); + +extern int sem_destroy (sem_t *__sem) __attribute__ ((__nothrow__ )); + + +extern sem_t *sem_open (const char *__name, int __oflag, ...) __attribute__ ((__nothrow__ )); + + +extern int sem_close (sem_t *__sem) __attribute__ ((__nothrow__ )); + + +extern int sem_unlink (const char *__name) __attribute__ ((__nothrow__ )); + + + + + +extern int sem_wait (sem_t *__sem); + + + + + + +extern int sem_timedwait (sem_t *__restrict __sem, + const struct timespec *__restrict __abstime); + + + +extern int sem_trywait (sem_t *__sem) __attribute__ ((__nothrow__)); + + +extern int sem_post (sem_t *__sem) __attribute__ ((__nothrow__)); + + +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __attribute__ ((__nothrow__ )); +# 67 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + + +struct apr_proc_mutex_unix_lock_methods_t { + unsigned int flags; + apr_status_t (*create)(apr_proc_mutex_t *, const char *); + apr_status_t (*acquire)(apr_proc_mutex_t *); + apr_status_t (*tryacquire)(apr_proc_mutex_t *); + apr_status_t (*release)(apr_proc_mutex_t *); + apr_status_t (*cleanup)(void *); + apr_status_t (*child_init)(apr_proc_mutex_t **, apr_pool_t *, const char *); + const char *name; +}; +typedef struct apr_proc_mutex_unix_lock_methods_t apr_proc_mutex_unix_lock_methods_t; + + + + + +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; +}; + + +struct apr_proc_mutex_t { + apr_pool_t *pool; + const apr_proc_mutex_unix_lock_methods_t *meth; + const apr_proc_mutex_unix_lock_methods_t *inter_meth; + int curr_locked; + char *fname; + + apr_file_t *interproc; + + + sem_t *psem_interproc; + + + pthread_mutex_t *pthread_interproc; + +}; + +void apr_proc_mutex_unix_setup_lock(void); +# 20 "./../locks/unix/proc_mutex.c" 2 + +# 1 "../include/apr_hash.h" 1 +# 52 "../include/apr_hash.h" +typedef struct apr_hash_t apr_hash_t; + + + + +typedef struct apr_hash_index_t apr_hash_index_t; + + + + + + + +typedef unsigned int (*apr_hashfunc_t)(const char *key, apr_ssize_t *klen); + + + + +unsigned int apr_hashfunc_default(const char *key, + apr_ssize_t *klen); + + + + + + +apr_hash_t * apr_hash_make(apr_pool_t *pool); + + + + + + + +apr_hash_t * apr_hash_make_custom(apr_pool_t *pool, + apr_hashfunc_t hash_func); +# 96 "../include/apr_hash.h" +apr_hash_t * apr_hash_copy(apr_pool_t *pool, + const apr_hash_t *h); +# 107 "../include/apr_hash.h" +void apr_hash_set(apr_hash_t *ht, const void *key, + apr_ssize_t klen, const void *val); +# 117 "../include/apr_hash.h" +void * apr_hash_get(apr_hash_t *ht, const void *key, + apr_ssize_t klen); +# 147 "../include/apr_hash.h" +apr_hash_index_t * apr_hash_first(apr_pool_t *p, apr_hash_t *ht); + + + + + + + +apr_hash_index_t * apr_hash_next(apr_hash_index_t *hi); +# 166 "../include/apr_hash.h" +void apr_hash_this(apr_hash_index_t *hi, const void **key, + apr_ssize_t *klen, void **val); + + + + + + +const void* apr_hash_this_key(apr_hash_index_t *hi); + + + + + + +apr_ssize_t apr_hash_this_key_len(apr_hash_index_t *hi); + + + + + + +void* apr_hash_this_val(apr_hash_index_t *hi); + + + + + + +unsigned int apr_hash_count(apr_hash_t *ht); + + + + + +void apr_hash_clear(apr_hash_t *ht); +# 212 "../include/apr_hash.h" +apr_hash_t * apr_hash_overlay(apr_pool_t *p, + const apr_hash_t *overlay, + const apr_hash_t *base); +# 230 "../include/apr_hash.h" +apr_hash_t * apr_hash_merge(apr_pool_t *p, + const apr_hash_t *h1, + const apr_hash_t *h2, + void * (*merger)(apr_pool_t *p, + const void *key, + apr_ssize_t klen, + const void *h1_val, + const void *h2_val, + const void *data), + const void *data); +# 252 "../include/apr_hash.h" +typedef int (apr_hash_do_callback_fn_t)(void *rec, const void *key, + apr_ssize_t klen, + const void *value); +# 268 "../include/apr_hash.h" +int apr_hash_do(apr_hash_do_callback_fn_t *comp, + void *rec, const apr_hash_t *ht); + + + + +apr_pool_t * apr_hash_pool_get (const apr_hash_t *thehash); +# 22 "./../locks/unix/proc_mutex.c" 2 + +apr_status_t apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) +{ + return apr_pool_cleanup_run(mutex->pool, mutex, apr_proc_mutex_cleanup); +} + + + +static apr_status_t proc_mutex_no_child_init(apr_proc_mutex_t **mutex, + apr_pool_t *cont, + const char *fname) +{ + return 0; +} +# 44 "./../locks/unix/proc_mutex.c" +static apr_status_t proc_mutex_posix_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex = mutex_; + + if (sem_close(mutex->psem_interproc) < 0) { + return (*__errno_location ()); + } + + return 0; +} + +static unsigned int rshash (char *p) { + + unsigned int b = 378551; + unsigned int a = 63689; + unsigned int retval = 0; + + for( ; *p; p++) + { + retval = retval * a + (*p); + a *= b; + } + + return retval; +} + +static apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + + sem_t *psem; + char semname[32]; + + new_mutex->interproc = apr_palloc(new_mutex->pool, + sizeof(*new_mutex->interproc)); +# 101 "./../locks/unix/proc_mutex.c" + if (fname) { + apr_ssize_t flen = strlen(fname); + char *p = apr_pstrndup(new_mutex->pool, fname, strlen(fname)); + unsigned int h1, h2; + h1 = (apr_hashfunc_default((const char *)p, &flen) & 0xffffffff); + h2 = (rshash(p) & 0xffffffff); + apr_snprintf(semname, sizeof(semname), "/ApR.%xH%x", h1, h2); + } else { + apr_time_t now; + unsigned long sec; + unsigned long usec; + now = apr_time_now(); + sec = ((now) / 1000000L); + usec = ((now) % 1000000L); + apr_snprintf(semname, sizeof(semname), "/ApR.%lxZ%lx", sec, usec); + } + psem = sem_open(semname, 0100 | 0200, 0644, 1); + if (psem == (sem_t *)((sem_t *) 0)) { + if ((*__errno_location ()) == 36) { + + semname[13] = '\0'; + } else { + return (*__errno_location ()); + } + psem = sem_open(semname, 0100 | 0200, 0644, 1); + } + + if (psem == (sem_t *)((sem_t *) 0)) { + return (*__errno_location ()); + } + + sem_unlink(semname); + new_mutex->psem_interproc = psem; + new_mutex->fname = apr_pstrdup(new_mutex->pool, semname); + apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_posix_acquire(apr_proc_mutex_t *mutex) +{ + if (sem_wait(mutex->psem_interproc) < 0) { + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_posix_tryacquire(apr_proc_mutex_t *mutex) +{ + if (sem_trywait(mutex->psem_interproc) < 0) { + if ((*__errno_location ()) == 11) { + return ((20000 + 50000) + 25); + } + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_posix_release(apr_proc_mutex_t *mutex) +{ + mutex->curr_locked = 0; + if (sem_post(mutex->psem_interproc) < 0) { + + + return (*__errno_location ()); + } + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_posixsem_methods = +{ + + + + 0, + + proc_mutex_posix_create, + proc_mutex_posix_acquire, + proc_mutex_posix_tryacquire, + proc_mutex_posix_release, + proc_mutex_posix_cleanup, + proc_mutex_no_child_init, + "posixsem" +}; + + + + + +static struct sembuf proc_mutex_op_on; +static struct sembuf proc_mutex_op_try; +static struct sembuf proc_mutex_op_off; + +static void proc_mutex_sysv_setup(void) +{ + proc_mutex_op_on.sem_num = 0; + proc_mutex_op_on.sem_op = -1; + proc_mutex_op_on.sem_flg = 0x1000; + proc_mutex_op_try.sem_num = 0; + proc_mutex_op_try.sem_op = -1; + proc_mutex_op_try.sem_flg = 0x1000 | 04000; + proc_mutex_op_off.sem_num = 0; + proc_mutex_op_off.sem_op = 1; + proc_mutex_op_off.sem_flg = 0x1000; +} + +static apr_status_t proc_mutex_sysv_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex=mutex_; + union semun ick; + + if (mutex->interproc->filedes != -1) { + ick.val = 0; + semctl(mutex->interproc->filedes, 0, 0, ick); + } + return 0; +} + +static apr_status_t proc_mutex_sysv_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + union semun ick; + apr_status_t rv; + + new_mutex->interproc = apr_palloc(new_mutex->pool, sizeof(*new_mutex->interproc)); + new_mutex->interproc->filedes = semget(((__key_t) 0), 1, 01000 | 0600); + + if (new_mutex->interproc->filedes < 0) { + rv = (*__errno_location ()); + proc_mutex_sysv_cleanup(new_mutex); + return rv; + } + ick.val = 1; + if (semctl(new_mutex->interproc->filedes, 0, 16, ick) < 0) { + rv = (*__errno_location ()); + proc_mutex_sysv_cleanup(new_mutex); + return rv; + } + new_mutex->curr_locked = 0; + apr_pool_cleanup_register(new_mutex->pool, + (void *)new_mutex, apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_sysv_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = semop(mutex->interproc->filedes, &proc_mutex_op_on, 1); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_sysv_tryacquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = semop(mutex->interproc->filedes, &proc_mutex_op_try, 1); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + if ((*__errno_location ()) == 11) { + return ((20000 + 50000) + 25); + } + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_sysv_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked = 0; + do { + rc = semop(mutex->interproc->filedes, &proc_mutex_op_off, 1); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_sysv_methods = +{ + + + + 0, + + proc_mutex_sysv_create, + proc_mutex_sysv_acquire, + proc_mutex_sysv_tryacquire, + proc_mutex_sysv_release, + proc_mutex_sysv_cleanup, + proc_mutex_no_child_init, + "sysvsem" +}; + + + + + +static apr_status_t proc_mutex_proc_pthread_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex=mutex_; + apr_status_t rv; + + if (mutex->curr_locked == 1) { + if ((rv = pthread_mutex_unlock(mutex->pthread_interproc))) { + + + + return rv; + } + } + + if (mutex->curr_locked != -1) { + if ((rv = pthread_mutex_destroy(mutex->pthread_interproc))) { + + + + return rv; + } + } + if (munmap((caddr_t)mutex->pthread_interproc, sizeof(pthread_mutex_t))) { + return (*__errno_location ()); + } + return 0; +} + +static apr_status_t proc_mutex_proc_pthread_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + apr_status_t rv; + int fd; + pthread_mutexattr_t mattr; + + fd = open("/dev/zero", 02); + if (fd < 0) { + return (*__errno_location ()); + } + + new_mutex->pthread_interproc = (pthread_mutex_t *)mmap( + (caddr_t) 0, + sizeof(pthread_mutex_t), + 0x1 | 0x2, 0x01, + fd, 0); + if (new_mutex->pthread_interproc == (pthread_mutex_t *) (caddr_t) -1) { + close(fd); + return (*__errno_location ()); + } + close(fd); + + new_mutex->curr_locked = -1; + + if ((rv = pthread_mutexattr_init(&mattr))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + return rv; + } + if ((rv = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + + + if ((rv = pthread_mutexattr_setrobust_np(&mattr, + PTHREAD_MUTEX_ROBUST_NP))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + if ((rv = pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + + + if ((rv = pthread_mutex_init(new_mutex->pthread_interproc, &mattr))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + + new_mutex->curr_locked = 0; + + if ((rv = pthread_mutexattr_destroy(&mattr))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + return rv; + } + + apr_pool_cleanup_register(new_mutex->pool, + (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_proc_pthread_acquire(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + if ((rv = pthread_mutex_lock(mutex->pthread_interproc))) { + + + + + + if (rv == 130) { + pthread_mutex_consistent_np(mutex->pthread_interproc); + } + else + return rv; + + + + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_proc_pthread_tryacquire(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + if ((rv = pthread_mutex_trylock(mutex->pthread_interproc))) { + + + + if (rv == 16) { + return ((20000 + 50000) + 25); + } + + + if (rv == 130) { + pthread_mutex_consistent_np(mutex->pthread_interproc); + rv = 0; + } + else + return rv; + + + + } + mutex->curr_locked = 1; + return rv; +} + +static apr_status_t proc_mutex_proc_pthread_release(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + mutex->curr_locked = 0; + if ((rv = pthread_mutex_unlock(mutex->pthread_interproc))) { + + + + return rv; + } + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_methods = +{ + 1, + proc_mutex_proc_pthread_create, + proc_mutex_proc_pthread_acquire, + proc_mutex_proc_pthread_tryacquire, + proc_mutex_proc_pthread_release, + proc_mutex_proc_pthread_cleanup, + proc_mutex_no_child_init, + "pthread" +}; + + + + + +static struct flock proc_mutex_lock_it; +static struct flock proc_mutex_unlock_it; + +static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *); + +static void proc_mutex_fcntl_setup(void) +{ + proc_mutex_lock_it.l_whence = 0; + proc_mutex_lock_it.l_start = 0; + proc_mutex_lock_it.l_len = 0; + proc_mutex_lock_it.l_type = 1; + proc_mutex_lock_it.l_pid = 0; + proc_mutex_unlock_it.l_whence = 0; + proc_mutex_unlock_it.l_start = 0; + proc_mutex_unlock_it.l_len = 0; + proc_mutex_unlock_it.l_type = 2; + proc_mutex_unlock_it.l_pid = 0; +} + +static apr_status_t proc_mutex_fcntl_cleanup(void *mutex_) +{ + apr_status_t status; + apr_proc_mutex_t *mutex=mutex_; + + if (mutex->curr_locked == 1) { + status = proc_mutex_fcntl_release(mutex); + if (status != 0) + return status; + } + + return apr_file_close(mutex->interproc); +} + +static apr_status_t proc_mutex_fcntl_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + int rv; + + if (fname) { + new_mutex->fname = apr_pstrdup(new_mutex->pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + 0x00004 | 0x00002 | 0x00040, + 0x0400 | 0x0200 | 0x0040 | 0x0004, + new_mutex->pool); + } + else { + new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX"); + rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname, + 0x00004 | 0x00002 | 0x00040, + new_mutex->pool); + } + + if (rv != 0) { + return rv; + } + + new_mutex->curr_locked = 0; + unlink(new_mutex->fname); + apr_pool_cleanup_register(new_mutex->pool, + (void*)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_fcntl_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = fcntl(mutex->interproc->filedes, 7, &proc_mutex_lock_it); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + mutex->curr_locked=1; + return 0; +} + +static apr_status_t proc_mutex_fcntl_tryacquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = fcntl(mutex->interproc->filedes, 6, &proc_mutex_lock_it); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + + + + if ((*__errno_location ()) == 11) { + + return ((20000 + 50000) + 25); + } + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked=0; + do { + rc = fcntl(mutex->interproc->filedes, 7, &proc_mutex_unlock_it); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_fcntl_methods = +{ + + + + 0, + + proc_mutex_fcntl_create, + proc_mutex_fcntl_acquire, + proc_mutex_fcntl_tryacquire, + proc_mutex_fcntl_release, + proc_mutex_fcntl_cleanup, + proc_mutex_no_child_init, + "fcntl" +}; + + + + + +static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *); + +static apr_status_t proc_mutex_flock_cleanup(void *mutex_) +{ + apr_status_t status; + apr_proc_mutex_t *mutex=mutex_; + + if (mutex->curr_locked == 1) { + status = proc_mutex_flock_release(mutex); + if (status != 0) + return status; + } + if (mutex->interproc) { + apr_file_close(mutex->interproc); + } + unlink(mutex->fname); + return 0; +} + +static apr_status_t proc_mutex_flock_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + int rv; + + if (fname) { + new_mutex->fname = apr_pstrdup(new_mutex->pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + 0x00004 | 0x00002 | 0x00040, + 0x0400 | 0x0200, + new_mutex->pool); + } + else { + new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX"); + rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname, + 0x00004 | 0x00002 | 0x00040, + new_mutex->pool); + } + + if (rv != 0) { + proc_mutex_flock_cleanup(new_mutex); + return (*__errno_location ()); + } + new_mutex->curr_locked = 0; + apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_flock_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = flock(mutex->interproc->filedes, 2); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_flock_tryacquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = flock(mutex->interproc->filedes, 2 | 4); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + if ((*__errno_location ()) == 11 || (*__errno_location ()) == 11) { + return ((20000 + 50000) + 25); + } + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked = 0; + do { + rc = flock(mutex->interproc->filedes, 8); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + return 0; +} + +static apr_status_t proc_mutex_flock_child_init(apr_proc_mutex_t **mutex, + apr_pool_t *pool, + const char *fname) +{ + apr_proc_mutex_t *new_mutex; + int rv; + + new_mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t)); + + memcpy(new_mutex, *mutex, sizeof *new_mutex); + new_mutex->pool = pool; + if (!fname) { + fname = (*mutex)->fname; + } + new_mutex->fname = apr_pstrdup(pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + 0x00002, 0, new_mutex->pool); + if (rv != 0) { + return rv; + } + *mutex = new_mutex; + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_flock_methods = +{ + + + + 0, + + proc_mutex_flock_create, + proc_mutex_flock_acquire, + proc_mutex_flock_tryacquire, + proc_mutex_flock_release, + proc_mutex_flock_cleanup, + proc_mutex_flock_child_init, + "flock" +}; + + + +void apr_proc_mutex_unix_setup_lock(void) +{ + + + proc_mutex_sysv_setup(); + + + proc_mutex_fcntl_setup(); + +} + +static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech) +{ + switch (mech) { + case APR_LOCK_FCNTL: + + new_mutex->inter_meth = &mutex_fcntl_methods; + + + + break; + case APR_LOCK_FLOCK: + + new_mutex->inter_meth = &mutex_flock_methods; + + + + break; + case APR_LOCK_SYSVSEM: + + new_mutex->inter_meth = &mutex_sysv_methods; + + + + break; + case APR_LOCK_POSIXSEM: + + new_mutex->inter_meth = &mutex_posixsem_methods; + + + + break; + case APR_LOCK_PROC_PTHREAD: + + new_mutex->inter_meth = &mutex_proc_pthread_methods; + + + + break; + case APR_LOCK_DEFAULT: + + + + new_mutex->inter_meth = &mutex_sysv_methods; +# 842 "./../locks/unix/proc_mutex.c" + break; + default: + return ((20000 + 50000) + 23); + } + return 0; +} + +const char * apr_proc_mutex_defname(void) +{ + apr_status_t rv; + apr_proc_mutex_t mutex; + + if ((rv = proc_mutex_choose_method(&mutex, APR_LOCK_DEFAULT)) != 0) { + return "unknown"; + } + mutex.meth = mutex.inter_meth; + + return apr_proc_mutex_name(&mutex); +} + +static apr_status_t proc_mutex_create(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech, const char *fname) +{ + apr_status_t rv; + + if ((rv = proc_mutex_choose_method(new_mutex, mech)) != 0) { + return rv; + } + + new_mutex->meth = new_mutex->inter_meth; + + if ((rv = new_mutex->meth->create(new_mutex, fname)) != 0) { + return rv; + } + + return 0; +} + +apr_status_t apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool) +{ + apr_proc_mutex_t *new_mutex; + apr_status_t rv; + + new_mutex = memset(apr_palloc(pool, sizeof(apr_proc_mutex_t)), 0, sizeof(apr_proc_mutex_t)); + new_mutex->pool = pool; + + if ((rv = proc_mutex_create(new_mutex, mech, fname)) != 0) + return rv; + + *mutex = new_mutex; + return 0; +} + +apr_status_t apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool) +{ + return (*mutex)->meth->child_init(mutex, pool, fname); +} + +apr_status_t apr_proc_mutex_lock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->acquire(mutex); +} + +apr_status_t apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->tryacquire(mutex); +} + +apr_status_t apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->release(mutex); +} + +apr_status_t apr_proc_mutex_cleanup(void *mutex) +{ + return ((apr_proc_mutex_t *)mutex)->meth->cleanup(mutex); +} + +const char * apr_proc_mutex_name(apr_proc_mutex_t *mutex) +{ + return mutex->meth->name; +} + +const char * apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) +{ + + + + if (mutex->meth == &mutex_flock_methods) { + return mutex->fname; + } + + + if (mutex->meth == &mutex_fcntl_methods) { + return mutex->fname; + } + + return ((void*)0); +} + +apr_pool_t * apr_proc_mutex_pool_get (const apr_proc_mutex_t *theproc_mutex) { return theproc_mutex->pool; } + + + +apr_status_t apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex) +{ + + if (pmutex->interproc) { + ospmutex->crossproc = pmutex->interproc->filedes; + } + else { + ospmutex->crossproc = -1; + } + + + ospmutex->pthread_interproc = pmutex->pthread_interproc; + + return 0; +} + +apr_status_t apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *pool) +{ + if (pool == ((void*)0)) { + return (20000 + 2); + } + if ((*pmutex) == ((void*)0)) { + (*pmutex) = (apr_proc_mutex_t *)memset(apr_palloc(pool, sizeof(apr_proc_mutex_t)), 0, sizeof(apr_proc_mutex_t)); + + (*pmutex)->pool = pool; + } + + apr_os_file_put(&(*pmutex)->interproc, &ospmutex->crossproc, 0, pool); + + + (*pmutex)->pthread_interproc = ospmutex->pthread_interproc; + + return 0; +} +# 14 "main1.c" 2 +# 1 "./../memory/unix/apr_pools.c" 1 +# 31 "./../memory/unix/apr_pools.c" +# 1 "../include/apr_want.h" 1 +# 32 "./../memory/unix/apr_pools.c" 2 +# 1 "../include/apr_env.h" 1 +# 42 "../include/apr_env.h" +apr_status_t apr_env_get(char **value, const char *envvar, + apr_pool_t *pool); + + + + + + + +apr_status_t apr_env_set(const char *envvar, const char *value, + apr_pool_t *pool); + + + + + + +apr_status_t apr_env_delete(const char *envvar, apr_pool_t *pool); +# 33 "./../memory/unix/apr_pools.c" 2 +# 85 "./../memory/unix/apr_pools.c" +struct apr_allocator_t { + + apr_uint32_t max_index; + + + + + + apr_uint32_t max_free_index; + + + + + apr_uint32_t current_free_index; + + apr_thread_mutex_t *mutex; + + apr_pool_t *owner; +# 113 "./../memory/unix/apr_pools.c" + apr_memnode_t *free[20]; +}; +# 123 "./../memory/unix/apr_pools.c" +apr_status_t apr_allocator_create(apr_allocator_t **allocator) +{ + apr_allocator_t *new_allocator; + + *allocator = ((void*)0); + + if ((new_allocator = malloc((((sizeof(apr_allocator_t)) + ((8) - 1)) & ~((8) - 1)))) == ((void*)0)) + return 12; + + memset(new_allocator, 0, (((sizeof(apr_allocator_t)) + ((8) - 1)) & ~((8) - 1))); + new_allocator->max_free_index = 0; + + *allocator = new_allocator; + + return 0; +} + +void apr_allocator_destroy(apr_allocator_t *allocator) +{ + apr_uint32_t index; + apr_memnode_t *node, **ref; + + for (index = 0; index < 20; index++) { + ref = &allocator->free[index]; + while ((node = *ref) != ((void*)0)) { + *ref = node->next; + + + + free(node); + + } + } + + free(allocator); +} + + +void apr_allocator_mutex_set(apr_allocator_t *allocator, + apr_thread_mutex_t *mutex) +{ + allocator->mutex = mutex; +} + +apr_thread_mutex_t * apr_allocator_mutex_get( + apr_allocator_t *allocator) +{ + return allocator->mutex; +} + + +void apr_allocator_owner_set(apr_allocator_t *allocator, + apr_pool_t *pool) +{ + allocator->owner = pool; +} + +apr_pool_t * apr_allocator_owner_get(apr_allocator_t *allocator) +{ + return allocator->owner; +} + +void apr_allocator_max_free_set(apr_allocator_t *allocator, + apr_size_t in_size) +{ + apr_uint32_t max_free_index; + apr_uint32_t size = (apr_uint32_t)in_size; + + + apr_thread_mutex_t *mutex; + + mutex = apr_allocator_mutex_get(allocator); + if (mutex != ((void*)0)) + apr_thread_mutex_lock(mutex); + + + max_free_index = (((size) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)) >> 12; + allocator->current_free_index += max_free_index; + allocator->current_free_index -= allocator->max_free_index; + allocator->max_free_index = max_free_index; + if (allocator->current_free_index > max_free_index) + allocator->current_free_index = max_free_index; + + + if (mutex != ((void*)0)) + apr_thread_mutex_unlock(mutex); + +} + +static __inline__ +apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t in_size) +{ + apr_memnode_t *node, **ref; + apr_uint32_t max_index; + apr_size_t size, i, index; + + + + + size = (((in_size + (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1))) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)); + if (size < in_size) { + return ((void*)0); + } + if (size < (2 * (1 << 12))) + size = (2 * (1 << 12)); + + + + + index = (size >> 12) - 1; + + if (index > (4294967295U)) { + return ((void*)0); + } + + + + + if (index <= allocator->max_index) { + + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); +# 257 "./../memory/unix/apr_pools.c" + max_index = allocator->max_index; + ref = &allocator->free[index]; + i = index; + while (*ref == ((void*)0) && i < max_index) { + ref++; + i++; + } + + if ((node = *ref) != ((void*)0)) { + + + + + + if ((*ref = node->next) == ((void*)0) && i >= max_index) { + do { + ref--; + max_index--; + } + while (*ref == ((void*)0) && max_index > 0); + + allocator->max_index = max_index; + } + + allocator->current_free_index += node->index + 1; + if (allocator->current_free_index > allocator->max_free_index) + allocator->current_free_index = allocator->max_free_index; + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + + node->next = ((void*)0); + node->first_avail = (char *)node + (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)); + + return node; + } + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + } + + + + + else if (allocator->free[0]) { + + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); + + + + + + ref = &allocator->free[0]; + while ((node = *ref) != ((void*)0) && index > node->index) + ref = &node->next; + + if (node) { + *ref = node->next; + + allocator->current_free_index += node->index + 1; + if (allocator->current_free_index > allocator->max_free_index) + allocator->current_free_index = allocator->max_free_index; + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + + node->next = ((void*)0); + node->first_avail = (char *)node + (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)); + + return node; + } + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + } +# 349 "./../memory/unix/apr_pools.c" + if ((node = malloc(size)) == ((void*)0)) + + return ((void*)0); + + node->next = ((void*)0); + node->index = (apr_uint32_t)index; + node->first_avail = (char *)node + (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)); + node->endp = (char *)node + size; + + return node; +} + +static __inline__ +void allocator_free(apr_allocator_t *allocator, apr_memnode_t *node) +{ + apr_memnode_t *next; apr_memnode_t *freelist = ((void*)0); + apr_uint32_t index, max_index; + apr_uint32_t max_free_index, current_free_index; + + + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); + + + max_index = allocator->max_index; + max_free_index = allocator->max_free_index; + current_free_index = allocator->current_free_index; + + + + + do { + next = node->next; + index = node->index; + + if (max_free_index != 0 + && index + 1 > current_free_index) { + node->next = freelist; + freelist = node; + } + else if (index < 20) { + + + + if ((node->next = allocator->free[index]) == ((void*)0) + && index > max_index) { + max_index = index; + } + allocator->free[index] = node; + if (current_free_index >= index + 1) + current_free_index -= index + 1; + else + current_free_index = 0; + } + else { + + + + node->next = allocator->free[0]; + allocator->free[0] = node; + if (current_free_index >= index + 1) + current_free_index -= index + 1; + else + current_free_index = 0; + } + } while ((node = next) != ((void*)0)); + + allocator->max_index = max_index; + allocator->current_free_index = current_free_index; + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + + while (freelist != ((void*)0)) { + node = freelist; + freelist = node->next; + + + + free(node); + + } +} + +apr_memnode_t * apr_allocator_alloc(apr_allocator_t *allocator, + apr_size_t size) +{ + return allocator_alloc(allocator, size); +} + +void apr_allocator_free(apr_allocator_t *allocator, + apr_memnode_t *node) +{ + allocator_free(allocator, node); +} +# 467 "./../memory/unix/apr_pools.c" +typedef struct cleanup_t cleanup_t; + + +struct process_chain { + + apr_proc_t *proc; + apr_kill_conditions_e kill_how; + + struct process_chain *next; +}; +# 500 "./../memory/unix/apr_pools.c" +struct apr_pool_t { + apr_pool_t *parent; + apr_pool_t *child; + apr_pool_t *sibling; + apr_pool_t **ref; + cleanup_t *cleanups; + cleanup_t *free_cleanups; + apr_allocator_t *allocator; + struct process_chain *subprocesses; + apr_abortfunc_t abort_fn; + apr_hash_t *user_data; + const char *tag; + + + apr_memnode_t *active; + apr_memnode_t *self; + char *self_first_avail; +# 535 "./../memory/unix/apr_pools.c" + cleanup_t *pre_cleanups; +}; +# 545 "./../memory/unix/apr_pools.c" +static apr_byte_t apr_pools_initialized = 0; +static apr_pool_t *global_pool = ((void*)0); + + +static apr_allocator_t *global_allocator = ((void*)0); +# 560 "./../memory/unix/apr_pools.c" +static void run_cleanups(cleanup_t **c); +static void free_proc_chain(struct process_chain *procs); +# 572 "./../memory/unix/apr_pools.c" +apr_status_t apr_pool_initialize(void) +{ + apr_status_t rv; + + if (apr_pools_initialized++) + return 0; +# 587 "./../memory/unix/apr_pools.c" + if ((rv = apr_allocator_create(&global_allocator)) != 0) { + apr_pools_initialized = 0; + return rv; + } + + if ((rv = apr_pool_create_ex(&global_pool, ((void*)0), ((void*)0), + global_allocator)) != 0) { + apr_allocator_destroy(global_allocator); + global_allocator = ((void*)0); + apr_pools_initialized = 0; + return rv; + } + + apr_pool_tag(global_pool, "apr_global_pool"); + + + + + + + + if ((rv = apr_atomic_init(global_pool)) != 0) { + return rv; + } + + + { + apr_thread_mutex_t *mutex; + + if ((rv = apr_thread_mutex_create(&mutex, + 0x0, + global_pool)) != 0) { + return rv; + } + + apr_allocator_mutex_set(global_allocator, mutex); + } + + + apr_allocator_owner_set(global_allocator, global_pool); + + return 0; +} + +void apr_pool_terminate(void) +{ + if (!apr_pools_initialized) + return; + + if (--apr_pools_initialized) + return; + + apr_pool_destroy(global_pool); + global_pool = ((void*)0); + + global_allocator = ((void*)0); +} +# 668 "./../memory/unix/apr_pools.c" +void * apr_palloc(apr_pool_t *pool, apr_size_t in_size) +{ + apr_memnode_t *active, *node; + void *mem; + apr_size_t size, free_index; + + size = (((in_size) + ((8) - 1)) & ~((8) - 1)); + if (size < in_size) { + if (pool->abort_fn) + pool->abort_fn(12); + + return ((void*)0); + } + active = pool->active; + + + if (size <= ((apr_size_t)(active->endp - active->first_avail))) { + mem = active->first_avail; + active->first_avail += size; + + return mem; + } + + node = active->next; + if (size <= ((apr_size_t)(node->endp - node->first_avail))) { + do { *node->ref = node->next; node->next->ref = node->ref; } while (0); + } + else { + if ((node = allocator_alloc(pool->allocator, size)) == ((void*)0)) { + if (pool->abort_fn) + pool->abort_fn(12); + + return ((void*)0); + } + } + + node->free_index = 0; + + mem = node->first_avail; + node->first_avail += size; + + do { node->ref = active->ref; *node->ref = node; node->next = active; active->ref = &node->next; } while (0); + + pool->active = node; + + free_index = ((((active->endp - active->first_avail + 1) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)) - (1 << 12)) >> 12; + + + active->free_index = (apr_uint32_t)free_index; + node = active->next; + if (free_index >= node->free_index) + return mem; + + do { + node = node->next; + } + while (free_index < node->free_index); + + do { *active->ref = active->next; active->next->ref = active->ref; } while (0); + do { active->ref = node->ref; *active->ref = active; active->next = node; node->ref = &active->next; } while (0); + + return mem; +} +# 740 "./../memory/unix/apr_pools.c" +void * apr_pcalloc(apr_pool_t *pool, apr_size_t size); +void * apr_pcalloc(apr_pool_t *pool, apr_size_t size) +{ + void *mem; + + if ((mem = apr_palloc(pool, size)) != ((void*)0)) { + memset(mem, 0, size); + } + + return mem; +} + + + + + + +void apr_pool_clear(apr_pool_t *pool) +{ + apr_memnode_t *active; + + + run_cleanups(&pool->pre_cleanups); + pool->pre_cleanups = ((void*)0); + + + + + while (pool->child) + apr_pool_destroy(pool->child); + + + run_cleanups(&pool->cleanups); + pool->cleanups = ((void*)0); + pool->free_cleanups = ((void*)0); + + + free_proc_chain(pool->subprocesses); + pool->subprocesses = ((void*)0); + + + pool->user_data = ((void*)0); + + + + + active = pool->active = pool->self; + active->first_avail = pool->self_first_avail; + + if (active->next == active) + return; + + *active->ref = ((void*)0); + allocator_free(pool->allocator, active->next); + active->next = active; + active->ref = &active->next; +} + +void apr_pool_destroy(apr_pool_t *pool) +{ + apr_memnode_t *active; + apr_allocator_t *allocator; + + + run_cleanups(&pool->pre_cleanups); + pool->pre_cleanups = ((void*)0); + + + + + while (pool->child) + apr_pool_destroy(pool->child); + + + run_cleanups(&pool->cleanups); + + + free_proc_chain(pool->subprocesses); + + + if (pool->parent) { + + apr_thread_mutex_t *mutex; + + if ((mutex = apr_allocator_mutex_get(pool->parent->allocator)) != ((void*)0)) + apr_thread_mutex_lock(mutex); + + + if ((*pool->ref = pool->sibling) != ((void*)0)) + pool->sibling->ref = pool->ref; + + + if (mutex) + apr_thread_mutex_unlock(mutex); + + } + + + + + allocator = pool->allocator; + active = pool->self; + *active->ref = ((void*)0); + + + if (apr_allocator_owner_get(allocator) == pool) { + + + + apr_allocator_mutex_set(allocator, ((void*)0)); + } + + + + + + allocator_free(allocator, active); + + + + + + + if (apr_allocator_owner_get(allocator) == pool) { + apr_allocator_destroy(allocator); + } +} + +apr_status_t apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) +{ + apr_pool_t *pool; + apr_memnode_t *node; + + *newpool = ((void*)0); + + if (!parent) + parent = global_pool; + + + + + + if (!abort_fn && parent) + abort_fn = parent->abort_fn; + + if (allocator == ((void*)0)) + allocator = parent->allocator; + + if ((node = allocator_alloc(allocator, + (2 * (1 << 12)) - (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)))) == ((void*)0)) { + if (abort_fn) + abort_fn(12); + + return 12; + } + + node->next = node; + node->ref = &node->next; + + pool = (apr_pool_t *)node->first_avail; + node->first_avail = pool->self_first_avail = (char *)pool + (((sizeof(apr_pool_t)) + ((8) - 1)) & ~((8) - 1)); + + pool->allocator = allocator; + pool->active = pool->self = node; + pool->abort_fn = abort_fn; + pool->child = ((void*)0); + pool->cleanups = ((void*)0); + pool->free_cleanups = ((void*)0); + pool->pre_cleanups = ((void*)0); + pool->subprocesses = ((void*)0); + pool->user_data = ((void*)0); + pool->tag = ((void*)0); + + + + + + if ((pool->parent = parent) != ((void*)0)) { + + apr_thread_mutex_t *mutex; + + if ((mutex = apr_allocator_mutex_get(parent->allocator)) != ((void*)0)) + apr_thread_mutex_lock(mutex); + + + if ((pool->sibling = parent->child) != ((void*)0)) + pool->sibling->ref = &pool->sibling; + + parent->child = pool; + pool->ref = &parent->child; + + + if (mutex) + apr_thread_mutex_unlock(mutex); + + } + else { + pool->sibling = ((void*)0); + pool->ref = ((void*)0); + } + + *newpool = pool; + + return 0; +} + + + +apr_status_t apr_pool_create_core_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) +{ + return apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator); +} + +apr_status_t apr_pool_create_unmanaged_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) +{ + apr_pool_t *pool; + apr_memnode_t *node; + apr_allocator_t *pool_allocator; + + *newpool = ((void*)0); + + if (!apr_pools_initialized) + return (20000 + 2); + if ((pool_allocator = allocator) == ((void*)0)) { + if ((pool_allocator = malloc((((sizeof(apr_allocator_t)) + ((8) - 1)) & ~((8) - 1)))) == ((void*)0)) { + if (abort_fn) + abort_fn(12); + + return 12; + } + memset(pool_allocator, 0, (((sizeof(apr_allocator_t)) + ((8) - 1)) & ~((8) - 1))); + pool_allocator->max_free_index = 0; + } + if ((node = allocator_alloc(pool_allocator, + (2 * (1 << 12)) - (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)))) == ((void*)0)) { + if (abort_fn) + abort_fn(12); + + return 12; + } + + node->next = node; + node->ref = &node->next; + + pool = (apr_pool_t *)node->first_avail; + node->first_avail = pool->self_first_avail = (char *)pool + (((sizeof(apr_pool_t)) + ((8) - 1)) & ~((8) - 1)); + + pool->allocator = pool_allocator; + pool->active = pool->self = node; + pool->abort_fn = abort_fn; + pool->child = ((void*)0); + pool->cleanups = ((void*)0); + pool->free_cleanups = ((void*)0); + pool->pre_cleanups = ((void*)0); + pool->subprocesses = ((void*)0); + pool->user_data = ((void*)0); + pool->tag = ((void*)0); + pool->parent = ((void*)0); + pool->sibling = ((void*)0); + pool->ref = ((void*)0); + + + + + if (!allocator) + pool_allocator->owner = pool; + *newpool = pool; + + return 0; +} +# 1036 "./../memory/unix/apr_pools.c" +struct psprintf_data { + apr_vformatter_buff_t vbuff; + apr_memnode_t *node; + apr_pool_t *pool; + apr_byte_t got_a_new_node; + apr_memnode_t *free; +}; + + + +static int psprintf_flush(apr_vformatter_buff_t *vbuff) +{ + struct psprintf_data *ps = (struct psprintf_data *)vbuff; + apr_memnode_t *node, *active; + apr_size_t cur_len, size; + char *strp; + apr_pool_t *pool; + apr_size_t free_index; + + pool = ps->pool; + active = ps->node; + strp = ps->vbuff.curpos; + cur_len = strp - active->first_avail; + size = cur_len << 1; + + + + + + + if (size < 32) + size = 32; + + node = active->next; + if (!ps->got_a_new_node && size <= ((apr_size_t)(node->endp - node->first_avail))) { + + do { *node->ref = node->next; node->next->ref = node->ref; } while (0); + do { node->ref = active->ref; *node->ref = node; node->next = active; active->ref = &node->next; } while (0); + + node->free_index = 0; + + pool->active = node; + + free_index = ((((active->endp - active->first_avail + 1) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)) - (1 << 12)) >> 12; + + + active->free_index = (apr_uint32_t)free_index; + node = active->next; + if (free_index < node->free_index) { + do { + node = node->next; + } + while (free_index < node->free_index); + + do { *active->ref = active->next; active->next->ref = active->ref; } while (0); + do { active->ref = node->ref; *active->ref = active; active->next = node; node->ref = &active->next; } while (0); + } + + node = pool->active; + } + else { + if ((node = allocator_alloc(pool->allocator, size)) == ((void*)0)) + return -1; + + if (ps->got_a_new_node) { + active->next = ps->free; + ps->free = active; + } + + ps->got_a_new_node = 1; + } + + memcpy(node->first_avail, active->first_avail, cur_len); + + ps->node = node; + ps->vbuff.curpos = node->first_avail + cur_len; + ps->vbuff.endpos = node->endp - 1; + + return 0; +} + +char * apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) +{ + struct psprintf_data ps; + char *strp; + apr_size_t size; + apr_memnode_t *active, *node; + apr_size_t free_index; + + ps.node = active = pool->active; + ps.pool = pool; + ps.vbuff.curpos = ps.node->first_avail; + + + ps.vbuff.endpos = ps.node->endp - 1; + ps.got_a_new_node = 0; + ps.free = ((void*)0); + + + + + if (ps.node->first_avail == ps.node->endp) { + if (psprintf_flush(&ps.vbuff) == -1) { + if (pool->abort_fn) { + pool->abort_fn(12); + } + + return ((void*)0); + } + } + + if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) { + if (pool->abort_fn) + pool->abort_fn(12); + + return ((void*)0); + } + + strp = ps.vbuff.curpos; + *strp++ = '\0'; + + size = strp - ps.node->first_avail; + size = (((size) + ((8) - 1)) & ~((8) - 1)); + strp = ps.node->first_avail; + ps.node->first_avail += size; + + if (ps.free) + allocator_free(pool->allocator, ps.free); + + + + + if (!ps.got_a_new_node) + return strp; + + active = pool->active; + node = ps.node; + + node->free_index = 0; + + do { node->ref = active->ref; *node->ref = node; node->next = active; active->ref = &node->next; } while (0); + + pool->active = node; + + free_index = ((((active->endp - active->first_avail + 1) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)) - (1 << 12)) >> 12; + + + active->free_index = (apr_uint32_t)free_index; + node = active->next; + + if (free_index >= node->free_index) + return strp; + + do { + node = node->next; + } + while (free_index < node->free_index); + + do { *active->ref = active->next; active->next->ref = active->ref; } while (0); + do { active->ref = node->ref; *active->ref = active; active->next = node; node->ref = &active->next; } while (0); + + return strp; +} +# 2049 "./../memory/unix/apr_pools.c" +char * apr_psprintf(apr_pool_t *p, const char *fmt, ...) +{ + va_list ap; + char *res; + + __builtin_va_start(ap, fmt); + res = apr_pvsprintf(p, fmt, ap); + __builtin_va_end(ap); + return res; +} + + + + + +void apr_pool_abort_set(apr_abortfunc_t abort_fn, + apr_pool_t *pool) +{ + pool->abort_fn = abort_fn; +} + +apr_abortfunc_t apr_pool_abort_get(apr_pool_t *pool) +{ + return pool->abort_fn; +} + +apr_pool_t * apr_pool_parent_get(apr_pool_t *pool) +{ + + + + + + + + return pool->parent; +} + +apr_allocator_t * apr_pool_allocator_get(apr_pool_t *pool) +{ + return pool->allocator; +} + + + + +int apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b) +{ + if (a == ((void*)0)) + return 1; +# 2108 "./../memory/unix/apr_pools.c" + while (b) { + if (a == b) + return 1; + + b = b->parent; + } + + return 0; +} + +void apr_pool_tag(apr_pool_t *pool, const char *tag) +{ + pool->tag = tag; +} + + + + + + +apr_status_t apr_pool_userdata_set(const void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_pool_t *pool) +{ + + + + + if (pool->user_data == ((void*)0)) + pool->user_data = apr_hash_make(pool); + + if (apr_hash_get(pool->user_data, key, (-1)) == ((void*)0)) { + char *new_key = apr_pstrdup(pool, key); + apr_hash_set(pool->user_data, new_key, (-1), data); + } + else { + apr_hash_set(pool->user_data, key, (-1), data); + } + + if (cleanup) + apr_pool_cleanup_register(pool, data, cleanup, cleanup); + + return 0; +} + +apr_status_t apr_pool_userdata_setn(const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) +{ + + + + + if (pool->user_data == ((void*)0)) + pool->user_data = apr_hash_make(pool); + + apr_hash_set(pool->user_data, key, (-1), data); + + if (cleanup) + apr_pool_cleanup_register(pool, data, cleanup, cleanup); + + return 0; +} + +apr_status_t apr_pool_userdata_get(void **data, const char *key, + apr_pool_t *pool) +{ + + + + + if (pool->user_data == ((void*)0)) { + *data = ((void*)0); + } + else { + *data = apr_hash_get(pool->user_data, key, (-1)); + } + + return 0; +} + + + + + + +struct cleanup_t { + struct cleanup_t *next; + const void *data; + apr_status_t (*plain_cleanup_fn)(void *data); + apr_status_t (*child_cleanup_fn)(void *data); +}; + +void apr_pool_cleanup_register(apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup_fn)(void *data), + apr_status_t (*child_cleanup_fn)(void *data)) +{ + cleanup_t *c; + + + + + + if (p != ((void*)0)) { + if (p->free_cleanups) { + + c = p->free_cleanups; + p->free_cleanups = c->next; + } else { + c = apr_palloc(p, sizeof(cleanup_t)); + } + c->data = data; + c->plain_cleanup_fn = plain_cleanup_fn; + c->child_cleanup_fn = child_cleanup_fn; + c->next = p->cleanups; + p->cleanups = c; + } +} + +void apr_pool_pre_cleanup_register(apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup_fn)(void *data)) +{ + cleanup_t *c; + + + + + + if (p != ((void*)0)) { + if (p->free_cleanups) { + + c = p->free_cleanups; + p->free_cleanups = c->next; + } else { + c = apr_palloc(p, sizeof(cleanup_t)); + } + c->data = data; + c->plain_cleanup_fn = plain_cleanup_fn; + c->next = p->pre_cleanups; + p->pre_cleanups = c; + } +} + +void apr_pool_cleanup_kill(apr_pool_t *p, const void *data, + apr_status_t (*cleanup_fn)(void *)) +{ + cleanup_t *c, **lastp; + + + + + + if (p == ((void*)0)) + return; + + c = p->cleanups; + lastp = &p->cleanups; + while (c) { +# 2276 "./../memory/unix/apr_pools.c" + if (c->data == data && c->plain_cleanup_fn == cleanup_fn) { + *lastp = c->next; + + c->next = p->free_cleanups; + p->free_cleanups = c; + break; + } + + lastp = &c->next; + c = c->next; + } + + + c = p->pre_cleanups; + lastp = &p->pre_cleanups; + while (c) { +# 2301 "./../memory/unix/apr_pools.c" + if (c->data == data && c->plain_cleanup_fn == cleanup_fn) { + *lastp = c->next; + + c->next = p->free_cleanups; + p->free_cleanups = c; + break; + } + + lastp = &c->next; + c = c->next; + } + +} + +void apr_pool_child_cleanup_set(apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup_fn)(void *), + apr_status_t (*child_cleanup_fn)(void *)) +{ + cleanup_t *c; + + + + + + if (p == ((void*)0)) + return; + + c = p->cleanups; + while (c) { + if (c->data == data && c->plain_cleanup_fn == plain_cleanup_fn) { + c->child_cleanup_fn = child_cleanup_fn; + break; + } + + c = c->next; + } +} + +apr_status_t apr_pool_cleanup_run(apr_pool_t *p, void *data, + apr_status_t (*cleanup_fn)(void *)) +{ + apr_pool_cleanup_kill(p, data, cleanup_fn); + return (*cleanup_fn)(data); +} + +static void run_cleanups(cleanup_t **cref) +{ + cleanup_t *c = *cref; + + while (c) { + *cref = c->next; + (*c->plain_cleanup_fn)((void *)c->data); + c = *cref; + } +} + + + +static void run_child_cleanups(cleanup_t **cref) +{ + cleanup_t *c = *cref; + + while (c) { + *cref = c->next; + (*c->child_cleanup_fn)((void *)c->data); + c = *cref; + } +} + +static void cleanup_pool_for_exec(apr_pool_t *p) +{ + run_child_cleanups(&p->cleanups); + + for (p = p->child; p; p = p->sibling) + cleanup_pool_for_exec(p); +} + +void apr_pool_cleanup_for_exec(void) +{ + cleanup_pool_for_exec(global_pool); +} +# 2402 "./../memory/unix/apr_pools.c" +apr_status_t apr_pool_cleanup_null(void *data) +{ + + return 0; +} +# 2415 "./../memory/unix/apr_pools.c" +void apr_pool_note_subprocess(apr_pool_t *pool, apr_proc_t *proc, + apr_kill_conditions_e how) +{ + struct process_chain *pc = apr_palloc(pool, sizeof(struct process_chain)); + + pc->proc = proc; + pc->kill_how = how; + pc->next = pool->subprocesses; + pool->subprocesses = pc; +} + +static void free_proc_chain(struct process_chain *procs) +{ + + + + + struct process_chain *pc; + int need_timeout = 0; + apr_time_t timeout_interval; + + if (!procs) + return; +# 2448 "./../memory/unix/apr_pools.c" + for (pc = procs; pc; pc = pc->next) { + if (apr_proc_wait(pc->proc, ((void*)0), ((void*)0), APR_NOWAIT) != ((20000 + 50000) + 6)) + pc->kill_how = APR_KILL_NEVER; + } + + + for (pc = procs; pc; pc = pc->next) { + + if ((pc->kill_how == APR_KILL_AFTER_TIMEOUT) + || (pc->kill_how == APR_KILL_ONLY_ONCE)) { + + + + + + + if (apr_proc_kill(pc->proc, 15) == 0) + need_timeout = 1; + } + else if (pc->kill_how == APR_KILL_ALWAYS) { + + + + + + apr_proc_kill(pc->proc, 9); + } + } + + + + + + if (need_timeout) { + timeout_interval = 46875; + apr_sleep(timeout_interval); + + do { + + need_timeout = 0; + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how == APR_KILL_AFTER_TIMEOUT) { + if (apr_proc_wait(pc->proc, ((void*)0), ((void*)0), APR_NOWAIT) + == ((20000 + 50000) + 6)) + need_timeout = 1; + else + pc->kill_how = APR_KILL_NEVER; + } + } + if (need_timeout) { + if (timeout_interval >= 3000000) { + break; + } + apr_sleep(timeout_interval); + timeout_interval *= 2; + } + } while (need_timeout); + } + + + + + + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how == APR_KILL_AFTER_TIMEOUT) + apr_proc_kill(pc->proc, 9); + } + + + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how != APR_KILL_NEVER) + (void)apr_proc_wait(pc->proc, ((void*)0), ((void*)0), APR_WAIT); + } +} +# 2530 "./../memory/unix/apr_pools.c" +void * apr_palloc_debug(apr_pool_t *pool, apr_size_t size, + const char *file_line) +{ + return apr_palloc(pool, size); +} + +void * apr_pcalloc_debug(apr_pool_t *pool, apr_size_t size, + const char *file_line) +{ + return apr_pcalloc(pool, size); +} + +void apr_pool_clear_debug(apr_pool_t *pool, + const char *file_line) +{ + apr_pool_clear(pool); +} + +void apr_pool_destroy_debug(apr_pool_t *pool, + const char *file_line) +{ + apr_pool_destroy(pool); +} + +apr_status_t apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) +{ + return apr_pool_create_ex(newpool, parent, abort_fn, allocator); +} + +apr_status_t apr_pool_create_core_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) +{ + return apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator); +} + +apr_status_t apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) +{ + return apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator); +} +# 15 "main1.c" 2 +# 1 "./../misc/unix/start.c" 1 +# 20 "./../misc/unix/start.c" +# 1 "../include/apr_signal.h" 1 +# 57 "../include/apr_signal.h" +typedef void apr_sigfunc_t(int); + + + + + + +apr_sigfunc_t * apr_signal(int signo, apr_sigfunc_t * func); +# 80 "../include/apr_signal.h" +const char * apr_signal_description_get(int signum); + + + + + + +void apr_signal_init(apr_pool_t *pglobal); + + + + + + +apr_status_t apr_signal_block(int signum); + + + + + + +apr_status_t apr_signal_unblock(int signum); +# 21 "./../misc/unix/start.c" 2 + + + +# 1 "../include/arch/unix/apr_arch_internal_time.h" 1 +# 22 "../include/arch/unix/apr_arch_internal_time.h" +void apr_unix_setup_time(void); +# 25 "./../misc/unix/start.c" 2 + + +apr_status_t apr_app_initialize(int *argc, + const char * const * *argv, + const char * const * *env) +{ + + + + + + return apr_initialize(); +} + +static int initialized = 0; + +apr_status_t apr_initialize(void) +{ + apr_pool_t *pool; + apr_status_t status; + + if (initialized++) { + return 0; + } + + + apr_proc_mutex_unix_setup_lock(); + apr_unix_setup_time(); + + + if ((status = apr_pool_initialize()) != 0) + return status; + + if (apr_pool_create_ex(&pool, ((void*)0), ((void*)0), ((void*)0)) != 0) { + return (20000 + 2); + } + + apr_pool_tag(pool, "apr_initialize"); +# 71 "./../misc/unix/start.c" + apr_signal_init(pool); + + return 0; +} + +void apr_terminate(void) +{ + initialized--; + if (initialized) { + return; + } + apr_pool_terminate(); + +} + +void apr_terminate2(void) +{ + apr_terminate(); +} +# 16 "main1.c" 2 +# 1 "./../time/unix/time.c" 1 +# 43 "./../time/unix/time.c" +static apr_int32_t get_offset(struct tm *tm) +{ + + return tm->tm_gmtoff; +# 64 "./../time/unix/time.c" +} + +apr_status_t apr_time_ansi_put(apr_time_t *result, + time_t input) +{ + *result = (apr_time_t)input * 1000000L; + return 0; +} + + +apr_time_t apr_time_now(void) +{ + struct timeval tv; + gettimeofday(&tv, ((void*)0)); + return tv.tv_sec * 1000000L + tv.tv_usec; +} + +static void explode_time(apr_time_exp_t *xt, apr_time_t t, + apr_int32_t offset, int use_localtime) +{ + struct tm tm; + time_t tt = (t / 1000000L) + offset; + xt->tm_usec = t % 1000000L; + + + if (use_localtime) + localtime_r(&tt, &tm); + else + gmtime_r(&tt, &tm); + + + + + + + + xt->tm_sec = tm.tm_sec; + xt->tm_min = tm.tm_min; + xt->tm_hour = tm.tm_hour; + xt->tm_mday = tm.tm_mday; + xt->tm_mon = tm.tm_mon; + xt->tm_year = tm.tm_year; + xt->tm_wday = tm.tm_wday; + xt->tm_yday = tm.tm_yday; + xt->tm_isdst = tm.tm_isdst; + xt->tm_gmtoff = get_offset(&tm); +} + +apr_status_t apr_time_exp_tz(apr_time_exp_t *result, + apr_time_t input, apr_int32_t offs) +{ + explode_time(result, input, offs, 0); + result->tm_gmtoff = offs; + return 0; +} + +apr_status_t apr_time_exp_gmt(apr_time_exp_t *result, + apr_time_t input) +{ + return apr_time_exp_tz(result, input, 0); +} + +apr_status_t apr_time_exp_lt(apr_time_exp_t *result, + apr_time_t input) +{ + + + + + explode_time(result, input, 0, 1); + return 0; + +} + +apr_status_t apr_time_exp_get(apr_time_t *t, apr_time_exp_t *xt) +{ + apr_time_t year = xt->tm_year; + apr_time_t days; + static const int dayoffset[12] = + {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; + + + + if (xt->tm_mon < 2) + year--; + + + + days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4; + days += dayoffset[xt->tm_mon] + xt->tm_mday - 1; + days -= 25508; + days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec; + + if (days < 0) { + return (20000 + 4); + } + *t = days * 1000000L + xt->tm_usec; + return 0; +} + +apr_status_t apr_time_exp_gmt_get(apr_time_t *t, + apr_time_exp_t *xt) +{ + apr_status_t status = apr_time_exp_get(t, xt); + if (status == 0) + *t -= (apr_time_t) xt->tm_gmtoff * 1000000L; + return status; +} + +apr_status_t apr_os_imp_time_get(apr_os_imp_time_t **ostime, + apr_time_t *aprtime) +{ + (*ostime)->tv_usec = *aprtime % 1000000L; + (*ostime)->tv_sec = *aprtime / 1000000L; + return 0; +} + +apr_status_t apr_os_exp_time_get(apr_os_exp_time_t **ostime, + apr_time_exp_t *aprtime) +{ + (*ostime)->tm_sec = aprtime->tm_sec; + (*ostime)->tm_min = aprtime->tm_min; + (*ostime)->tm_hour = aprtime->tm_hour; + (*ostime)->tm_mday = aprtime->tm_mday; + (*ostime)->tm_mon = aprtime->tm_mon; + (*ostime)->tm_year = aprtime->tm_year; + (*ostime)->tm_wday = aprtime->tm_wday; + (*ostime)->tm_yday = aprtime->tm_yday; + (*ostime)->tm_isdst = aprtime->tm_isdst; + + + (*ostime)->tm_gmtoff = aprtime->tm_gmtoff; + + + + + return 0; +} + +apr_status_t apr_os_imp_time_put(apr_time_t *aprtime, + apr_os_imp_time_t **ostime, + apr_pool_t *cont) +{ + *aprtime = (*ostime)->tv_sec * 1000000L + (*ostime)->tv_usec; + return 0; +} + +apr_status_t apr_os_exp_time_put(apr_time_exp_t *aprtime, + apr_os_exp_time_t **ostime, + apr_pool_t *cont) +{ + aprtime->tm_sec = (*ostime)->tm_sec; + aprtime->tm_min = (*ostime)->tm_min; + aprtime->tm_hour = (*ostime)->tm_hour; + aprtime->tm_mday = (*ostime)->tm_mday; + aprtime->tm_mon = (*ostime)->tm_mon; + aprtime->tm_year = (*ostime)->tm_year; + aprtime->tm_wday = (*ostime)->tm_wday; + aprtime->tm_yday = (*ostime)->tm_yday; + aprtime->tm_isdst = (*ostime)->tm_isdst; + + + aprtime->tm_gmtoff = (*ostime)->tm_gmtoff; + + + + + return 0; +} + +void apr_sleep(apr_interval_time_t t) +{ + + + + + + + + struct timeval tv; + tv.tv_usec = t % 1000000L; + tv.tv_sec = t / 1000000L; + select(0, ((void*)0), ((void*)0), ((void*)0), &tv); + +} +# 296 "./../time/unix/time.c" +void apr_unix_setup_time(void) +{ +# 339 "./../time/unix/time.c" +} + + + + +void apr_time_clock_hires(apr_pool_t *p) +{ + return; +} +# 17 "main1.c" 2 +# 1 "./../atomic/unix/builtins.c" 1 +# 17 "./../atomic/unix/builtins.c" +# 1 "../include/arch/unix/apr_arch_atomic.h" 1 +# 18 "./../atomic/unix/builtins.c" 2 + + + +apr_status_t apr_atomic_init(apr_pool_t *p) +{ + return 0; +} + +apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem) +{ + return *mem; +} + +void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + *mem = val; +} + +apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + return __sync_fetch_and_add(mem, val); +} + +void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + __sync_fetch_and_sub(mem, val); +} + +apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem) +{ + return __sync_fetch_and_add(mem, 1); +} + +int apr_atomic_dec32(volatile apr_uint32_t *mem) +{ + return __sync_sub_and_fetch(mem, 1); +} + +apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, + apr_uint32_t cmp) +{ + return __sync_val_compare_and_swap(mem, cmp, with); +} + +apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + __sync_synchronize(); + + return __sync_lock_test_and_set(mem, val); +} + +void* apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) +{ + return (void*) __sync_val_compare_and_swap(mem, cmp, with); +} + +void* apr_atomic_xchgptr(volatile void **mem, void *with) +{ + __sync_synchronize(); + + return (void*) __sync_lock_test_and_set(mem, with); +} +# 18 "main1.c" 2 +# 1 "./../threadproc/unix/signals.c" 1 +# 18 "./../threadproc/unix/signals.c" +# 1 "../include/arch/unix/apr_arch_threadproc.h" 1 +# 55 "../include/arch/unix/apr_arch_threadproc.h" +struct apr_thread_t { + apr_pool_t *pool; + pthread_t *td; + void *data; + apr_thread_start_t func; + apr_status_t exitval; +}; + +struct apr_threadattr_t { + apr_pool_t *pool; + pthread_attr_t attr; +}; + +struct apr_threadkey_t { + apr_pool_t *pool; + pthread_key_t key; +}; + +struct apr_thread_once_t { + pthread_once_t once; +}; + + + +struct apr_procattr_t { + apr_pool_t *pool; + apr_file_t *parent_in; + apr_file_t *child_in; + apr_file_t *parent_out; + apr_file_t *child_out; + apr_file_t *parent_err; + apr_file_t *child_err; + char *currdir; + apr_int32_t cmdtype; + apr_int32_t detached; + + struct rlimit *limit_cpu; + + + struct rlimit *limit_mem; + + + struct rlimit *limit_nproc; + + + struct rlimit *limit_nofile; + + apr_child_errfn_t *errfn; + apr_int32_t errchk; + apr_uid_t uid; + apr_gid_t gid; +}; +# 19 "./../threadproc/unix/signals.c" 2 + + + + + +# 1 "/usr/include/assert.h" 1 3 4 +# 25 "./../threadproc/unix/signals.c" 2 +# 35 "./../threadproc/unix/signals.c" +apr_status_t apr_proc_kill(apr_proc_t *proc, int signum) +{ +# 48 "./../threadproc/unix/signals.c" + if (kill(proc->pid, signum) == -1) { + return (*__errno_location ()); + } + + return 0; +} +# 74 "./../threadproc/unix/signals.c" +apr_sigfunc_t * apr_signal(int signo, apr_sigfunc_t * func) +{ + struct sigaction act, oact; + + act.__sigaction_handler.sa_handler = func; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + + act.sa_flags |= 0x20000000; +# 103 "./../threadproc/unix/signals.c" + if (sigaction(signo, &act, &oact) < 0) + return ((__sighandler_t) -1); + return oact.__sigaction_handler.sa_handler; +} + + + + + + + +void apr_signal_init(apr_pool_t *pglobal) +{ +} +const char *apr_signal_description_get(int signum) +{ + return (signum >= 0) ? sys_siglist[signum] : "unknown signal (number)"; +} +# 274 "./../threadproc/unix/signals.c" +static void remove_sync_sigs(sigset_t *sig_mask) +{ + + sigdelset(sig_mask, 6); + + + sigdelset(sig_mask, 7); + + + + + + sigdelset(sig_mask, 8); + + + sigdelset(sig_mask, 4); + + + sigdelset(sig_mask, 6); + + + sigdelset(sig_mask, 13); + + + sigdelset(sig_mask, 11); + + + sigdelset(sig_mask, 31); + + + sigdelset(sig_mask, 5); +# 315 "./../threadproc/unix/signals.c" + sigdelset(sig_mask, 12); + +} + +apr_status_t apr_signal_thread(int(*signal_handler)(int signum)) +{ + sigset_t sig_mask; + + int (*sig_func)(int signum) = (int (*)(int))signal_handler; + + + + sigfillset(&sig_mask); + + + + + + + sigdelset(&sig_mask, 9); + + + sigdelset(&sig_mask, 19); + + + sigdelset(&sig_mask, 18); + + + + + + + remove_sync_sigs(&sig_mask); +# 379 "./../threadproc/unix/signals.c" + while (1) { + + int signal_received; + + if (sigwait((&sig_mask),(&signal_received)) != 0) + { + + } + + if (sig_func(signal_received) == 1) { + return 0; + } + + + + + + } +} + +apr_status_t apr_setup_signal_thread(void) +{ + sigset_t sig_mask; + int rv; +# 416 "./../threadproc/unix/signals.c" + sigfillset(&sig_mask); + remove_sync_sigs(&sig_mask); + + + + + + + if ((rv = pthread_sigmask(2, &sig_mask, ((void*)0))) != 0) { + + + + } + + return rv; +} + + + +apr_status_t apr_signal_block(int signum) +{ + + sigset_t sig_mask; + int rv; + + sigemptyset(&sig_mask); + + sigaddset(&sig_mask, signum); + + + + + + + if ((rv = pthread_sigmask(0, &sig_mask, ((void*)0))) != 0) { + + + + } + + return rv; + + + +} + +apr_status_t apr_signal_unblock(int signum) +{ + + sigset_t sig_mask; + int rv; + + sigemptyset(&sig_mask); + + sigaddset(&sig_mask, signum); + + + + + + + if ((rv = pthread_sigmask(1, &sig_mask, ((void*)0))) != 0) { + + + + } + + return rv; + + + +} +# 19 "main1.c" 2 +# 1 "./../threadproc/unix/thread.c" 1 +# 19 "./../threadproc/unix/thread.c" +# 1 "../include/arch/unix/apr_arch_threadproc.h" 1 +# 20 "./../threadproc/unix/thread.c" 2 + + + + + + +static apr_status_t threadattr_cleanup(void *data) +{ + apr_threadattr_t *attr = data; + apr_status_t rv; + + rv = pthread_attr_destroy(&attr->attr); + + + + + + return rv; +} + +apr_status_t apr_threadattr_create(apr_threadattr_t **new, + apr_pool_t *pool) +{ + apr_status_t stat; + + (*new) = apr_palloc(pool, sizeof(apr_threadattr_t)); + (*new)->pool = pool; + stat = pthread_attr_init(&(*new)->attr); + + if (stat == 0) { + apr_pool_cleanup_register(pool, *new, threadattr_cleanup, + apr_pool_cleanup_null); + return 0; + } + + + + + return stat; +} + + + + + + + +apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr, + apr_int32_t on) +{ + apr_status_t stat; + + + + + + if ((stat = pthread_attr_setdetachstate(&attr->attr, + ((on) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE))) == 0) { + + return 0; + } + else { + + + + + return stat; + } +} + +apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr) +{ + int state; + + + + + pthread_attr_getdetachstate(&attr->attr, &state); + + if (state == ((1) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE)) + return ((20000 + 50000) + 3); + return ((20000 + 50000) + 4); +} + +apr_status_t apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize) +{ + int stat; + + stat = pthread_attr_setstacksize(&attr->attr, stacksize); + if (stat == 0) { + return 0; + } + + + + + return stat; +} + +apr_status_t apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t size) +{ + + apr_status_t rv; + + rv = pthread_attr_setguardsize(&attr->attr, size); + if (rv == 0) { + return 0; + } + + + + return rv; + + + +} + +static void *dummy_worker(void *opaque) +{ + apr_thread_t *thread = (apr_thread_t*)opaque; + return thread->func(thread, thread->data); +} + +apr_status_t apr_thread_create(apr_thread_t **new, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, + apr_pool_t *pool) +{ + apr_status_t stat; + pthread_attr_t *temp; + + (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); + + if ((*new) == ((void*)0)) { + return 12; + } + + (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t)); + + if ((*new)->td == ((void*)0)) { + return 12; + } + + (*new)->data = data; + (*new)->func = func; + + if (attr) + temp = &attr->attr; + else + temp = ((void*)0); + + stat = apr_pool_create_ex(&(*new)->pool, pool, ((void*)0), ((void*)0)); + if (stat != 0) { + return stat; + } + + if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) { + return 0; + } + else { + + + + + return stat; + } +} + +apr_os_thread_t apr_os_thread_current(void) +{ + return pthread_self(); +} + +int apr_os_thread_equal(apr_os_thread_t tid1, + apr_os_thread_t tid2) +{ + return pthread_equal(tid1, tid2); +} + +apr_status_t apr_thread_exit(apr_thread_t *thd, + apr_status_t retval) +{ + thd->exitval = retval; + apr_pool_destroy(thd->pool); + pthread_exit(((void*)0)); + return 0; +} + +apr_status_t apr_thread_join(apr_status_t *retval, + apr_thread_t *thd) +{ + apr_status_t stat; + apr_status_t *thread_stat; + + if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) { + *retval = thd->exitval; + return 0; + } + else { + + + + + return stat; + } +} + +apr_status_t apr_thread_detach(apr_thread_t *thd) +{ + apr_status_t stat; + + + + + if ((stat = pthread_detach(*thd->td)) == 0) { + + + return 0; + } + else { + + + + + return stat; + } +} + +void apr_thread_yield(void) +{ + + + + + pthread_yield(); + + + + + + +} + +apr_status_t apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread) +{ + return apr_pool_userdata_get(data, key, thread->pool); +} + +apr_status_t apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_thread_t *thread) +{ + return apr_pool_userdata_set(data, key, cleanup, thread->pool); +} + +apr_status_t apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd) +{ + *thethd = thd->td; + return 0; +} + +apr_status_t apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *pool) +{ + if (pool == ((void*)0)) { + return (20000 + 2); + } + + if ((*thd) == ((void*)0)) { + (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); + (*thd)->pool = pool; + } + + (*thd)->td = thethd; + return 0; +} + +apr_status_t apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p) +{ + static const pthread_once_t once_init = 0; + + *control = apr_palloc(p, sizeof(**control)); + (*control)->once = once_init; + return 0; +} + +apr_status_t apr_thread_once(apr_thread_once_t *control, + void (*func)(void)) +{ + return pthread_once(&control->once, func); +} + +apr_pool_t * apr_thread_pool_get (const apr_thread_t *thethread) { return thethread->pool; } +# 20 "main1.c" 2 +# 1 "./../test/abts.c" 1 +# 17 "./../test/abts.c" +# 1 "./../test/abts.h" 1 +# 18 "./../test/abts.c" 2 +# 1 "./../test/abts_tests.h" 1 +# 20 "./../test/abts_tests.h" +# 1 "./../test/abts.h" 1 +# 21 "./../test/abts_tests.h" 2 +# 1 "./../test/testutil.h" 1 +# 19 "./../test/testutil.h" +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 22 "./../test/abts_tests.h" 2 + +const struct testlist { + abts_suite *(*func)(abts_suite *suite); +} alltests[] = { + {testatomic}, + {testdir}, + {testdso}, + {testdup}, + {testenv}, + {testescape}, + {testfile}, + {testfilecopy}, + {testfileinfo}, + {testflock}, + {testfmt}, + {testfnmatch}, + {testgetopt}, + + + + {testhash}, + {testipsub}, + {testlock}, + {testcond}, + {testlfs}, + {testmmap}, + {testnames}, + {testoc}, + {testpath}, + {testpipe}, + {testpoll}, + {testpool}, + {testproc}, + {testprocmutex}, + {testrand}, + {testsleep}, + {testshm}, + {testsock}, + {testsockets}, + {testsockopt}, + {teststr}, + {teststrnatcmp}, + {testtable}, + {testtemp}, + {testthread}, + {testtime}, + {testud}, + {testuser}, + {testvsn} +}; +# 19 "./../test/abts.c" 2 +# 1 "./../test/testutil.h" 1 +# 19 "./../test/testutil.h" +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 20 "./../test/abts.c" 2 + + +static char status[6] = {'|', '/', '-', '|', '\\', '-'}; +static int curr_char; +static int verbose = 0; +static int exclude = 0; +static int quiet = 0; +static int list_tests = 0; + +const char **testlist = ((void*)0); + +static int find_test_name(const char *testname) { + int i; + for (i = 0; testlist[i] != ((void*)0); i++) { + if (!strcmp(testlist[i], testname)) { + return 1; + } + } + return 0; +} + + +static int should_test_run(const char *testname) { + int found = 0; + if (list_tests == 1) { + return 0; + } + if (testlist == ((void*)0)) { + return 1; + } + found = find_test_name(testname); + if ((found && !exclude) || (!found && exclude)) { + return 1; + } + return 0; +} + +static void reset_status(void) +{ + curr_char = 0; +} + +static void update_status(void) +{ + if (!quiet) { + curr_char = (curr_char + 1) % 6; + fprintf(stdout, "\b%c", status[curr_char]); + fflush(stdout); + } +} + +static void end_suite(abts_suite *suite) +{ + if (suite != ((void*)0)) { + sub_suite *last = suite->tail; + if (!quiet) { + fprintf(stdout, "\b"); + fflush(stdout); + } + if (last->failed == 0) { + fprintf(stdout, "SUCCESS\n"); + fflush(stdout); + } + else { + fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test); + fflush(stdout); + } + } +} + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full) +{ + sub_suite *subsuite; + char *p; + const char *suite_name; + curr_char = 0; + + + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + subsuite = malloc(sizeof(*subsuite)); + subsuite->num_test = 0; + subsuite->failed = 0; + subsuite->next = ((void*)0); + + + suite_name = strrchr(suite_name_full, '/'); + if (!suite_name) { + suite_name = strrchr(suite_name_full, '\\'); + } + if (suite_name) { + suite_name++; + } else { + suite_name = suite_name_full; + } + p = strrchr(suite_name, '.'); + if (p) { + subsuite->name = memcpy(calloc(p - suite_name + 1, 1), + suite_name, p - suite_name); + } + else { + subsuite->name = suite_name; + } + + if (list_tests) { + fprintf(stdout, "%s\n", subsuite->name); + } + + subsuite->not_run = 0; + + if (suite == ((void*)0)) { + suite = malloc(sizeof(*suite)); + suite->head = subsuite; + suite->tail = subsuite; + } + else { + suite->tail->next = subsuite; + suite->tail = subsuite; + } + + if (!should_test_run(subsuite->name)) { + subsuite->not_run = 1; + return suite; + } + + reset_status(); + fprintf(stdout, "%-20s: ", subsuite->name); + update_status(); + fflush(stdout); + + return suite; +} + +void abts_run_test(abts_suite *ts, test_func f, void *value) +{ + abts_case tc; + sub_suite *ss; + + if (!should_test_run(ts->tail->name)) { + return; + } + ss = ts->tail; + + tc.failed = 0; + tc.suite = ss; + + ss->num_test++; + update_status(); + + f(&tc, value); + + if (tc.failed) { + ss->failed++; + } +} + +static int report(abts_suite *suite) +{ + int count = 0; + sub_suite *dptr; + + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + for (dptr = suite->head; dptr; dptr = dptr->next) { + count += dptr->failed; + } + + if (list_tests) { + return 0; + } + + if (count == 0) { + printf("All tests passed.\n"); + return 0; + } + + dptr = suite->head; + fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); + fprintf(stdout, "===================================================\n"); + while (dptr != ((void*)0)) { + if (dptr->failed != 0) { + float percent = ((float)dptr->failed / (float)dptr->num_test); + fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, + dptr->num_test, dptr->failed, percent * 100); + } + dptr = dptr->next; + } + return 1; +} + +void abts_log_message(const char *fmt, ...) +{ + va_list args; + update_status(); + + if (verbose) { + __builtin_va_start(args, fmt); + vfprintf(stderr, fmt, args); + __builtin_va_end(args); + fprintf(stderr, "\n"); + fflush(stderr); + } +} + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected != actual) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected something other than <%d>, but saw <%d>\n", + lineno, expected, actual); + fflush(stderr); + } +} + +void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = 1; + if (verbose) { + + fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno, + (unsigned long)expected, (unsigned long)actual); + fflush(stderr); + } +} + +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!expected && !actual) return; + if (expected && actual) + if (!strcmp(expected, actual)) { return; } + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno) +{ + update_status(); + if (tc->failed) { return; } + + if (!strncmp(expected, actual, n)) { return; } + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected something other than <%s>, but saw <%s>\n", + lineno, expected, actual); + fflush(stderr); + } +} + +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno) +{ + update_status(); + if (tc->failed) { return; } + + if (ptr != ((void*)0)) { return; } + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected non-NULL, but saw NULL\n", lineno); + fflush(stderr); + } +} + +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno) +{ + update_status(); + if (tc->failed) { return; } + + if (expected == actual) { return; } + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_fail(abts_case *tc, const char *message, int lineno) +{ + update_status(); + if (tc->failed) { return; } + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_assert(abts_case *tc, const char *message, int condition, int lineno) +{ + update_status(); + if (tc->failed) { return; } + + if (condition) { return; } + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_true(abts_case *tc, int condition, int lineno) +{ + update_status(); + if (tc->failed) { return; } + + if (condition) { return; } + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno); + fflush(stderr); + } +} + +void abts_not_impl(abts_case *tc, const char *message, int lineno) +{ + update_status(); + + tc->suite->not_impl++; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} +# 21 "main1.c" 2 + + + + + + +int fflush(FILE *stream){ + return 0; +} + +int fprintf(FILE *stream, const char *format, ...){ + return 0; +} + +void test_atomics_threaded_1(abts_case *tc, void *data) +{ + apr_thread_t *t1[3]; + apr_status_t rv; + int i; + + + + + + rv = apr_thread_mutex_create(&thread_lock, 0x0, p); + (((rv == 0) && "Could not create lock") ? (void) (0) : __assert_fail ("(rv == 0) && \"Could not create lock\"", "main1.c", 46, __PRETTY_FUNCTION__)); + + for (i = 0; i < 3; i++) { + apr_status_t r1; + r1 = apr_thread_create(&t1[i], ((void*)0), thread_func_mutex, ((void*)0), p); + ((!r1 && "Failed creating threads") ? (void) (0) : __assert_fail ("!r1 && \"Failed creating threads\"", "main1.c", 51, __PRETTY_FUNCTION__)); + } + + for (i = 0; i < 3; i++) { + apr_status_t s1; + apr_thread_join(&s1, t1[i]); + + ((s1 == exit_ret_val && "Invalid return value from thread_join") ? (void) (0) : __assert_fail ("s1 == exit_ret_val && \"Invalid return value from thread_join\"", "main1.c", 59, __PRETTY_FUNCTION__)); + + } + + abts_int_equal(tc, 3 * 1, mutex_locks, 62); + + rv = apr_thread_mutex_destroy(thread_lock); + ((rv == 0 && "Failed creating threads") ? (void) (0) : __assert_fail ("rv == 0 && \"Failed creating threads\"", "main1.c", 65, __PRETTY_FUNCTION__)); +} + +int main(int argc, char *argv[]){ + + initialize(); + + abts_case tc; + tc.failed = 0; + tc.suite = ((void*)0); + test_atomics_threaded_1(&tc,((void*)0)); + + return 0; +} diff --git a/clang/test/apr_2_unannotated.c b/clang/test/apr_2_unannotated.c new file mode 100644 index 0000000..96bd6c6 --- /dev/null +++ b/clang/test/apr_2_unannotated.c @@ -0,0 +1,13827 @@ +/* Adapted from the sources of the Apache Portable Runtime library version 1.5.1: + * https://apr.apache.org/ + */ + +/* BOUND 5 */ +# 1 "main2.c" +# 1 "" 1 +# 1 "" 3 +# 312 "" 3 +# 1 "" 1 +# 1 "" 2 +# 1 "main2.c" 2 + + + + + +# 1 "./../test/abts.h" 1 +# 21 "./../test/abts.h" +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdarg.h" 1 3 +# 30 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdarg.h" 3 +typedef __builtin_va_list va_list; +# 50 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdarg.h" 3 +typedef __builtin_va_list __gnuc_va_list; +# 22 "./../test/abts.h" 2 +# 1 "/usr/include/stdio.h" 1 3 4 +# 27 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/features.h" 1 3 4 +# 352 "/usr/include/features.h" 3 4 +# 1 "/usr/include/stdc-predef.h" 1 3 4 +# 353 "/usr/include/features.h" 2 3 4 +# 374 "/usr/include/features.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4 +# 385 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 386 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4 +# 375 "/usr/include/features.h" 2 3 4 +# 398 "/usr/include/features.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4 +# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4 +# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4 +# 399 "/usr/include/features.h" 2 3 4 +# 28 "/usr/include/stdio.h" 2 3 4 + + + + + +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 58 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 3 4 +typedef long unsigned int size_t; +# 34 "/usr/include/stdio.h" 2 3 4 + +# 1 "/usr/include/x86_64-linux-gnu/bits/types.h" 1 3 4 +# 27 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 + + +typedef unsigned char __u_char; +typedef unsigned short int __u_short; +typedef unsigned int __u_int; +typedef unsigned long int __u_long; + + +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef signed short int __int16_t; +typedef unsigned short int __uint16_t; +typedef signed int __int32_t; +typedef unsigned int __uint32_t; + +typedef signed long int __int64_t; +typedef unsigned long int __uint64_t; + + + + + + + +typedef long int __quad_t; +typedef unsigned long int __u_quad_t; +# 121 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/typesizes.h" 1 3 4 +# 122 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 + + +typedef unsigned long int __dev_t; +typedef unsigned int __uid_t; +typedef unsigned int __gid_t; +typedef unsigned long int __ino_t; +typedef unsigned long int __ino64_t; +typedef unsigned int __mode_t; +typedef unsigned long int __nlink_t; +typedef long int __off_t; +typedef long int __off64_t; +typedef int __pid_t; +typedef struct { int __val[2]; } __fsid_t; +typedef long int __clock_t; +typedef unsigned long int __rlim_t; +typedef unsigned long int __rlim64_t; +typedef unsigned int __id_t; +typedef long int __time_t; +typedef unsigned int __useconds_t; +typedef long int __suseconds_t; + +typedef int __daddr_t; +typedef int __key_t; + + +typedef int __clockid_t; + + +typedef void * __timer_t; + + +typedef long int __blksize_t; + + + + +typedef long int __blkcnt_t; +typedef long int __blkcnt64_t; + + +typedef unsigned long int __fsblkcnt_t; +typedef unsigned long int __fsblkcnt64_t; + + +typedef unsigned long int __fsfilcnt_t; +typedef unsigned long int __fsfilcnt64_t; + + +typedef long int __fsword_t; + +typedef long int __ssize_t; + + +typedef long int __syscall_slong_t; + +typedef unsigned long int __syscall_ulong_t; + + + +typedef __off64_t __loff_t; +typedef __quad_t *__qaddr_t; +typedef char *__caddr_t; + + +typedef long int __intptr_t; + + +typedef unsigned int __socklen_t; +# 36 "/usr/include/stdio.h" 2 3 4 + + + + + + + + +struct _IO_FILE; + + + +typedef struct _IO_FILE FILE; +# 64 "/usr/include/stdio.h" 3 4 +typedef struct _IO_FILE __FILE; +# 74 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/libio.h" 1 3 4 +# 31 "/usr/include/libio.h" 3 4 +# 1 "/usr/include/_G_config.h" 1 3 4 +# 15 "/usr/include/_G_config.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 16 "/usr/include/_G_config.h" 2 3 4 + + + + +# 1 "/usr/include/wchar.h" 1 3 4 +# 82 "/usr/include/wchar.h" 3 4 +typedef struct +{ + int __count; + union + { + + unsigned int __wch; + + + + char __wchb[4]; + } __value; +} __mbstate_t; +# 21 "/usr/include/_G_config.h" 2 3 4 +typedef struct +{ + __off_t __pos; + __mbstate_t __state; +} _G_fpos_t; +typedef struct +{ + __off64_t __pos; + __mbstate_t __state; +} _G_fpos64_t; +# 32 "/usr/include/libio.h" 2 3 4 +# 144 "/usr/include/libio.h" 3 4 +struct _IO_jump_t; struct _IO_FILE; +# 154 "/usr/include/libio.h" 3 4 +typedef void _IO_lock_t; + + + + + +struct _IO_marker { + struct _IO_marker *_next; + struct _IO_FILE *_sbuf; + + + + int _pos; +# 177 "/usr/include/libio.h" 3 4 +}; + + +enum __codecvt_result +{ + __codecvt_ok, + __codecvt_partial, + __codecvt_error, + __codecvt_noconv +}; +# 245 "/usr/include/libio.h" 3 4 +struct _IO_FILE { + int _flags; + + + + + char* _IO_read_ptr; + char* _IO_read_end; + char* _IO_read_base; + char* _IO_write_base; + char* _IO_write_ptr; + char* _IO_write_end; + char* _IO_buf_base; + char* _IO_buf_end; + + char *_IO_save_base; + char *_IO_backup_base; + char *_IO_save_end; + + struct _IO_marker *_markers; + + struct _IO_FILE *_chain; + + int _fileno; + + + + int _flags2; + + __off_t _old_offset; + + + + unsigned short _cur_column; + signed char _vtable_offset; + char _shortbuf[1]; + + + + _IO_lock_t *_lock; +# 293 "/usr/include/libio.h" 3 4 + __off64_t _offset; +# 302 "/usr/include/libio.h" 3 4 + void *__pad1; + void *__pad2; + void *__pad3; + void *__pad4; + size_t __pad5; + + int _mode; + + char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]; + +}; + + +typedef struct _IO_FILE _IO_FILE; + + +struct _IO_FILE_plus; + +extern struct _IO_FILE_plus _IO_2_1_stdin_; +extern struct _IO_FILE_plus _IO_2_1_stdout_; +extern struct _IO_FILE_plus _IO_2_1_stderr_; +# 338 "/usr/include/libio.h" 3 4 +typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes); + + + + + + + +typedef __ssize_t __io_write_fn (void *__cookie, const char *__buf, + size_t __n); + + + + + + + +typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w); + + +typedef int __io_close_fn (void *__cookie); +# 390 "/usr/include/libio.h" 3 4 +extern int __underflow (_IO_FILE *); +extern int __uflow (_IO_FILE *); +extern int __overflow (_IO_FILE *, int); +# 434 "/usr/include/libio.h" 3 4 +extern int _IO_getc (_IO_FILE *__fp); +extern int _IO_putc (int __c, _IO_FILE *__fp); +extern int _IO_feof (_IO_FILE *__fp) __attribute__ ((__nothrow__ )); +extern int _IO_ferror (_IO_FILE *__fp) __attribute__ ((__nothrow__ )); + +extern int _IO_peekc_locked (_IO_FILE *__fp); + + + + + +extern void _IO_flockfile (_IO_FILE *) __attribute__ ((__nothrow__ )); +extern void _IO_funlockfile (_IO_FILE *) __attribute__ ((__nothrow__ )); +extern int _IO_ftrylockfile (_IO_FILE *) __attribute__ ((__nothrow__ )); +# 464 "/usr/include/libio.h" 3 4 +extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict, + __gnuc_va_list, int *__restrict); +extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict, + __gnuc_va_list); +extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t); +extern size_t _IO_sgetn (_IO_FILE *, void *, size_t); + +extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t, int, int); +extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t, int); + +extern void _IO_free_backup_area (_IO_FILE *) __attribute__ ((__nothrow__ )); +# 75 "/usr/include/stdio.h" 2 3 4 + + + + +typedef __gnuc_va_list va_list; +# 90 "/usr/include/stdio.h" 3 4 +typedef __off_t off_t; +# 102 "/usr/include/stdio.h" 3 4 +typedef __ssize_t ssize_t; + + + + + + + +typedef _G_fpos_t fpos_t; +# 164 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/stdio_lim.h" 1 3 4 +# 165 "/usr/include/stdio.h" 2 3 4 + + + +extern struct _IO_FILE *stdin; +extern struct _IO_FILE *stdout; +extern struct _IO_FILE *stderr; + + + + + + + +extern int remove (const char *__filename) __attribute__ ((__nothrow__ )); + +extern int rename (const char *__old, const char *__new) __attribute__ ((__nothrow__ )); + + + + +extern int renameat (int __oldfd, const char *__old, int __newfd, + const char *__new) __attribute__ ((__nothrow__ )); +# 195 "/usr/include/stdio.h" 3 4 +extern FILE *tmpfile (void) ; +# 209 "/usr/include/stdio.h" 3 4 +extern char *tmpnam (char *__s) __attribute__ ((__nothrow__ )) ; + + + + + +extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__ )) ; +# 227 "/usr/include/stdio.h" 3 4 +extern char *tempnam (const char *__dir, const char *__pfx) + __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ; +# 237 "/usr/include/stdio.h" 3 4 +extern int fclose (FILE *__stream); + + + + +extern int fflush (FILE *__stream); +# 252 "/usr/include/stdio.h" 3 4 +extern int fflush_unlocked (FILE *__stream); +# 272 "/usr/include/stdio.h" 3 4 +extern FILE *fopen (const char *__restrict __filename, + const char *__restrict __modes) ; + + + + +extern FILE *freopen (const char *__restrict __filename, + const char *__restrict __modes, + FILE *__restrict __stream) ; +# 306 "/usr/include/stdio.h" 3 4 +extern FILE *fdopen (int __fd, const char *__modes) __attribute__ ((__nothrow__ )) ; +# 319 "/usr/include/stdio.h" 3 4 +extern FILE *fmemopen (void *__s, size_t __len, const char *__modes) + __attribute__ ((__nothrow__ )) ; + + + + +extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__ )) ; + + + + + + +extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__ )); + + + +extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf, + int __modes, size_t __n) __attribute__ ((__nothrow__ )); + + + + + +extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf, + size_t __size) __attribute__ ((__nothrow__ )); + + +extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__ )); +# 356 "/usr/include/stdio.h" 3 4 +extern int fprintf (FILE *__restrict __stream, + const char *__restrict __format, ...); + + + + +extern int printf (const char *__restrict __format, ...); + +extern int sprintf (char *__restrict __s, + const char *__restrict __format, ...) __attribute__ ((__nothrow__)); + + + + + +extern int vfprintf (FILE *__restrict __s, const char *__restrict __format, + __gnuc_va_list __arg); + + + + +extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg); + +extern int vsprintf (char *__restrict __s, const char *__restrict __format, + __gnuc_va_list __arg) __attribute__ ((__nothrow__)); + + + + + +extern int snprintf (char *__restrict __s, size_t __maxlen, + const char *__restrict __format, ...) + __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4))); + +extern int vsnprintf (char *__restrict __s, size_t __maxlen, + const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0))); +# 412 "/usr/include/stdio.h" 3 4 +extern int vdprintf (int __fd, const char *__restrict __fmt, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__printf__, 2, 0))); +extern int dprintf (int __fd, const char *__restrict __fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +# 425 "/usr/include/stdio.h" 3 4 +extern int fscanf (FILE *__restrict __stream, + const char *__restrict __format, ...) ; + + + + +extern int scanf (const char *__restrict __format, ...) ; + +extern int sscanf (const char *__restrict __s, + const char *__restrict __format, ...) __attribute__ ((__nothrow__ )); +# 443 "/usr/include/stdio.h" 3 4 +extern int fscanf (FILE *__restrict __stream, const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf") ; + + +extern int scanf (const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf") ; + +extern int sscanf (const char *__restrict __s, const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__ )); +# 471 "/usr/include/stdio.h" 3 4 +extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 2, 0))) ; + + + + + +extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 1, 0))) ; + + +extern int vsscanf (const char *__restrict __s, + const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__nothrow__ )) __attribute__ ((__format__ (__scanf__, 2, 0))); +# 494 "/usr/include/stdio.h" 3 4 +extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf") + + + + __attribute__ ((__format__ (__scanf__, 2, 0))) ; +extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf") + + __attribute__ ((__format__ (__scanf__, 1, 0))) ; +extern int vsscanf (const char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf") __attribute__ ((__nothrow__ )) + + + + __attribute__ ((__format__ (__scanf__, 2, 0))); +# 531 "/usr/include/stdio.h" 3 4 +extern int fgetc (FILE *__stream); +extern int getc (FILE *__stream); + + + + + +extern int getchar (void); +# 550 "/usr/include/stdio.h" 3 4 +extern int getc_unlocked (FILE *__stream); +extern int getchar_unlocked (void); +# 561 "/usr/include/stdio.h" 3 4 +extern int fgetc_unlocked (FILE *__stream); +# 573 "/usr/include/stdio.h" 3 4 +extern int fputc (int __c, FILE *__stream); +extern int putc (int __c, FILE *__stream); + + + + + +extern int putchar (int __c); +# 594 "/usr/include/stdio.h" 3 4 +extern int fputc_unlocked (int __c, FILE *__stream); + + + + + + + +extern int putc_unlocked (int __c, FILE *__stream); +extern int putchar_unlocked (int __c); + + + + + + +extern int getw (FILE *__stream); + + +extern int putw (int __w, FILE *__stream); +# 622 "/usr/include/stdio.h" 3 4 +extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) + ; +# 638 "/usr/include/stdio.h" 3 4 +extern char *gets (char *__s) __attribute__ ((__deprecated__)); +# 665 "/usr/include/stdio.h" 3 4 +extern __ssize_t __getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) ; +extern __ssize_t getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) ; + + + + + + + +extern __ssize_t getline (char **__restrict __lineptr, + size_t *__restrict __n, + FILE *__restrict __stream) ; +# 689 "/usr/include/stdio.h" 3 4 +extern int fputs (const char *__restrict __s, FILE *__restrict __stream); + + + + + +extern int puts (const char *__s); + + + + + + +extern int ungetc (int __c, FILE *__stream); + + + + + + +extern size_t fread (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) ; + + + + +extern size_t fwrite (const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __s); +# 737 "/usr/include/stdio.h" 3 4 +extern size_t fread_unlocked (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) ; +extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream); +# 749 "/usr/include/stdio.h" 3 4 +extern int fseek (FILE *__stream, long int __off, int __whence); + + + + +extern long int ftell (FILE *__stream) ; + + + + +extern void rewind (FILE *__stream); +# 773 "/usr/include/stdio.h" 3 4 +extern int fseeko (FILE *__stream, __off_t __off, int __whence); + + + + +extern __off_t ftello (FILE *__stream) ; +# 798 "/usr/include/stdio.h" 3 4 +extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos); + + + + +extern int fsetpos (FILE *__stream, const fpos_t *__pos); +# 826 "/usr/include/stdio.h" 3 4 +extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__ )); + +extern int feof (FILE *__stream) __attribute__ ((__nothrow__ )) ; + +extern int ferror (FILE *__stream) __attribute__ ((__nothrow__ )) ; + + + + +extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__ )); +extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__ )) ; +extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__ )) ; +# 846 "/usr/include/stdio.h" 3 4 +extern void perror (const char *__s); + + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 3 4 +extern int sys_nerr; +extern const char *const sys_errlist[]; +# 854 "/usr/include/stdio.h" 2 3 4 + + + + +extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ )) ; + + + + +extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ )) ; +# 873 "/usr/include/stdio.h" 3 4 +extern FILE *popen (const char *__command, const char *__modes) ; + + + + + +extern int pclose (FILE *__stream); + + + + + +extern char *ctermid (char *__s) __attribute__ ((__nothrow__ )); +# 913 "/usr/include/stdio.h" 3 4 +extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ )); + + + +extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ )) ; + + +extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ )); +# 23 "./../test/abts.h" 2 +# 1 "/usr/include/stdlib.h" 1 3 4 +# 32 "/usr/include/stdlib.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 86 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 3 4 +typedef int wchar_t; +# 33 "/usr/include/stdlib.h" 2 3 4 + + + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/waitflags.h" 1 3 4 +# 50 "/usr/include/x86_64-linux-gnu/bits/waitflags.h" 3 4 +typedef enum +{ + P_ALL, + P_PID, + P_PGID +} idtype_t; +# 42 "/usr/include/stdlib.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/waitstatus.h" 1 3 4 +# 64 "/usr/include/x86_64-linux-gnu/bits/waitstatus.h" 3 4 +# 1 "/usr/include/endian.h" 1 3 4 +# 36 "/usr/include/endian.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/endian.h" 1 3 4 +# 37 "/usr/include/endian.h" 2 3 4 +# 60 "/usr/include/endian.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 2 3 4 + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/byteswap-16.h" 1 3 4 +# 36 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 2 3 4 +# 61 "/usr/include/endian.h" 2 3 4 +# 65 "/usr/include/x86_64-linux-gnu/bits/waitstatus.h" 2 3 4 + +union wait + { + int w_status; + struct + { + + unsigned int __w_termsig:7; + unsigned int __w_coredump:1; + unsigned int __w_retcode:8; + unsigned int:16; + + + + + + + + } __wait_terminated; + struct + { + + unsigned int __w_stopval:8; + unsigned int __w_stopsig:8; + unsigned int:16; + + + + + + + } __wait_stopped; + }; +# 43 "/usr/include/stdlib.h" 2 3 4 +# 67 "/usr/include/stdlib.h" 3 4 +typedef union + { + union wait *__uptr; + int *__iptr; + } __WAIT_STATUS __attribute__ ((__transparent_union__)); +# 97 "/usr/include/stdlib.h" 3 4 +typedef struct + { + int quot; + int rem; + } div_t; + + + +typedef struct + { + long int quot; + long int rem; + } ldiv_t; + + + + + + + +__extension__ typedef struct + { + long long int quot; + long long int rem; + } lldiv_t; +# 139 "/usr/include/stdlib.h" 3 4 +extern size_t __ctype_get_mb_cur_max (void) __attribute__ ((__nothrow__ )) ; + + + + +extern double atof (const char *__nptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + +extern int atoi (const char *__nptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + +extern long int atol (const char *__nptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + + + + + +__extension__ extern long long int atoll (const char *__nptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + + + + + +extern double strtod (const char *__restrict __nptr, + char **__restrict __endptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern float strtof (const char *__restrict __nptr, + char **__restrict __endptr) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + +extern long double strtold (const char *__restrict __nptr, + char **__restrict __endptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern long int strtol (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + +extern unsigned long int strtoul (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + +__extension__ +extern long long int strtoq (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + +__extension__ +extern unsigned long long int strtouq (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +__extension__ +extern long long int strtoll (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + +__extension__ +extern unsigned long long int strtoull (const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 305 "/usr/include/stdlib.h" 3 4 +extern char *l64a (long int __n) __attribute__ ((__nothrow__ )) ; + + +extern long int a64l (const char *__s) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ; + + + + + +# 1 "/usr/include/x86_64-linux-gnu/sys/types.h" 1 3 4 +# 33 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef __u_char u_char; +typedef __u_short u_short; +typedef __u_int u_int; +typedef __u_long u_long; +typedef __quad_t quad_t; +typedef __u_quad_t u_quad_t; +typedef __fsid_t fsid_t; + + + + +typedef __loff_t loff_t; + + + +typedef __ino_t ino_t; +# 60 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef __dev_t dev_t; + + + + +typedef __gid_t gid_t; + + + + +typedef __mode_t mode_t; + + + + +typedef __nlink_t nlink_t; + + + + +typedef __uid_t uid_t; +# 98 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef __pid_t pid_t; + + + + + +typedef __id_t id_t; +# 115 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef __daddr_t daddr_t; +typedef __caddr_t caddr_t; + + + + + +typedef __key_t key_t; +# 132 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 59 "/usr/include/time.h" 3 4 +typedef __clock_t clock_t; +# 75 "/usr/include/time.h" 3 4 +typedef __time_t time_t; +# 91 "/usr/include/time.h" 3 4 +typedef __clockid_t clockid_t; +# 103 "/usr/include/time.h" 3 4 +typedef __timer_t timer_t; +# 133 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 +# 146 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 147 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 + + + +typedef unsigned long int ulong; +typedef unsigned short int ushort; +typedef unsigned int uint; +# 194 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +typedef int int8_t __attribute__ ((__mode__ (__QI__))); +typedef int int16_t __attribute__ ((__mode__ (__HI__))); +typedef int int32_t __attribute__ ((__mode__ (__SI__))); +typedef int int64_t __attribute__ ((__mode__ (__DI__))); + + +typedef unsigned int u_int8_t __attribute__ ((__mode__ (__QI__))); +typedef unsigned int u_int16_t __attribute__ ((__mode__ (__HI__))); +typedef unsigned int u_int32_t __attribute__ ((__mode__ (__SI__))); +typedef unsigned int u_int64_t __attribute__ ((__mode__ (__DI__))); + +typedef int register_t __attribute__ ((__mode__ (__word__))); +# 219 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/sys/select.h" 1 3 4 +# 30 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/select.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/select.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/bits/select.h" 2 3 4 +# 31 "/usr/include/x86_64-linux-gnu/sys/select.h" 2 3 4 + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sigset.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/sigset.h" 3 4 +typedef int __sig_atomic_t; + + + + +typedef struct + { + unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))]; + } __sigset_t; +# 34 "/usr/include/x86_64-linux-gnu/sys/select.h" 2 3 4 + + + +typedef __sigset_t sigset_t; + + + + + + +# 1 "/usr/include/time.h" 1 3 4 +# 120 "/usr/include/time.h" 3 4 +struct timespec + { + __time_t tv_sec; + __syscall_slong_t tv_nsec; + }; +# 44 "/usr/include/x86_64-linux-gnu/sys/select.h" 2 3 4 + +# 1 "/usr/include/x86_64-linux-gnu/bits/time.h" 1 3 4 +# 30 "/usr/include/x86_64-linux-gnu/bits/time.h" 3 4 +struct timeval + { + __time_t tv_sec; + __suseconds_t tv_usec; + }; +# 46 "/usr/include/x86_64-linux-gnu/sys/select.h" 2 3 4 + + +typedef __suseconds_t suseconds_t; + + + + + +typedef long int __fd_mask; +# 64 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4 +typedef struct + { + + + + + + + __fd_mask __fds_bits[1024 / (8 * (int) sizeof (__fd_mask))]; + + + } fd_set; + + + + + + +typedef __fd_mask fd_mask; +# 106 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4 +extern int select (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + struct timeval *__restrict __timeout); +# 118 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4 +extern int pselect (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + const struct timespec *__restrict __timeout, + const __sigset_t *__restrict __sigmask); +# 220 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 + + +# 1 "/usr/include/x86_64-linux-gnu/sys/sysmacros.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/sys/sysmacros.h" 3 4 +__extension__ +extern unsigned int gnu_dev_major (unsigned long long int __dev) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +__extension__ +extern unsigned int gnu_dev_minor (unsigned long long int __dev) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +__extension__ +extern unsigned long long int gnu_dev_makedev (unsigned int __major, + unsigned int __minor) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 223 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 + + + + + +typedef __blksize_t blksize_t; + + + + + + +typedef __blkcnt_t blkcnt_t; + + + +typedef __fsblkcnt_t fsblkcnt_t; + + + +typedef __fsfilcnt_t fsfilcnt_t; +# 270 "/usr/include/x86_64-linux-gnu/sys/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 1 3 4 +# 21 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 2 3 4 +# 60 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 +typedef unsigned long int pthread_t; + + +union pthread_attr_t +{ + char __size[56]; + long int __align; +}; + +typedef union pthread_attr_t pthread_attr_t; + + + + + +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +# 90 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + + unsigned int __nusers; + + + + int __kind; + + short __spins; + short __elision; + __pthread_list_t __list; +# 124 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 + } __data; + char __size[40]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[4]; + int __align; +} pthread_mutexattr_t; + + + + +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[48]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[4]; + int __align; +} pthread_condattr_t; + + + +typedef unsigned int pthread_key_t; + + + +typedef int pthread_once_t; + + + + + +typedef union +{ + + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + + + unsigned int __flags; + + } __data; +# 211 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" 3 4 + char __size[56]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[8]; + long int __align; +} pthread_rwlockattr_t; + + + + + +typedef volatile int pthread_spinlock_t; + + + + +typedef union +{ + char __size[32]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[4]; + int __align; +} pthread_barrierattr_t; +# 271 "/usr/include/x86_64-linux-gnu/sys/types.h" 2 3 4 +# 315 "/usr/include/stdlib.h" 2 3 4 + + + + + + +extern long int random (void) __attribute__ ((__nothrow__ )); + + +extern void srandom (unsigned int __seed) __attribute__ ((__nothrow__ )); + + + + + +extern char *initstate (unsigned int __seed, char *__statebuf, + size_t __statelen) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + +extern char *setstate (char *__statebuf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + + +struct random_data + { + int32_t *fptr; + int32_t *rptr; + int32_t *state; + int rand_type; + int rand_deg; + int rand_sep; + int32_t *end_ptr; + }; + +extern int random_r (struct random_data *__restrict __buf, + int32_t *__restrict __result) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + +extern int srandom_r (unsigned int __seed, struct random_data *__buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + +extern int initstate_r (unsigned int __seed, char *__restrict __statebuf, + size_t __statelen, + struct random_data *__restrict __buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))); + +extern int setstate_r (char *__restrict __statebuf, + struct random_data *__restrict __buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + + + +extern int rand (void) __attribute__ ((__nothrow__ )); + +extern void srand (unsigned int __seed) __attribute__ ((__nothrow__ )); + + + + +extern int rand_r (unsigned int *__seed) __attribute__ ((__nothrow__ )); + + + + + + + +extern double drand48 (void) __attribute__ ((__nothrow__ )); +extern double erand48 (unsigned short int __xsubi[3]) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern long int lrand48 (void) __attribute__ ((__nothrow__ )); +extern long int nrand48 (unsigned short int __xsubi[3]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern long int mrand48 (void) __attribute__ ((__nothrow__ )); +extern long int jrand48 (unsigned short int __xsubi[3]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern void srand48 (long int __seedval) __attribute__ ((__nothrow__ )); +extern unsigned short int *seed48 (unsigned short int __seed16v[3]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +extern void lcong48 (unsigned short int __param[7]) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +struct drand48_data + { + unsigned short int __x[3]; + unsigned short int __old_x[3]; + unsigned short int __c; + unsigned short int __init; + __extension__ unsigned long long int __a; + + }; + + +extern int drand48_r (struct drand48_data *__restrict __buffer, + double *__restrict __result) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern int erand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + double *__restrict __result) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int lrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern int nrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int mrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern int jrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int srand48_r (long int __seedval, struct drand48_data *__buffer) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + +extern int seed48_r (unsigned short int __seed16v[3], + struct drand48_data *__buffer) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + +extern int lcong48_r (unsigned short int __param[7], + struct drand48_data *__buffer) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +# 466 "/usr/include/stdlib.h" 3 4 +extern void *malloc (size_t __size) __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ; + +extern void *calloc (size_t __nmemb, size_t __size) + __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ; +# 480 "/usr/include/stdlib.h" 3 4 +extern void *realloc (void *__ptr, size_t __size) + __attribute__ ((__nothrow__ )) __attribute__ ((__warn_unused_result__)); + +extern void free (void *__ptr) __attribute__ ((__nothrow__ )); + + + + +extern void cfree (void *__ptr) __attribute__ ((__nothrow__ )); + + + + +# 1 "/usr/include/alloca.h" 1 3 4 +# 24 "/usr/include/alloca.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 25 "/usr/include/alloca.h" 2 3 4 + + + + + + + +extern void *alloca (size_t __size) __attribute__ ((__nothrow__ )); +# 493 "/usr/include/stdlib.h" 2 3 4 + + + + + +extern void *valloc (size_t __size) __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ; + + + + +extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 515 "/usr/include/stdlib.h" 3 4 +extern void abort (void) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); + + + +extern int atexit (void (*__func) (void)) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 535 "/usr/include/stdlib.h" 3 4 +extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + +extern void exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); +# 557 "/usr/include/stdlib.h" 3 4 +extern void _Exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); + + + + + + +extern char *getenv (const char *__name) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 578 "/usr/include/stdlib.h" 3 4 +extern int putenv (char *__string) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int setenv (const char *__name, const char *__value, int __replace) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + +extern int unsetenv (const char *__name) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int clearenv (void) __attribute__ ((__nothrow__ )); +# 606 "/usr/include/stdlib.h" 3 4 +extern char *mktemp (char *__template) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 620 "/usr/include/stdlib.h" 3 4 +extern int mkstemp (char *__template) __attribute__ ((__nonnull__ (1))) ; +# 642 "/usr/include/stdlib.h" 3 4 +extern int mkstemps (char *__template, int __suffixlen) __attribute__ ((__nonnull__ (1))) ; +# 663 "/usr/include/stdlib.h" 3 4 +extern char *mkdtemp (char *__template) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 717 "/usr/include/stdlib.h" 3 4 +extern int system (const char *__command) ; +# 734 "/usr/include/stdlib.h" 3 4 +extern char *realpath (const char *__restrict __name, + char *__restrict __resolved) __attribute__ ((__nothrow__ )) ; + + + + + + +typedef int (*__compar_fn_t) (const void *, const void *); +# 755 "/usr/include/stdlib.h" 3 4 +extern void *bsearch (const void *__key, const void *__base, + size_t __nmemb, size_t __size, __compar_fn_t __compar) + __attribute__ ((__nonnull__ (1, 2, 5))) ; + + + + + + + +extern void qsort (void *__base, size_t __nmemb, size_t __size, + __compar_fn_t __compar) __attribute__ ((__nonnull__ (1, 4))); +# 775 "/usr/include/stdlib.h" 3 4 +extern int abs (int __x) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; +extern long int labs (long int __x) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; + + + +__extension__ extern long long int llabs (long long int __x) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; + + + + + + + +extern div_t div (int __numer, int __denom) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; +extern ldiv_t ldiv (long int __numer, long int __denom) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; + + + + +__extension__ extern lldiv_t lldiv (long long int __numer, + long long int __denom) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ; +# 812 "/usr/include/stdlib.h" 3 4 +extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))) ; + + + + +extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))) ; + + + + +extern char *gcvt (double __value, int __ndigit, char *__buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3))) ; + + + + +extern char *qecvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))) ; +extern char *qfcvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))) ; +extern char *qgcvt (long double __value, int __ndigit, char *__buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3))) ; + + + + +extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4, 5))); +extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4, 5))); + +extern int qecvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4, 5))); +extern int qfcvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4, 5))); + + + + + + +extern int mblen (const char *__s, size_t __n) __attribute__ ((__nothrow__ )); + + +extern int mbtowc (wchar_t *__restrict __pwc, + const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ )); + + +extern int wctomb (char *__s, wchar_t __wchar) __attribute__ ((__nothrow__ )); + + + +extern size_t mbstowcs (wchar_t *__restrict __pwcs, + const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ )); + +extern size_t wcstombs (char *__restrict __s, + const wchar_t *__restrict __pwcs, size_t __n) + __attribute__ ((__nothrow__ )); +# 888 "/usr/include/stdlib.h" 3 4 +extern int rpmatch (const char *__response) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 899 "/usr/include/stdlib.h" 3 4 +extern int getsubopt (char **__restrict __optionp, + char *const *__restrict __tokens, + char **__restrict __valuep) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2, 3))) ; +# 951 "/usr/include/stdlib.h" 3 4 +extern int getloadavg (double __loadavg[], int __nelem) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/stdlib-float.h" 1 3 4 +# 956 "/usr/include/stdlib.h" 2 3 4 +# 24 "./../test/abts.h" 2 +# 1 "/usr/include/string.h" 1 3 4 +# 32 "/usr/include/string.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 33 "/usr/include/string.h" 2 3 4 +# 46 "/usr/include/string.h" 3 4 +extern void *memcpy (void *__restrict __dest, const void *__restrict __src, + size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern void *memmove (void *__dest, const void *__src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + + + +extern void *memccpy (void *__restrict __dest, const void *__restrict __src, + int __c, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + + +extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int memcmp (const void *__s1, const void *__s2, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 96 "/usr/include/string.h" 3 4 +extern void *memchr (const void *__s, int __c, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +# 129 "/usr/include/string.h" 3 4 +extern char *strcpy (char *__restrict __dest, const char *__restrict __src) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + +extern char *strncpy (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern char *strcat (char *__restrict __dest, const char *__restrict __src) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + +extern char *strncat (char *__restrict __dest, const char *__restrict __src, + size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int strcmp (const char *__s1, const char *__s2) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + +extern int strncmp (const char *__s1, const char *__s2, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + + +extern int strcoll (const char *__s1, const char *__s2) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + +extern size_t strxfrm (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + + + + +# 1 "/usr/include/xlocale.h" 1 3 4 +# 27 "/usr/include/xlocale.h" 3 4 +typedef struct __locale_struct +{ + + struct __locale_data *__locales[13]; + + + const unsigned short int *__ctype_b; + const int *__ctype_tolower; + const int *__ctype_toupper; + + + const char *__names[13]; +} *__locale_t; + + +typedef __locale_t locale_t; +# 164 "/usr/include/string.h" 2 3 4 + + +extern int strcoll_l (const char *__s1, const char *__s2, __locale_t __l) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 3))); + +extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n, + __locale_t __l) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))); + + + + + +extern char *strdup (const char *__s) + __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1))); + + + + + + +extern char *strndup (const char *__string, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1))); +# 236 "/usr/include/string.h" 3 4 +extern char *strchr (const char *__s, int __c) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +# 263 "/usr/include/string.h" 3 4 +extern char *strrchr (const char *__s, int __c) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +# 285 "/usr/include/string.h" 3 4 +extern size_t strcspn (const char *__s, const char *__reject) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + + +extern size_t strspn (const char *__s, const char *__accept) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 315 "/usr/include/string.h" 3 4 +extern char *strpbrk (const char *__s, const char *__accept) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 342 "/usr/include/string.h" 3 4 +extern char *strstr (const char *__haystack, const char *__needle) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern char *strtok (char *__restrict __s, const char *__restrict __delim) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + +extern char *__strtok_r (char *__restrict __s, + const char *__restrict __delim, + char **__restrict __save_ptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); + +extern char *strtok_r (char *__restrict __s, const char *__restrict __delim, + char **__restrict __save_ptr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); +# 399 "/usr/include/string.h" 3 4 +extern size_t strlen (const char *__s) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); + + + + + +extern size_t strnlen (const char *__string, size_t __maxlen) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); + + + + + +extern char *strerror (int __errnum) __attribute__ ((__nothrow__ )); +# 427 "/usr/include/string.h" 3 4 +extern int strerror_r (int __errnum, char *__buf, size_t __buflen) __asm__ ("" "__xpg_strerror_r") __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); +# 445 "/usr/include/string.h" 3 4 +extern char *strerror_l (int __errnum, __locale_t __l) __attribute__ ((__nothrow__ )); + + + + + +extern void __bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern void bcopy (const void *__src, void *__dest, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern void bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int bcmp (const void *__s1, const void *__s2, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 489 "/usr/include/string.h" 3 4 +extern char *index (const char *__s, int __c) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +# 517 "/usr/include/string.h" 3 4 +extern char *rindex (const char *__s, int __c) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); + + + + +extern int ffs (int __i) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 534 "/usr/include/string.h" 3 4 +extern int strcasecmp (const char *__s1, const char *__s2) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); + + +extern int strncasecmp (const char *__s1, const char *__s2, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 557 "/usr/include/string.h" 3 4 +extern char *strsep (char **__restrict __stringp, + const char *__restrict __delim) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern char *strsignal (int __sig) __attribute__ ((__nothrow__ )); + + +extern char *__stpcpy (char *__restrict __dest, const char *__restrict __src) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern char *stpcpy (char *__restrict __dest, const char *__restrict __src) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern char *__stpncpy (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +extern char *stpncpy (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +# 25 "./../test/abts.h" 2 + + + +# 1 "/usr/include/unistd.h" 1 3 4 +# 202 "/usr/include/unistd.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/posix_opt.h" 1 3 4 +# 203 "/usr/include/unistd.h" 2 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/environments.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/environments.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/bits/environments.h" 2 3 4 +# 207 "/usr/include/unistd.h" 2 3 4 +# 226 "/usr/include/unistd.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 227 "/usr/include/unistd.h" 2 3 4 +# 255 "/usr/include/unistd.h" 3 4 +typedef __useconds_t useconds_t; +# 267 "/usr/include/unistd.h" 3 4 +typedef __intptr_t intptr_t; + + + + + + +typedef __socklen_t socklen_t; +# 287 "/usr/include/unistd.h" 3 4 +extern int access (const char *__name, int __type) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 304 "/usr/include/unistd.h" 3 4 +extern int faccessat (int __fd, const char *__file, int __type, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))) ; +# 334 "/usr/include/unistd.h" 3 4 +extern __off_t lseek (int __fd, __off_t __offset, int __whence) __attribute__ ((__nothrow__ )); +# 353 "/usr/include/unistd.h" 3 4 +extern int close (int __fd); + + + + + + +extern ssize_t read (int __fd, void *__buf, size_t __nbytes) ; + + + + + +extern ssize_t write (int __fd, const void *__buf, size_t __n) ; +# 376 "/usr/include/unistd.h" 3 4 +extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, + __off_t __offset) ; + + + + + + +extern ssize_t pwrite (int __fd, const void *__buf, size_t __n, + __off_t __offset) ; +# 417 "/usr/include/unistd.h" 3 4 +extern int pipe (int __pipedes[2]) __attribute__ ((__nothrow__ )) ; +# 432 "/usr/include/unistd.h" 3 4 +extern unsigned int alarm (unsigned int __seconds) __attribute__ ((__nothrow__ )); +# 444 "/usr/include/unistd.h" 3 4 +extern unsigned int sleep (unsigned int __seconds); + + + + + + + +extern __useconds_t ualarm (__useconds_t __value, __useconds_t __interval) + __attribute__ ((__nothrow__ )); + + + + + + +extern int usleep (__useconds_t __useconds); +# 469 "/usr/include/unistd.h" 3 4 +extern int pause (void); + + + +extern int chown (const char *__file, __uid_t __owner, __gid_t __group) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + +extern int fchown (int __fd, __uid_t __owner, __gid_t __group) __attribute__ ((__nothrow__ )) ; + + + + +extern int lchown (const char *__file, __uid_t __owner, __gid_t __group) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + + + + +extern int fchownat (int __fd, const char *__file, __uid_t __owner, + __gid_t __group, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))) ; + + + +extern int chdir (const char *__path) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + +extern int fchdir (int __fd) __attribute__ ((__nothrow__ )) ; +# 511 "/usr/include/unistd.h" 3 4 +extern char *getcwd (char *__buf, size_t __size) __attribute__ ((__nothrow__ )) ; +# 525 "/usr/include/unistd.h" 3 4 +extern char *getwd (char *__buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) __attribute__ ((__deprecated__)) ; + + + + +extern int dup (int __fd) __attribute__ ((__nothrow__ )) ; + + +extern int dup2 (int __fd, int __fd2) __attribute__ ((__nothrow__ )); +# 543 "/usr/include/unistd.h" 3 4 +extern char **__environ; + + + + + + + +extern int execve (const char *__path, char *const __argv[], + char *const __envp[]) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern int fexecve (int __fd, char *const __argv[], char *const __envp[]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + +extern int execv (const char *__path, char *const __argv[]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int execle (const char *__path, const char *__arg, ...) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int execl (const char *__path, const char *__arg, ...) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int execvp (const char *__file, char *const __argv[]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern int execlp (const char *__file, const char *__arg, ...) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +# 598 "/usr/include/unistd.h" 3 4 +extern int nice (int __inc) __attribute__ ((__nothrow__ )) ; + + + + +extern void _exit (int __status) __attribute__ ((__noreturn__)); + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/confname.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/confname.h" 3 4 +enum + { + _PC_LINK_MAX, + + _PC_MAX_CANON, + + _PC_MAX_INPUT, + + _PC_NAME_MAX, + + _PC_PATH_MAX, + + _PC_PIPE_BUF, + + _PC_CHOWN_RESTRICTED, + + _PC_NO_TRUNC, + + _PC_VDISABLE, + + _PC_SYNC_IO, + + _PC_ASYNC_IO, + + _PC_PRIO_IO, + + _PC_SOCK_MAXBUF, + + _PC_FILESIZEBITS, + + _PC_REC_INCR_XFER_SIZE, + + _PC_REC_MAX_XFER_SIZE, + + _PC_REC_MIN_XFER_SIZE, + + _PC_REC_XFER_ALIGN, + + _PC_ALLOC_SIZE_MIN, + + _PC_SYMLINK_MAX, + + _PC_2_SYMLINKS + + }; + + +enum + { + _SC_ARG_MAX, + + _SC_CHILD_MAX, + + _SC_CLK_TCK, + + _SC_NGROUPS_MAX, + + _SC_OPEN_MAX, + + _SC_STREAM_MAX, + + _SC_TZNAME_MAX, + + _SC_JOB_CONTROL, + + _SC_SAVED_IDS, + + _SC_REALTIME_SIGNALS, + + _SC_PRIORITY_SCHEDULING, + + _SC_TIMERS, + + _SC_ASYNCHRONOUS_IO, + + _SC_PRIORITIZED_IO, + + _SC_SYNCHRONIZED_IO, + + _SC_FSYNC, + + _SC_MAPPED_FILES, + + _SC_MEMLOCK, + + _SC_MEMLOCK_RANGE, + + _SC_MEMORY_PROTECTION, + + _SC_MESSAGE_PASSING, + + _SC_SEMAPHORES, + + _SC_SHARED_MEMORY_OBJECTS, + + _SC_AIO_LISTIO_MAX, + + _SC_AIO_MAX, + + _SC_AIO_PRIO_DELTA_MAX, + + _SC_DELAYTIMER_MAX, + + _SC_MQ_OPEN_MAX, + + _SC_MQ_PRIO_MAX, + + _SC_VERSION, + + _SC_PAGESIZE, + + + _SC_RTSIG_MAX, + + _SC_SEM_NSEMS_MAX, + + _SC_SEM_VALUE_MAX, + + _SC_SIGQUEUE_MAX, + + _SC_TIMER_MAX, + + + + + _SC_BC_BASE_MAX, + + _SC_BC_DIM_MAX, + + _SC_BC_SCALE_MAX, + + _SC_BC_STRING_MAX, + + _SC_COLL_WEIGHTS_MAX, + + _SC_EQUIV_CLASS_MAX, + + _SC_EXPR_NEST_MAX, + + _SC_LINE_MAX, + + _SC_RE_DUP_MAX, + + _SC_CHARCLASS_NAME_MAX, + + + _SC_2_VERSION, + + _SC_2_C_BIND, + + _SC_2_C_DEV, + + _SC_2_FORT_DEV, + + _SC_2_FORT_RUN, + + _SC_2_SW_DEV, + + _SC_2_LOCALEDEF, + + + _SC_PII, + + _SC_PII_XTI, + + _SC_PII_SOCKET, + + _SC_PII_INTERNET, + + _SC_PII_OSI, + + _SC_POLL, + + _SC_SELECT, + + _SC_UIO_MAXIOV, + + _SC_IOV_MAX = _SC_UIO_MAXIOV, + + _SC_PII_INTERNET_STREAM, + + _SC_PII_INTERNET_DGRAM, + + _SC_PII_OSI_COTS, + + _SC_PII_OSI_CLTS, + + _SC_PII_OSI_M, + + _SC_T_IOV_MAX, + + + + _SC_THREADS, + + _SC_THREAD_SAFE_FUNCTIONS, + + _SC_GETGR_R_SIZE_MAX, + + _SC_GETPW_R_SIZE_MAX, + + _SC_LOGIN_NAME_MAX, + + _SC_TTY_NAME_MAX, + + _SC_THREAD_DESTRUCTOR_ITERATIONS, + + _SC_THREAD_KEYS_MAX, + + _SC_THREAD_STACK_MIN, + + _SC_THREAD_THREADS_MAX, + + _SC_THREAD_ATTR_STACKADDR, + + _SC_THREAD_ATTR_STACKSIZE, + + _SC_THREAD_PRIORITY_SCHEDULING, + + _SC_THREAD_PRIO_INHERIT, + + _SC_THREAD_PRIO_PROTECT, + + _SC_THREAD_PROCESS_SHARED, + + + _SC_NPROCESSORS_CONF, + + _SC_NPROCESSORS_ONLN, + + _SC_PHYS_PAGES, + + _SC_AVPHYS_PAGES, + + _SC_ATEXIT_MAX, + + _SC_PASS_MAX, + + + _SC_XOPEN_VERSION, + + _SC_XOPEN_XCU_VERSION, + + _SC_XOPEN_UNIX, + + _SC_XOPEN_CRYPT, + + _SC_XOPEN_ENH_I18N, + + _SC_XOPEN_SHM, + + + _SC_2_CHAR_TERM, + + _SC_2_C_VERSION, + + _SC_2_UPE, + + + _SC_XOPEN_XPG2, + + _SC_XOPEN_XPG3, + + _SC_XOPEN_XPG4, + + + _SC_CHAR_BIT, + + _SC_CHAR_MAX, + + _SC_CHAR_MIN, + + _SC_INT_MAX, + + _SC_INT_MIN, + + _SC_LONG_BIT, + + _SC_WORD_BIT, + + _SC_MB_LEN_MAX, + + _SC_NZERO, + + _SC_SSIZE_MAX, + + _SC_SCHAR_MAX, + + _SC_SCHAR_MIN, + + _SC_SHRT_MAX, + + _SC_SHRT_MIN, + + _SC_UCHAR_MAX, + + _SC_UINT_MAX, + + _SC_ULONG_MAX, + + _SC_USHRT_MAX, + + + _SC_NL_ARGMAX, + + _SC_NL_LANGMAX, + + _SC_NL_MSGMAX, + + _SC_NL_NMAX, + + _SC_NL_SETMAX, + + _SC_NL_TEXTMAX, + + + _SC_XBS5_ILP32_OFF32, + + _SC_XBS5_ILP32_OFFBIG, + + _SC_XBS5_LP64_OFF64, + + _SC_XBS5_LPBIG_OFFBIG, + + + _SC_XOPEN_LEGACY, + + _SC_XOPEN_REALTIME, + + _SC_XOPEN_REALTIME_THREADS, + + + _SC_ADVISORY_INFO, + + _SC_BARRIERS, + + _SC_BASE, + + _SC_C_LANG_SUPPORT, + + _SC_C_LANG_SUPPORT_R, + + _SC_CLOCK_SELECTION, + + _SC_CPUTIME, + + _SC_THREAD_CPUTIME, + + _SC_DEVICE_IO, + + _SC_DEVICE_SPECIFIC, + + _SC_DEVICE_SPECIFIC_R, + + _SC_FD_MGMT, + + _SC_FIFO, + + _SC_PIPE, + + _SC_FILE_ATTRIBUTES, + + _SC_FILE_LOCKING, + + _SC_FILE_SYSTEM, + + _SC_MONOTONIC_CLOCK, + + _SC_MULTI_PROCESS, + + _SC_SINGLE_PROCESS, + + _SC_NETWORKING, + + _SC_READER_WRITER_LOCKS, + + _SC_SPIN_LOCKS, + + _SC_REGEXP, + + _SC_REGEX_VERSION, + + _SC_SHELL, + + _SC_SIGNALS, + + _SC_SPAWN, + + _SC_SPORADIC_SERVER, + + _SC_THREAD_SPORADIC_SERVER, + + _SC_SYSTEM_DATABASE, + + _SC_SYSTEM_DATABASE_R, + + _SC_TIMEOUTS, + + _SC_TYPED_MEMORY_OBJECTS, + + _SC_USER_GROUPS, + + _SC_USER_GROUPS_R, + + _SC_2_PBS, + + _SC_2_PBS_ACCOUNTING, + + _SC_2_PBS_LOCATE, + + _SC_2_PBS_MESSAGE, + + _SC_2_PBS_TRACK, + + _SC_SYMLOOP_MAX, + + _SC_STREAMS, + + _SC_2_PBS_CHECKPOINT, + + + _SC_V6_ILP32_OFF32, + + _SC_V6_ILP32_OFFBIG, + + _SC_V6_LP64_OFF64, + + _SC_V6_LPBIG_OFFBIG, + + + _SC_HOST_NAME_MAX, + + _SC_TRACE, + + _SC_TRACE_EVENT_FILTER, + + _SC_TRACE_INHERIT, + + _SC_TRACE_LOG, + + + _SC_LEVEL1_ICACHE_SIZE, + + _SC_LEVEL1_ICACHE_ASSOC, + + _SC_LEVEL1_ICACHE_LINESIZE, + + _SC_LEVEL1_DCACHE_SIZE, + + _SC_LEVEL1_DCACHE_ASSOC, + + _SC_LEVEL1_DCACHE_LINESIZE, + + _SC_LEVEL2_CACHE_SIZE, + + _SC_LEVEL2_CACHE_ASSOC, + + _SC_LEVEL2_CACHE_LINESIZE, + + _SC_LEVEL3_CACHE_SIZE, + + _SC_LEVEL3_CACHE_ASSOC, + + _SC_LEVEL3_CACHE_LINESIZE, + + _SC_LEVEL4_CACHE_SIZE, + + _SC_LEVEL4_CACHE_ASSOC, + + _SC_LEVEL4_CACHE_LINESIZE, + + + + _SC_IPV6 = _SC_LEVEL1_ICACHE_SIZE + 50, + + _SC_RAW_SOCKETS, + + + _SC_V7_ILP32_OFF32, + + _SC_V7_ILP32_OFFBIG, + + _SC_V7_LP64_OFF64, + + _SC_V7_LPBIG_OFFBIG, + + + _SC_SS_REPL_MAX, + + + _SC_TRACE_EVENT_NAME_MAX, + + _SC_TRACE_NAME_MAX, + + _SC_TRACE_SYS_MAX, + + _SC_TRACE_USER_EVENT_MAX, + + + _SC_XOPEN_STREAMS, + + + _SC_THREAD_ROBUST_PRIO_INHERIT, + + _SC_THREAD_ROBUST_PRIO_PROTECT + + }; + + +enum + { + _CS_PATH, + + + _CS_V6_WIDTH_RESTRICTED_ENVS, + + + + _CS_GNU_LIBC_VERSION, + + _CS_GNU_LIBPTHREAD_VERSION, + + + _CS_V5_WIDTH_RESTRICTED_ENVS, + + + + _CS_V7_WIDTH_RESTRICTED_ENVS, + + + + _CS_LFS_CFLAGS = 1000, + + _CS_LFS_LDFLAGS, + + _CS_LFS_LIBS, + + _CS_LFS_LINTFLAGS, + + _CS_LFS64_CFLAGS, + + _CS_LFS64_LDFLAGS, + + _CS_LFS64_LIBS, + + _CS_LFS64_LINTFLAGS, + + + _CS_XBS5_ILP32_OFF32_CFLAGS = 1100, + + _CS_XBS5_ILP32_OFF32_LDFLAGS, + + _CS_XBS5_ILP32_OFF32_LIBS, + + _CS_XBS5_ILP32_OFF32_LINTFLAGS, + + _CS_XBS5_ILP32_OFFBIG_CFLAGS, + + _CS_XBS5_ILP32_OFFBIG_LDFLAGS, + + _CS_XBS5_ILP32_OFFBIG_LIBS, + + _CS_XBS5_ILP32_OFFBIG_LINTFLAGS, + + _CS_XBS5_LP64_OFF64_CFLAGS, + + _CS_XBS5_LP64_OFF64_LDFLAGS, + + _CS_XBS5_LP64_OFF64_LIBS, + + _CS_XBS5_LP64_OFF64_LINTFLAGS, + + _CS_XBS5_LPBIG_OFFBIG_CFLAGS, + + _CS_XBS5_LPBIG_OFFBIG_LDFLAGS, + + _CS_XBS5_LPBIG_OFFBIG_LIBS, + + _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS, + + + _CS_POSIX_V6_ILP32_OFF32_CFLAGS, + + _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, + + _CS_POSIX_V6_ILP32_OFF32_LIBS, + + _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS, + + _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS, + + _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS, + + _CS_POSIX_V6_ILP32_OFFBIG_LIBS, + + _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS, + + _CS_POSIX_V6_LP64_OFF64_CFLAGS, + + _CS_POSIX_V6_LP64_OFF64_LDFLAGS, + + _CS_POSIX_V6_LP64_OFF64_LIBS, + + _CS_POSIX_V6_LP64_OFF64_LINTFLAGS, + + _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS, + + _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, + + _CS_POSIX_V6_LPBIG_OFFBIG_LIBS, + + _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS, + + + _CS_POSIX_V7_ILP32_OFF32_CFLAGS, + + _CS_POSIX_V7_ILP32_OFF32_LDFLAGS, + + _CS_POSIX_V7_ILP32_OFF32_LIBS, + + _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS, + + _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS, + + _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS, + + _CS_POSIX_V7_ILP32_OFFBIG_LIBS, + + _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS, + + _CS_POSIX_V7_LP64_OFF64_CFLAGS, + + _CS_POSIX_V7_LP64_OFF64_LDFLAGS, + + _CS_POSIX_V7_LP64_OFF64_LIBS, + + _CS_POSIX_V7_LP64_OFF64_LINTFLAGS, + + _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS, + + _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS, + + _CS_POSIX_V7_LPBIG_OFFBIG_LIBS, + + _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS, + + + _CS_V6_ENV, + + _CS_V7_ENV + + }; +# 610 "/usr/include/unistd.h" 2 3 4 + + +extern long int pathconf (const char *__path, int __name) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern long int fpathconf (int __fd, int __name) __attribute__ ((__nothrow__ )); + + +extern long int sysconf (int __name) __attribute__ ((__nothrow__ )); + + + +extern size_t confstr (int __name, char *__buf, size_t __len) __attribute__ ((__nothrow__ )); + + + + +extern __pid_t getpid (void) __attribute__ ((__nothrow__ )); + + +extern __pid_t getppid (void) __attribute__ ((__nothrow__ )); + + +extern __pid_t getpgrp (void) __attribute__ ((__nothrow__ )); + + +extern __pid_t __getpgid (__pid_t __pid) __attribute__ ((__nothrow__ )); + +extern __pid_t getpgid (__pid_t __pid) __attribute__ ((__nothrow__ )); + + + + + + +extern int setpgid (__pid_t __pid, __pid_t __pgid) __attribute__ ((__nothrow__ )); +# 660 "/usr/include/unistd.h" 3 4 +extern int setpgrp (void) __attribute__ ((__nothrow__ )); + + + + + + +extern __pid_t setsid (void) __attribute__ ((__nothrow__ )); + + + +extern __pid_t getsid (__pid_t __pid) __attribute__ ((__nothrow__ )); + + + +extern __uid_t getuid (void) __attribute__ ((__nothrow__ )); + + +extern __uid_t geteuid (void) __attribute__ ((__nothrow__ )); + + +extern __gid_t getgid (void) __attribute__ ((__nothrow__ )); + + +extern __gid_t getegid (void) __attribute__ ((__nothrow__ )); + + + + +extern int getgroups (int __size, __gid_t __list[]) __attribute__ ((__nothrow__ )) ; +# 700 "/usr/include/unistd.h" 3 4 +extern int setuid (__uid_t __uid) __attribute__ ((__nothrow__ )) ; + + + + +extern int setreuid (__uid_t __ruid, __uid_t __euid) __attribute__ ((__nothrow__ )) ; + + + + +extern int seteuid (__uid_t __uid) __attribute__ ((__nothrow__ )) ; + + + + + + +extern int setgid (__gid_t __gid) __attribute__ ((__nothrow__ )) ; + + + + +extern int setregid (__gid_t __rgid, __gid_t __egid) __attribute__ ((__nothrow__ )) ; + + + + +extern int setegid (__gid_t __gid) __attribute__ ((__nothrow__ )) ; +# 756 "/usr/include/unistd.h" 3 4 +extern __pid_t fork (void) __attribute__ ((__nothrow__)); + + + + + + + +extern __pid_t vfork (void) __attribute__ ((__nothrow__ )); + + + + + +extern char *ttyname (int __fd) __attribute__ ((__nothrow__ )); + + + +extern int ttyname_r (int __fd, char *__buf, size_t __buflen) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))) ; + + + +extern int isatty (int __fd) __attribute__ ((__nothrow__ )); + + + + + +extern int ttyslot (void) __attribute__ ((__nothrow__ )); + + + + +extern int link (const char *__from, const char *__to) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))) ; + + + + +extern int linkat (int __fromfd, const char *__from, int __tofd, + const char *__to, int __flags) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))) ; + + + + +extern int symlink (const char *__from, const char *__to) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))) ; + + + + +extern ssize_t readlink (const char *__restrict __path, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))) ; + + + + +extern int symlinkat (const char *__from, int __tofd, + const char *__to) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 3))) ; + + +extern ssize_t readlinkat (int __fd, const char *__restrict __path, + char *__restrict __buf, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))) ; + + + +extern int unlink (const char *__name) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int unlinkat (int __fd, const char *__name, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + +extern int rmdir (const char *__path) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern __pid_t tcgetpgrp (int __fd) __attribute__ ((__nothrow__ )); + + +extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) __attribute__ ((__nothrow__ )); + + + + + + +extern char *getlogin (void); + + + + + + + +extern int getlogin_r (char *__name, size_t __name_len) __attribute__ ((__nonnull__ (1))); + + + + +extern int setlogin (const char *__name) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 871 "/usr/include/unistd.h" 3 4 +# 1 "/usr/include/getopt.h" 1 3 4 +# 57 "/usr/include/getopt.h" 3 4 +extern char *optarg; +# 71 "/usr/include/getopt.h" 3 4 +extern int optind; + + + + +extern int opterr; + + + +extern int optopt; +# 150 "/usr/include/getopt.h" 3 4 +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __attribute__ ((__nothrow__ )); +# 872 "/usr/include/unistd.h" 2 3 4 + + + + + + + +extern int gethostname (char *__name, size_t __len) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int sethostname (const char *__name, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + +extern int sethostid (long int __id) __attribute__ ((__nothrow__ )) ; + + + + + +extern int getdomainname (char *__name, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +extern int setdomainname (const char *__name, size_t __len) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + + + +extern int vhangup (void) __attribute__ ((__nothrow__ )); + + +extern int revoke (const char *__file) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + + + + + +extern int profil (unsigned short int *__sample_buffer, size_t __size, + size_t __offset, unsigned int __scale) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int acct (const char *__name) __attribute__ ((__nothrow__ )); + + + +extern char *getusershell (void) __attribute__ ((__nothrow__ )); +extern void endusershell (void) __attribute__ ((__nothrow__ )); +extern void setusershell (void) __attribute__ ((__nothrow__ )); + + + + + +extern int daemon (int __nochdir, int __noclose) __attribute__ ((__nothrow__ )) ; + + + + + + +extern int chroot (const char *__path) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; + + + +extern char *getpass (const char *__prompt) __attribute__ ((__nonnull__ (1))); + + + + + + + +extern int fsync (int __fd); +# 969 "/usr/include/unistd.h" 3 4 +extern long int gethostid (void); + + +extern void sync (void) __attribute__ ((__nothrow__ )); + + + + + +extern int getpagesize (void) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + + + +extern int getdtablesize (void) __attribute__ ((__nothrow__ )); +# 993 "/usr/include/unistd.h" 3 4 +extern int truncate (const char *__file, __off_t __length) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) ; +# 1016 "/usr/include/unistd.h" 3 4 +extern int ftruncate (int __fd, __off_t __length) __attribute__ ((__nothrow__ )) ; +# 1037 "/usr/include/unistd.h" 3 4 +extern int brk (void *__addr) __attribute__ ((__nothrow__ )) ; + + + + + +extern void *sbrk (intptr_t __delta) __attribute__ ((__nothrow__ )); +# 1058 "/usr/include/unistd.h" 3 4 +extern long int syscall (long int __sysno, ...) __attribute__ ((__nothrow__ )); +# 1081 "/usr/include/unistd.h" 3 4 +extern int lockf (int __fd, int __cmd, __off_t __len) ; +# 1112 "/usr/include/unistd.h" 3 4 +extern int fdatasync (int __fildes); +# 29 "./../test/abts.h" 2 +# 41 "./../test/abts.h" +struct sub_suite { + const char *name; + int num_test; + int failed; + int not_run; + int not_impl; + struct sub_suite *next; +}; +typedef struct sub_suite sub_suite; + +struct abts_suite { + sub_suite *head; + sub_suite *tail; +}; +typedef struct abts_suite abts_suite; + +struct abts_case { + int failed; + sub_suite *suite; +}; +typedef struct abts_case abts_case; + +typedef void (*test_func)(abts_case *tc, void *data); + + + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name); +void abts_run_test(abts_suite *ts, test_func f, void *value); +void abts_log_message(const char *fmt, ...); + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno); +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno); +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno); +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno); +void abts_true(abts_case *tc, int condition, int lineno); +void abts_fail(abts_case *tc, const char *message, int lineno); +void abts_not_impl(abts_case *tc, const char *message, int lineno); +void abts_assert(abts_case *tc, const char *message, int condition, int lineno); +void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno); +# 99 "./../test/abts.h" +abts_suite *run_tests(abts_suite *suite); +abts_suite *run_tests1(abts_suite *suite); +# 7 "main2.c" 2 +# 1 "./../test/testutil.h" 1 +# 17 "./../test/testutil.h" +# 1 "../include/apr_pools.h" 1 +# 43 "../include/apr_pools.h" +# 1 "../include/apr.h" 1 +# 168 "../include/apr.h" +# 1 "/usr/include/x86_64-linux-gnu/sys/socket.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/sys/uio.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/uio.h" 1 3 4 +# 43 "/usr/include/x86_64-linux-gnu/bits/uio.h" 3 4 +struct iovec + { + void *iov_base; + size_t iov_len; + }; +# 29 "/usr/include/x86_64-linux-gnu/sys/uio.h" 2 3 4 +# 39 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +extern ssize_t readv (int __fd, const struct iovec *__iovec, int __count) + ; +# 50 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +extern ssize_t writev (int __fd, const struct iovec *__iovec, int __count) + ; +# 65 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +extern ssize_t preadv (int __fd, const struct iovec *__iovec, int __count, + __off_t __offset) ; +# 77 "/usr/include/x86_64-linux-gnu/sys/uio.h" 3 4 +extern ssize_t pwritev (int __fd, const struct iovec *__iovec, int __count, + __off_t __offset) ; +# 27 "/usr/include/x86_64-linux-gnu/sys/socket.h" 2 3 4 + +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/sys/socket.h" 2 3 4 +# 38 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/socket.h" 1 3 4 +# 27 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/socket.h" 2 3 4 +# 38 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/socket_type.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/socket_type.h" 3 4 +enum __socket_type +{ + SOCK_STREAM = 1, + + + SOCK_DGRAM = 2, + + + SOCK_RAW = 3, + + SOCK_RDM = 4, + + SOCK_SEQPACKET = 5, + + + SOCK_DCCP = 6, + + SOCK_PACKET = 10, + + + + + + + + SOCK_CLOEXEC = 02000000, + + + SOCK_NONBLOCK = 00004000 + + +}; +# 39 "/usr/include/x86_64-linux-gnu/bits/socket.h" 2 3 4 +# 146 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/sockaddr.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/sockaddr.h" 3 4 +typedef unsigned short int sa_family_t; +# 147 "/usr/include/x86_64-linux-gnu/bits/socket.h" 2 3 4 + + +struct sockaddr + { + sa_family_t sa_family; + char sa_data[14]; + }; +# 162 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +struct sockaddr_storage + { + sa_family_t ss_family; + unsigned long int __ss_align; + char __ss_padding[(128 - (2 * sizeof (unsigned long int)))]; + }; + + + +enum + { + MSG_OOB = 0x01, + + MSG_PEEK = 0x02, + + MSG_DONTROUTE = 0x04, + + + + + + + MSG_CTRUNC = 0x08, + + MSG_PROXY = 0x10, + + MSG_TRUNC = 0x20, + + MSG_DONTWAIT = 0x40, + + MSG_EOR = 0x80, + + MSG_WAITALL = 0x100, + + MSG_FIN = 0x200, + + MSG_SYN = 0x400, + + MSG_CONFIRM = 0x800, + + MSG_RST = 0x1000, + + MSG_ERRQUEUE = 0x2000, + + MSG_NOSIGNAL = 0x4000, + + MSG_MORE = 0x8000, + + MSG_WAITFORONE = 0x10000, + + MSG_FASTOPEN = 0x20000000, + + + MSG_CMSG_CLOEXEC = 0x40000000 + + + + }; + + + + +struct msghdr + { + void *msg_name; + socklen_t msg_namelen; + + struct iovec *msg_iov; + size_t msg_iovlen; + + void *msg_control; + size_t msg_controllen; + + + + + int msg_flags; + }; + + +struct cmsghdr + { + size_t cmsg_len; + + + + + int cmsg_level; + int cmsg_type; + + __extension__ unsigned char __cmsg_data []; + + }; +# 272 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __attribute__ ((__nothrow__ )); +# 299 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +enum + { + SCM_RIGHTS = 0x01 + + + + + + }; +# 345 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/asm/socket.h" 1 3 4 +# 1 "/usr/include/asm-generic/socket.h" 1 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/asm/sockios.h" 1 3 4 +# 1 "/usr/include/asm-generic/sockios.h" 1 3 4 +# 2 "/usr/include/x86_64-linux-gnu/asm/sockios.h" 2 3 4 +# 5 "/usr/include/asm-generic/socket.h" 2 3 4 +# 2 "/usr/include/x86_64-linux-gnu/asm/socket.h" 2 3 4 +# 346 "/usr/include/x86_64-linux-gnu/bits/socket.h" 2 3 4 +# 379 "/usr/include/x86_64-linux-gnu/bits/socket.h" 3 4 +struct linger + { + int l_onoff; + int l_linger; + }; +# 39 "/usr/include/x86_64-linux-gnu/sys/socket.h" 2 3 4 + + + + +struct osockaddr + { + unsigned short int sa_family; + unsigned char sa_data[14]; + }; + + + + +enum +{ + SHUT_RD = 0, + + SHUT_WR, + + SHUT_RDWR + +}; +# 113 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int socket (int __domain, int __type, int __protocol) __attribute__ ((__nothrow__ )); + + + + + +extern int socketpair (int __domain, int __type, int __protocol, + int __fds[2]) __attribute__ ((__nothrow__ )); + + +extern int bind (int __fd, const struct sockaddr * __addr, socklen_t __len) + __attribute__ ((__nothrow__ )); + + +extern int getsockname (int __fd, struct sockaddr *__restrict __addr, + socklen_t *__restrict __len) __attribute__ ((__nothrow__ )); +# 137 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int connect (int __fd, const struct sockaddr * __addr, socklen_t __len); + + + +extern int getpeername (int __fd, struct sockaddr *__restrict __addr, + socklen_t *__restrict __len) __attribute__ ((__nothrow__ )); + + + + + + +extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); + + + + + + +extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); + + + + + + +extern ssize_t sendto (int __fd, const void *__buf, size_t __n, + int __flags, const struct sockaddr * __addr, + socklen_t __addr_len); +# 174 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n, + int __flags, struct sockaddr *__restrict __addr, + socklen_t *__restrict __addr_len); + + + + + + + +extern ssize_t sendmsg (int __fd, const struct msghdr *__message, + int __flags); +# 202 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags); +# 219 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int getsockopt (int __fd, int __level, int __optname, + void *__restrict __optval, + socklen_t *__restrict __optlen) __attribute__ ((__nothrow__ )); + + + + +extern int setsockopt (int __fd, int __level, int __optname, + const void *__optval, socklen_t __optlen) __attribute__ ((__nothrow__ )); + + + + + +extern int listen (int __fd, int __n) __attribute__ ((__nothrow__ )); +# 243 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int accept (int __fd, struct sockaddr *__restrict __addr, + socklen_t *__restrict __addr_len); +# 261 "/usr/include/x86_64-linux-gnu/sys/socket.h" 3 4 +extern int shutdown (int __fd, int __how) __attribute__ ((__nothrow__ )); + + + + +extern int sockatmark (int __fd) __attribute__ ((__nothrow__ )); + + + + + + + +extern int isfdtype (int __fd, int __fdtype) __attribute__ ((__nothrow__ )); +# 169 "../include/apr.h" 2 +# 178 "../include/apr.h" +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdint.h" 1 3 +# 61 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdint.h" 3 +# 1 "/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include/stdint.h" 1 3 4 + + + + + + + + +# 1 "/usr/include/stdint.h" 1 3 4 +# 26 "/usr/include/stdint.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wchar.h" 1 3 4 +# 27 "/usr/include/stdint.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 28 "/usr/include/stdint.h" 2 3 4 +# 48 "/usr/include/stdint.h" 3 4 +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; + +typedef unsigned int uint32_t; + + + +typedef unsigned long int uint64_t; +# 65 "/usr/include/stdint.h" 3 4 +typedef signed char int_least8_t; +typedef short int int_least16_t; +typedef int int_least32_t; + +typedef long int int_least64_t; + + + + + + +typedef unsigned char uint_least8_t; +typedef unsigned short int uint_least16_t; +typedef unsigned int uint_least32_t; + +typedef unsigned long int uint_least64_t; +# 90 "/usr/include/stdint.h" 3 4 +typedef signed char int_fast8_t; + +typedef long int int_fast16_t; +typedef long int int_fast32_t; +typedef long int int_fast64_t; +# 103 "/usr/include/stdint.h" 3 4 +typedef unsigned char uint_fast8_t; + +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; +typedef unsigned long int uint_fast64_t; +# 122 "/usr/include/stdint.h" 3 4 +typedef unsigned long int uintptr_t; +# 134 "/usr/include/stdint.h" 3 4 +typedef long int intmax_t; +typedef unsigned long int uintmax_t; +# 10 "/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/include/stdint.h" 2 3 4 +# 62 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdint.h" 2 3 +# 179 "../include/apr.h" 2 + + + +# 1 "/usr/include/x86_64-linux-gnu/sys/wait.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +# 1 "/usr/include/signal.h" 1 3 4 +# 32 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/sigset.h" 1 3 4 +# 102 "/usr/include/x86_64-linux-gnu/bits/sigset.h" 3 4 +extern int __sigismember (const __sigset_t *, int); +extern int __sigaddset (__sigset_t *, int); +extern int __sigdelset (__sigset_t *, int); +# 33 "/usr/include/signal.h" 2 3 4 + + + + + + + +typedef __sig_atomic_t sig_atomic_t; +# 57 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/signum.h" 1 3 4 +# 58 "/usr/include/signal.h" 2 3 4 +# 75 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 76 "/usr/include/signal.h" 2 3 4 + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 2 3 4 + + + + + + + +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +# 58 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +typedef __clock_t __sigchld_clock_t; + + + +typedef struct + { + int si_signo; + int si_errno; + + int si_code; + + union + { + int _pad[((128 / sizeof (int)) - 4)]; + + + struct + { + __pid_t si_pid; + __uid_t si_uid; + } _kill; + + + struct + { + int si_tid; + int si_overrun; + sigval_t si_sigval; + } _timer; + + + struct + { + __pid_t si_pid; + __uid_t si_uid; + sigval_t si_sigval; + } _rt; + + + struct + { + __pid_t si_pid; + __uid_t si_uid; + int si_status; + __sigchld_clock_t si_utime; + __sigchld_clock_t si_stime; + } _sigchld; + + + struct + { + void *si_addr; + short int si_addr_lsb; + } _sigfault; + + + struct + { + long int si_band; + int si_fd; + } _sigpoll; + + + struct + { + void *_call_addr; + int _syscall; + unsigned int _arch; + } _sigsys; + } _sifields; + } siginfo_t ; +# 153 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +enum +{ + SI_ASYNCNL = -60, + + SI_TKILL = -6, + + SI_SIGIO, + + SI_ASYNCIO, + + SI_MESGQ, + + SI_TIMER, + + SI_QUEUE, + + SI_USER, + + SI_KERNEL = 0x80 + +}; + + + +enum +{ + ILL_ILLOPC = 1, + + ILL_ILLOPN, + + ILL_ILLADR, + + ILL_ILLTRP, + + ILL_PRVOPC, + + ILL_PRVREG, + + ILL_COPROC, + + ILL_BADSTK + +}; + + +enum +{ + FPE_INTDIV = 1, + + FPE_INTOVF, + + FPE_FLTDIV, + + FPE_FLTOVF, + + FPE_FLTUND, + + FPE_FLTRES, + + FPE_FLTINV, + + FPE_FLTSUB + +}; + + +enum +{ + SEGV_MAPERR = 1, + + SEGV_ACCERR + +}; + + +enum +{ + BUS_ADRALN = 1, + + BUS_ADRERR, + + BUS_OBJERR, + + BUS_MCEERR_AR, + + BUS_MCEERR_AO + +}; + + +enum +{ + TRAP_BRKPT = 1, + + TRAP_TRACE + +}; + + +enum +{ + CLD_EXITED = 1, + + CLD_KILLED, + + CLD_DUMPED, + + CLD_TRAPPED, + + CLD_STOPPED, + + CLD_CONTINUED + +}; + + +enum +{ + POLL_IN = 1, + + POLL_OUT, + + POLL_MSG, + + POLL_ERR, + + POLL_PRI, + + POLL_HUP + +}; +# 307 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[((64 / sizeof (int)) - 4)]; + + + + __pid_t _tid; + + struct + { + void (*_function) (sigval_t); + pthread_attr_t *_attribute; + } _sigev_thread; + } _sigev_un; + } sigevent_t; + + + + + + +enum +{ + SIGEV_SIGNAL = 0, + + SIGEV_NONE, + + SIGEV_THREAD, + + + SIGEV_THREAD_ID = 4 + +}; +# 81 "/usr/include/signal.h" 2 3 4 + + + + +typedef void (*__sighandler_t) (int); + + + + +extern __sighandler_t __sysv_signal (int __sig, __sighandler_t __handler) + __attribute__ ((__nothrow__ )); +# 102 "/usr/include/signal.h" 3 4 +extern __sighandler_t signal (int __sig, __sighandler_t __handler) + __attribute__ ((__nothrow__ )); +# 127 "/usr/include/signal.h" 3 4 +extern int kill (__pid_t __pid, int __sig) __attribute__ ((__nothrow__ )); + + + + + + +extern int killpg (__pid_t __pgrp, int __sig) __attribute__ ((__nothrow__ )); + + + + +extern int raise (int __sig) __attribute__ ((__nothrow__ )); + + + + +extern __sighandler_t ssignal (int __sig, __sighandler_t __handler) + __attribute__ ((__nothrow__ )); +extern int gsignal (int __sig) __attribute__ ((__nothrow__ )); + + + + +extern void psignal (int __sig, const char *__s); + + + + +extern void psiginfo (const siginfo_t *__pinfo, const char *__s); +# 167 "/usr/include/signal.h" 3 4 +extern int __sigpause (int __sig_or_mask, int __is_sig); +# 189 "/usr/include/signal.h" 3 4 +extern int sigblock (int __mask) __attribute__ ((__nothrow__ )) __attribute__ ((__deprecated__)); + + +extern int sigsetmask (int __mask) __attribute__ ((__nothrow__ )) __attribute__ ((__deprecated__)); + + +extern int siggetmask (void) __attribute__ ((__nothrow__ )) __attribute__ ((__deprecated__)); +# 209 "/usr/include/signal.h" 3 4 +typedef __sighandler_t sig_t; + + + + + +extern int sigemptyset (sigset_t *__set) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int sigfillset (sigset_t *__set) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int sigaddset (sigset_t *__set, int __signo) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int sigdelset (sigset_t *__set, int __signo) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int sigismember (const sigset_t *__set, int __signo) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 245 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/sigaction.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/sigaction.h" 3 4 +struct sigaction + { + + + union + { + + __sighandler_t sa_handler; + + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; + + + + + + + + __sigset_t sa_mask; + + + int sa_flags; + + + void (*sa_restorer) (void); + }; +# 246 "/usr/include/signal.h" 2 3 4 + + +extern int sigprocmask (int __how, const sigset_t *__restrict __set, + sigset_t *__restrict __oset) __attribute__ ((__nothrow__ )); + + + + + + +extern int sigsuspend (const sigset_t *__set) __attribute__ ((__nonnull__ (1))); + + +extern int sigaction (int __sig, const struct sigaction *__restrict __act, + struct sigaction *__restrict __oact) __attribute__ ((__nothrow__ )); + + +extern int sigpending (sigset_t *__set) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int sigwait (const sigset_t *__restrict __set, int *__restrict __sig) + __attribute__ ((__nonnull__ (1, 2))); + + + + + + +extern int sigwaitinfo (const sigset_t *__restrict __set, + siginfo_t *__restrict __info) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int sigtimedwait (const sigset_t *__restrict __set, + siginfo_t *__restrict __info, + const struct timespec *__restrict __timeout) + __attribute__ ((__nonnull__ (1))); + + + +extern int sigqueue (__pid_t __pid, int __sig, const union sigval __val) + __attribute__ ((__nothrow__ )); +# 303 "/usr/include/signal.h" 3 4 +extern const char *const _sys_siglist[65]; +extern const char *const sys_siglist[65]; + + +struct sigvec + { + __sighandler_t sv_handler; + int sv_mask; + + int sv_flags; + + }; +# 327 "/usr/include/signal.h" 3 4 +extern int sigvec (int __sig, const struct sigvec *__vec, + struct sigvec *__ovec) __attribute__ ((__nothrow__ )); + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sigcontext.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/bits/sigcontext.h" 3 4 +struct _fpx_sw_bytes +{ + __uint32_t magic1; + __uint32_t extended_size; + __uint64_t xstate_bv; + __uint32_t xstate_size; + __uint32_t padding[7]; +}; + +struct _fpreg +{ + unsigned short significand[4]; + unsigned short exponent; +}; + +struct _fpxreg +{ + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _xmmreg +{ + __uint32_t element[4]; +}; +# 121 "/usr/include/x86_64-linux-gnu/bits/sigcontext.h" 3 4 +struct _fpstate +{ + + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + struct _fpxreg _st[8]; + struct _xmmreg _xmm[16]; + __uint32_t padding[24]; +}; + +struct sigcontext +{ + __uint64_t r8; + __uint64_t r9; + __uint64_t r10; + __uint64_t r11; + __uint64_t r12; + __uint64_t r13; + __uint64_t r14; + __uint64_t r15; + __uint64_t rdi; + __uint64_t rsi; + __uint64_t rbp; + __uint64_t rbx; + __uint64_t rdx; + __uint64_t rax; + __uint64_t rcx; + __uint64_t rsp; + __uint64_t rip; + __uint64_t eflags; + unsigned short cs; + unsigned short gs; + unsigned short fs; + unsigned short __pad0; + __uint64_t err; + __uint64_t trapno; + __uint64_t oldmask; + __uint64_t cr2; + __extension__ union + { + struct _fpstate * fpstate; + __uint64_t __fpstate_word; + }; + __uint64_t __reserved1 [8]; +}; + + + +struct _xsave_hdr +{ + __uint64_t xstate_bv; + __uint64_t reserved1[2]; + __uint64_t reserved2[5]; +}; + +struct _ymmh_state +{ + __uint32_t ymmh_space[64]; +}; + +struct _xstate +{ + struct _fpstate fpstate; + struct _xsave_hdr xstate_hdr; + struct _ymmh_state ymmh; +}; +# 333 "/usr/include/signal.h" 2 3 4 + + +extern int sigreturn (struct sigcontext *__scp) __attribute__ ((__nothrow__ )); + + + + + + + +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 343 "/usr/include/signal.h" 2 3 4 + + + + +extern int siginterrupt (int __sig, int __interrupt) __attribute__ ((__nothrow__ )); + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sigstack.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/bits/sigstack.h" 3 4 +struct sigstack + { + void *ss_sp; + int ss_onstack; + }; + + + +enum +{ + SS_ONSTACK = 1, + + SS_DISABLE + +}; +# 49 "/usr/include/x86_64-linux-gnu/bits/sigstack.h" 3 4 +typedef struct sigaltstack + { + void *ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; +# 350 "/usr/include/signal.h" 2 3 4 + + +# 1 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 3 4 +# 1 "/usr/include/signal.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 2 3 4 + + + + + + + + +__extension__ typedef long long int greg_t; + + + + + +typedef greg_t gregset_t[23]; +# 92 "/usr/include/x86_64-linux-gnu/sys/ucontext.h" 3 4 +struct _libc_fpxreg +{ + unsigned short int significand[4]; + unsigned short int exponent; + unsigned short int padding[3]; +}; + +struct _libc_xmmreg +{ + __uint32_t element[4]; +}; + +struct _libc_fpstate +{ + + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + struct _libc_fpxreg _st[8]; + struct _libc_xmmreg _xmm[16]; + __uint32_t padding[24]; +}; + + +typedef struct _libc_fpstate *fpregset_t; + + +typedef struct + { + gregset_t gregs; + + fpregset_t fpregs; + __extension__ unsigned long long __reserved1 [8]; +} mcontext_t; + + +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; + } ucontext_t; +# 353 "/usr/include/signal.h" 2 3 4 + + + + + +extern int sigstack (struct sigstack *__ss, struct sigstack *__oss) + __attribute__ ((__nothrow__ )) __attribute__ ((__deprecated__)); + + + +extern int sigaltstack (const struct sigaltstack *__restrict __ss, + struct sigaltstack *__restrict __oss) __attribute__ ((__nothrow__ )); +# 388 "/usr/include/signal.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/sigthread.h" 1 3 4 +# 30 "/usr/include/x86_64-linux-gnu/bits/sigthread.h" 3 4 +extern int pthread_sigmask (int __how, + const __sigset_t *__restrict __newmask, + __sigset_t *__restrict __oldmask)__attribute__ ((__nothrow__ )); + + +extern int pthread_kill (pthread_t __threadid, int __signo) __attribute__ ((__nothrow__ )); +# 389 "/usr/include/signal.h" 2 3 4 + + + + + + +extern int __libc_current_sigrtmin (void) __attribute__ ((__nothrow__ )); + +extern int __libc_current_sigrtmax (void) __attribute__ ((__nothrow__ )); +# 30 "/usr/include/x86_64-linux-gnu/sys/wait.h" 2 3 4 +# 102 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +extern __pid_t wait (__WAIT_STATUS __stat_loc); +# 125 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +extern __pid_t waitpid (__pid_t __pid, int *__stat_loc, int __options); +# 135 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/bits/siginfo.h" 2 3 4 +# 136 "/usr/include/x86_64-linux-gnu/sys/wait.h" 2 3 4 +# 148 "/usr/include/x86_64-linux-gnu/sys/wait.h" 3 4 +extern int waitid (idtype_t __idtype, __id_t __id, siginfo_t *__infop, + int __options); + + + + + +struct rusage; + + + + + + +extern __pid_t wait3 (__WAIT_STATUS __stat_loc, int __options, + struct rusage * __usage) __attribute__ ((__nothrow__)); + + + + +extern __pid_t wait4 (__pid_t __pid, __WAIT_STATUS __stat_loc, int __options, + struct rusage *__usage) __attribute__ ((__nothrow__)); +# 183 "../include/apr.h" 2 +# 193 "../include/apr.h" +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/limits.h" 1 3 +# 37 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/limits.h" 3 +# 1 "/usr/include/limits.h" 1 3 4 +# 143 "/usr/include/limits.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 1 3 4 +# 160 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 1 3 4 +# 38 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 3 4 +# 1 "/usr/include/linux/limits.h" 1 3 4 +# 39 "/usr/include/x86_64-linux-gnu/bits/local_lim.h" 2 3 4 +# 161 "/usr/include/x86_64-linux-gnu/bits/posix1_lim.h" 2 3 4 +# 144 "/usr/include/limits.h" 2 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/posix2_lim.h" 1 3 4 +# 148 "/usr/include/limits.h" 2 3 4 +# 38 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/limits.h" 2 3 +# 194 "../include/apr.h" 2 +# 309 "../include/apr.h" +typedef unsigned char apr_byte_t; + +typedef short apr_int16_t; +typedef unsigned short apr_uint16_t; + +typedef int apr_int32_t; +typedef unsigned int apr_uint32_t; +# 352 "../include/apr.h" + typedef long apr_int64_t; + typedef unsigned long apr_uint64_t; + + +typedef size_t apr_size_t; +typedef ssize_t apr_ssize_t; +typedef off_t apr_off_t; +typedef socklen_t apr_socklen_t; +typedef ino_t apr_ino_t; + + +typedef apr_uint64_t apr_uintptr_t; +# 44 "../include/apr_pools.h" 2 +# 1 "../include/apr_errno.h" 1 +# 28 "../include/apr_errno.h" +# 1 "/usr/include/errno.h" 1 3 4 +# 35 "/usr/include/errno.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/errno.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/errno.h" 3 4 +# 1 "/usr/include/linux/errno.h" 1 3 4 +# 1 "/usr/include/x86_64-linux-gnu/asm/errno.h" 1 3 4 +# 1 "/usr/include/asm-generic/errno.h" 1 3 4 + + + +# 1 "/usr/include/asm-generic/errno-base.h" 1 3 4 +# 5 "/usr/include/asm-generic/errno.h" 2 3 4 +# 2 "/usr/include/x86_64-linux-gnu/asm/errno.h" 2 3 4 +# 2 "/usr/include/linux/errno.h" 2 3 4 +# 25 "/usr/include/x86_64-linux-gnu/bits/errno.h" 2 3 4 +# 50 "/usr/include/x86_64-linux-gnu/bits/errno.h" 3 4 +extern int *__errno_location (void) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 36 "/usr/include/errno.h" 2 3 4 +# 29 "../include/apr_errno.h" 2 +# 44 "../include/apr_errno.h" +typedef int apr_status_t; + + + + + + + +char * apr_strerror(apr_status_t statcode, char *buf, + apr_size_t bufsize); +# 45 "../include/apr_pools.h" 2 +# 1 "../include/apr_general.h" 1 +# 29 "../include/apr_general.h" +# 1 "../include/apr_pools.h" 1 +# 30 "../include/apr_general.h" 2 +# 68 "../include/apr_general.h" +typedef int apr_signum_t; +# 177 "../include/apr_general.h" +apr_status_t apr_initialize(void); +# 191 "../include/apr_general.h" +apr_status_t apr_app_initialize(int *argc, + char const * const * *argv, + char const * const * *env); +# 205 "../include/apr_general.h" +void apr_terminate(void); +# 216 "../include/apr_general.h" +void apr_terminate2(void); +# 233 "../include/apr_general.h" +apr_status_t apr_generate_random_bytes(unsigned char * buf, + apr_size_t length); +# 46 "../include/apr_pools.h" 2 + +# 1 "../include/apr_want.h" 1 +# 48 "../include/apr_pools.h" 2 +# 60 "../include/apr_pools.h" +typedef struct apr_pool_t apr_pool_t; +# 148 "../include/apr_pools.h" +typedef int (*apr_abortfunc_t)(int retcode); +# 164 "../include/apr_pools.h" +apr_status_t apr_pool_initialize(void); + + + + + + + +void apr_pool_terminate(void); + + + + + + + +# 1 "../include/apr_allocator.h" 1 +# 28 "../include/apr_allocator.h" +# 1 "../include/apr_want.h" 1 +# 29 "../include/apr_allocator.h" 2 +# 41 "../include/apr_allocator.h" +typedef struct apr_allocator_t apr_allocator_t; + +typedef struct apr_memnode_t apr_memnode_t; +# 54 "../include/apr_allocator.h" +struct apr_memnode_t { + apr_memnode_t *next; + apr_memnode_t **ref; + apr_uint32_t index; + apr_uint32_t free_index; + char *first_avail; + char *endp; +}; +# 74 "../include/apr_allocator.h" +apr_status_t apr_allocator_create(apr_allocator_t **allocator) + __attribute__((nonnull(1))); + + + + + + + +void apr_allocator_destroy(apr_allocator_t *allocator) + __attribute__((nonnull(1))); + + + + + + + +apr_memnode_t * apr_allocator_alloc(apr_allocator_t *allocator, + apr_size_t size) + __attribute__((nonnull(1))); +# 103 "../include/apr_allocator.h" +void apr_allocator_free(apr_allocator_t *allocator, + apr_memnode_t *memnode) + __attribute__((nonnull(1,2))); + + +# 1 "../include/apr_pools.h" 1 +# 108 "../include/apr_allocator.h" 2 +# 120 "../include/apr_allocator.h" +void apr_allocator_owner_set(apr_allocator_t *allocator, + apr_pool_t *pool) + __attribute__((nonnull(1))); + + + + + +apr_pool_t * apr_allocator_owner_get(apr_allocator_t *allocator) + __attribute__((nonnull(1))); + + + + + + + +void apr_allocator_max_free_set(apr_allocator_t *allocator, + apr_size_t size) + __attribute__((nonnull(1))); + + +# 1 "../include/apr_thread_mutex.h" 1 +# 41 "../include/apr_thread_mutex.h" +typedef struct apr_thread_mutex_t apr_thread_mutex_t; + + + + + + + +# 1 "../include/apr_pools.h" 1 +# 49 "../include/apr_thread_mutex.h" 2 +# 65 "../include/apr_thread_mutex.h" +apr_status_t apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool); + + + + + +apr_status_t apr_thread_mutex_lock(apr_thread_mutex_t *mutex); +# 82 "../include/apr_thread_mutex.h" +apr_status_t apr_thread_mutex_trylock(apr_thread_mutex_t *mutex); + + + + + +apr_status_t apr_thread_mutex_unlock(apr_thread_mutex_t *mutex); + + + + + +apr_status_t apr_thread_mutex_destroy(apr_thread_mutex_t *mutex); + + + + + +apr_pool_t * apr_thread_mutex_pool_get (const apr_thread_mutex_t *thethread_mutex); +# 142 "../include/apr_allocator.h" 2 + + + + + + + +void apr_allocator_mutex_set(apr_allocator_t *allocator, + apr_thread_mutex_t *mutex) + __attribute__((nonnull(1))); + + + + + +apr_thread_mutex_t * apr_allocator_mutex_get( + apr_allocator_t *allocator) + __attribute__((nonnull(1))); +# 180 "../include/apr_pools.h" 2 +# 196 "../include/apr_pools.h" +apr_status_t apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) + __attribute__((nonnull(1))); + + + + + +apr_status_t apr_pool_create_core_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator); +# 226 "../include/apr_pools.h" +apr_status_t apr_pool_create_unmanaged_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) + __attribute__((nonnull(1))); +# 247 "../include/apr_pools.h" +apr_status_t apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) + __attribute__((nonnull(1))); +# 264 "../include/apr_pools.h" +apr_status_t apr_pool_create_core_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line); +# 284 "../include/apr_pools.h" +apr_status_t apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) + __attribute__((nonnull(1))); +# 354 "../include/apr_pools.h" +apr_allocator_t * apr_pool_allocator_get(apr_pool_t *pool) + __attribute__((nonnull(1))); +# 365 "../include/apr_pools.h" +void apr_pool_clear(apr_pool_t *p) __attribute__((nonnull(1))); +# 380 "../include/apr_pools.h" +void apr_pool_clear_debug(apr_pool_t *p, + const char *file_line) + __attribute__((nonnull(1))); +# 395 "../include/apr_pools.h" +void apr_pool_destroy(apr_pool_t *p) __attribute__((nonnull(1))); +# 410 "../include/apr_pools.h" +void apr_pool_destroy_debug(apr_pool_t *p, + const char *file_line) + __attribute__((nonnull(1))); +# 430 "../include/apr_pools.h" +void * apr_palloc(apr_pool_t *p, apr_size_t size) + + + + __attribute__((nonnull(1))); +# 444 "../include/apr_pools.h" +void * apr_palloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line) + + + + __attribute__((nonnull(1))); +# 476 "../include/apr_pools.h" +void * apr_pcalloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line) + __attribute__((nonnull(1))); +# 498 "../include/apr_pools.h" +void apr_pool_abort_set(apr_abortfunc_t abortfunc, + apr_pool_t *pool) + __attribute__((nonnull(2))); + + + + + + +apr_abortfunc_t apr_pool_abort_get(apr_pool_t *pool) + __attribute__((nonnull(1))); + + + + + + +apr_pool_t * apr_pool_parent_get(apr_pool_t *pool) + __attribute__((nonnull(1))); +# 529 "../include/apr_pools.h" +int apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b); + + + + + + +void apr_pool_tag(apr_pool_t *pool, const char *tag) + __attribute__((nonnull(1))); +# 563 "../include/apr_pools.h" +apr_status_t apr_pool_userdata_set(const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) + __attribute__((nonnull(2,4))); +# 588 "../include/apr_pools.h" +apr_status_t apr_pool_userdata_setn( + const void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) + __attribute__((nonnull(2,4))); + + + + + + + +apr_status_t apr_pool_userdata_get(void **data, const char *key, + apr_pool_t *pool) + __attribute__((nonnull(1,2,3))); +# 628 "../include/apr_pools.h" +void apr_pool_cleanup_register( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)) + __attribute__((nonnull(3,4))); +# 646 "../include/apr_pools.h" +void apr_pool_pre_cleanup_register( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *)) + __attribute__((nonnull(3))); +# 663 "../include/apr_pools.h" +void apr_pool_cleanup_kill(apr_pool_t *p, const void *data, + apr_status_t (*cleanup)(void *)) + __attribute__((nonnull(3))); +# 679 "../include/apr_pools.h" +void apr_pool_child_cleanup_set( + apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)) + __attribute__((nonnull(3,4))); +# 696 "../include/apr_pools.h" +apr_status_t apr_pool_cleanup_run(apr_pool_t *p, void *data, + apr_status_t (*cleanup)(void *)) + __attribute__((nonnull(3))); +# 707 "../include/apr_pools.h" +apr_status_t apr_pool_cleanup_null(void *data); + + + + + + + +void apr_pool_cleanup_for_exec(void); +# 18 "./../test/testutil.h" 2 + +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 52 "./../test/testutil.h" +extern apr_pool_t *p; + + + +void apr_assert_success(abts_case* tc, const char *context, + apr_status_t rv, int lineno); + + + +void initialize(void); + +abts_suite *testatomic(abts_suite *suite); +abts_suite *testdir(abts_suite *suite); +abts_suite *testdso(abts_suite *suite); +abts_suite *testdup(abts_suite *suite); +abts_suite *testescape(abts_suite *suite); +abts_suite *testenv(abts_suite *suite); +abts_suite *testfile(abts_suite *suite); +abts_suite *testfilecopy(abts_suite *suite); +abts_suite *testfileinfo(abts_suite *suite); +abts_suite *testflock(abts_suite *suite); +abts_suite *testfmt(abts_suite *suite); +abts_suite *testfnmatch(abts_suite *suite); +abts_suite *testgetopt(abts_suite *suite); +abts_suite *testglobalmutex(abts_suite *suite); +abts_suite *testhash(abts_suite *suite); +abts_suite *testipsub(abts_suite *suite); +abts_suite *testlock(abts_suite *suite); +abts_suite *testcond(abts_suite *suite); +abts_suite *testlfs(abts_suite *suite); +abts_suite *testmmap(abts_suite *suite); +abts_suite *testnames(abts_suite *suite); +abts_suite *testoc(abts_suite *suite); +abts_suite *testpath(abts_suite *suite); +abts_suite *testpipe(abts_suite *suite); +abts_suite *testpoll(abts_suite *suite); +abts_suite *testpool(abts_suite *suite); +abts_suite *testproc(abts_suite *suite); +abts_suite *testprocmutex(abts_suite *suite); +abts_suite *testrand(abts_suite *suite); +abts_suite *testsleep(abts_suite *suite); +abts_suite *testshm(abts_suite *suite); +abts_suite *testsock(abts_suite *suite); +abts_suite *testsockets(abts_suite *suite); +abts_suite *testsockopt(abts_suite *suite); +abts_suite *teststr(abts_suite *suite); +abts_suite *teststrnatcmp(abts_suite *suite); +abts_suite *testtable(abts_suite *suite); +abts_suite *testtemp(abts_suite *suite); +abts_suite *testthread(abts_suite *suite); +abts_suite *testtime(abts_suite *suite); +abts_suite *testud(abts_suite *suite); +abts_suite *testuser(abts_suite *suite); +abts_suite *testvsn(abts_suite *suite); +# 8 "main2.c" 2 + +# 1 "./../test/testatomic.c" 1 +# 17 "./../test/testatomic.c" +# 1 "./../test/testutil.h" 1 +# 19 "./../test/testutil.h" +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 18 "./../test/testatomic.c" 2 +# 1 "../include/apr_strings.h" 1 +# 52 "../include/apr_strings.h" +# 1 "../include/apr_want.h" 1 +# 53 "../include/apr_strings.h" 2 +# 76 "../include/apr_strings.h" +int apr_strnatcmp(char const *a, char const *b); +# 87 "../include/apr_strings.h" +int apr_strnatcasecmp(char const *a, char const *b); + + + + + + + +char * apr_pstrdup(apr_pool_t *p, const char *s); +# 109 "../include/apr_strings.h" +char * apr_pstrmemdup(apr_pool_t *p, const char *s, apr_size_t n) + + + + ; +# 125 "../include/apr_strings.h" +char * apr_pstrndup(apr_pool_t *p, const char *s, apr_size_t n); +# 135 "../include/apr_strings.h" +void * apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n) + + + + ; + + + + + + + +char * apr_pstrcat(apr_pool_t *p, ...) + + __attribute__((sentinel)) + + ; +# 161 "../include/apr_strings.h" +char * apr_pstrcatv(apr_pool_t *p, const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes); +# 172 "../include/apr_strings.h" +char * apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap); +# 182 "../include/apr_strings.h" +char * apr_psprintf(apr_pool_t *p, const char *fmt, ...) + __attribute__((format(printf,2,3))); +# 207 "../include/apr_strings.h" +char * apr_cpystrn(char *dst, const char *src, + apr_size_t dst_size); +# 217 "../include/apr_strings.h" +char * apr_collapse_spaces(char *dest, const char *src); +# 226 "../include/apr_strings.h" +apr_status_t apr_tokenize_to_argv(const char *arg_str, + char ***argv_out, + apr_pool_t *token_context); +# 247 "../include/apr_strings.h" +char * apr_strtok(char *str, const char *sep, char **last); +# 279 "../include/apr_strings.h" +int apr_snprintf(char *buf, apr_size_t len, + const char *format, ...) + __attribute__((format(printf,3,4))); +# 291 "../include/apr_strings.h" +int apr_vsnprintf(char *buf, apr_size_t len, const char *format, + va_list ap); +# 301 "../include/apr_strings.h" +char * apr_itoa(apr_pool_t *p, int n); + + + + + + + +char * apr_ltoa(apr_pool_t *p, long n); + + + + + + + +char * apr_off_t_toa(apr_pool_t *p, apr_off_t n); +# 335 "../include/apr_strings.h" +apr_status_t apr_strtoff(apr_off_t *offset, const char *buf, + char **end, int base); +# 353 "../include/apr_strings.h" +apr_int64_t apr_strtoi64(const char *buf, char **end, int base); +# 362 "../include/apr_strings.h" +apr_int64_t apr_atoi64(const char *buf); +# 372 "../include/apr_strings.h" +char * apr_strfsize(apr_off_t size, char *buf); +# 19 "./../test/testatomic.c" 2 +# 1 "../include/apr_thread_proc.h" 1 +# 26 "../include/apr_thread_proc.h" +# 1 "../include/apr_file_io.h" 1 +# 27 "../include/apr_file_io.h" +# 1 "../include/apr_time.h" 1 +# 40 "../include/apr_time.h" + extern const char apr_month_snames[12][4]; + + extern const char apr_day_snames[7][4]; + + + +typedef apr_int64_t apr_time_t; +# 56 "../include/apr_time.h" +typedef apr_int64_t apr_interval_time_t; + +typedef apr_int32_t apr_short_interval_time_t; +# 88 "../include/apr_time.h" +apr_time_t apr_time_now(void); + + +typedef struct apr_time_exp_t apr_time_exp_t; + + + + + + +struct apr_time_exp_t { + + apr_int32_t tm_usec; + + apr_int32_t tm_sec; + + apr_int32_t tm_min; + + apr_int32_t tm_hour; + + apr_int32_t tm_mday; + + apr_int32_t tm_mon; + + apr_int32_t tm_year; + + apr_int32_t tm_wday; + + apr_int32_t tm_yday; + + apr_int32_t tm_isdst; + + apr_int32_t tm_gmtoff; +}; + + + + + + +apr_status_t apr_time_ansi_put(apr_time_t *result, + time_t input); +# 138 "../include/apr_time.h" +apr_status_t apr_time_exp_tz(apr_time_exp_t *result, + apr_time_t input, + apr_int32_t offs); + + + + + + +apr_status_t apr_time_exp_gmt(apr_time_exp_t *result, + apr_time_t input); + + + + + + +apr_status_t apr_time_exp_lt(apr_time_exp_t *result, + apr_time_t input); + + + + + + + +apr_status_t apr_time_exp_get(apr_time_t *result, + apr_time_exp_t *input); + + + + + + + +apr_status_t apr_time_exp_gmt_get(apr_time_t *result, + apr_time_exp_t *input); + + + + + + +void apr_sleep(apr_interval_time_t t); +# 193 "../include/apr_time.h" +apr_status_t apr_rfc822_date(char *date_str, apr_time_t t); +# 207 "../include/apr_time.h" +apr_status_t apr_ctime(char *date_str, apr_time_t t); +# 217 "../include/apr_time.h" +apr_status_t apr_strftime(char *s, apr_size_t *retsize, + apr_size_t max, const char *format, + apr_time_exp_t *tm); + + + + + + + +void apr_time_clock_hires(apr_pool_t *p); +# 28 "../include/apr_file_io.h" 2 + +# 1 "../include/apr_file_info.h" 1 +# 26 "../include/apr_file_info.h" +# 1 "../include/apr_user.h" 1 +# 45 "../include/apr_user.h" +typedef uid_t apr_uid_t; +# 54 "../include/apr_user.h" +typedef gid_t apr_gid_t; +# 66 "../include/apr_user.h" +apr_status_t apr_uid_current(apr_uid_t *userid, + apr_gid_t *groupid, + apr_pool_t *p); +# 77 "../include/apr_user.h" +apr_status_t apr_uid_name_get(char **username, apr_uid_t userid, + apr_pool_t *p); +# 88 "../include/apr_user.h" +apr_status_t apr_uid_get(apr_uid_t *userid, apr_gid_t *groupid, + const char *username, apr_pool_t *p); +# 98 "../include/apr_user.h" +apr_status_t apr_uid_homepath_get(char **dirname, + const char *username, + apr_pool_t *p); +# 123 "../include/apr_user.h" +apr_status_t apr_gid_name_get(char **groupname, + apr_gid_t groupid, apr_pool_t *p); +# 133 "../include/apr_user.h" +apr_status_t apr_gid_get(apr_gid_t *groupid, + const char *groupname, apr_pool_t *p); +# 27 "../include/apr_file_info.h" 2 + +# 1 "../include/apr_tables.h" 1 +# 56 "../include/apr_tables.h" +typedef struct apr_table_t apr_table_t; + + +typedef struct apr_array_header_t apr_array_header_t; + + +struct apr_array_header_t { + + apr_pool_t *pool; + + int elt_size; + + int nelts; + + int nalloc; + + char *elts; +}; + + + + +typedef struct apr_table_entry_t apr_table_entry_t; + + +struct apr_table_entry_t { + + char *key; + + + + char *val; + + + apr_uint32_t key_checksum; +}; + + + + + + +const apr_array_header_t * apr_table_elts(const apr_table_t *t); + + + + + + +int apr_is_empty_table(const apr_table_t *t); + + + + + + +int apr_is_empty_array(const apr_array_header_t *a); +# 121 "../include/apr_tables.h" +apr_array_header_t * apr_array_make(apr_pool_t *p, + int nelts, int elt_size); +# 131 "../include/apr_tables.h" +void * apr_array_push(apr_array_header_t *arr); +# 158 "../include/apr_tables.h" +void * apr_array_pop(apr_array_header_t *arr); + + + + + + + +void apr_array_clear(apr_array_header_t *arr); + + + + + + + +void apr_array_cat(apr_array_header_t *dst, + const apr_array_header_t *src); +# 186 "../include/apr_tables.h" +apr_array_header_t * apr_array_copy(apr_pool_t *p, + const apr_array_header_t *arr); +# 196 "../include/apr_tables.h" +apr_array_header_t * apr_array_copy_hdr(apr_pool_t *p, + const apr_array_header_t *arr); +# 206 "../include/apr_tables.h" +apr_array_header_t * apr_array_append(apr_pool_t *p, + const apr_array_header_t *first, + const apr_array_header_t *second); +# 221 "../include/apr_tables.h" +char * apr_array_pstrcat(apr_pool_t *p, + const apr_array_header_t *arr, + const char sep); +# 232 "../include/apr_tables.h" +apr_table_t * apr_table_make(apr_pool_t *p, int nelts); +# 241 "../include/apr_tables.h" +apr_table_t * apr_table_copy(apr_pool_t *p, + const apr_table_t *t); +# 252 "../include/apr_tables.h" +apr_table_t * apr_table_clone(apr_pool_t *p, + const apr_table_t *t); + + + + + +void apr_table_clear(apr_table_t *t); +# 268 "../include/apr_tables.h" +const char * apr_table_get(const apr_table_t *t, const char *key); +# 279 "../include/apr_tables.h" +const char * apr_table_getm(apr_pool_t *p, const apr_table_t *t, + const char *key); +# 291 "../include/apr_tables.h" +void apr_table_set(apr_table_t *t, const char *key, + const char *val); +# 304 "../include/apr_tables.h" +void apr_table_setn(apr_table_t *t, const char *key, + const char *val); + + + + + + +void apr_table_unset(apr_table_t *t, const char *key); +# 323 "../include/apr_tables.h" +void apr_table_merge(apr_table_t *t, const char *key, + const char *val); +# 335 "../include/apr_tables.h" +void apr_table_mergen(apr_table_t *t, const char *key, + const char *val); +# 347 "../include/apr_tables.h" +void apr_table_add(apr_table_t *t, const char *key, + const char *val); +# 360 "../include/apr_tables.h" +void apr_table_addn(apr_table_t *t, const char *key, + const char *val); +# 370 "../include/apr_tables.h" +apr_table_t * apr_table_overlay(apr_pool_t *p, + const apr_table_t *overlay, + const apr_table_t *base); +# 384 "../include/apr_tables.h" +typedef int (apr_table_do_callback_fn_t)(void *rec, const char *key, + const char *value); +# 406 "../include/apr_tables.h" +int apr_table_do(apr_table_do_callback_fn_t *comp, + void *rec, const apr_table_t *t, ...) + + __attribute__((sentinel)) + + ; +# 432 "../include/apr_tables.h" +int apr_table_vdo(apr_table_do_callback_fn_t *comp, + void *rec, const apr_table_t *t, va_list vp); +# 478 "../include/apr_tables.h" +void apr_table_overlap(apr_table_t *a, const apr_table_t *b, + unsigned flags); +# 491 "../include/apr_tables.h" +void apr_table_compress(apr_table_t *t, unsigned flags); +# 29 "../include/apr_file_info.h" 2 +# 62 "../include/apr_file_info.h" +typedef enum { + APR_NOFILE = 0, + APR_REG, + APR_DIR, + APR_CHR, + APR_BLK, + APR_PIPE, + APR_LNK, + APR_SOCK, + APR_UNKFILE = 127 +} apr_filetype_e; +# 121 "../include/apr_file_info.h" +typedef struct apr_dir_t apr_dir_t; + + + +typedef apr_int32_t apr_fileperms_t; +# 135 "../include/apr_file_info.h" +typedef dev_t apr_dev_t; + + + + + + + +typedef struct apr_finfo_t apr_finfo_t; +# 174 "../include/apr_file_info.h" +struct apr_finfo_t { + + apr_pool_t *pool; + + + apr_int32_t valid; + + apr_fileperms_t protection; + + + + + apr_filetype_e filetype; + + apr_uid_t user; + + apr_gid_t group; + + apr_ino_t inode; + + apr_dev_t device; + + apr_int32_t nlink; + + apr_off_t size; + + apr_off_t csize; + + apr_time_t atime; + + apr_time_t mtime; + + apr_time_t ctime; + + const char *fname; + + const char *name; + + struct apr_file_t *filehand; +}; +# 229 "../include/apr_file_info.h" +apr_status_t apr_stat(apr_finfo_t *finfo, const char *fname, + apr_int32_t wanted, apr_pool_t *pool); +# 244 "../include/apr_file_info.h" +apr_status_t apr_dir_open(apr_dir_t **new_dir, + const char *dirname, + apr_pool_t *pool); + + + + + +apr_status_t apr_dir_close(apr_dir_t *thedir); +# 267 "../include/apr_file_info.h" +apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, + apr_dir_t *thedir); + + + + + +apr_status_t apr_dir_rewind(apr_dir_t *thedir); +# 336 "../include/apr_file_info.h" +apr_status_t apr_filepath_root(const char **rootpath, + const char **filepath, + apr_int32_t flags, + apr_pool_t *p); +# 354 "../include/apr_file_info.h" +apr_status_t apr_filepath_merge(char **newpath, + const char *rootpath, + const char *addpath, + apr_int32_t flags, + apr_pool_t *p); +# 369 "../include/apr_file_info.h" +apr_status_t apr_filepath_list_split(apr_array_header_t **pathelts, + const char *liststr, + apr_pool_t *p); +# 382 "../include/apr_file_info.h" +apr_status_t apr_filepath_list_merge(char **liststr, + apr_array_header_t *pathelts, + apr_pool_t *p); +# 393 "../include/apr_file_info.h" +apr_status_t apr_filepath_get(char **path, apr_int32_t flags, + apr_pool_t *p); + + + + + + +apr_status_t apr_filepath_set(const char *path, apr_pool_t *p); +# 419 "../include/apr_file_info.h" +apr_status_t apr_filepath_encoding(int *style, apr_pool_t *p); +# 30 "../include/apr_file_io.h" 2 +# 1 "../include/apr_inherit.h" 1 +# 31 "../include/apr_file_io.h" 2 + + + +# 1 "../include/apr_want.h" 1 +# 35 "../include/apr_file_io.h" 2 +# 180 "../include/apr_file_io.h" +typedef apr_uint32_t apr_fileattrs_t; + + +typedef int apr_seek_where_t; + + + + +typedef struct apr_file_t apr_file_t; +# 250 "../include/apr_file_io.h" +apr_status_t apr_file_open(apr_file_t **newf, const char *fname, + apr_int32_t flag, apr_fileperms_t perm, + apr_pool_t *pool); + + + + + +apr_status_t apr_file_close(apr_file_t *file); +# 267 "../include/apr_file_io.h" +apr_status_t apr_file_remove(const char *path, apr_pool_t *pool); +# 278 "../include/apr_file_io.h" +apr_status_t apr_file_rename(const char *from_path, + const char *to_path, + apr_pool_t *pool); + + + + + + + +apr_status_t apr_file_link(const char *from_path, + const char *to_path); +# 303 "../include/apr_file_io.h" +apr_status_t apr_file_copy(const char *from_path, + const char *to_path, + apr_fileperms_t perms, + apr_pool_t *pool); +# 319 "../include/apr_file_io.h" +apr_status_t apr_file_append(const char *from_path, + const char *to_path, + apr_fileperms_t perms, + apr_pool_t *pool); + + + + + + +apr_status_t apr_file_eof(apr_file_t *fptr); +# 346 "../include/apr_file_io.h" +apr_status_t apr_file_open_stderr(apr_file_t **thefile, + apr_pool_t *pool); +# 356 "../include/apr_file_io.h" +apr_status_t apr_file_open_stdout(apr_file_t **thefile, + apr_pool_t *pool); +# 366 "../include/apr_file_io.h" +apr_status_t apr_file_open_stdin(apr_file_t **thefile, + apr_pool_t *pool); +# 386 "../include/apr_file_io.h" +apr_status_t apr_file_open_flags_stderr(apr_file_t **thefile, + apr_int32_t flags, + apr_pool_t *pool); +# 407 "../include/apr_file_io.h" +apr_status_t apr_file_open_flags_stdout(apr_file_t **thefile, + apr_int32_t flags, + apr_pool_t *pool); +# 428 "../include/apr_file_io.h" +apr_status_t apr_file_open_flags_stdin(apr_file_t **thefile, + apr_int32_t flags, + apr_pool_t *pool); +# 449 "../include/apr_file_io.h" +apr_status_t apr_file_read(apr_file_t *thefile, void *buf, + apr_size_t *nbytes); +# 467 "../include/apr_file_io.h" +apr_status_t apr_file_write(apr_file_t *thefile, const void *buf, + apr_size_t *nbytes); +# 485 "../include/apr_file_io.h" +apr_status_t apr_file_writev(apr_file_t *thefile, + const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes); +# 509 "../include/apr_file_io.h" +apr_status_t apr_file_read_full(apr_file_t *thefile, void *buf, + apr_size_t nbytes, + apr_size_t *bytes_read); +# 533 "../include/apr_file_io.h" +apr_status_t apr_file_write_full(apr_file_t *thefile, + const void *buf, + apr_size_t nbytes, + apr_size_t *bytes_written); +# 552 "../include/apr_file_io.h" +apr_status_t apr_file_writev_full(apr_file_t *thefile, + const struct iovec *vec, + apr_size_t nvec, + apr_size_t *nbytes); + + + + + +apr_status_t apr_file_putc(char ch, apr_file_t *thefile); + + + + + + +apr_status_t apr_file_getc(char *ch, apr_file_t *thefile); + + + + + + +apr_status_t apr_file_ungetc(char ch, apr_file_t *thefile); +# 585 "../include/apr_file_io.h" +apr_status_t apr_file_gets(char *str, int len, + apr_file_t *thefile); + + + + + + +apr_status_t apr_file_puts(const char *str, apr_file_t *thefile); + + + + + +apr_status_t apr_file_flush(apr_file_t *thefile); + + + + + +apr_status_t apr_file_sync(apr_file_t *thefile); + + + + + +apr_status_t apr_file_datasync(apr_file_t *thefile); +# 620 "../include/apr_file_io.h" +apr_status_t apr_file_dup(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p); +# 632 "../include/apr_file_io.h" +apr_status_t apr_file_dup2(apr_file_t *new_file, + apr_file_t *old_file, + apr_pool_t *p); +# 647 "../include/apr_file_io.h" +apr_status_t apr_file_setaside(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p); +# 662 "../include/apr_file_io.h" +apr_status_t apr_file_buffer_set(apr_file_t *thefile, + char * buffer, + apr_size_t bufsize); + + + + + +apr_size_t apr_file_buffer_size_get(apr_file_t *thefile); +# 683 "../include/apr_file_io.h" +apr_status_t apr_file_seek(apr_file_t *thefile, + apr_seek_where_t where, + apr_off_t *offset); +# 700 "../include/apr_file_io.h" +apr_status_t apr_file_pipe_create(apr_file_t **in, + apr_file_t **out, + apr_pool_t *pool); +# 723 "../include/apr_file_io.h" +apr_status_t apr_file_pipe_create_ex(apr_file_t **in, + apr_file_t **out, + apr_int32_t blocking, + apr_pool_t *pool); + + + + + + + +apr_status_t apr_file_namedpipe_create(const char *filename, + apr_fileperms_t perm, + apr_pool_t *pool); + + + + + + +apr_status_t apr_file_pipe_timeout_get(apr_file_t *thepipe, + apr_interval_time_t *timeout); + + + + + + + +apr_status_t apr_file_pipe_timeout_set(apr_file_t *thepipe, + apr_interval_time_t timeout); +# 766 "../include/apr_file_io.h" +apr_status_t apr_file_lock(apr_file_t *thefile, int type); + + + + + +apr_status_t apr_file_unlock(apr_file_t *thefile); +# 781 "../include/apr_file_io.h" +apr_status_t apr_file_name_get(const char **new_path, + apr_file_t *thefile); + + + + + + + +apr_status_t apr_file_data_get(void **data, const char *key, + apr_file_t *file); +# 800 "../include/apr_file_io.h" +apr_status_t apr_file_data_set(apr_file_t *file, void *data, + const char *key, + apr_status_t (*cleanup)(void *)); +# 811 "../include/apr_file_io.h" +int apr_file_printf(apr_file_t *fptr, + const char *format, ...) + __attribute__((format(printf,2,3))); +# 827 "../include/apr_file_io.h" +apr_status_t apr_file_perms_set(const char *fname, + apr_fileperms_t perms); +# 846 "../include/apr_file_io.h" +apr_status_t apr_file_attrs_set(const char *fname, + apr_fileattrs_t attributes, + apr_fileattrs_t attr_mask, + apr_pool_t *pool); +# 859 "../include/apr_file_io.h" +apr_status_t apr_file_mtime_set(const char *fname, + apr_time_t mtime, + apr_pool_t *pool); + + + + + + + +apr_status_t apr_dir_make(const char *path, apr_fileperms_t perm, + apr_pool_t *pool); +# 879 "../include/apr_file_io.h" +apr_status_t apr_dir_make_recursive(const char *path, + apr_fileperms_t perm, + apr_pool_t *pool); +# 890 "../include/apr_file_io.h" +apr_status_t apr_dir_remove(const char *path, apr_pool_t *pool); + + + + + + + +apr_status_t apr_file_info_get(apr_finfo_t *finfo, + apr_int32_t wanted, + apr_file_t *thefile); +# 909 "../include/apr_file_io.h" +apr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset); + + + + + + +apr_int32_t apr_file_flags_get(apr_file_t *f); + + + + +apr_pool_t * apr_file_pool_get (const apr_file_t *thefile); + + + + + +apr_status_t apr_file_inherit_set( apr_file_t *thefile); + + + + +apr_status_t apr_file_inherit_unset( apr_file_t *thefile); +# 951 "../include/apr_file_io.h" +apr_status_t apr_file_mktemp(apr_file_t **fp, char *templ, + apr_int32_t flags, apr_pool_t *p); +# 964 "../include/apr_file_io.h" +apr_status_t apr_temp_dir_get(const char **temp_dir, + apr_pool_t *p); +# 27 "../include/apr_thread_proc.h" 2 + + + + +# 1 "/usr/include/x86_64-linux-gnu/sys/time.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/sys/time.h" 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/sys/time.h" 2 3 4 + +# 1 "/usr/include/x86_64-linux-gnu/bits/time.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/sys/time.h" 2 3 4 +# 55 "/usr/include/x86_64-linux-gnu/sys/time.h" 3 4 +struct timezone + { + int tz_minuteswest; + int tz_dsttime; + }; + +typedef struct timezone *__restrict __timezone_ptr_t; +# 71 "/usr/include/x86_64-linux-gnu/sys/time.h" 3 4 +extern int gettimeofday (struct timeval *__restrict __tv, + __timezone_ptr_t __tz) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + +extern int settimeofday (const struct timeval *__tv, + const struct timezone *__tz) + __attribute__ ((__nothrow__ )); + + + + + +extern int adjtime (const struct timeval *__delta, + struct timeval *__olddelta) __attribute__ ((__nothrow__ )); + + + + +enum __itimer_which + { + + ITIMER_REAL = 0, + + + ITIMER_VIRTUAL = 1, + + + + ITIMER_PROF = 2 + + }; + + + +struct itimerval + { + + struct timeval it_interval; + + struct timeval it_value; + }; + + + + + + +typedef int __itimer_which_t; + + + + +extern int getitimer (__itimer_which_t __which, + struct itimerval *__value) __attribute__ ((__nothrow__ )); + + + + +extern int setitimer (__itimer_which_t __which, + const struct itimerval *__restrict __new, + struct itimerval *__restrict __old) __attribute__ ((__nothrow__ )); + + + + +extern int utimes (const char *__file, const struct timeval __tvp[2]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int lutimes (const char *__file, const struct timeval __tvp[2]) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int futimes (int __fd, const struct timeval __tvp[2]) __attribute__ ((__nothrow__ )); +# 32 "../include/apr_thread_proc.h" 2 +# 1 "/usr/include/x86_64-linux-gnu/sys/resource.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/sys/resource.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/resource.h" 1 3 4 +# 31 "/usr/include/x86_64-linux-gnu/bits/resource.h" 3 4 +enum __rlimit_resource +{ + + RLIMIT_CPU = 0, + + + + RLIMIT_FSIZE = 1, + + + + RLIMIT_DATA = 2, + + + + RLIMIT_STACK = 3, + + + + RLIMIT_CORE = 4, + + + + + + + __RLIMIT_RSS = 5, + + + + RLIMIT_NOFILE = 7, + __RLIMIT_OFILE = RLIMIT_NOFILE, + + + + + RLIMIT_AS = 9, + + + + __RLIMIT_NPROC = 6, + + + + __RLIMIT_MEMLOCK = 8, + + + + __RLIMIT_LOCKS = 10, + + + + __RLIMIT_SIGPENDING = 11, + + + + __RLIMIT_MSGQUEUE = 12, + + + + + + __RLIMIT_NICE = 13, + + + + + __RLIMIT_RTPRIO = 14, + + + + + + __RLIMIT_RTTIME = 15, + + + __RLIMIT_NLIMITS = 16, + __RLIM_NLIMITS = __RLIMIT_NLIMITS + + +}; +# 131 "/usr/include/x86_64-linux-gnu/bits/resource.h" 3 4 +typedef __rlim_t rlim_t; + + + + + + + +struct rlimit + { + + rlim_t rlim_cur; + + rlim_t rlim_max; + }; +# 158 "/usr/include/x86_64-linux-gnu/bits/resource.h" 3 4 +enum __rusage_who +{ + + RUSAGE_SELF = 0, + + + + RUSAGE_CHILDREN = -1 +# 176 "/usr/include/x86_64-linux-gnu/bits/resource.h" 3 4 +}; + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/time.h" 1 3 4 +# 180 "/usr/include/x86_64-linux-gnu/bits/resource.h" 2 3 4 + + + + + + + +struct rusage + { + + struct timeval ru_utime; + + struct timeval ru_stime; + + __extension__ union + { + long int ru_maxrss; + __syscall_slong_t __ru_maxrss_word; + }; + + + + __extension__ union + { + long int ru_ixrss; + __syscall_slong_t __ru_ixrss_word; + }; + + __extension__ union + { + long int ru_idrss; + __syscall_slong_t __ru_idrss_word; + }; + + __extension__ union + { + long int ru_isrss; + __syscall_slong_t __ru_isrss_word; + }; + + + __extension__ union + { + long int ru_minflt; + __syscall_slong_t __ru_minflt_word; + }; + + __extension__ union + { + long int ru_majflt; + __syscall_slong_t __ru_majflt_word; + }; + + __extension__ union + { + long int ru_nswap; + __syscall_slong_t __ru_nswap_word; + }; + + + __extension__ union + { + long int ru_inblock; + __syscall_slong_t __ru_inblock_word; + }; + + __extension__ union + { + long int ru_oublock; + __syscall_slong_t __ru_oublock_word; + }; + + __extension__ union + { + long int ru_msgsnd; + __syscall_slong_t __ru_msgsnd_word; + }; + + __extension__ union + { + long int ru_msgrcv; + __syscall_slong_t __ru_msgrcv_word; + }; + + __extension__ union + { + long int ru_nsignals; + __syscall_slong_t __ru_nsignals_word; + }; + + + + __extension__ union + { + long int ru_nvcsw; + __syscall_slong_t __ru_nvcsw_word; + }; + + + __extension__ union + { + long int ru_nivcsw; + __syscall_slong_t __ru_nivcsw_word; + }; + }; + + + + + + + +enum __priority_which +{ + PRIO_PROCESS = 0, + + PRIO_PGRP = 1, + + PRIO_USER = 2 + +}; +# 25 "/usr/include/x86_64-linux-gnu/sys/resource.h" 2 3 4 +# 42 "/usr/include/x86_64-linux-gnu/sys/resource.h" 3 4 +typedef int __rlimit_resource_t; +typedef int __rusage_who_t; +typedef int __priority_which_t; + + + + + +extern int getrlimit (__rlimit_resource_t __resource, + struct rlimit *__rlimits) __attribute__ ((__nothrow__ )); +# 69 "/usr/include/x86_64-linux-gnu/sys/resource.h" 3 4 +extern int setrlimit (__rlimit_resource_t __resource, + const struct rlimit *__rlimits) __attribute__ ((__nothrow__ )); +# 87 "/usr/include/x86_64-linux-gnu/sys/resource.h" 3 4 +extern int getrusage (__rusage_who_t __who, struct rusage *__usage) __attribute__ ((__nothrow__ )); + + + + + +extern int getpriority (__priority_which_t __which, id_t __who) __attribute__ ((__nothrow__ )); + + + +extern int setpriority (__priority_which_t __which, id_t __who, int __prio) + __attribute__ ((__nothrow__ )); +# 33 "../include/apr_thread_proc.h" 2 +# 45 "../include/apr_thread_proc.h" +typedef enum { + APR_SHELLCMD, + APR_PROGRAM, + APR_PROGRAM_ENV, + APR_PROGRAM_PATH, + APR_SHELLCMD_ENV + + +} apr_cmdtype_e; + +typedef enum { + APR_WAIT, + APR_NOWAIT +} apr_wait_how_e; + + + + + + +typedef enum { + APR_PROC_EXIT = 1, + APR_PROC_SIGNAL = 2, + APR_PROC_SIGNAL_CORE = 4 +} apr_exit_why_e; +# 133 "../include/apr_thread_proc.h" +typedef struct apr_proc_t { + + pid_t pid; + + apr_file_t *in; + + apr_file_t *out; + + apr_file_t *err; +# 161 "../include/apr_thread_proc.h" +} apr_proc_t; +# 173 "../include/apr_thread_proc.h" +typedef void (apr_child_errfn_t)(apr_pool_t *proc, apr_status_t err, + const char *description); + + +typedef struct apr_thread_t apr_thread_t; + + +typedef struct apr_threadattr_t apr_threadattr_t; + + +typedef struct apr_procattr_t apr_procattr_t; + + +typedef struct apr_thread_once_t apr_thread_once_t; + + +typedef struct apr_threadkey_t apr_threadkey_t; + + +typedef struct apr_other_child_rec_t apr_other_child_rec_t; + + + + +typedef void *( *apr_thread_start_t)(apr_thread_t*, void*); + +typedef enum { + APR_KILL_NEVER, + + + APR_KILL_ALWAYS, + APR_KILL_AFTER_TIMEOUT, + APR_JUST_WAIT, + APR_KILL_ONLY_ONCE +} apr_kill_conditions_e; +# 218 "../include/apr_thread_proc.h" +apr_status_t apr_threadattr_create(apr_threadattr_t **new_attr, + apr_pool_t *cont); + + + + + + +apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr, + apr_int32_t on); + + + + + + + +apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr); + + + + + + +apr_status_t apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize); +# 255 "../include/apr_thread_proc.h" +apr_status_t apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t guardsize); +# 266 "../include/apr_thread_proc.h" +apr_status_t apr_thread_create(apr_thread_t **new_thread, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, apr_pool_t *cont); + + + + + + +apr_status_t apr_thread_exit(apr_thread_t *thd, + apr_status_t retval); + + + + + + +apr_status_t apr_thread_join(apr_status_t *retval, + apr_thread_t *thd); + + + + +void apr_thread_yield(void); + + + + + + + +apr_status_t apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p); +# 310 "../include/apr_thread_proc.h" +apr_status_t apr_thread_once(apr_thread_once_t *control, + void (*func)(void)); + + + + + +apr_status_t apr_thread_detach(apr_thread_t *thd); + + + + + + + +apr_status_t apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread); +# 335 "../include/apr_thread_proc.h" +apr_status_t apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_thread_t *thread); + + + + + + + +apr_status_t apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), + apr_pool_t *cont); + + + + + + +apr_status_t apr_threadkey_private_get(void **new_mem, + apr_threadkey_t *key); + + + + + + +apr_status_t apr_threadkey_private_set(void *priv, + apr_threadkey_t *key); + + + + + +apr_status_t apr_threadkey_private_delete(apr_threadkey_t *key); + + + + + + + +apr_status_t apr_threadkey_data_get(void **data, const char *key, + apr_threadkey_t *threadkey); +# 387 "../include/apr_thread_proc.h" +apr_status_t apr_threadkey_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_threadkey_t *threadkey); +# 398 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_create(apr_procattr_t **new_attr, + apr_pool_t *cont); +# 415 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_io_set(apr_procattr_t *attr, + apr_int32_t in, apr_int32_t out, + apr_int32_t err); +# 434 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_child_in_set(struct apr_procattr_t *attr, + apr_file_t *child_in, + apr_file_t *parent_in); +# 451 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_child_out_set(struct apr_procattr_t *attr, + apr_file_t *child_out, + apr_file_t *parent_out); +# 468 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_child_err_set(struct apr_procattr_t *attr, + apr_file_t *child_err, + apr_file_t *parent_err); +# 479 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_dir_set(apr_procattr_t *attr, + const char *dir); +# 493 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd); + + + + + + +apr_status_t apr_procattr_detach_set(apr_procattr_t *attr, + apr_int32_t detach); +# 517 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_limit_set(apr_procattr_t *attr, + apr_int32_t what, + struct rlimit *limit); +# 533 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn); +# 548 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk); +# 558 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace); +# 569 "../include/apr_thread_proc.h" +apr_status_t apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password); + + + + + + +apr_status_t apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname); +# 591 "../include/apr_thread_proc.h" +apr_status_t apr_proc_fork(apr_proc_t *proc, apr_pool_t *cont); +# 610 "../include/apr_thread_proc.h" +apr_status_t apr_proc_create(apr_proc_t *new_proc, + const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, + apr_pool_t *pool); +# 643 "../include/apr_thread_proc.h" +apr_status_t apr_proc_wait(apr_proc_t *proc, + int *exitcode, apr_exit_why_e *exitwhy, + apr_wait_how_e waithow); +# 673 "../include/apr_thread_proc.h" +apr_status_t apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p); +# 688 "../include/apr_thread_proc.h" +apr_status_t apr_proc_detach(int daemonize); +# 707 "../include/apr_thread_proc.h" +void apr_proc_other_child_register(apr_proc_t *proc, + void (*maintenance) (int reason, + void *, + int status), + void *data, apr_file_t *write_fd, + apr_pool_t *p); +# 723 "../include/apr_thread_proc.h" +void apr_proc_other_child_unregister(void *data); +# 745 "../include/apr_thread_proc.h" +apr_status_t apr_proc_other_child_alert(apr_proc_t *proc, + int reason, + int status); +# 756 "../include/apr_thread_proc.h" +void apr_proc_other_child_refresh(apr_other_child_rec_t *ocr, + int reason); + + + + + + + +void apr_proc_other_child_refresh_all(int reason); + + + + + + +apr_status_t apr_proc_kill(apr_proc_t *proc, int sig); +# 787 "../include/apr_thread_proc.h" +void apr_pool_note_subprocess(apr_pool_t *a, apr_proc_t *proc, + apr_kill_conditions_e how); +# 798 "../include/apr_thread_proc.h" +apr_status_t apr_setup_signal_thread(void); +# 807 "../include/apr_thread_proc.h" +apr_status_t apr_signal_thread(int(*signal_handler)(int signum)); + + + + + + + +apr_pool_t * apr_thread_pool_get (const apr_thread_t *thethread); +# 20 "./../test/testatomic.c" 2 + + +# 1 "../include/apr_atomic.h" 1 +# 47 "../include/apr_atomic.h" +apr_status_t apr_atomic_init(apr_pool_t *p); +# 59 "../include/apr_atomic.h" +apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem); + + + + + + +void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val); + + + + + + + +apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val); + + + + + + +void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val); + + + + + + +apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem); + + + + + + +int apr_atomic_dec32(volatile apr_uint32_t *mem); +# 105 "../include/apr_atomic.h" +apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, + apr_uint32_t cmp); + + + + + + + +apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val); +# 124 "../include/apr_atomic.h" +void* apr_atomic_casptr(volatile void **mem, void *with, const void *cmp); + + + + + + + +void* apr_atomic_xchgptr(volatile void **mem, void *with); +# 23 "./../test/testatomic.c" 2 +# 37 "./../test/testatomic.c" +static void test_init(abts_case *tc, void *data) +{ + apr_assert_success(tc, "Could not initliaze atomics", apr_atomic_init(p), 39); +} + +static void test_set32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_atomic_set32(&y32, 2); + abts_int_equal(tc, 2, y32, 46); +} + +static void test_read32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_atomic_set32(&y32, 2); + abts_int_equal(tc, 2, apr_atomic_read32(&y32), 53); +} + +static void test_dec32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + int rv; + + apr_atomic_set32(&y32, 2); + + rv = apr_atomic_dec32(&y32); + abts_int_equal(tc, 1, y32, 64); + abts_assert(tc, "atomic_dec returned zero when it shouldn't", rv != 0, 65);; + + rv = apr_atomic_dec32(&y32); + abts_int_equal(tc, 0, y32, 68); + abts_assert(tc, "atomic_dec didn't returned zero when it should", rv == 0, 69);; +} + +static void test_xchg32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 100); + oldval = apr_atomic_xchg32(&y32, 50); + + abts_int_equal(tc, 100, oldval, 80); + abts_int_equal(tc, 50, y32, 81); +} + +static void test_xchgptr(abts_case *tc, void *data) +{ + int a; + void *ref = "little piggy"; + volatile void *target_ptr = ref; + void *old_ptr; + + old_ptr = apr_atomic_xchgptr(&target_ptr, &a); + abts_ptr_equal(tc, ref, old_ptr, 92); + abts_ptr_equal(tc, &a, (void *) target_ptr, 93); +} + +static void test_cas_equal(abts_case *tc, void *data) +{ + apr_uint32_t casval = 0; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 12, 0); + abts_int_equal(tc, 0, oldval, 102); + abts_int_equal(tc, 12, casval, 103); +} + +static void test_cas_equal_nonnull(abts_case *tc, void *data) +{ + apr_uint32_t casval = 12; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 23, 12); + abts_int_equal(tc, 12, oldval, 112); + abts_int_equal(tc, 23, casval, 113); +} + +static void test_cas_notequal(abts_case *tc, void *data) +{ + apr_uint32_t casval = 12; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 23, 2); + abts_int_equal(tc, 12, oldval, 122); + abts_int_equal(tc, 12, casval, 123); +} + +static void test_casptr_equal(abts_case *tc, void *data) +{ + int a; + volatile void *target_ptr = ((void*)0); + void *old_ptr; + + old_ptr = apr_atomic_casptr(&target_ptr, &a, ((void*)0)); + abts_ptr_equal(tc, ((void*)0), old_ptr, 133); + abts_ptr_equal(tc, &a, (void *) target_ptr, 134); +} + +static void test_casptr_equal_nonnull(abts_case *tc, void *data) +{ + int a, b; + volatile void *target_ptr = &a; + void *old_ptr; + + old_ptr = apr_atomic_casptr(&target_ptr, &b, &a); + abts_ptr_equal(tc, &a, old_ptr, 144); + abts_ptr_equal(tc, &b, (void *) target_ptr, 145); +} + +static void test_casptr_notequal(abts_case *tc, void *data) +{ + int a, b; + volatile void *target_ptr = &a; + void *old_ptr; + + old_ptr = apr_atomic_casptr(&target_ptr, &a, &b); + abts_ptr_equal(tc, &a, old_ptr, 155); + abts_ptr_equal(tc, &a, (void *) target_ptr, 156); +} + +static void test_add32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 23); + oldval = apr_atomic_add32(&y32, 4); + abts_int_equal(tc, 23, oldval, 166); + abts_int_equal(tc, 27, y32, 167); +} + +static void test_add32_neg(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 23); + oldval = apr_atomic_add32(&y32, -10); + abts_int_equal(tc, 23, oldval, 177); + abts_int_equal(tc, 13, y32, 178); +} + +static void test_inc32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 23); + oldval = apr_atomic_inc32(&y32); + abts_int_equal(tc, 23, oldval, 188); + abts_int_equal(tc, 24, y32, 189); +} + +static void test_set_add_inc_sub(abts_case *tc, void *data) +{ + apr_uint32_t y32; + + apr_atomic_set32(&y32, 0); + apr_atomic_add32(&y32, 20); + apr_atomic_inc32(&y32); + apr_atomic_sub32(&y32, 10); + + abts_int_equal(tc, 11, y32, 201); +} + +static void test_wrap_zero(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_uint32_t rv; + apr_uint32_t minus1 = -1; + char *str; + + apr_atomic_set32(&y32, 0); + rv = apr_atomic_dec32(&y32); + + abts_assert(tc, "apr_atomic_dec32 on zero returned zero.", rv != 0, 214);; + str = apr_psprintf(p, "zero wrap failed: 0 - 1 = %d", y32); + abts_assert(tc, str, y32 == minus1, 216);; +} + +static void test_inc_neg1(abts_case *tc, void *data) +{ + apr_uint32_t y32 = -1; + apr_uint32_t minus1 = -1; + apr_uint32_t rv; + char *str; + + rv = apr_atomic_inc32(&y32); + + abts_assert(tc, "apr_atomic_inc32 didn't return the old value.", rv == minus1, 228);; + str = apr_psprintf(p, "zero wrap failed: -1 + 1 = %d", y32); + abts_assert(tc, str, y32 == 0, 230);; +} + + + + +void * thread_func_mutex(apr_thread_t *thd, void *data); +void * thread_func_atomic(apr_thread_t *thd, void *data); + +apr_thread_mutex_t *thread_lock; +volatile apr_uint32_t mutex_locks = 0; +volatile apr_uint32_t atomic_ops = 0; +apr_status_t exit_ret_val = 123; + +void * thread_func_mutex(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < 1; i++) { + apr_thread_mutex_lock(thread_lock); + mutex_locks++; + apr_thread_mutex_unlock(thread_lock); + } + apr_thread_exit(thd, exit_ret_val); + return ((void*)0); +} + +void * thread_func_atomic(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < 1 ; i++) { + apr_atomic_inc32(&atomic_ops); + apr_atomic_add32(&atomic_ops, 2); + apr_atomic_dec32(&atomic_ops); + apr_atomic_dec32(&atomic_ops); + } + apr_thread_exit(thd, exit_ret_val); + return ((void*)0); +} + +static void test_atomics_threaded(abts_case *tc, void *data) +{ + apr_thread_t *t1[2]; + apr_thread_t *t2[2]; + apr_status_t rv; + int i; + + + + + + rv = apr_thread_mutex_create(&thread_lock, 0x0, p); + apr_assert_success(tc, "Could not create lock", rv, 283); + + for (i = 0; i < 2; i++) { + apr_status_t r1, r2; + r1 = apr_thread_create(&t1[i], ((void*)0), thread_func_mutex, ((void*)0), p); + r2 = apr_thread_create(&t2[i], ((void*)0), thread_func_atomic, ((void*)0), p); + abts_assert(tc, "Failed creating threads", !r1 && !r2, 289);; + } + + for (i = 0; i < 2; i++) { + apr_status_t s1, s2; + apr_thread_join(&s1, t1[i]); + apr_thread_join(&s2, t2[i]); + + abts_assert(tc, "Invalid return value from thread_join", s1 == exit_ret_val && s2 == exit_ret_val, 298);; + + } + + abts_int_equal(tc, 2 * 1, mutex_locks, 301); + abts_int_equal(tc, 2 * 1, apr_atomic_read32(&atomic_ops), 303); + + + rv = apr_thread_mutex_destroy(thread_lock); + abts_assert(tc, "Failed creating threads", rv == 0, 306);; +} + +typedef struct tbox_t tbox_t; + +struct tbox_t { + abts_case *tc; + apr_uint32_t *mem; + apr_uint32_t preval; + apr_uint32_t postval; + apr_uint32_t loop; + void (*func)(tbox_t *box); +}; + +static __inline__ void busyloop_read32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + val = apr_atomic_read32(tbox->mem); + + if (val != tbox->preval) + apr_thread_yield(); + else + break; + } while (1); +} + +static void busyloop_set32(tbox_t *tbox) +{ + do { + busyloop_read32(tbox); + apr_atomic_set32(tbox->mem, tbox->postval); + } while (--tbox->loop); +} + +static void busyloop_add32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + busyloop_read32(tbox); + val = apr_atomic_add32(tbox->mem, tbox->postval); + apr_thread_mutex_lock(thread_lock); + abts_int_equal(tbox->tc, val, tbox->preval, 350); + apr_thread_mutex_unlock(thread_lock); + } while (--tbox->loop); +} + +static void busyloop_sub32(tbox_t *tbox) +{ + do { + busyloop_read32(tbox); + apr_atomic_sub32(tbox->mem, tbox->postval); + } while (--tbox->loop); +} + +static void busyloop_inc32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + busyloop_read32(tbox); + val = apr_atomic_inc32(tbox->mem); + apr_thread_mutex_lock(thread_lock); + abts_int_equal(tbox->tc, val, tbox->preval, 371); + apr_thread_mutex_unlock(thread_lock); + } while (--tbox->loop); +} + +static void busyloop_dec32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + busyloop_read32(tbox); + val = apr_atomic_dec32(tbox->mem); + apr_thread_mutex_lock(thread_lock); + abts_int_nequal(tbox->tc, 0, val, 384); + apr_thread_mutex_unlock(thread_lock); + } while (--tbox->loop); +} + +static void busyloop_cas32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + do { + val = apr_atomic_cas32(tbox->mem, tbox->postval, tbox->preval); + + if (val != tbox->preval) + apr_thread_yield(); + else + break; + } while (1); + } while (--tbox->loop); +} + +static void busyloop_xchg32(tbox_t *tbox) +{ + apr_uint32_t val; + + do { + busyloop_read32(tbox); + val = apr_atomic_xchg32(tbox->mem, tbox->postval); + apr_thread_mutex_lock(thread_lock); + abts_int_equal(tbox->tc, val, tbox->preval, 413); + apr_thread_mutex_unlock(thread_lock); + } while (--tbox->loop); +} + +static void * thread_func_busyloop(apr_thread_t *thd, void *data) +{ + tbox_t *tbox = data; + + tbox->func(tbox); + + apr_thread_exit(thd, 0); + + return ((void*)0); +} + +static void test_atomics_busyloop_threaded(abts_case *tc, void *data) +{ + unsigned int i; + apr_status_t rv; + apr_uint32_t count = 0; + tbox_t tbox[2]; + apr_thread_t *thread[2]; + + rv = apr_thread_mutex_create(&thread_lock, 0x0, p); + apr_assert_success(tc, "Could not create lock", rv, 438); + + + for (i = 0; i < 2; i++) { + tbox[i].tc = tc; + tbox[i].mem = &count; + tbox[i].loop = 50; + } + + tbox[0].preval = 98; + tbox[0].postval = 3891; + tbox[0].func = busyloop_add32; + + tbox[1].preval = 3989; + tbox[1].postval = 1010; + tbox[1].func = busyloop_sub32; + + tbox[2].preval = 2979; + tbox[2].postval = 0; + tbox[2].func = busyloop_inc32; + + tbox[3].preval = 2980; + tbox[3].postval = 16384; + tbox[3].func = busyloop_set32; + + tbox[4].preval = 16384; + tbox[4].postval = 0; + tbox[4].func = busyloop_dec32; + + tbox[5].preval = 16383; + tbox[5].postval = 1048576; + tbox[5].func = busyloop_cas32; + + tbox[6].preval = 1048576; + tbox[6].postval = 98; + tbox[6].func = busyloop_xchg32; + + + for (i = 0; i < 2; i++) { + rv = apr_thread_create(&thread[i], ((void*)0), thread_func_busyloop, + &tbox[i], p); + abts_assert(tc, "Failed creating thread", rv == 0, 479);; + } + + + apr_atomic_set32(tbox->mem, 98); + + for (i = 0; i < 2; i++) { + apr_status_t retval; + rv = apr_thread_join(&retval, thread[i]); + abts_assert(tc, "Thread join failed", rv == 0, 488);; + abts_assert(tc, "Invalid return value from thread_join", retval == 0, 489);; + } + + abts_int_equal(tbox->tc, 98, count, 492); + + rv = apr_thread_mutex_destroy(thread_lock); + abts_assert(tc, "Failed creating threads", rv == 0, 495);; +} + + + +abts_suite *testatomic(abts_suite *suite) +{ + suite = abts_add_suite(suite, "./../test/testatomic.c"); + + abts_run_test(suite, test_init, ((void*)0)); + abts_run_test(suite, test_set32, ((void*)0)); + abts_run_test(suite, test_read32, ((void*)0)); + abts_run_test(suite, test_dec32, ((void*)0)); + abts_run_test(suite, test_xchg32, ((void*)0)); + abts_run_test(suite, test_xchgptr, ((void*)0)); + abts_run_test(suite, test_cas_equal, ((void*)0)); + abts_run_test(suite, test_cas_equal_nonnull, ((void*)0)); + abts_run_test(suite, test_cas_notequal, ((void*)0)); + abts_run_test(suite, test_casptr_equal, ((void*)0)); + abts_run_test(suite, test_casptr_equal_nonnull, ((void*)0)); + abts_run_test(suite, test_casptr_notequal, ((void*)0)); + abts_run_test(suite, test_add32, ((void*)0)); + abts_run_test(suite, test_add32_neg, ((void*)0)); + abts_run_test(suite, test_inc32, ((void*)0)); + abts_run_test(suite, test_set_add_inc_sub, ((void*)0)); + abts_run_test(suite, test_wrap_zero, ((void*)0)); + abts_run_test(suite, test_inc_neg1, ((void*)0)); + + + abts_run_test(suite, test_atomics_threaded, ((void*)0)); + abts_run_test(suite, test_atomics_busyloop_threaded, ((void*)0)); + + + return suite; +} +# 10 "main2.c" 2 +# 1 "./../test/testutil.c" 1 +# 20 "./../test/testutil.c" +# 1 "./../test/abts.h" 1 +# 21 "./../test/testutil.c" 2 +# 1 "./../test/testutil.h" 1 +# 19 "./../test/testutil.h" +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 22 "./../test/testutil.c" 2 + + +apr_pool_t *p; + +void apr_assert_success(abts_case* tc, const char* context, apr_status_t rv, + int lineno) +{ + if (rv == ((20000 + 50000) + 23)) { + abts_not_impl(tc, context, lineno); + } else if (rv != 0) { + char buf[8096], ebuf[128]; + sprintf(buf, "%s (%d): %s\n", context, rv, + apr_strerror(rv, ebuf, sizeof ebuf)); + abts_fail(tc, buf, lineno); + } +} + +void initialize(void) { + apr_initialize(); + atexit(apr_terminate); + + apr_pool_create_ex(&p, ((void*)0), ((void*)0), ((void*)0)); +} +# 11 "main2.c" 2 +# 1 "./../locks/unix/thread_mutex.c" 1 +# 17 "./../locks/unix/thread_mutex.c" +# 1 "../include/arch/unix/apr_arch_thread_mutex.h" 1 +# 21 "../include/arch/unix/apr_arch_thread_mutex.h" +# 1 "../include/arch/unix/apr_private.h" 1 +# 999 "../include/arch/unix/apr_private.h" +# 1 "../include/arch/unix/../apr_private_common.h" 1 +# 27 "../include/arch/unix/../apr_private_common.h" +apr_status_t apr_filepath_list_split_impl(apr_array_header_t **pathelts, + const char *liststr, + char separator, + apr_pool_t *p); + +apr_status_t apr_filepath_list_merge_impl(char **liststr, + apr_array_header_t *pathelts, + char separator, + apr_pool_t *p); +# 1000 "../include/arch/unix/apr_private.h" 2 +# 22 "../include/arch/unix/apr_arch_thread_mutex.h" 2 + + +# 1 "../include/apr_portable.h" 1 +# 32 "../include/apr_portable.h" +# 1 "../include/apr_network_io.h" 1 +# 31 "../include/apr_network_io.h" +# 1 "/usr/include/netinet/in.h" 1 3 4 +# 22 "/usr/include/netinet/in.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stdint.h" 1 3 4 +# 23 "/usr/include/netinet/in.h" 2 3 4 + + + + + + + +typedef uint32_t in_addr_t; +struct in_addr + { + in_addr_t s_addr; + }; + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/in.h" 1 3 4 +# 112 "/usr/include/x86_64-linux-gnu/bits/in.h" 3 4 +struct ip_opts + { + struct in_addr ip_dst; + char ip_opts[40]; + }; + + +struct ip_mreqn + { + struct in_addr imr_multiaddr; + struct in_addr imr_address; + int imr_ifindex; + }; + + +struct in_pktinfo + { + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; + }; +# 38 "/usr/include/netinet/in.h" 2 3 4 + + +enum + { + IPPROTO_IP = 0, + + IPPROTO_ICMP = 1, + + IPPROTO_IGMP = 2, + + IPPROTO_IPIP = 4, + + IPPROTO_TCP = 6, + + IPPROTO_EGP = 8, + + IPPROTO_PUP = 12, + + IPPROTO_UDP = 17, + + IPPROTO_IDP = 22, + + IPPROTO_TP = 29, + + IPPROTO_DCCP = 33, + + IPPROTO_IPV6 = 41, + + IPPROTO_RSVP = 46, + + IPPROTO_GRE = 47, + + IPPROTO_ESP = 50, + + IPPROTO_AH = 51, + + IPPROTO_MTP = 92, + + IPPROTO_BEETPH = 94, + + IPPROTO_ENCAP = 98, + + IPPROTO_PIM = 103, + + IPPROTO_COMP = 108, + + IPPROTO_SCTP = 132, + + IPPROTO_UDPLITE = 136, + + IPPROTO_RAW = 255, + + IPPROTO_MAX + }; + + + + + +enum + { + IPPROTO_HOPOPTS = 0, + + IPPROTO_ROUTING = 43, + + IPPROTO_FRAGMENT = 44, + + IPPROTO_ICMPV6 = 58, + + IPPROTO_NONE = 59, + + IPPROTO_DSTOPTS = 60, + + IPPROTO_MH = 135 + + }; + + + +typedef uint16_t in_port_t; + + +enum + { + IPPORT_ECHO = 7, + IPPORT_DISCARD = 9, + IPPORT_SYSTAT = 11, + IPPORT_DAYTIME = 13, + IPPORT_NETSTAT = 15, + IPPORT_FTP = 21, + IPPORT_TELNET = 23, + IPPORT_SMTP = 25, + IPPORT_TIMESERVER = 37, + IPPORT_NAMESERVER = 42, + IPPORT_WHOIS = 43, + IPPORT_MTP = 57, + + IPPORT_TFTP = 69, + IPPORT_RJE = 77, + IPPORT_FINGER = 79, + IPPORT_TTYLINK = 87, + IPPORT_SUPDUP = 95, + + + IPPORT_EXECSERVER = 512, + IPPORT_LOGINSERVER = 513, + IPPORT_CMDSERVER = 514, + IPPORT_EFSSERVER = 520, + + + IPPORT_BIFFUDP = 512, + IPPORT_WHOSERVER = 513, + IPPORT_ROUTESERVER = 520, + + + IPPORT_RESERVED = 1024, + + + IPPORT_USERRESERVED = 5000 + }; +# 209 "/usr/include/netinet/in.h" 3 4 +struct in6_addr + { + union + { + uint8_t __u6_addr8[16]; + + uint16_t __u6_addr16[8]; + uint32_t __u6_addr32[4]; + + } __in6_u; + + + + + + }; + + +extern const struct in6_addr in6addr_any; +extern const struct in6_addr in6addr_loopback; +# 237 "/usr/include/netinet/in.h" 3 4 +struct sockaddr_in + { + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; + + + unsigned char sin_zero[sizeof (struct sockaddr) - + (sizeof (unsigned short int)) - + sizeof (in_port_t) - + sizeof (struct in_addr)]; + }; + + + +struct sockaddr_in6 + { + sa_family_t sin6_family; + in_port_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; + uint32_t sin6_scope_id; + }; + + + + +struct ip_mreq + { + + struct in_addr imr_multiaddr; + + + struct in_addr imr_interface; + }; + +struct ip_mreq_source + { + + struct in_addr imr_multiaddr; + + + struct in_addr imr_interface; + + + struct in_addr imr_sourceaddr; + }; + + + + +struct ipv6_mreq + { + + struct in6_addr ipv6mr_multiaddr; + + + unsigned int ipv6mr_interface; + }; + + + + +struct group_req + { + + uint32_t gr_interface; + + + struct sockaddr_storage gr_group; + }; + +struct group_source_req + { + + uint32_t gsr_interface; + + + struct sockaddr_storage gsr_group; + + + struct sockaddr_storage gsr_source; + }; + + + +struct ip_msfilter + { + + struct in_addr imsf_multiaddr; + + + struct in_addr imsf_interface; + + + uint32_t imsf_fmode; + + + uint32_t imsf_numsrc; + + struct in_addr imsf_slist[1]; + }; + + + + + +struct group_filter + { + + uint32_t gf_interface; + + + struct sockaddr_storage gf_group; + + + uint32_t gf_fmode; + + + uint32_t gf_numsrc; + + struct sockaddr_storage gf_slist[1]; +}; +# 374 "/usr/include/netinet/in.h" 3 4 +extern uint32_t ntohl (uint32_t __netlong) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern uint16_t ntohs (uint16_t __netshort) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern uint32_t htonl (uint32_t __hostlong) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern uint16_t htons (uint16_t __hostshort) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/byteswap.h" 1 3 4 +# 386 "/usr/include/netinet/in.h" 2 3 4 +# 501 "/usr/include/netinet/in.h" 3 4 +extern int bindresvport (int __sockfd, struct sockaddr_in *__sock_in) __attribute__ ((__nothrow__ )); + + +extern int bindresvport6 (int __sockfd, struct sockaddr_in6 *__sock_in) + __attribute__ ((__nothrow__ )); +# 32 "../include/apr_network_io.h" 2 +# 108 "../include/apr_network_io.h" +typedef enum { + APR_SHUTDOWN_READ, + APR_SHUTDOWN_WRITE, + APR_SHUTDOWN_READWRITE +} apr_shutdown_how_e; +# 172 "../include/apr_network_io.h" +typedef enum { + APR_LOCAL, + APR_REMOTE +} apr_interface_e; +# 193 "../include/apr_network_io.h" +typedef struct apr_socket_t apr_socket_t; + + + +typedef struct apr_hdtr_t apr_hdtr_t; + +typedef struct in_addr apr_in_addr_t; + +typedef struct apr_ipsubnet_t apr_ipsubnet_t; + + +typedef apr_uint16_t apr_port_t; + + + + +typedef struct apr_sockaddr_t apr_sockaddr_t; + + + +struct apr_sockaddr_t { + + apr_pool_t *pool; + + char *hostname; + + char *servname; + + apr_port_t port; + + apr_int32_t family; + + apr_socklen_t salen; + + int ipaddr_len; + + + int addr_str_len; + + + void *ipaddr_ptr; + + + apr_sockaddr_t *next; + + union { + + struct sockaddr_in sin; + + + struct sockaddr_in6 sin6; + + + + + struct sockaddr_storage sas; + + } sa; +}; +# 263 "../include/apr_network_io.h" +struct apr_hdtr_t { + + struct iovec* headers; + + int numheaders; + + struct iovec* trailers; + + int numtrailers; +}; +# 287 "../include/apr_network_io.h" +apr_status_t apr_socket_create(apr_socket_t **new_sock, + int family, int type, + int protocol, + apr_pool_t *cont); +# 305 "../include/apr_network_io.h" +apr_status_t apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how); + + + + + +apr_status_t apr_socket_close(apr_socket_t *thesocket); +# 321 "../include/apr_network_io.h" +apr_status_t apr_socket_bind(apr_socket_t *sock, + apr_sockaddr_t *sa); +# 331 "../include/apr_network_io.h" +apr_status_t apr_socket_listen(apr_socket_t *sock, + apr_int32_t backlog); +# 345 "../include/apr_network_io.h" +apr_status_t apr_socket_accept(apr_socket_t **new_sock, + apr_socket_t *sock, + apr_pool_t *connection_pool); + + + + + + + +apr_status_t apr_socket_connect(apr_socket_t *sock, + apr_sockaddr_t *sa); +# 370 "../include/apr_network_io.h" +apr_status_t apr_socket_atreadeof(apr_socket_t *sock, + int *atreadeof); +# 396 "../include/apr_network_io.h" +apr_status_t apr_sockaddr_info_get(apr_sockaddr_t **sa, + const char *hostname, + apr_int32_t family, + apr_port_t port, + apr_int32_t flags, + apr_pool_t *p); +# 411 "../include/apr_network_io.h" +apr_status_t apr_getnameinfo(char **hostname, + apr_sockaddr_t *sa, + apr_int32_t flags); +# 445 "../include/apr_network_io.h" +apr_status_t apr_parse_addr_port(char **addr, + char **scope_id, + apr_port_t *port, + const char *str, + apr_pool_t *p); +# 459 "../include/apr_network_io.h" +apr_status_t apr_gethostname(char *buf, int len, apr_pool_t *cont); + + + + + + + +apr_status_t apr_socket_data_get(void **data, const char *key, + apr_socket_t *sock); +# 477 "../include/apr_network_io.h" +apr_status_t apr_socket_data_set(apr_socket_t *sock, void *data, + const char *key, + apr_status_t (*cleanup)(void*)); +# 498 "../include/apr_network_io.h" +apr_status_t apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len); +# 519 "../include/apr_network_io.h" +apr_status_t apr_socket_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len); +# 530 "../include/apr_network_io.h" +apr_status_t apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len); +# 548 "../include/apr_network_io.h" +apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len); +# 573 "../include/apr_network_io.h" +apr_status_t apr_socket_sendfile(apr_socket_t *sock, + apr_file_t *file, + apr_hdtr_t *hdtr, + apr_off_t *offset, + apr_size_t *len, + apr_int32_t flags); +# 601 "../include/apr_network_io.h" +apr_status_t apr_socket_recv(apr_socket_t *sock, + char *buf, apr_size_t *len); +# 626 "../include/apr_network_io.h" +apr_status_t apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on); +# 640 "../include/apr_network_io.h" +apr_status_t apr_socket_timeout_set(apr_socket_t *sock, + apr_interval_time_t t); +# 662 "../include/apr_network_io.h" +apr_status_t apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on); + + + + + + +apr_status_t apr_socket_timeout_get(apr_socket_t *sock, + apr_interval_time_t *t); + + + + + + + +apr_status_t apr_socket_atmark(apr_socket_t *sock, + int *atmark); +# 690 "../include/apr_network_io.h" +apr_status_t apr_socket_addr_get(apr_sockaddr_t **sa, + apr_interface_e which, + apr_socket_t *sock); +# 701 "../include/apr_network_io.h" +apr_status_t apr_sockaddr_ip_get(char **addr, + apr_sockaddr_t *sockaddr); + + + + + + +apr_status_t apr_sockaddr_ip_getbuf(char *buf, apr_size_t buflen, + apr_sockaddr_t *sockaddr); +# 722 "../include/apr_network_io.h" +int apr_sockaddr_equal(const apr_sockaddr_t *addr1, + const apr_sockaddr_t *addr2); +# 733 "../include/apr_network_io.h" +int apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr); + + + + + + +apr_status_t apr_socket_type_get(apr_socket_t *sock, + int *type); + + + + + + +apr_status_t apr_getservbyname(apr_sockaddr_t *sockaddr, + const char *servname); +# 758 "../include/apr_network_io.h" +apr_status_t apr_ipsubnet_create(apr_ipsubnet_t **ipsub, + const char *ipstr, + const char *mask_or_numbits, + apr_pool_t *p); +# 770 "../include/apr_network_io.h" +int apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa); +# 791 "../include/apr_network_io.h" +apr_status_t apr_socket_protocol_get(apr_socket_t *sock, + int *protocol); + + + + +apr_pool_t * apr_socket_pool_get (const apr_socket_t *thesocket); + + + + +apr_status_t apr_socket_inherit_set( apr_socket_t *thesocket); + + + + +apr_status_t apr_socket_inherit_unset( apr_socket_t *thesocket); +# 823 "../include/apr_network_io.h" +apr_status_t apr_mcast_join(apr_socket_t *sock, + apr_sockaddr_t *join, + apr_sockaddr_t *iface, + apr_sockaddr_t *source); +# 838 "../include/apr_network_io.h" +apr_status_t apr_mcast_leave(apr_socket_t *sock, + apr_sockaddr_t *addr, + apr_sockaddr_t *iface, + apr_sockaddr_t *source); +# 850 "../include/apr_network_io.h" +apr_status_t apr_mcast_hops(apr_socket_t *sock, + apr_byte_t ttl); + + + + + + +apr_status_t apr_mcast_loopback(apr_socket_t *sock, + apr_byte_t opt); + + + + + + + +apr_status_t apr_mcast_interface(apr_socket_t *sock, + apr_sockaddr_t *iface); +# 33 "../include/apr_portable.h" 2 + +# 1 "../include/apr_global_mutex.h" 1 +# 26 "../include/apr_global_mutex.h" +# 1 "../include/apr_proc_mutex.h" 1 +# 44 "../include/apr_proc_mutex.h" +typedef enum { + APR_LOCK_FCNTL, + APR_LOCK_FLOCK, + APR_LOCK_SYSVSEM, + APR_LOCK_PROC_PTHREAD, + APR_LOCK_POSIXSEM, + APR_LOCK_DEFAULT +} apr_lockmech_e; + + +typedef struct apr_proc_mutex_t apr_proc_mutex_t; +# 79 "../include/apr_proc_mutex.h" +apr_status_t apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool); +# 95 "../include/apr_proc_mutex.h" +apr_status_t apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool); + + + + + + +apr_status_t apr_proc_mutex_lock(apr_proc_mutex_t *mutex); +# 113 "../include/apr_proc_mutex.h" +apr_status_t apr_proc_mutex_trylock(apr_proc_mutex_t *mutex); + + + + + +apr_status_t apr_proc_mutex_unlock(apr_proc_mutex_t *mutex); + + + + + +apr_status_t apr_proc_mutex_destroy(apr_proc_mutex_t *mutex); + + + + + + + +apr_status_t apr_proc_mutex_cleanup(void *mutex); + + + + + + +const char * apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex); + + + + + + +const char * apr_proc_mutex_name(apr_proc_mutex_t *mutex); + + + + +const char * apr_proc_mutex_defname(void); + + + + + +apr_pool_t * apr_proc_mutex_pool_get (const apr_proc_mutex_t *theproc_mutex); +# 27 "../include/apr_global_mutex.h" 2 +# 46 "../include/apr_global_mutex.h" +typedef struct apr_global_mutex_t apr_global_mutex_t; +# 74 "../include/apr_global_mutex.h" +apr_status_t apr_global_mutex_create(apr_global_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool); +# 90 "../include/apr_global_mutex.h" +apr_status_t apr_global_mutex_child_init( + apr_global_mutex_t **mutex, + const char *fname, + apr_pool_t *pool); + + + + + + +apr_status_t apr_global_mutex_lock(apr_global_mutex_t *mutex); +# 109 "../include/apr_global_mutex.h" +apr_status_t apr_global_mutex_trylock(apr_global_mutex_t *mutex); + + + + + +apr_status_t apr_global_mutex_unlock(apr_global_mutex_t *mutex); + + + + + +apr_status_t apr_global_mutex_destroy(apr_global_mutex_t *mutex); + + + + + +const char * apr_global_mutex_lockfile(apr_global_mutex_t *mutex); + + + + + + + +const char * apr_global_mutex_name(apr_global_mutex_t *mutex); + + + + + +apr_pool_t * apr_global_mutex_pool_get (const apr_global_mutex_t *theglobal_mutex); +# 35 "../include/apr_portable.h" 2 + + +# 1 "../include/apr_dso.h" 1 +# 44 "../include/apr_dso.h" +typedef struct apr_dso_handle_t apr_dso_handle_t; + + + + +typedef void * apr_dso_handle_sym_t; +# 59 "../include/apr_dso.h" +apr_status_t apr_dso_load(apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *ctx); + + + + + +apr_status_t apr_dso_unload(apr_dso_handle_t *handle); + + + + + + + +apr_status_t apr_dso_sym(apr_dso_handle_sym_t *ressym, + apr_dso_handle_t *handle, + const char *symname); + + + + + + + +const char * apr_dso_error(apr_dso_handle_t *dso, char *buf, apr_size_t bufsize); +# 38 "../include/apr_portable.h" 2 +# 1 "../include/apr_shm.h" 1 +# 43 "../include/apr_shm.h" +typedef struct apr_shm_t apr_shm_t; +# 69 "../include/apr_shm.h" +apr_status_t apr_shm_create(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *pool); +# 114 "../include/apr_shm.h" +apr_status_t apr_shm_create_ex(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *pool, + apr_int32_t flags); +# 135 "../include/apr_shm.h" +apr_status_t apr_shm_remove(const char *filename, + apr_pool_t *pool); + + + + + +apr_status_t apr_shm_destroy(apr_shm_t *m); +# 153 "../include/apr_shm.h" +apr_status_t apr_shm_attach(apr_shm_t **m, + const char *filename, + apr_pool_t *pool); +# 167 "../include/apr_shm.h" +apr_status_t apr_shm_attach_ex(apr_shm_t **m, + const char *filename, + apr_pool_t *pool, + apr_int32_t flags); + + + + + + +apr_status_t apr_shm_detach(apr_shm_t *m); +# 188 "../include/apr_shm.h" +void * apr_shm_baseaddr_get(const apr_shm_t *m); + + + + + + +apr_size_t apr_shm_size_get(const apr_shm_t *m); + + + + +apr_pool_t * apr_shm_pool_get (const apr_shm_t *theshm); +# 39 "../include/apr_portable.h" 2 + + +# 1 "/usr/include/dirent.h" 1 3 4 +# 61 "/usr/include/dirent.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/dirent.h" 1 3 4 +# 22 "/usr/include/x86_64-linux-gnu/bits/dirent.h" 3 4 +struct dirent + { + + __ino_t d_ino; + __off_t d_off; + + + + + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; + }; +# 62 "/usr/include/dirent.h" 2 3 4 +# 97 "/usr/include/dirent.h" 3 4 +enum + { + DT_UNKNOWN = 0, + + DT_FIFO = 1, + + DT_CHR = 2, + + DT_DIR = 4, + + DT_BLK = 6, + + DT_REG = 8, + + DT_LNK = 10, + + DT_SOCK = 12, + + DT_WHT = 14 + + }; +# 127 "/usr/include/dirent.h" 3 4 +typedef struct __dirstream DIR; + + + + + + +extern DIR *opendir (const char *__name) __attribute__ ((__nonnull__ (1))); + + + + + + +extern DIR *fdopendir (int __fd); + + + + + + + +extern int closedir (DIR *__dirp) __attribute__ ((__nonnull__ (1))); +# 162 "/usr/include/dirent.h" 3 4 +extern struct dirent *readdir (DIR *__dirp) __attribute__ ((__nonnull__ (1))); +# 183 "/usr/include/dirent.h" 3 4 +extern int readdir_r (DIR *__restrict __dirp, + struct dirent *__restrict __entry, + struct dirent **__restrict __result) + __attribute__ ((__nonnull__ (1, 2, 3))); +# 208 "/usr/include/dirent.h" 3 4 +extern void rewinddir (DIR *__dirp) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern void seekdir (DIR *__dirp, long int __pos) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern long int telldir (DIR *__dirp) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int dirfd (DIR *__dirp) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 244 "/usr/include/dirent.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 245 "/usr/include/dirent.h" 2 3 4 +# 254 "/usr/include/dirent.h" 3 4 +extern int scandir (const char *__restrict __dir, + struct dirent ***__restrict __namelist, + int (*__selector) (const struct dirent *), + int (*__cmp) (const struct dirent **, + const struct dirent **)) + __attribute__ ((__nonnull__ (1, 2))); +# 324 "/usr/include/dirent.h" 3 4 +extern int alphasort (const struct dirent **__e1, + const struct dirent **__e2) + __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2))); +# 352 "/usr/include/dirent.h" 3 4 +extern __ssize_t getdirentries (int __fd, char *__restrict __buf, + size_t __nbytes, + __off_t *__restrict __basep) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))); +# 42 "../include/apr_portable.h" 2 + + +# 1 "/usr/include/fcntl.h" 1 3 4 +# 35 "/usr/include/fcntl.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/fcntl.h" 1 3 4 +# 35 "/usr/include/x86_64-linux-gnu/bits/fcntl.h" 3 4 +struct flock + { + short int l_type; + short int l_whence; + + __off_t l_start; + __off_t l_len; + + + + + __pid_t l_pid; + }; +# 61 "/usr/include/x86_64-linux-gnu/bits/fcntl.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h" 1 3 4 +# 62 "/usr/include/x86_64-linux-gnu/bits/fcntl.h" 2 3 4 +# 36 "/usr/include/fcntl.h" 2 3 4 +# 67 "/usr/include/fcntl.h" 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 68 "/usr/include/fcntl.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/stat.h" 1 3 4 +# 46 "/usr/include/x86_64-linux-gnu/bits/stat.h" 3 4 +struct stat + { + __dev_t st_dev; + + + + + __ino_t st_ino; + + + + + + + + __nlink_t st_nlink; + __mode_t st_mode; + + __uid_t st_uid; + __gid_t st_gid; + + int __pad0; + + __dev_t st_rdev; + + + + + __off_t st_size; + + + + __blksize_t st_blksize; + + __blkcnt_t st_blocks; +# 91 "/usr/include/x86_64-linux-gnu/bits/stat.h" 3 4 + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +# 106 "/usr/include/x86_64-linux-gnu/bits/stat.h" 3 4 + __syscall_slong_t __glibc_reserved[3]; +# 115 "/usr/include/x86_64-linux-gnu/bits/stat.h" 3 4 + }; +# 69 "/usr/include/fcntl.h" 2 3 4 +# 137 "/usr/include/fcntl.h" 3 4 +extern int fcntl (int __fd, int __cmd, ...); +# 146 "/usr/include/fcntl.h" 3 4 +extern int open (const char *__file, int __oflag, ...) __attribute__ ((__nonnull__ (1))); +# 170 "/usr/include/fcntl.h" 3 4 +extern int openat (int __fd, const char *__file, int __oflag, ...) + __attribute__ ((__nonnull__ (2))); +# 192 "/usr/include/fcntl.h" 3 4 +extern int creat (const char *__file, mode_t __mode) __attribute__ ((__nonnull__ (1))); +# 238 "/usr/include/fcntl.h" 3 4 +extern int posix_fadvise (int __fd, off_t __offset, off_t __len, + int __advise) __attribute__ ((__nothrow__ )); +# 260 "/usr/include/fcntl.h" 3 4 +extern int posix_fallocate (int __fd, off_t __offset, off_t __len); +# 45 "../include/apr_portable.h" 2 + + +# 1 "/usr/include/pthread.h" 1 3 4 +# 23 "/usr/include/pthread.h" 3 4 +# 1 "/usr/include/sched.h" 1 3 4 +# 28 "/usr/include/sched.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 29 "/usr/include/sched.h" 2 3 4 + + + +# 1 "/usr/include/time.h" 1 3 4 +# 33 "/usr/include/sched.h" 2 3 4 + + + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sched.h" 1 3 4 +# 72 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 +struct sched_param + { + int __sched_priority; + }; +# 103 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 +struct __sched_param + { + int __sched_priority; + }; +# 118 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 +typedef unsigned long int __cpu_mask; + + + + + + +typedef struct +{ + __cpu_mask __bits[1024 / (8 * sizeof (__cpu_mask))]; +} cpu_set_t; +# 203 "/usr/include/x86_64-linux-gnu/bits/sched.h" 3 4 +extern int __sched_cpucount (size_t __setsize, const cpu_set_t *__setp) + __attribute__ ((__nothrow__ )); +extern cpu_set_t *__sched_cpualloc (size_t __count) __attribute__ ((__nothrow__ )) ; +extern void __sched_cpufree (cpu_set_t *__set) __attribute__ ((__nothrow__ )); +# 42 "/usr/include/sched.h" 2 3 4 + + + + + + + +extern int sched_setparam (__pid_t __pid, const struct sched_param *__param) + __attribute__ ((__nothrow__ )); + + +extern int sched_getparam (__pid_t __pid, struct sched_param *__param) __attribute__ ((__nothrow__ )); + + +extern int sched_setscheduler (__pid_t __pid, int __policy, + const struct sched_param *__param) __attribute__ ((__nothrow__ )); + + +extern int sched_getscheduler (__pid_t __pid) __attribute__ ((__nothrow__ )); + + +extern int sched_yield (void) __attribute__ ((__nothrow__ )); + + +extern int sched_get_priority_max (int __algorithm) __attribute__ ((__nothrow__ )); + + +extern int sched_get_priority_min (int __algorithm) __attribute__ ((__nothrow__ )); + + +extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __attribute__ ((__nothrow__ )); +# 24 "/usr/include/pthread.h" 2 3 4 +# 1 "/usr/include/time.h" 1 3 4 +# 37 "/usr/include/time.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 38 "/usr/include/time.h" 2 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/time.h" 1 3 4 +# 42 "/usr/include/time.h" 2 3 4 +# 133 "/usr/include/time.h" 3 4 +struct tm +{ + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; + + + long int tm_gmtoff; + const char *tm_zone; + + + + +}; +# 161 "/usr/include/time.h" 3 4 +struct itimerspec + { + struct timespec it_interval; + struct timespec it_value; + }; + + +struct sigevent; +# 189 "/usr/include/time.h" 3 4 +extern clock_t clock (void) __attribute__ ((__nothrow__ )); + + +extern time_t time (time_t *__timer) __attribute__ ((__nothrow__ )); + + +extern double difftime (time_t __time1, time_t __time0) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + +extern time_t mktime (struct tm *__tp) __attribute__ ((__nothrow__ )); + + + + + +extern size_t strftime (char *__restrict __s, size_t __maxsize, + const char *__restrict __format, + const struct tm *__restrict __tp) __attribute__ ((__nothrow__ )); +# 223 "/usr/include/time.h" 3 4 +extern size_t strftime_l (char *__restrict __s, size_t __maxsize, + const char *__restrict __format, + const struct tm *__restrict __tp, + __locale_t __loc) __attribute__ ((__nothrow__ )); +# 239 "/usr/include/time.h" 3 4 +extern struct tm *gmtime (const time_t *__timer) __attribute__ ((__nothrow__ )); + + + +extern struct tm *localtime (const time_t *__timer) __attribute__ ((__nothrow__ )); + + + + + +extern struct tm *gmtime_r (const time_t *__restrict __timer, + struct tm *__restrict __tp) __attribute__ ((__nothrow__ )); + + + +extern struct tm *localtime_r (const time_t *__restrict __timer, + struct tm *__restrict __tp) __attribute__ ((__nothrow__ )); + + + + + +extern char *asctime (const struct tm *__tp) __attribute__ ((__nothrow__ )); + + +extern char *ctime (const time_t *__timer) __attribute__ ((__nothrow__ )); + + + + + + + +extern char *asctime_r (const struct tm *__restrict __tp, + char *__restrict __buf) __attribute__ ((__nothrow__ )); + + +extern char *ctime_r (const time_t *__restrict __timer, + char *__restrict __buf) __attribute__ ((__nothrow__ )); + + + + +extern char *__tzname[2]; +extern int __daylight; +extern long int __timezone; + + + + +extern char *tzname[2]; + + + +extern void tzset (void) __attribute__ ((__nothrow__ )); + + + +extern int daylight; +extern long int timezone; + + + + + +extern int stime (const time_t *__when) __attribute__ ((__nothrow__ )); +# 319 "/usr/include/time.h" 3 4 +extern time_t timegm (struct tm *__tp) __attribute__ ((__nothrow__ )); + + +extern time_t timelocal (struct tm *__tp) __attribute__ ((__nothrow__ )); + + +extern int dysize (int __year) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 334 "/usr/include/time.h" 3 4 +extern int nanosleep (const struct timespec *__requested_time, + struct timespec *__remaining); + + + +extern int clock_getres (clockid_t __clock_id, struct timespec *__res) __attribute__ ((__nothrow__ )); + + +extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __attribute__ ((__nothrow__ )); + + +extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp) + __attribute__ ((__nothrow__ )); + + + + + + +extern int clock_nanosleep (clockid_t __clock_id, int __flags, + const struct timespec *__req, + struct timespec *__rem); + + +extern int clock_getcpuclockid (pid_t __pid, clockid_t *__clock_id) __attribute__ ((__nothrow__ )); + + + + +extern int timer_create (clockid_t __clock_id, + struct sigevent *__restrict __evp, + timer_t *__restrict __timerid) __attribute__ ((__nothrow__ )); + + +extern int timer_delete (timer_t __timerid) __attribute__ ((__nothrow__ )); + + +extern int timer_settime (timer_t __timerid, int __flags, + const struct itimerspec *__restrict __value, + struct itimerspec *__restrict __ovalue) __attribute__ ((__nothrow__ )); + + +extern int timer_gettime (timer_t __timerid, struct itimerspec *__value) + __attribute__ ((__nothrow__ )); + + +extern int timer_getoverrun (timer_t __timerid) __attribute__ ((__nothrow__ )); +# 25 "/usr/include/pthread.h" 2 3 4 + + +# 1 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 27 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" 2 3 4 + + + + +typedef long int __jmp_buf[8]; +# 28 "/usr/include/pthread.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 29 "/usr/include/pthread.h" 2 3 4 + + + +enum +{ + PTHREAD_CREATE_JOINABLE, + + PTHREAD_CREATE_DETACHED + +}; + + + +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP + + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL + + + + + +}; + + + + +enum +{ + PTHREAD_MUTEX_STALLED, + PTHREAD_MUTEX_STALLED_NP = PTHREAD_MUTEX_STALLED, + PTHREAD_MUTEX_ROBUST, + PTHREAD_MUTEX_ROBUST_NP = PTHREAD_MUTEX_ROBUST +}; + + + + + +enum +{ + PTHREAD_PRIO_NONE, + PTHREAD_PRIO_INHERIT, + PTHREAD_PRIO_PROTECT +}; +# 125 "/usr/include/pthread.h" 3 4 +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP +}; +# 166 "/usr/include/pthread.h" 3 4 +enum +{ + PTHREAD_INHERIT_SCHED, + + PTHREAD_EXPLICIT_SCHED + +}; + + + +enum +{ + PTHREAD_SCOPE_SYSTEM, + + PTHREAD_SCOPE_PROCESS + +}; + + + +enum +{ + PTHREAD_PROCESS_PRIVATE, + + PTHREAD_PROCESS_SHARED + +}; +# 201 "/usr/include/pthread.h" 3 4 +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); + void *__arg; + int __canceltype; + struct _pthread_cleanup_buffer *__prev; +}; + + +enum +{ + PTHREAD_CANCEL_ENABLE, + + PTHREAD_CANCEL_DISABLE + +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, + + PTHREAD_CANCEL_ASYNCHRONOUS + +}; +# 244 "/usr/include/pthread.h" 3 4 +extern int pthread_create (pthread_t *__restrict __newthread, + const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 3))); + + + + + +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + + + + + + + +extern int pthread_join (pthread_t __th, void **__thread_return); +# 282 "/usr/include/pthread.h" 3 4 +extern int pthread_detach (pthread_t __th) __attribute__ ((__nothrow__ )); + + + +extern pthread_t pthread_self (void) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); + + + + + + + +extern int pthread_attr_init (pthread_attr_t *__attr) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_attr_destroy (pthread_attr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_attr_getdetachstate (const pthread_attr_t *__attr, + int *__detachstate) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_attr_getguardsize (const pthread_attr_t *__attr, + size_t *__guardsize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict __attr, + struct sched_param *__restrict __param) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + const struct sched_param *__restrict + __param) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_attr_getscope (const pthread_attr_t *__restrict __attr, + int *__restrict __scope) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))) __attribute__ ((__deprecated__)); + + + + + +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))) __attribute__ ((__deprecated__)); + + +extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_attr_getstack (const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2, 3))); + + + + +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 440 "/usr/include/pthread.h" 3 4 +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + const struct sched_param *__param) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3))); + + +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); + + +extern int pthread_setschedprio (pthread_t __target_thread, int __prio) + __attribute__ ((__nothrow__ )); +# 505 "/usr/include/pthread.h" 3 4 +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)) __attribute__ ((__nonnull__ (1, 2))); +# 517 "/usr/include/pthread.h" 3 4 +extern int pthread_setcancelstate (int __state, int *__oldstate); + + + +extern int pthread_setcanceltype (int __type, int *__oldtype); + + +extern int pthread_cancel (pthread_t __th); + + + + +extern void pthread_testcancel (void); + + + + +typedef struct +{ + struct + { + __jmp_buf __cancel_jmp_buf; + int __mask_was_saved; + } __cancel_jmp_buf[1]; + void *__pad[4]; +} __pthread_unwind_buf_t __attribute__ ((__aligned__)); +# 551 "/usr/include/pthread.h" 3 4 +struct __pthread_cleanup_frame +{ + void (*__cancel_routine) (void *); + void *__cancel_arg; + int __do_it; + int __cancel_type; +}; +# 691 "/usr/include/pthread.h" 3 4 +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) + ; +# 703 "/usr/include/pthread.h" 3 4 +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) + ; +# 744 "/usr/include/pthread.h" 3 4 +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) + __attribute__ ((__noreturn__)) + + __attribute__ ((__weak__)) + + ; + + + +struct __jmp_buf_tag; +extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__)); + + + + + +extern int pthread_mutex_init (pthread_mutex_t *__mutex, + const pthread_mutexattr_t *__mutexattr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + const struct timespec *__restrict + __abstime) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutex_getprioceiling (const pthread_mutex_t * + __restrict __mutex, + int *__restrict __prioceiling) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict __mutex, + int __prioceiling, + int *__restrict __old_ceiling) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 3))); + + + + +extern int pthread_mutex_consistent (pthread_mutex_t *__mutex) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 817 "/usr/include/pthread.h" 3 4 +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutexattr_getpshared (const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutexattr_gettype (const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutexattr_getprotocol (const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __protocol) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr, + int __protocol) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __prioceiling) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *__attr, + int __prioceiling) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr, + int *__robustness) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + + + + + +extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr, + int __robustness) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 899 "/usr/include/pthread.h" 3 4 +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + const pthread_rwlockattr_t *__restrict + __attr) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + const struct timespec *__restrict + __abstime) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + const struct timespec *__restrict + __abstime) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + + + +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pref) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + + + +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + const pthread_condattr_t *__restrict __cond_attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_cond_destroy (pthread_cond_t *__cond) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_cond_signal (pthread_cond_t *__cond) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_cond_broadcast (pthread_cond_t *__cond) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex) + __attribute__ ((__nonnull__ (1, 2))); +# 1011 "/usr/include/pthread.h" 3 4 +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + const struct timespec *__restrict __abstime) + __attribute__ ((__nonnull__ (1, 2, 3))); + + + + +extern int pthread_condattr_init (pthread_condattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_condattr_getpshared (const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_condattr_getclock (const pthread_condattr_t * + __restrict __attr, + __clockid_t *__restrict __clock_id) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_condattr_setclock (pthread_condattr_t *__attr, + __clockid_t __clock_id) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 1055 "/usr/include/pthread.h" 3 4 +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_spin_lock (pthread_spinlock_t *__lock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + + + + +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); + + + +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); +# 1122 "/usr/include/pthread.h" 3 4 +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + +extern int pthread_key_delete (pthread_key_t __key) __attribute__ ((__nothrow__ )); + + +extern void *pthread_getspecific (pthread_key_t __key) __attribute__ ((__nothrow__ )); + + +extern int pthread_setspecific (pthread_key_t __key, + const void *__pointer) __attribute__ ((__nothrow__ )) ; + + + + +extern int pthread_getcpuclockid (pthread_t __thread_id, + __clockid_t *__clock_id) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); +# 1156 "/usr/include/pthread.h" 3 4 +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __attribute__ ((__nothrow__ )); +# 48 "../include/apr_portable.h" 2 +# 127 "../include/apr_portable.h" +struct apr_os_proc_mutex_t { + + + int crossproc; + + + + pthread_mutex_t *pthread_interproc; + + + + + + pthread_mutex_t *intraproc; + + +}; + +typedef int apr_os_file_t; +typedef DIR apr_os_dir_t; +typedef int apr_os_sock_t; +typedef struct apr_os_proc_mutex_t apr_os_proc_mutex_t; + + + +typedef pthread_t apr_os_thread_t; +typedef pthread_key_t apr_os_threadkey_t; + + +typedef pid_t apr_os_proc_t; +typedef struct timeval apr_os_imp_time_t; +typedef struct tm apr_os_exp_time_t; +# 169 "../include/apr_portable.h" +typedef void * apr_os_dso_handle_t; + +typedef void* apr_os_shm_t; +# 183 "../include/apr_portable.h" +struct apr_os_sock_info_t { + apr_os_sock_t *os_sock; + struct sockaddr *local; + struct sockaddr *remote; + int family; + int type; + int protocol; +}; + +typedef struct apr_os_sock_info_t apr_os_sock_info_t; +# 203 "../include/apr_portable.h" + struct apr_os_global_mutex_t { + apr_pool_t *pool; + apr_proc_mutex_t *proc_mutex; + + apr_thread_mutex_t *thread_mutex; + + }; + typedef struct apr_os_global_mutex_t apr_os_global_mutex_t; + +apr_status_t apr_os_global_mutex_get(apr_os_global_mutex_t *ospmutex, + apr_global_mutex_t *pmutex); +# 224 "../include/apr_portable.h" +apr_status_t apr_os_file_get(apr_os_file_t *thefile, + apr_file_t *file); + + + + + + +apr_status_t apr_os_dir_get(apr_os_dir_t **thedir, + apr_dir_t *dir); + + + + + + +apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, + apr_socket_t *sock); + + + + + + +apr_status_t apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex); + + + + + + +apr_status_t apr_os_exp_time_get(apr_os_exp_time_t **ostime, + apr_time_exp_t *aprtime); + + + + + + +apr_status_t apr_os_imp_time_get(apr_os_imp_time_t **ostime, + apr_time_t *aprtime); + + + + + + +apr_status_t apr_os_shm_get(apr_os_shm_t *osshm, + apr_shm_t *shm); +# 285 "../include/apr_portable.h" +apr_status_t apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd); + + + + + + +apr_status_t apr_os_threadkey_get(apr_os_threadkey_t *thekey, + apr_threadkey_t *key); + + + + + + + +apr_status_t apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, + apr_pool_t *cont); + + + +apr_os_thread_t apr_os_thread_current(void); + + + + + + + +int apr_os_thread_equal(apr_os_thread_t tid1, + apr_os_thread_t tid2); +# 341 "../include/apr_portable.h" +apr_status_t apr_os_file_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_int32_t flags, apr_pool_t *cont); +# 353 "../include/apr_portable.h" +apr_status_t apr_os_pipe_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_pool_t *cont); +# 367 "../include/apr_portable.h" +apr_status_t apr_os_pipe_put_ex(apr_file_t **file, + apr_os_file_t *thefile, + int register_cleanup, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_dir_put(apr_dir_t **dir, + apr_os_dir_t *thedir, + apr_pool_t *cont); +# 390 "../include/apr_portable.h" +apr_status_t apr_os_sock_put(apr_socket_t **sock, + apr_os_sock_t *thesock, + apr_pool_t *cont); +# 404 "../include/apr_portable.h" +apr_status_t apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_imp_time_put(apr_time_t *aprtime, + apr_os_imp_time_t **ostime, + apr_pool_t *cont); + + + + + + + +apr_status_t apr_os_exp_time_put(apr_time_exp_t *aprtime, + apr_os_exp_time_t **ostime, + apr_pool_t *cont); +# 447 "../include/apr_portable.h" +apr_status_t apr_os_shm_put(apr_shm_t **shm, + apr_os_shm_t *osshm, + apr_pool_t *cont); +# 463 "../include/apr_portable.h" +apr_status_t apr_os_dso_handle_put(apr_dso_handle_t **dso, + apr_os_dso_handle_t thedso, + apr_pool_t *pool); + + + + + + +apr_status_t apr_os_dso_handle_get(apr_os_dso_handle_t *dso, + apr_dso_handle_t *aprdso); +# 491 "../include/apr_portable.h" +const char* apr_os_default_encoding(apr_pool_t *pool); +# 500 "../include/apr_portable.h" +const char* apr_os_locale_encoding(apr_pool_t *pool); +# 25 "../include/arch/unix/apr_arch_thread_mutex.h" 2 + + + + + + + +struct apr_thread_mutex_t { + apr_pool_t *pool; + pthread_mutex_t mutex; +}; +# 18 "./../locks/unix/thread_mutex.c" 2 + +# 1 "../include/apr_want.h" 1 +# 20 "./../locks/unix/thread_mutex.c" 2 + + + +static apr_status_t thread_mutex_cleanup(void *data) +{ + apr_thread_mutex_t *mutex = data; + apr_status_t rv; + + rv = pthread_mutex_destroy(&mutex->mutex); + + + + + + return rv; +} + +apr_status_t apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool) +{ + apr_thread_mutex_t *new_mutex; + apr_status_t rv; + + + + + + + + new_mutex = memset(apr_palloc(pool, sizeof(apr_thread_mutex_t)), 0, sizeof(apr_thread_mutex_t)); + new_mutex->pool = pool; + + + if (flags & 0x1) { + pthread_mutexattr_t mattr; + + rv = pthread_mutexattr_init(&mattr); + if (rv) return rv; + + rv = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); + if (rv) { + pthread_mutexattr_destroy(&mattr); + return rv; + } + + rv = pthread_mutex_init(&new_mutex->mutex, &mattr); + + pthread_mutexattr_destroy(&mattr); + } else + + rv = pthread_mutex_init(&new_mutex->mutex, ((void*)0)); + + if (rv) { + + + + return rv; + } + + apr_pool_cleanup_register(new_mutex->pool, + new_mutex, thread_mutex_cleanup, + apr_pool_cleanup_null); + + *mutex = new_mutex; + return 0; +} + +apr_status_t apr_thread_mutex_lock(apr_thread_mutex_t *mutex) +{ + apr_status_t rv; + + rv = pthread_mutex_lock(&mutex->mutex); + + + + + + + return rv; +} + +apr_status_t apr_thread_mutex_trylock(apr_thread_mutex_t *mutex) +{ + apr_status_t rv; + + rv = pthread_mutex_trylock(&mutex->mutex); + if (rv) { + + + + return (rv == 16) ? ((20000 + 50000) + 25) : rv; + } + + return 0; +} + +apr_status_t apr_thread_mutex_unlock(apr_thread_mutex_t *mutex) +{ + apr_status_t status; + + status = pthread_mutex_unlock(&mutex->mutex); + + + + + + + return status; +} + +apr_status_t apr_thread_mutex_destroy(apr_thread_mutex_t *mutex) +{ + return apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup); +} + +apr_pool_t * apr_thread_mutex_pool_get (const apr_thread_mutex_t *thethread_mutex) { return thethread_mutex->pool; } +# 12 "main2.c" 2 +# 1 "./../locks/unix/proc_mutex.c" 1 +# 19 "./../locks/unix/proc_mutex.c" +# 1 "../include/arch/unix/apr_arch_proc_mutex.h" 1 +# 23 "../include/arch/unix/apr_arch_proc_mutex.h" +# 1 "../include/apr_lib.h" 1 +# 32 "../include/apr_lib.h" +# 1 "/usr/include/ctype.h" 1 3 4 +# 46 "/usr/include/ctype.h" 3 4 +enum +{ + _ISupper = ((0) < 8 ? ((1 << (0)) << 8) : ((1 << (0)) >> 8)), + _ISlower = ((1) < 8 ? ((1 << (1)) << 8) : ((1 << (1)) >> 8)), + _ISalpha = ((2) < 8 ? ((1 << (2)) << 8) : ((1 << (2)) >> 8)), + _ISdigit = ((3) < 8 ? ((1 << (3)) << 8) : ((1 << (3)) >> 8)), + _ISxdigit = ((4) < 8 ? ((1 << (4)) << 8) : ((1 << (4)) >> 8)), + _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)), + _ISprint = ((6) < 8 ? ((1 << (6)) << 8) : ((1 << (6)) >> 8)), + _ISgraph = ((7) < 8 ? ((1 << (7)) << 8) : ((1 << (7)) >> 8)), + _ISblank = ((8) < 8 ? ((1 << (8)) << 8) : ((1 << (8)) >> 8)), + _IScntrl = ((9) < 8 ? ((1 << (9)) << 8) : ((1 << (9)) >> 8)), + _ISpunct = ((10) < 8 ? ((1 << (10)) << 8) : ((1 << (10)) >> 8)), + _ISalnum = ((11) < 8 ? ((1 << (11)) << 8) : ((1 << (11)) >> 8)) +}; +# 79 "/usr/include/ctype.h" 3 4 +extern const unsigned short int **__ctype_b_loc (void) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern const __int32_t **__ctype_tolower_loc (void) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +extern const __int32_t **__ctype_toupper_loc (void) + __attribute__ ((__nothrow__ )) __attribute__ ((__const__)); +# 110 "/usr/include/ctype.h" 3 4 +extern int isalnum (int) __attribute__ ((__nothrow__ )); +extern int isalpha (int) __attribute__ ((__nothrow__ )); +extern int iscntrl (int) __attribute__ ((__nothrow__ )); +extern int isdigit (int) __attribute__ ((__nothrow__ )); +extern int islower (int) __attribute__ ((__nothrow__ )); +extern int isgraph (int) __attribute__ ((__nothrow__ )); +extern int isprint (int) __attribute__ ((__nothrow__ )); +extern int ispunct (int) __attribute__ ((__nothrow__ )); +extern int isspace (int) __attribute__ ((__nothrow__ )); +extern int isupper (int) __attribute__ ((__nothrow__ )); +extern int isxdigit (int) __attribute__ ((__nothrow__ )); + + + +extern int tolower (int __c) __attribute__ ((__nothrow__ )); + + +extern int toupper (int __c) __attribute__ ((__nothrow__ )); +# 136 "/usr/include/ctype.h" 3 4 +extern int isblank (int) __attribute__ ((__nothrow__ )); +# 150 "/usr/include/ctype.h" 3 4 +extern int isascii (int __c) __attribute__ ((__nothrow__ )); + + + +extern int toascii (int __c) __attribute__ ((__nothrow__ )); + + + +extern int _toupper (int) __attribute__ ((__nothrow__ )); +extern int _tolower (int) __attribute__ ((__nothrow__ )); +# 271 "/usr/include/ctype.h" 3 4 +extern int isalnum_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isalpha_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int iscntrl_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isdigit_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int islower_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isgraph_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isprint_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int ispunct_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isspace_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isupper_l (int, __locale_t) __attribute__ ((__nothrow__ )); +extern int isxdigit_l (int, __locale_t) __attribute__ ((__nothrow__ )); + +extern int isblank_l (int, __locale_t) __attribute__ ((__nothrow__ )); + + + +extern int __tolower_l (int __c, __locale_t __l) __attribute__ ((__nothrow__ )); +extern int tolower_l (int __c, __locale_t __l) __attribute__ ((__nothrow__ )); + + +extern int __toupper_l (int __c, __locale_t __l) __attribute__ ((__nothrow__ )); +extern int toupper_l (int __c, __locale_t __l) __attribute__ ((__nothrow__ )); +# 33 "../include/apr_lib.h" 2 +# 59 "../include/apr_lib.h" +typedef struct apr_vformatter_buff_t apr_vformatter_buff_t; + + + + +struct apr_vformatter_buff_t { + + char *curpos; + + char *endpos; +}; +# 84 "../include/apr_lib.h" +const char * apr_filepath_name_get(const char *pathname); +# 174 "../include/apr_lib.h" +int apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *b), + apr_vformatter_buff_t *c, const char *fmt, + va_list ap); +# 189 "../include/apr_lib.h" +apr_status_t apr_password_get(const char *prompt, char *pwbuf, + apr_size_t *bufsize); +# 24 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + + + +# 1 "../include/arch/unix/apr_arch_file_io.h" 1 +# 41 "../include/arch/unix/apr_arch_file_io.h" +# 1 "/usr/include/errno.h" 1 3 4 +# 42 "../include/arch/unix/apr_arch_file_io.h" 2 + + + + + +# 1 "/usr/include/strings.h" 1 3 4 +# 48 "../include/arch/unix/apr_arch_file_io.h" 2 + + + + + +# 1 "/usr/include/x86_64-linux-gnu/sys/stat.h" 1 3 4 +# 105 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/stat.h" 1 3 4 +# 106 "/usr/include/x86_64-linux-gnu/sys/stat.h" 2 3 4 +# 209 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int stat (const char *__restrict __file, + struct stat *__restrict __buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); + + + +extern int fstat (int __fd, struct stat *__buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); +# 238 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int fstatat (int __fd, const char *__restrict __file, + struct stat *__restrict __buf, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); +# 263 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int lstat (const char *__restrict __file, + struct stat *__restrict __buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1, 2))); +# 284 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int chmod (const char *__file, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int lchmod (const char *__file, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + +extern int fchmod (int __fd, __mode_t __mode) __attribute__ ((__nothrow__ )); + + + + + +extern int fchmodat (int __fd, const char *__file, __mode_t __mode, + int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))) ; + + + + + + +extern __mode_t umask (__mode_t __mask) __attribute__ ((__nothrow__ )); +# 321 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int mkdir (const char *__path, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int mkdirat (int __fd, const char *__path, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + + + +extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int mknodat (int __fd, const char *__path, __mode_t __mode, + __dev_t __dev) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + + +extern int mkfifo (const char *__path, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (1))); + + + + + +extern int mkfifoat (int __fd, const char *__path, __mode_t __mode) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + + +extern int utimensat (int __fd, const char *__path, + const struct timespec __times[2], + int __flags) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2))); + + + + +extern int futimens (int __fd, const struct timespec __times[2]) __attribute__ ((__nothrow__ )); +# 399 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int __fxstat (int __ver, int __fildes, struct stat *__stat_buf) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3))); +extern int __xstat (int __ver, const char *__filename, + struct stat *__stat_buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); +extern int __lxstat (int __ver, const char *__filename, + struct stat *__stat_buf) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 3))); +extern int __fxstatat (int __ver, int __fildes, const char *__filename, + struct stat *__stat_buf, int __flag) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 4))); +# 442 "/usr/include/x86_64-linux-gnu/sys/stat.h" 3 4 +extern int __xmknod (int __ver, const char *__path, __mode_t __mode, + __dev_t *__dev) __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (2, 4))); + +extern int __xmknodat (int __ver, int __fd, const char *__path, + __mode_t __mode, __dev_t *__dev) + __attribute__ ((__nothrow__ )) __attribute__ ((__nonnull__ (3, 5))); +# 54 "../include/arch/unix/apr_arch_file_io.h" 2 +# 75 "../include/arch/unix/apr_arch_file_io.h" +# 1 "/usr/include/x86_64-linux-gnu/sys/param.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/sys/param.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/sys/param.h" 2 3 4 + + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/param.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/param.h" 3 4 +# 1 "/usr/include/linux/param.h" 1 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/asm/param.h" 1 3 4 +# 1 "/usr/include/asm-generic/param.h" 1 3 4 +# 2 "/usr/include/x86_64-linux-gnu/asm/param.h" 2 3 4 +# 5 "/usr/include/linux/param.h" 2 3 4 +# 29 "/usr/include/x86_64-linux-gnu/bits/param.h" 2 3 4 +# 32 "/usr/include/x86_64-linux-gnu/sys/param.h" 2 3 4 +# 76 "../include/arch/unix/apr_arch_file_io.h" 2 +# 93 "../include/arch/unix/apr_arch_file_io.h" +struct apr_file_t { + apr_pool_t *pool; + int filedes; + char *fname; + apr_int32_t flags; + int eof_hit; + int is_pipe; + apr_interval_time_t timeout; + int buffered; + enum {BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking; + int ungetchar; + + + + + + char *buffer; + apr_size_t bufpos; + apr_size_t bufsize; + unsigned long dataRead; + int direction; + apr_off_t filePtr; + + struct apr_thread_mutex_t *thlock; + +}; +# 142 "../include/arch/unix/apr_arch_file_io.h" +typedef struct stat struct_stat; +# 151 "../include/arch/unix/apr_arch_file_io.h" +struct apr_dir_t { + apr_pool_t *pool; + char *dirname; + DIR *dirstruct; + + + + struct dirent *entry; + +}; + +apr_status_t apr_unix_file_cleanup(void *); +apr_status_t apr_unix_child_file_cleanup(void *); + +mode_t apr_unix_perms2mode(apr_fileperms_t perms); +apr_fileperms_t apr_unix_mode2perms(mode_t mode); + +apr_status_t apr_file_flush_locked(apr_file_t *thefile); +apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted, + apr_file_t *thefile); +# 29 "../include/arch/unix/apr_arch_proc_mutex.h" 2 +# 42 "../include/arch/unix/apr_arch_proc_mutex.h" +# 1 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/ipctypes.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/ipctypes.h" 3 4 +typedef int __ipc_pid_t; +# 29 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 2 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/ipc.h" 1 3 4 +# 42 "/usr/include/x86_64-linux-gnu/bits/ipc.h" 3 4 +struct ipc_perm + { + __key_t __key; + __uid_t uid; + __gid_t gid; + __uid_t cuid; + __gid_t cgid; + unsigned short int mode; + unsigned short int __pad1; + unsigned short int __seq; + unsigned short int __pad2; + __syscall_ulong_t __glibc_reserved1; + __syscall_ulong_t __glibc_reserved2; + }; +# 30 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 2 3 4 +# 54 "/usr/include/x86_64-linux-gnu/sys/ipc.h" 3 4 +extern key_t ftok (const char *__pathname, int __proj_id) __attribute__ ((__nothrow__ )); +# 43 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + +# 1 "/usr/include/x86_64-linux-gnu/sys/sem.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/sys/sem.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/sys/sem.h" 2 3 4 + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sem.h" 1 3 4 +# 38 "/usr/include/x86_64-linux-gnu/bits/sem.h" 3 4 +struct semid_ds +{ + struct ipc_perm sem_perm; + __time_t sem_otime; + __syscall_ulong_t __glibc_reserved1; + __time_t sem_ctime; + __syscall_ulong_t __glibc_reserved2; + __syscall_ulong_t sem_nsems; + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +# 72 "/usr/include/x86_64-linux-gnu/bits/sem.h" 3 4 +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; +# 31 "/usr/include/x86_64-linux-gnu/sys/sem.h" 2 3 4 +# 41 "/usr/include/x86_64-linux-gnu/sys/sem.h" 3 4 +struct sembuf +{ + unsigned short int sem_num; + short int sem_op; + short int sem_flg; +}; + + + + + +extern int semctl (int __semid, int __semnum, int __cmd, ...) __attribute__ ((__nothrow__ )); + + +extern int semget (key_t __key, int __nsems, int __semflg) __attribute__ ((__nothrow__ )); + + +extern int semop (int __semid, struct sembuf *__sops, size_t __nsops) __attribute__ ((__nothrow__ )); +# 46 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + +# 1 "/usr/include/x86_64-linux-gnu/sys/file.h" 1 3 4 +# 50 "/usr/include/x86_64-linux-gnu/sys/file.h" 3 4 +extern int flock (int __fd, int __operation) __attribute__ ((__nothrow__ )); +# 49 "../include/arch/unix/apr_arch_proc_mutex.h" 2 +# 60 "../include/arch/unix/apr_arch_proc_mutex.h" +# 1 "/usr/include/x86_64-linux-gnu/sys/mman.h" 1 3 4 +# 25 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +# 1 "/usr/lib/llvm-3.5/bin/../lib/clang/3.5.0/include/stddef.h" 1 3 4 +# 26 "/usr/include/x86_64-linux-gnu/sys/mman.h" 2 3 4 +# 41 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/mman.h" 1 3 4 +# 45 "/usr/include/x86_64-linux-gnu/bits/mman.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/mman-linux.h" 1 3 4 +# 46 "/usr/include/x86_64-linux-gnu/bits/mman.h" 2 3 4 +# 42 "/usr/include/x86_64-linux-gnu/sys/mman.h" 2 3 4 +# 57 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +extern void *mmap (void *__addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset) __attribute__ ((__nothrow__ )); +# 76 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +extern int munmap (void *__addr, size_t __len) __attribute__ ((__nothrow__ )); + + + + +extern int mprotect (void *__addr, size_t __len, int __prot) __attribute__ ((__nothrow__ )); + + + + + + + +extern int msync (void *__addr, size_t __len, int __flags); + + + + +extern int madvise (void *__addr, size_t __len, int __advice) __attribute__ ((__nothrow__ )); + + + +extern int posix_madvise (void *__addr, size_t __len, int __advice) __attribute__ ((__nothrow__ )); + + + + +extern int mlock (const void *__addr, size_t __len) __attribute__ ((__nothrow__ )); + + +extern int munlock (const void *__addr, size_t __len) __attribute__ ((__nothrow__ )); + + + + +extern int mlockall (int __flags) __attribute__ ((__nothrow__ )); + + + +extern int munlockall (void) __attribute__ ((__nothrow__ )); + + + + + + + +extern int mincore (void *__start, size_t __len, unsigned char *__vec) + __attribute__ ((__nothrow__ )); +# 144 "/usr/include/x86_64-linux-gnu/sys/mman.h" 3 4 +extern int shm_open (const char *__name, int __oflag, mode_t __mode); + + +extern int shm_unlink (const char *__name); +# 61 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + + + + +# 1 "/usr/include/semaphore.h" 1 3 4 +# 29 "/usr/include/semaphore.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/semaphore.h" 1 3 4 +# 23 "/usr/include/x86_64-linux-gnu/bits/semaphore.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 24 "/usr/include/x86_64-linux-gnu/bits/semaphore.h" 2 3 4 +# 36 "/usr/include/x86_64-linux-gnu/bits/semaphore.h" 3 4 +typedef union +{ + char __size[32]; + long int __align; +} sem_t; +# 30 "/usr/include/semaphore.h" 2 3 4 + + + + + + +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) + __attribute__ ((__nothrow__ )); + +extern int sem_destroy (sem_t *__sem) __attribute__ ((__nothrow__ )); + + +extern sem_t *sem_open (const char *__name, int __oflag, ...) __attribute__ ((__nothrow__ )); + + +extern int sem_close (sem_t *__sem) __attribute__ ((__nothrow__ )); + + +extern int sem_unlink (const char *__name) __attribute__ ((__nothrow__ )); + + + + + +extern int sem_wait (sem_t *__sem); + + + + + + +extern int sem_timedwait (sem_t *__restrict __sem, + const struct timespec *__restrict __abstime); + + + +extern int sem_trywait (sem_t *__sem) __attribute__ ((__nothrow__)); + + +extern int sem_post (sem_t *__sem) __attribute__ ((__nothrow__)); + + +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __attribute__ ((__nothrow__ )); +# 67 "../include/arch/unix/apr_arch_proc_mutex.h" 2 + + + +struct apr_proc_mutex_unix_lock_methods_t { + unsigned int flags; + apr_status_t (*create)(apr_proc_mutex_t *, const char *); + apr_status_t (*acquire)(apr_proc_mutex_t *); + apr_status_t (*tryacquire)(apr_proc_mutex_t *); + apr_status_t (*release)(apr_proc_mutex_t *); + apr_status_t (*cleanup)(void *); + apr_status_t (*child_init)(apr_proc_mutex_t **, apr_pool_t *, const char *); + const char *name; +}; +typedef struct apr_proc_mutex_unix_lock_methods_t apr_proc_mutex_unix_lock_methods_t; + + + + + +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; +}; + + +struct apr_proc_mutex_t { + apr_pool_t *pool; + const apr_proc_mutex_unix_lock_methods_t *meth; + const apr_proc_mutex_unix_lock_methods_t *inter_meth; + int curr_locked; + char *fname; + + apr_file_t *interproc; + + + sem_t *psem_interproc; + + + pthread_mutex_t *pthread_interproc; + +}; + +void apr_proc_mutex_unix_setup_lock(void); +# 20 "./../locks/unix/proc_mutex.c" 2 + +# 1 "../include/apr_hash.h" 1 +# 52 "../include/apr_hash.h" +typedef struct apr_hash_t apr_hash_t; + + + + +typedef struct apr_hash_index_t apr_hash_index_t; + + + + + + + +typedef unsigned int (*apr_hashfunc_t)(const char *key, apr_ssize_t *klen); + + + + +unsigned int apr_hashfunc_default(const char *key, + apr_ssize_t *klen); + + + + + + +apr_hash_t * apr_hash_make(apr_pool_t *pool); + + + + + + + +apr_hash_t * apr_hash_make_custom(apr_pool_t *pool, + apr_hashfunc_t hash_func); +# 96 "../include/apr_hash.h" +apr_hash_t * apr_hash_copy(apr_pool_t *pool, + const apr_hash_t *h); +# 107 "../include/apr_hash.h" +void apr_hash_set(apr_hash_t *ht, const void *key, + apr_ssize_t klen, const void *val); +# 117 "../include/apr_hash.h" +void * apr_hash_get(apr_hash_t *ht, const void *key, + apr_ssize_t klen); +# 147 "../include/apr_hash.h" +apr_hash_index_t * apr_hash_first(apr_pool_t *p, apr_hash_t *ht); + + + + + + + +apr_hash_index_t * apr_hash_next(apr_hash_index_t *hi); +# 166 "../include/apr_hash.h" +void apr_hash_this(apr_hash_index_t *hi, const void **key, + apr_ssize_t *klen, void **val); + + + + + + +const void* apr_hash_this_key(apr_hash_index_t *hi); + + + + + + +apr_ssize_t apr_hash_this_key_len(apr_hash_index_t *hi); + + + + + + +void* apr_hash_this_val(apr_hash_index_t *hi); + + + + + + +unsigned int apr_hash_count(apr_hash_t *ht); + + + + + +void apr_hash_clear(apr_hash_t *ht); +# 212 "../include/apr_hash.h" +apr_hash_t * apr_hash_overlay(apr_pool_t *p, + const apr_hash_t *overlay, + const apr_hash_t *base); +# 230 "../include/apr_hash.h" +apr_hash_t * apr_hash_merge(apr_pool_t *p, + const apr_hash_t *h1, + const apr_hash_t *h2, + void * (*merger)(apr_pool_t *p, + const void *key, + apr_ssize_t klen, + const void *h1_val, + const void *h2_val, + const void *data), + const void *data); +# 252 "../include/apr_hash.h" +typedef int (apr_hash_do_callback_fn_t)(void *rec, const void *key, + apr_ssize_t klen, + const void *value); +# 268 "../include/apr_hash.h" +int apr_hash_do(apr_hash_do_callback_fn_t *comp, + void *rec, const apr_hash_t *ht); + + + + +apr_pool_t * apr_hash_pool_get (const apr_hash_t *thehash); +# 22 "./../locks/unix/proc_mutex.c" 2 + +apr_status_t apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) +{ + return apr_pool_cleanup_run(mutex->pool, mutex, apr_proc_mutex_cleanup); +} + + + +static apr_status_t proc_mutex_no_child_init(apr_proc_mutex_t **mutex, + apr_pool_t *cont, + const char *fname) +{ + return 0; +} +# 44 "./../locks/unix/proc_mutex.c" +static apr_status_t proc_mutex_posix_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex = mutex_; + + if (sem_close(mutex->psem_interproc) < 0) { + return (*__errno_location ()); + } + + return 0; +} + +static unsigned int rshash (char *p) { + + unsigned int b = 378551; + unsigned int a = 63689; + unsigned int retval = 0; + + for( ; *p; p++) + { + retval = retval * a + (*p); + a *= b; + } + + return retval; +} + +static apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + + sem_t *psem; + char semname[32]; + + new_mutex->interproc = apr_palloc(new_mutex->pool, + sizeof(*new_mutex->interproc)); +# 101 "./../locks/unix/proc_mutex.c" + if (fname) { + apr_ssize_t flen = strlen(fname); + char *p = apr_pstrndup(new_mutex->pool, fname, strlen(fname)); + unsigned int h1, h2; + h1 = (apr_hashfunc_default((const char *)p, &flen) & 0xffffffff); + h2 = (rshash(p) & 0xffffffff); + apr_snprintf(semname, sizeof(semname), "/ApR.%xH%x", h1, h2); + } else { + apr_time_t now; + unsigned long sec; + unsigned long usec; + now = apr_time_now(); + sec = ((now) / 1000000L); + usec = ((now) % 1000000L); + apr_snprintf(semname, sizeof(semname), "/ApR.%lxZ%lx", sec, usec); + } + psem = sem_open(semname, 0100 | 0200, 0644, 1); + if (psem == (sem_t *)((sem_t *) 0)) { + if ((*__errno_location ()) == 36) { + + semname[13] = '\0'; + } else { + return (*__errno_location ()); + } + psem = sem_open(semname, 0100 | 0200, 0644, 1); + } + + if (psem == (sem_t *)((sem_t *) 0)) { + return (*__errno_location ()); + } + + sem_unlink(semname); + new_mutex->psem_interproc = psem; + new_mutex->fname = apr_pstrdup(new_mutex->pool, semname); + apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_posix_acquire(apr_proc_mutex_t *mutex) +{ + if (sem_wait(mutex->psem_interproc) < 0) { + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_posix_tryacquire(apr_proc_mutex_t *mutex) +{ + if (sem_trywait(mutex->psem_interproc) < 0) { + if ((*__errno_location ()) == 11) { + return ((20000 + 50000) + 25); + } + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_posix_release(apr_proc_mutex_t *mutex) +{ + mutex->curr_locked = 0; + if (sem_post(mutex->psem_interproc) < 0) { + + + return (*__errno_location ()); + } + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_posixsem_methods = +{ + + + + 0, + + proc_mutex_posix_create, + proc_mutex_posix_acquire, + proc_mutex_posix_tryacquire, + proc_mutex_posix_release, + proc_mutex_posix_cleanup, + proc_mutex_no_child_init, + "posixsem" +}; + + + + + +static struct sembuf proc_mutex_op_on; +static struct sembuf proc_mutex_op_try; +static struct sembuf proc_mutex_op_off; + +static void proc_mutex_sysv_setup(void) +{ + proc_mutex_op_on.sem_num = 0; + proc_mutex_op_on.sem_op = -1; + proc_mutex_op_on.sem_flg = 0x1000; + proc_mutex_op_try.sem_num = 0; + proc_mutex_op_try.sem_op = -1; + proc_mutex_op_try.sem_flg = 0x1000 | 04000; + proc_mutex_op_off.sem_num = 0; + proc_mutex_op_off.sem_op = 1; + proc_mutex_op_off.sem_flg = 0x1000; +} + +static apr_status_t proc_mutex_sysv_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex=mutex_; + union semun ick; + + if (mutex->interproc->filedes != -1) { + ick.val = 0; + semctl(mutex->interproc->filedes, 0, 0, ick); + } + return 0; +} + +static apr_status_t proc_mutex_sysv_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + union semun ick; + apr_status_t rv; + + new_mutex->interproc = apr_palloc(new_mutex->pool, sizeof(*new_mutex->interproc)); + new_mutex->interproc->filedes = semget(((__key_t) 0), 1, 01000 | 0600); + + if (new_mutex->interproc->filedes < 0) { + rv = (*__errno_location ()); + proc_mutex_sysv_cleanup(new_mutex); + return rv; + } + ick.val = 1; + if (semctl(new_mutex->interproc->filedes, 0, 16, ick) < 0) { + rv = (*__errno_location ()); + proc_mutex_sysv_cleanup(new_mutex); + return rv; + } + new_mutex->curr_locked = 0; + apr_pool_cleanup_register(new_mutex->pool, + (void *)new_mutex, apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_sysv_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = semop(mutex->interproc->filedes, &proc_mutex_op_on, 1); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_sysv_tryacquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = semop(mutex->interproc->filedes, &proc_mutex_op_try, 1); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + if ((*__errno_location ()) == 11) { + return ((20000 + 50000) + 25); + } + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_sysv_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked = 0; + do { + rc = semop(mutex->interproc->filedes, &proc_mutex_op_off, 1); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_sysv_methods = +{ + + + + 0, + + proc_mutex_sysv_create, + proc_mutex_sysv_acquire, + proc_mutex_sysv_tryacquire, + proc_mutex_sysv_release, + proc_mutex_sysv_cleanup, + proc_mutex_no_child_init, + "sysvsem" +}; + + + + + +static apr_status_t proc_mutex_proc_pthread_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex=mutex_; + apr_status_t rv; + + if (mutex->curr_locked == 1) { + if ((rv = pthread_mutex_unlock(mutex->pthread_interproc))) { + + + + return rv; + } + } + + if (mutex->curr_locked != -1) { + if ((rv = pthread_mutex_destroy(mutex->pthread_interproc))) { + + + + return rv; + } + } + if (munmap((caddr_t)mutex->pthread_interproc, sizeof(pthread_mutex_t))) { + return (*__errno_location ()); + } + return 0; +} + +static apr_status_t proc_mutex_proc_pthread_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + apr_status_t rv; + int fd; + pthread_mutexattr_t mattr; + + fd = open("/dev/zero", 02); + if (fd < 0) { + return (*__errno_location ()); + } + + new_mutex->pthread_interproc = (pthread_mutex_t *)mmap( + (caddr_t) 0, + sizeof(pthread_mutex_t), + 0x1 | 0x2, 0x01, + fd, 0); + if (new_mutex->pthread_interproc == (pthread_mutex_t *) (caddr_t) -1) { + close(fd); + return (*__errno_location ()); + } + close(fd); + + new_mutex->curr_locked = -1; + + if ((rv = pthread_mutexattr_init(&mattr))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + return rv; + } + if ((rv = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + + + if ((rv = pthread_mutexattr_setrobust_np(&mattr, + PTHREAD_MUTEX_ROBUST_NP))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + if ((rv = pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + + + if ((rv = pthread_mutex_init(new_mutex->pthread_interproc, &mattr))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + + new_mutex->curr_locked = 0; + + if ((rv = pthread_mutexattr_destroy(&mattr))) { + + + + proc_mutex_proc_pthread_cleanup(new_mutex); + return rv; + } + + apr_pool_cleanup_register(new_mutex->pool, + (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_proc_pthread_acquire(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + if ((rv = pthread_mutex_lock(mutex->pthread_interproc))) { + + + + + + if (rv == 130) { + pthread_mutex_consistent_np(mutex->pthread_interproc); + } + else + return rv; + + + + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_proc_pthread_tryacquire(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + if ((rv = pthread_mutex_trylock(mutex->pthread_interproc))) { + + + + if (rv == 16) { + return ((20000 + 50000) + 25); + } + + + if (rv == 130) { + pthread_mutex_consistent_np(mutex->pthread_interproc); + rv = 0; + } + else + return rv; + + + + } + mutex->curr_locked = 1; + return rv; +} + +static apr_status_t proc_mutex_proc_pthread_release(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + mutex->curr_locked = 0; + if ((rv = pthread_mutex_unlock(mutex->pthread_interproc))) { + + + + return rv; + } + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_methods = +{ + 1, + proc_mutex_proc_pthread_create, + proc_mutex_proc_pthread_acquire, + proc_mutex_proc_pthread_tryacquire, + proc_mutex_proc_pthread_release, + proc_mutex_proc_pthread_cleanup, + proc_mutex_no_child_init, + "pthread" +}; + + + + + +static struct flock proc_mutex_lock_it; +static struct flock proc_mutex_unlock_it; + +static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *); + +static void proc_mutex_fcntl_setup(void) +{ + proc_mutex_lock_it.l_whence = 0; + proc_mutex_lock_it.l_start = 0; + proc_mutex_lock_it.l_len = 0; + proc_mutex_lock_it.l_type = 1; + proc_mutex_lock_it.l_pid = 0; + proc_mutex_unlock_it.l_whence = 0; + proc_mutex_unlock_it.l_start = 0; + proc_mutex_unlock_it.l_len = 0; + proc_mutex_unlock_it.l_type = 2; + proc_mutex_unlock_it.l_pid = 0; +} + +static apr_status_t proc_mutex_fcntl_cleanup(void *mutex_) +{ + apr_status_t status; + apr_proc_mutex_t *mutex=mutex_; + + if (mutex->curr_locked == 1) { + status = proc_mutex_fcntl_release(mutex); + if (status != 0) + return status; + } + + return apr_file_close(mutex->interproc); +} + +static apr_status_t proc_mutex_fcntl_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + int rv; + + if (fname) { + new_mutex->fname = apr_pstrdup(new_mutex->pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + 0x00004 | 0x00002 | 0x00040, + 0x0400 | 0x0200 | 0x0040 | 0x0004, + new_mutex->pool); + } + else { + new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX"); + rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname, + 0x00004 | 0x00002 | 0x00040, + new_mutex->pool); + } + + if (rv != 0) { + return rv; + } + + new_mutex->curr_locked = 0; + unlink(new_mutex->fname); + apr_pool_cleanup_register(new_mutex->pool, + (void*)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_fcntl_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = fcntl(mutex->interproc->filedes, 7, &proc_mutex_lock_it); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + mutex->curr_locked=1; + return 0; +} + +static apr_status_t proc_mutex_fcntl_tryacquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = fcntl(mutex->interproc->filedes, 6, &proc_mutex_lock_it); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + + + + if ((*__errno_location ()) == 11) { + + return ((20000 + 50000) + 25); + } + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked=0; + do { + rc = fcntl(mutex->interproc->filedes, 7, &proc_mutex_unlock_it); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_fcntl_methods = +{ + + + + 0, + + proc_mutex_fcntl_create, + proc_mutex_fcntl_acquire, + proc_mutex_fcntl_tryacquire, + proc_mutex_fcntl_release, + proc_mutex_fcntl_cleanup, + proc_mutex_no_child_init, + "fcntl" +}; + + + + + +static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *); + +static apr_status_t proc_mutex_flock_cleanup(void *mutex_) +{ + apr_status_t status; + apr_proc_mutex_t *mutex=mutex_; + + if (mutex->curr_locked == 1) { + status = proc_mutex_flock_release(mutex); + if (status != 0) + return status; + } + if (mutex->interproc) { + apr_file_close(mutex->interproc); + } + unlink(mutex->fname); + return 0; +} + +static apr_status_t proc_mutex_flock_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + int rv; + + if (fname) { + new_mutex->fname = apr_pstrdup(new_mutex->pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + 0x00004 | 0x00002 | 0x00040, + 0x0400 | 0x0200, + new_mutex->pool); + } + else { + new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX"); + rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname, + 0x00004 | 0x00002 | 0x00040, + new_mutex->pool); + } + + if (rv != 0) { + proc_mutex_flock_cleanup(new_mutex); + return (*__errno_location ()); + } + new_mutex->curr_locked = 0; + apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return 0; +} + +static apr_status_t proc_mutex_flock_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = flock(mutex->interproc->filedes, 2); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_flock_tryacquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = flock(mutex->interproc->filedes, 2 | 4); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + if ((*__errno_location ()) == 11 || (*__errno_location ()) == 11) { + return ((20000 + 50000) + 25); + } + return (*__errno_location ()); + } + mutex->curr_locked = 1; + return 0; +} + +static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked = 0; + do { + rc = flock(mutex->interproc->filedes, 8); + } while (rc < 0 && (*__errno_location ()) == 4); + if (rc < 0) { + return (*__errno_location ()); + } + return 0; +} + +static apr_status_t proc_mutex_flock_child_init(apr_proc_mutex_t **mutex, + apr_pool_t *pool, + const char *fname) +{ + apr_proc_mutex_t *new_mutex; + int rv; + + new_mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t)); + + memcpy(new_mutex, *mutex, sizeof *new_mutex); + new_mutex->pool = pool; + if (!fname) { + fname = (*mutex)->fname; + } + new_mutex->fname = apr_pstrdup(pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + 0x00002, 0, new_mutex->pool); + if (rv != 0) { + return rv; + } + *mutex = new_mutex; + return 0; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_flock_methods = +{ + + + + 0, + + proc_mutex_flock_create, + proc_mutex_flock_acquire, + proc_mutex_flock_tryacquire, + proc_mutex_flock_release, + proc_mutex_flock_cleanup, + proc_mutex_flock_child_init, + "flock" +}; + + + +void apr_proc_mutex_unix_setup_lock(void) +{ + + + proc_mutex_sysv_setup(); + + + proc_mutex_fcntl_setup(); + +} + +static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech) +{ + switch (mech) { + case APR_LOCK_FCNTL: + + new_mutex->inter_meth = &mutex_fcntl_methods; + + + + break; + case APR_LOCK_FLOCK: + + new_mutex->inter_meth = &mutex_flock_methods; + + + + break; + case APR_LOCK_SYSVSEM: + + new_mutex->inter_meth = &mutex_sysv_methods; + + + + break; + case APR_LOCK_POSIXSEM: + + new_mutex->inter_meth = &mutex_posixsem_methods; + + + + break; + case APR_LOCK_PROC_PTHREAD: + + new_mutex->inter_meth = &mutex_proc_pthread_methods; + + + + break; + case APR_LOCK_DEFAULT: + + + + new_mutex->inter_meth = &mutex_sysv_methods; +# 842 "./../locks/unix/proc_mutex.c" + break; + default: + return ((20000 + 50000) + 23); + } + return 0; +} + +const char * apr_proc_mutex_defname(void) +{ + apr_status_t rv; + apr_proc_mutex_t mutex; + + if ((rv = proc_mutex_choose_method(&mutex, APR_LOCK_DEFAULT)) != 0) { + return "unknown"; + } + mutex.meth = mutex.inter_meth; + + return apr_proc_mutex_name(&mutex); +} + +static apr_status_t proc_mutex_create(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech, const char *fname) +{ + apr_status_t rv; + + if ((rv = proc_mutex_choose_method(new_mutex, mech)) != 0) { + return rv; + } + + new_mutex->meth = new_mutex->inter_meth; + + if ((rv = new_mutex->meth->create(new_mutex, fname)) != 0) { + return rv; + } + + return 0; +} + +apr_status_t apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool) +{ + apr_proc_mutex_t *new_mutex; + apr_status_t rv; + + new_mutex = memset(apr_palloc(pool, sizeof(apr_proc_mutex_t)), 0, sizeof(apr_proc_mutex_t)); + new_mutex->pool = pool; + + if ((rv = proc_mutex_create(new_mutex, mech, fname)) != 0) + return rv; + + *mutex = new_mutex; + return 0; +} + +apr_status_t apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool) +{ + return (*mutex)->meth->child_init(mutex, pool, fname); +} + +apr_status_t apr_proc_mutex_lock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->acquire(mutex); +} + +apr_status_t apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->tryacquire(mutex); +} + +apr_status_t apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->release(mutex); +} + +apr_status_t apr_proc_mutex_cleanup(void *mutex) +{ + return ((apr_proc_mutex_t *)mutex)->meth->cleanup(mutex); +} + +const char * apr_proc_mutex_name(apr_proc_mutex_t *mutex) +{ + return mutex->meth->name; +} + +const char * apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) +{ + + + + if (mutex->meth == &mutex_flock_methods) { + return mutex->fname; + } + + + if (mutex->meth == &mutex_fcntl_methods) { + return mutex->fname; + } + + return ((void*)0); +} + +apr_pool_t * apr_proc_mutex_pool_get (const apr_proc_mutex_t *theproc_mutex) { return theproc_mutex->pool; } + + + +apr_status_t apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex) +{ + + if (pmutex->interproc) { + ospmutex->crossproc = pmutex->interproc->filedes; + } + else { + ospmutex->crossproc = -1; + } + + + ospmutex->pthread_interproc = pmutex->pthread_interproc; + + return 0; +} + +apr_status_t apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *pool) +{ + if (pool == ((void*)0)) { + return (20000 + 2); + } + if ((*pmutex) == ((void*)0)) { + (*pmutex) = (apr_proc_mutex_t *)memset(apr_palloc(pool, sizeof(apr_proc_mutex_t)), 0, sizeof(apr_proc_mutex_t)); + + (*pmutex)->pool = pool; + } + + apr_os_file_put(&(*pmutex)->interproc, &ospmutex->crossproc, 0, pool); + + + (*pmutex)->pthread_interproc = ospmutex->pthread_interproc; + + return 0; +} +# 13 "main2.c" 2 +# 1 "./../memory/unix/apr_pools.c" 1 +# 31 "./../memory/unix/apr_pools.c" +# 1 "../include/apr_want.h" 1 +# 32 "./../memory/unix/apr_pools.c" 2 +# 1 "../include/apr_env.h" 1 +# 42 "../include/apr_env.h" +apr_status_t apr_env_get(char **value, const char *envvar, + apr_pool_t *pool); + + + + + + + +apr_status_t apr_env_set(const char *envvar, const char *value, + apr_pool_t *pool); + + + + + + +apr_status_t apr_env_delete(const char *envvar, apr_pool_t *pool); +# 33 "./../memory/unix/apr_pools.c" 2 +# 85 "./../memory/unix/apr_pools.c" +struct apr_allocator_t { + + apr_uint32_t max_index; + + + + + + apr_uint32_t max_free_index; + + + + + apr_uint32_t current_free_index; + + apr_thread_mutex_t *mutex; + + apr_pool_t *owner; +# 113 "./../memory/unix/apr_pools.c" + apr_memnode_t *free[20]; +}; +# 123 "./../memory/unix/apr_pools.c" +apr_status_t apr_allocator_create(apr_allocator_t **allocator) +{ + apr_allocator_t *new_allocator; + + *allocator = ((void*)0); + + if ((new_allocator = malloc((((sizeof(apr_allocator_t)) + ((8) - 1)) & ~((8) - 1)))) == ((void*)0)) + return 12; + + memset(new_allocator, 0, (((sizeof(apr_allocator_t)) + ((8) - 1)) & ~((8) - 1))); + new_allocator->max_free_index = 0; + + *allocator = new_allocator; + + return 0; +} + +void apr_allocator_destroy(apr_allocator_t *allocator) +{ + apr_uint32_t index; + apr_memnode_t *node, **ref; + + for (index = 0; index < 20; index++) { + ref = &allocator->free[index]; + while ((node = *ref) != ((void*)0)) { + *ref = node->next; + + + + free(node); + + } + } + + free(allocator); +} + + +void apr_allocator_mutex_set(apr_allocator_t *allocator, + apr_thread_mutex_t *mutex) +{ + allocator->mutex = mutex; +} + +apr_thread_mutex_t * apr_allocator_mutex_get( + apr_allocator_t *allocator) +{ + return allocator->mutex; +} + + +void apr_allocator_owner_set(apr_allocator_t *allocator, + apr_pool_t *pool) +{ + allocator->owner = pool; +} + +apr_pool_t * apr_allocator_owner_get(apr_allocator_t *allocator) +{ + return allocator->owner; +} + +void apr_allocator_max_free_set(apr_allocator_t *allocator, + apr_size_t in_size) +{ + apr_uint32_t max_free_index; + apr_uint32_t size = (apr_uint32_t)in_size; + + + apr_thread_mutex_t *mutex; + + mutex = apr_allocator_mutex_get(allocator); + if (mutex != ((void*)0)) + apr_thread_mutex_lock(mutex); + + + max_free_index = (((size) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)) >> 12; + allocator->current_free_index += max_free_index; + allocator->current_free_index -= allocator->max_free_index; + allocator->max_free_index = max_free_index; + if (allocator->current_free_index > max_free_index) + allocator->current_free_index = max_free_index; + + + if (mutex != ((void*)0)) + apr_thread_mutex_unlock(mutex); + +} + +static __inline__ +apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t in_size) +{ + apr_memnode_t *node, **ref; + apr_uint32_t max_index; + apr_size_t size, i, index; + + + + + size = (((in_size + (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1))) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)); + if (size < in_size) { + return ((void*)0); + } + if (size < (2 * (1 << 12))) + size = (2 * (1 << 12)); + + + + + index = (size >> 12) - 1; + + if (index > (4294967295U)) { + return ((void*)0); + } + + + + + if (index <= allocator->max_index) { + + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); +# 257 "./../memory/unix/apr_pools.c" + max_index = allocator->max_index; + ref = &allocator->free[index]; + i = index; + while (*ref == ((void*)0) && i < max_index) { + ref++; + i++; + } + + if ((node = *ref) != ((void*)0)) { + + + + + + if ((*ref = node->next) == ((void*)0) && i >= max_index) { + do { + ref--; + max_index--; + } + while (*ref == ((void*)0) && max_index > 0); + + allocator->max_index = max_index; + } + + allocator->current_free_index += node->index + 1; + if (allocator->current_free_index > allocator->max_free_index) + allocator->current_free_index = allocator->max_free_index; + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + + node->next = ((void*)0); + node->first_avail = (char *)node + (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)); + + return node; + } + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + } + + + + + else if (allocator->free[0]) { + + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); + + + + + + ref = &allocator->free[0]; + while ((node = *ref) != ((void*)0) && index > node->index) + ref = &node->next; + + if (node) { + *ref = node->next; + + allocator->current_free_index += node->index + 1; + if (allocator->current_free_index > allocator->max_free_index) + allocator->current_free_index = allocator->max_free_index; + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + + node->next = ((void*)0); + node->first_avail = (char *)node + (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)); + + return node; + } + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + } +# 349 "./../memory/unix/apr_pools.c" + if ((node = malloc(size)) == ((void*)0)) + + return ((void*)0); + + node->next = ((void*)0); + node->index = (apr_uint32_t)index; + node->first_avail = (char *)node + (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)); + node->endp = (char *)node + size; + + return node; +} + +static __inline__ +void allocator_free(apr_allocator_t *allocator, apr_memnode_t *node) +{ + apr_memnode_t *next, *freelist = ((void*)0); + apr_uint32_t index, max_index; + apr_uint32_t max_free_index, current_free_index; + + + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); + + + max_index = allocator->max_index; + max_free_index = allocator->max_free_index; + current_free_index = allocator->current_free_index; + + + + + do { + next = node->next; + index = node->index; + + if (max_free_index != 0 + && index + 1 > current_free_index) { + node->next = freelist; + freelist = node; + } + else if (index < 20) { + + + + if ((node->next = allocator->free[index]) == ((void*)0) + && index > max_index) { + max_index = index; + } + allocator->free[index] = node; + if (current_free_index >= index + 1) + current_free_index -= index + 1; + else + current_free_index = 0; + } + else { + + + + node->next = allocator->free[0]; + allocator->free[0] = node; + if (current_free_index >= index + 1) + current_free_index -= index + 1; + else + current_free_index = 0; + } + } while ((node = next) != ((void*)0)); + + allocator->max_index = max_index; + allocator->current_free_index = current_free_index; + + + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); + + + while (freelist != ((void*)0)) { + node = freelist; + freelist = node->next; + + + + free(node); + + } +} + +apr_memnode_t * apr_allocator_alloc(apr_allocator_t *allocator, + apr_size_t size) +{ + return allocator_alloc(allocator, size); +} + +void apr_allocator_free(apr_allocator_t *allocator, + apr_memnode_t *node) +{ + allocator_free(allocator, node); +} +# 467 "./../memory/unix/apr_pools.c" +typedef struct cleanup_t cleanup_t; + + +struct process_chain { + + apr_proc_t *proc; + apr_kill_conditions_e kill_how; + + struct process_chain *next; +}; +# 500 "./../memory/unix/apr_pools.c" +struct apr_pool_t { + apr_pool_t *parent; + apr_pool_t *child; + apr_pool_t *sibling; + apr_pool_t **ref; + cleanup_t *cleanups; + cleanup_t *free_cleanups; + apr_allocator_t *allocator; + struct process_chain *subprocesses; + apr_abortfunc_t abort_fn; + apr_hash_t *user_data; + const char *tag; + + + apr_memnode_t *active; + apr_memnode_t *self; + char *self_first_avail; +# 535 "./../memory/unix/apr_pools.c" + cleanup_t *pre_cleanups; +}; +# 545 "./../memory/unix/apr_pools.c" +static apr_byte_t apr_pools_initialized = 0; +static apr_pool_t *global_pool = ((void*)0); + + +static apr_allocator_t *global_allocator = ((void*)0); +# 560 "./../memory/unix/apr_pools.c" +static void run_cleanups(cleanup_t **c); +static void free_proc_chain(struct process_chain *procs); +# 572 "./../memory/unix/apr_pools.c" +apr_status_t apr_pool_initialize(void) +{ + apr_status_t rv; + + if (apr_pools_initialized++) + return 0; +# 587 "./../memory/unix/apr_pools.c" + if ((rv = apr_allocator_create(&global_allocator)) != 0) { + apr_pools_initialized = 0; + return rv; + } + + if ((rv = apr_pool_create_ex(&global_pool, ((void*)0), ((void*)0), + global_allocator)) != 0) { + apr_allocator_destroy(global_allocator); + global_allocator = ((void*)0); + apr_pools_initialized = 0; + return rv; + } + + apr_pool_tag(global_pool, "apr_global_pool"); + + + + + + + + if ((rv = apr_atomic_init(global_pool)) != 0) { + return rv; + } + + + { + apr_thread_mutex_t *mutex; + + if ((rv = apr_thread_mutex_create(&mutex, + 0x0, + global_pool)) != 0) { + return rv; + } + + apr_allocator_mutex_set(global_allocator, mutex); + } + + + apr_allocator_owner_set(global_allocator, global_pool); + + return 0; +} + +void apr_pool_terminate(void) +{ + if (!apr_pools_initialized) + return; + + if (--apr_pools_initialized) + return; + + apr_pool_destroy(global_pool); + global_pool = ((void*)0); + + global_allocator = ((void*)0); +} +# 668 "./../memory/unix/apr_pools.c" +void * apr_palloc(apr_pool_t *pool, apr_size_t in_size) +{ + apr_memnode_t *active, *node; + void *mem; + apr_size_t size, free_index; + + size = (((in_size) + ((8) - 1)) & ~((8) - 1)); + if (size < in_size) { + if (pool->abort_fn) + pool->abort_fn(12); + + return ((void*)0); + } + active = pool->active; + + + if (size <= ((apr_size_t)(active->endp - active->first_avail))) { + mem = active->first_avail; + active->first_avail += size; + + return mem; + } + + node = active->next; + if (size <= ((apr_size_t)(node->endp - node->first_avail))) { + do { *node->ref = node->next; node->next->ref = node->ref; } while (0); + } + else { + if ((node = allocator_alloc(pool->allocator, size)) == ((void*)0)) { + if (pool->abort_fn) + pool->abort_fn(12); + + return ((void*)0); + } + } + + node->free_index = 0; + + mem = node->first_avail; + node->first_avail += size; + + do { node->ref = active->ref; *node->ref = node; node->next = active; active->ref = &node->next; } while (0); + + pool->active = node; + + free_index = ((((active->endp - active->first_avail + 1) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)) - (1 << 12)) >> 12; + + + active->free_index = (apr_uint32_t)free_index; + node = active->next; + if (free_index >= node->free_index) + return mem; + + do { + node = node->next; + } + while (free_index < node->free_index); + + do { *active->ref = active->next; active->next->ref = active->ref; } while (0); + do { active->ref = node->ref; *active->ref = active; active->next = node; node->ref = &active->next; } while (0); + + return mem; +} +# 740 "./../memory/unix/apr_pools.c" +void * apr_pcalloc(apr_pool_t *pool, apr_size_t size); +void * apr_pcalloc(apr_pool_t *pool, apr_size_t size) +{ + void *mem; + + if ((mem = apr_palloc(pool, size)) != ((void*)0)) { + memset(mem, 0, size); + } + + return mem; +} + + + + + + +void apr_pool_clear(apr_pool_t *pool) +{ + apr_memnode_t *active; + + + run_cleanups(&pool->pre_cleanups); + pool->pre_cleanups = ((void*)0); + + + + + while (pool->child) + apr_pool_destroy(pool->child); + + + run_cleanups(&pool->cleanups); + pool->cleanups = ((void*)0); + pool->free_cleanups = ((void*)0); + + + free_proc_chain(pool->subprocesses); + pool->subprocesses = ((void*)0); + + + pool->user_data = ((void*)0); + + + + + active = pool->active = pool->self; + active->first_avail = pool->self_first_avail; + + if (active->next == active) + return; + + *active->ref = ((void*)0); + allocator_free(pool->allocator, active->next); + active->next = active; + active->ref = &active->next; +} + +void apr_pool_destroy(apr_pool_t *pool) +{ + apr_memnode_t *active; + apr_allocator_t *allocator; + + + run_cleanups(&pool->pre_cleanups); + pool->pre_cleanups = ((void*)0); + + + + + while (pool->child) + apr_pool_destroy(pool->child); + + + run_cleanups(&pool->cleanups); + + + free_proc_chain(pool->subprocesses); + + + if (pool->parent) { + + apr_thread_mutex_t *mutex; + + if ((mutex = apr_allocator_mutex_get(pool->parent->allocator)) != ((void*)0)) + apr_thread_mutex_lock(mutex); + + + if ((*pool->ref = pool->sibling) != ((void*)0)) + pool->sibling->ref = pool->ref; + + + if (mutex) + apr_thread_mutex_unlock(mutex); + + } + + + + + allocator = pool->allocator; + active = pool->self; + *active->ref = ((void*)0); + + + if (apr_allocator_owner_get(allocator) == pool) { + + + + apr_allocator_mutex_set(allocator, ((void*)0)); + } + + + + + + allocator_free(allocator, active); + + + + + + + if (apr_allocator_owner_get(allocator) == pool) { + apr_allocator_destroy(allocator); + } +} + +apr_status_t apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) +{ + apr_pool_t *pool; + apr_memnode_t *node; + + *newpool = ((void*)0); + + if (!parent) + parent = global_pool; + + + + + + if (!abort_fn && parent) + abort_fn = parent->abort_fn; + + if (allocator == ((void*)0)) + allocator = parent->allocator; + + if ((node = allocator_alloc(allocator, + (2 * (1 << 12)) - (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)))) == ((void*)0)) { + if (abort_fn) + abort_fn(12); + + return 12; + } + + node->next = node; + node->ref = &node->next; + + pool = (apr_pool_t *)node->first_avail; + node->first_avail = pool->self_first_avail = (char *)pool + (((sizeof(apr_pool_t)) + ((8) - 1)) & ~((8) - 1)); + + pool->allocator = allocator; + pool->active = pool->self = node; + pool->abort_fn = abort_fn; + pool->child = ((void*)0); + pool->cleanups = ((void*)0); + pool->free_cleanups = ((void*)0); + pool->pre_cleanups = ((void*)0); + pool->subprocesses = ((void*)0); + pool->user_data = ((void*)0); + pool->tag = ((void*)0); + + + + + + if ((pool->parent = parent) != ((void*)0)) { + + apr_thread_mutex_t *mutex; + + if ((mutex = apr_allocator_mutex_get(parent->allocator)) != ((void*)0)) + apr_thread_mutex_lock(mutex); + + + if ((pool->sibling = parent->child) != ((void*)0)) + pool->sibling->ref = &pool->sibling; + + parent->child = pool; + pool->ref = &parent->child; + + + if (mutex) + apr_thread_mutex_unlock(mutex); + + } + else { + pool->sibling = ((void*)0); + pool->ref = ((void*)0); + } + + *newpool = pool; + + return 0; +} + + + +apr_status_t apr_pool_create_core_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) +{ + return apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator); +} + +apr_status_t apr_pool_create_unmanaged_ex(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) +{ + apr_pool_t *pool; + apr_memnode_t *node; + apr_allocator_t *pool_allocator; + + *newpool = ((void*)0); + + if (!apr_pools_initialized) + return (20000 + 2); + if ((pool_allocator = allocator) == ((void*)0)) { + if ((pool_allocator = malloc((((sizeof(apr_allocator_t)) + ((8) - 1)) & ~((8) - 1)))) == ((void*)0)) { + if (abort_fn) + abort_fn(12); + + return 12; + } + memset(pool_allocator, 0, (((sizeof(apr_allocator_t)) + ((8) - 1)) & ~((8) - 1))); + pool_allocator->max_free_index = 0; + } + if ((node = allocator_alloc(pool_allocator, + (2 * (1 << 12)) - (((sizeof(apr_memnode_t)) + ((8) - 1)) & ~((8) - 1)))) == ((void*)0)) { + if (abort_fn) + abort_fn(12); + + return 12; + } + + node->next = node; + node->ref = &node->next; + + pool = (apr_pool_t *)node->first_avail; + node->first_avail = pool->self_first_avail = (char *)pool + (((sizeof(apr_pool_t)) + ((8) - 1)) & ~((8) - 1)); + + pool->allocator = pool_allocator; + pool->active = pool->self = node; + pool->abort_fn = abort_fn; + pool->child = ((void*)0); + pool->cleanups = ((void*)0); + pool->free_cleanups = ((void*)0); + pool->pre_cleanups = ((void*)0); + pool->subprocesses = ((void*)0); + pool->user_data = ((void*)0); + pool->tag = ((void*)0); + pool->parent = ((void*)0); + pool->sibling = ((void*)0); + pool->ref = ((void*)0); + + + + + if (!allocator) + pool_allocator->owner = pool; + *newpool = pool; + + return 0; +} +# 1036 "./../memory/unix/apr_pools.c" +struct psprintf_data { + apr_vformatter_buff_t vbuff; + apr_memnode_t *node; + apr_pool_t *pool; + apr_byte_t got_a_new_node; + apr_memnode_t *free; +}; + + + +static int psprintf_flush(apr_vformatter_buff_t *vbuff) +{ + struct psprintf_data *ps = (struct psprintf_data *)vbuff; + apr_memnode_t *node, *active; + apr_size_t cur_len, size; + char *strp; + apr_pool_t *pool; + apr_size_t free_index; + + pool = ps->pool; + active = ps->node; + strp = ps->vbuff.curpos; + cur_len = strp - active->first_avail; + size = cur_len << 1; + + + + + + + if (size < 32) + size = 32; + + node = active->next; + if (!ps->got_a_new_node && size <= ((apr_size_t)(node->endp - node->first_avail))) { + + do { *node->ref = node->next; node->next->ref = node->ref; } while (0); + do { node->ref = active->ref; *node->ref = node; node->next = active; active->ref = &node->next; } while (0); + + node->free_index = 0; + + pool->active = node; + + free_index = ((((active->endp - active->first_avail + 1) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)) - (1 << 12)) >> 12; + + + active->free_index = (apr_uint32_t)free_index; + node = active->next; + if (free_index < node->free_index) { + do { + node = node->next; + } + while (free_index < node->free_index); + + do { *active->ref = active->next; active->next->ref = active->ref; } while (0); + do { active->ref = node->ref; *active->ref = active; active->next = node; node->ref = &active->next; } while (0); + } + + node = pool->active; + } + else { + if ((node = allocator_alloc(pool->allocator, size)) == ((void*)0)) + return -1; + + if (ps->got_a_new_node) { + active->next = ps->free; + ps->free = active; + } + + ps->got_a_new_node = 1; + } + + memcpy(node->first_avail, active->first_avail, cur_len); + + ps->node = node; + ps->vbuff.curpos = node->first_avail + cur_len; + ps->vbuff.endpos = node->endp - 1; + + return 0; +} + +char * apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) +{ + struct psprintf_data ps; + char *strp; + apr_size_t size; + apr_memnode_t *active, *node; + apr_size_t free_index; + + ps.node = active = pool->active; + ps.pool = pool; + ps.vbuff.curpos = ps.node->first_avail; + + + ps.vbuff.endpos = ps.node->endp - 1; + ps.got_a_new_node = 0; + ps.free = ((void*)0); + + + + + if (ps.node->first_avail == ps.node->endp) { + if (psprintf_flush(&ps.vbuff) == -1) { + if (pool->abort_fn) { + pool->abort_fn(12); + } + + return ((void*)0); + } + } + + if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) { + if (pool->abort_fn) + pool->abort_fn(12); + + return ((void*)0); + } + + strp = ps.vbuff.curpos; + *strp++ = '\0'; + + size = strp - ps.node->first_avail; + size = (((size) + ((8) - 1)) & ~((8) - 1)); + strp = ps.node->first_avail; + ps.node->first_avail += size; + + if (ps.free) + allocator_free(pool->allocator, ps.free); + + + + + if (!ps.got_a_new_node) + return strp; + + active = pool->active; + node = ps.node; + + node->free_index = 0; + + do { node->ref = active->ref; *node->ref = node; node->next = active; active->ref = &node->next; } while (0); + + pool->active = node; + + free_index = ((((active->endp - active->first_avail + 1) + (((1 << 12)) - 1)) & ~(((1 << 12)) - 1)) - (1 << 12)) >> 12; + + + active->free_index = (apr_uint32_t)free_index; + node = active->next; + + if (free_index >= node->free_index) + return strp; + + do { + node = node->next; + } + while (free_index < node->free_index); + + do { *active->ref = active->next; active->next->ref = active->ref; } while (0); + do { active->ref = node->ref; *active->ref = active; active->next = node; node->ref = &active->next; } while (0); + + return strp; +} +# 2049 "./../memory/unix/apr_pools.c" +char * apr_psprintf(apr_pool_t *p, const char *fmt, ...) +{ + va_list ap; + char *res; + + __builtin_va_start(ap, fmt); + res = apr_pvsprintf(p, fmt, ap); + __builtin_va_end(ap); + return res; +} + + + + + +void apr_pool_abort_set(apr_abortfunc_t abort_fn, + apr_pool_t *pool) +{ + pool->abort_fn = abort_fn; +} + +apr_abortfunc_t apr_pool_abort_get(apr_pool_t *pool) +{ + return pool->abort_fn; +} + +apr_pool_t * apr_pool_parent_get(apr_pool_t *pool) +{ + + + + + + + + return pool->parent; +} + +apr_allocator_t * apr_pool_allocator_get(apr_pool_t *pool) +{ + return pool->allocator; +} + + + + +int apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b) +{ + if (a == ((void*)0)) + return 1; +# 2108 "./../memory/unix/apr_pools.c" + while (b) { + if (a == b) + return 1; + + b = b->parent; + } + + return 0; +} + +void apr_pool_tag(apr_pool_t *pool, const char *tag) +{ + pool->tag = tag; +} + + + + + + +apr_status_t apr_pool_userdata_set(const void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_pool_t *pool) +{ + + + + + if (pool->user_data == ((void*)0)) + pool->user_data = apr_hash_make(pool); + + if (apr_hash_get(pool->user_data, key, (-1)) == ((void*)0)) { + char *new_key = apr_pstrdup(pool, key); + apr_hash_set(pool->user_data, new_key, (-1), data); + } + else { + apr_hash_set(pool->user_data, key, (-1), data); + } + + if (cleanup) + apr_pool_cleanup_register(pool, data, cleanup, cleanup); + + return 0; +} + +apr_status_t apr_pool_userdata_setn(const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) +{ + + + + + if (pool->user_data == ((void*)0)) + pool->user_data = apr_hash_make(pool); + + apr_hash_set(pool->user_data, key, (-1), data); + + if (cleanup) + apr_pool_cleanup_register(pool, data, cleanup, cleanup); + + return 0; +} + +apr_status_t apr_pool_userdata_get(void **data, const char *key, + apr_pool_t *pool) +{ + + + + + if (pool->user_data == ((void*)0)) { + *data = ((void*)0); + } + else { + *data = apr_hash_get(pool->user_data, key, (-1)); + } + + return 0; +} + + + + + + +struct cleanup_t { + struct cleanup_t *next; + const void *data; + apr_status_t (*plain_cleanup_fn)(void *data); + apr_status_t (*child_cleanup_fn)(void *data); +}; + +void apr_pool_cleanup_register(apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup_fn)(void *data), + apr_status_t (*child_cleanup_fn)(void *data)) +{ + cleanup_t *c; + + + + + + if (p != ((void*)0)) { + if (p->free_cleanups) { + + c = p->free_cleanups; + p->free_cleanups = c->next; + } else { + c = apr_palloc(p, sizeof(cleanup_t)); + } + c->data = data; + c->plain_cleanup_fn = plain_cleanup_fn; + c->child_cleanup_fn = child_cleanup_fn; + c->next = p->cleanups; + p->cleanups = c; + } +} + +void apr_pool_pre_cleanup_register(apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup_fn)(void *data)) +{ + cleanup_t *c; + + + + + + if (p != ((void*)0)) { + if (p->free_cleanups) { + + c = p->free_cleanups; + p->free_cleanups = c->next; + } else { + c = apr_palloc(p, sizeof(cleanup_t)); + } + c->data = data; + c->plain_cleanup_fn = plain_cleanup_fn; + c->next = p->pre_cleanups; + p->pre_cleanups = c; + } +} + +void apr_pool_cleanup_kill(apr_pool_t *p, const void *data, + apr_status_t (*cleanup_fn)(void *)) +{ + cleanup_t *c, **lastp; + + + + + + if (p == ((void*)0)) + return; + + c = p->cleanups; + lastp = &p->cleanups; + while (c) { +# 2276 "./../memory/unix/apr_pools.c" + if (c->data == data && c->plain_cleanup_fn == cleanup_fn) { + *lastp = c->next; + + c->next = p->free_cleanups; + p->free_cleanups = c; + break; + } + + lastp = &c->next; + c = c->next; + } + + + c = p->pre_cleanups; + lastp = &p->pre_cleanups; + while (c) { +# 2301 "./../memory/unix/apr_pools.c" + if (c->data == data && c->plain_cleanup_fn == cleanup_fn) { + *lastp = c->next; + + c->next = p->free_cleanups; + p->free_cleanups = c; + break; + } + + lastp = &c->next; + c = c->next; + } + +} + +void apr_pool_child_cleanup_set(apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup_fn)(void *), + apr_status_t (*child_cleanup_fn)(void *)) +{ + cleanup_t *c; + + + + + + if (p == ((void*)0)) + return; + + c = p->cleanups; + while (c) { + if (c->data == data && c->plain_cleanup_fn == plain_cleanup_fn) { + c->child_cleanup_fn = child_cleanup_fn; + break; + } + + c = c->next; + } +} + +apr_status_t apr_pool_cleanup_run(apr_pool_t *p, void *data, + apr_status_t (*cleanup_fn)(void *)) +{ + apr_pool_cleanup_kill(p, data, cleanup_fn); + return (*cleanup_fn)(data); +} + +static void run_cleanups(cleanup_t **cref) +{ + cleanup_t *c = *cref; + + while (c) { + *cref = c->next; + (*c->plain_cleanup_fn)((void *)c->data); + c = *cref; + } +} + + + +static void run_child_cleanups(cleanup_t **cref) +{ + cleanup_t *c = *cref; + + while (c) { + *cref = c->next; + (*c->child_cleanup_fn)((void *)c->data); + c = *cref; + } +} + +static void cleanup_pool_for_exec(apr_pool_t *p) +{ + run_child_cleanups(&p->cleanups); + + for (p = p->child; p; p = p->sibling) + cleanup_pool_for_exec(p); +} + +void apr_pool_cleanup_for_exec(void) +{ + cleanup_pool_for_exec(global_pool); +} +# 2402 "./../memory/unix/apr_pools.c" +apr_status_t apr_pool_cleanup_null(void *data) +{ + + return 0; +} +# 2415 "./../memory/unix/apr_pools.c" +void apr_pool_note_subprocess(apr_pool_t *pool, apr_proc_t *proc, + apr_kill_conditions_e how) +{ + struct process_chain *pc = apr_palloc(pool, sizeof(struct process_chain)); + + pc->proc = proc; + pc->kill_how = how; + pc->next = pool->subprocesses; + pool->subprocesses = pc; +} + +static void free_proc_chain(struct process_chain *procs) +{ + + + + + struct process_chain *pc; + int need_timeout = 0; + apr_time_t timeout_interval; + + if (!procs) + return; +# 2448 "./../memory/unix/apr_pools.c" + for (pc = procs; pc; pc = pc->next) { + if (apr_proc_wait(pc->proc, ((void*)0), ((void*)0), APR_NOWAIT) != ((20000 + 50000) + 6)) + pc->kill_how = APR_KILL_NEVER; + } + + + for (pc = procs; pc; pc = pc->next) { + + if ((pc->kill_how == APR_KILL_AFTER_TIMEOUT) + || (pc->kill_how == APR_KILL_ONLY_ONCE)) { + + + + + + + if (apr_proc_kill(pc->proc, 15) == 0) + need_timeout = 1; + } + else if (pc->kill_how == APR_KILL_ALWAYS) { + + + + + + apr_proc_kill(pc->proc, 9); + } + } + + + + + + if (need_timeout) { + timeout_interval = 46875; + apr_sleep(timeout_interval); + + do { + + need_timeout = 0; + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how == APR_KILL_AFTER_TIMEOUT) { + if (apr_proc_wait(pc->proc, ((void*)0), ((void*)0), APR_NOWAIT) + == ((20000 + 50000) + 6)) + need_timeout = 1; + else + pc->kill_how = APR_KILL_NEVER; + } + } + if (need_timeout) { + if (timeout_interval >= 3000000) { + break; + } + apr_sleep(timeout_interval); + timeout_interval *= 2; + } + } while (need_timeout); + } + + + + + + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how == APR_KILL_AFTER_TIMEOUT) + apr_proc_kill(pc->proc, 9); + } + + + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how != APR_KILL_NEVER) + (void)apr_proc_wait(pc->proc, ((void*)0), ((void*)0), APR_WAIT); + } +} +# 2530 "./../memory/unix/apr_pools.c" +void * apr_palloc_debug(apr_pool_t *pool, apr_size_t size, + const char *file_line) +{ + return apr_palloc(pool, size); +} + +void * apr_pcalloc_debug(apr_pool_t *pool, apr_size_t size, + const char *file_line) +{ + return apr_pcalloc(pool, size); +} + +void apr_pool_clear_debug(apr_pool_t *pool, + const char *file_line) +{ + apr_pool_clear(pool); +} + +void apr_pool_destroy_debug(apr_pool_t *pool, + const char *file_line) +{ + apr_pool_destroy(pool); +} + +apr_status_t apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) +{ + return apr_pool_create_ex(newpool, parent, abort_fn, allocator); +} + +apr_status_t apr_pool_create_core_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) +{ + return apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator); +} + +apr_status_t apr_pool_create_unmanaged_ex_debug(apr_pool_t **newpool, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) +{ + return apr_pool_create_unmanaged_ex(newpool, abort_fn, allocator); +} +# 14 "main2.c" 2 +# 1 "./../misc/unix/start.c" 1 +# 20 "./../misc/unix/start.c" +# 1 "../include/apr_signal.h" 1 +# 57 "../include/apr_signal.h" +typedef void apr_sigfunc_t(int); + + + + + + +apr_sigfunc_t * apr_signal(int signo, apr_sigfunc_t * func); +# 80 "../include/apr_signal.h" +const char * apr_signal_description_get(int signum); + + + + + + +void apr_signal_init(apr_pool_t *pglobal); + + + + + + +apr_status_t apr_signal_block(int signum); + + + + + + +apr_status_t apr_signal_unblock(int signum); +# 21 "./../misc/unix/start.c" 2 + + + +# 1 "../include/arch/unix/apr_arch_internal_time.h" 1 +# 22 "../include/arch/unix/apr_arch_internal_time.h" +void apr_unix_setup_time(void); +# 25 "./../misc/unix/start.c" 2 + + +apr_status_t apr_app_initialize(int *argc, + const char * const * *argv, + const char * const * *env) +{ + + + + + + return apr_initialize(); +} + +static int initialized = 0; + +apr_status_t apr_initialize(void) +{ + apr_pool_t *pool; + apr_status_t status; + + if (initialized++) { + return 0; + } + + + apr_proc_mutex_unix_setup_lock(); + apr_unix_setup_time(); + + + if ((status = apr_pool_initialize()) != 0) + return status; + + if (apr_pool_create_ex(&pool, ((void*)0), ((void*)0), ((void*)0)) != 0) { + return (20000 + 2); + } + + apr_pool_tag(pool, "apr_initialize"); +# 71 "./../misc/unix/start.c" + apr_signal_init(pool); + + return 0; +} + +void apr_terminate(void) +{ + initialized--; + if (initialized) { + return; + } + apr_pool_terminate(); + +} + +void apr_terminate2(void) +{ + apr_terminate(); +} +# 15 "main2.c" 2 +# 1 "./../time/unix/time.c" 1 +# 43 "./../time/unix/time.c" +static apr_int32_t get_offset(struct tm *tm) +{ + + return tm->tm_gmtoff; +# 64 "./../time/unix/time.c" +} + +apr_status_t apr_time_ansi_put(apr_time_t *result, + time_t input) +{ + *result = (apr_time_t)input * 1000000L; + return 0; +} + + +apr_time_t apr_time_now(void) +{ + struct timeval tv; + gettimeofday(&tv, ((void*)0)); + return tv.tv_sec * 1000000L + tv.tv_usec; +} + +static void explode_time(apr_time_exp_t *xt, apr_time_t t, + apr_int32_t offset, int use_localtime) +{ + struct tm tm; + time_t tt = (t / 1000000L) + offset; + xt->tm_usec = t % 1000000L; + + + if (use_localtime) + localtime_r(&tt, &tm); + else + gmtime_r(&tt, &tm); + + + + + + + + xt->tm_sec = tm.tm_sec; + xt->tm_min = tm.tm_min; + xt->tm_hour = tm.tm_hour; + xt->tm_mday = tm.tm_mday; + xt->tm_mon = tm.tm_mon; + xt->tm_year = tm.tm_year; + xt->tm_wday = tm.tm_wday; + xt->tm_yday = tm.tm_yday; + xt->tm_isdst = tm.tm_isdst; + xt->tm_gmtoff = get_offset(&tm); +} + +apr_status_t apr_time_exp_tz(apr_time_exp_t *result, + apr_time_t input, apr_int32_t offs) +{ + explode_time(result, input, offs, 0); + result->tm_gmtoff = offs; + return 0; +} + +apr_status_t apr_time_exp_gmt(apr_time_exp_t *result, + apr_time_t input) +{ + return apr_time_exp_tz(result, input, 0); +} + +apr_status_t apr_time_exp_lt(apr_time_exp_t *result, + apr_time_t input) +{ + + + + + explode_time(result, input, 0, 1); + return 0; + +} + +apr_status_t apr_time_exp_get(apr_time_t *t, apr_time_exp_t *xt) +{ + apr_time_t year = xt->tm_year; + apr_time_t days; + static const int dayoffset[12] = + {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; + + + + if (xt->tm_mon < 2) + year--; + + + + days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4; + days += dayoffset[xt->tm_mon] + xt->tm_mday - 1; + days -= 25508; + days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec; + + if (days < 0) { + return (20000 + 4); + } + *t = days * 1000000L + xt->tm_usec; + return 0; +} + +apr_status_t apr_time_exp_gmt_get(apr_time_t *t, + apr_time_exp_t *xt) +{ + apr_status_t status = apr_time_exp_get(t, xt); + if (status == 0) + *t -= (apr_time_t) xt->tm_gmtoff * 1000000L; + return status; +} + +apr_status_t apr_os_imp_time_get(apr_os_imp_time_t **ostime, + apr_time_t *aprtime) +{ + (*ostime)->tv_usec = *aprtime % 1000000L; + (*ostime)->tv_sec = *aprtime / 1000000L; + return 0; +} + +apr_status_t apr_os_exp_time_get(apr_os_exp_time_t **ostime, + apr_time_exp_t *aprtime) +{ + (*ostime)->tm_sec = aprtime->tm_sec; + (*ostime)->tm_min = aprtime->tm_min; + (*ostime)->tm_hour = aprtime->tm_hour; + (*ostime)->tm_mday = aprtime->tm_mday; + (*ostime)->tm_mon = aprtime->tm_mon; + (*ostime)->tm_year = aprtime->tm_year; + (*ostime)->tm_wday = aprtime->tm_wday; + (*ostime)->tm_yday = aprtime->tm_yday; + (*ostime)->tm_isdst = aprtime->tm_isdst; + + + (*ostime)->tm_gmtoff = aprtime->tm_gmtoff; + + + + + return 0; +} + +apr_status_t apr_os_imp_time_put(apr_time_t *aprtime, + apr_os_imp_time_t **ostime, + apr_pool_t *cont) +{ + *aprtime = (*ostime)->tv_sec * 1000000L + (*ostime)->tv_usec; + return 0; +} + +apr_status_t apr_os_exp_time_put(apr_time_exp_t *aprtime, + apr_os_exp_time_t **ostime, + apr_pool_t *cont) +{ + aprtime->tm_sec = (*ostime)->tm_sec; + aprtime->tm_min = (*ostime)->tm_min; + aprtime->tm_hour = (*ostime)->tm_hour; + aprtime->tm_mday = (*ostime)->tm_mday; + aprtime->tm_mon = (*ostime)->tm_mon; + aprtime->tm_year = (*ostime)->tm_year; + aprtime->tm_wday = (*ostime)->tm_wday; + aprtime->tm_yday = (*ostime)->tm_yday; + aprtime->tm_isdst = (*ostime)->tm_isdst; + + + aprtime->tm_gmtoff = (*ostime)->tm_gmtoff; + + + + + return 0; +} + +void apr_sleep(apr_interval_time_t t) +{ + + + + + + + + struct timeval tv; + tv.tv_usec = t % 1000000L; + tv.tv_sec = t / 1000000L; + select(0, ((void*)0), ((void*)0), ((void*)0), &tv); + +} +# 296 "./../time/unix/time.c" +void apr_unix_setup_time(void) +{ +# 339 "./../time/unix/time.c" +} + + + + +void apr_time_clock_hires(apr_pool_t *p) +{ + return; +} +# 16 "main2.c" 2 +# 1 "./../atomic/unix/builtins.c" 1 +# 17 "./../atomic/unix/builtins.c" +# 1 "../include/arch/unix/apr_arch_atomic.h" 1 +# 18 "./../atomic/unix/builtins.c" 2 + + + +apr_status_t apr_atomic_init(apr_pool_t *p) +{ + return 0; +} + +apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem) +{ + return *mem; +} + +void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + *mem = val; +} + +apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + return __sync_fetch_and_add(mem, val); +} + +void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + __sync_fetch_and_sub(mem, val); +} + +apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem) +{ + return __sync_fetch_and_add(mem, 1); +} + +int apr_atomic_dec32(volatile apr_uint32_t *mem) +{ + return __sync_sub_and_fetch(mem, 1); +} + +apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, + apr_uint32_t cmp) +{ + return __sync_val_compare_and_swap(mem, cmp, with); +} + +apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + __sync_synchronize(); + + return __sync_lock_test_and_set(mem, val); +} + +void* apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) +{ + return (void*) __sync_val_compare_and_swap(mem, cmp, with); +} + +void* apr_atomic_xchgptr(volatile void **mem, void *with) +{ + __sync_synchronize(); + + return (void*) __sync_lock_test_and_set(mem, with); +} +# 17 "main2.c" 2 +# 1 "./../threadproc/unix/signals.c" 1 +# 18 "./../threadproc/unix/signals.c" +# 1 "../include/arch/unix/apr_arch_threadproc.h" 1 +# 55 "../include/arch/unix/apr_arch_threadproc.h" +struct apr_thread_t { + apr_pool_t *pool; + pthread_t *td; + void *data; + apr_thread_start_t func; + apr_status_t exitval; +}; + +struct apr_threadattr_t { + apr_pool_t *pool; + pthread_attr_t attr; +}; + +struct apr_threadkey_t { + apr_pool_t *pool; + pthread_key_t key; +}; + +struct apr_thread_once_t { + pthread_once_t once; +}; + + + +struct apr_procattr_t { + apr_pool_t *pool; + apr_file_t *parent_in; + apr_file_t *child_in; + apr_file_t *parent_out; + apr_file_t *child_out; + apr_file_t *parent_err; + apr_file_t *child_err; + char *currdir; + apr_int32_t cmdtype; + apr_int32_t detached; + + struct rlimit *limit_cpu; + + + struct rlimit *limit_mem; + + + struct rlimit *limit_nproc; + + + struct rlimit *limit_nofile; + + apr_child_errfn_t *errfn; + apr_int32_t errchk; + apr_uid_t uid; + apr_gid_t gid; +}; +# 19 "./../threadproc/unix/signals.c" 2 + + + + + +# 1 "/usr/include/assert.h" 1 3 4 +# 69 "/usr/include/assert.h" 3 4 +extern void __assert_fail (const char *__assertion, const char *__file, + unsigned int __line, const char *__function) + __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); + + +extern void __assert_perror_fail (int __errnum, const char *__file, + unsigned int __line, const char *__function) + __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); + + + + +extern void __assert (const char *__assertion, const char *__file, int __line) + __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__)); +# 25 "./../threadproc/unix/signals.c" 2 +# 35 "./../threadproc/unix/signals.c" +apr_status_t apr_proc_kill(apr_proc_t *proc, int signum) +{ +# 48 "./../threadproc/unix/signals.c" + if (kill(proc->pid, signum) == -1) { + return (*__errno_location ()); + } + + return 0; +} +# 74 "./../threadproc/unix/signals.c" +apr_sigfunc_t * apr_signal(int signo, apr_sigfunc_t * func) +{ + struct sigaction act, oact; + + act.__sigaction_handler.sa_handler = func; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + + act.sa_flags |= 0x20000000; +# 103 "./../threadproc/unix/signals.c" + if (sigaction(signo, &act, &oact) < 0) + return ((__sighandler_t) -1); + return oact.__sigaction_handler.sa_handler; +} + + + + + + + +void apr_signal_init(apr_pool_t *pglobal) +{ +} +const char *apr_signal_description_get(int signum) +{ + return (signum >= 0) ? sys_siglist[signum] : "unknown signal (number)"; +} +# 274 "./../threadproc/unix/signals.c" +static void remove_sync_sigs(sigset_t *sig_mask) +{ + + sigdelset(sig_mask, 6); + + + sigdelset(sig_mask, 7); + + + + + + sigdelset(sig_mask, 8); + + + sigdelset(sig_mask, 4); + + + sigdelset(sig_mask, 6); + + + sigdelset(sig_mask, 13); + + + sigdelset(sig_mask, 11); + + + sigdelset(sig_mask, 31); + + + sigdelset(sig_mask, 5); +# 315 "./../threadproc/unix/signals.c" + sigdelset(sig_mask, 12); + +} + +apr_status_t apr_signal_thread(int(*signal_handler)(int signum)) +{ + sigset_t sig_mask; + + int (*sig_func)(int signum) = (int (*)(int))signal_handler; + + + + sigfillset(&sig_mask); + + + + + + + sigdelset(&sig_mask, 9); + + + sigdelset(&sig_mask, 19); + + + sigdelset(&sig_mask, 18); + + + + + + + remove_sync_sigs(&sig_mask); +# 379 "./../threadproc/unix/signals.c" + while (1) { + + int signal_received; + + if (sigwait((&sig_mask),(&signal_received)) != 0) + { + + } + + if (sig_func(signal_received) == 1) { + return 0; + } + + + + + + } +} + +apr_status_t apr_setup_signal_thread(void) +{ + sigset_t sig_mask; + int rv; +# 416 "./../threadproc/unix/signals.c" + sigfillset(&sig_mask); + remove_sync_sigs(&sig_mask); + + + + + + + if ((rv = pthread_sigmask(2, &sig_mask, ((void*)0))) != 0) { + + + + } + + return rv; +} + + + +apr_status_t apr_signal_block(int signum) +{ + + sigset_t sig_mask; + int rv; + + sigemptyset(&sig_mask); + + sigaddset(&sig_mask, signum); + + + + + + + if ((rv = pthread_sigmask(0, &sig_mask, ((void*)0))) != 0) { + + + + } + + return rv; + + + +} + +apr_status_t apr_signal_unblock(int signum) +{ + + sigset_t sig_mask; + int rv; + + sigemptyset(&sig_mask); + + sigaddset(&sig_mask, signum); + + + + + + + if ((rv = pthread_sigmask(1, &sig_mask, ((void*)0))) != 0) { + + + + } + + return rv; + + + +} +# 18 "main2.c" 2 +# 1 "./../threadproc/unix/thread.c" 1 +# 19 "./../threadproc/unix/thread.c" +# 1 "../include/arch/unix/apr_arch_threadproc.h" 1 +# 20 "./../threadproc/unix/thread.c" 2 + + + + + + +static apr_status_t threadattr_cleanup(void *data) +{ + apr_threadattr_t *attr = data; + apr_status_t rv; + + rv = pthread_attr_destroy(&attr->attr); + + + + + + return rv; +} + +apr_status_t apr_threadattr_create(apr_threadattr_t **new, + apr_pool_t *pool) +{ + apr_status_t stat; + + (*new) = apr_palloc(pool, sizeof(apr_threadattr_t)); + (*new)->pool = pool; + stat = pthread_attr_init(&(*new)->attr); + + if (stat == 0) { + apr_pool_cleanup_register(pool, *new, threadattr_cleanup, + apr_pool_cleanup_null); + return 0; + } + + + + + return stat; +} + + + + + + + +apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr, + apr_int32_t on) +{ + apr_status_t stat; + + + + + + if ((stat = pthread_attr_setdetachstate(&attr->attr, + ((on) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE))) == 0) { + + return 0; + } + else { + + + + + return stat; + } +} + +apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr) +{ + int state; + + + + + pthread_attr_getdetachstate(&attr->attr, &state); + + if (state == ((1) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE)) + return ((20000 + 50000) + 3); + return ((20000 + 50000) + 4); +} + +apr_status_t apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize) +{ + int stat; + + stat = pthread_attr_setstacksize(&attr->attr, stacksize); + if (stat == 0) { + return 0; + } + + + + + return stat; +} + +apr_status_t apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t size) +{ + + apr_status_t rv; + + rv = pthread_attr_setguardsize(&attr->attr, size); + if (rv == 0) { + return 0; + } + + + + return rv; + + + +} + +static void *dummy_worker(void *opaque) +{ + apr_thread_t *thread = (apr_thread_t*)opaque; + return thread->func(thread, thread->data); +} + +apr_status_t apr_thread_create(apr_thread_t **new, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, + apr_pool_t *pool) +{ + apr_status_t stat; + pthread_attr_t *temp; + + (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); + + if ((*new) == ((void*)0)) { + return 12; + } + + (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t)); + + if ((*new)->td == ((void*)0)) { + return 12; + } + + (*new)->data = data; + (*new)->func = func; + + if (attr) + temp = &attr->attr; + else + temp = ((void*)0); + + stat = apr_pool_create_ex(&(*new)->pool, pool, ((void*)0), ((void*)0)); + if (stat != 0) { + return stat; + } + + if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) { + return 0; + } + else { + + + + + return stat; + } +} + +apr_os_thread_t apr_os_thread_current(void) +{ + return pthread_self(); +} + +int apr_os_thread_equal(apr_os_thread_t tid1, + apr_os_thread_t tid2) +{ + return pthread_equal(tid1, tid2); +} + +apr_status_t apr_thread_exit(apr_thread_t *thd, + apr_status_t retval) +{ + thd->exitval = retval; + apr_pool_destroy(thd->pool); + pthread_exit(((void*)0)); + return 0; +} + +apr_status_t apr_thread_join(apr_status_t *retval, + apr_thread_t *thd) +{ + apr_status_t stat; + apr_status_t *thread_stat; + + if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) { + *retval = thd->exitval; + return 0; + } + else { + + + + + return stat; + } +} + +apr_status_t apr_thread_detach(apr_thread_t *thd) +{ + apr_status_t stat; + + + + + if ((stat = pthread_detach(*thd->td)) == 0) { + + + return 0; + } + else { + + + + + return stat; + } +} + +void apr_thread_yield(void) +{ + + + + + pthread_yield(); + + + + + + +} + +apr_status_t apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread) +{ + return apr_pool_userdata_get(data, key, thread->pool); +} + +apr_status_t apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_thread_t *thread) +{ + return apr_pool_userdata_set(data, key, cleanup, thread->pool); +} + +apr_status_t apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd) +{ + *thethd = thd->td; + return 0; +} + +apr_status_t apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *pool) +{ + if (pool == ((void*)0)) { + return (20000 + 2); + } + + if ((*thd) == ((void*)0)) { + (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); + (*thd)->pool = pool; + } + + (*thd)->td = thethd; + return 0; +} + +apr_status_t apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p) +{ + static const pthread_once_t once_init = 0; + + *control = apr_palloc(p, sizeof(**control)); + (*control)->once = once_init; + return 0; +} + +apr_status_t apr_thread_once(apr_thread_once_t *control, + void (*func)(void)) +{ + return pthread_once(&control->once, func); +} + +apr_pool_t * apr_thread_pool_get (const apr_thread_t *thethread) { return thethread->pool; } +# 19 "main2.c" 2 +# 1 "./../test/abts.c" 1 +# 17 "./../test/abts.c" +# 1 "./../test/abts.h" 1 +# 18 "./../test/abts.c" 2 +# 1 "./../test/abts_tests.h" 1 +# 20 "./../test/abts_tests.h" +# 1 "./../test/abts.h" 1 +# 21 "./../test/abts_tests.h" 2 +# 1 "./../test/testutil.h" 1 +# 19 "./../test/testutil.h" +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 22 "./../test/abts_tests.h" 2 + +const struct testlist { + abts_suite *(*func)(abts_suite *suite); +} alltests[] = { + {testatomic}, + {testdir}, + {testdso}, + {testdup}, + {testenv}, + {testescape}, + {testfile}, + {testfilecopy}, + {testfileinfo}, + {testflock}, + {testfmt}, + {testfnmatch}, + {testgetopt}, + + + + {testhash}, + {testipsub}, + {testlock}, + {testcond}, + {testlfs}, + {testmmap}, + {testnames}, + {testoc}, + {testpath}, + {testpipe}, + {testpoll}, + {testpool}, + {testproc}, + {testprocmutex}, + {testrand}, + {testsleep}, + {testshm}, + {testsock}, + {testsockets}, + {testsockopt}, + {teststr}, + {teststrnatcmp}, + {testtable}, + {testtemp}, + {testthread}, + {testtime}, + {testud}, + {testuser}, + {testvsn} +}; +# 19 "./../test/abts.c" 2 +# 1 "./../test/testutil.h" 1 +# 19 "./../test/testutil.h" +# 1 "./../test/abts.h" 1 +# 20 "./../test/testutil.h" 2 +# 20 "./../test/abts.c" 2 + + +static char status[6] = {'|', '/', '-', '|', '\\', '-'}; +static int curr_char; +static int verbose = 0; +static int exclude = 0; +static int quiet = 0; +static int list_tests = 0; + +const char **testlist = ((void*)0); + +static int find_test_name(const char *testname) { + int i; + for (i = 0; testlist[i] != ((void*)0); i++) { + if (!strcmp(testlist[i], testname)) { + return 1; + } + } + return 0; +} + + +static int should_test_run(const char *testname) { + int found = 0; + if (list_tests == 1) { + return 0; + } + if (testlist == ((void*)0)) { + return 1; + } + found = find_test_name(testname); + if ((found && !exclude) || (!found && exclude)) { + return 1; + } + return 0; +} + +static void reset_status(void) +{ + curr_char = 0; +} + +static void update_status(void) +{ + if (!quiet) { + curr_char = (curr_char + 1) % 6; + fprintf(stdout, "\b%c", status[curr_char]); + fflush(stdout); + } +} + +static void end_suite(abts_suite *suite) +{ + if (suite != ((void*)0)) { + sub_suite *last = suite->tail; + if (!quiet) { + fprintf(stdout, "\b"); + fflush(stdout); + } + if (last->failed == 0) { + fprintf(stdout, "SUCCESS\n"); + fflush(stdout); + } + else { + fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test); + fflush(stdout); + } + } +} + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full) +{ + sub_suite *subsuite; + char *p; + const char *suite_name; + curr_char = 0; + + + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + subsuite = malloc(sizeof(*subsuite)); + subsuite->num_test = 0; + subsuite->failed = 0; + subsuite->next = ((void*)0); + + + suite_name = strrchr(suite_name_full, '/'); + if (!suite_name) { + suite_name = strrchr(suite_name_full, '\\'); + } + if (suite_name) { + suite_name++; + } else { + suite_name = suite_name_full; + } + p = strrchr(suite_name, '.'); + if (p) { + subsuite->name = memcpy(calloc(p - suite_name + 1, 1), + suite_name, p - suite_name); + } + else { + subsuite->name = suite_name; + } + + if (list_tests) { + fprintf(stdout, "%s\n", subsuite->name); + } + + subsuite->not_run = 0; + + if (suite == ((void*)0)) { + suite = malloc(sizeof(*suite)); + suite->head = subsuite; + suite->tail = subsuite; + } + else { + suite->tail->next = subsuite; + suite->tail = subsuite; + } + + if (!should_test_run(subsuite->name)) { + subsuite->not_run = 1; + return suite; + } + + reset_status(); + fprintf(stdout, "%-20s: ", subsuite->name); + update_status(); + fflush(stdout); + + return suite; +} + +void abts_run_test(abts_suite *ts, test_func f, void *value) +{ + abts_case tc; + sub_suite *ss; + + if (!should_test_run(ts->tail->name)) { + return; + } + ss = ts->tail; + + tc.failed = 0; + tc.suite = ss; + + ss->num_test++; + update_status(); + + f(&tc, value); + + if (tc.failed) { + ss->failed++; + } +} + +static int report(abts_suite *suite) +{ + int count = 0; + sub_suite *dptr; + + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + for (dptr = suite->head; dptr; dptr = dptr->next) { + count += dptr->failed; + } + + if (list_tests) { + return 0; + } + + if (count == 0) { + printf("All tests passed.\n"); + return 0; + } + + dptr = suite->head; + fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); + fprintf(stdout, "===================================================\n"); + while (dptr != ((void*)0)) { + if (dptr->failed != 0) { + float percent = ((float)dptr->failed / (float)dptr->num_test); + fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, + dptr->num_test, dptr->failed, percent * 100); + } + dptr = dptr->next; + } + return 1; +} + +void abts_log_message(const char *fmt, ...) +{ + va_list args; + update_status(); + + if (verbose) { + __builtin_va_start(args, fmt); + vfprintf(stderr, fmt, args); + __builtin_va_end(args); + fprintf(stderr, "\n"); + fflush(stderr); + } +} + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected != actual) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected something other than <%d>, but saw <%d>\n", + lineno, expected, actual); + fflush(stderr); + } +} + +void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = 1; + if (verbose) { + + fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno, + (unsigned long)expected, (unsigned long)actual); + fflush(stderr); + } +} + +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!expected && !actual) return; + if (expected && actual) + if (!strcmp(expected, actual)) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!strncmp(expected, actual, n)) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected something other than <%s>, but saw <%s>\n", + lineno, expected, actual); + fflush(stderr); + } +} + +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (ptr != ((void*)0)) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected non-NULL, but saw NULL\n", lineno); + fflush(stderr); + } +} + +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_fail(abts_case *tc, const char *message, int lineno) +{ + update_status(); + if (tc->failed) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_assert(abts_case *tc, const char *message, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (condition) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_true(abts_case *tc, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (condition) return; + + tc->failed = 1; + if (verbose) { + fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno); + fflush(stderr); + } +} + +void abts_not_impl(abts_case *tc, const char *message, int lineno) +{ + update_status(); + + tc->suite->not_impl++; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} +# 20 "main2.c" 2 + + + + + + +int fflush(FILE *stream){ + return 0; +} + +int fprintf(FILE *stream, const char *format, ...){ + return 0; +} + +void test_atomics_threaded_2(abts_case *tc, void *data) +{ + apr_thread_t *t2[2]; + apr_status_t rv; + int i; + + + + + + rv = apr_thread_mutex_create(&thread_lock, 0x0, p); + (((rv == 0) && "Could not create lock") ? (void) (0) : __assert_fail ("(rv == 0) && \"Could not create lock\"", "main2.c", 45, __PRETTY_FUNCTION__)); + + for (i = 0; i < 2; i++) { + apr_status_t r2; + r2 = apr_thread_create(&t2[i], ((void*)0), thread_func_atomic, ((void*)0), p); + ((!r2 && "Failed creating threads") ? (void) (0) : __assert_fail ("!r2 && \"Failed creating threads\"", "main2.c", 50, __PRETTY_FUNCTION__)); + } + + for (i = 0; i < 2; i++) { + apr_status_t s2; + apr_thread_join(&s2, t2[i]); + + ((s2 == exit_ret_val && "Invalid return value from thread_join") ? (void) (0) : __assert_fail ("s2 == exit_ret_val && \"Invalid return value from thread_join\"", "main2.c", 58, __PRETTY_FUNCTION__)); + + } + + abts_int_equal(tc, 2 * 1, apr_atomic_read32(&atomic_ops), 62); + + + rv = apr_thread_mutex_destroy(thread_lock); + ((rv == 0 && "Failed creating threads") ? (void) (0) : __assert_fail ("rv == 0 && \"Failed creating threads\"", "main2.c", 65, __PRETTY_FUNCTION__)); +} + +int main(int argc, char *argv[]){ + + initialize(); + + abts_case tc; + tc.failed = 0; + tc.suite = ((void*)0); + test_atomics_threaded_2(&tc,((void*)0)); + + return 0; +} diff --git a/clang/test/bitops.c b/clang/test/bitops.c new file mode 100644 index 0000000..ba329d9 --- /dev/null +++ b/clang/test/bitops.c @@ -0,0 +1,137 @@ +#include +#include "libinterface.h" + +/* atomic */ int flag1, flag2; + +#define true 1 +#define false 0 +#define NULL 0 +#define MAX_FREELIST 4 /* Each thread can own up to MAX_FREELIST free nodes */ +static unsigned int (*free_lists)[MAX_FREELIST]; + +typedef /* atomic */ unsigned long long pointer_t; +typedef unsigned long long pointer; +#define MAKE_POINTER(ptr, count) ((((pointer)count) << 32) | ptr) +#define COUNT_MASK (0xffffffffLL << 32) +#define PTR_MASK 0xffffffffLL +static inline unsigned int get_count(MCID _mp, pointer p, MCID * retval) { *retval = MCID_NODEP; +return (p & COUNT_MASK) >> 32; } +static inline unsigned int get_ptr(MCID _mp, pointer p, MCID * retval) { *retval = MCID_NODEP; +return p & PTR_MASK; } +#define MAX_NODES 0xf + +typedef struct node { + unsigned int value; + pointer_t next; +} node_t; + +typedef struct { + pointer_t top; + node_t nodes[MAX_NODES + 1]; +} stack_t; + +static unsigned int new_node(MCID * retval) +{ + int i; + int t = get_thread_num(); // should be thrd_current but that's not guaranteed to be an array index + MC2_enterLoop(); + for (i = 0; i < MAX_FREELIST; i++) { + void * _p1 = &free_lists[t][i]; MCID _mp1 = MC2_function_id(8, 2, sizeof(_p1), t, i, _p1); + MCID _mnode; _mnode=MC2_nextOpLoad(_mp1); unsigned int node = load_64(p1); + MCID _br0; + + int _cond0 = node; + MCID _cond0_m = MC2_function_id(1, 1, sizeof(_cond0), _cond0, _mnode); + if (_cond0) { + _br0 = MC2_branchUsesID(_mnode, 1, 2, true); + MC2_nextOpStore(_mfree_lists, MCID_NODEP); + store_64(&free_lists[t][i], 0); + *retval = _mnode; + MC2_exitLoop(); + return node; + } + } else { _br0 = MC2_branchUsesID(_mnode, 0, 2, true); MC2_merge(_br0); + } +MC2_exitLoop(); + + *retval = MCID_NODEP; + return 0; +} + +void p0(MCID _ms, stack_t *s) { + MCID _rv0; + unsigned int nodeIdx = new_node(&_rv0); + MCID _mnode; node_t *node = &s->nodes[nodeIdx]; // why is this not load_64'd? + MCID _moldTop; _moldTop=MC2_nextOpLoadOffset(_ms, MC2_OFFSET(stack_t *, top)); pointer oldTop = load_64(&s->top); + MCID _fn0; MCID _rv1; + pointer newTop = MAKE_POINTER(nodeIdx, get_count(oldTop) + 1); + _fn0 = MC2_function_id(4, 2, sizeof (newTop), (uint64_t)newTop, _moldTop, _rv0); + MC2_nextOpStoreOffset(_mnode, MC2_OFFSET(node_t *, next), _moldTop); + store_64(&node->next, oldTop); + MCID _rmw0 = MC2_nextRMWOffset(_ms, MC2_OFFSET(stack_t *, top), MCID_NODEP, _rv1); + rmw_64(CAS, &s->top, &oldTop, newTop); +} + +void p0_no_macros(MCID _ms, stack_t *s) { + MCID _rv2; + unsigned int nodeIdx = new_node(&_rv2); + MCID _mnode; node_t *node = &s->nodes[nodeIdx]; + MCID _moldTop; _moldTop=MC2_nextOpLoadOffset(_ms, MC2_OFFSET(stack_t *, top)); pointer oldTop = load_64(&s->top); + MCID _fn1; pointer newTop = (pointer) (((((oldTop & COUNT_MASK) >> 32) + 1) << 32) | nodeIdx); + _fn1 = MC2_function_id(5, 2, sizeof (newTop), (uint64_t)newTop, _moldTop, _rv2); + MC2_nextOpStoreOffset(_mnode, MC2_OFFSET(node_t *, next), _moldTop); + store_64(&node->next, oldTop); + MCID _rmw1 = MC2_nextRMWOffset(_ms, MC2_OFFSET(stack_t *, top), MCID_NODEP, _fn1); + rmw_64(CAS, &s->top, &oldTop, newTop); +} + +int p1(MCID _ms, stack_t *s, MCID * retval) { + MCID _mnext; MCID _fn2; MCID _moldTop; _moldTop=MC2_nextOpLoadOffset(_ms, MC2_OFFSET(stack_t *, top)); pointer oldTop = load_64(&s->top), newTop, next; + node_t *node; + MCID _br1; + + int _cond1 = get_ptr(oldTop) == 0; + MCID _cond1_m = MC2_function_id(2, 1, sizeof(_cond1), _cond1, _moldTop); + if (_cond1) { + *retval = MCID_NODEP; + _br1 = MC2_branchUsesID(_cond1_m, 1, 2, true); + return 0; } + else { _br1 = MC2_branchUsesID(_cond1_m, 0, 2, true); MC2_merge(_br1); + }MCID _rv3; + node = &s->nodes[get_ptr(MCID_NODEP, oldTop, &_rv3)]; // why is this not load_64'd? + + _mnext=MC2_nextOpLoadOffset(_mnode, MC2_OFFSET(node_t *, next)), next = load_64(&node->next); + MCID _rv5; + MCID _rv4; + newTop = MAKE_POINTER(get_ptr(next), get_count(oldTop) + 1); + MCID _mnewTop = MC2_function_id(9, 2, sizeof (newTop), (uint64_t)newTop, get_ptr(next), get_count(oldTop) + 1); + + MCID _rmw2 = MC2_nextRMWOffset(_ms, MC2_OFFSET(stack_t *, top), MCID_NODEP, _fn2); + rmw_64(CAS, &s->top, &oldTop, newTop); + *retval = MCID_NODEP; + return 0; +} + +int p1_no_macros(MCID _ms, stack_t *s, MCID * retval) { + MCID _mnext; MCID _fn3; MCID _moldTop; _moldTop=MC2_nextOpLoadOffset(_ms, MC2_OFFSET(stack_t *, top)); pointer oldTop = load_64(&s->top), newTop, next; + node_t *node; + MCID _br2; + + int _cond2 = (oldTop & 4294967295LL) == 0; + MCID _cond2_m = MC2_function_id(3, 1, sizeof(_cond2), _cond2, _moldTop); + if (_cond2) { + *retval = MCID_NODEP; + _br2 = MC2_branchUsesID(_cond2_m, 1, 2, true); + return 0; } + else { _br2 = MC2_branchUsesID(_cond2_m, 0, 2, true); MC2_merge(_br2); + }node = &s->nodes[oldTop & PTR_MASK]; + + _mnext=MC2_nextOpLoadOffset(_mnode, MC2_OFFSET(node_t *, next)), next = load_64(&node->next); + newTop = (pointer) (((((oldTop & COUNT_MASK) >> 32) + 1) << 32) | (next & PTR_MASK)); + _fn3 = MC2_function_id(7, 3, sizeof (newTop), (uint64_t)newTop, _fn3, _mnext, _moldTop); + + MCID _rmw3 = MC2_nextRMWOffset(_ms, MC2_OFFSET(stack_t *, top), MCID_NODEP, _fn3); + rmw_64(CAS, &s->top, &oldTop, newTop); + *retval = MCID_NODEP; + return 0; +} diff --git a/clang/test/bitops_unannotated.c b/clang/test/bitops_unannotated.c new file mode 100644 index 0000000..77ce654 --- /dev/null +++ b/clang/test/bitops_unannotated.c @@ -0,0 +1,89 @@ +#include +#include "libinterface.h" + +/* atomic */ int flag1, flag2; + +#define true 1 +#define false 0 +#define NULL 0 +#define MAX_FREELIST 4 /* Each thread can own up to MAX_FREELIST free nodes */ +static unsigned int (*free_lists)[MAX_FREELIST]; + +typedef /* atomic */ unsigned long long pointer_t; +typedef unsigned long long pointer; +#define MAKE_POINTER(ptr, count) ((((pointer)count) << 32) | ptr) +#define COUNT_MASK (0xffffffffLL << 32) +#define PTR_MASK 0xffffffffLL +static inline unsigned int get_count(pointer p) { return (p & COUNT_MASK) >> 32; } +static inline unsigned int get_ptr(pointer p) { return p & PTR_MASK; } +#define MAX_NODES 0xf + +typedef struct node { + unsigned int value; + pointer_t next; +} node_t; + +typedef struct { + pointer_t top; + node_t nodes[MAX_NODES + 1]; +} stack_t; + +static unsigned int new_node() +{ + int i; + int t = get_thread_num(); + for (i = 0; i < MAX_FREELIST; i++) { + unsigned int node = load_64(&free_lists[t][i]); + if (node) { + store_64(&free_lists[t][i], 0); + return node; + } + } + return 0; +} + +void p0(stack_t *s) { + unsigned int nodeIdx = new_node(); + node_t *node = &s->nodes[nodeIdx]; + pointer oldTop = load_64(&s->top); + pointer newTop = MAKE_POINTER(nodeIdx, get_count(oldTop) + 1); + store_64(&node->next, oldTop); + rmw_64(CAS, &s->top, &oldTop, newTop); +} + +void p0_no_macros(stack_t *s) { + unsigned int nodeIdx = new_node(); + node_t *node = &s->nodes[nodeIdx]; + pointer oldTop = load_64(&s->top); + pointer newTop = (pointer) (((((oldTop & COUNT_MASK) >> 32) + 1) << 32) | nodeIdx); + store_64(&node->next, oldTop); + rmw_64(CAS, &s->top, &oldTop, newTop); +} + +int p1(stack_t *s) { + pointer oldTop = load_64(&s->top), newTop, next; + node_t *node; + if (get_ptr(oldTop) == 0) + return 0; + node = &s->nodes[get_ptr(oldTop)]; + + next = load_64(&node->next); + newTop = MAKE_POINTER(get_ptr(next), get_count(oldTop) + 1); + + rmw_64(CAS, &s->top, &oldTop, newTop); + return 0; +} + +int p1_no_macros(stack_t *s) { + pointer oldTop = load_64(&s->top), newTop, next; + node_t *node; + if ((oldTop & PTR_MASK) == 0) + return 0; + node = &s->nodes[oldTop & PTR_MASK]; + + next = load_64(&node->next); + newTop = (pointer) (((((oldTop & COUNT_MASK) >> 32) + 1) << 32) | (next & PTR_MASK)); + + rmw_64(CAS, &s->top, &oldTop, newTop); + return 0; +} diff --git a/clang/test/linuxrwlocks.c b/clang/test/linuxrwlocks.c new file mode 100644 index 0000000..650d0f8 --- /dev/null +++ b/clang/test/linuxrwlocks.c @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "libinterface.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline void read_lock(MCID _mrw, rwlock_t *rw) +{ + MCID _rmw0 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + + MC2_enterLoop(); + while (true) { + MCID _br0; + + int _cond0 = priorvalue <= 0; + MCID _cond0_m = MC2_function(1, sizeof(_cond0), _cond0, _rmw0); + if (_cond0) {_br0 = MC2_branchUsesID(_cond0_m, 1, 2, true); + + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_cond0_m, 0, 2, true); + break; + } + + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); + + MC2_enterLoop(); + while (true) { + MCID _mstatus; _mstatus=MC2_nextOpLoadOffset(_mrw, MC2_OFFSET(rwlock_t *, lock)); int status = load_32(&rw->lock); + MCID _br1; + + int _cond1 = status > 0; + MCID _cond1_m = MC2_function(1, sizeof(_cond1), _cond1, _mstatus); + if (_cond1) {_br1 = MC2_branchUsesID(_cond1_m, 1, 2, true); + + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_cond1_m, 0, 2, true); + break; + } + MC2_yield(); + } +MC2_exitLoop(); + + + MCID _rmw2 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + MC2_loopIterate(); + } +MC2_exitLoop(); + +} + +static inline void write_lock(MCID _mrw, rwlock_t *rw) +{ + MCID _rmw3 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + MC2_enterLoop(); + while(true) { + + MCID _br2; + + int _cond2 = priorvalue != 1048576; + MCID _cond2_m = MC2_function(1, sizeof(_cond2), _cond2, _rmw3); + if (_cond2) {_br2 = MC2_branchUsesID(_cond2_m, 1, 2, true); + + MC2_merge(_br2); + } else { + _br2 = MC2_branchUsesID(_cond2_m, 0, 2, true); + break; + } + + MCID _rmw4 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + + MC2_enterLoop(); + while (true) { + MCID _mstatus; _mstatus=MC2_nextOpLoadOffset(_mrw, MC2_OFFSET(rwlock_t *, lock)); int status = load_32(&rw->lock); + MCID _br3; + + int _cond3 = status != 1048576; + MCID _cond3_m = MC2_function(1, sizeof(_cond3), _cond3, _mstatus); + if (_cond3) {_br3 = MC2_branchUsesID(_cond3_m, 1, 2, true); + + MC2_merge(_br3); + } else { + _br3 = MC2_branchUsesID(_cond3_m, 0, 2, true); + break; + } + MC2_yield(); + } +MC2_exitLoop(); + + + MCID _rmw5 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + } +MC2_exitLoop(); + +} + +static inline bool write_trylock(MCID _mrw, rwlock_t *rw, MCID * retval) +{ + MCID _rmw6 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + + MCID _fn0; int flag = priorvalue != RW_LOCK_BIAS; + _fn0 = MC2_function(1, sizeof (flag), flag, _rmw6); + MCID _br4; + if (flag) {_br4 = MC2_branchUsesID(_fn0, 1, 2, true); + + MC2_merge(_br4); + } else { + _br4 = MC2_branchUsesID(_fn0, 0, 2, true); + MCID _rmw7 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + MC2_merge(_br4); + } + + *retval = _fn0; + return flag; +} + +static inline void read_unlock(MCID _mrw, rwlock_t *rw) +{ + MCID _rmw8 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); +} + +static inline void write_unlock(MCID _mrw, rwlock_t *rw) +{ + MCID _rmw9 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); +} + +MCID _mmylock; rwlock_t mylock; +int shareddata; + +static void foo() { + MCID _rv0; + int flag=write_trylock(MCID_NODEP, &mylock, &_rv0); + MCID _br5; + if (flag) { + _br5 = MC2_branchUsesID(_rv0, 1, 2, true); + write_unlock(MCID_NODEP, &mylock); + MC2_merge(_br5); + } else { _br5 = MC2_branchUsesID(_rv0, 0, 2, true); MC2_merge(_br5); + } +} + +static void a(void *obj) +{ + int i; + MC2_enterLoop(); + for(i=0;i<13;i++) + foo(); +MC2_exitLoop(); + +} + +int user_main(int argc, char **argv) +{ + thrd_t t1, t2; + //, t3, t4; + MC2_nextOpStoreOffset(_mmylock, MC2_OFFSET(rwlock_t, lock), MCID_NODEP); + store_32(&mylock.lock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + // thrd_create(&t3, (thrd_start_t)&a, NULL); + // thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + // thrd_join(t3); + // thrd_join(t4); + + return 0; +} diff --git a/clang/test/linuxrwlocks_unannotated.c b/clang/test/linuxrwlocks_unannotated.c new file mode 100644 index 0000000..bb543fd --- /dev/null +++ b/clang/test/linuxrwlocks_unannotated.c @@ -0,0 +1,125 @@ +#include +#include +#include + +#include "libinterface.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline void read_lock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + + while (true) { + if (priorvalue <= 0) { + } else { + break; + } + + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); + + while (true) { + int status = load_32(&rw->lock); + if (status > 0) { + } else { + break; + } + MC2_yield(); + } + + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-1)); + MC2_loopIterate(); + } +} + +static inline void write_lock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + while(true) { + + if (priorvalue != RW_LOCK_BIAS) { + } else { + break; + } + + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + + while (true) { + int status = load_32(&rw->lock); + if (status != RW_LOCK_BIAS) { + } else { + break; + } + MC2_yield(); + } + + priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + } +} + +static inline bool write_trylock(rwlock_t *rw) +{ + int priorvalue=rmw_32(ADD, &rw->lock, /* dummy */ 0, ((unsigned int)-(RW_LOCK_BIAS))); + + int flag = priorvalue != RW_LOCK_BIAS; + if (flag) { + } else { + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); + } + + return flag; +} + +static inline void read_unlock(rwlock_t *rw) +{ + rmw_32(ADD, &rw->lock, /* dummy */ 0, 1); +} + +static inline void write_unlock(rwlock_t *rw) +{ + rmw_32(ADD, &rw->lock, /* dummy */ 0, RW_LOCK_BIAS); +} + +rwlock_t mylock; +int shareddata; + +static void foo() { + int flag=write_trylock(&mylock); + if (flag) { + write_unlock(&mylock); + } +} + +static void a(void *obj) +{ + int i; + for(i=0;i<13;i++) + foo(); +} + +int user_main(int argc, char **argv) +{ + thrd_t t1, t2; + //, t3, t4; + store_32(&mylock.lock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + // thrd_create(&t3, (thrd_start_t)&a, NULL); + // thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + // thrd_join(t3); + // thrd_join(t4); + + return 0; +} diff --git a/clang/test/mcs-lock_unannotated.cc b/clang/test/mcs-lock_unannotated.cc new file mode 100644 index 0000000..cbc45dc --- /dev/null +++ b/clang/test/mcs-lock_unannotated.cc @@ -0,0 +1,139 @@ +#include +#include + +#include "libinterface.h" + +// mcs on stack + +struct mcs_node { + mcs_node * next; + int gate; + + mcs_node() { + store_64(&next, 0); + store_32(&gate, 0); + } +}; + +struct mcs_mutex { +public: + // tail is null when lock is not held + mcs_node * m_tail; + + mcs_mutex() { + store_64(&m_tail, (uint64_t)NULL); + } + ~mcs_mutex() { + // ASSERT( m_tail.load() == NULL ); + } + + class guard { + public: + mcs_mutex * m_t; + mcs_node m_node; // node held on the stack + + guard(mcs_mutex * t) : m_t(t) { t->lock(this); } + ~guard() { m_t->unlock(this); } + }; + + void lock(guard * I) { + mcs_node * me = &(I->m_node); + + // set up my node : + // not published yet so relaxed : + store_64(&me->next, (uint64_t)NULL); + store_32(&me->gate, 1); + + // publish my node as the new tail : + // mcs_node * pred = m_tail.exchange(me, std::mo_acq_rel); + mcs_node * pred = (mcs_node *)rmw_64(EXC, &m_tail, (uint64_t) me, (uint64_t) NULL); + if ( pred != NULL ) { + // (*1) race here + // unlock of pred can see me in the tail before I fill next + + // publish me to previous lock-holder : + store_64(&pred->next, (uint64_t)me); + + // (*2) pred not touched any more + + // now this is the spin - + // wait on predecessor setting my flag - + while ( true ) { + if (!load_32(&me->gate)) { + break; + } else { + ; + } + thrd_yield(); + } + } + } + + void unlock(guard * I) { + mcs_node * me = &(I->m_node); + + mcs_node * next = (mcs_node *)load_64(&me->next); + if ( next == NULL ) + { + mcs_node * tail_was_me = me; + //if ( m_tail.compare_exchange_strong( tail_was_me,NULL,std::mo_acq_rel) ) { + if (rmw_64(CAS, &m_tail, (uint64_t)tail_was_me, (uint64_t)NULL)) { + // got null in tail, mutex is unlocked + return; + } + + // (*1) catch the race : + while(true) { + next = (mcs_node *)load_64(&me->next); + if ( next != NULL ) { + break; + } else { + ; + } + thrd_yield(); + } + } + + // (*2) - store to next must be done, + // so no locker can be viewing my node any more + + // let next guy in : + store_32(&next->gate, 0); + } +}; + +struct mcs_mutex *mutex; +static uint32_t shared; + +void threadA(void *arg) +{ + mcs_mutex::guard g(mutex); + printf("store: %d\n", 17); + store_32(&shared, 17); + mutex->unlock(&g); + mutex->lock(&g); + printf("load: %u\n", load_32(&shared)); +} + +void threadB(void *arg) +{ + mcs_mutex::guard g(mutex); + printf("load: %u\n", load_32(&shared)); + mutex->unlock(&g); + mutex->lock(&g); + printf("store: %d\n", 17); + store_32(&shared, 17); +} + +int user_main(int argc, char **argv) +{ + thrd_t A; thrd_t B; + + mutex = new mcs_mutex(); + + thrd_create(&A, &threadA, NULL); + thrd_create(&B, &threadB, NULL); + thrd_join(A); + thrd_join(B); + return 0; +} diff --git a/clang/test/minimal-no-braces-if.c b/clang/test/minimal-no-braces-if.c new file mode 100644 index 0000000..22ad73d --- /dev/null +++ b/clang/test/minimal-no-braces-if.c @@ -0,0 +1,108 @@ +#include +#include +#include "libinterface.h" + +/* atomic */ int flag1; + +#define true 1 +#define false 0 +#define NULL 0 + +/* uint32_t */ int var = 0; + +void p0() { + MCID _mf1; int f1, t; + MC2_enterLoop(); + while (true) + { + _mf1=MC2_nextOpLoad(MCID_NODEP), f1 = load_32(&flag1); + MCID _br0; + if (!f1) + {_br0 = MC2_branchUsesID(_mf1, 1, 2, true); + break; +} else { _br0 = MC2_branchUsesID(_mf1, 0, 2, true); MC2_merge(_br0); + }} +MC2_exitLoop(); + +} + +void p1() { + MCID _mf1; int f1, t; + MC2_enterLoop(); + while (true) + { + _mf1=MC2_nextOpLoad(MCID_NODEP), f1 = load_32(&flag1); + MCID _br1; + if (!f1) + {_br1 = MC2_branchUsesID(_mf1, 1, 2, true); + break; +} else + {_br1 = MC2_branchUsesID(_mf1, 0, 2, true); + MC2_merge(_br1); + ;} + } +MC2_exitLoop(); + +} + +void p2() { + MCID _mf1; int f1, t; + MC2_enterLoop(); + while (true) + { + _mf1=MC2_nextOpLoad(MCID_NODEP), f1 = load_32(&flag1); + MCID _br2; + if (!f1) { + _br2 = MC2_branchUsesID(_mf1, 1, 2, true); + break; + } + } else { _br2 = MC2_branchUsesID(_mf1, 0, 2, true); MC2_merge(_br2); + } +MC2_exitLoop(); + +} + +void p3() { + MCID _mf1; int f1, t; + MC2_enterLoop(); + while (true) + { + _mf1=MC2_nextOpLoad(MCID_NODEP), f1 = load_32(&flag1); + MCID _br3; + if (!f1) { + _br3 = MC2_branchUsesID(_mf1, 1, 2, true); + break; + } else { + _br3 = MC2_branchUsesID(_mf1, 0, 2, true); + ; + MC2_merge(_br3); + } + } +MC2_exitLoop(); + +} + + +int user_main(int argc, char **argv) +{ + thrd_t a; + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, false); + + thrd_create(&a, p0, NULL); + thrd_join(a); + + return 0; +} + +void pf(MCID _mq, int q) { + // need to create a tmp variable etc + MCID _br4; + if (q) { + _br4 = MC2_branchUsesID(, 1, 2, true); + ; + MC2_merge(_br4); + } + else { _br4 = MC2_branchUsesID(, 0, 2, true); MC2_merge(_br4); + }} diff --git a/clang/test/minimal-no-braces-if_unannotated.c b/clang/test/minimal-no-braces-if_unannotated.c new file mode 100644 index 0000000..8104b6a --- /dev/null +++ b/clang/test/minimal-no-braces-if_unannotated.c @@ -0,0 +1,77 @@ +#include +#include +#include "libinterface.h" + +/* atomic */ int flag1; + +#define true 1 +#define false 0 +#define NULL 0 + +/* uint32_t */ int var = 0; + +void p0() { + int f1, t; + while (true) + { + f1 = load_32(&flag1); + if (!f1) + break; + } +} + +void p1() { + int f1, t; + while (true) + { + f1 = load_32(&flag1); + if (!f1) + break; + else + ; + } +} + +void p2() { + int f1, t; + while (true) + { + f1 = load_32(&flag1); + if (!f1) { + break; + } + } +} + +void p3() { + int f1, t; + while (true) + { + f1 = load_32(&flag1); + if (!f1) { + break; + } else { + ; + } + } +} + + +int user_main(int argc, char **argv) +{ + thrd_t a; + + store_32(&flag1, false); + + thrd_create(&a, p0, NULL); + thrd_join(a); + + return 0; +} + +void pf(int q) { + // need to create a tmp variable etc + if (q) { + ; + } +} diff --git a/clang/test/ms-queue-simple-offset.c b/clang/test/ms-queue-simple-offset.c new file mode 100644 index 0000000..f1ad3dd --- /dev/null +++ b/clang/test/ms-queue-simple-offset.c @@ -0,0 +1,209 @@ +#define PROBLEMSIZE 10 +#include +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue-simple.h" +#include "libinterface.h" + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads); +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val); +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal, MCID * retval); + +queue_t queue; + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads) { + MCID _fn0; struct node *newnode=malloc(sizeof (struct node)); + _fn0 = MC2_function(0, sizeof (newnode), newnode); + MC2_nextOpStoreOffset(_fn0, MC2_OFFSET(struct node *, value), MCID_NODEP); + store_32(&newnode->value, 0); + + MC2_nextOpStoreOffset(_fn0, MC2_OFFSET(struct node *, next), MCID_NODEP); + store_64(&newnode->next, (uintptr_t) NULL); + /* initialize queue */ + MC2_nextOpStoreOffset(_mq, MC2_OFFSET(queue_t *, head), _fn0); + store_64(&q->head, (uintptr_t) newnode); + + MC2_nextOpStoreOffset(_mq, MC2_OFFSET(queue_t *, tail), _fn0); + store_64(&q->tail, (uintptr_t) newnode); +} + +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val) { + MCID _mtail; struct node *tail; + MCID _fn1; struct node * node_ptr = malloc(sizeof(struct node)); + _fn1 = MC2_function(0, sizeof (node_ptr), node_ptr); + + MC2_nextOpStoreOffset(_fn1, MC2_OFFSET(struct node *, value), _mval); + store_32(&node_ptr->value, val); + + + MC2_nextOpStoreOffset(_fn1, MC2_OFFSET(struct node *, next), MCID_NODEP); + store_64(&node_ptr->next, (uintptr_t) NULL); + + MC2_enterLoop(); + while (true) { + + _mtail=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, tail)), tail = (struct node *) load_64(&q->tail); + struct node ** tail_ptr_next= &tail->next; + + MCID _mnext=MC2_nextOpLoadOffset(_fn2, MC2_OFFSET(struct node *, next)); + struct node * next = (struct node *) load_64(tail_ptr_next); + + MCID _mqtail; + _mqtail=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *,tail)); struct node * qtail = (struct node *) load_64(&q->tail); + + MCID _fn16; + int tqt = MC2_equals(_fn2, tail, _mqtail, qtail, &_fn16); + MCID _br0; + if (tqt) { + + _br0 = MC2_branchUsesID(_fn16, 1, 2, true); + + MCID _br1; + if (next) { + _br1 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_yield(); + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_mnext, 0, 2, true); + MCID _rmw0 = MC2_nextRMWOffset(_fn2, MC2_OFFSET(struct node *, next), _mnext, _fn1); + struct node * valread = (struct node *) rmw_64(CAS, tail_ptr_next, (uintptr_t) next, (uintptr_t) node_ptr); + MCID _fn17; + int vn = MC2_equals(_mnext, next, _rmw0, valread, &_fn17); + MCID _br1; + if (vn) { + _br1 = MC2_branchUsesID(_fn17, 1, 2, true); + break; + } else { _br1 = MC2_branchUsesID(_fn17, 0, 2, true); MC2_merge(_br1); + } + } + MCID _mnew_tailptr = MC2_nextOpLoadOffset(_fn2, MC2_OFFSET(struct node *, next)); + struct node * new_tailptr = (struct node *)load_64( tail_ptr_next); + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, _fn2, _mnew_tailptr); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) new_tailptr); + MC2_yield(); + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_fn16, 0, 2, true); + MC2_yield(); + MC2_merge(_br0); + } + } + MC2_exitLoop(); + + MCID _rmw2 = MC2_nextRMW(MCID_NODEP, _fn2, _fn1); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) node_ptr); +} + +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal) { + MC2_enterLoop(); + while (true) { + void * _p8 = &q->head; + MCID _mhead=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, head)); + struct node * head = (struct node *) load_64(_p8); + void * _p9 = &q->tail; + MCID _mtail=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, tail)); + struct node * tail = (struct node *) load_64(_p9); + void * _p10 = &head->next; + MCID _mnext = MC2_nextOpLoadOffset(_mhead, MC2_OFFSET(struct node *, next)); + struct node * next = (struct node *) load_64(_p10); + + void * _p11 = &q->head; + MCID _mload=MC2_nextOpLoadOffset(_mq, MC2_OFFSET(queue_t *, head)); + struct node * headr = (struct node *) load_64(_p11); + + MCID _mt; + int t = MC2_equals(_mhead, head, _mload, headr, &_mt); + MCID _br0; + + if (t) { + _br0 = MC2_branchUsesID(_mt, 1, 2, true); + + MCID _fn18; + int ht = MC2_equals(_mhead, head, _mtail, tail, &_fn18); + + MCID _br1; + + if (ht) { + _br1 = MC2_branchUsesID(_fn18, 1, 2, true); + + MCID _br2; + if (next) { + _br2 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_yield(); + MC2_merge(_br2); + } else { + _br2 = MC2_branchUsesID(_mnext, 0, 2, true); + MC2_exitLoop(); + return false; // NULL + } + MCID _rmw3 = MC2_nextRMW(MCID_NODEP, _mtail, _mnext); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) next); + MC2_yield(); + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_fn18, 0, 2, true); + void * nextval= &(next->value); + MCID _rVal = MC2_nextOpLoadOffset(_mnext, MC2_OFFSET(struct node *, value)); + *retVal = load_32(&next->value); + MCID _rmw4 = MC2_nextRMW(MCID_NODEP, _mhead, _mnext); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) next); + MCID _fn19; + int ohh = MC2_equals(_mhead, head, _rmw4, old_head, &_fn19); + MCID _br6; + + if (ohh) { + _br6 = MC2_branchUsesID(_fn19, 1, 2, true); + MC2_exitLoop(); + return true; + } else { + _br6 = MC2_branchUsesID(_fn19, 0, 2, true); + MC2_yield(); + MC2_merge(_br6); + } + MC2_merge(_br1); + } + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_mt, 0, 2, true); + MC2_yield(); + MC2_merge(_br0); + } + } + MC2_exitLoop(); +} + +/* ms-queue-main */ +bool succ1, succ2; + +static void e(void *p) { + int i; + for(i=0;i<4;i++) + enqueue(MCID_NODEP, &queue, MCID_NODEP, 1); +} + +static void d(void *p) { + unsigned int val; + int i; + for(i=0;i +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue-simple.h" +#include "libinterface.h" + +void init_queue(queue_t *q, int num_threads); +void enqueue(queue_t *q, unsigned int val); +bool dequeue(queue_t *q, unsigned int *retVal); + +queue_t queue; + +void init_queue(queue_t *q, int num_threads) { + struct node *newnode=malloc(sizeof (struct node)); + store_32(&newnode->value, 0); + + store_64(&newnode->next, (uintptr_t) NULL); + /* initialize queue */ + store_64(&q->head, (uintptr_t) newnode); + + store_64(&q->tail, (uintptr_t) newnode); +} + +void enqueue(queue_t *q, unsigned int val) { + struct node *tail; + struct node * node_ptr = malloc(sizeof(struct node)); + + store_32(&node_ptr->value, val); + + + store_64(&node_ptr->next, (uintptr_t) NULL); + + while (true) { + + tail = (struct node *) load_64(&q->tail); + struct node ** tail_ptr_next= & tail->next; + + struct node * next = (struct node *) load_64(tail_ptr_next); + + struct node * qtail = (struct node *) load_64(&q->tail); + + if (tail == qtail) { + if (next) { + MC2_yield(); + } else { + struct node * valread = (struct node *) rmw_64(CAS, tail_ptr_next, (uintptr_t) next, (uintptr_t) node_ptr); + if (next == valread) { + break; + } + } + struct node * new_tailptr = (struct node *)load_64( tail_ptr_next); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) new_tailptr); + MC2_yield(); + } else { + MC2_yield(); + } + } + + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) node_ptr); +} + +bool dequeue(queue_t *q, unsigned int *retVal) { + while (true) { + struct node * head = (struct node *) load_64(&q->head); + struct node * tail = (struct node *) load_64(&q->tail); + struct node * next = (struct node *) load_64(&head->next); + + struct node * headr = (struct node *) load_64(&q->head); + + if (head == headr) { + + if (head == tail) { + + if (next) { + MC2_yield(); + } else { + return false; // NULL + } + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) next); + MC2_yield(); + } else { + void * nextval= &(next->value); + *retVal = load_32(&next->value); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) next); + if (head == old_head) { + MC2_exitLoop(); + return true; + } else { + MC2_yield(); + } + } + } else { + MC2_yield(); + } + } +} + +/* ms-queue-main */ +bool succ1, succ2; + +static void e(void *p) { + int i; + for(i=0;i<4;i++) + enqueue(&queue, 1); +} + +static void d(void *p) { + unsigned int val; + int i; + for(i=0;i +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue-simple.h" +#include "libinterface.h" + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads); +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val); +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal); + +queue_t queue; + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads) { + MCID _fn13; struct node *newnode=malloc(sizeof (struct node)); + _fn13 = MC2_function(0, sizeof (newnode), newnode); + + void * _p0 = &newnode->value; + MCID _fn0 = MC2_function(1, MC2_PTR_LENGTH, _p0, _fn13); MC2_nextOpStore(_fn0, MCID_NODEP); + store_32(_p0, 0); + + + void * _p1 = &newnode->next; + MCID _fn1 = MC2_function(1, MC2_PTR_LENGTH, _p1, _fn13); MC2_nextOpStore(_fn1, MCID_NODEP); + store_64(_p1, (uintptr_t) NULL); + /* initialize queue */ + + void * _p2 = &q->head; + MCID _fn2 = MC2_function(1, MC2_PTR_LENGTH, _p2, _mq); MC2_nextOpStore(_fn2, _fn13); + store_64(_p2, (uintptr_t) newnode); + + + void * _p3 = &q->tail; + MCID _fn3 = MC2_function(1, MC2_PTR_LENGTH, _p3, _mq); MC2_nextOpStore(_fn3, _fn13); + store_64(_p3, (uintptr_t) newnode); +} + +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val) { + MCID _fn15; struct node *tail; + MCID _fn14; struct node * node_ptr = malloc(sizeof(struct node)); + _fn14 = MC2_function(0, sizeof (node_ptr), node_ptr); + + void * _p4 = &node_ptr->value; + MCID _fn4 = MC2_function(1, MC2_PTR_LENGTH, _p4, _fn14); MC2_nextOpStore(_fn4, _mval); + store_32(_p4, val); + + + void * _p5 = &node_ptr->next; + MCID _fn5 = MC2_function(1, MC2_PTR_LENGTH, _p5, _fn14); MC2_nextOpStore(_fn5, MCID_NODEP); + store_64(_p5, (uintptr_t) NULL); + + MC2_enterLoop(); + while (true) { + + void * _p6 = &q->tail; + MCID _fn6 = MC2_function(1, MC2_PTR_LENGTH, _p6, _mq); _fn15=MC2_nextOpLoad(_fn6), tail = (struct node *) load_64(_p6); + _fn15 = MC2_function(1, sizeof (tail), tail, _fn15); + MCID _fn16; struct node ** tail_ptr_next= & tail->next; + _fn16 = MC2_function(1, sizeof (tail_ptr_next), tail_ptr_next, _fn15); + + MCID _mnext; _mnext=MC2_nextOpLoad(_fn16); struct node * next = (struct node *) load_64(tail_ptr_next); + + MCID _mqtail; + void * _p7 = &q->tail; + MCID _fn7 = MC2_function(1, MC2_PTR_LENGTH, _p7, _mq); _mqtail=MC2_nextOpLoad(_fn7); struct node * qtail = (struct node *) load_64(_p7); + MCID _fn17; int tqt = (tail == qtail); + _fn17 = MC2_function(2, sizeof (tqt), tqt, _fn15, _mqtail); + MCID _br0; + if (tqt) { + + MCID _br1; + _br0 = MC2_branchUsesID(_fn17, 1, 2, true); + if (next) { + _br1 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_yield(); + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_mnext, 0, 2, true); + MCID _rmw0 = MC2_nextRMW(_fn16, _mnext, _fn14); + struct node * valread = (struct node *) rmw_64(CAS, tail_ptr_next, (uintptr_t) next, (uintptr_t) node_ptr); + MCID _fn18; int vn = (valread == next); + _fn18 = MC2_function(2, sizeof (vn), vn, _mnext, _rmw0); + MCID _br2; + if (vn) { + _br2 = MC2_branchUsesID(_fn18, 1, 2, true); + break; + } else { + _br2 = MC2_branchUsesID(_fn18, 0, 2, true); + MC2_yield(); + MC2_merge(_br2); + } + MC2_merge(_br1); + } + MCID _mnew_tailptr; _mnew_tailptr=MC2_nextOpLoad(_fn16); struct node * new_tailptr = (struct node *)load_64( tail_ptr_next); + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, _fn15, _mnew_tailptr); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) new_tailptr); + MC2_yield(); + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_fn17, 0, 2, true); + MC2_yield(); + MC2_merge(_br0); + } + } +MC2_exitLoop(); + + MCID _rmw2 = MC2_nextRMW(MCID_NODEP, _fn15, _fn14); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) node_ptr); +} + +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal) { + MC2_enterLoop(); + while (true) { + MCID _mhead; + void * _p8 = &q->head; + MCID _fn8 = MC2_function(1, MC2_PTR_LENGTH, _p8, _mq); _mhead=MC2_nextOpLoad(_fn8); struct node * head = (struct node *) load_64(_p8); + MCID _mtail; + void * _p9 = &q->tail; + MCID _fn9 = MC2_function(1, MC2_PTR_LENGTH, _p9, _mq); _mtail=MC2_nextOpLoad(_fn9); struct node * tail = (struct node *) load_64(_p9); + MCID _mnext; + void * _p10 = &head->next; + MCID _fn10 = MC2_function(1, MC2_PTR_LENGTH, _p10, _mhead); _mnext=MC2_nextOpLoad(_fn10); struct node * next = (struct node *) load_64(_p10); + + MCID _mt; + void * _p11 = &q->head; + MCID _fn11 = MC2_function(1, MC2_PTR_LENGTH, _p11, _mq); _mt=MC2_nextOpLoad(_fn11); int t = ((struct node *) load_64(_p11)) == head; + MCID _br3; + if (t) { + MCID _fn19; _br3 = MC2_branchUsesID(_mt, 1, 2, true); + int ht = (head == tail); + _fn19 = MC2_function(2, sizeof (ht), ht, _mhead, _mtail); + MCID _br4; + if (ht) { + + MCID _br5; + _br4 = MC2_branchUsesID(_fn19, 1, 2, true); + if (next) { + _br5 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_yield(); + MC2_merge(_br5); + } else { + _br5 = MC2_branchUsesID(_mnext, 0, 2, true); + MC2_exitLoop(); + return false; // NULL + } + MCID _rmw3 = MC2_nextRMW(MCID_NODEP, _mtail, _mnext); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) next); + MC2_yield(); + MC2_merge(_br4); + } else { + MCID _mnv; _br4 = MC2_branchUsesID(_fn19, 0, 2, true); + + void * _p12 = &next->value; + MCID _fn12 = MC2_function(1, MC2_PTR_LENGTH, _p12, _mnext); _mnv=MC2_nextOpLoad(_fn12); int nv = load_32(_p12); + MC2_nextOpStore(_mretVal, _mnv); + store_32(retVal, nv); + MCID _rmw4 = MC2_nextRMW(MCID_NODEP, _mhead, _mnext); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) next); + MCID _fn20; int ohh = (old_head == head); + _fn20 = MC2_function(2, sizeof (ohh), ohh, _mhead, _rmw4); + MCID _br6; + if (ohh) { + _br6 = MC2_branchUsesID(_fn20, 1, 2, true); + MC2_exitLoop(); + return true; + } else { + _br6 = MC2_branchUsesID(_fn20, 0, 2, true); + MC2_yield(); + MC2_merge(_br6); + } + MC2_merge(_br4); + } + MC2_merge(_br3); + } else { + _br3 = MC2_branchUsesID(_mt, 0, 2, true); + MC2_yield(); + MC2_merge(_br3); + } + } +MC2_exitLoop(); + +} + +/* ms-queue-main */ +bool succ1, succ2; + +static void e(void *p) { + int i; + MC2_enterLoop(); + for(i=0;i<2;i++) + enqueue(MCID_NODEP, &queue, MCID_NODEP, 1); +MC2_exitLoop(); + +} + +static void d(void *p) { + unsigned int val; + int i; + MC2_enterLoop(); + for(i=0;i<2;i++) + dequeue(MCID_NODEP, &queue, MCID_NODEP, &val); +MC2_exitLoop(); + +} + +int user_main(int argc, char **argv) +{ + init_queue(MCID_NODEP, &queue, MCID_NODEP, 2); + + thrd_t t1,t2; + thrd_create(&t1, e, NULL); + thrd_create(&t2, d, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} diff --git a/clang/test/ms-queue-simple.h b/clang/test/ms-queue-simple.h new file mode 100644 index 0000000..9f7f11c --- /dev/null +++ b/clang/test/ms-queue-simple.h @@ -0,0 +1,15 @@ +typedef struct node { + unsigned int value; + struct node * next; +} node_t; + +typedef struct { + struct node * head; + struct node * tail; +} queue_t; + +//void init_queue(queue_t *q, int num_threads); +//void enqueue(queue_t *q, unsigned int val); +//bool dequeue(queue_t *q, unsigned int *retVal); +int get_thread_num(); + diff --git a/clang/test/ms-queue-simple_manual.c b/clang/test/ms-queue-simple_manual.c new file mode 100644 index 0000000..e905972 --- /dev/null +++ b/clang/test/ms-queue-simple_manual.c @@ -0,0 +1,201 @@ +#include +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue-simple.h" +#include "libinterface.h" + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads); +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val); +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal); + +queue_t queue; + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads) { + MCID _fn6; struct node *newnode=malloc(sizeof (struct node)); + + void * _p0 = &newnode->value; + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(_p0, 0); + + + void * _p1 = &newnode->next; + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_64(_p1, (uintptr_t) NULL); + /* initialize queue */ + + void * _p2 = &q->head; + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_64(_p2, (uintptr_t) newnode); + + + void * _p3 = &q->tail; + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_64(_p3, (uintptr_t) newnode); +} + +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val) { + MCID _fn8; struct node *tail; + MCID _fn7; struct node * node_ptr = malloc(sizeof(struct node)); + _fn7 = MC2_function(0, sizeof (node_ptr), node_ptr); + + void * _p4 = &node_ptr->value; + MCID _fn4 = MC2_function(1, MC2_PTR_LENGTH, _p4, _fn7); + MC2_nextOpStore(_fn4, _mval); + store_32(_p4, val); + + + void * _p5 = &node_ptr->next; + MCID _fn5 = MC2_function(1, MC2_PTR_LENGTH, _p5, _fn7); + MC2_nextOpStore(_fn5, MCID_NODEP); + store_64(_p5, (uintptr_t) NULL); + + MC2_enterLoop(); + while (true) { + _fn8=MC2_nextOpLoad(MCID_NODEP), tail = (struct node *) load_64(&q->tail); + + MCID _fn9; struct node ** tail_ptr_next= & tail->next; + _fn9 = MC2_function(1, sizeof (tail_ptr_next), tail_ptr_next, _fn8); + + MCID _mnext; _mnext=MC2_nextOpLoad(_fn9); struct node * next = (struct node *) load_64(tail_ptr_next); + + MCID _mqtail; _mqtail=MC2_nextOpLoad(MCID_NODEP); struct node * qtail = (struct node *) load_64(&q->tail); + + bool comp = (tail==qtail); + MCID _comp = MC2_function(2, 4, comp, _fn8, _mqtail); + MCID _br0; + if (comp) { + _br0 = MC2_branchUsesID(_comp, 1, 2, true); + + MCID _br1; + if (next) { + _br1 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_mnext, 0, 2, true); + MCID _rmw0 = MC2_nextRMW(_fn9, _mnext, _fn7); + struct node * valread = (struct node *) rmw_64(CAS, tail_ptr_next, (uintptr_t) next, (uintptr_t) node_ptr); + bool comp2=(valread == next); + MCID _comp2 = MC2_function(2, 4, comp2, _rmw0, _mnext); + MCID _br2; + if (comp2) { + _br2 = MC2_branchUsesID(_comp2, 1, 2, true); + break; + } else { + _br2 = MC2_branchUsesID(_comp2, 0, 2, true); + MC2_merge(_br2); + } + MC2_merge(_br1); + } + MCID _mnew_tailptr; _mnew_tailptr=MC2_nextOpLoad(_fn9); struct node * new_tailptr = (struct node *)load_64( tail_ptr_next); + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, _fn8, _mnew_tailptr); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) new_tailptr); + MC2_yield(); + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_comp, 0, 2, true); + MC2_yield(); + MC2_merge(_br0); + } + } + MC2_exitLoop(); + + MCID _rmw2 = MC2_nextRMW(MCID_NODEP, _fn8, _fn7); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) node_ptr); +} + +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal) { + MC2_enterLoop(); + while (true) { + MCID _mhead; _mhead=MC2_nextOpLoad(MCID_NODEP); struct node * head = (struct node *) load_64(&q->head); + MCID _mtail; _mtail=MC2_nextOpLoad(MCID_NODEP); struct node * tail = (struct node *) load_64(&q->tail); + MCID _mnext; _mnext=MC2_nextOpLoad(MCID_NODEP); struct node * next = (struct node *) load_64(&head->next); + + MCID _mt; _mt=MC2_nextOpLoad(MCID_NODEP); int t = ((struct node *) load_64(&q->head)) == head; + MCID _br0; + + if (t) { + _br0 = MC2_branchUsesID(_mt, 1, 2, true); + + bool comp = head == tail; + MCID _mcomp = MC2_function(2, 4, comp, _mhead, _mtail); + MCID _br1; + + if (comp) { + _br1 = MC2_branchUsesID(_mcomp, 1, 2, true); + MCID _br2; + if (next) { + _br2 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_merge(_br2); + } else { + _br2 = MC2_branchUsesID(_mnext, 0, 2, true); + MC2_exitLoop(); + return false; // NULL + } + MCID _rmw3 = MC2_nextRMW(MCID_NODEP, _mtail, _mnext); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) next); + MC2_yield(); + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_mcomp, 0, 2, true); + void * nextval= &(next->value); + MCID _mnextval = MC2_function(1, MC2_PTR_LENGTH, nextval, _mnext); + MCID _rVal = MC2_nextOpLoad(_mnextval); + *retVal = load_32(&next->value); + MCID _rmw4 = MC2_nextRMW(MCID_NODEP, _mhead, _mnext); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) next); + bool comp1 = old_head == head; + MCID _mcomp1 = MC2_function(2, 4, comp1, _rmw4, _mhead); + MCID _br2; + + if (comp1) { + _br2 = MC2_branchUsesID(_mcomp1, 1, 2, true); + MC2_exitLoop(); + return true; + } else { + _br2 = MC2_branchUsesID(_mcomp1, 0, 2, true); + MC2_yield(); + MC2_merge(_br2); + } + MC2_merge(_br1); + } + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_mt, 0, 2, true); + MC2_merge(_br0); + } + } + MC2_exitLoop(); + +} + +/* ms-queue-main */ +bool succ1, succ2; + +static void e(void *p) { + enqueue(MCID_NODEP, &queue, MCID_NODEP, 1); +} + +static void d(void *p) { + unsigned int val; + dequeue(MCID_NODEP, &queue, MCID_NODEP, &val); +} + +int user_main(int argc, char **argv) +{ + init_queue(MCID_NODEP, &queue, MCID_NODEP, 2); + + thrd_t t1,t2; + thrd_create(&t1, e, NULL); + thrd_create(&t2, d, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} diff --git a/clang/test/ms-queue-simple_unannotated.c b/clang/test/ms-queue-simple_unannotated.c new file mode 100644 index 0000000..97defd0 --- /dev/null +++ b/clang/test/ms-queue-simple_unannotated.c @@ -0,0 +1,131 @@ +#include +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue-simple.h" +#include "libinterface.h" + +void init_queue(queue_t *q, int num_threads); +void enqueue(queue_t *q, unsigned int val); +bool dequeue(queue_t *q, unsigned int *retVal); + +queue_t queue; + +void init_queue(queue_t *q, int num_threads) { + struct node *newnode=malloc(sizeof (struct node)); + store_32(&newnode->value, 0); + + store_64(&newnode->next, (uintptr_t) NULL); + /* initialize queue */ + store_64(&q->head, (uintptr_t) newnode); + + store_64(&q->tail, (uintptr_t) newnode); +} + +void enqueue(queue_t *q, unsigned int val) { + struct node *tail; + struct node * node_ptr = malloc(sizeof(struct node)); + store_32(&node_ptr->value, val); + + store_64(&node_ptr->next, (uintptr_t) NULL); + + while (true) { + tail = (struct node *) load_64(&q->tail); + struct node ** tail_ptr_next= & tail->next; + + struct node * next = (struct node *) load_64(tail_ptr_next); + + struct node * qtail = (struct node *) load_64(&q->tail); + int tqt = (tail == qtail); + if (tqt) { + + if (next) { + MC2_yield(); + } else { + struct node * valread = (struct node *) rmw_64(CAS, tail_ptr_next, (uintptr_t) next, (uintptr_t) node_ptr); + int vn = (valread == next); + if (vn) { + break; + } else { + MC2_yield(); + } + } + struct node * new_tailptr = (struct node *)load_64( tail_ptr_next); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) new_tailptr); + MC2_yield(); + } else { + MC2_yield(); + } + } + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) node_ptr); +} + +bool dequeue(queue_t *q, unsigned int *retVal) { + while (true) { + struct node * head = (struct node *) load_64(&q->head); + struct node * tail = (struct node *) load_64(&q->tail); + struct node * next = (struct node *) load_64(&head->next); + + int t = ((struct node *) load_64(&q->head)) == head; + if (t) { + int ht = (head == tail); + if (ht) { + + if (next) { + MC2_yield(); + } else { + return false; // NULL + } + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) next); + MC2_yield(); + } else { + int nv = load_32(&next->value); + store_32(retVal, nv); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) next); + int ohh = (old_head == head); + if (ohh) { + return true; + } else { + MC2_yield(); + } + } + } else { + MC2_yield(); + } + } +} + +/* ms-queue-main */ +bool succ1, succ2; + +static void e(void *p) { + int i; + for(i=0;i<2;i++) + enqueue(&queue, 1); +} + +static void d(void *p) { + unsigned int val; + int i; + for(i=0;i<2;i++) + dequeue(&queue, &val); +} + +int user_main(int argc, char **argv) +{ + init_queue(&queue, 2); + + thrd_t t1,t2; + thrd_create(&t1, e, NULL); + thrd_create(&t2, d, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} diff --git a/clang/test/ms-queue_unannotated.c b/clang/test/ms-queue_unannotated.c new file mode 100644 index 0000000..1b12eca --- /dev/null +++ b/clang/test/ms-queue_unannotated.c @@ -0,0 +1,132 @@ +#include +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue.h" +#include "libinterface.h" + +void init_queue(queue_t *q, int num_threads); +void enqueue(queue_t *q, unsigned int val); +bool dequeue(queue_t *q, unsigned int *retVal); + +void init_queue(queue_t *q, int num_threads) { + int i, j; + struct node *newnode=malloc(sizeof (struct node)); + store_32(&newnode->value, 0); + + store_64(&newnode->next, (uintptr_t) MAKE_POINTER(NULL, 0LL)); + /* initialize queue */ + store_64(&q->head, (uintptr_t) MAKE_POINTER(newnode, 0LL)); + + store_64(&q->tail, (uintptr_t) MAKE_POINTER(newnode, 0LL)); +} + +void enqueue(queue_t *q, unsigned int val) { + struct node *tail; + struct node * node_ptr = malloc(sizeof(struct node)); + store_32(&node_ptr->value, val); + + store_64(&node_ptr->next, (uintptr_t) MAKE_POINTER(NULL, GET_COUNT(1))); + + while (true) { + tail = (struct node *) load_64(&q->tail); + struct node ** tail_ptr_next= & GET_PTR(tail)->next; + + struct node * next = (struct node *) load_64(tail_ptr_next); + + struct node * qtail = (struct node *) load_64(&q->tail); + int tqt = (tail == qtail); + if (tqt) { + struct node *next_ptr=GET_PTR(next); + + int npn = (next_ptr == NULL); + if (npn) { + struct node * new_node = MAKE_POINTER(node_ptr, GET_COUNT(next) +1); + struct node * valread = (struct node *) rmw_64(CAS, tail_ptr_next, (uintptr_t) next, (uintptr_t) new_node); + int vn = (valread == next); + if (vn) { + break; + } else { + MC2_yield(); + } + } else { + MC2_yield(); + } + struct node * new_tailptr = GET_PTR(load_64( tail_ptr_next)); + struct node * newtail = MAKE_POINTER(new_tailptr, GET_COUNT(tail) + 1); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) newtail); + MC2_yield(); + } else { + MC2_yield(); + } + } + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t)MAKE_POINTER(node_ptr, GET_COUNT(tail) + 1)); +} + +bool dequeue(queue_t *q, unsigned int *retVal) { + while (true) { + struct node * head = (struct node *) load_64(&q->head); + struct node * tail = (struct node *) load_64(&q->tail); + struct node * next = (struct node *) load_64(&(GET_PTR(head)->next)); + + int t = ((struct node *) load_64(&q->head)) == head; + if (t) { + if (GET_PTR(head) == GET_PTR(tail)) { + + if (GET_PTR(next) == NULL) { + return false; // NULL + } else { + MC2_yield(); + } + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) MAKE_POINTER(GET_PTR(next), GET_COUNT(tail) + 1)); + MC2_yield(); + } else { + int nv = load_32(&GET_PTR(next)->value); + store_32(retVal, nv); + struct node * nh = MAKE_POINTER(GET_PTR(next), GET_COUNT(head)+1); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) nh); + if (old_head == head) { + return true; + } else { + MC2_yield(); + } + } + } + } +} + +/* ms-queue-main */ +static queue_t queue; +bool succ1, succ2; + +static void e(void *p) { + int i; + for(i=0;i<2;i++) + enqueue(&queue, 1); +} + +static void d(void *p) { + unsigned int val; + int i; + for(i=0;i<2;i++) + dequeue(&queue, &val); +} + +int user_main(int argc, char **argv) +{ + init_queue(&queue, 2); + + thrd_t t1,t2; + thrd_create(&t1, e, NULL); + thrd_create(&t2, d, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} diff --git a/clang/test/seqlock.c b/clang/test/seqlock.c new file mode 100644 index 0000000..4e8f708 --- /dev/null +++ b/clang/test/seqlock.c @@ -0,0 +1,135 @@ +#include +#include + +#include "threads.h" +#include "libinterface.h" +#define PROBLEMSIZE 100 + +/*atomic_*/ int _seq; +/*atomic_*/ int _data; + +void seqlock_init() { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_seq, 0); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_data, 10); +} + +int seqlock_read(MCID * retval) { + MCID _mres; int res; + MCID _mold_seq; _mold_seq=MC2_nextOpLoad(MCID_NODEP); int old_seq = load_32(&_seq); + + MCID _br0; + + int _cond0 = old_seq % 2 == 1; + MCID _cond0_m = MC2_function_id(1, 1, sizeof(_cond0), _cond0, _mold_seq); + if (_cond0) { + _br0 = MC2_branchUsesID(_cond0_m, 1, 2, true); + res = -1; + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_cond0_m, 0, 2, true); + _mres=MC2_nextOpLoad(MCID_NODEP), res = load_32(&_data); + MCID _mseq; _mseq=MC2_nextOpLoad(MCID_NODEP); int seq = load_32(&_seq); + + MCID _br1; + + MCID _cond1_m; + + int _cond1 = MC2_equals(_mseq, seq, _mold_seq, old_seq, &_cond1_m); + if (_cond1) {_br1 = MC2_branchUsesID(_cond1_m, 1, 2, true); + // relaxed + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_cond1_m, 0, 2, true); + res = -1; + MC2_merge(_br1); + } + MC2_merge(_br0); + } + *retval = _mres; + return res; +} + +int seqlock_write(MCID _mnew_data, int new_data, MCID * retval) { + MCID _mold_seq; _mold_seq=MC2_nextOpLoad(MCID_NODEP); int old_seq = load_32(&_seq); + int res; + MCID _br2; + + int _cond2 = old_seq % 2 == 1; + MCID _cond2_m = MC2_function_id(2, 1, sizeof(_cond2), _cond2, _mold_seq); + if (_cond2) { + _br2 = MC2_branchUsesID(_cond2_m, 1, 2, true); + res = 0; + MC2_merge(_br2); + } else { + MCID _fn0; _br2 = MC2_branchUsesID(_cond2_m, 0, 2, true); + int new_seq = old_seq + 1; + _fn0 = MC2_function_id(3, 1, sizeof (new_seq), new_seq, _mold_seq); + MCID _rmw0 = MC2_nextRMW(MCID_NODEP, _mold_seq, _fn0); + int cas_value = rmw_32(CAS, &_seq, old_seq, new_seq); + MCID _br3; + + MCID _cond3_m; + + int _cond3 = MC2_equals(_rmw0, cas_value, _mold_seq, old_seq, &_cond3_m); + if (_cond3) { + _br3 = MC2_branchUsesID(_cond3_m, 1, 2, true); + MC2_nextOpStore(MCID_NODEP, _mnew_data); + store_32(&_data, new_data); + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &_seq, /*dummy */0, 1); + res = 1; + MC2_merge(_br3); + } else { + _br3 = MC2_branchUsesID(_cond3_m, 0, 2, true); + res = 0; + MC2_merge(_br3); + } + MC2_merge(_br2); + } + *retval = MCID_NODEP; + return res; +} + +static void a(void *obj) { + MC2_enterLoop(); + for (int i = 0; i < PROBLEMSIZE; i++) + seqlock_write(30); +MC2_exitLoop(); + +} + +static void b(void *obj) { + int r1; + MC2_enterLoop(); + for (int i = 0; i < PROBLEMSIZE; i++) + MCID _rv0; + r1 = seqlock_read(&_rv0); +MC2_exitLoop(); + +} + +static void c(void *obj) { + int r1; + MC2_enterLoop(); + for (int i = 0; i < PROBLEMSIZE; i++) + MCID _rv1; + r1 = seqlock_read(&_rv1); +MC2_exitLoop(); + +} + +int user_main(int argc, char **argv) { + thrd_t t1; thrd_t t2; thrd_t t3; + seqlock_init(); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + thrd_create(&t3, (thrd_start_t)&c, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + return 0; +} diff --git a/clang/test/seqlock_raw_unannotated.c b/clang/test/seqlock_raw_unannotated.c new file mode 100644 index 0000000..f087751 --- /dev/null +++ b/clang/test/seqlock_raw_unannotated.c @@ -0,0 +1,74 @@ +#include +#include +#include + +#include +#include "threads.h" +#include "libinterface.h" + +/*atomic_*/ int _seq; +/*atomic_*/ int _data; + +void seqlock_init() { + store_32(&_seq, 0); + store_32(&_data, 0); +} + +int seqlock_read() { + while (true) { + int old_seq = load_32(&_seq); + + if (old_seq % 2 == 1) { + } else { + int res = load_32(&_data); + int seq = load_32(&_seq); + + if (seq == old_seq) { // relaxed + return res; + } + } + } +} + +void seqlock_write(int new_data) { + while (true) { + int old_seq = load_32(&_seq); + if (old_seq % 2 == 1) { + } else { + int new_seq = old_seq + 1; + int cas_value = rmw_32(CAS, &_seq, old_seq, new_seq); + if (old_seq == cas_value) { + break; + } + } + } + store_32(&_data, new_data); + + rmw_32(ADD, &_seq, /*dummy */0, 1); +} + +static void a(void *obj) { + seqlock_write(3); +} + +static void b(void *obj) { + seqlock_write(2); +} + +static void c(void *obj) { + int r1 = seqlock_read(); +} + +int user_main(int argc, char **argv) { + thrd_t t1, t2, t3; + seqlock_init(); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + thrd_create(&t3, (thrd_start_t)&c, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + return 0; +} diff --git a/clang/test/seqlock_unannotated.c b/clang/test/seqlock_unannotated.c new file mode 100644 index 0000000..2cdd353 --- /dev/null +++ b/clang/test/seqlock_unannotated.c @@ -0,0 +1,82 @@ +#include +#include + +#include "threads.h" +#include "libinterface.h" +#define PROBLEMSIZE 100 + +/*atomic_*/ int _seq; +/*atomic_*/ int _data; + +void seqlock_init() { + store_32(&_seq, 0); + store_32(&_data, 10); +} + +int seqlock_read() { + int res; + int old_seq = load_32(&_seq); + + if (old_seq % 2 == 1) { + res = -1; + } else { + res = load_32(&_data); + int seq = load_32(&_seq); + + if (seq == old_seq) { // relaxed + } else { + res = -1; + } + } + return res; +} + +int seqlock_write(int new_data) { + int old_seq = load_32(&_seq); + int res; + if (old_seq % 2 == 1) { + res = 0; + } else { + int new_seq = old_seq + 1; + int cas_value = rmw_32(CAS, &_seq, old_seq, new_seq); + if (cas_value == old_seq) { + store_32(&_data, new_data); + rmw_32(ADD, &_seq, /*dummy */0, 1); + res = 1; + } else { + res = 0; + } + } + return res; +} + +static void a(void *obj) { + for (int i = 0; i < PROBLEMSIZE; i++) + seqlock_write(30); +} + +static void b(void *obj) { + int r1; + for (int i = 0; i < PROBLEMSIZE; i++) + r1 = seqlock_read(); +} + +static void c(void *obj) { + int r1; + for (int i = 0; i < PROBLEMSIZE; i++) + r1 = seqlock_read(); +} + +int user_main(int argc, char **argv) { + thrd_t t1; thrd_t t2; thrd_t t3; + seqlock_init(); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + thrd_create(&t3, (thrd_start_t)&c, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + return 0; +} diff --git a/clang/test/spsc-queue_unannotated.cc b/clang/test/spsc-queue_unannotated.cc new file mode 100644 index 0000000..87e6c1d --- /dev/null +++ b/clang/test/spsc-queue_unannotated.cc @@ -0,0 +1,91 @@ +#include +#include "libinterface.h" + +struct node { + // atomic next; + struct node * next; + int data; + + node(int d = 0) : data(d) { + store_64(&next, 0); + } +}; + + +class spsc_queue { +public: + spsc_queue() + { + node* n = new node (); + head = n; + tail = n; + } + + ~spsc_queue() + { + } + + void enqueue(int data) + { + node* n = new node(data); + store_64(&head->next, (uint64_t)n); + head = n; + } + + int dequeue() { + int data=0; + while (0 == data) { + data = try_dequeue(); + } + return data; + } + +private: + + struct node* head; + struct node* tail; + + int try_dequeue() { + node* t = tail; + node* n = (node *)load_64(&t->next); + if (0 == n) { + return 0; + } + int data = load_64(&n->data); + tail = n; + return data; + } +}; + + +spsc_queue *q; + +void thread(unsigned thread_index) +{ + for (int i = 0; i < 40; i++) { + if (0 == thread_index) + { + q->enqueue(11); + } + else + { + int d = q->dequeue(); + // RL_ASSERT(11 == d); + } + } +} + +int user_main(int argc, char **argv) +{ + thrd_t A; thrd_t B; + + q = new spsc_queue(); + + thrd_create(&A, (thrd_start_t)&thread, (void *)0); + thrd_create(&B, (thrd_start_t)&thread, (void *)1); + thrd_join(A); + thrd_join(B); + + + return 0; +} diff --git a/clang/test/userprog2_unannotated.c b/clang/test/userprog2_unannotated.c new file mode 100644 index 0000000..fcf55d6 --- /dev/null +++ b/clang/test/userprog2_unannotated.c @@ -0,0 +1,61 @@ +#include +#include +#include + +#include "libinterface.h" + +int x; +int y; +int gr1; +int gr2; + +static void a(void *obj) +{ + int r1=load_32(&y); + if (r1) { + r1=42; + } else { + r1=0; + } + + store_32(&x, r1); + + store_32(&gr1, r1); + printf("r1=%d\n",r1); +} + +static void b(void *obj) +{ + int r2=load_32(&x); + store_32(&y, 42); + + store_32(&gr2, r2); + printf("r2=%d\n",r2); +} + +int user_main(int argc, char **argv) +{ + thrd_t t1, t2; + + store_32(&x, 0); + store_32(&y, 0); + + printf("Main thread: creating 2 threads\n"); + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + + thrd_join(t1); + thrd_join(t2); + printf("Main thread is finished\n"); + int lgr1=load_32(&gr1); + + int lgr2=load_32(&gr2); + if (lgr1==42) { + if (lgr2==42) { + } else { + } + } else { + } + + return 0; +} diff --git a/clang/test/userprog_unannotated.c b/clang/test/userprog_unannotated.c new file mode 100644 index 0000000..de2eb1c --- /dev/null +++ b/clang/test/userprog_unannotated.c @@ -0,0 +1,55 @@ +#include +#include +#include "threads.h" +#include "libinterface.h" + +int x; +int y; +int gr1; +int gr2; + +static void a(void *obj) +{ + int r1 = load_32(&y); + store_32(&x, r1); + + store_32(&gr1, r1); + printf("r1=%d\n",r1); +} + +static void b(void *obj) +{ + int r2=load_32(&x); + store_32(&y, 42); + + store_32(&gr2, r2); + printf("r2=%d\n",r2); +} + +int user_main(int argc, char **argv) +{ + thrd_t t1, t2; + + store_32(&x, 0); + store_32(&y, 0); + + printf("Main thread: creating 2 threads\n"); + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + + thrd_join(t1); + thrd_join(t2); + printf("Main thread is finished\n"); + int lgr1=load_32(&gr1); + + int lgr2=load_32(&gr2); + if (lgr1==42) { + if (lgr2==42) + ; + else { + } + } else + ; + + return 0; +} diff --git a/clang/test/various-loads.c b/clang/test/various-loads.c new file mode 100644 index 0000000..88b65f6 --- /dev/null +++ b/clang/test/various-loads.c @@ -0,0 +1,54 @@ +#include +#include +#include "libinterface.h" + +/* atomic */ int flag1, flag2; + +#define true 1 +#define false 0 +#define NULL 0 + +uint64_t var = 0, var2 = 0; + +void p0() {MC2_nextOpLoad(MCID_NODEP); + load_64(&flag2); + MCID _mq; _mq=MC2_nextOpLoad(MCID_NODEP); int q = load_64(&flag1); + MCID _br0; + MCID _m_cond0_m=MC2_nextOpLoad(MCID_NODEP); + int _cond0 = load_64(&flag1); + MCID _cond0_m = MC2_function_id(1, 1, sizeof(_cond0), _cond0); + if (_cond0) { + _br0 = MC2_branchUsesID(_cond0_m, 1, 2, true); + ; + MC2_merge(_br0); + } + else { _br0 = MC2_branchUsesID(_cond0_m, 0, 2, true); MC2_merge(_br0); + } MCID _br1; + MC2_nextOpLoad(MCID_NODEP); + int _cond1 = !load_64(&flag1); + MCID _cond1_m = MC2_function_id(2, 1, sizeof(_cond1), _cond1); + if (_cond1) { + _br1 = MC2_branchUsesID(_cond1_m, 0, 2, true); + ; + MC2_merge(_br1); + } + else { _br1 = MC2_branchUsesID(_cond1_m, 1, 2, true); MC2_merge(_br1); + }} + +void p1() { + MCID _rmw0 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_64(CAS, &flag1, var, var2); + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + int r = rmw_64(CAS, &flag1, var, var2); + MCID _br2; + MCID _rmw2 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + + int _cond2 = rmw_64(CAS, &flag1, var, var2); + MCID _cond2_m = MC2_function_id(3, 1, sizeof(_cond2), _cond2); + if (_cond2) { + _br2 = MC2_branchUsesID(_cond2_m, 1, 2, true); + ; + MC2_merge(_br2); + } + else { _br2 = MC2_branchUsesID(_cond2_m, 0, 2, true); MC2_merge(_br2); + }} diff --git a/clang/test/various-loads_unannotated.c b/clang/test/various-loads_unannotated.c new file mode 100644 index 0000000..02d7564 --- /dev/null +++ b/clang/test/various-loads_unannotated.c @@ -0,0 +1,30 @@ +#include +#include +#include "libinterface.h" + +/* atomic */ int flag1, flag2; + +#define true 1 +#define false 0 +#define NULL 0 + +uint64_t var = 0, var2 = 0; + +void p0() { + load_64(&flag2); + int q = load_64(&flag1); + if (load_64(&flag1)) { + ; + } + if (!load_64(&flag1)) { + ; + } +} + +void p1() { + rmw_64(CAS, &flag1, var, var2); + int r = rmw_64(CAS, &flag1, var, var2); + if (rmw_64(CAS, &flag1, var, var2)) { + ; + } +} diff --git a/classlist.h b/classlist.h new file mode 100644 index 0000000..ba7af68 --- /dev/null +++ b/classlist.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef CLASSLIST_H +#define CLASSLIST_H +#include "hashset.h" +#include "mymemory.h" +#include + +class StoreLoadSet; +class RecPair; +class MCChange; +class CGoal; +class EPRecord; +class EPValue; +class EventRecord; +class ExecPoint; +class MC; +class MCExecution; +class MCScheduler; +class ModelAction; +class Planner; +class Thread; +class ConstGen; +class Constraint; +class BranchRecord; +class ValueRecord; +class FunctionRecord; +class EqualsRecord; +class LoadRF; +class ScheduleBuilder; +class IncrementalSolver; + +typedef unsigned int uint; +enum EventType {LOAD, STORE, RMW, BRANCHDIR, MERGE, FUNCTION, THREADCREATE, THREADBEGIN, NONLOCALTRANS, LABEL,YIELD, THREADJOIN, LOOPENTER, LOOPSTART, ALLOC, EQUALS, FENCE}; +typedef HashSet RecordSet; +typedef HSIterator RecordIterator; +typedef HashTable BranchTable; +typedef HashSet SnapRecordSet; +typedef HSIterator, default_equals > SnapRecordIterator; +typedef HashTable StoreLoadSetHashTable; +typedef HashTable LoadHashTable; +typedef HashSet IntHashSet; +typedef HSIterator IntIterator; +typedef HashSet SnapIntHashSet; +typedef HSIterator SnapIntIterator; +typedef HashTable VarTable; +typedef HashTable FunctionTable; +typedef HashTable EqualsTable; +#endif diff --git a/cmodelint.cc b/cmodelint.cc new file mode 100644 index 0000000..2c95808 --- /dev/null +++ b/cmodelint.cc @@ -0,0 +1,46 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "model.h" +#include "cmodelint.h" +#include "threads-model.h" + +/** Performs a read action.*/ +uint64_t model_read_action(void * obj, memory_order ord) { + return -1; +} + +/** Performs a write action.*/ +void model_write_action(void * obj, memory_order ord, uint64_t val) { +} + +/** Performs an init action. */ +void model_init_action(void * obj, uint64_t val) { +} + +/** + * Performs the read part of a RMW action. The next action must either be the + * write part of the RMW action or an explicit close out of the RMW action w/o + * a write. + */ +uint64_t model_rmwr_action(void *obj, memory_order ord) { + return -1; +} + +/** Performs the write part of a RMW action. */ +void model_rmw_action(void *obj, memory_order ord, uint64_t val) { +} + +/** Closes out a RMW action without doing a write. */ +void model_rmwc_action(void *obj, memory_order ord) { +} + +/** Issues a fence operation. */ +void model_fence_action(memory_order ord) { +} diff --git a/common.cc b/common.cc new file mode 100644 index 0000000..b57e93c --- /dev/null +++ b/common.cc @@ -0,0 +1,180 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "model.h" +#include "stacktrace.h" +#include "output.h" + +#define MAX_TRACE_LEN 100 + +/** @brief Model-checker output file descriptor; default to stdout until redirected */ +int model_out = STDOUT_FILENO; + +#define CONFIG_STACKTRACE +/** Print a backtrace of the current program state. */ +void print_trace(void) +{ +#ifdef CONFIG_STACKTRACE + print_stacktrace(model_out); +#else + void *array[MAX_TRACE_LEN]; + char **strings; + int size, i; + + size = backtrace(array, MAX_TRACE_LEN); + strings = backtrace_symbols(array, size); + + model_print("\nDumping stack trace (%d frames):\n", size); + + for (i = 0; i < size; i++) + model_print("\t%s\n", strings[i]); + + free(strings); +#endif /* CONFIG_STACKTRACE */ +} + +void assert_hook(void) +{ + model_print("Add breakpoint to line %u in file %s.\n", __LINE__, __FILE__); +} + +void model_assert(bool expr, const char *file, int line) +{ + if (!expr) { + printf("Program has hit assertion in file %s at line %d\n", + file, line); + } +} + +#ifndef CONFIG_DEBUG + +static int fd_user_out; /**< @brief File descriptor from which to read user program output */ + +/** + * @brief Setup output redirecting + * + * Redirects user program's stdout to a pipe so that we can dump it + * selectively, when displaying bugs, etc. + * Also connects a file descriptor 'model_out' directly to stdout, for printing + * data when needed. + * + * The model-checker can selectively choose to print/hide the user program + * output. + * @see clear_program_output + * @see print_program_output + * + * Note that the user program's pipe has limited memory, so if a program will + * output much data, we will need to buffer it in user-space during execution. + * This also means that if ModelChecker decides not to print an execution, it + * should promptly clear the pipe. + * + * This function should only be called once. + */ +void redirect_output() +{ + /* Save stdout for later use */ + model_out = dup(STDOUT_FILENO); + if (model_out < 0) { + perror("dup"); + exit(EXIT_FAILURE); + } + + /* Redirect program output to a pipe */ + int pipefd[2]; + if (pipe(pipefd) < 0) { + perror("pipe"); + exit(EXIT_FAILURE); + } + if (dup2(pipefd[1], STDOUT_FILENO) < 0) { + perror("dup2"); + exit(EXIT_FAILURE); + } + close(pipefd[1]); + + /* Save the "read" side of the pipe for use later */ + if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) < 0) { + perror("fcntl"); + exit(EXIT_FAILURE); + } + fd_user_out = pipefd[0]; +} + +/** + * @brief Wrapper for reading data to buffer + * + * Besides a simple read, this handles the subtleties of EOF and nonblocking + * input (if fd is O_NONBLOCK). + * + * @param fd The file descriptor to read. + * @param buf Buffer to read to. + * @param maxlen Maximum data to read to buffer + * @return The length of data read. If zero, then we hit EOF or ran out of data + * (non-blocking) + */ +static ssize_t read_to_buf(int fd, char *buf, size_t maxlen) +{ + ssize_t ret = read(fd, buf, maxlen); + if (ret < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + return 0; + } else { + perror("read"); + exit(EXIT_FAILURE); + } + } + return ret; +} + +/** @brief Dump any pending program output without printing */ +void clear_program_output() +{ + fflush(stdout); + char buf[200]; + while (read_to_buf(fd_user_out, buf, sizeof(buf))); +} + +/** @brief Print out any pending program output */ +void print_program_output() +{ + char buf[200]; + + model_print("---- BEGIN PROGRAM OUTPUT ----\n"); + + /* Gather all program output */ + fflush(stdout); + + /* Read program output pipe and write to (real) stdout */ + ssize_t ret; + while (1) { + ret = read_to_buf(fd_user_out, buf, sizeof(buf)); + if (!ret) + break; + while (ret > 0) { + ssize_t res = write(model_out, buf, ret); + if (res < 0) { + perror("write"); + exit(EXIT_FAILURE); + } + ret -= res; + } + } + + model_print("---- END PROGRAM OUTPUT ----\n"); +} +#endif /* ! CONFIG_DEBUG */ diff --git a/common.h b/common.h new file mode 100644 index 0000000..7206371 --- /dev/null +++ b/common.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file common.h + * @brief General purpose macros. + */ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include +#include "config.h" + +extern int model_out; + +#define model_print(fmt, ...) do { dprintf(model_out, fmt, ##__VA_ARGS__); } while (0) + +#ifdef CONFIG_DEBUG +#define DEBUG(fmt, ...) do { model_print("*** %15s:%-4d %25s() *** " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__); } while (0) +#define DBG() DEBUG("\n") +#define DBG_ENABLED() (1) +#else +#define DEBUG(fmt, ...) +#define DBG() +#define DBG_ENABLED() (0) +#endif + +void assert_hook(void); + +#ifdef CONFIG_ASSERT +#define ASSERT(expr) \ +do { \ + if (!(expr)) { \ + fprintf(stderr, "Error: assertion failed in %s at line %d\n", __FILE__, __LINE__); \ + /* print_trace(); // Trace printing may cause dynamic memory allocation */ \ + assert_hook(); \ + exit(EXIT_FAILURE); \ + } \ +} while (0) +#else +#define ASSERT(expr) \ + do { } while (0) +#endif /* CONFIG_ASSERT */ + +#define error_msg(...) fprintf(stderr, "Error: " __VA_ARGS__) + +void print_trace(void); +#endif /* __COMMON_H__ */ diff --git a/common.mk b/common.mk new file mode 100644 index 0000000..b91369f --- /dev/null +++ b/common.mk @@ -0,0 +1,17 @@ +# A few common Makefile items + +CC := gcc +CXX := g++ + +UNAME := $(shell uname) + +LIB_NAME := model +TSO_LIB_SO := libtso_$(LIB_NAME).so +SC_LIB_SO := libsc_$(LIB_NAME).so + +CPPFLAGS += -Wall -g -O3 + +# Mac OSX options +ifeq ($(UNAME), Darwin) +CPPFLAGS += -D_XOPEN_SOURCE -DMAC +endif diff --git a/config.h b/config.h new file mode 100644 index 0000000..9efd32e --- /dev/null +++ b/config.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file config.h + * @brief Configuration file. + */ + +#ifndef CONFIG_H +#define CONFIG_H + +/** Turn on debugging. */ +#ifndef CONFIG_DEBUG +//#define CONFIG_DEBUG +#endif + +#ifndef CONFIG_ASSERT +//#define CONFIG_ASSERT +#endif + +//#define VERBOSE_CONSTRAINTS + +/** Turn on support for dumping cyclegraphs as dot files at each + * printed summary.*/ +//#define SUPPORT_MOD_ORDER_DUMP 1 + +/** Do we have a 48 bit virtual address (64 bit machine) or 32 bit addresses. + * Set to 1 for 48-bit, 0 for 32-bit. */ +#ifndef BIT48 +#ifdef _LP64 +#define BIT48 1 +#else +#define BIT48 0 +#endif +#endif /* BIT48 */ + +/** Snapshotting configurables */ + +/** + * If USE_MPROTECT_SNAPSHOT=2, then snapshot by tuned mmap() algorithm + * If USE_MPROTECT_SNAPSHOT=1, then snapshot by using mmap() and mprotect() + * If USE_MPROTECT_SNAPSHOT=0, then snapshot by using fork() */ +#define USE_MPROTECT_SNAPSHOT 2 + +/** Size of signal stack */ +#define SIGSTACKSIZE 65536 + +/** Page size configuration */ +#define PAGESIZE 4096 + +/** Thread parameters */ + +/* Size of stack to allocate for a thread. */ +#define STACK_SIZE (1024 * 1024) + +/** Enable debugging assertions (via ASSERT()) */ +//#define CONFIG_ASSERT + +/** Enable dumping event graphs in DOT compatiable format. */ +//#define DUMP_EVENT_GRAPHS + +/** Print Achieved Goals. */ +//#define PRINT_ACHIEVED_GOALS + +/** Use TSO Memory Model */ +//#define TSO + +/** Record Stats */ +//#define STATS + +#endif diff --git a/constgen.cc b/constgen.cc new file mode 100644 index 0000000..60cceb7 --- /dev/null +++ b/constgen.cc @@ -0,0 +1,1897 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "constgen.h" +#include "mcexecution.h" +#include "constraint.h" +#include "branchrecord.h" +#include "functionrecord.h" +#include "equalsrecord.h" +#include "storeloadset.h" +#include "loadrf.h" +#include "schedulebuilder.h" +#include "model.h" +#include +#include +#include +#include "inc_solver.h" +#include + +long long myclock() { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec*1000000+tv.tv_usec; +} + +ConstGen::ConstGen(MCExecution *e) : + storeloadtable(new StoreLoadSetHashTable()), + loadtable(new LoadHashTable()), + execution(e), + workstack(new ModelVector()), + threadactions(new ModelVector *>()), + rpt(new RecPairTable()), + numconstraints(0), + goalset(new ModelVector()), + goalvararray(NULL), + vars(new ModelVector()), + branchtable(new BranchTable()), + functiontable(new FunctionTable()), + equalstable(new EqualsTable()), + schedulebuilder(new ScheduleBuilder(e, this)), + nonlocaltrans(new RecordSet()), + execcondtable(new LoadHashTable()), + solver(NULL), + rectoint(new RecToIntTable()), + varindex(1), + schedule_graph(0), + has_untaken_branches(false) +{ +#ifdef STATS + curr_stat=new MC_Stat(); + curr_stat->time=0; + curr_stat->was_incremental=false; + curr_stat->was_sat=true; + curr_stat->fgoals=0; + curr_stat->bgoals=0; + stats=new ModelVector(); +#endif +} + +ConstGen::~ConstGen() { + reset(); + if (solver != NULL) + delete solver; + for(uint i=0;isize();i++) { + Constraint *var=(*vars)[i]; + Constraint *notvar=var->neg; + delete var; + delete notvar; + } + vars->clear(); + delete storeloadtable; + delete loadtable; + delete workstack; + delete threadactions; + delete rpt; + delete goalset; + delete vars; + delete branchtable; + delete functiontable; + delete equalstable; + delete schedulebuilder; + delete nonlocaltrans; + delete execcondtable; + delete rectoint; +} + +void resetstoreloadtable(StoreLoadSetHashTable * storeloadtable) { + for(uint i=0;icapacity;i++) { + struct hashlistnode * ptr=& storeloadtable->table[i]; + if (ptr->val != NULL) { + if (ptr->val->removeAddress(ptr->key)) + delete ptr->val; + ptr->val=NULL; + ptr->key=NULL; + } + } + + if (storeloadtable->zero != NULL) { + if (storeloadtable->zero->val->removeAddress(storeloadtable->zero->key)) { + delete storeloadtable->zero->val; + } else + ASSERT(false); + model_free(storeloadtable -> zero); + storeloadtable->zero = NULL; + } + storeloadtable->size = 0; +} + +void ConstGen::reset() { + for(uint i=0;isize();i++) { + delete (*threadactions)[i]; + } + if (goalvararray != NULL) { + model_free(goalvararray); + goalvararray=NULL; + } + functiontable->resetanddelete(); + equalstable->resetanddelete(); + branchtable->resetanddelete(); + loadtable->resetanddelete(); + execcondtable->resetanddelete(); + rpt->resetanddelete(); + resetstoreloadtable(storeloadtable); + nonlocaltrans->reset(); + threadactions->clear(); + rectoint->reset(); + goalset->clear(); + varindex=1; + numconstraints=0; + has_untaken_branches=false; +} + +void ConstGen::translateGoals() { + int size=goalset->size(); + goalvararray=(Constraint **) model_malloc(size*sizeof(Constraint *)); + + for(int i=0;inegate(), goal)); + } + Constraint *atleastonegoal=new Constraint(OR, size, goalvararray); + ADDCONSTRAINT(atleastonegoal, "atleastonegoal"); +} + +bool ConstGen::canReuseEncoding() { + if (solver == NULL) + return false; + Constraint *array[goalset->size()]; + int remaininggoals=0; + + //Zero out the achieved goals + for(uint i=0;isize();i++) { + Constraint *var=goalvararray[i]; + if (var != NULL) { + array[remaininggoals++]=var; + } + } + if (remaininggoals == 0) + return false; + Constraint *atleastonegoal=new Constraint(OR, remaininggoals, array); + ADDCONSTRAINT(atleastonegoal, "atleastonegoal"); + solver->finishedClauses(); + clock_t start=myclock(); + bool *solution=runSolver(); + clock_t finish=myclock(); +#ifdef STATS + if (curr_stat != NULL) + stats->push_back(curr_stat); + curr_stat=new MC_Stat(); + curr_stat->time=finish-start; + curr_stat->was_incremental=true; + curr_stat->was_sat=(solution!=NULL); + curr_stat->fgoals=0; + curr_stat->bgoals=0; +#endif + model_print("start %lu, finish %lu\n", start,finish); + model_print("Incremental time = %12.6f\n", ((double)(finish-start))/1000000); + + if (solution==NULL) { + return false; + } + + //Zero out the achieved goals + for(uint i=0;isize();i++) { + Constraint *var=goalvararray[i]; + if (var != NULL) { + if (solution[var->getVar()]) { + // if (goalvararray[i] != NULL) + //model_print("SAT clearing goal %d.\n", i); + + goalvararray[i]=NULL; + } + } + } + + schedulebuilder->buildSchedule(solution); + model_free(solution); + + return true; +} + +bool ConstGen::process() { +#ifdef DUMP_EVENT_GRAPHS + printEventGraph(); +#endif + + if (solver != NULL) { + delete solver; + solver = NULL; + } + + solver=new IncrementalSolver(); + + traverse(true); + genTransOrderConstraints(); +#ifdef TSO + genTSOTransOrderConstraints(); +#endif + traverse(false); + translateGoals(); + if (goalset->size()==0) { +#ifdef STATS + stats->push_back(curr_stat); + for(uint i=0;isize();i++) { + struct MC_Stat *s=(*stats)[i]; + model_print("time=%lld fgoals=%d bgoals=%d incremental=%d sat=%d\n", s->time, s->fgoals, s->bgoals, s->was_incremental, s->was_sat); + } +#endif + model_print("No goals, done\n"); + delete solver; + solver = NULL; + return true; + } + + if (model->params.branches && !has_untaken_branches) { + delete solver; + solver = NULL; + return true; + } + + solver->finishedClauses(); + + //Freeze the goal variables + for(uint i=0;isize();i++) { + Constraint *var=goalvararray[i]; + solver->freeze(var->getVar()); + } + + clock_t start=myclock(); + bool *solution=runSolver(); + clock_t finish=myclock(); +#ifdef STATS + if (curr_stat != NULL) + stats->push_back(curr_stat); + curr_stat=new MC_Stat(); + curr_stat->time=finish-start; + curr_stat->was_incremental=false; + curr_stat->was_sat=(solution!=NULL); + curr_stat->fgoals=0; + curr_stat->bgoals=0; + + if (solution == NULL) { + stats->push_back(curr_stat); + for(uint i=0;isize();i++) { + struct MC_Stat *s=(*stats)[i]; + model_print("time=%lld fgoals=%d bgoals=%d incremental=%d sat=%d\n", s->time, s->fgoals, s->bgoals, s->was_incremental, s->was_sat); + } + + } +#endif + + model_print("start %lu, finish %lu\n", start,finish); + model_print("Initial time = %12.6f\n", ((double)(finish-start))/1000000); + + + if (solution==NULL) { + delete solver; + solver = NULL; + return true; + } + + //Zero out the achieved goals + for(uint i=0;isize();i++) { + Constraint *var=goalvararray[i]; + if (var != NULL) { + if (solution[var->getVar()]) { + //if (goalvararray[i] != NULL) + // model_print("SAT clearing goal %d.\n", i); + goalvararray[i]=NULL; + } + } + } + + schedulebuilder->buildSchedule(solution); + model_free(solution); + return false; +} + +void ConstGen::printEventGraph() { + char buffer[128]; + sprintf(buffer, "eventgraph%u.dot",schedule_graph); + schedule_graph++; + int file=open(buffer,O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU); + dprintf(file, "digraph eventgraph {\n"); + + EPRecord *first=execution->getEPRecord(MCID_FIRST); + printRecord(first, file); + while(!workstack->empty()) { + EPRecord *record=workstack->back(); + workstack->pop_back(); + printRecord(record, file); + } + + dprintf(file, "}\n"); + close(file); +} + +void ConstGen::doPrint(EPRecord *record, int file) { + dprintf(file, "%lu[label=\"",(uintptr_t)record); + record->print(file); + dprintf(file, "\"];\n"); + if (record->getNextRecord()!=NULL) + dprintf(file, "%lu->%lu;\n", (uintptr_t) record, (uintptr_t) record->getNextRecord()); + + if (record->getChildRecord()!=NULL) + dprintf(file, "%lu->%lu[color=red];\n", (uintptr_t) record, (uintptr_t) record->getChildRecord()); +} + +void ConstGen::printRecord(EPRecord *record, int file) { + do { + doPrint(record,file); + + if (record->getType()==LOOPENTER) { + workstack->push_back(record->getNextRecord()); + workstack->push_back(record->getChildRecord()); + return; + } + if (record->getChildRecord()!=NULL) { + workstack->push_back(record->getChildRecord()); + } + if (record->getType()==NONLOCALTRANS) { + return; + } + if (record->getType()==BRANCHDIR) { + EPRecord *next=record->getNextRecord(); + if (next != NULL) + workstack->push_back(next); + for(uint i=0;inumValues();i++) { + EPValue *branchdir=record->getValue(i); + + //Could have an empty branch, so make sure the branch actually + //runs code + if (branchdir->getFirstRecord()!=NULL) { + workstack->push_back(branchdir->getFirstRecord()); + dprintf(file, "%lu->%lu[color=blue];\n", (uintptr_t) record, (uintptr_t) branchdir->getFirstRecord()); + } + } + return; + } else + record=record->getNextRecord(); + } while(record!=NULL); +} + + +/* This function traverses a thread's graph in execution order. */ + +void ConstGen::traverse(bool initial) { + EPRecord *first=execution->getEPRecord(MCID_FIRST); + traverseRecord(first, initial); + while(!workstack->empty()) { + EPRecord *record=workstack->back(); + workstack->pop_back(); + traverseRecord(record, initial); + } +} + +/** This method looks for all other memory operations that could + potentially share a location, and build partitions of memory + locations such that all memory locations that can share the same + address are in the same group. + + These memory operations should share an encoding of addresses and + values. +*/ + +void ConstGen::groupMemoryOperations(EPRecord *op) { + /** Handle our first address */ + IntHashSet *addrset=op->getSet(VC_ADDRINDEX); + IntIterator *ait=addrset->iterator(); + + void *iaddr=(void *) ait->next(); + StoreLoadSet *isls=storeloadtable->get(iaddr); + if (isls==NULL) { + isls=new StoreLoadSet(); + storeloadtable->put(iaddr, isls); + } + isls->add(op); + + while(ait->hasNext()) { + void *addr=(void *)ait->next(); + StoreLoadSet *sls=storeloadtable->get(addr); + if (sls==NULL) { + storeloadtable->put(addr, isls); + } else if (sls!=isls) { + //must do merge + mergeSets(isls, sls); + } + } + delete ait; +} + + +RecordSet * ConstGen::computeConflictSet(EPRecord *store, EPRecord *load, RecordSet * baseset) { + //See if we can determine addresses that store/load may use + IntIterator * storeaddr=store->getSet(VC_ADDRINDEX)->iterator(); + int numaddr=0;void *commonaddr=NULL; + while(storeaddr->hasNext()) { + void *addr=(void *) storeaddr->next(); + if (load->getSet(VC_ADDRINDEX)->contains((uint64_t)addr)) { + commonaddr=addr; + numaddr++; + } + } + delete storeaddr; + + ASSERT(numaddr!=0); + if (numaddr!=1) + return NULL; + + RecordSet *srscopy=baseset->copy(); + RecordIterator *sri=srscopy->iterator(); + while(sri->hasNext()) { + bool pruneconflictstore=false; + EPRecord *conflictstore=sri->next(); + bool conflictafterstore=getOrderConstraint(store,conflictstore)->isTrue(); + bool conflictbeforeload=getOrderConstraint(conflictstore,load)->isTrue(); + + if (conflictafterstore) { + RecordIterator *sricheck=srscopy->iterator(); + while(sricheck->hasNext()) { + EPRecord *checkstore=sricheck->next(); + bool checkafterstore=getOrderConstraint(store, checkstore)->isTrue(); + if (!checkafterstore) + continue; + bool checkbeforeconflict=getOrderConstraint(checkstore,conflictstore)->isTrue(); + if (!checkbeforeconflict) + continue; + + //See if the checkstore must store to the relevant address + IntHashSet * storeaddr=checkstore->getSet(VC_ADDRINDEX); + + if (storeaddr->getSize()!=1 || !storeaddr->contains((uint64_t)commonaddr)) + continue; + + + if (subsumesExecutionConstraint(checkstore, conflictstore)) { + pruneconflictstore=true; + break; + } + } + delete sricheck; + } + + if (conflictbeforeload && !pruneconflictstore) { + RecordIterator *sricheck=srscopy->iterator(); + while(sricheck->hasNext()) { + EPRecord *checkstore=sricheck->next(); + + bool checkafterconflict=getOrderConstraint(conflictstore, checkstore)->isTrue(); + if (!checkafterconflict) + continue; + + bool checkbeforeload=getOrderConstraint(checkstore, load)->isTrue(); + if (!checkbeforeload) + continue; + + //See if the checkstore must store to the relevant address + IntHashSet * storeaddr=checkstore->getSet(VC_ADDRINDEX); + if (storeaddr->getSize()!=1 || !storeaddr->contains((uint64_t)commonaddr)) + continue; + + + if (subsumesExecutionConstraint(checkstore, conflictstore)) { + pruneconflictstore=true; + break; + } + } + delete sricheck; + } + if (pruneconflictstore) { + //This store is redundant + sri->remove(); + } + } + + delete sri; + return srscopy; +} + + +/** This method returns all stores that a load may read from. */ + +RecordSet * ConstGen::getMayReadFromSet(EPRecord *load) { + if (load->getSet(VC_ADDRINDEX)->getSize()==1) + return getMayReadFromSetOpt(load); + + RecordSet *srs=loadtable->get(load); + ExecPoint *epload=load->getEP(); + thread_id_t loadtid=epload->get_tid(); + if (srs==NULL) { + srs=new RecordSet(); + loadtable->put(load, srs); + + IntHashSet *addrset=load->getSet(VC_ADDRINDEX); + IntIterator *ait=addrset->iterator(); + + while(ait->hasNext()) { + void *addr=(void *)ait->next(); + RecordSet *rs=execution->getStoreTable(addr); + if (rs==NULL) + continue; + + RecordIterator * rit=rs->iterator(); + while(rit->hasNext()) { + EPRecord *rec=rit->next(); + ExecPoint *epstore=rec->getEP(); + thread_id_t storetid=epstore->get_tid(); + if (storetid != loadtid || + epstore->compare(epload) == CR_AFTER) + srs->add(rec); + } + delete rit; + } + delete ait; + } + return srs; +} + + +RecordSet * ConstGen::getMayReadFromSetOpt(EPRecord *load) { + RecordSet *srs=loadtable->get(load); + ExecPoint *epload=load->getEP(); + thread_id_t loadtid=epload->get_tid(); + if (srs==NULL) { + srs=new RecordSet(); + loadtable->put(load, srs); + + IntHashSet *addrset=load->getSet(VC_ADDRINDEX); + IntIterator *ait=addrset->iterator(); + void *addr=(void *)ait->next(); + delete ait; + + RecordSet *rs=execution->getStoreTable(addr); + RecordIterator * rit=rs->iterator(); + ExecPoint *latest=NULL; + while(rit->hasNext()) { + EPRecord *store=rit->next(); + ExecPoint *epstore=store->getEP(); + thread_id_t storetid=epstore->get_tid(); + if (storetid == loadtid && isAlwaysExecuted(store) && + store->getSet(VC_ADDRINDEX)->getSize()==1 && + epstore->compare(epload) == CR_AFTER && + (latest==NULL || latest->compare(epstore) == CR_AFTER)) { + latest=epstore; + } + } + delete rit; + rit=rs->iterator(); + while(rit->hasNext()) { + EPRecord *store=rit->next(); + ExecPoint *epstore=store->getEP(); + thread_id_t storetid=epstore->get_tid(); + if (storetid == loadtid) { + if (epstore->compare(epload) == CR_AFTER && + (latest==NULL || epstore->compare(latest) != CR_AFTER)) + srs->add(store); + } else { + srs->add(store); + } + } + delete rit; + } + return srs; +} + +/** This function merges two recordsets and updates the storeloadtable + accordingly. */ + +void ConstGen::mergeSets(StoreLoadSet *to, StoreLoadSet *from) { + RecordIterator * sri=from->iterator(); + while(sri->hasNext()) { + EPRecord *rec=sri->next(); + to->add(rec); + IntHashSet *addrset=rec->getSet(VC_ADDRINDEX); + IntIterator *ait=addrset->iterator(); + while(ait->hasNext()) { + void *addr=(void *)ait->next(); + storeloadtable->put(addr, to); + } + delete ait; + } + delete sri; + delete from; +} + +#ifdef TSO +/** This function creates ordering variables between stores and loads + * in same thread for TSO. */ + +void ConstGen::insertTSOAction(EPRecord *load) { + if (load->getType() != LOAD) + return; + ExecPoint *load_ep=load->getEP(); + thread_id_t tid=load_ep->get_tid(); + uint thread=id_to_int(tid); + ModelVector * vector=(*threadactions)[thread]; + uint j=vector->size()-1; + while (j>0) { + EPRecord *oldrec=(*vector)[--j]; + EventType oldrec_t=oldrec->getType(); + + if (((oldrec_t == RMW) || (oldrec_t==FENCE)) && + isAlwaysExecuted(oldrec)) { + return; + } else if (oldrec_t == STORE) { + /* Only generate variables for things that can actually both run */ + + createOrderConstraint(oldrec, load); + } + } +} + +void ConstGen::genTSOTransOrderConstraints() { + for(uint t1=0;t1size();t1++) { + ModelVector *tvec=(*threadactions)[t1]; + uint size=tvec->size(); + EPRecord *laststore=NULL; + for(uint store_i=0;store_igetType(); + if (store_t != STORE) + continue; + EPRecord *lastload=NULL; + for(uint load_i=store_i+1;load_igetType(); + if (((rec_t == RMW) || (rec_t == FENCE)) && + isAlwaysExecuted(rec)) + break; + if (rec_t != LOAD) + continue; + if (laststore != NULL) { + Constraint * storeload=getOrderConstraint(store, rec); + Constraint * earlystoreload=getOrderConstraint(laststore, rec); + Constraint * c=new Constraint(IMPLIES, storeload, earlystoreload); + ADDCONSTRAINT(c, "earylstore"); + } + if (lastload != NULL) { + Constraint * storeearlyload=getOrderConstraint(store, lastload); + Constraint * storeload=getOrderConstraint(store, rec); + Constraint * c=new Constraint(IMPLIES, storeearlyload, storeload); + ADDCONSTRAINT(c, "earylload"); + } + lastload=rec; + } + laststore=store; + } + } +} +#endif + +/** This function creates ordering constraints to implement SC for + memory operations. */ + +void ConstGen::insertAction(EPRecord *record) { + thread_id_t tid=record->getEP()->get_tid(); + uint thread=id_to_int(tid); + if (threadactions->size()<=thread) { + uint oldsize=threadactions->size(); + threadactions->resize(thread+1); + for(;oldsize<=thread;oldsize++) { + (*threadactions)[oldsize]=new ModelVector(); + } + } + + (*threadactions)[thread]->push_back(record); + + for(uint i=0;isize();i++) { + if (i==thread) + continue; + ModelVector * vector=(*threadactions)[i]; + for(uint j=0;jsize();j++) { + EPRecord *oldrec=(*vector)[j]; + createOrderConstraint(oldrec, record); + } + } +#ifdef TSO + insertTSOAction(record); +#endif +} + +void ConstGen::genTransOrderConstraints() { + for(uint t1=0;t1size();t1++) { + ModelVector *t1vec=(*threadactions)[t1]; + for(uint t2=0;t2 *t2vec=(*threadactions)[t2]; + genTransOrderConstraints(t1vec, t2vec); + genTransOrderConstraints(t2vec, t1vec); + for(uint t3=0;t3 *t3vec=(*threadactions)[t3]; + genTransOrderConstraints(t1vec, t2vec, t3vec); + } + } + } +} + +void ConstGen::genTransOrderConstraints(ModelVector * t1vec, ModelVector *t2vec) { + for(uint t1i=0;t1isize();t1i++) { + EPRecord *t1rec=(*t1vec)[t1i]; + for(uint t2i=0;t2isize();t2i++) { + EPRecord *t2rec=(*t2vec)[t2i]; + + /* Note: One only really needs to generate the first constraint + in the first loop and the last constraint in the last loop. + I tried this and performance suffered on linuxrwlocks and + linuxlocks at the current time. BD - August 2014*/ + Constraint *c21=getOrderConstraint(t2rec, t1rec); + + /* short circuit for the trivial case */ + if (c21->isTrue()) + continue; + + for(uint t3i=t2i+1;t3isize();t3i++) { + EPRecord *t3rec=(*t2vec)[t3i]; + Constraint *c13=getOrderConstraint(t1rec, t3rec); +#ifdef TSO + Constraint *c32=getOrderConstraint(t3rec, t2rec); + Constraint * array[]={c21, c32, c13}; + Constraint *intratransorder=new Constraint(OR, 3, array); +#else + Constraint *intratransorder=new Constraint(OR, c21, c13); +#endif + ADDCONSTRAINT(intratransorder,"intratransorder"); + } + + for(uint t0i=0;t0i * t1vec, ModelVector *t2vec, ModelVector * t3vec) { + for(uint t1i=0;t1isize();t1i++) { + EPRecord *t1rec=(*t1vec)[t1i]; + for(uint t2i=0;t2isize();t2i++) { + EPRecord *t2rec=(*t2vec)[t2i]; + for(uint t3i=0;t3isize();t3i++) { + EPRecord *t3rec=(*t3vec)[t3i]; + genTransOrderConstraint(t1rec, t2rec, t3rec); + } + } + } +} + +void ConstGen::genTransOrderConstraint(EPRecord *t1rec, EPRecord *t2rec, EPRecord *t3rec) { + Constraint *c21=getOrderConstraint(t2rec, t1rec); + Constraint *c32=getOrderConstraint(t3rec, t2rec); + Constraint *c13=getOrderConstraint(t1rec, t3rec); + Constraint * cimpl1[]={c21, c32, c13}; + Constraint * c1=new Constraint(OR, 3, cimpl1); + ADDCONSTRAINT(c1, "intertransorder"); + + Constraint *c12=getOrderConstraint(t1rec, t2rec); + Constraint *c23=getOrderConstraint(t2rec, t3rec); + Constraint *c31=getOrderConstraint(t3rec, t1rec); + Constraint * cimpl2[]={c12, c23, c31}; + Constraint *c2=new Constraint(OR, 3, cimpl2); + ADDCONSTRAINT(c2, "intertransorder"); +} + +void ConstGen::addGoal(EPRecord *r, Constraint *c) { + rectoint->put(r, goalset->size()); + goalset->push_back(c); +} + +void ConstGen::addBranchGoal(EPRecord *r, Constraint *c) { + has_untaken_branches=true; + rectoint->put(r, goalset->size()); + goalset->push_back(c); +} + +void ConstGen::achievedGoal(EPRecord *r) { + if (rectoint->contains(r)) { + uint index=rectoint->get(r); + //if (goalvararray[index] != NULL) + //model_print("Run Clearing goal index %d\n",index); + goalvararray[index]=NULL; + } +} + +void ConstGen::addConstraint(Constraint *c) { + ModelVector *vec=c->simplify(); + for(uint i=0;isize();i++) { + Constraint *simp=(*vec)[i]; + if (simp->type==TRUE) + continue; + ASSERT(simp->type!=FALSE); + simp->printDIMACS(this); +#ifdef VERBOSE_CONSTRAINTS + simp->print(); + model_print("\n"); +#endif + numconstraints++; + simp->freerec(); + } + delete vec; +} + +void ConstGen::printNegConstraint(uint value) { + int val=-value; + solver->addClauseLiteral(val); +} + +void ConstGen::printConstraint(uint value) { + solver->addClauseLiteral(value); +} + +bool * ConstGen::runSolver() { + int solution=solver->solve(); + if (solution == IS_UNSAT) { + return NULL; + } else if (solution == IS_SAT) { + bool * assignments=(bool *)model_malloc(sizeof(bool)*(varindex+1)); + for(uint i=0;i<=varindex;i++) + assignments[i]=solver->getValue(i); + return assignments; + } else { + delete solver; + solver=NULL; + dprintf(2, "INDETER\n"); + model_print("INDETER\n"); + exit(-1); + return NULL; + } +} + +Constraint * ConstGen::getOrderConstraint(EPRecord *first, EPRecord *second) { +#ifndef TSO + if (first->getEP()->get_tid()==second->getEP()->get_tid()) { + if (first->getEP()->compare(second->getEP())==CR_AFTER) + return &ctrue; + else { + return &cfalse; + } + } +#endif + RecPair rp(first, second); + RecPair *rpc=rpt->get(&rp); +#ifdef TSO + if ((rpc==NULL) && + first->getEP()->get_tid()==second->getEP()->get_tid()) { + if (first->getEP()->compare(second->getEP())==CR_AFTER) + return &ctrue; + else { + return &cfalse; + } + } +#endif + ASSERT(rpc!=NULL); + // delete rp; + Constraint *c=rpc->constraint; + if (rpc->epr1!=first) { + //have to flip arguments + return c->negate(); + } else { + return c; + } +} + +bool ConstGen::getOrder(EPRecord *first, EPRecord *second, bool * satsolution) { + RecPair rp(first, second); + RecPair *rpc=rpt->get(&rp); +#ifdef TSO + if ((rpc==NULL) && + first->getEP()->get_tid()==second->getEP()->get_tid()) { + if (first->getEP()->compare(second->getEP())==CR_AFTER) + return true; + else { + return false; + } + } +#endif + + ASSERT(rpc!=NULL); + + Constraint *c=rpc->constraint; + CType type=c->getType(); + bool order; + + if (type==TRUE) + order=true; + else if (type==FALSE) + order=false; + else { + uint index=c->getVar(); + order=satsolution[index]; + } + if (rpc->epr1==first) + return order; + else + return !order; +} + +/** This function determines whether events first and second are + * ordered by start and join operations. */ + +bool ConstGen::orderThread(EPRecord *first, EPRecord *second) { + ExecPoint * ep1=first->getEP(); + ExecPoint * ep2=second->getEP(); + thread_id_t thr1=ep1->get_tid(); + thread_id_t thr2=ep2->get_tid(); + Thread *tr2=execution->get_thread(thr2); + EPRecord *thr2start=tr2->getParentRecord(); + if (thr2start!=NULL) { + ExecPoint *epthr2start=thr2start->getEP(); + if (epthr2start->get_tid()==thr1 && + ep1->compare(epthr2start)==CR_AFTER) + return true; + } + ModelVector * joinvec=execution->getJoins(); + for(uint i=0;isize();i++) { + EPRecord *join=(*joinvec)[i]; + ExecPoint *jp=join->getEP(); + if (jp->get_tid()==thr2 && + jp->compare(ep2)==CR_AFTER) + return true; + } + return false; +} + +/** This function generates an ordering constraint for two events. */ + +void ConstGen::createOrderConstraint(EPRecord *first, EPRecord *second) { + RecPair * rp=new RecPair(first, second); + if (!rpt->contains(rp)) { + if (orderThread(first, second)) + rp->constraint=&ctrue; + else if (orderThread(second, first)) + rp->constraint=&cfalse; + else + rp->constraint=getNewVar(); + + rpt->put(rp, rp); + } else { + delete rp; + } +} + +Constraint * ConstGen::getNewVar() { + Constraint *var; + if (varindex>vars->size()) { + var=new Constraint(VAR, varindex); + Constraint *varneg=new Constraint(NOTVAR, varindex); + var->setNeg(varneg); + varneg->setNeg(var); + vars->push_back(var); + } else { + var=(*vars)[varindex-1]; + } + varindex++; + return var; +} + +/** Gets an array of new variables. */ + +void ConstGen::getArrayNewVars(uint num, Constraint **carray) { + for(uint i=0;igetSet(VC_ADDRINDEX)->iterator(); + void *addr=(void *)it->next(); + delete it; + return storeloadtable->get(addr); +} + +/** Returns a constraint that is true if the output of record has the + given value. */ + +Constraint * ConstGen::getRetValueEncoding(EPRecord *record, uint64_t value) { + switch(record->getType()) { + case EQUALS: + return equalstable->get(record)->getValueEncoding(value); + case FUNCTION: + return functiontable->get(record)->getValueEncoding(value); + case LOAD: { + return getStoreLoadSet(record)->getValueEncoding(this, record, value); + } + case RMW: { + return getStoreLoadSet(record)->getRMWRValueEncoding(this, record, value); + } + default: + ASSERT(false); + exit(-1); + } +} + +Constraint * ConstGen::getMemValueEncoding(EPRecord *record, uint64_t value) { + switch(record->getType()) { + case STORE: + return getStoreLoadSet(record)->getValueEncoding(this, record, value); + case RMW: + return getStoreLoadSet(record)->getValueEncoding(this, record, value); + default: + ASSERT(false); + exit(-1); + } +} + +/** Return true if the execution of record implies the execution of + * recordsubsumes */ + +bool ConstGen::subsumesExecutionConstraint(EPRecord *recordsubsumes, EPRecord *record) { + EPValue *branch=record->getBranch(); + EPValue *branchsubsumes=recordsubsumes->getBranch(); + if (branchsubsumes != NULL) { + bool branchsubsumed=false; + while(branch!=NULL) { + if (branchsubsumes==branch) { + branchsubsumed=true; + break; + } + branch=branch->getRecord()->getBranch(); + } + if (!branchsubsumed) + return false; + } + RecordSet *srs=execcondtable->get(recordsubsumes); + + if (srs!=NULL) { + RecordIterator *sri=srs->iterator(); + while(sri->hasNext()) { + EPRecord *rec=sri->next(); + + if (!getOrderConstraint(rec, record)->isTrue()) { + delete sri; + return false; + } + } + delete sri; + } + return true; +} + +Constraint * ConstGen::getExecutionConstraint(EPRecord *record) { + EPValue *branch=record->getBranch(); + RecordSet *srs=execcondtable->get(record); + int size=srs==NULL?0:srs->getSize(); + if (branch!=NULL) + size++; + + Constraint *array[size]; + int index=0; + if (srs!=NULL) { + RecordIterator *sri=srs->iterator(); + while(sri->hasNext()) { + EPRecord *rec=sri->next(); + EPValue *recbranch=rec->getBranch(); + BranchRecord *guardbr=branchtable->get(recbranch->getRecord()); + array[index++]=guardbr->getBranch(recbranch)->negate(); + } + delete sri; + } + if (branch!=NULL) { + BranchRecord *guardbr=branchtable->get(branch->getRecord()); + array[index++]=guardbr->getBranch(branch); + } + if (index==0) + return &ctrue; + else if (index==1) + return array[0]; + else + return new Constraint(AND, index, array); +} + +bool ConstGen::isAlwaysExecuted(EPRecord *record) { + EPValue *branch=record->getBranch(); + RecordSet *srs=execcondtable->get(record); + int size=srs==NULL?0:srs->getSize(); + if (branch!=NULL) + size++; + + return size==0; +} + +void ConstGen::insertBranch(EPRecord *record) { + uint numvalue=record->numValues(); + /** need one value for new directions */ + if (numvaluegetLen()) + numvalue++; + /** need extra value to represent that branch wasn't executed. **/ + bool alwaysexecuted=isAlwaysExecuted(record); + if (!alwaysexecuted) + numvalue++; + uint numbits=NUMBITS(numvalue-1); + Constraint *bits[numbits]; + getArrayNewVars(numbits, bits); + BranchRecord *br=new BranchRecord(record, numbits, bits, alwaysexecuted); + branchtable->put(record, br); +} + +void ConstGen::processBranch(EPRecord *record) { + BranchRecord *br=branchtable->get(record); + if (record->numValues()getLen()) { + Constraint *goal=br->getNewBranch(); + ADDBRANCHGOAL(record, goal,"newbranch"); + } + + /** Insert criteria of parent branch going the right way. **/ + Constraint *baseconstraint=getExecutionConstraint(record); + + if (!isAlwaysExecuted(record)) { + Constraint *parentbranch=new Constraint(IMPLIES, br->getAnyBranch(), baseconstraint); + ADDCONSTRAINT(parentbranch, "parentbranch"); + } + + /** Insert criteria for directions */ + ModelVector * depvec=execution->getRevDependences(record, VC_BASEINDEX); + ASSERT(depvec->size()==1); + EPRecord * val_record=(*depvec)[0]; + for(unsigned int i=0;inumValues();i++) { + EPValue * branchval=record->getValue(i); + uint64_t val=branchval->getValue(); + + if (val==0) { + Constraint *execconstraint=getExecutionConstraint(record); + Constraint *br_false=new Constraint(IMPLIES, + new Constraint(AND, execconstraint, + getRetValueEncoding(val_record, val)), br->getBranch(branchval)); + ADDCONSTRAINT(br_false, "br_false"); + } else { + if (record->getBranchAnyValue()) { + if (getRetValueEncoding(val_record, 0)!=NULL) { + Constraint *execconstraint=getExecutionConstraint(record); + Constraint *br_true1=new Constraint(IMPLIES, new Constraint(AND, getRetValueEncoding(val_record, 0)->negate(), + execconstraint), + br->getBranch(branchval)); + ADDCONSTRAINT(br_true1, "br_true1"); + } else { + for(unsigned int j=0;jnumValues();j++) { + EPValue * epval=val_record->getValue(j); + Constraint *execconstraint=getExecutionConstraint(record); + Constraint *valuematches=getRetValueEncoding(val_record, epval->getValue()); + Constraint *br_true2=new Constraint(IMPLIES, new Constraint(AND, execconstraint, valuematches), br->getBranch(branchval)); + ADDCONSTRAINT(br_true2, "br_true2"); + } + } + } else { + Constraint *execconstraint=getExecutionConstraint(record); + Constraint *br_val=new Constraint(IMPLIES, new Constraint(AND, execconstraint, getRetValueEncoding(val_record, val)), br->getBranch(branchval)); + ADDCONSTRAINT(br_val, "br_val"); + } + } + } +} + +void ConstGen::insertFunction(EPRecord *record) { + FunctionRecord * fr=new FunctionRecord(this, record); + functiontable->put(record, fr); +} + +void ConstGen::insertEquals(EPRecord *record) { + EqualsRecord * fr=new EqualsRecord(this, record); + equalstable->put(record, fr); +} + +void ConstGen::processLoad(EPRecord *record) { + LoadRF * lrf=new LoadRF(record, this); + lrf->genConstraints(this); + delete lrf; + processAddresses(record); +} + +/** This procedure generates the constraints that set the address + variables for load/store/rmw operations. */ + +void ConstGen::processAddresses(EPRecord *record) { + StoreLoadSet *sls=getStoreLoadSet(record); + ModelVector * depvec=execution->getRevDependences(record, VC_ADDRINDEX); + if (depvec==NULL) { + //we have a hard coded address + const void *addr=record->getValue(0)->getAddr(); + Constraint *addrenc=sls->getAddressEncoding(this, record, addr); + ADDCONSTRAINT(addrenc,"fixedaddress"); + } else { + //we take as input an address and have to generate implications + //for each possible input address + ASSERT(depvec->size()==1); + EPRecord *src=(*depvec)[0]; + IntIterator *it=record->getSet(VC_ADDRINDEX)->iterator(); + + uintptr_t offset=record->getOffset(); + + while(it->hasNext()) { + uint64_t addr=it->next(); + Constraint *srcenc=getRetValueEncoding(src, addr-offset); + Constraint *addrenc=sls->getAddressEncoding(this, record, (void *) addr); + Constraint *addrmatch=new Constraint(IMPLIES, srcenc, addrenc); + ADDCONSTRAINT(addrmatch,"setaddress"); + } + delete it; + } +} + +void ConstGen::processCAS(EPRecord *record) { + //First do the load + LoadRF * lrf=new LoadRF(record, this); + lrf->genConstraints(this); + delete lrf; + //Next see if we are successful + Constraint *eq=getNewVar(); + ModelVector * depveccas=execution->getRevDependences(record, VC_OLDVALCASINDEX); + if (depveccas==NULL) { + //Hard coded old value + IntIterator *iit=record->getSet(VC_OLDVALCASINDEX)->iterator(); + uint64_t valcas=iit->next(); + delete iit; + Constraint *rmwr=getStoreLoadSet(record)->getRMWRValueEncoding(this, record, valcas); + if (rmwr==NULL) { + Constraint *cascond=eq->negate(); + ADDCONSTRAINT(cascond, "cascond"); + } else { + Constraint *cascond=generateEquivConstraint(eq, rmwr); + ADDCONSTRAINT(cascond, "cascond"); + } + } else { + ASSERT(depveccas->size()==1); + EPRecord *src=(*depveccas)[0]; + IntIterator *it=getStoreLoadSet(record)->getValues()->iterator(); + + while(it->hasNext()) { + uint64_t valcas=it->next(); + Constraint *srcenc=getRetValueEncoding(src, valcas); + Constraint *storeenc=getStoreLoadSet(record)->getRMWRValueEncoding(this, record, valcas); + + if (srcenc!=NULL && storeenc!=NULL) { + Constraint *cond=new Constraint(AND, + new Constraint(IMPLIES, srcenc->clone(), eq), + new Constraint(IMPLIES, eq, srcenc)); + Constraint *cas=new Constraint(IMPLIES, storeenc, cond); + ADDCONSTRAINT(cas, "cas"); + } else if (srcenc==NULL) { + Constraint *casfail=new Constraint(IMPLIES, storeenc, eq->negate()); + ADDCONSTRAINT(casfail,"casfail_eq"); + } else { + //srcenc must be non-null and store-encoding must be null + srcenc->free(); + } + } + delete it; + IntIterator *iit=record->getSet(VC_OLDVALCASINDEX)->iterator(); + while(iit->hasNext()) { + uint64_t val=iit->next(); + if (!getStoreLoadSet(record)->getValues()->contains(val)) { + Constraint *srcenc=getRetValueEncoding(src, val); + Constraint *casfail=new Constraint(IMPLIES, srcenc, eq->negate()); + ADDCONSTRAINT(casfail,"casfailretval"); + } + } + delete iit; + } + + ModelVector * depvec=execution->getRevDependences(record, VC_BASEINDEX); + if (depvec==NULL) { + IntIterator *iit=record->getSet(VC_BASEINDEX)->iterator(); + uint64_t val=iit->next(); + delete iit; + Constraint *storeenc=getMemValueEncoding(record, val); + Constraint *casmemsuc=new Constraint(IMPLIES, eq, storeenc); + ADDCONSTRAINT(casmemsuc, "casmemsuc"); + } else { + ASSERT(depvec->size()==1); + EPRecord *src=(*depvec)[0]; + IntIterator *it=record->getStoreSet()->iterator(); + + while(it->hasNext()) { + uint64_t val=it->next(); + Constraint *srcenc=getRetValueEncoding(src, val); + if (srcenc==NULL) { + //this can happen for values that are in the store set because + //we re-stored them on a failed CAS + continue; + } + Constraint *storeenc=getMemValueEncoding(record, val); + Constraint *storevalue=new Constraint(IMPLIES, new Constraint(AND, eq, srcenc), storeenc); + ADDCONSTRAINT(storevalue,"casmemsuc"); + } + delete it; + } + StoreLoadSet *sls=getStoreLoadSet(record); + + Constraint *repeatval=generateEquivConstraint(sls->getNumValVars(), sls->getValVars(this, record), sls->getRMWRValVars(this, record)); + Constraint *failcas=new Constraint(IMPLIES, eq->negate(), repeatval); + ADDCONSTRAINT(failcas,"casmemfail"); + + processAddresses(record); +} + +void ConstGen::processEXC(EPRecord *record) { + //First do the load + LoadRF * lrf=new LoadRF(record, this); + lrf->genConstraints(this); + delete lrf; + + ModelVector * depvec=execution->getRevDependences(record, VC_BASEINDEX); + if (depvec==NULL) { + IntIterator *iit=record->getSet(VC_BASEINDEX)->iterator(); + uint64_t val=iit->next(); + delete iit; + Constraint *storeenc=getMemValueEncoding(record, val); + ADDCONSTRAINT(storeenc, "excmemsuc"); + } else { + ASSERT(depvec->size()==1); + EPRecord *src=(*depvec)[0]; + IntIterator *it=record->getStoreSet()->iterator(); + + while(it->hasNext()) { + uint64_t val=it->next(); + Constraint *srcenc=getRetValueEncoding(src, val); + Constraint *storeenc=getMemValueEncoding(record, val); + Constraint *storevalue=new Constraint(IMPLIES, srcenc, storeenc); + ADDCONSTRAINT(storevalue,"excmemsuc"); + } + delete it; + } + + processAddresses(record); +} + +void ConstGen::processAdd(EPRecord *record) { + //First do the load + LoadRF * lrf=new LoadRF(record, this); + lrf->genConstraints(this); + delete lrf; + Constraint *var=getNewVar(); + Constraint *newadd=new Constraint(AND, var, getExecutionConstraint(record)); + ADDGOAL(record, newadd, "newadd"); + + ModelVector * depvec=execution->getRevDependences(record, VC_BASEINDEX); + if (depvec==NULL) { + IntIterator *valit=record->getSet(VC_BASEINDEX)->iterator(); + uint64_t val=valit->next(); + delete valit; + IntHashSet *valset=getStoreLoadSet(record)->getValues(); + IntIterator *sis=valset->iterator(); + while(sis->hasNext()) { + uint64_t memval=sis->next(); + uint64_t sumval=(memval+val)&getmask(record->getLen()); + + if (valset->contains(sumval)) { + + Constraint *loadenc=getStoreLoadSet(record)->getRMWRValueEncoding(this, record, memval); + Constraint *storeenc=getMemValueEncoding(record, sumval); + Constraint *notvar=var->negate(); + Constraint *addinputfix=new Constraint(IMPLIES, loadenc, new Constraint(AND, storeenc, notvar)); + ADDCONSTRAINT(addinputfix, "addinputfix"); + } + } + + delete sis; + } else { + ASSERT(depvec->size()==1); + EPRecord *src=(*depvec)[0]; + IntIterator *it=record->getStoreSet()->iterator(); + IntHashSet *valset=getStoreLoadSet(record)->getValues(); + + while(it->hasNext()) { + uint64_t val=it->next(); + IntIterator *sis=valset->iterator(); + while(sis->hasNext()) { + uint64_t memval=sis->next(); + uint64_t sum=(memval+val)&getmask(record->getLen()); + if (valset->contains(sum)) { + Constraint *srcenc=getRetValueEncoding(src, val); + Constraint *loadenc=getStoreLoadSet(record)->getRMWRValueEncoding(this, record, memval); + Constraint *storeenc=getMemValueEncoding(record, sum); + Constraint *notvar=var->negate(); + Constraint *addop=new Constraint(IMPLIES, new Constraint(AND, srcenc, loadenc), + new Constraint(AND, notvar, storeenc)); + ADDCONSTRAINT(addop,"addinputvar"); + } + } + delete sis; + } + delete it; + } + + processAddresses(record); +} + +/** This function ensures that the value of a store's SAT variables + matches the store's input value. + + TODO: Could optimize the case where the encodings are the same... +*/ + +void ConstGen::processStore(EPRecord *record) { + ModelVector * depvec=execution->getRevDependences(record, VC_BASEINDEX); + if (depvec==NULL) { + //We have a hard coded value + uint64_t val=record->getValue(0)->getValue(); + Constraint *storeenc=getMemValueEncoding(record, val); + ADDCONSTRAINT(storeenc,"storefix"); + } else { + //We have a value from an input + ASSERT(depvec->size()==1); + EPRecord *src=(*depvec)[0]; + IntIterator *it=record->getStoreSet()->iterator(); + + while(it->hasNext()) { + uint64_t val=it->next(); + Constraint *srcenc=getRetValueEncoding(src, val); + Constraint *storeenc=getMemValueEncoding(record, val); + Constraint *storevalue=new Constraint(IMPLIES, srcenc, storeenc); + ADDCONSTRAINT(storevalue,"storevar"); + } + delete it; + } + processAddresses(record); +} + +/** Handle yields by just forbidding them via the SAT formula. */ + +void ConstGen::processYield(EPRecord *record) { + if (model->params.noyields && + record->getBranch()!=NULL) { + Constraint * noyield=getExecutionConstraint(record)->negate(); + ADDCONSTRAINT(noyield, "noyield"); + } +} + +void ConstGen::processLoopPhi(EPRecord *record) { + EPRecordIDSet *phiset=record->getPhiLoopTable(); + EPRecordIDIterator *rit=phiset->iterator(); + + while(rit->hasNext()) { + struct RecordIDPair *rip=rit->next(); + EPRecord *input=rip->idrecord; + + IntIterator * it=record->getSet(VC_BASEINDEX)->iterator(); + while(it->hasNext()) { + uint64_t value=it->next(); + Constraint * inputencoding=getRetValueEncoding(input, value); + if (inputencoding==NULL) + continue; + Constraint * branchconstraint=getExecutionConstraint(rip->record); + Constraint * outputencoding=getRetValueEncoding(record, value); + Constraint * phiimplication=new Constraint(IMPLIES, new Constraint(AND, inputencoding, branchconstraint), outputencoding); + ADDCONSTRAINT(phiimplication,"philoop"); + } + delete it; + } + delete rit; +} + +void ConstGen::processPhi(EPRecord *record) { + ModelVector * inputs=execution->getRevDependences(record, VC_BASEINDEX); + for(uint i=0;isize();i++) { + EPRecord * input=(*inputs)[i]; + + IntIterator * it=record->getSet(VC_BASEINDEX)->iterator(); + while(it->hasNext()) { + uint64_t value=it->next(); + Constraint * inputencoding=getRetValueEncoding(input, value); + if (inputencoding==NULL) + continue; + Constraint * branchconstraint=getExecutionConstraint(input); + Constraint * outputencoding=getRetValueEncoding(record, value); + Constraint * phiimplication=new Constraint(IMPLIES, new Constraint(AND, inputencoding, branchconstraint), outputencoding); + ADDCONSTRAINT(phiimplication,"phi"); + } + delete it; + } +} + +void ConstGen::processFunction(EPRecord *record) { + if (record->getLoopPhi()) { + processLoopPhi(record); + return; + } else if (record->getPhi()) { + processPhi(record); + return; + } + + CGoalSet *knownbehaviors=record->completedGoalSet(); + CGoalIterator *cit=knownbehaviors->iterator(); + uint numinputs=record->getNumFuncInputs(); + EPRecord * inputs[numinputs]; + for(uint i=0;i * depvec=execution->getRevDependences(record, i+VC_BASEINDEX); + ASSERT(depvec->size()==1); + inputs[i]=(*depvec)[0]; + } + while(cit->hasNext()) { + CGoal *goal=cit->next(); + Constraint *carray[numinputs]; + if (record->isSharedGoals()) { + bool badvalue=false; + for(uint i=0;igetValue(i+VC_BASEINDEX); + if (!record->getSet(i+VC_BASEINDEX)->contains(inputval)) { + badvalue=true; + break; + } + } + if (badvalue) + continue; + } + + /* Build up constraints for each input */ + for(uint i=0;igetValue(i+VC_BASEINDEX); + Constraint * inputc=getRetValueEncoding(inputs[i], inputval); + ASSERT(inputc!=NULL); + carray[i]=inputc; + } + Constraint * outputconstraint=getRetValueEncoding(record, goal->getOutput()); + if (numinputs==0) { + ADDCONSTRAINT(outputconstraint,"functionimpl"); + } else { + Constraint * functionimplication=new Constraint(IMPLIES, new Constraint(AND, numinputs, carray), outputconstraint); + ADDCONSTRAINT(functionimplication,"functionimpl"); + } + } + delete cit; + + FunctionRecord *fr=functiontable->get(record); + Constraint *goal=fr->getNoValueEncoding(); + Constraint *newfunc=new Constraint(AND, goal, getExecutionConstraint(record)); + ADDGOAL(record, newfunc, "newfunc"); +} + +void ConstGen::processEquals(EPRecord *record) { + ASSERT (record->getNumFuncInputs() == 2); + EPRecord * inputs[2]; + + for(uint i=0;i<2;i++) { + ModelVector * depvec=execution->getRevDependences(record, i+VC_BASEINDEX); + if (depvec==NULL) { + inputs[i]=NULL; + } else if (depvec->size()==1) { + inputs[i]=(*depvec)[0]; + } else ASSERT(false); + } + + //rely on this being a variable + Constraint * outputtrue=getRetValueEncoding(record, 1); + ASSERT(outputtrue->getType()==VAR); + + if (inputs[0]!=NULL && inputs[1]!=NULL && + (inputs[0]->getType()==LOAD || inputs[0]->getType()==RMW) && + (inputs[1]->getType()==LOAD || inputs[1]->getType()==RMW) && + (getStoreLoadSet(inputs[0])==getStoreLoadSet(inputs[1]))) { + StoreLoadSet * sls=getStoreLoadSet(inputs[0]); + int numvalvars=sls->getNumValVars(); + Constraint **valvar1=(inputs[0]->getType()==RMW)?sls->getRMWRValVars(this, inputs[0]):sls->getValVars(this, inputs[0]); + Constraint **valvar2=(inputs[1]->getType()==RMW)?sls->getRMWRValVars(this, inputs[1]):sls->getValVars(this, inputs[1]); + //new test + + Constraint *vars[numvalvars]; + for(int i=0;inegate(), vars[i]->negate()}; + Constraint * array2[]={var2, var1->negate(), vars[i]->negate()}; + Constraint * a=new Constraint(OR, 3, array); + ADDCONSTRAINT(a, "equala"); + Constraint * a2=new Constraint(OR, 3, array2); + ADDCONSTRAINT(a2, "equala2"); + Constraint * arrayb[]={var1, var2, vars[i]}; + Constraint * array2b[]={var2->negate(), var1->negate(), vars[i]}; + Constraint * b=new Constraint(OR, 3, arrayb); + ADDCONSTRAINT(b, "equalb"); + Constraint *b2=new Constraint(OR, 3, array2b); + ADDCONSTRAINT(b2, "equalb2"); + } + ADDCONSTRAINT(new Constraint(IMPLIES, new Constraint(AND, numvalvars, vars), outputtrue),"impequal1"); + + ADDCONSTRAINT(new Constraint(IMPLIES, outputtrue, new Constraint(AND, numvalvars, vars)), "impequal2"); + + /* + + Constraint * functionimplication=new Constraint(IMPLIES,generateEquivConstraint(numvalvars, valvar1, valvar2), outputtrue); + ADDCONSTRAINT(functionimplication,"equalsimplspecial"); + Constraint * functionimplicationneg=new Constraint(IMPLIES,outputtrue, generateEquivConstraint(numvalvars, valvar1, valvar2)); + ADDCONSTRAINT(functionimplicationneg,"equalsimplspecialneg"); + */ + return; + } + + if (inputs[0]==NULL && inputs[1]==NULL) { + IntIterator *iit0=record->getSet(VC_BASEINDEX+0)->iterator(); + uint64_t constval=iit0->next(); + delete iit0; + IntIterator *iit1=record->getSet(VC_BASEINDEX+1)->iterator(); + uint64_t constval2=iit1->next(); + delete iit1; + + if (constval==constval2) { + ADDCONSTRAINT(outputtrue, "equalsconst"); + } else { + ADDCONSTRAINT(outputtrue->negate(), "equalsconst"); + } + return; + } + + if (inputs[0]==NULL || + inputs[1]==NULL) { + int nullindex=inputs[0]==NULL?0:1; + IntIterator *iit=record->getSet(VC_BASEINDEX+nullindex)->iterator(); + uint64_t constval=iit->next(); + delete iit; + + record->getSet(VC_BASEINDEX+nullindex); + EPRecord *r=inputs[1-nullindex]; + Constraint *l=getRetValueEncoding(r, constval); + Constraint *functionimplication=new Constraint(IMPLIES, l, outputtrue); + ADDCONSTRAINT(functionimplication,"equalsimpl"); + + Constraint *l2=getRetValueEncoding(r, constval); + Constraint *functionimplication2=new Constraint(IMPLIES, outputtrue, l2); + ADDCONSTRAINT(functionimplication2,"equalsimpl"); + } + + IntIterator *iit=record->getSet(VC_BASEINDEX)->iterator(); + while(iit->hasNext()) { + uint64_t val1=iit->next(); + + IntIterator *iit2=record->getSet(VC_BASEINDEX+1)->iterator(); + while(iit2->hasNext()) { + uint64_t val2=iit2->next(); + Constraint *l=getRetValueEncoding(inputs[0], val1); + Constraint *r=getRetValueEncoding(inputs[1], val2); + Constraint *imp=(val1==val2)?outputtrue:outputtrue->negate(); + Constraint * functionimplication=new Constraint(IMPLIES, new Constraint(AND, l, r), imp); + ADDCONSTRAINT(functionimplication,"equalsimpl"); + } + delete iit2; + } + delete iit; +} + +#ifdef TSO +void ConstGen::processFence(EPRecord *record) { + //do we already account for the fence? + if (isAlwaysExecuted(record)) + return; + ExecPoint * record_ep=record->getEP(); + thread_id_t tid=record_ep->get_tid(); + uint thread=id_to_int(tid); + ModelVector *tvec=(*threadactions)[thread]; + uint size=tvec->size(); + + EPRecord *prevstore=NULL; + uint i; + for(i=0;igetType()==STORE) { + prevstore=rec; + } + if (rec == record) { + i++; + break; + } + } + if (prevstore == NULL) { + return; + } + for(;igetType()==LOAD) { + Constraint * condition=getExecutionConstraint(record); + Constraint * storeload=getOrderConstraint(prevstore, rec); + Constraint * c=new Constraint(IMPLIES, condition, storeload); + ADDCONSTRAINT(c, "fence"); + return; + } + } +} +#endif + +void ConstGen::processRecord(EPRecord *record) { + switch (record->getType()) { + case FUNCTION: + processFunction(record); + break; + case EQUALS: + processEquals(record); + break; + case LOAD: + processLoad(record); + break; + case STORE: + processStore(record); + break; +#ifdef TSO + case FENCE: + processFence(record); + break; +#endif + case RMW: +#ifdef TSO + processFence(record); +#endif + if (record->getOp()==ADD) { + processAdd(record); + } else if (record->getOp()==CAS) { + processCAS(record); + } else if (record->getOp()==EXC) { + processEXC(record); + } else + ASSERT(0); + break; + case YIELD: + processYield(record); + break; + case BRANCHDIR: + processBranch(record); + break; + default: + break; + } +} + +void ConstGen::visitRecord(EPRecord *record) { + switch (record->getType()) { + case EQUALS: + recordExecCond(record); + insertEquals(record); + break; + case FUNCTION: + recordExecCond(record); + insertFunction(record); + break; +#ifdef TSO + case FENCE: + recordExecCond(record); + insertAction(record); + break; +#endif + case LOAD: + recordExecCond(record); + insertAction(record); + groupMemoryOperations(record); + break; + case STORE: + recordExecCond(record); + insertAction(record); + groupMemoryOperations(record); + break; + case RMW: + recordExecCond(record); + insertAction(record); + groupMemoryOperations(record); + break; + case BRANCHDIR: + recordExecCond(record); + insertBranch(record); + break; + case NONLOCALTRANS: + recordExecCond(record); + insertNonLocal(record); + break; + case LABEL: + insertLabel(record); + break; + case YIELD: + recordExecCond(record); + break; + default: + break; + } +} + +void ConstGen::recordExecCond(EPRecord *record) { + ExecPoint *eprecord=record->getEP(); + EPValue * branchval=record->getBranch(); + EPRecord * branch=(branchval==NULL)?NULL:branchval->getRecord(); + ExecPoint *epbranch= (branch==NULL) ? NULL : branch->getEP(); + RecordSet *srs=NULL; + RecordIterator *sri=nonlocaltrans->iterator(); + while(sri->hasNext()) { + EPRecord *nonlocal=sri->next(); + ExecPoint *epnl=nonlocal->getEP(); + if (epbranch!=NULL) { + if (epbranch->compare(epnl)==CR_BEFORE) { + //branch occurs after non local and thus will subsume condition + //branch subsumes this condition + continue; + } + } + if (eprecord->compare(epnl)==CR_BEFORE) { + //record occurs after non-local, so add it to set + if (srs==NULL) + srs=new RecordSet(); + srs->add(nonlocal); + } + } + delete sri; + if (srs!=NULL) + execcondtable->put(record, srs); +} + +void ConstGen::insertNonLocal(EPRecord *record) { + nonlocaltrans->add(record); +} + +void ConstGen::insertLabel(EPRecord *record) { + RecordIterator *sri=nonlocaltrans->iterator(); + while(sri->hasNext()) { + EPRecord *nonlocal=sri->next(); + if (nonlocal->getNextRecord()==record) + sri->remove(); + } + + delete sri; +} + +void ConstGen::traverseRecord(EPRecord *record, bool initial) { + do { + if (initial) { + visitRecord(record); + } else { + processRecord(record); + } + if (record->getType()==LOOPENTER) { + workstack->push_back(record->getNextRecord()); + workstack->push_back(record->getChildRecord()); + return; + } + if (record->getChildRecord()!=NULL) { + workstack->push_back(record->getChildRecord()); + } + if (record->getType()==NONLOCALTRANS) { + return; + } + if (record->getType()==BRANCHDIR) { + EPRecord *next=record->getNextRecord(); + if (next != NULL) + workstack->push_back(next); + for(uint i=0;inumValues();i++) { + EPValue *branchdir=record->getValue(i); + + //Could have an empty branch, so make sure the branch actually + //runs code + if (branchdir->getFirstRecord()!=NULL) + workstack->push_back(branchdir->getFirstRecord()); + } + return; + } else + record=record->getNextRecord(); + } while(record!=NULL); +} + +unsigned int RecPairHash(RecPair *rp) { + uintptr_t v=(uintptr_t) rp->epr1; + uintptr_t v2=(uintptr_t) rp->epr2; + uintptr_t x=v^v2; + uintptr_t a=v&v2; + return (uint)((x>>4)^(a)); +} + +bool RecPairEquals(RecPair *r1, RecPair *r2) { + return ((r1->epr1==r2->epr1)&&(r1->epr2==r2->epr2)) || + ((r1->epr1==r2->epr2)&&(r1->epr2==r2->epr1)); +} diff --git a/constgen.h b/constgen.h new file mode 100644 index 0000000..68c02e7 --- /dev/null +++ b/constgen.h @@ -0,0 +1,182 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef CONSTGEN_H +#define CONSTGEN_H +#include "classlist.h" +#include "stl-model.h" + + +#ifdef VERBOSE_CONSTRAINTS +#define ADDCONSTRAINT(cn, str) do {Constraint *c=cn; model_print("%s ",str);c->print();model_print("\n");addConstraint(c);} while(0); +#define ADDCONSTRAINT2(cg, cn, str) do {Constraint *c=cn; model_print("%s ",str);c->print();model_print("\n");cg->addConstraint(c);} while(0); + +#define ADDGOAL(r, cn, str) do {Constraint *c=cn; model_print("%s ",str);c->print();model_print("\n");addGoal(r, c);} while(0); +#define ADDBRANCHGOAL(r, cn, str) do {Constraint *c=cn; model_print("%s ",str);c->print();model_print("\n");addBranchGoal(r, c);} while(0); +#else + +#define ADDCONSTRAINT(cn, store) addConstraint(cn); +#define ADDCONSTRAINT2(cg, cn, store) cg->addConstraint(cn); + +#define ADDGOAL(r, cn, store) addGoal(r, cn); +#define ADDBRANCHGOAL(r, cn, store) addBranchGoal(r, cn); +#endif + +unsigned int RecPairHash(RecPair *rp); +bool RecPairEquals(RecPair *r1, RecPair *r2); +typedef HashTable RecPairTable; + +typedef HashTable RecToIntTable; + +#ifdef STATS +struct MC_Stat { + long long time; + int bgoals; + int fgoals; + bool was_incremental; + bool was_sat; + MEMALLOC; +}; +#endif + +class ConstGen { + public: + ConstGen(MCExecution *e); + ~ConstGen(); + bool process(); + void reset(); + bool canReuseEncoding(); + Constraint * getNewVar(); + void getArrayNewVars(uint num, Constraint **); + RecordSet * computeConflictSet(EPRecord *store, EPRecord *load, RecordSet *baseset); + RecordSet * getMayReadFromSet(EPRecord *load); + RecordSet * getMayReadFromSetOpt(EPRecord *load); + void addConstraint(Constraint *c); + bool * runSolver(); + StoreLoadSet * getStoreLoadSet(EPRecord *op); + Constraint * getOrderConstraint(EPRecord *first, EPRecord *second); + Constraint * getExecutionConstraint(EPRecord *record); + bool isAlwaysExecuted(EPRecord *record); + BranchRecord * getBranchRecord(EPRecord *branch) {return branchtable->get(branch);} + bool getOrder(EPRecord *first, EPRecord *second, bool * satsolution); + void printConstraint(uint value); + void printNegConstraint(uint value); + void achievedGoal(EPRecord *record); +#ifdef STATS + MC_Stat *curr_stat; +#endif + + MEMALLOC; + private: + Constraint * getRetValueEncoding(EPRecord *record, uint64_t value); + Constraint * getMemValueEncoding(EPRecord *record, uint64_t value); + bool subsumesExecutionConstraint(EPRecord *recordsubsumes, EPRecord *record); + + void addBranchGoal(EPRecord *, Constraint *c); + void addGoal(EPRecord *, Constraint *c); + void translateGoals(); + + /** Methods to print execution graph .*/ + void printEventGraph(); + void printRecord(EPRecord *record, int file); + void doPrint(EPRecord *record, int file); + + /** Methods to traverse execution graph .*/ + void traverse(bool initial); + void traverseRecord(EPRecord *record, bool initial); + + /** Methods for initially visit records */ + void visitRecord(EPRecord *record); + void insertAction(EPRecord *record); + void insertFunction(EPRecord *record); + void insertEquals(EPRecord *record); + void insertBranch(EPRecord *record); + void insertNonLocal(EPRecord *record); + void insertLabel(EPRecord *record); + + /** Methods for second pass over records */ + void processRecord(EPRecord *record); + void processYield(EPRecord *record); + void processFunction(EPRecord *record); + void processEquals(EPRecord *record); + void processLoopPhi(EPRecord *record); + void processPhi(EPRecord *record); + void processCAS(EPRecord *record); + void processEXC(EPRecord *record); + void processAdd(EPRecord *record); + void processStore(EPRecord *record); + void processBranch(EPRecord *record); + void processLoad(EPRecord *record); + void processAddresses(EPRecord *record); + void recordExecCond(EPRecord *record); + + /** TSO Specific methods */ +#ifdef TSO + void genTSOTransOrderConstraints(); + void insertTSOAction(EPRecord *record); + void processFence(EPRecord *record); +#endif + + /** These functions build closed groups of memory operations that + can store/load from each other. */ + void groupMemoryOperations(EPRecord *op); + void mergeSets(StoreLoadSet *to, StoreLoadSet *from); + + bool orderThread(EPRecord *first, EPRecord *second); + void createOrderConstraint(EPRecord *r1, EPRecord *r2); + void genTransOrderConstraints(); + void genTransOrderConstraints(ModelVector * t1vec, ModelVector *t2vec, ModelVector * t3vec); + void genTransOrderConstraints(ModelVector * t1vec, ModelVector *t2vec); + void genTransOrderConstraint(EPRecord *t1rec, EPRecord *t2rec, EPRecord *t3rec); + + /** The hashtable maps an address to the closure set of + memory operations that may touch that address. */ + StoreLoadSetHashTable *storeloadtable; + /** This hashtable maps a load to all of the stores it may read + from. */ + LoadHashTable *loadtable; + + MCExecution *execution; + ModelVector * workstack; + ModelVector *> * threadactions; + RecPairTable *rpt; + uint numconstraints; + ModelVector * goalset; + Constraint ** goalvararray; + ModelVector * vars; + BranchTable * branchtable; + FunctionTable *functiontable; + EqualsTable *equalstable; + ScheduleBuilder *schedulebuilder; + RecordSet *nonlocaltrans; + LoadHashTable *execcondtable; + IncrementalSolver *solver; + RecToIntTable *rectoint; +#ifdef STATS + ModelVector * stats; +#endif + uint varindex; + int schedule_graph; + bool has_untaken_branches; +}; + +class RecPair { + public: + RecPair(EPRecord *r1, EPRecord *r2) : + epr1(r1), + epr2(r2), + constraint(NULL) { + } + EPRecord *epr1; + EPRecord *epr2; + Constraint *constraint; + MEMALLOC; +}; + +#endif diff --git a/constraint.cc b/constraint.cc new file mode 100644 index 0000000..457eaab --- /dev/null +++ b/constraint.cc @@ -0,0 +1,423 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "constraint.h" +#include "mymemory.h" +#include "constgen.h" + +Constraint ctrue(TRUE); +Constraint cfalse(FALSE); + +Constraint::Constraint(CType t, Constraint *l, Constraint *r) : + type(t), + numoperandsorvar(2), + operands((Constraint **)model_malloc(2*sizeof(Constraint *))), + neg(NULL) +{ + ASSERT(l!=NULL); + //if (type==IMPLIES) { + //type=OR; + // operands[0]=l->negate(); + // } else { + operands[0]=l; + // } + operands[1]=r; +} + +Constraint::Constraint(CType t, Constraint *l) : + type(t), + numoperandsorvar(1), + operands((Constraint **)model_malloc(sizeof(Constraint *))), + neg(NULL) +{ + operands[0]=l; +} + +Constraint::Constraint(CType t, uint num, Constraint **array) : + type(t), + numoperandsorvar(num), + operands((Constraint **)model_malloc(num*sizeof(Constraint *))), + neg(NULL) +{ + memcpy(operands, array, num*sizeof(Constraint *)); +} + +Constraint::Constraint(CType t) : + type(t), + numoperandsorvar(0xffffffff), + operands(NULL), + neg(NULL) +{ +} + +Constraint::Constraint(CType t, uint v) : + type(t), + numoperandsorvar(v), + operands(NULL), + neg(NULL) +{ +} + +Constraint::~Constraint() { + if (operands!=NULL) + model_free(operands); +} + +void Constraint::printDIMACS(ConstGen *cg) { + if (type==VAR) { + cg->printConstraint(numoperandsorvar); + cg->printConstraint(0); + } else if (type==NOTVAR) { + cg->printNegConstraint(numoperandsorvar); + cg->printConstraint(0); + } else { + ASSERT(type==OR); + for(uint i=0;itype==VAR) { + cg->printConstraint(c->numoperandsorvar); + } else if (c->type==NOTVAR) { + cg->printNegConstraint(c->numoperandsorvar); + } else ASSERT(0); + } + cg->printConstraint(0); + } +} + +void Constraint::free() { + switch(type) { + case TRUE: + case FALSE: + case NOTVAR: + case VAR: + return; + case BOGUS: + ASSERT(0); + default: + type=BOGUS; + delete this; + } +} + +void Constraint::freerec() { + switch(type) { + case TRUE: + case FALSE: + case NOTVAR: + case VAR: + return; + case BOGUS: + ASSERT(0); + default: + if (operands!=NULL) { + for(uint i=0;ifreerec(); + } + type=BOGUS; + delete this; + } +} + + +void Constraint::print() { + switch(type) { + case TRUE: + model_print("true"); + break; + case FALSE: + model_print("false"); + break; + case IMPLIES: + model_print("("); + operands[0]->print(); + model_print(")"); + model_print("=>"); + model_print("("); + operands[1]->print(); + model_print(")"); + break; + case AND: + case OR: + model_print("("); + for(uint i=0;iprint(); + } + model_print(")"); + break; + case VAR: + model_print("t%u",numoperandsorvar); + break; + case NOTVAR: + model_print("!t%u",numoperandsorvar); + break; + default: + ASSERT(0); + } +} + +Constraint * Constraint::clone() { + switch(type) { + case TRUE: + case FALSE: + case VAR: + case NOTVAR: + return this; + case IMPLIES: + return new Constraint(IMPLIES, operands[0]->clone(), operands[1]->clone()); + case AND: + case OR: { + Constraint *array[numoperandsorvar]; + for(uint i=0;iclone(); + } + return new Constraint(type, numoperandsorvar, array); + } + default: + ASSERT(0); + return NULL; + } +} + +Constraint * generateConstraint(uint numvars, Constraint ** vars, uint value) { + Constraint *carray[numvars]; + for(uint j=0;jnegate(); + value=value>>1; + } + + return new Constraint(AND, numvars, carray); +} + +/** Generates a constraint to ensure that all encodings are less than value */ +Constraint * generateLTConstraint(ConstGen *cg, uint numvars, Constraint ** vars, uint value) { + Constraint *orarray[numvars]; + Constraint *andarray[numvars]; + uint andi=0; + + while(true) { + uint val=value; + uint ori=0; + for(uint j=0;jnegate(); + val=val>>1; + } + //no ones to flip, so bail now... + if (ori==0) { + return new Constraint(AND, andi, andarray); + } + andarray[andi++]=new Constraint(OR, ori, orarray); + + value=value+(1<<(__builtin_ctz(value)));//flip the last one + } +} + +Constraint * generateEquivConstraint(uint numvars, Constraint **var1, Constraint **var2) { + if (numvars==0) + return &ctrue; + Constraint *array[numvars*2]; + for(uint i=0;iclone()->negate(), var2[i]); + array[i*2+1]=new Constraint(OR, var1[i], var2[i]->clone()->negate()); + } + return new Constraint(AND, numvars*2, array); +} + +Constraint * generateEquivConstraint(Constraint *var1, Constraint *var2) { + Constraint * imp1=new Constraint(OR, var1->clone()->negate(), var2); + Constraint * imp2=new Constraint(OR, var1, var2->clone()->negate()); + + return new Constraint(AND, imp1, imp2); +} + +bool mergeandfree(ModelVector * to, ModelVector * from) { + for(uint i=0;isize();i++) { + Constraint *c=(*from)[i]; + if (c->type==TRUE) + continue; + if (c->type==FALSE) { + for(uint j=i+1;jsize();j++) + (*from)[j]->freerec(); + for(uint j=0;jsize();j++) + (*to)[j]->freerec(); + to->clear(); + to->push_back(&ctrue); + delete from; + return true; + } + to->push_back(c); + } + delete from; + return false; +} + +ModelVector * Constraint::simplify() { + switch(type) { + case TRUE: + case VAR: + case NOTVAR: + case FALSE: { + ModelVector *vec=new ModelVector(); + vec->push_back(this); + return vec; + } + case AND: { + ModelVector *vec=new ModelVector(); + for(uint i=0;i *subvec=operands[i]->simplify(); + if (mergeandfree(vec, subvec)) { + for(uint j=i+1;jfreerec(); + } + this->free(); + return vec; + } + } + this->free(); + return vec; + } + case OR: { + for(uint i=0;itype) { + case TRUE: { + ModelVector *vec=new ModelVector(); + vec->push_back(c); + this->freerec(); + return vec; + } + case FALSE: { + Constraint *array[numoperandsorvar-1]; + uint index=0; + for(uint j=0;j *vec=cn->simplify(); + this->free(); + return vec; + } + case VAR: + case NOTVAR: + break; + case OR: { + uint nsize=numoperandsorvar+c->numoperandsorvar-1; + Constraint *array[nsize]; + uint index=0; + for(uint j=0;jnumoperandsorvar;j++) + array[index++]=c->operands[j]; + Constraint *cn=new Constraint(OR, nsize, array); + ModelVector *vec=cn->simplify(); + this->free(); + c->free(); + return vec; + } + case IMPLIES: { + uint nsize=numoperandsorvar+1; + Constraint *array[nsize]; + uint index=0; + for(uint j=0;joperands[0]->negate(); + array[index++]=c->operands[1]; + Constraint *cn=new Constraint(OR, nsize, array); + ModelVector *vec=cn->simplify(); + this->free(); + c->free(); + return vec; + } + case AND: { + Constraint *array[numoperandsorvar]; + + ModelVector *vec=new ModelVector(); + for(uint j=0;jnumoperandsorvar;j++) { + //copy other elements + for(uint k=0;kclone(); + } + } + + array[i]=c->operands[j]->clone(); + Constraint *cn=new Constraint(OR, numoperandsorvar, array); + ModelVector * newvec=cn->simplify(); + if (mergeandfree(vec, newvec)) { + this->freerec(); + return vec; + } + } + this->freerec(); + return vec; + } + default: + ASSERT(0); + } + //continue on to next item + } + ModelVector *vec=new ModelVector(); + if (numoperandsorvar==1) { + Constraint *c=operands[0]; + this->freerec(); + vec->push_back(c); + } else + vec->push_back(this); + return vec; + } + case IMPLIES: { + Constraint *cn=new Constraint(OR, operands[0]->negate(), operands[1]); + ModelVector *vec=cn->simplify(); + this->free(); + return vec; + } + default: + ASSERT(0); + return NULL; + } +} + +Constraint * Constraint::negate() { + switch(type) { + case TRUE: + return &cfalse; + case FALSE: + return &ctrue; + case NOTVAR: + case VAR: + return this->neg; + case IMPLIES: { + Constraint *l=operands[0]; + Constraint *r=operands[1]; + operands[0]=r; + operands[1]=l; + return this; + } + case AND: + case OR: { + for(uint i=0;inegate(); + } + type=(type==AND)?OR:AND; + return this; + } + default: + ASSERT(0); + return NULL; + } +} diff --git a/constraint.h b/constraint.h new file mode 100644 index 0000000..bf97b31 --- /dev/null +++ b/constraint.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef CONSTRAINT_H +#define CONSTRAINT_H +#include "classlist.h" +#include "stl-model.h" + +enum ConstraintType { + TRUE, FALSE, IMPLIES, AND, OR, VAR, NOTVAR, BOGUS +}; + +typedef enum ConstraintType CType; + +class Constraint { + public: + Constraint(CType t, Constraint *l, Constraint *r); + Constraint(CType t, Constraint *l); + Constraint(CType t, uint num, Constraint ** array); + Constraint(CType t, uint var); + Constraint(CType t); + ~Constraint(); + void print(); + void printDIMACS(ConstGen *cg); + uint getVar() {ASSERT(type==VAR); return numoperandsorvar;} + ModelVector * simplify(); + CType getType() {return type;} + bool isFalse() {return type==FALSE;} + bool isTrue() {return type==TRUE;} + void free(); + void freerec(); + Constraint * clone(); + void setNeg(Constraint *c) {neg=c;} + Constraint *negate(); + + MEMALLOC; + private: + CType type; + uint numoperandsorvar; + Constraint ** operands; + Constraint *neg; + friend class ConstGen; + friend bool mergeandfree(ModelVector * to, ModelVector * from); +}; + +extern Constraint ctrue; +extern Constraint cfalse; + +Constraint * generateConstraint(uint numvars, Constraint ** vars, uint value); +Constraint * generateLTConstraint(ConstGen *cg, uint numvars, Constraint ** vars, uint value); +Constraint * generateEquivConstraint(uint numvars, Constraint **var1, Constraint **var2); +Constraint * generateEquivConstraint(Constraint *var1, Constraint *var2); +#endif diff --git a/context.cc b/context.cc new file mode 100644 index 0000000..7081656 --- /dev/null +++ b/context.cc @@ -0,0 +1,36 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "context.h" + +#ifdef MAC + +int model_swapcontext(ucontext_t *oucp, ucontext_t *ucp) +{ + /* + * Mac OSX swapcontext() clobbers some registers, so use a hand-rolled + * version with {get,set}context(). We can avoid the same problem + * (where optimizations can break the following code) because we don't + * statically link with the C library + */ + + /* volatile, so that 'i' doesn't get promoted to a register */ + volatile int i = 0; + + getcontext(oucp); + + if (i == 0) { + i = 1; + setcontext(ucp); + } + + return 0; +} + +#endif /* MAC */ diff --git a/context.h b/context.h new file mode 100644 index 0000000..948d89f --- /dev/null +++ b/context.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** + * @file context.h + * @brief ucontext header, since Mac OSX swapcontext() is broken + */ + +#ifndef __CONTEXT_H__ +#define __CONTEXT_H__ + +#include + +#ifdef MAC + +int model_swapcontext(ucontext_t *oucp, ucontext_t *ucp); + +#else /* !MAC */ + +static inline int model_swapcontext(ucontext_t *oucp, ucontext_t *ucp) +{ + return swapcontext(oucp, ucp); +} + +#endif /* !MAC */ + +#endif /* __CONTEXT_H__ */ diff --git a/eprecord.cc b/eprecord.cc new file mode 100644 index 0000000..c7bf25f --- /dev/null +++ b/eprecord.cc @@ -0,0 +1,236 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "eprecord.h" +#include "change.h" +#include "model.h" +#include "planner.h" + +EPRecord::EPRecord(EventType _event, ExecPoint *_execpoint, EPValue *_branch, uintptr_t _offset, unsigned int _numinputs, uint _len, bool _anyvalue) : + valuevector(new ValueVector()), + execpoint(_execpoint), + completed(NULL), + branch(_branch), + setarray((IntHashSet **)model_malloc(sizeof(IntHashSet *)*(_numinputs+VC_BASEINDEX))), + nextRecord(NULL), + childRecord(NULL), + philooptable(NULL), + offset(_offset), + event(_event), + jointhread(THREAD_ID_T_NONE), + numinputs(_numinputs+VC_BASEINDEX), + len(_len), + anyvalue(_anyvalue), + phi(false), + loopphi(false), + size(0), + func_shares_goalset(false), + ptr(NULL) +{ + for(unsigned int i=0;iiterator(); + while(rit->hasNext()) { + struct RecordIDPair *val=rit->next(); + model_free(val); + } + delete rit; + delete philooptable; + } + model_free(setarray); +} + +const char * eventToStr(EventType event) { + switch(event) { + case ALLOC: + return "alloc"; + case LOAD: + return "load"; + case RMW: + return "rmw"; + case STORE: + return "store"; + case BRANCHDIR: + return "br_dir"; + case MERGE: + return "merge"; + case FUNCTION: + return "func"; + case EQUALS: + return "equals"; + case THREADCREATE: + return "thr_create"; + case THREADBEGIN: + return "thr_begin"; + case THREADJOIN: + return "join"; + case YIELD: + return "yield"; + case NONLOCALTRANS: + return "nonlocal"; + case LABEL: + return "label"; + case LOOPENTER: + return "loopenter"; + case LOOPSTART: + return "loopstart"; + case FENCE: + return "fence"; + default: + return "unknown"; + } +} + +IntHashSet * EPRecord::getReturnValueSet() { + switch(event) { + case FUNCTION: + case EQUALS: + return getSet(VC_FUNCOUTINDEX); + case RMW: + return getSet(VC_RMWOUTINDEX); + case LOAD: + return getSet(VC_RFINDEX); + case ALLOC: + case BRANCHDIR: + case MERGE: + case STORE: + case THREADCREATE: + case THREADBEGIN: + case THREADJOIN: + case YIELD: + case FENCE: + case NONLOCALTRANS: + case LABEL: + case LOOPENTER: + case LOOPSTART: + ASSERT(false); + return NULL; + default: + ASSERT(false); + return NULL; + } +} + +void EPRecord::print(int f) { + if (event==RMW) { + if (op==ADD) + dprintf(f, "add"); + else if (op==EXC) + dprintf(f, "exc"); + else + dprintf(f, "cas"); + } else + dprintf(f, "%s",eventToStr(event)); + IntHashSet *i=NULL; + switch(event) { + case LOAD: + i=setarray[VC_RFINDEX]; + break; + case STORE: + i=setarray[VC_BASEINDEX]; + break; + case RMW: + i=setarray[VC_RMWOUTINDEX]; + break; + case FUNCTION: { + if (!getPhi()) { + CGoalIterator *cit=completed->iterator(); + dprintf(f, "{"); + while(cit->hasNext()) { + CGoal *goal=cit->next(); + dprintf(f,"("); + for(uint i=0;igetValue(i+VC_BASEINDEX)); + } + dprintf(f,"=> %lu)", goal->getOutput()); + } + delete cit; + } + break; + } + default: + ; + } + if (i!=NULL) { + IntIterator *it=i->iterator(); + dprintf(f, "{"); + + while(it->hasNext()) { + dprintf(f, "%lu ", it->next()); + } + dprintf(f, "}"); + delete it; + } + + for(uint i=0;iiterator(); + dprintf(f,"{"); + while(it->hasNext()) { + uint64_t v=it->next(); + dprintf(f,"%lu ", v); + } + dprintf(f,"}"); + delete it; + } + dprintf(f, "}"); + + + execpoint->print(f); +} + +void EPRecord::print() { + model_print("%s",eventToStr(event)); + execpoint->print(); + model_print(" CR=%p ", this); + model_print(" NR=%p", nextRecord); +} + +bool EPRecord::hasAddr(const void * addr) { + return getSet(VC_ADDRINDEX)->contains((uintptr_t)addr); +} + +int EPRecord::getIndex(EPValue *val) { + for(unsigned int i=0;isize();i++) { + EPValue *epv=(*valuevector)[i]; + if (epv==val) + return i; + } + return -1; +} + +int EPRecord::getIndex(uint64_t val) { + for(unsigned int i=0;isize();i++) { + EPValue *epv=(*valuevector)[i]; + if (epv->getValue()==val) + return i; + } + return -1; +} + +bool EPRecord::hasValue(uint64_t val) { + for(unsigned int i=0;isize();i++) { + EPValue *epv=(*valuevector)[i]; + if (epv->getValue()==val) + return true; + } + return false; +} + +bool compatibleStoreLoad(EPRecord *store, EPRecord *load) { + return true; +} diff --git a/eprecord.h b/eprecord.h new file mode 100644 index 0000000..1d5e23a --- /dev/null +++ b/eprecord.h @@ -0,0 +1,110 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef EPRECORD_H +#define EPRECORD_H +#include "epvalue.h" +#include "stl-model.h" +#include "cgoal.h" +#include "hashset.h" +#include "modeltypes.h" +#include +#include + +typedef ModelVector ValueVector; +const char * eventToStr(EventType event); +struct RecordIDPair { + EPRecord *record; + EPRecord *idrecord; +}; + +inline unsigned int RIDP_hash_function(struct RecordIDPair * pair) { + return (unsigned int)(((uintptr_t)pair->record) >> 4) ^ ((uintptr_t)pair->idrecord); +} + +inline bool RIDP_equals(struct RecordIDPair * key1, struct RecordIDPair * key2) { + if (key1==NULL) + return key1==key2; + return key1->record == key2->record && key1->idrecord == key2->idrecord; +} + +typedef HashSet EPRecordIDSet; + +typedef HSIterator EPRecordIDIterator; + +class EPRecord { + public: + EPRecord(EventType event, ExecPoint *execpoint, EPValue *branch, uintptr_t _offset, unsigned int numinputs,uint len, bool anyvalue = false); + ~EPRecord(); + ExecPoint * getEP() {return execpoint;} + void addEPValue(EPValue *v) {valuevector->push_back(v);} + bool hasAddr(const void *addr); + bool hasValue(uint64_t val); + unsigned int numValues() {return valuevector->size();} + EPValue * getValue(unsigned int i) {return (*valuevector)[i];} + EPValue * getBranch() {return branch;} + int getIndex(EPValue *v); + int getIndex(uint64_t val); + EventType getType() {return event;} + CGoalSet *completedGoalSet() {return completed;} + IntHashSet * getSet(unsigned int i) {return setarray[i];} + IntHashSet * getReturnValueSet(); + IntHashSet * getStoreSet() { if (event==RMW) return setarray[VC_RMWOUTINDEX]; else return setarray[VC_BASEINDEX];} + uint getNumInputs() {return numinputs;} + uint getNumFuncInputs() {return numinputs-VC_BASEINDEX;} + bool getBranchAnyValue() {return anyvalue;} + void print(); + void print(int fd); + EPRecord *getNextRecord() {return nextRecord;} + EPRecord *getChildRecord() {return childRecord;} + void setNextRecord(EPRecord * n) {nextRecord=n;} + void setChildRecord(EPRecord *n) {childRecord=n;} + bool getPhi() {return phi;} + void setPhi() {phi=true;} + bool getLoopPhi() {return loopphi;} + void setLoopPhi() {if (philooptable==NULL) philooptable=new EPRecordIDSet(); phi=true; loopphi=true;} + void setRMW(enum atomicop _op) {op=_op;} + enum atomicop getOp() {return op;} + uint getLen() {return len;} + void setJoinThread(thread_id_t _j) {jointhread=_j;} + thread_id_t getJoinThread() {return jointhread;} + EPRecordIDSet * getPhiLoopTable() {return philooptable;} + void setSize(size_t s) {size=s;} + size_t getSize() {return size;} + void setPtr(void *p) {ptr=p;} + void * getPtr() {return ptr;} + void setCompletedGoal(CGoalSet *c, bool shared) {completed=c;func_shares_goalset=shared;} + bool isSharedGoals() {return func_shares_goalset;} + uintptr_t getOffset() {return offset;} + MEMALLOC; + + private: + ValueVector * valuevector; + ExecPoint * execpoint; + CGoalSet *completed; + EPValue *branch; + IntHashSet **setarray; + EPRecord *nextRecord; + EPRecord *childRecord; + EPRecordIDSet * philooptable; + uintptr_t offset; + EventType event; + thread_id_t jointhread; + unsigned int numinputs; + uint len; + bool anyvalue; + bool phi; + bool loopphi; + enum atomicop op; + size_t size; + bool func_shares_goalset; + void *ptr; +}; + +#endif diff --git a/epvalue.cc b/epvalue.cc new file mode 100644 index 0000000..a234889 --- /dev/null +++ b/epvalue.cc @@ -0,0 +1,39 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "epvalue.h" +#include "execpoint.h" +#include "mcutil.h" + +EPValue::EPValue(ExecPoint * ep, EPRecord * epr, const void * _addr, uint64_t ivalue, int ilen) : + firstrecord(NULL), + lastrecord(NULL), + execpoint(ep), + record(epr), + addr(_addr), + value(keepbytes(ivalue, ilen)), + len(ilen) +{ +} + +EPValue::~EPValue() { +} + +bool EPValueEquals(EPValue * ep1, EPValue *ep2) { + if (ep1 == NULL) + return ep2 == NULL; + + if (ep1->addr != ep2->addr || ep1->len!=ep2->len || ep1->value!=ep2->value) + return false; + return ExecPointEquals(ep1->execpoint, ep2->execpoint); +} + +unsigned int EPValueHash(EPValue *ep) { + return ExecPointHash(ep->execpoint) ^ ep->len ^ ep->value ^ ((intptr_t)ep->addr); +} diff --git a/epvalue.h b/epvalue.h new file mode 100644 index 0000000..5d3a85b --- /dev/null +++ b/epvalue.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef EPVALUE_H +#define EPVALUE_H +#include "classlist.h" +#include "mymemory.h" +#include "stl-model.h" +#include "mcutil.h" + +#define VC_ADDRINDEX 0 +#define VC_RFINDEX 1 +#define VC_BASEINDEX 2 +#define VC_OLDVALCASINDEX 3 +#define VC_RMWOUTINDEX 4 +#define VC_VALOUTINDEX 5 +#define VC_FUNCOUTINDEX 1 + +class EPValue { + public: + EPValue(ExecPoint *, EPRecord *, const void *addr, uint64_t value, int len); + ~EPValue(); + uint64_t getValue() {return value;} + ExecPoint * getEP() {return execpoint;} + const void *getAddr() {return addr;} + int getLen() {return len;} + EPRecord * getFirstRecord() {return firstrecord;} + EPRecord *firstrecord; + EPRecord *lastrecord; + EPRecord * getRecord() {return record;} + + MEMALLOC; + private: + ExecPoint * execpoint; + EPRecord *record; + const void *addr; + uint64_t value; + int len; + friend bool EPValueEquals(EPValue * ep1, EPValue *ep2); + friend unsigned int EPValueHash(EPValue *ep); +}; + +bool EPValueEquals(EPValue * ep1, EPValue *ep2); +unsigned int EPValueHash(EPValue *ep); +#endif diff --git a/equalsrecord.cc b/equalsrecord.cc new file mode 100644 index 0000000..364bdb3 --- /dev/null +++ b/equalsrecord.cc @@ -0,0 +1,28 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "equalsrecord.h" +#include "constraint.h" +#include "constgen.h" +#include "eprecord.h" + +EqualsRecord::EqualsRecord(ConstGen *cg, EPRecord *eq) : equals(eq) { + vars=cg->getNewVar(); +} + +EqualsRecord::~EqualsRecord() { +} + +Constraint * EqualsRecord::getValueEncoding(uint64_t val) { + if (val) + return vars; + else + return vars->negate(); +} + diff --git a/equalsrecord.h b/equalsrecord.h new file mode 100644 index 0000000..14968ba --- /dev/null +++ b/equalsrecord.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef EQUALSRECORD_H +#define EQUALSRECORD_H +#include "classlist.h" + +class EqualsRecord { + public: + EqualsRecord(ConstGen *cg, EPRecord *func); + ~EqualsRecord(); + Constraint * getValueEncoding(uint64_t val); + EPRecord *getRecord() {return equals;} + + MEMALLOC; + private: + EPRecord *equals; + Constraint *vars; +}; +#endif diff --git a/execpoint.cc b/execpoint.cc new file mode 100644 index 0000000..d35bd8d --- /dev/null +++ b/execpoint.cc @@ -0,0 +1,176 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "execpoint.h" +#include "mymemory.h" +#include +#include "mcutil.h" +#include "common.h" +#include + +ExecPoint::ExecPoint(int _length, thread_id_t thread_id) : + length(_length<<1), + size(0), + pairarray((execcount_t *)model_malloc(sizeof(execcount_t)*length)), + hashvalue(id_to_int(thread_id)), + tid(thread_id) +{ +} + +ExecPoint::ExecPoint(ExecPoint *e) : + length(e->size), + size(e->size), + pairarray((execcount_t *)model_malloc(sizeof(execcount_t)*length)), + hashvalue(e->hashvalue), + tid(e->tid) +{ + memcpy(pairarray, e->pairarray, sizeof(execcount_t)*length); +} + +ExecPoint::~ExecPoint() { + model_free(pairarray); +} + +void ExecPoint::reset() { + size=0; + hashvalue=id_to_int(tid); +} + +/** Return CR_AFTER means that ep occurs after this. + Return CR_BEFORE means tha te occurs before this. + Return CR_EQUALS means that they are the same point. + Return CR_INCOMPARABLE means that they are not comparable. +*/ + +CompareResult ExecPoint::compare(const ExecPoint * ep) const { + if (this==ep) + return CR_EQUALS; + unsigned int minsize=(sizesize)?size:ep->size; + for(unsigned int i=0;ipairarray[i]); + if (pairarray[i+1]!=ep->pairarray[i+1]) { + //we have a difference + if (pairarray[i]==EP_BRANCH) + return CR_INCOMPARABLE; + else if (pairarray[i+1]pairarray[i+1]) + return CR_AFTER; + else + return CR_BEFORE; + } + } + if (size < ep->size) + return CR_AFTER; + else if (size > ep->size) + return CR_BEFORE; + else + return CR_EQUALS; +} + +void ExecPoint::pop() { + hashvalue = rotate_right((hashvalue ^ pairarray[size-1]), 3); + size-=2; +} + +bool ExecPoint::directInLoop() { + return ((ExecPointType)pairarray[size-4])==EP_LOOP; +} + +bool ExecPoint::inLoop() { + int index; + for(index=size-2;index>0;index-=2) { + if ((ExecPointType)pairarray[index]==EP_LOOP) + return true; + } + return false; +} + +ExecPointType ExecPoint::getType() { + return (ExecPointType)pairarray[size-2]; +} + +void ExecPoint::push(ExecPointType type, execcount_t value) { + if (size==length) { + length=length<<1; + execcount_t *tmp=(execcount_t *)model_malloc(sizeof(execcount_t)*length); + memcpy(tmp, pairarray, sizeof(execcount_t)*size); + model_free(pairarray); + pairarray=tmp; + } + hashvalue = rotate_left(hashvalue, 3) ^ value; + pairarray[size++]=type; + pairarray[size++]=value; +} + +void ExecPoint::incrementTop() { + execcount_t current=pairarray[size-1]; + hashvalue = hashvalue ^ current ^ (current+1); + pairarray[size-1]=current+1; +} + +unsigned int ExecPointHash(ExecPoint *e) { + return e->hashvalue; +} + +bool ExecPointEquals(ExecPoint *e1, ExecPoint * e2) { + if (e1 == NULL) + return e2==NULL; + if (e1->tid != e2->tid || e1->size != e2->size || e1->hashvalue != e2->hashvalue) + return false; + for(unsigned int i=0; isize; i++) { + if (e1->pairarray[i]!=e2->pairarray[i]) + return false; + } + return true; +} + +void ExecPoint::print(int f) { + dprintf(f,""); +} + +void ExecPoint::print() { + model_print(""); +} diff --git a/execpoint.h b/execpoint.h new file mode 100644 index 0000000..74344ea --- /dev/null +++ b/execpoint.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef EXECPOINT_H +#define EXECPOINT_H +#include "mymemory.h" +#include "threads-model.h" +#include + +/** @brief An execution point in a trace. These give an execution + * independent way of numbering steps in a trace.*/ + +typedef unsigned int execcount_t; +enum ExecPointType {EP_BRANCH, EP_COUNTER, EP_LOOP}; +enum CompareResult {CR_BEFORE, CR_AFTER, CR_EQUALS, CR_INCOMPARABLE}; + +class ExecPoint { + public: + ExecPoint(int length, thread_id_t thread_id); + ExecPoint(ExecPoint * e); + ~ExecPoint(); + void reset(); + void pop(); + void push(ExecPointType type, execcount_t value); + void incrementTop(); + int getSize() {return (size>>1);} + CompareResult compare(const ExecPoint * ep) const; + thread_id_t get_tid() const {return tid;} + bool directInLoop(); + bool inLoop(); + ExecPointType getType(); + friend bool ExecPointEquals(ExecPoint *e1, ExecPoint * e2); + friend unsigned int ExecPointHash(ExecPoint *e1); + void print(); + void print(int f); + MEMALLOC; + private: + unsigned int length; + unsigned int size; + execcount_t * pairarray; + unsigned int hashvalue; + thread_id_t tid; +}; + +unsigned int ExecPointHash(ExecPoint *e); +bool ExecPointEquals(ExecPoint *e1, ExecPoint * e2); + +#endif diff --git a/functionrecord.cc b/functionrecord.cc new file mode 100644 index 0000000..a7576b7 --- /dev/null +++ b/functionrecord.cc @@ -0,0 +1,66 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "functionrecord.h" +#include "constraint.h" +#include "constgen.h" +#include "eprecord.h" + +FunctionRecord::FunctionRecord(ConstGen *cg, EPRecord *func) : function(func) { + if (function->getPhi()) { + uint numvals=function->getSet(VC_BASEINDEX)->getSize(); + numvars=NUMBITS(numvals-1); + vars=(Constraint **)model_malloc(numvars*sizeof(Constraint *)); + cg->getArrayNewVars(numvars, vars); + } else { + uint numvals=function->getSet(VC_FUNCOUTINDEX)->getSize(); + numvals++;//allow for new combinations in sat formulas + numvars=NUMBITS(numvals-1); + vars=(Constraint **)model_malloc(numvars*sizeof(Constraint *)); + cg->getArrayNewVars(numvars, vars); + } +} + +FunctionRecord::~FunctionRecord() { + model_free(vars); +} + +Constraint * FunctionRecord::getValueEncoding(uint64_t val) { + int index=-1; + if (function->getPhi()) { + IntIterator *it=function->getSet(VC_BASEINDEX)->iterator(); + int count=0; + while(it->hasNext()) { + if (it->next()==val) { + index=count; + break; + } + count++; + } + delete it; + } else { + IntIterator *it=function->getSet(VC_FUNCOUTINDEX)->iterator(); + int count=0; + while(it->hasNext()) { + if (it->next()==val) { + index=count; + break; + } + count++; + } + delete it; + } + if (index==-1) + return NULL; + return generateConstraint(numvars, vars, (uint)index); +} + +Constraint * FunctionRecord::getNoValueEncoding() { + return new Constraint(AND, numvars, vars); +} diff --git a/functionrecord.h b/functionrecord.h new file mode 100644 index 0000000..a7ecce8 --- /dev/null +++ b/functionrecord.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef FUNCTIONRECORD_H +#define FUNCTIONRECORD_H +#include "classlist.h" + +class FunctionRecord { + public: + FunctionRecord(ConstGen *cg, EPRecord *func); + ~FunctionRecord(); + Constraint * getValueEncoding(uint64_t val); + Constraint * getNoValueEncoding(); + + MEMALLOC; + private: + EPRecord *function; + Constraint **vars; + uint numvars; +}; +#endif diff --git a/hashset.h b/hashset.h new file mode 100644 index 0000000..c4274e2 --- /dev/null +++ b/hashset.h @@ -0,0 +1,218 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef HASH_SET_H +#define HASH_SET_H +#include "hashtable.h" + +template +struct LinkNode { + _Key key; + LinkNode<_Key> *prev; + LinkNode<_Key> *next; +}; + +template +class HashSet; + +template, bool (*equals)(_Key, _Key) = default_equals<_Key> > +class HSIterator { + public: + HSIterator(LinkNode<_Key> *_curr, HashSet <_Key, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals> * _set) : + curr(_curr), + set(_set) + { + } + + /** Override: new operator */ + void * operator new(size_t size) { + return _malloc(size); + } + + /** Override: delete operator */ + void operator delete(void *p, size_t size) { + _free(p); + } + + /** Override: new[] operator */ + void * operator new[](size_t size) { + return _malloc(size); + } + + /** Override: delete[] operator */ + void operator delete[](void *p, size_t size) { + _free(p); + } + + bool hasNext() { + return curr!=NULL; + } + + _Key next() { + _Key k=curr->key; + last=curr; + curr=curr->next; + return k; + } + + _Key currKey() { + return last->key; + } + + void remove() { + _Key k=last->key; + set->remove(k); + } + + private: + LinkNode<_Key> *curr; + LinkNode<_Key> *last; + HashSet <_Key, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals> * set; +}; + +template, bool (*equals)(_Key, _Key) = default_equals<_Key> > +class HashSet { + public: + HashSet(unsigned int initialcapacity = 16, double factor = 0.5) : + table(new HashTable<_Key, LinkNode<_Key> *, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals>(initialcapacity, factor)), + list(NULL), + tail(NULL) + { + } + + /** @brief Hashset destructor */ + ~HashSet() { + LinkNode<_Key> *tmp=list; + while(tmp!=NULL) { + LinkNode<_Key> *tmpnext=tmp->next; + _free(tmp); + tmp=tmpnext; + } + delete table; + } + + HashSet<_Key, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals> * copy() { + HashSet<_Key, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals> *copy=new HashSet<_Key, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals>(table->getCapacity(), table->getLoadFactor()); + HSIterator<_Key, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals> * it=iterator(); + while(it->hasNext()) + copy->add(it->next()); + delete it; + return copy; + } + + void reset() { + LinkNode<_Key> *tmp=list; + while(tmp!=NULL) { + LinkNode<_Key> *tmpnext=tmp->next; + _free(tmp); + tmp=tmpnext; + } + list=tail=NULL; + table->reset(); + } + + /** @brief Adds a new key to the hashset. Returns false if the key + * is already present. */ + + bool add(_Key key) { + LinkNode<_Key> * val=table->get(key); + if (val==NULL) { + LinkNode<_Key> * newnode=(LinkNode<_Key> *) _malloc(sizeof(struct LinkNode<_Key>)); + newnode->prev=tail; + newnode->next=NULL; + newnode->key=key; + if (tail!=NULL) + tail->next=newnode; + else + list=newnode; + tail=newnode; + table->put(key, newnode); + return true; + } else + return false; + } + + /** @brief Gets the original key corresponding to this one from the + * hashset. Returns NULL if not present. */ + + _Key get(_Key key) { + LinkNode<_Key> * val=table->get(key); + if (val!=NULL) + return val->key; + else + return NULL; + } + + bool contains(_Key key) { + return table->get(key)!=NULL; + } + + bool remove(_Key key) { + LinkNode<_Key> * oldlinknode; + oldlinknode=table->get(key); + if (oldlinknode==NULL) { + return false; + } + table->remove(key); + + //remove link node from the list + if (oldlinknode->prev==NULL) + list=oldlinknode->next; + else + oldlinknode->prev->next=oldlinknode->next; + if (oldlinknode->next!=NULL) + oldlinknode->next->prev=oldlinknode->prev; + else + tail=oldlinknode->prev; + _free(oldlinknode); + return true; + } + + unsigned int getSize() { + return table->getSize(); + } + + bool isEmpty() { + return getSize()==0; + } + + + + HSIterator<_Key, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals> * iterator() { + return new HSIterator<_Key, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals>(list, this); + } + + /** Override: new operator */ + void * operator new(size_t size) { + return _malloc(size); + } + + /** Override: delete operator */ + void operator delete(void *p, size_t size) { + _free(p); + } + + /** Override: new[] operator */ + void * operator new[](size_t size) { + return _malloc(size); + } + + /** Override: delete[] operator */ + void operator delete[](void *p, size_t size) { + _free(p); + } + + private: + HashTable<_Key, LinkNode<_Key>*, _KeyInt, _Shift, _malloc, _calloc, _free, hash_function, equals> * table; + LinkNode<_Key> *list; + LinkNode<_Key> *tail; +}; +#endif diff --git a/hashtable.h b/hashtable.h new file mode 100644 index 0000000..bcc8e70 --- /dev/null +++ b/hashtable.h @@ -0,0 +1,370 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file hashtable.h + * @brief Hashtable. Standard chained bucket variety. + */ + +#ifndef __HASHTABLE_H__ +#define __HASHTABLE_H__ + +#include +#include +#include +#include "mymemory.h" +#include "common.h" + +/** + * @brief HashTable node + * + * @tparam _Key Type name for the key + * @tparam _Val Type name for the values to be stored + */ +template +struct hashlistnode { + _Key key; + _Val val; +}; + +template +inline unsigned int default_hash_function(_Key hash) { + return (unsigned int)(((_KeyInt)hash) >> _Shift); +} + +template +inline bool default_equals(_Key key1, _Key key2) { + return key1 == key2; +} + +/** + * @brief A simple, custom hash table + * + * By default it is snapshotting, but you can pass in your own allocation + * functions. Note that this table does not support the value 0 (NULL) used as + * a key and is designed primarily with pointer-based keys in mind. Other + * primitive key types are supported only for non-zero values. + * + * @tparam _Key Type name for the key + * @tparam _Val Type name for the values to be stored + * @tparam _KeyInt Integer type that is at least as large as _Key. Used for key + * manipulation and storage. + * @tparam _Shift Logical shift to apply to all keys. Default 0. + * @tparam _malloc Provide your own 'malloc' for the table, or default to + * snapshotting. + * @tparam _calloc Provide your own 'calloc' for the table, or default to + * snapshotting. + * @tparam _free Provide your own 'free' for the table, or default to + * snapshotting. + */ +template, bool (*equals)(_Key, _Key) = default_equals<_Key> > +class HashTable { + public: + /** + * @brief Hash table constructor + * @param initialcapacity Sets the initial capacity of the hash table. + * Default size 1024. + * @param factor Sets the percentage full before the hashtable is + * resized. Default ratio 0.5. + */ + HashTable(unsigned int initialcapacity = 1024, double factor = 0.5) { + // Allocate space for the hash table + table = (struct hashlistnode<_Key, _Val> *)_calloc(initialcapacity, sizeof(struct hashlistnode<_Key, _Val>)); + zero = NULL; + loadfactor = factor; + capacity = initialcapacity; + capacitymask = initialcapacity - 1; + + threshold = (unsigned int)(initialcapacity * loadfactor); + size = 0; // Initial number of elements in the hash + } + + /** @brief Hash table destructor */ + ~HashTable() { + _free(table); + if (zero) + _free(zero); + } + + /** Override: new operator */ + void * operator new(size_t size) { + return _malloc(size); + } + + /** Override: delete operator */ + void operator delete(void *p, size_t size) { + _free(p); + } + + /** Override: new[] operator */ + void * operator new[](size_t size) { + return _malloc(size); + } + + /** Override: delete[] operator */ + void operator delete[](void *p, size_t size) { + _free(p); + } + + /** @brief Reset the table to its initial state. */ + void reset() { + memset(table, 0, capacity * sizeof(struct hashlistnode<_Key, _Val>)); + if (zero) { + _free(zero); + zero = NULL; + } + size = 0; + } + + void resetanddelete() { + for(unsigned int i=0;i *bin = &table[i]; + if (bin->key != NULL) { + bin->key = NULL; + if (bin->val != NULL) { + delete bin->val; + bin->val = NULL; + } + } + } + if (zero) { + if (zero->val != NULL) + delete zero->val; + _free(zero); + zero = NULL; + } + size = 0; + } + + void resetandfree() { + for(unsigned int i=0;i *bin = &table[i]; + if (bin->key != NULL) { + bin->key = NULL; + if (bin->val != NULL) { + _free(bin->val); + bin->val = NULL; + } + } + } + if (zero) { + if (zero->val != NULL) + _free(zero->val); + _free(zero); + zero = NULL; + } + size = 0; + } + + /** + * @brief Put a key/value pair into the table + * @param key The key for the new value; must not be 0 or NULL + * @param val The value to store in the table + */ + void put(_Key key, _Val val) { + /* HashTable cannot handle 0 as a key */ + if (!key) { + if (!zero) { + zero=(struct hashlistnode<_Key, _Val> *)_malloc(sizeof(struct hashlistnode<_Key, _Val>)); + size++; + } + zero->key=key; + zero->val=val; + return; + } + + if (size > threshold) + resize(capacity << 1); + + struct hashlistnode<_Key, _Val> *search; + + unsigned int index = hash_function(key); + do { + index &= capacitymask; + search = &table[index]; + if (!search->key) { + //key is null, probably done + break; + } + if (equals(search->key, key)) { + search->val = val; + return; + } + index++; + } while (true); + + search->key = key; + search->val = val; + size++; + } + + /** + * @brief Lookup the corresponding value for the given key + * @param key The key for finding the value; must not be 0 or NULL + * @return The value in the table, if the key is found; otherwise 0 + */ + _Val get(_Key key) const { + struct hashlistnode<_Key, _Val> *search; + + /* HashTable cannot handle 0 as a key */ + if (!key) { + if (zero) + return zero->val; + else + return (_Val) 0; + } + + unsigned int oindex = hash_function(key) & capacitymask; + unsigned int index=oindex; + do { + search = &table[index]; + if (!search->key) { + if (!search->val) + break; + } else + if (equals(search->key, key)) + return search->val; + index++; + index &= capacitymask; + if (index==oindex) + break; + } while (true); + return (_Val)0; + } + + /** + * @brief Remove the given key and return the corresponding value + * @param key The key for finding the value; must not be 0 or NULL + * @return The value in the table, if the key is found; otherwise 0 + */ + _Val remove(_Key key) { + struct hashlistnode<_Key, _Val> *search; + + /* HashTable cannot handle 0 as a key */ + if (!key) { + if (!zero) { + return (_Val)0; + } else { + _Val v=zero->val; + _free(zero); + zero=NULL; + size--; + return v; + } + } + + + unsigned int index = hash_function(key); + do { + index &= capacitymask; + search = &table[index]; + if (!search->key) { + if (!search->val) + break; + } else + if (equals(search->key, key)) { + _Val v=search->val; + //empty out this bin + search->val=(_Val) 1; + search->key=0; + size--; + return v; + } + index++; + } while (true); + return (_Val)0; + } + + unsigned int getSize() const { + return size; + } + + + /** + * @brief Check whether the table contains a value for the given key + * @param key The key for finding the value; must not be 0 or NULL + * @return True, if the key is found; false otherwise + */ + bool contains(_Key key) const { + struct hashlistnode<_Key, _Val> *search; + + /* HashTable cannot handle 0 as a key */ + if (!key) { + return zero!=NULL; + } + + unsigned int index = hash_function(key); + do { + index &= capacitymask; + search = &table[index]; + if (!search->key) { + if (!search->val) + break; + } else + if (equals(search->key, key)) + return true; + index++; + } while (true); + return false; + } + + /** + * @brief Resize the table + * @param newsize The new size of the table + */ + void resize(unsigned int newsize) { + struct hashlistnode<_Key, _Val> *oldtable = table; + struct hashlistnode<_Key, _Val> *newtable; + unsigned int oldcapacity = capacity; + + if ((newtable = (struct hashlistnode<_Key, _Val> *)_calloc(newsize, sizeof(struct hashlistnode<_Key, _Val>))) == NULL) { + model_print("calloc error %s %d\n", __FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + table = newtable; // Update the global hashtable upon resize() + capacity = newsize; + capacitymask = newsize - 1; + + threshold = (unsigned int)(newsize * loadfactor); + + struct hashlistnode<_Key, _Val> *bin = &oldtable[0]; + struct hashlistnode<_Key, _Val> *lastbin = &oldtable[oldcapacity]; + for (; bin < lastbin; bin++) { + _Key key = bin->key; + + struct hashlistnode<_Key, _Val> *search; + if (!key) + continue; + + unsigned int index = hash_function(key); + do { + index &= capacitymask; + search = &table[index]; + index++; + } while (search->key); + + search->key = key; + search->val = bin->val; + } + + _free(oldtable); // Free the memory of the old hash table + } + double getLoadFactor() {return loadfactor;} + unsigned int getCapacity() {return capacity;} + struct hashlistnode<_Key, _Val> *table; + struct hashlistnode<_Key, _Val> *zero; + unsigned int capacity; + unsigned int size; + private: + unsigned int capacitymask; + unsigned int threshold; + double loadfactor; +}; + +#endif /* __HASHTABLE_H__ */ diff --git a/inc_solver.cc b/inc_solver.cc new file mode 100644 index 0000000..daeeb1e --- /dev/null +++ b/inc_solver.cc @@ -0,0 +1,164 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "inc_solver.h" +#define SATSOLVER "sat_solver" +#include + +IncrementalSolver::IncrementalSolver() : + buffer((int *)model_malloc(sizeof(int)*IS_BUFFERSIZE)), + solution(NULL), + solutionsize(0), + offset(0) +{ + createSolver(); +} + +IncrementalSolver::~IncrementalSolver() { + killSolver(); + model_free(buffer); + if (solution != NULL) + model_free(solution); +} + +void IncrementalSolver::reset() { + killSolver(); + offset = 0; + createSolver(); +} + +void IncrementalSolver::addClauseLiteral(int literal) { + buffer[offset++]=literal; + if (offset==IS_BUFFERSIZE) { + flushBuffer(); + } +} + +void IncrementalSolver::finishedClauses() { + addClauseLiteral(0); +} + +void IncrementalSolver::freeze(int variable) { + addClauseLiteral(IS_FREEZE); + addClauseLiteral(variable); +} + +int IncrementalSolver::solve() { + //add an empty clause + startSolve(); + return getSolution(); +} + + +void IncrementalSolver::startSolve() { + addClauseLiteral(IS_RUNSOLVER); + flushBuffer(); +} + +int IncrementalSolver::getSolution() { + int result=readIntSolver(); + if (result == IS_SAT) { + int numVars=readIntSolver(); + if (numVars > solutionsize) { + if (solution != NULL) + model_free(solution); + solution = (int *) model_malloc((numVars+1)*sizeof(int)); + solution[0] = 0; + } + readSolver(&solution[1], numVars * sizeof(int)); + } + return result; +} + +int IncrementalSolver::readIntSolver() { + int value; + readSolver(&value, 4); + return value; +} + +void IncrementalSolver::readSolver(void * tmp, ssize_t size) { + char *result = (char *) tmp; + ssize_t bytestoread=size; + ssize_t bytesread=0; + do { + ssize_t n=read(from_solver_fd, &((char *)result)[bytesread], bytestoread); + if (n == -1) { + model_print("Read failure\n"); + exit(-1); + } + bytestoread -= n; + bytesread += n; + } while(bytestoread != 0); +} + +bool IncrementalSolver::getValue(int variable) { + return solution[variable]; +} + +void IncrementalSolver::createSolver() { + int to_pipe[2]; + int from_pipe[2]; + if (pipe(to_pipe) || pipe(from_pipe)) { + model_print("Error creating pipe.\n"); + exit(-1); + } + if ((solver_pid = fork()) == -1) { + model_print("Error forking.\n"); + exit(-1); + } + if (solver_pid == 0) { + //Solver process + close(to_pipe[1]); + close(from_pipe[0]); + int fd=open("log_file", O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU); + + if ((dup2(to_pipe[0], 0) == -1) || + (dup2(from_pipe[1], IS_OUT_FD) == -1) || + (dup2(fd, 1) == -1)) { + model_print("Error duplicating pipes\n"); + } + // setsid(); + execlp(SATSOLVER, SATSOLVER, NULL); + model_print("execlp Failed\n"); + close(fd); + } else { + //Our process + to_solver_fd = to_pipe[1]; + from_solver_fd = from_pipe[0]; + close(to_pipe[0]); + close(from_pipe[1]); + } +} + +void IncrementalSolver::killSolver() { + close(to_solver_fd); + close(from_solver_fd); + //Stop the solver + if (solver_pid > 0) { + int status; + kill(solver_pid, SIGKILL); + waitpid(solver_pid, &status, 0); + } +} + +void IncrementalSolver::flushBuffer() { + ssize_t bytestowrite=sizeof(int)*offset; + ssize_t byteswritten=0; + do { + ssize_t n=write(to_solver_fd, &((char *)buffer)[byteswritten], bytestowrite); + if (n == -1) { + perror("Write failure\n"); + model_print("to_solver_fd=%d\n",to_solver_fd); + exit(-1); + } + bytestowrite -= n; + byteswritten += n; + } while(bytestowrite != 0); + offset = 0; +} diff --git a/inc_solver.h b/inc_solver.h new file mode 100644 index 0000000..d5b7f3c --- /dev/null +++ b/inc_solver.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef INC_SOLVER_H +#define INC_SOLVER_H +#include +#include +#include +#include +#include +#include +#include "solver_interface.h" +#include "classlist.h" + +class IncrementalSolver { + public: + IncrementalSolver(); + ~IncrementalSolver(); + void addClauseLiteral(int literal); + void finishedClauses(); + void freeze(int variable); + int solve(); + void startSolve(); + int getSolution(); + + bool getValue(int variable); + void reset(); + MEMALLOC; + + private: + void createSolver(); + void killSolver(); + void flushBuffer(); + int readIntSolver(); + void readSolver(void * buffer, ssize_t size); + int * buffer; + int * solution; + int solutionsize; + int offset; + pid_t solver_pid; + int to_solver_fd; + int from_solver_fd; +}; +#endif diff --git a/include/atomic b/include/atomic new file mode 100644 index 0000000..5984e72 --- /dev/null +++ b/include/atomic @@ -0,0 +1,11 @@ +/** + * @file atomic + * @brief C++11 atomic interface header + */ + +#ifndef __CXX_ATOMIC__ +#define __CXX_ATOMIC__ + +#include "impatomic.h" + +#endif /* __CXX_ATOMIC__ */ diff --git a/include/cmodelint.h b/include/cmodelint.h new file mode 100644 index 0000000..24c5f6f --- /dev/null +++ b/include/cmodelint.h @@ -0,0 +1,28 @@ +/** @file cmodelint.h + * @brief C interface to the model checker. + */ + +#ifndef CMODELINT_H +#define CMODELINT_H +#include +#include "memoryorder.h" + +#if __cplusplus +using std::memory_order; +extern "C" { +#endif + +uint64_t model_read_action(void * obj, memory_order ord); +void model_write_action(void * obj, memory_order ord, uint64_t val); +void model_init_action(void * obj, uint64_t val); +uint64_t model_rmwr_action(void *obj, memory_order ord); +void model_rmw_action(void *obj, memory_order ord, uint64_t val); +void model_rmwc_action(void *obj, memory_order ord); +void model_fence_action(memory_order ord); + + +#if __cplusplus +} +#endif + +#endif diff --git a/include/condition_variable b/include/condition_variable new file mode 100644 index 0000000..2a7447b --- /dev/null +++ b/include/condition_variable @@ -0,0 +1,24 @@ +#ifndef __CXX_CONDITION_VARIABLE__ +#define __CXX_CONDITION_VARIABLE__ + +namespace std { + class mutex; + + struct condition_variable_state { + int reserved; + }; + + class condition_variable { + public: + condition_variable(); + ~condition_variable(); + void notify_one(); + void notify_all(); + void wait(mutex& lock); + + private: + struct condition_variable_state state; + }; +} + +#endif /* __CXX_CONDITION_VARIABLE__ */ diff --git a/include/cstdatomic b/include/cstdatomic new file mode 100644 index 0000000..b441097 --- /dev/null +++ b/include/cstdatomic @@ -0,0 +1,7 @@ +/** + * @file cstdatomic + * @brief C11 atomic interface header + */ + +#include "impatomic.h" + diff --git a/include/impatomic.h b/include/impatomic.h new file mode 100644 index 0000000..1b9ce6b --- /dev/null +++ b/include/impatomic.h @@ -0,0 +1,3923 @@ +/** + * @file impatomic.h + * @brief Common header for C11/C++11 atomics + * + * Note that some features are unavailable, as they require support from a true + * C11/C++11 compiler. + */ + +#ifndef __IMPATOMIC_H__ +#define __IMPATOMIC_H__ + +#include "memoryorder.h" +#include "cmodelint.h" + +#ifdef __cplusplus +namespace std { +#else +#include +#endif + +#define CPP0X( feature ) + +typedef struct atomic_flag +{ +#ifdef __cplusplus + bool test_and_set( memory_order = memory_order_seq_cst ) volatile; + void clear( memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_flag() = default; ) + CPP0X( atomic_flag( const atomic_flag& ) = delete; ) + atomic_flag& operator =( const atomic_flag& ) CPP0X(=delete); + +CPP0X(private:) +#endif + bool __f__; +} atomic_flag; + +#define ATOMIC_FLAG_INIT { false } + +#ifdef __cplusplus +extern "C" { +#endif + +extern bool atomic_flag_test_and_set( volatile atomic_flag* ); +extern bool atomic_flag_test_and_set_explicit +( volatile atomic_flag*, memory_order ); +extern void atomic_flag_clear( volatile atomic_flag* ); +extern void atomic_flag_clear_explicit +( volatile atomic_flag*, memory_order ); +extern void __atomic_flag_wait__ +( volatile atomic_flag* ); +extern void __atomic_flag_wait_explicit__ +( volatile atomic_flag*, memory_order ); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +inline bool atomic_flag::test_and_set( memory_order __x__ ) volatile +{ return atomic_flag_test_and_set_explicit( this, __x__ ); } + +inline void atomic_flag::clear( memory_order __x__ ) volatile +{ atomic_flag_clear_explicit( this, __x__ ); } + +#endif + + +/* + The remainder of the example implementation uses the following + macros. These macros exploit GNU extensions for value-returning + blocks (AKA statement expressions) and __typeof__. + + The macros rely on data fields of atomic structs being named __f__. + Other symbols used are __a__=atomic, __e__=expected, __f__=field, + __g__=flag, __m__=modified, __o__=operation, __r__=result, + __p__=pointer to field, __v__=value (for single evaluation), + __x__=memory-ordering, and __y__=memory-ordering. +*/ + +#define _ATOMIC_LOAD_( __a__, __x__ ) \ + ({ volatile __typeof__((__a__)->__f__)* __p__ = & ((__a__)->__f__); \ + __typeof__((__a__)->__f__) __r__ = (__typeof__((__a__)->__f__))model_read_action((void *)__p__, __x__); \ + __r__; }) + +#define _ATOMIC_STORE_( __a__, __m__, __x__ ) \ + ({ volatile __typeof__((__a__)->__f__)* __p__ = & ((__a__)->__f__); \ + __typeof__(__m__) __v__ = (__m__); \ + model_write_action((void *) __p__, __x__, (uint64_t) __v__); \ + __v__ = __v__; /* Silence clang (-Wunused-value) */ \ + }) + + +#define _ATOMIC_INIT_( __a__, __m__ ) \ + ({ volatile __typeof__((__a__)->__f__)* __p__ = & ((__a__)->__f__); \ + __typeof__(__m__) __v__ = (__m__); \ + model_init_action((void *) __p__, (uint64_t) __v__); \ + __v__ = __v__; /* Silence clang (-Wunused-value) */ \ + }) + +#define _ATOMIC_MODIFY_( __a__, __o__, __m__, __x__ ) \ + ({ volatile __typeof__((__a__)->__f__)* __p__ = & ((__a__)->__f__); \ + __typeof__((__a__)->__f__) __old__=(__typeof__((__a__)->__f__)) model_rmwr_action((void *)__p__, __x__); \ + __typeof__(__m__) __v__ = (__m__); \ + __typeof__((__a__)->__f__) __copy__= __old__; \ + __copy__ __o__ __v__; \ + model_rmw_action((void *)__p__, __x__, (uint64_t) __copy__); \ + __old__ = __old__; /* Silence clang (-Wunused-value) */ \ + }) + +/* No spurious failure for now */ +#define _ATOMIC_CMPSWP_WEAK_ _ATOMIC_CMPSWP_ + +#define _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ) \ + ({ volatile __typeof__((__a__)->__f__)* __p__ = & ((__a__)->__f__); \ + __typeof__(__e__) __q__ = (__e__); \ + __typeof__(__m__) __v__ = (__m__); \ + bool __r__; \ + __typeof__((__a__)->__f__) __t__=(__typeof__((__a__)->__f__)) model_rmwr_action((void *)__p__, __x__); \ + if (__t__ == * __q__ ) { \ + model_rmw_action((void *)__p__, __x__, (uint64_t) __v__); __r__ = true; } \ + else { model_rmwc_action((void *)__p__, __x__); *__q__ = __t__; __r__ = false;} \ + __r__; }) + +#define _ATOMIC_FENCE_( __x__ ) \ + ({ model_fence_action(__x__);}) + + +#define ATOMIC_CHAR_LOCK_FREE 1 +#define ATOMIC_CHAR16_T_LOCK_FREE 1 +#define ATOMIC_CHAR32_T_LOCK_FREE 1 +#define ATOMIC_WCHAR_T_LOCK_FREE 1 +#define ATOMIC_SHORT_LOCK_FREE 1 +#define ATOMIC_INT_LOCK_FREE 1 +#define ATOMIC_LONG_LOCK_FREE 1 +#define ATOMIC_LLONG_LOCK_FREE 1 +#define ATOMIC_ADDRESS_LOCK_FREE 1 + +typedef struct atomic_bool +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( bool, memory_order = memory_order_seq_cst ) volatile; + bool load( memory_order = memory_order_seq_cst ) volatile; + bool exchange( bool, memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak ( bool&, bool, memory_order, memory_order ) volatile; + bool compare_exchange_strong ( bool&, bool, memory_order, memory_order ) volatile; + bool compare_exchange_weak ( bool&, bool, + memory_order = memory_order_seq_cst) volatile; + bool compare_exchange_strong ( bool&, bool, + memory_order = memory_order_seq_cst) volatile; + + CPP0X( atomic_bool() = delete; ) + CPP0X( constexpr explicit atomic_bool( bool __v__ ) : __f__( __v__ ) { } ) + CPP0X( atomic_bool( const atomic_bool& ) = delete; ) + atomic_bool& operator =( const atomic_bool& ) CPP0X(=delete); + + bool operator =( bool __v__ ) volatile + { store( __v__ ); return __v__; } + + friend void atomic_store_explicit( volatile atomic_bool*, bool, + memory_order ); + friend bool atomic_load_explicit( volatile atomic_bool*, memory_order ); + friend bool atomic_exchange_explicit( volatile atomic_bool*, bool, + memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_bool*, bool*, bool, + memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_bool*, bool*, bool, + memory_order, memory_order ); + +CPP0X(private:) +#endif + bool __f__; +} atomic_bool; + + +typedef struct atomic_address +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( void*, memory_order = memory_order_seq_cst ) volatile; + void* load( memory_order = memory_order_seq_cst ) volatile; + void* exchange( void*, memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( void*&, void*, memory_order, memory_order ) volatile; + bool compare_exchange_strong( void*&, void*, memory_order, memory_order ) volatile; + bool compare_exchange_weak( void*&, void*, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( void*&, void*, + memory_order = memory_order_seq_cst ) volatile; + void* fetch_add( ptrdiff_t, memory_order = memory_order_seq_cst ) volatile; + void* fetch_sub( ptrdiff_t, memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_address() = default; ) + CPP0X( constexpr explicit atomic_address( void* __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_address( const atomic_address& ) = delete; ) + atomic_address& operator =( const atomic_address & ) CPP0X(=delete); + + void* operator =( void* __v__ ) volatile + { store( __v__ ); return __v__; } + + void* operator +=( ptrdiff_t __v__ ) volatile + { return fetch_add( __v__ ); } + + void* operator -=( ptrdiff_t __v__ ) volatile + { return fetch_sub( __v__ ); } + + friend void atomic_store_explicit( volatile atomic_address*, void*, + memory_order ); + friend void* atomic_load_explicit( volatile atomic_address*, memory_order ); + friend void* atomic_exchange_explicit( volatile atomic_address*, void*, + memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_address*, + void**, void*, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_address*, + void**, void*, memory_order, memory_order ); + friend void* atomic_fetch_add_explicit( volatile atomic_address*, ptrdiff_t, + memory_order ); + friend void* atomic_fetch_sub_explicit( volatile atomic_address*, ptrdiff_t, + memory_order ); + +CPP0X(private:) +#endif + void* __f__; +} atomic_address; + + +typedef struct atomic_char +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( char, + memory_order = memory_order_seq_cst ) volatile; + char load( memory_order = memory_order_seq_cst ) volatile; + char exchange( char, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( char&, char, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( char&, char, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( char&, char, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( char&, char, + memory_order = memory_order_seq_cst ) volatile; + char fetch_add( char, + memory_order = memory_order_seq_cst ) volatile; + char fetch_sub( char, + memory_order = memory_order_seq_cst ) volatile; + char fetch_and( char, + memory_order = memory_order_seq_cst ) volatile; + char fetch_or( char, + memory_order = memory_order_seq_cst ) volatile; + char fetch_xor( char, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_char() = default; ) + CPP0X( constexpr atomic_char( char __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_char( const atomic_char& ) = delete; ) + atomic_char& operator =( const atomic_char& ) CPP0X(=delete); + + char operator =( char __v__ ) volatile + { store( __v__ ); return __v__; } + + char operator ++( int ) volatile + { return fetch_add( 1 ); } + + char operator --( int ) volatile + { return fetch_sub( 1 ); } + + char operator ++() volatile + { return fetch_add( 1 ) + 1; } + + char operator --() volatile + { return fetch_sub( 1 ) - 1; } + + char operator +=( char __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + char operator -=( char __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + char operator &=( char __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + char operator |=( char __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + char operator ^=( char __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_char*, char, + memory_order ); + friend char atomic_load_explicit( volatile atomic_char*, + memory_order ); + friend char atomic_exchange_explicit( volatile atomic_char*, + char, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_char*, + char*, char, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_char*, + char*, char, memory_order, memory_order ); + friend char atomic_fetch_add_explicit( volatile atomic_char*, + char, memory_order ); + friend char atomic_fetch_sub_explicit( volatile atomic_char*, + char, memory_order ); + friend char atomic_fetch_and_explicit( volatile atomic_char*, + char, memory_order ); + friend char atomic_fetch_or_explicit( volatile atomic_char*, + char, memory_order ); + friend char atomic_fetch_xor_explicit( volatile atomic_char*, + char, memory_order ); + +CPP0X(private:) +#endif + char __f__; +} atomic_char; + + +typedef struct atomic_schar +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( signed char, + memory_order = memory_order_seq_cst ) volatile; + signed char load( memory_order = memory_order_seq_cst ) volatile; + signed char exchange( signed char, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( signed char&, signed char, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( signed char&, signed char, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( signed char&, signed char, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( signed char&, signed char, + memory_order = memory_order_seq_cst ) volatile; + signed char fetch_add( signed char, + memory_order = memory_order_seq_cst ) volatile; + signed char fetch_sub( signed char, + memory_order = memory_order_seq_cst ) volatile; + signed char fetch_and( signed char, + memory_order = memory_order_seq_cst ) volatile; + signed char fetch_or( signed char, + memory_order = memory_order_seq_cst ) volatile; + signed char fetch_xor( signed char, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_schar() = default; ) + CPP0X( constexpr atomic_schar( signed char __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_schar( const atomic_schar& ) = delete; ) + atomic_schar& operator =( const atomic_schar& ) CPP0X(=delete); + + signed char operator =( signed char __v__ ) volatile + { store( __v__ ); return __v__; } + + signed char operator ++( int ) volatile + { return fetch_add( 1 ); } + + signed char operator --( int ) volatile + { return fetch_sub( 1 ); } + + signed char operator ++() volatile + { return fetch_add( 1 ) + 1; } + + signed char operator --() volatile + { return fetch_sub( 1 ) - 1; } + + signed char operator +=( signed char __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + signed char operator -=( signed char __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + signed char operator &=( signed char __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + signed char operator |=( signed char __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + signed char operator ^=( signed char __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_schar*, signed char, + memory_order ); + friend signed char atomic_load_explicit( volatile atomic_schar*, + memory_order ); + friend signed char atomic_exchange_explicit( volatile atomic_schar*, + signed char, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_schar*, + signed char*, signed char, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_schar*, + signed char*, signed char, memory_order, memory_order ); + friend signed char atomic_fetch_add_explicit( volatile atomic_schar*, + signed char, memory_order ); + friend signed char atomic_fetch_sub_explicit( volatile atomic_schar*, + signed char, memory_order ); + friend signed char atomic_fetch_and_explicit( volatile atomic_schar*, + signed char, memory_order ); + friend signed char atomic_fetch_or_explicit( volatile atomic_schar*, + signed char, memory_order ); + friend signed char atomic_fetch_xor_explicit( volatile atomic_schar*, + signed char, memory_order ); + +CPP0X(private:) +#endif + signed char __f__; +} atomic_schar; + + +typedef struct atomic_uchar +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( unsigned char, + memory_order = memory_order_seq_cst ) volatile; + unsigned char load( memory_order = memory_order_seq_cst ) volatile; + unsigned char exchange( unsigned char, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( unsigned char&, unsigned char, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( unsigned char&, unsigned char, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( unsigned char&, unsigned char, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( unsigned char&, unsigned char, + memory_order = memory_order_seq_cst ) volatile; + unsigned char fetch_add( unsigned char, + memory_order = memory_order_seq_cst ) volatile; + unsigned char fetch_sub( unsigned char, + memory_order = memory_order_seq_cst ) volatile; + unsigned char fetch_and( unsigned char, + memory_order = memory_order_seq_cst ) volatile; + unsigned char fetch_or( unsigned char, + memory_order = memory_order_seq_cst ) volatile; + unsigned char fetch_xor( unsigned char, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_uchar() = default; ) + CPP0X( constexpr atomic_uchar( unsigned char __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_uchar( const atomic_uchar& ) = delete; ) + atomic_uchar& operator =( const atomic_uchar& ) CPP0X(=delete); + + unsigned char operator =( unsigned char __v__ ) volatile + { store( __v__ ); return __v__; } + + unsigned char operator ++( int ) volatile + { return fetch_add( 1 ); } + + unsigned char operator --( int ) volatile + { return fetch_sub( 1 ); } + + unsigned char operator ++() volatile + { return fetch_add( 1 ) + 1; } + + unsigned char operator --() volatile + { return fetch_sub( 1 ) - 1; } + + unsigned char operator +=( unsigned char __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + unsigned char operator -=( unsigned char __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + unsigned char operator &=( unsigned char __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + unsigned char operator |=( unsigned char __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + unsigned char operator ^=( unsigned char __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_uchar*, unsigned char, + memory_order ); + friend unsigned char atomic_load_explicit( volatile atomic_uchar*, + memory_order ); + friend unsigned char atomic_exchange_explicit( volatile atomic_uchar*, + unsigned char, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_uchar*, + unsigned char*, unsigned char, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_uchar*, + unsigned char*, unsigned char, memory_order, memory_order ); + friend unsigned char atomic_fetch_add_explicit( volatile atomic_uchar*, + unsigned char, memory_order ); + friend unsigned char atomic_fetch_sub_explicit( volatile atomic_uchar*, + unsigned char, memory_order ); + friend unsigned char atomic_fetch_and_explicit( volatile atomic_uchar*, + unsigned char, memory_order ); + friend unsigned char atomic_fetch_or_explicit( volatile atomic_uchar*, + unsigned char, memory_order ); + friend unsigned char atomic_fetch_xor_explicit( volatile atomic_uchar*, + unsigned char, memory_order ); + +CPP0X(private:) +#endif + unsigned char __f__; +} atomic_uchar; + + +typedef struct atomic_short +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( short, + memory_order = memory_order_seq_cst ) volatile; + short load( memory_order = memory_order_seq_cst ) volatile; + short exchange( short, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( short&, short, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( short&, short, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( short&, short, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( short&, short, + memory_order = memory_order_seq_cst ) volatile; + short fetch_add( short, + memory_order = memory_order_seq_cst ) volatile; + short fetch_sub( short, + memory_order = memory_order_seq_cst ) volatile; + short fetch_and( short, + memory_order = memory_order_seq_cst ) volatile; + short fetch_or( short, + memory_order = memory_order_seq_cst ) volatile; + short fetch_xor( short, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_short() = default; ) + CPP0X( constexpr atomic_short( short __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_short( const atomic_short& ) = delete; ) + atomic_short& operator =( const atomic_short& ) CPP0X(=delete); + + short operator =( short __v__ ) volatile + { store( __v__ ); return __v__; } + + short operator ++( int ) volatile + { return fetch_add( 1 ); } + + short operator --( int ) volatile + { return fetch_sub( 1 ); } + + short operator ++() volatile + { return fetch_add( 1 ) + 1; } + + short operator --() volatile + { return fetch_sub( 1 ) - 1; } + + short operator +=( short __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + short operator -=( short __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + short operator &=( short __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + short operator |=( short __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + short operator ^=( short __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_short*, short, + memory_order ); + friend short atomic_load_explicit( volatile atomic_short*, + memory_order ); + friend short atomic_exchange_explicit( volatile atomic_short*, + short, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_short*, + short*, short, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_short*, + short*, short, memory_order, memory_order ); + friend short atomic_fetch_add_explicit( volatile atomic_short*, + short, memory_order ); + friend short atomic_fetch_sub_explicit( volatile atomic_short*, + short, memory_order ); + friend short atomic_fetch_and_explicit( volatile atomic_short*, + short, memory_order ); + friend short atomic_fetch_or_explicit( volatile atomic_short*, + short, memory_order ); + friend short atomic_fetch_xor_explicit( volatile atomic_short*, + short, memory_order ); + +CPP0X(private:) +#endif + short __f__; +} atomic_short; + + +typedef struct atomic_ushort +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( unsigned short, + memory_order = memory_order_seq_cst ) volatile; + unsigned short load( memory_order = memory_order_seq_cst ) volatile; + unsigned short exchange( unsigned short, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( unsigned short&, unsigned short, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( unsigned short&, unsigned short, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( unsigned short&, unsigned short, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( unsigned short&, unsigned short, + memory_order = memory_order_seq_cst ) volatile; + unsigned short fetch_add( unsigned short, + memory_order = memory_order_seq_cst ) volatile; + unsigned short fetch_sub( unsigned short, + memory_order = memory_order_seq_cst ) volatile; + unsigned short fetch_and( unsigned short, + memory_order = memory_order_seq_cst ) volatile; + unsigned short fetch_or( unsigned short, + memory_order = memory_order_seq_cst ) volatile; + unsigned short fetch_xor( unsigned short, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_ushort() = default; ) + CPP0X( constexpr atomic_ushort( unsigned short __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_ushort( const atomic_ushort& ) = delete; ) + atomic_ushort& operator =( const atomic_ushort& ) CPP0X(=delete); + + unsigned short operator =( unsigned short __v__ ) volatile + { store( __v__ ); return __v__; } + + unsigned short operator ++( int ) volatile + { return fetch_add( 1 ); } + + unsigned short operator --( int ) volatile + { return fetch_sub( 1 ); } + + unsigned short operator ++() volatile + { return fetch_add( 1 ) + 1; } + + unsigned short operator --() volatile + { return fetch_sub( 1 ) - 1; } + + unsigned short operator +=( unsigned short __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + unsigned short operator -=( unsigned short __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + unsigned short operator &=( unsigned short __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + unsigned short operator |=( unsigned short __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + unsigned short operator ^=( unsigned short __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_ushort*, unsigned short, + memory_order ); + friend unsigned short atomic_load_explicit( volatile atomic_ushort*, + memory_order ); + friend unsigned short atomic_exchange_explicit( volatile atomic_ushort*, + unsigned short, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_ushort*, + unsigned short*, unsigned short, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_ushort*, + unsigned short*, unsigned short, memory_order, memory_order ); + friend unsigned short atomic_fetch_add_explicit( volatile atomic_ushort*, + unsigned short, memory_order ); + friend unsigned short atomic_fetch_sub_explicit( volatile atomic_ushort*, + unsigned short, memory_order ); + friend unsigned short atomic_fetch_and_explicit( volatile atomic_ushort*, + unsigned short, memory_order ); + friend unsigned short atomic_fetch_or_explicit( volatile atomic_ushort*, + unsigned short, memory_order ); + friend unsigned short atomic_fetch_xor_explicit( volatile atomic_ushort*, + unsigned short, memory_order ); + +CPP0X(private:) +#endif + unsigned short __f__; +} atomic_ushort; + + +typedef struct atomic_int +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( int, + memory_order = memory_order_seq_cst ) volatile; + int load( memory_order = memory_order_seq_cst ) volatile; + int exchange( int, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( int&, int, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( int&, int, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( int&, int, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( int&, int, + memory_order = memory_order_seq_cst ) volatile; + int fetch_add( int, + memory_order = memory_order_seq_cst ) volatile; + int fetch_sub( int, + memory_order = memory_order_seq_cst ) volatile; + int fetch_and( int, + memory_order = memory_order_seq_cst ) volatile; + int fetch_or( int, + memory_order = memory_order_seq_cst ) volatile; + int fetch_xor( int, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_int() = default; ) + CPP0X( constexpr atomic_int( int __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_int( const atomic_int& ) = delete; ) + atomic_int& operator =( const atomic_int& ) CPP0X(=delete); + + int operator =( int __v__ ) volatile + { store( __v__ ); return __v__; } + + int operator ++( int ) volatile + { return fetch_add( 1 ); } + + int operator --( int ) volatile + { return fetch_sub( 1 ); } + + int operator ++() volatile + { return fetch_add( 1 ) + 1; } + + int operator --() volatile + { return fetch_sub( 1 ) - 1; } + + int operator +=( int __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + int operator -=( int __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + int operator &=( int __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + int operator |=( int __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + int operator ^=( int __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_int*, int, + memory_order ); + friend int atomic_load_explicit( volatile atomic_int*, + memory_order ); + friend int atomic_exchange_explicit( volatile atomic_int*, + int, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_int*, + int*, int, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_int*, + int*, int, memory_order, memory_order ); + friend int atomic_fetch_add_explicit( volatile atomic_int*, + int, memory_order ); + friend int atomic_fetch_sub_explicit( volatile atomic_int*, + int, memory_order ); + friend int atomic_fetch_and_explicit( volatile atomic_int*, + int, memory_order ); + friend int atomic_fetch_or_explicit( volatile atomic_int*, + int, memory_order ); + friend int atomic_fetch_xor_explicit( volatile atomic_int*, + int, memory_order ); + +CPP0X(private:) +#endif + int __f__; +} atomic_int; + + +typedef struct atomic_uint +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( unsigned int, + memory_order = memory_order_seq_cst ) volatile; + unsigned int load( memory_order = memory_order_seq_cst ) volatile; + unsigned int exchange( unsigned int, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( unsigned int&, unsigned int, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( unsigned int&, unsigned int, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( unsigned int&, unsigned int, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( unsigned int&, unsigned int, + memory_order = memory_order_seq_cst ) volatile; + unsigned int fetch_add( unsigned int, + memory_order = memory_order_seq_cst ) volatile; + unsigned int fetch_sub( unsigned int, + memory_order = memory_order_seq_cst ) volatile; + unsigned int fetch_and( unsigned int, + memory_order = memory_order_seq_cst ) volatile; + unsigned int fetch_or( unsigned int, + memory_order = memory_order_seq_cst ) volatile; + unsigned int fetch_xor( unsigned int, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_uint() = default; ) + CPP0X( constexpr atomic_uint( unsigned int __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_uint( const atomic_uint& ) = delete; ) + atomic_uint& operator =( const atomic_uint& ) CPP0X(=delete); + + unsigned int operator =( unsigned int __v__ ) volatile + { store( __v__ ); return __v__; } + + unsigned int operator ++( int ) volatile + { return fetch_add( 1 ); } + + unsigned int operator --( int ) volatile + { return fetch_sub( 1 ); } + + unsigned int operator ++() volatile + { return fetch_add( 1 ) + 1; } + + unsigned int operator --() volatile + { return fetch_sub( 1 ) - 1; } + + unsigned int operator +=( unsigned int __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + unsigned int operator -=( unsigned int __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + unsigned int operator &=( unsigned int __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + unsigned int operator |=( unsigned int __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + unsigned int operator ^=( unsigned int __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_uint*, unsigned int, + memory_order ); + friend unsigned int atomic_load_explicit( volatile atomic_uint*, + memory_order ); + friend unsigned int atomic_exchange_explicit( volatile atomic_uint*, + unsigned int, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_uint*, + unsigned int*, unsigned int, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_uint*, + unsigned int*, unsigned int, memory_order, memory_order ); + friend unsigned int atomic_fetch_add_explicit( volatile atomic_uint*, + unsigned int, memory_order ); + friend unsigned int atomic_fetch_sub_explicit( volatile atomic_uint*, + unsigned int, memory_order ); + friend unsigned int atomic_fetch_and_explicit( volatile atomic_uint*, + unsigned int, memory_order ); + friend unsigned int atomic_fetch_or_explicit( volatile atomic_uint*, + unsigned int, memory_order ); + friend unsigned int atomic_fetch_xor_explicit( volatile atomic_uint*, + unsigned int, memory_order ); + +CPP0X(private:) +#endif + unsigned int __f__; +} atomic_uint; + + +typedef struct atomic_long +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( long, + memory_order = memory_order_seq_cst ) volatile; + long load( memory_order = memory_order_seq_cst ) volatile; + long exchange( long, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( long&, long, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( long&, long, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( long&, long, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( long&, long, + memory_order = memory_order_seq_cst ) volatile; + long fetch_add( long, + memory_order = memory_order_seq_cst ) volatile; + long fetch_sub( long, + memory_order = memory_order_seq_cst ) volatile; + long fetch_and( long, + memory_order = memory_order_seq_cst ) volatile; + long fetch_or( long, + memory_order = memory_order_seq_cst ) volatile; + long fetch_xor( long, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_long() = default; ) + CPP0X( constexpr atomic_long( long __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_long( const atomic_long& ) = delete; ) + atomic_long& operator =( const atomic_long& ) CPP0X(=delete); + + long operator =( long __v__ ) volatile + { store( __v__ ); return __v__; } + + long operator ++( int ) volatile + { return fetch_add( 1 ); } + + long operator --( int ) volatile + { return fetch_sub( 1 ); } + + long operator ++() volatile + { return fetch_add( 1 ) + 1; } + + long operator --() volatile + { return fetch_sub( 1 ) - 1; } + + long operator +=( long __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + long operator -=( long __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + long operator &=( long __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + long operator |=( long __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + long operator ^=( long __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_long*, long, + memory_order ); + friend long atomic_load_explicit( volatile atomic_long*, + memory_order ); + friend long atomic_exchange_explicit( volatile atomic_long*, + long, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_long*, + long*, long, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_long*, + long*, long, memory_order, memory_order ); + friend long atomic_fetch_add_explicit( volatile atomic_long*, + long, memory_order ); + friend long atomic_fetch_sub_explicit( volatile atomic_long*, + long, memory_order ); + friend long atomic_fetch_and_explicit( volatile atomic_long*, + long, memory_order ); + friend long atomic_fetch_or_explicit( volatile atomic_long*, + long, memory_order ); + friend long atomic_fetch_xor_explicit( volatile atomic_long*, + long, memory_order ); + +CPP0X(private:) +#endif + long __f__; +} atomic_long; + + +typedef struct atomic_ulong +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( unsigned long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long load( memory_order = memory_order_seq_cst ) volatile; + unsigned long exchange( unsigned long, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( unsigned long&, unsigned long, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( unsigned long&, unsigned long, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( unsigned long&, unsigned long, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( unsigned long&, unsigned long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long fetch_add( unsigned long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long fetch_sub( unsigned long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long fetch_and( unsigned long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long fetch_or( unsigned long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long fetch_xor( unsigned long, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_ulong() = default; ) + CPP0X( constexpr atomic_ulong( unsigned long __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_ulong( const atomic_ulong& ) = delete; ) + atomic_ulong& operator =( const atomic_ulong& ) CPP0X(=delete); + + unsigned long operator =( unsigned long __v__ ) volatile + { store( __v__ ); return __v__; } + + unsigned long operator ++( int ) volatile + { return fetch_add( 1 ); } + + unsigned long operator --( int ) volatile + { return fetch_sub( 1 ); } + + unsigned long operator ++() volatile + { return fetch_add( 1 ) + 1; } + + unsigned long operator --() volatile + { return fetch_sub( 1 ) - 1; } + + unsigned long operator +=( unsigned long __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + unsigned long operator -=( unsigned long __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + unsigned long operator &=( unsigned long __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + unsigned long operator |=( unsigned long __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + unsigned long operator ^=( unsigned long __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_ulong*, unsigned long, + memory_order ); + friend unsigned long atomic_load_explicit( volatile atomic_ulong*, + memory_order ); + friend unsigned long atomic_exchange_explicit( volatile atomic_ulong*, + unsigned long, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_ulong*, + unsigned long*, unsigned long, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_ulong*, + unsigned long*, unsigned long, memory_order, memory_order ); + friend unsigned long atomic_fetch_add_explicit( volatile atomic_ulong*, + unsigned long, memory_order ); + friend unsigned long atomic_fetch_sub_explicit( volatile atomic_ulong*, + unsigned long, memory_order ); + friend unsigned long atomic_fetch_and_explicit( volatile atomic_ulong*, + unsigned long, memory_order ); + friend unsigned long atomic_fetch_or_explicit( volatile atomic_ulong*, + unsigned long, memory_order ); + friend unsigned long atomic_fetch_xor_explicit( volatile atomic_ulong*, + unsigned long, memory_order ); + +CPP0X(private:) +#endif + unsigned long __f__; +} atomic_ulong; + + +typedef struct atomic_llong +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( long long, + memory_order = memory_order_seq_cst ) volatile; + long long load( memory_order = memory_order_seq_cst ) volatile; + long long exchange( long long, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( long long&, long long, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( long long&, long long, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( long long&, long long, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( long long&, long long, + memory_order = memory_order_seq_cst ) volatile; + long long fetch_add( long long, + memory_order = memory_order_seq_cst ) volatile; + long long fetch_sub( long long, + memory_order = memory_order_seq_cst ) volatile; + long long fetch_and( long long, + memory_order = memory_order_seq_cst ) volatile; + long long fetch_or( long long, + memory_order = memory_order_seq_cst ) volatile; + long long fetch_xor( long long, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_llong() = default; ) + CPP0X( constexpr atomic_llong( long long __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_llong( const atomic_llong& ) = delete; ) + atomic_llong& operator =( const atomic_llong& ) CPP0X(=delete); + + long long operator =( long long __v__ ) volatile + { store( __v__ ); return __v__; } + + long long operator ++( int ) volatile + { return fetch_add( 1 ); } + + long long operator --( int ) volatile + { return fetch_sub( 1 ); } + + long long operator ++() volatile + { return fetch_add( 1 ) + 1; } + + long long operator --() volatile + { return fetch_sub( 1 ) - 1; } + + long long operator +=( long long __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + long long operator -=( long long __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + long long operator &=( long long __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + long long operator |=( long long __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + long long operator ^=( long long __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_llong*, long long, + memory_order ); + friend long long atomic_load_explicit( volatile atomic_llong*, + memory_order ); + friend long long atomic_exchange_explicit( volatile atomic_llong*, + long long, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_llong*, + long long*, long long, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_llong*, + long long*, long long, memory_order, memory_order ); + friend long long atomic_fetch_add_explicit( volatile atomic_llong*, + long long, memory_order ); + friend long long atomic_fetch_sub_explicit( volatile atomic_llong*, + long long, memory_order ); + friend long long atomic_fetch_and_explicit( volatile atomic_llong*, + long long, memory_order ); + friend long long atomic_fetch_or_explicit( volatile atomic_llong*, + long long, memory_order ); + friend long long atomic_fetch_xor_explicit( volatile atomic_llong*, + long long, memory_order ); + +CPP0X(private:) +#endif + long long __f__; +} atomic_llong; + + +typedef struct atomic_ullong +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long long load( memory_order = memory_order_seq_cst ) volatile; + unsigned long long exchange( unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( unsigned long long&, unsigned long long, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( unsigned long long&, unsigned long long, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( unsigned long long&, unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( unsigned long long&, unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long long fetch_add( unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long long fetch_sub( unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long long fetch_and( unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long long fetch_or( unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + unsigned long long fetch_xor( unsigned long long, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_ullong() = default; ) + CPP0X( constexpr atomic_ullong( unsigned long long __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_ullong( const atomic_ullong& ) = delete; ) + atomic_ullong& operator =( const atomic_ullong& ) CPP0X(=delete); + + unsigned long long operator =( unsigned long long __v__ ) volatile + { store( __v__ ); return __v__; } + + unsigned long long operator ++( int ) volatile + { return fetch_add( 1 ); } + + unsigned long long operator --( int ) volatile + { return fetch_sub( 1 ); } + + unsigned long long operator ++() volatile + { return fetch_add( 1 ) + 1; } + + unsigned long long operator --() volatile + { return fetch_sub( 1 ) - 1; } + + unsigned long long operator +=( unsigned long long __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + unsigned long long operator -=( unsigned long long __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + unsigned long long operator &=( unsigned long long __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + unsigned long long operator |=( unsigned long long __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + unsigned long long operator ^=( unsigned long long __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_ullong*, unsigned long long, + memory_order ); + friend unsigned long long atomic_load_explicit( volatile atomic_ullong*, + memory_order ); + friend unsigned long long atomic_exchange_explicit( volatile atomic_ullong*, + unsigned long long, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_ullong*, + unsigned long long*, unsigned long long, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_ullong*, + unsigned long long*, unsigned long long, memory_order, memory_order ); + friend unsigned long long atomic_fetch_add_explicit( volatile atomic_ullong*, + unsigned long long, memory_order ); + friend unsigned long long atomic_fetch_sub_explicit( volatile atomic_ullong*, + unsigned long long, memory_order ); + friend unsigned long long atomic_fetch_and_explicit( volatile atomic_ullong*, + unsigned long long, memory_order ); + friend unsigned long long atomic_fetch_or_explicit( volatile atomic_ullong*, + unsigned long long, memory_order ); + friend unsigned long long atomic_fetch_xor_explicit( volatile atomic_ullong*, + unsigned long long, memory_order ); + +CPP0X(private:) +#endif + unsigned long long __f__; +} atomic_ullong; + + +typedef atomic_schar atomic_int_least8_t; +typedef atomic_uchar atomic_uint_least8_t; +typedef atomic_short atomic_int_least16_t; +typedef atomic_ushort atomic_uint_least16_t; +typedef atomic_int atomic_int_least32_t; +typedef atomic_uint atomic_uint_least32_t; +typedef atomic_llong atomic_int_least64_t; +typedef atomic_ullong atomic_uint_least64_t; + +typedef atomic_schar atomic_int_fast8_t; +typedef atomic_uchar atomic_uint_fast8_t; +typedef atomic_short atomic_int_fast16_t; +typedef atomic_ushort atomic_uint_fast16_t; +typedef atomic_int atomic_int_fast32_t; +typedef atomic_uint atomic_uint_fast32_t; +typedef atomic_llong atomic_int_fast64_t; +typedef atomic_ullong atomic_uint_fast64_t; + +typedef atomic_long atomic_intptr_t; +typedef atomic_ulong atomic_uintptr_t; + +typedef atomic_long atomic_ssize_t; +typedef atomic_ulong atomic_size_t; + +typedef atomic_long atomic_ptrdiff_t; + +typedef atomic_llong atomic_intmax_t; +typedef atomic_ullong atomic_uintmax_t; + + +#ifdef __cplusplus + + +typedef struct atomic_wchar_t +{ +#ifdef __cplusplus + bool is_lock_free() const volatile; + void store( wchar_t, memory_order = memory_order_seq_cst ) volatile; + wchar_t load( memory_order = memory_order_seq_cst ) volatile; + wchar_t exchange( wchar_t, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( wchar_t&, wchar_t, + memory_order, memory_order ) volatile; + bool compare_exchange_strong( wchar_t&, wchar_t, + memory_order, memory_order ) volatile; + bool compare_exchange_weak( wchar_t&, wchar_t, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( wchar_t&, wchar_t, + memory_order = memory_order_seq_cst ) volatile; + wchar_t fetch_add( wchar_t, + memory_order = memory_order_seq_cst ) volatile; + wchar_t fetch_sub( wchar_t, + memory_order = memory_order_seq_cst ) volatile; + wchar_t fetch_and( wchar_t, + memory_order = memory_order_seq_cst ) volatile; + wchar_t fetch_or( wchar_t, + memory_order = memory_order_seq_cst ) volatile; + wchar_t fetch_xor( wchar_t, + memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic_wchar_t() = default; ) + CPP0X( constexpr atomic_wchar_t( wchar_t __v__ ) : __f__( __v__) { } ) + CPP0X( atomic_wchar_t( const atomic_wchar_t& ) = delete; ) + atomic_wchar_t& operator =( const atomic_wchar_t& ) CPP0X(=delete); + + wchar_t operator =( wchar_t __v__ ) volatile + { store( __v__ ); return __v__; } + + wchar_t operator ++( int ) volatile + { return fetch_add( 1 ); } + + wchar_t operator --( int ) volatile + { return fetch_sub( 1 ); } + + wchar_t operator ++() volatile + { return fetch_add( 1 ) + 1; } + + wchar_t operator --() volatile + { return fetch_sub( 1 ) - 1; } + + wchar_t operator +=( wchar_t __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + wchar_t operator -=( wchar_t __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } + + wchar_t operator &=( wchar_t __v__ ) volatile + { return fetch_and( __v__ ) & __v__; } + + wchar_t operator |=( wchar_t __v__ ) volatile + { return fetch_or( __v__ ) | __v__; } + + wchar_t operator ^=( wchar_t __v__ ) volatile + { return fetch_xor( __v__ ) ^ __v__; } + + friend void atomic_store_explicit( volatile atomic_wchar_t*, wchar_t, + memory_order ); + friend wchar_t atomic_load_explicit( volatile atomic_wchar_t*, + memory_order ); + friend wchar_t atomic_exchange_explicit( volatile atomic_wchar_t*, + wchar_t, memory_order ); + friend bool atomic_compare_exchange_weak_explicit( volatile atomic_wchar_t*, + wchar_t*, wchar_t, memory_order, memory_order ); + friend bool atomic_compare_exchange_strong_explicit( volatile atomic_wchar_t*, + wchar_t*, wchar_t, memory_order, memory_order ); + friend wchar_t atomic_fetch_add_explicit( volatile atomic_wchar_t*, + wchar_t, memory_order ); + friend wchar_t atomic_fetch_sub_explicit( volatile atomic_wchar_t*, + wchar_t, memory_order ); + friend wchar_t atomic_fetch_and_explicit( volatile atomic_wchar_t*, + wchar_t, memory_order ); + friend wchar_t atomic_fetch_or_explicit( volatile atomic_wchar_t*, + wchar_t, memory_order ); + friend wchar_t atomic_fetch_xor_explicit( volatile atomic_wchar_t*, + wchar_t, memory_order ); + +CPP0X(private:) +#endif + wchar_t __f__; +} atomic_wchar_t; + + +#else + +typedef atomic_int_least16_t atomic_char16_t; +typedef atomic_int_least32_t atomic_char32_t; +typedef atomic_int_least32_t atomic_wchar_t; + +#endif + + +#ifdef __cplusplus + +template< typename T > +struct atomic +{ +#ifdef __cplusplus + + bool is_lock_free() const volatile; + void store( T, memory_order = memory_order_seq_cst ) volatile; + T load( memory_order = memory_order_seq_cst ) volatile; + T exchange( T __v__, memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( T&, T, memory_order, memory_order ) volatile; + bool compare_exchange_strong( T&, T, memory_order, memory_order ) volatile; + bool compare_exchange_weak( T&, T, memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( T&, T, memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( T __v__ ) : __f__( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + T operator =( T __v__ ) volatile + { store( __v__ ); return __v__; } + +CPP0X(private:) +#endif + T __f__; +}; + +#endif + +#ifdef __cplusplus + +template struct atomic< T* > : atomic_address +{ + T* load( memory_order = memory_order_seq_cst ) volatile; + T* exchange( T*, memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_weak( T*&, T*, memory_order, memory_order ) volatile; + bool compare_exchange_strong( T*&, T*, memory_order, memory_order ) volatile; + bool compare_exchange_weak( T*&, T*, + memory_order = memory_order_seq_cst ) volatile; + bool compare_exchange_strong( T*&, T*, + memory_order = memory_order_seq_cst ) volatile; + T* fetch_add( ptrdiff_t, memory_order = memory_order_seq_cst ) volatile; + T* fetch_sub( ptrdiff_t, memory_order = memory_order_seq_cst ) volatile; + + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( T __v__ ) : atomic_address( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + T* operator =( T* __v__ ) volatile + { store( __v__ ); return __v__; } + + T* operator ++( int ) volatile + { return fetch_add( 1 ); } + + T* operator --( int ) volatile + { return fetch_sub( 1 ); } + + T* operator ++() volatile + { return fetch_add( 1 ) + 1; } + + T* operator --() volatile + { return fetch_sub( 1 ) - 1; } + + T* operator +=( T* __v__ ) volatile + { return fetch_add( __v__ ) + __v__; } + + T* operator -=( T* __v__ ) volatile + { return fetch_sub( __v__ ) - __v__; } +}; + +#endif + +#ifdef __cplusplus + + +template<> struct atomic< bool > : atomic_bool +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( bool __v__ ) + : atomic_bool( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + bool operator =( bool __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< void* > : atomic_address +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( void* __v__ ) + : atomic_address( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + void* operator =( void* __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< char > : atomic_char +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( char __v__ ) + : atomic_char( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + char operator =( char __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< signed char > : atomic_schar +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( signed char __v__ ) + : atomic_schar( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + signed char operator =( signed char __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< unsigned char > : atomic_uchar +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( unsigned char __v__ ) + : atomic_uchar( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + unsigned char operator =( unsigned char __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< short > : atomic_short +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( short __v__ ) + : atomic_short( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + short operator =( short __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< unsigned short > : atomic_ushort +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( unsigned short __v__ ) + : atomic_ushort( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + unsigned short operator =( unsigned short __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< int > : atomic_int +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( int __v__ ) + : atomic_int( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + int operator =( int __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< unsigned int > : atomic_uint +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( unsigned int __v__ ) + : atomic_uint( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + unsigned int operator =( unsigned int __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< long > : atomic_long +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( long __v__ ) + : atomic_long( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + long operator =( long __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< unsigned long > : atomic_ulong +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( unsigned long __v__ ) + : atomic_ulong( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + unsigned long operator =( unsigned long __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< long long > : atomic_llong +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( long long __v__ ) + : atomic_llong( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + long long operator =( long long __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< unsigned long long > : atomic_ullong +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( unsigned long long __v__ ) + : atomic_ullong( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + unsigned long long operator =( unsigned long long __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +template<> struct atomic< wchar_t > : atomic_wchar_t +{ + CPP0X( atomic() = default; ) + CPP0X( constexpr explicit atomic( wchar_t __v__ ) + : atomic_wchar_t( __v__ ) { } ) + CPP0X( atomic( const atomic& ) = delete; ) + atomic& operator =( const atomic& ) CPP0X(=delete); + + wchar_t operator =( wchar_t __v__ ) volatile + { store( __v__ ); return __v__; } +}; + + +#endif + + +#ifdef __cplusplus + + +inline bool atomic_is_lock_free +( const volatile atomic_bool* __a__ ) +{ return false; } + +inline bool atomic_load_explicit +( volatile atomic_bool* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline bool atomic_load +( volatile atomic_bool* __a__ ) { return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_bool* __a__, bool __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_bool* __a__, bool __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_bool* __a__, bool __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_exchange_explicit +( volatile atomic_bool* __a__, bool __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline bool atomic_exchange +( volatile atomic_bool* __a__, bool __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_bool* __a__, bool* __e__, bool __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_bool* __a__, bool* __e__, bool __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_bool* __a__, bool* __e__, bool __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_bool* __a__, bool* __e__, bool __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_address* __a__ ) +{ return false; } + +inline void* atomic_load_explicit +( volatile atomic_address* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline void* atomic_load( volatile atomic_address* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_address* __a__, void* __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_address* __a__, void* __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_address* __a__, void* __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline void* atomic_exchange_explicit +( volatile atomic_address* __a__, void* __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline void* atomic_exchange +( volatile atomic_address* __a__, void* __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_address* __a__, void** __e__, void* __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_address* __a__, void** __e__, void* __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_address* __a__, void** __e__, void* __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_address* __a__, void** __e__, void* __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_char* __a__ ) +{ return false; } + +inline char atomic_load_explicit +( volatile atomic_char* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline char atomic_load( volatile atomic_char* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_char* __a__, char __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_char* __a__, char __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_char* __a__, char __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline char atomic_exchange_explicit +( volatile atomic_char* __a__, char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline char atomic_exchange +( volatile atomic_char* __a__, char __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_char* __a__, char* __e__, char __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_char* __a__, char* __e__, char __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_char* __a__, char* __e__, char __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_char* __a__, char* __e__, char __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_schar* __a__ ) +{ return false; } + +inline signed char atomic_load_explicit +( volatile atomic_schar* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline signed char atomic_load( volatile atomic_schar* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_schar* __a__, signed char __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_schar* __a__, signed char __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_schar* __a__, signed char __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline signed char atomic_exchange_explicit +( volatile atomic_schar* __a__, signed char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline signed char atomic_exchange +( volatile atomic_schar* __a__, signed char __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_schar* __a__, signed char* __e__, signed char __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_schar* __a__, signed char* __e__, signed char __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_schar* __a__, signed char* __e__, signed char __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_schar* __a__, signed char* __e__, signed char __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_uchar* __a__ ) +{ return false; } + +inline unsigned char atomic_load_explicit +( volatile atomic_uchar* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline unsigned char atomic_load( volatile atomic_uchar* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_uchar* __a__, unsigned char __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_uchar* __a__, unsigned char __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_uchar* __a__, unsigned char __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline unsigned char atomic_exchange_explicit +( volatile atomic_uchar* __a__, unsigned char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline unsigned char atomic_exchange +( volatile atomic_uchar* __a__, unsigned char __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_uchar* __a__, unsigned char* __e__, unsigned char __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_uchar* __a__, unsigned char* __e__, unsigned char __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_uchar* __a__, unsigned char* __e__, unsigned char __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_uchar* __a__, unsigned char* __e__, unsigned char __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_short* __a__ ) +{ return false; } + +inline short atomic_load_explicit +( volatile atomic_short* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline short atomic_load( volatile atomic_short* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_short* __a__, short __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_short* __a__, short __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_short* __a__, short __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline short atomic_exchange_explicit +( volatile atomic_short* __a__, short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline short atomic_exchange +( volatile atomic_short* __a__, short __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_short* __a__, short* __e__, short __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_short* __a__, short* __e__, short __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_short* __a__, short* __e__, short __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_short* __a__, short* __e__, short __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_ushort* __a__ ) +{ return false; } + +inline unsigned short atomic_load_explicit +( volatile atomic_ushort* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline unsigned short atomic_load( volatile atomic_ushort* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_ushort* __a__, unsigned short __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_ushort* __a__, unsigned short __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_ushort* __a__, unsigned short __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline unsigned short atomic_exchange_explicit +( volatile atomic_ushort* __a__, unsigned short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline unsigned short atomic_exchange +( volatile atomic_ushort* __a__, unsigned short __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_ushort* __a__, unsigned short* __e__, unsigned short __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_ushort* __a__, unsigned short* __e__, unsigned short __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_ushort* __a__, unsigned short* __e__, unsigned short __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_ushort* __a__, unsigned short* __e__, unsigned short __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_int* __a__ ) +{ return false; } + +inline int atomic_load_explicit +( volatile atomic_int* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline int atomic_load( volatile atomic_int* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_int* __a__, int __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_int* __a__, int __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_int* __a__, int __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline int atomic_exchange_explicit +( volatile atomic_int* __a__, int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline int atomic_exchange +( volatile atomic_int* __a__, int __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_int* __a__, int* __e__, int __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_int* __a__, int* __e__, int __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_int* __a__, int* __e__, int __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_int* __a__, int* __e__, int __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_uint* __a__ ) +{ return false; } + +inline unsigned int atomic_load_explicit +( volatile atomic_uint* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline unsigned int atomic_load( volatile atomic_uint* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_uint* __a__, unsigned int __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_uint* __a__, unsigned int __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_uint* __a__, unsigned int __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline unsigned int atomic_exchange_explicit +( volatile atomic_uint* __a__, unsigned int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline unsigned int atomic_exchange +( volatile atomic_uint* __a__, unsigned int __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_uint* __a__, unsigned int* __e__, unsigned int __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_uint* __a__, unsigned int* __e__, unsigned int __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_uint* __a__, unsigned int* __e__, unsigned int __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_uint* __a__, unsigned int* __e__, unsigned int __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_long* __a__ ) +{ return false; } + +inline long atomic_load_explicit +( volatile atomic_long* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline long atomic_load( volatile atomic_long* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_long* __a__, long __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_long* __a__, long __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_long* __a__, long __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline long atomic_exchange_explicit +( volatile atomic_long* __a__, long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline long atomic_exchange +( volatile atomic_long* __a__, long __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_long* __a__, long* __e__, long __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_long* __a__, long* __e__, long __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_long* __a__, long* __e__, long __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_long* __a__, long* __e__, long __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_ulong* __a__ ) +{ return false; } + +inline unsigned long atomic_load_explicit +( volatile atomic_ulong* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline unsigned long atomic_load( volatile atomic_ulong* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_ulong* __a__, unsigned long __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_ulong* __a__, unsigned long __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_ulong* __a__, unsigned long __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline unsigned long atomic_exchange_explicit +( volatile atomic_ulong* __a__, unsigned long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline unsigned long atomic_exchange +( volatile atomic_ulong* __a__, unsigned long __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_ulong* __a__, unsigned long* __e__, unsigned long __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_ulong* __a__, unsigned long* __e__, unsigned long __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_ulong* __a__, unsigned long* __e__, unsigned long __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_ulong* __a__, unsigned long* __e__, unsigned long __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_llong* __a__ ) +{ return false; } + +inline long long atomic_load_explicit +( volatile atomic_llong* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline long long atomic_load( volatile atomic_llong* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_llong* __a__, long long __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_llong* __a__, long long __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_llong* __a__, long long __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline long long atomic_exchange_explicit +( volatile atomic_llong* __a__, long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline long long atomic_exchange +( volatile atomic_llong* __a__, long long __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_llong* __a__, long long* __e__, long long __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_llong* __a__, long long* __e__, long long __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_llong* __a__, long long* __e__, long long __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_llong* __a__, long long* __e__, long long __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_ullong* __a__ ) +{ return false; } + +inline unsigned long long atomic_load_explicit +( volatile atomic_ullong* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline unsigned long long atomic_load( volatile atomic_ullong* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_ullong* __a__, unsigned long long __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_ullong* __a__, unsigned long long __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_ullong* __a__, unsigned long long __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline unsigned long long atomic_exchange_explicit +( volatile atomic_ullong* __a__, unsigned long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline unsigned long long atomic_exchange +( volatile atomic_ullong* __a__, unsigned long long __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_ullong* __a__, unsigned long long* __e__, unsigned long long __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_ullong* __a__, unsigned long long* __e__, unsigned long long __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_ullong* __a__, unsigned long long* __e__, unsigned long long __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_ullong* __a__, unsigned long long* __e__, unsigned long long __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline bool atomic_is_lock_free( const volatile atomic_wchar_t* __a__ ) +{ return false; } + +inline wchar_t atomic_load_explicit +( volatile atomic_wchar_t* __a__, memory_order __x__ ) +{ return _ATOMIC_LOAD_( __a__, __x__ ); } + +inline wchar_t atomic_load( volatile atomic_wchar_t* __a__ ) +{ return atomic_load_explicit( __a__, memory_order_seq_cst ); } + +inline void atomic_init +( volatile atomic_wchar_t* __a__, wchar_t __m__ ) +{ _ATOMIC_INIT_( __a__, __m__ ); } + +inline void atomic_store_explicit +( volatile atomic_wchar_t* __a__, wchar_t __m__, memory_order __x__ ) +{ _ATOMIC_STORE_( __a__, __m__, __x__ ); } + +inline void atomic_store +( volatile atomic_wchar_t* __a__, wchar_t __m__ ) +{ atomic_store_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline wchar_t atomic_exchange_explicit +( volatile atomic_wchar_t* __a__, wchar_t __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, =, __m__, __x__ ); } + +inline wchar_t atomic_exchange +( volatile atomic_wchar_t* __a__, wchar_t __m__ ) +{ return atomic_exchange_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_weak_explicit +( volatile atomic_wchar_t* __a__, wchar_t* __e__, wchar_t __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_strong_explicit +( volatile atomic_wchar_t* __a__, wchar_t* __e__, wchar_t __m__, + memory_order __x__, memory_order __y__ ) +{ return _ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ); } + +inline bool atomic_compare_exchange_weak +( volatile atomic_wchar_t* __a__, wchar_t* __e__, wchar_t __m__ ) +{ return atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + +inline bool atomic_compare_exchange_strong +( volatile atomic_wchar_t* __a__, wchar_t* __e__, wchar_t __m__ ) +{ return atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, + memory_order_seq_cst, memory_order_seq_cst ); } + + +inline void* atomic_fetch_add_explicit +( volatile atomic_address* __a__, ptrdiff_t __m__, memory_order __x__ ) +{ + void* volatile* __p__ = &((__a__)->__f__); + void* __r__ = (void *) model_rmwr_action((void *)__p__, __x__); + model_rmw_action((void *)__p__, __x__, (uint64_t) ((char*)(*__p__) + __m__)); + return __r__; } + +inline void* atomic_fetch_add +( volatile atomic_address* __a__, ptrdiff_t __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline void* atomic_fetch_sub_explicit +( volatile atomic_address* __a__, ptrdiff_t __m__, memory_order __x__ ) +{ + void* volatile* __p__ = &((__a__)->__f__); + void* __r__ = (void *) model_rmwr_action((void *)__p__, __x__); + model_rmw_action((void *)__p__, __x__, (uint64_t)((char*)(*__p__) - __m__)); + return __r__; } + +inline void* atomic_fetch_sub +( volatile atomic_address* __a__, ptrdiff_t __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + +inline char atomic_fetch_add_explicit +( volatile atomic_char* __a__, char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline char atomic_fetch_add +( volatile atomic_char* __a__, char __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline char atomic_fetch_sub_explicit +( volatile atomic_char* __a__, char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline char atomic_fetch_sub +( volatile atomic_char* __a__, char __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline char atomic_fetch_and_explicit +( volatile atomic_char* __a__, char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline char atomic_fetch_and +( volatile atomic_char* __a__, char __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline char atomic_fetch_or_explicit +( volatile atomic_char* __a__, char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline char atomic_fetch_or +( volatile atomic_char* __a__, char __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline char atomic_fetch_xor_explicit +( volatile atomic_char* __a__, char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline char atomic_fetch_xor +( volatile atomic_char* __a__, char __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline signed char atomic_fetch_add_explicit +( volatile atomic_schar* __a__, signed char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline signed char atomic_fetch_add +( volatile atomic_schar* __a__, signed char __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline signed char atomic_fetch_sub_explicit +( volatile atomic_schar* __a__, signed char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline signed char atomic_fetch_sub +( volatile atomic_schar* __a__, signed char __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline signed char atomic_fetch_and_explicit +( volatile atomic_schar* __a__, signed char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline signed char atomic_fetch_and +( volatile atomic_schar* __a__, signed char __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline signed char atomic_fetch_or_explicit +( volatile atomic_schar* __a__, signed char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline signed char atomic_fetch_or +( volatile atomic_schar* __a__, signed char __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline signed char atomic_fetch_xor_explicit +( volatile atomic_schar* __a__, signed char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline signed char atomic_fetch_xor +( volatile atomic_schar* __a__, signed char __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned char atomic_fetch_add_explicit +( volatile atomic_uchar* __a__, unsigned char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline unsigned char atomic_fetch_add +( volatile atomic_uchar* __a__, unsigned char __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned char atomic_fetch_sub_explicit +( volatile atomic_uchar* __a__, unsigned char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline unsigned char atomic_fetch_sub +( volatile atomic_uchar* __a__, unsigned char __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned char atomic_fetch_and_explicit +( volatile atomic_uchar* __a__, unsigned char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline unsigned char atomic_fetch_and +( volatile atomic_uchar* __a__, unsigned char __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned char atomic_fetch_or_explicit +( volatile atomic_uchar* __a__, unsigned char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline unsigned char atomic_fetch_or +( volatile atomic_uchar* __a__, unsigned char __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned char atomic_fetch_xor_explicit +( volatile atomic_uchar* __a__, unsigned char __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline unsigned char atomic_fetch_xor +( volatile atomic_uchar* __a__, unsigned char __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline short atomic_fetch_add_explicit +( volatile atomic_short* __a__, short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline short atomic_fetch_add +( volatile atomic_short* __a__, short __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline short atomic_fetch_sub_explicit +( volatile atomic_short* __a__, short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline short atomic_fetch_sub +( volatile atomic_short* __a__, short __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline short atomic_fetch_and_explicit +( volatile atomic_short* __a__, short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline short atomic_fetch_and +( volatile atomic_short* __a__, short __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline short atomic_fetch_or_explicit +( volatile atomic_short* __a__, short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline short atomic_fetch_or +( volatile atomic_short* __a__, short __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline short atomic_fetch_xor_explicit +( volatile atomic_short* __a__, short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline short atomic_fetch_xor +( volatile atomic_short* __a__, short __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned short atomic_fetch_add_explicit +( volatile atomic_ushort* __a__, unsigned short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline unsigned short atomic_fetch_add +( volatile atomic_ushort* __a__, unsigned short __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned short atomic_fetch_sub_explicit +( volatile atomic_ushort* __a__, unsigned short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline unsigned short atomic_fetch_sub +( volatile atomic_ushort* __a__, unsigned short __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned short atomic_fetch_and_explicit +( volatile atomic_ushort* __a__, unsigned short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline unsigned short atomic_fetch_and +( volatile atomic_ushort* __a__, unsigned short __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned short atomic_fetch_or_explicit +( volatile atomic_ushort* __a__, unsigned short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline unsigned short atomic_fetch_or +( volatile atomic_ushort* __a__, unsigned short __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned short atomic_fetch_xor_explicit +( volatile atomic_ushort* __a__, unsigned short __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline unsigned short atomic_fetch_xor +( volatile atomic_ushort* __a__, unsigned short __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline int atomic_fetch_add_explicit +( volatile atomic_int* __a__, int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline int atomic_fetch_add +( volatile atomic_int* __a__, int __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline int atomic_fetch_sub_explicit +( volatile atomic_int* __a__, int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline int atomic_fetch_sub +( volatile atomic_int* __a__, int __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline int atomic_fetch_and_explicit +( volatile atomic_int* __a__, int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline int atomic_fetch_and +( volatile atomic_int* __a__, int __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline int atomic_fetch_or_explicit +( volatile atomic_int* __a__, int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline int atomic_fetch_or +( volatile atomic_int* __a__, int __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline int atomic_fetch_xor_explicit +( volatile atomic_int* __a__, int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline int atomic_fetch_xor +( volatile atomic_int* __a__, int __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned int atomic_fetch_add_explicit +( volatile atomic_uint* __a__, unsigned int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline unsigned int atomic_fetch_add +( volatile atomic_uint* __a__, unsigned int __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned int atomic_fetch_sub_explicit +( volatile atomic_uint* __a__, unsigned int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline unsigned int atomic_fetch_sub +( volatile atomic_uint* __a__, unsigned int __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned int atomic_fetch_and_explicit +( volatile atomic_uint* __a__, unsigned int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline unsigned int atomic_fetch_and +( volatile atomic_uint* __a__, unsigned int __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned int atomic_fetch_or_explicit +( volatile atomic_uint* __a__, unsigned int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline unsigned int atomic_fetch_or +( volatile atomic_uint* __a__, unsigned int __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned int atomic_fetch_xor_explicit +( volatile atomic_uint* __a__, unsigned int __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline unsigned int atomic_fetch_xor +( volatile atomic_uint* __a__, unsigned int __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long atomic_fetch_add_explicit +( volatile atomic_long* __a__, long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline long atomic_fetch_add +( volatile atomic_long* __a__, long __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long atomic_fetch_sub_explicit +( volatile atomic_long* __a__, long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline long atomic_fetch_sub +( volatile atomic_long* __a__, long __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long atomic_fetch_and_explicit +( volatile atomic_long* __a__, long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline long atomic_fetch_and +( volatile atomic_long* __a__, long __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long atomic_fetch_or_explicit +( volatile atomic_long* __a__, long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline long atomic_fetch_or +( volatile atomic_long* __a__, long __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long atomic_fetch_xor_explicit +( volatile atomic_long* __a__, long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline long atomic_fetch_xor +( volatile atomic_long* __a__, long __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long atomic_fetch_add_explicit +( volatile atomic_ulong* __a__, unsigned long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline unsigned long atomic_fetch_add +( volatile atomic_ulong* __a__, unsigned long __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long atomic_fetch_sub_explicit +( volatile atomic_ulong* __a__, unsigned long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline unsigned long atomic_fetch_sub +( volatile atomic_ulong* __a__, unsigned long __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long atomic_fetch_and_explicit +( volatile atomic_ulong* __a__, unsigned long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline unsigned long atomic_fetch_and +( volatile atomic_ulong* __a__, unsigned long __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long atomic_fetch_or_explicit +( volatile atomic_ulong* __a__, unsigned long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline unsigned long atomic_fetch_or +( volatile atomic_ulong* __a__, unsigned long __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long atomic_fetch_xor_explicit +( volatile atomic_ulong* __a__, unsigned long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline unsigned long atomic_fetch_xor +( volatile atomic_ulong* __a__, unsigned long __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long long atomic_fetch_add_explicit +( volatile atomic_llong* __a__, long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline long long atomic_fetch_add +( volatile atomic_llong* __a__, long long __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long long atomic_fetch_sub_explicit +( volatile atomic_llong* __a__, long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline long long atomic_fetch_sub +( volatile atomic_llong* __a__, long long __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long long atomic_fetch_and_explicit +( volatile atomic_llong* __a__, long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline long long atomic_fetch_and +( volatile atomic_llong* __a__, long long __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long long atomic_fetch_or_explicit +( volatile atomic_llong* __a__, long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline long long atomic_fetch_or +( volatile atomic_llong* __a__, long long __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline long long atomic_fetch_xor_explicit +( volatile atomic_llong* __a__, long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline long long atomic_fetch_xor +( volatile atomic_llong* __a__, long long __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long long atomic_fetch_add_explicit +( volatile atomic_ullong* __a__, unsigned long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline unsigned long long atomic_fetch_add +( volatile atomic_ullong* __a__, unsigned long long __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long long atomic_fetch_sub_explicit +( volatile atomic_ullong* __a__, unsigned long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline unsigned long long atomic_fetch_sub +( volatile atomic_ullong* __a__, unsigned long long __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long long atomic_fetch_and_explicit +( volatile atomic_ullong* __a__, unsigned long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline unsigned long long atomic_fetch_and +( volatile atomic_ullong* __a__, unsigned long long __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long long atomic_fetch_or_explicit +( volatile atomic_ullong* __a__, unsigned long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline unsigned long long atomic_fetch_or +( volatile atomic_ullong* __a__, unsigned long long __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline unsigned long long atomic_fetch_xor_explicit +( volatile atomic_ullong* __a__, unsigned long long __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline unsigned long long atomic_fetch_xor +( volatile atomic_ullong* __a__, unsigned long long __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline wchar_t atomic_fetch_add_explicit +( volatile atomic_wchar_t* __a__, wchar_t __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ); } + +inline wchar_t atomic_fetch_add +( volatile atomic_wchar_t* __a__, wchar_t __m__ ) +{ return atomic_fetch_add_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline wchar_t atomic_fetch_sub_explicit +( volatile atomic_wchar_t* __a__, wchar_t __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ); } + +inline wchar_t atomic_fetch_sub +( volatile atomic_wchar_t* __a__, wchar_t __m__ ) +{ return atomic_fetch_sub_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline wchar_t atomic_fetch_and_explicit +( volatile atomic_wchar_t* __a__, wchar_t __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ); } + +inline wchar_t atomic_fetch_and +( volatile atomic_wchar_t* __a__, wchar_t __m__ ) +{ return atomic_fetch_and_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline wchar_t atomic_fetch_or_explicit +( volatile atomic_wchar_t* __a__, wchar_t __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ); } + +inline wchar_t atomic_fetch_or +( volatile atomic_wchar_t* __a__, wchar_t __m__ ) +{ return atomic_fetch_or_explicit( __a__, __m__, memory_order_seq_cst ); } + + +inline wchar_t atomic_fetch_xor_explicit +( volatile atomic_wchar_t* __a__, wchar_t __m__, memory_order __x__ ) +{ return _ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ); } + +inline wchar_t atomic_fetch_xor +( volatile atomic_wchar_t* __a__, wchar_t __m__ ) +{ return atomic_fetch_xor_explicit( __a__, __m__, memory_order_seq_cst ); } + + +#else + + +#define atomic_is_lock_free( __a__ ) \ +false + +#define atomic_load( __a__ ) \ +_ATOMIC_LOAD_( __a__, memory_order_seq_cst ) + +#define atomic_load_explicit( __a__, __x__ ) \ +_ATOMIC_LOAD_( __a__, __x__ ) + +#define atomic_init( __a__, __m__ ) \ +_ATOMIC_INIT_( __a__, __m__ ) + +#define atomic_store( __a__, __m__ ) \ +_ATOMIC_STORE_( __a__, __m__, memory_order_seq_cst ) + +#define atomic_store_explicit( __a__, __m__, __x__ ) \ +_ATOMIC_STORE_( __a__, __m__, __x__ ) + +#define atomic_exchange( __a__, __m__ ) \ +_ATOMIC_MODIFY_( __a__, =, __m__, memory_order_seq_cst ) + +#define atomic_exchange_explicit( __a__, __m__, __x__ ) \ +_ATOMIC_MODIFY_( __a__, =, __m__, __x__ ) + +#define atomic_compare_exchange_weak( __a__, __e__, __m__ ) \ +_ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, memory_order_seq_cst ) + +#define atomic_compare_exchange_strong( __a__, __e__, __m__ ) \ +_ATOMIC_CMPSWP_( __a__, __e__, __m__, memory_order_seq_cst ) + +#define atomic_compare_exchange_weak_explicit( __a__, __e__, __m__, __x__, __y__ ) \ +_ATOMIC_CMPSWP_WEAK_( __a__, __e__, __m__, __x__ ) + +#define atomic_compare_exchange_strong_explicit( __a__, __e__, __m__, __x__, __y__ ) \ +_ATOMIC_CMPSWP_( __a__, __e__, __m__, __x__ ) + + +#define atomic_fetch_add_explicit( __a__, __m__, __x__ ) \ +_ATOMIC_MODIFY_( __a__, +=, __m__, __x__ ) + +#define atomic_fetch_add( __a__, __m__ ) \ +_ATOMIC_MODIFY_( __a__, +=, __m__, memory_order_seq_cst ) + + +#define atomic_fetch_sub_explicit( __a__, __m__, __x__ ) \ +_ATOMIC_MODIFY_( __a__, -=, __m__, __x__ ) + +#define atomic_fetch_sub( __a__, __m__ ) \ +_ATOMIC_MODIFY_( __a__, -=, __m__, memory_order_seq_cst ) + + +#define atomic_fetch_and_explicit( __a__, __m__, __x__ ) \ +_ATOMIC_MODIFY_( __a__, &=, __m__, __x__ ) + +#define atomic_fetch_and( __a__, __m__ ) \ +_ATOMIC_MODIFY_( __a__, &=, __m__, memory_order_seq_cst ) + + +#define atomic_fetch_or_explicit( __a__, __m__, __x__ ) \ +_ATOMIC_MODIFY_( __a__, |=, __m__, __x__ ) + +#define atomic_fetch_or( __a__, __m__ ) \ +_ATOMIC_MODIFY_( __a__, |=, __m__, memory_order_seq_cst ) + + +#define atomic_fetch_xor_explicit( __a__, __m__, __x__ ) \ +_ATOMIC_MODIFY_( __a__, ^=, __m__, __x__ ) + +#define atomic_fetch_xor( __a__, __m__ ) \ +_ATOMIC_MODIFY_( __a__, ^=, __m__, memory_order_seq_cst ) + + +#endif + + +#ifdef __cplusplus + + +inline bool atomic_bool::is_lock_free() const volatile +{ return false; } + +inline void atomic_bool::store +( bool __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline bool atomic_bool::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline bool atomic_bool::exchange +( bool __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_bool::compare_exchange_weak +( bool& __e__, bool __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_bool::compare_exchange_strong +( bool& __e__, bool __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_bool::compare_exchange_weak +( bool& __e__, bool __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_bool::compare_exchange_strong +( bool& __e__, bool __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_address::is_lock_free() const volatile +{ return false; } + +inline void atomic_address::store +( void* __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline void* atomic_address::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline void* atomic_address::exchange +( void* __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_address::compare_exchange_weak +( void*& __e__, void* __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_address::compare_exchange_strong +( void*& __e__, void* __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_address::compare_exchange_weak +( void*& __e__, void* __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_address::compare_exchange_strong +( void*& __e__, void* __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_char::is_lock_free() const volatile +{ return false; } + +inline void atomic_char::store +( char __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline char atomic_char::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline char atomic_char::exchange +( char __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_char::compare_exchange_weak +( char& __e__, char __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_char::compare_exchange_strong +( char& __e__, char __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_char::compare_exchange_weak +( char& __e__, char __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_char::compare_exchange_strong +( char& __e__, char __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_schar::is_lock_free() const volatile +{ return false; } + +inline void atomic_schar::store +( signed char __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline signed char atomic_schar::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline signed char atomic_schar::exchange +( signed char __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_schar::compare_exchange_weak +( signed char& __e__, signed char __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_schar::compare_exchange_strong +( signed char& __e__, signed char __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_schar::compare_exchange_weak +( signed char& __e__, signed char __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_schar::compare_exchange_strong +( signed char& __e__, signed char __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_uchar::is_lock_free() const volatile +{ return false; } + +inline void atomic_uchar::store +( unsigned char __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline unsigned char atomic_uchar::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline unsigned char atomic_uchar::exchange +( unsigned char __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_uchar::compare_exchange_weak +( unsigned char& __e__, unsigned char __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_uchar::compare_exchange_strong +( unsigned char& __e__, unsigned char __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_uchar::compare_exchange_weak +( unsigned char& __e__, unsigned char __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_uchar::compare_exchange_strong +( unsigned char& __e__, unsigned char __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_short::is_lock_free() const volatile +{ return false; } + +inline void atomic_short::store +( short __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline short atomic_short::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline short atomic_short::exchange +( short __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_short::compare_exchange_weak +( short& __e__, short __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_short::compare_exchange_strong +( short& __e__, short __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_short::compare_exchange_weak +( short& __e__, short __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_short::compare_exchange_strong +( short& __e__, short __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_ushort::is_lock_free() const volatile +{ return false; } + +inline void atomic_ushort::store +( unsigned short __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline unsigned short atomic_ushort::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline unsigned short atomic_ushort::exchange +( unsigned short __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_ushort::compare_exchange_weak +( unsigned short& __e__, unsigned short __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_ushort::compare_exchange_strong +( unsigned short& __e__, unsigned short __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_ushort::compare_exchange_weak +( unsigned short& __e__, unsigned short __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_ushort::compare_exchange_strong +( unsigned short& __e__, unsigned short __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_int::is_lock_free() const volatile +{ return false; } + +inline void atomic_int::store +( int __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline int atomic_int::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline int atomic_int::exchange +( int __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_int::compare_exchange_weak +( int& __e__, int __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_int::compare_exchange_strong +( int& __e__, int __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_int::compare_exchange_weak +( int& __e__, int __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_int::compare_exchange_strong +( int& __e__, int __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_uint::is_lock_free() const volatile +{ return false; } + +inline void atomic_uint::store +( unsigned int __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline unsigned int atomic_uint::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline unsigned int atomic_uint::exchange +( unsigned int __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_uint::compare_exchange_weak +( unsigned int& __e__, unsigned int __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_uint::compare_exchange_strong +( unsigned int& __e__, unsigned int __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_uint::compare_exchange_weak +( unsigned int& __e__, unsigned int __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_uint::compare_exchange_strong +( unsigned int& __e__, unsigned int __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_long::is_lock_free() const volatile +{ return false; } + +inline void atomic_long::store +( long __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline long atomic_long::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline long atomic_long::exchange +( long __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_long::compare_exchange_weak +( long& __e__, long __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_long::compare_exchange_strong +( long& __e__, long __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_long::compare_exchange_weak +( long& __e__, long __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_long::compare_exchange_strong +( long& __e__, long __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_ulong::is_lock_free() const volatile +{ return false; } + +inline void atomic_ulong::store +( unsigned long __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline unsigned long atomic_ulong::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline unsigned long atomic_ulong::exchange +( unsigned long __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_ulong::compare_exchange_weak +( unsigned long& __e__, unsigned long __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_ulong::compare_exchange_strong +( unsigned long& __e__, unsigned long __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_ulong::compare_exchange_weak +( unsigned long& __e__, unsigned long __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_ulong::compare_exchange_strong +( unsigned long& __e__, unsigned long __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_llong::is_lock_free() const volatile +{ return false; } + +inline void atomic_llong::store +( long long __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline long long atomic_llong::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline long long atomic_llong::exchange +( long long __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_llong::compare_exchange_weak +( long long& __e__, long long __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_llong::compare_exchange_strong +( long long& __e__, long long __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_llong::compare_exchange_weak +( long long& __e__, long long __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_llong::compare_exchange_strong +( long long& __e__, long long __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_ullong::is_lock_free() const volatile +{ return false; } + +inline void atomic_ullong::store +( unsigned long long __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline unsigned long long atomic_ullong::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline unsigned long long atomic_ullong::exchange +( unsigned long long __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_ullong::compare_exchange_weak +( unsigned long long& __e__, unsigned long long __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_ullong::compare_exchange_strong +( unsigned long long& __e__, unsigned long long __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_ullong::compare_exchange_weak +( unsigned long long& __e__, unsigned long long __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_ullong::compare_exchange_strong +( unsigned long long& __e__, unsigned long long __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline bool atomic_wchar_t::is_lock_free() const volatile +{ return false; } + +inline void atomic_wchar_t::store +( wchar_t __m__, memory_order __x__ ) volatile +{ atomic_store_explicit( this, __m__, __x__ ); } + +inline wchar_t atomic_wchar_t::load +( memory_order __x__ ) volatile +{ return atomic_load_explicit( this, __x__ ); } + +inline wchar_t atomic_wchar_t::exchange +( wchar_t __m__, memory_order __x__ ) volatile +{ return atomic_exchange_explicit( this, __m__, __x__ ); } + +inline bool atomic_wchar_t::compare_exchange_weak +( wchar_t& __e__, wchar_t __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_wchar_t::compare_exchange_strong +( wchar_t& __e__, wchar_t __m__, + memory_order __x__, memory_order __y__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, __y__ ); } + +inline bool atomic_wchar_t::compare_exchange_weak +( wchar_t& __e__, wchar_t __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_weak_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +inline bool atomic_wchar_t::compare_exchange_strong +( wchar_t& __e__, wchar_t __m__, memory_order __x__ ) volatile +{ return atomic_compare_exchange_strong_explicit( this, &__e__, __m__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +template< typename T > +inline bool atomic::is_lock_free() const volatile +{ return false; } + +template< typename T > +inline void atomic::store( T __v__, memory_order __x__ ) volatile +{ _ATOMIC_STORE_( this, __v__, __x__ ); } + +template< typename T > +inline T atomic::load( memory_order __x__ ) volatile +{ return _ATOMIC_LOAD_( this, __x__ ); } + +template< typename T > +inline T atomic::exchange( T __v__, memory_order __x__ ) volatile +{ return _ATOMIC_MODIFY_( this, =, __v__, __x__ ); } + +template< typename T > +inline bool atomic::compare_exchange_weak +( T& __r__, T __v__, memory_order __x__, memory_order __y__ ) volatile +{ return _ATOMIC_CMPSWP_WEAK_( this, &__r__, __v__, __x__ ); } + +template< typename T > +inline bool atomic::compare_exchange_strong +( T& __r__, T __v__, memory_order __x__, memory_order __y__ ) volatile +{ return _ATOMIC_CMPSWP_( this, &__r__, __v__, __x__ ); } + +template< typename T > +inline bool atomic::compare_exchange_weak +( T& __r__, T __v__, memory_order __x__ ) volatile +{ return compare_exchange_weak( __r__, __v__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +template< typename T > +inline bool atomic::compare_exchange_strong +( T& __r__, T __v__, memory_order __x__ ) volatile +{ return compare_exchange_strong( __r__, __v__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + + +inline void* atomic_address::fetch_add +( ptrdiff_t __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + +inline void* atomic_address::fetch_sub +( ptrdiff_t __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline char atomic_char::fetch_add +( char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline char atomic_char::fetch_sub +( char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline char atomic_char::fetch_and +( char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline char atomic_char::fetch_or +( char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline char atomic_char::fetch_xor +( char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline signed char atomic_schar::fetch_add +( signed char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline signed char atomic_schar::fetch_sub +( signed char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline signed char atomic_schar::fetch_and +( signed char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline signed char atomic_schar::fetch_or +( signed char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline signed char atomic_schar::fetch_xor +( signed char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline unsigned char atomic_uchar::fetch_add +( unsigned char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline unsigned char atomic_uchar::fetch_sub +( unsigned char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline unsigned char atomic_uchar::fetch_and +( unsigned char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline unsigned char atomic_uchar::fetch_or +( unsigned char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline unsigned char atomic_uchar::fetch_xor +( unsigned char __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline short atomic_short::fetch_add +( short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline short atomic_short::fetch_sub +( short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline short atomic_short::fetch_and +( short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline short atomic_short::fetch_or +( short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline short atomic_short::fetch_xor +( short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline unsigned short atomic_ushort::fetch_add +( unsigned short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline unsigned short atomic_ushort::fetch_sub +( unsigned short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline unsigned short atomic_ushort::fetch_and +( unsigned short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline unsigned short atomic_ushort::fetch_or +( unsigned short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline unsigned short atomic_ushort::fetch_xor +( unsigned short __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline int atomic_int::fetch_add +( int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline int atomic_int::fetch_sub +( int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline int atomic_int::fetch_and +( int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline int atomic_int::fetch_or +( int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline int atomic_int::fetch_xor +( int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline unsigned int atomic_uint::fetch_add +( unsigned int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline unsigned int atomic_uint::fetch_sub +( unsigned int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline unsigned int atomic_uint::fetch_and +( unsigned int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline unsigned int atomic_uint::fetch_or +( unsigned int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline unsigned int atomic_uint::fetch_xor +( unsigned int __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline long atomic_long::fetch_add +( long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline long atomic_long::fetch_sub +( long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline long atomic_long::fetch_and +( long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline long atomic_long::fetch_or +( long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline long atomic_long::fetch_xor +( long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline unsigned long atomic_ulong::fetch_add +( unsigned long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline unsigned long atomic_ulong::fetch_sub +( unsigned long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline unsigned long atomic_ulong::fetch_and +( unsigned long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline unsigned long atomic_ulong::fetch_or +( unsigned long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline unsigned long atomic_ulong::fetch_xor +( unsigned long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline long long atomic_llong::fetch_add +( long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline long long atomic_llong::fetch_sub +( long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline long long atomic_llong::fetch_and +( long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline long long atomic_llong::fetch_or +( long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline long long atomic_llong::fetch_xor +( long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline unsigned long long atomic_ullong::fetch_add +( unsigned long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline unsigned long long atomic_ullong::fetch_sub +( unsigned long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline unsigned long long atomic_ullong::fetch_and +( unsigned long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline unsigned long long atomic_ullong::fetch_or +( unsigned long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline unsigned long long atomic_ullong::fetch_xor +( unsigned long long __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +inline wchar_t atomic_wchar_t::fetch_add +( wchar_t __m__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, __m__, __x__ ); } + + +inline wchar_t atomic_wchar_t::fetch_sub +( wchar_t __m__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, __m__, __x__ ); } + + +inline wchar_t atomic_wchar_t::fetch_and +( wchar_t __m__, memory_order __x__ ) volatile +{ return atomic_fetch_and_explicit( this, __m__, __x__ ); } + + +inline wchar_t atomic_wchar_t::fetch_or +( wchar_t __m__, memory_order __x__ ) volatile +{ return atomic_fetch_or_explicit( this, __m__, __x__ ); } + + +inline wchar_t atomic_wchar_t::fetch_xor +( wchar_t __m__, memory_order __x__ ) volatile +{ return atomic_fetch_xor_explicit( this, __m__, __x__ ); } + + +template< typename T > +T* atomic::load( memory_order __x__ ) volatile +{ return static_cast( atomic_address::load( __x__ ) ); } + +template< typename T > +T* atomic::exchange( T* __v__, memory_order __x__ ) volatile +{ return static_cast( atomic_address::exchange( __v__, __x__ ) ); } + +template< typename T > +bool atomic::compare_exchange_weak +( T*& __r__, T* __v__, memory_order __x__, memory_order __y__) volatile +{ return atomic_address::compare_exchange_weak( *reinterpret_cast( &__r__ ), + static_cast( __v__ ), __x__, __y__ ); } +//{ return _ATOMIC_CMPSWP_WEAK_( this, &__r__, __v__, __x__ ); } + +template< typename T > +bool atomic::compare_exchange_strong +( T*& __r__, T* __v__, memory_order __x__, memory_order __y__) volatile +{ return atomic_address::compare_exchange_strong( *reinterpret_cast( &__r__ ), + static_cast( __v__ ), __x__, __y__ ); } +//{ return _ATOMIC_CMPSWP_( this, &__r__, __v__, __x__ ); } + +template< typename T > +bool atomic::compare_exchange_weak +( T*& __r__, T* __v__, memory_order __x__ ) volatile +{ return compare_exchange_weak( __r__, __v__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +template< typename T > +bool atomic::compare_exchange_strong +( T*& __r__, T* __v__, memory_order __x__ ) volatile +{ return compare_exchange_strong( __r__, __v__, __x__, + __x__ == memory_order_acq_rel ? memory_order_acquire : + __x__ == memory_order_release ? memory_order_relaxed : __x__ ); } + +template< typename T > +T* atomic::fetch_add( ptrdiff_t __v__, memory_order __x__ ) volatile +{ return atomic_fetch_add_explicit( this, sizeof(T) * __v__, __x__ ); } + +template< typename T > +T* atomic::fetch_sub( ptrdiff_t __v__, memory_order __x__ ) volatile +{ return atomic_fetch_sub_explicit( this, sizeof(T) * __v__, __x__ ); } + + +#endif + +#ifdef __cplusplus +extern "C" { +#endif +static inline void atomic_thread_fence(memory_order order) +{ _ATOMIC_FENCE_(order); } + +/** @todo Do we want to try to support a user's signal-handler? */ +static inline void atomic_signal_fence(memory_order order) +{ /* No-op? */ } +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus +} // namespace std +#endif + +#endif /* __IMPATOMIC_H__ */ diff --git a/include/libinterface.h b/include/libinterface.h new file mode 100644 index 0000000..e569ba1 --- /dev/null +++ b/include/libinterface.h @@ -0,0 +1,72 @@ +/** @file libinterface.h + * @brief Interface to check normal memory operations for data races. + */ + +#ifndef __LIBINTERFACE_H__ +#define __LIBINTERFACE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + typedef unsigned int MCID; +#define MC2_PTR_LENGTH sizeof(void *) + +#define MCID_NODEP ((MCID)0) +#define MCID_INIT ((MCID)0) +#define MCID_FIRST ((MCID)1) + +#define MC2_OFFSET(x, y) (uintptr_t)(&((x)(0))->y) + + void store_8(void *addr, uint8_t val); + void store_16(void *addr, uint16_t val); + void store_32(void *addr, uint32_t val); + void store_64(void *addr, uint64_t val); + + uint8_t load_8(const void *addr); + uint16_t load_16(const void *addr); + uint32_t load_32(const void *addr); + uint64_t load_64(const void *addr); + + enum atomicop { + ADD, + CAS, + EXC + }; + + uint8_t rmw_8(enum atomicop op, void *addr, uint8_t oldval, uint8_t valarg); + uint16_t rmw_16(enum atomicop op, void *addr, uint16_t oldval, uint16_t valarg); + uint32_t rmw_32(enum atomicop op, void *addr, uint32_t oldval, uint32_t valarg); + uint64_t rmw_64(enum atomicop op, void *addr, uint64_t oldval, uint64_t valarg); + MCID MC2_nextRMW(MCID addr, MCID oldval, MCID valarg); + + MCID MC2_nextOpLoad(MCID addr); + void MC2_nextOpStore(MCID addr, MCID value); + + MCID MC2_nextRMWOffset(MCID addr, uintptr_t offset, MCID oldval, MCID valarg); + + MCID MC2_nextOpLoadOffset(MCID addr, uintptr_t offset); + void MC2_nextOpStoreOffset(MCID addr, uintptr_t offset, MCID value); + MCID MC2_branchUsesID(MCID condition, int direction, int num_directions, bool anyvalue); + void MC2_nextOpThrd_create(MCID startfunc, MCID param); + void MC2_nextOpThrd_join(MCID jointhrd); + + void MC2_merge(MCID branchid); + MCID MC2_function(unsigned int num_args, int numbytesretval, uint64_t val, ...); + MCID MC2_function_id(unsigned int id, unsigned int num_args, int numbytesretval, uint64_t val, ...); + uint64_t MC2_equals(MCID op1, uint64_t val1, MCID op2, uint64_t val2, MCID *retval); + + MCID MC2_phi(MCID input); + MCID MC2_loop_phi(MCID input); + + void MC2_yield(); + void MC2_fence(); + void MC2_enterLoop(); + void MC2_exitLoop(); + void MC2_loopIterate(); +#ifdef __cplusplus +} +#endif + +#endif /* __LIBINTERFACE_H__ */ diff --git a/include/memoryorder.h b/include/memoryorder.h new file mode 100644 index 0000000..ba0dafd --- /dev/null +++ b/include/memoryorder.h @@ -0,0 +1,28 @@ +/** + * @file memoryorder.h + * @brief C11/C++11 atomic memory order listings + */ + +#ifndef MEMORYORDER_H +#define MEMORYORDER_H +#ifdef __cplusplus +#include +namespace std { +#else +#include +#endif + + +typedef enum memory_order { + memory_order_relaxed, memory_order_acquire, memory_order_release, + memory_order_acq_rel, memory_order_seq_cst +} memory_order; + + +#ifdef __cplusplus +} +#endif + + + +#endif diff --git a/include/model-assert.h b/include/model-assert.h new file mode 100644 index 0000000..ddc4427 --- /dev/null +++ b/include/model-assert.h @@ -0,0 +1,17 @@ +#ifndef __MODEL_ASSERT_H__ +#define __MODEL_ASSERT_H__ + +#if __cplusplus +extern "C" { +#else +#include +#endif + +void model_assert(bool expr, const char *file, int line); +#define MODEL_ASSERT(expr) model_assert((expr), __FILE__, __LINE__) + +#if __cplusplus +} +#endif + +#endif /* __MODEL_ASSERT_H__ */ diff --git a/include/modeltypes.h b/include/modeltypes.h new file mode 100644 index 0000000..34525d2 --- /dev/null +++ b/include/modeltypes.h @@ -0,0 +1,28 @@ +/** + * @file modeltypes.h + * @brief Common typedefs for the model-checker + */ + +#ifndef __MODELTYPES_H__ +#define __MODELTYPES_H__ + +/** + * @brief Represents a unique ID for a Thread + * + * The space of unique IDs may need to become a non-compact + * or non-zero-indexed set of integers (or even some other + * type). So this typedef is used to help identify which is + * which, where a simple 'int' is meant to be a compact, + * zero-indexed set and a 'thread_id_t' may be another type + * entirely. + * + * @see id_to_int + * @see int_to_id + */ +typedef int thread_id_t; + +#define THREAD_ID_T_NONE -1 + +typedef unsigned int modelclock_t; + +#endif /* __MODELTYPES_H__ */ diff --git a/include/mutex b/include/mutex new file mode 100644 index 0000000..bd65a78 --- /dev/null +++ b/include/mutex @@ -0,0 +1,31 @@ +/** + * @file mutex + * @brief C++11 mutex interface header + */ + +#ifndef __CXX_MUTEX__ +#define __CXX_MUTEX__ + +#include "modeltypes.h" + +namespace std { + struct mutex_state { + void *locked; /* Thread holding the lock */ + thread_id_t alloc_tid; + modelclock_t alloc_clock; + }; + + class mutex { + public: + mutex(); + ~mutex() {} + void lock(); + bool try_lock(); + void unlock(); + struct mutex_state * get_state() {return &state;} + + private: + struct mutex_state state; + }; +} +#endif /* __CXX_MUTEX__ */ diff --git a/include/stdatomic.h b/include/stdatomic.h new file mode 100644 index 0000000..d4d2198 --- /dev/null +++ b/include/stdatomic.h @@ -0,0 +1,72 @@ +/** + * @file stdatomic.h + * @brief C11 atomic interface header + */ + +#ifndef __STDATOMIC_H__ +#define __STDATOMIC_H__ + +#include "impatomic.h" + +#ifdef __cplusplus + + +using std::atomic_flag; + + +using std::atomic_bool; + + +using std::atomic_address; + + +using std::atomic_char; + + +using std::atomic_schar; + + +using std::atomic_uchar; + + +using std::atomic_short; + + +using std::atomic_ushort; + + +using std::atomic_int; + + +using std::atomic_uint; + + +using std::atomic_long; + + +using std::atomic_ulong; + + +using std::atomic_llong; + + +using std::atomic_ullong; + + +using std::atomic_wchar_t; + + +using std::atomic; +using std::memory_order; +using std::memory_order_relaxed; +using std::memory_order_acquire; +using std::memory_order_release; +using std::memory_order_acq_rel; +using std::memory_order_seq_cst; + +using std::atomic_thread_fence; +using std::atomic_signal_fence; + +#endif /* __cplusplus */ + +#endif /* __STDATOMIC_H__ */ diff --git a/include/threads.h b/include/threads.h new file mode 100644 index 0000000..f38be0a --- /dev/null +++ b/include/threads.h @@ -0,0 +1,37 @@ +/** @file threads.h + * @brief C11 Thread Library Functionality + */ + +#ifndef __THREADS_H__ +#define __THREADS_H__ + +/* Forward declaration */ +#ifdef __cplusplus +typedef class Thread *__thread_identifier; +#else +/* For C, we just need an opaque pointer */ +typedef void *__thread_identifier; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + typedef void (*thrd_start_t)(void *); + + typedef struct { + __thread_identifier priv; + } thrd_t; + + int thrd_create(thrd_t *t, thrd_start_t start_routine, void *arg); + int thrd_join(thrd_t); + void thrd_yield(void); + thrd_t thrd_current(void); + + int user_main(int, char**); + +#ifdef __cplusplus +} +#endif + +#endif /* __THREADS_H__ */ diff --git a/libinterface.cc b/libinterface.cc new file mode 100644 index 0000000..847861d --- /dev/null +++ b/libinterface.cc @@ -0,0 +1,186 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#define __STDC_FORMAT_MACROS +#include +#include + +#include "libinterface.h" +#include "common.h" +#include "model.h" +#include "threads-model.h" +#include "mcexecution.h" + +void store_8(void *addr, uint8_t val) +{ + DEBUG("addr = %p, val = %" PRIu8 "\n", addr, val); + model->get_execution()->store(addr, val, sizeof(val)); +} + +void store_16(void *addr, uint16_t val) +{ + DEBUG("addr = %p, val = %" PRIu16 "\n", addr, val); + model->get_execution()->store(addr, val, sizeof(val)); +} + +void store_32(void *addr, uint32_t val) +{ + DEBUG("addr = %p, val = %" PRIu32 "\n", addr, val); + model->get_execution()->store(addr, val, sizeof(val)); +} + +void store_64(void *addr, uint64_t val) +{ + DEBUG("addr = %p, val = %" PRIu64 "\n", addr, val); + model->get_execution()->store(addr, val, sizeof(val)); +} + +uint8_t load_8(const void *addr) +{ + DEBUG("addr = %p\n", addr); + return (uint8_t) model->get_execution()->load(addr, sizeof(uint8_t)); +} + +uint16_t load_16(const void *addr) +{ + DEBUG("addr = %p\n", addr); + return (uint16_t) model->get_execution()->load(addr, sizeof(uint16_t)); +} + +uint32_t load_32(const void *addr) +{ + DEBUG("addr = %p\n", addr); + return (uint32_t) model->get_execution()->load(addr, sizeof(uint32_t)); +} + +uint64_t load_64(const void *addr) +{ + DEBUG("addr = %p\n", addr); + return (uint64_t) model->get_execution()->load(addr, sizeof(uint64_t)); +} + +uint8_t rmw_8(enum atomicop op, void *addr, uint8_t oldval, uint8_t valarg) { + return (uint8_t) model->get_execution()->rmw(op, addr, sizeof(oldval), (uint64_t) *((uint8_t *)addr), (uint64_t) oldval, (uint64_t) valarg); +} + +uint16_t rmw_16(enum atomicop op, void *addr, uint16_t oldval, uint16_t valarg) { + return (uint16_t) model->get_execution()->rmw(op, addr, sizeof(oldval), (uint64_t) *((uint16_t *)addr), (uint64_t) oldval, (uint64_t) valarg); +} + +uint32_t rmw_32(enum atomicop op, void *addr, uint32_t oldval, uint32_t valarg) { + return (uint32_t) model->get_execution()->rmw(op, addr, sizeof(oldval), (uint64_t) *((uint32_t *)addr), (uint64_t) oldval, (uint64_t) valarg); +} + +uint64_t rmw_64(enum atomicop op, void *addr, uint64_t oldval, uint64_t valarg) { + return model->get_execution()->rmw(op, addr, sizeof(oldval), *((uint64_t *)addr), oldval, valarg); +} + +void MC2_nextOpThrd_create(MCID startfunc, MCID param) { +} + +void MC2_nextOpThrd_join(MCID jointhrd) { +} + +MCID MC2_nextOpLoad(MCID addr) { + return model->get_execution()->loadMCID(addr, 0); +} + +void MC2_nextOpStore(MCID addr, MCID value) { + return model->get_execution()->storeMCID(addr, 0, value); +} + +MCID MC2_nextOpLoadOffset(MCID addr, uintptr_t offset) { + return model->get_execution()->loadMCID(addr, offset); +} + +void MC2_nextOpStoreOffset(MCID addr, uintptr_t offset, MCID value) { + return model->get_execution()->storeMCID(addr, offset, value); +} + +MCID MC2_branchUsesID(MCID condition, int direction, int num_directions, bool anyvalue) { + return model->get_execution()->branchDir(condition, direction, num_directions, anyvalue); +} + +void MC2_merge(MCID branchid) { + model->get_execution()->merge(branchid); +} + +MCID MC2_phi(MCID input) { + return model->get_execution()->phi(input); +} + +MCID MC2_loop_phi(MCID input) { + return model->get_execution()->loop_phi(input); +} + +uint64_t MC2_equals(MCID op1, uint64_t val1, MCID op2, uint64_t val2, MCID *retval) { + return model->get_execution()->equals(op1, val1, op2, val2, retval); +} + + +MCID MC2_function(uint num_args, int numbytesretval, uint64_t val, ...) { + va_list vl; + MCID mcids[num_args]; + va_start(vl, val); + uint num_real_args=0;; + for(uint i=0;iget_execution()->function(0, numbytesretval, val, num_real_args, mcids); + return m; +} + +MCID MC2_function_id(unsigned int id, uint num_args, int numbytesretval, uint64_t val, ...) { + va_list vl; + MCID mcids[num_args]; + va_start(vl, val); + uint num_real_args=0;; + for(uint i=0;iget_execution()->function(id, numbytesretval, val, num_real_args, mcids); + return m; +} + +void MC2_enterLoop() { + model->get_execution()->enterLoop(); +} + +void MC2_exitLoop() { + model->get_execution()->exitLoop(); +} + +void MC2_loopIterate() { + model->get_execution()->loopIterate(); +} + +void MC2_yield() { + model->get_execution()->threadYield(); +} + +void MC2_fence() { +#ifdef TSO + model->get_execution()->fence(); +#endif +} + + +MCID MC2_nextRMW(MCID addr, MCID oldval, MCID valarg) { + return model->get_execution()->nextRMW(addr, 0, oldval, valarg); +} + +MCID MC2_nextRMWOffset(MCID addr, uintptr_t offset, MCID oldval, MCID valarg) { + return model->get_execution()->nextRMW(addr, offset, oldval, valarg); +} diff --git a/libthreads.cc b/libthreads.cc new file mode 100644 index 0000000..da4dca4 --- /dev/null +++ b/libthreads.cc @@ -0,0 +1,41 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include "common.h" +#include "threads-model.h" + +/* global "model" object */ +#include "model.h" + +/* + * User program API functions + */ +int thrd_create(thrd_t *t, thrd_start_t start_routine, void *arg) +{ + model->get_execution()->threadCreate(t, start_routine, arg); + return 0; +} + +int thrd_join(thrd_t t) +{ + Thread *th = t.priv; + model->get_execution()->threadJoin(th); + return 0; +} + +void thrd_yield(void) +{ + model->get_execution()->threadYield(); +} + +thrd_t thrd_current(void) +{ + return thread_current()->get_thrd_t(); +} diff --git a/loadrf.cc b/loadrf.cc new file mode 100644 index 0000000..1b9c551 --- /dev/null +++ b/loadrf.cc @@ -0,0 +1,115 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "loadrf.h" +#include "constgen.h" +#include "mcutil.h" +#include "constraint.h" +#include "storeloadset.h" +#include "eprecord.h" +#include "execpoint.h" + +LoadRF::LoadRF(EPRecord *_load, ConstGen *cg) : load(_load) { + RecordSet *mrfSet=cg->getMayReadFromSet(load); + uint numstores=mrfSet->getSize(); + numvars=NUMBITS(numstores-1); + vars=(Constraint **)model_malloc(numvars*sizeof(Constraint *)); + cg->getArrayNewVars(numvars, vars); +} + +LoadRF::~LoadRF() { + model_free(vars); +} + +void LoadRF::genConstraints(ConstGen *cg) { + uint storeindex=0; + RecordSet *mrfSet=cg->getMayReadFromSet(load); + StoreLoadSet * sls=cg->getStoreLoadSet(load); + uint numvalvars=sls->getNumValVars(); + uint numaddrvars=sls->getNumAddrVars(); + Constraint ** loadvalvars=(load->getType()==RMW)?sls->getRMWRValVars(cg, load):sls->getValVars(cg, load); + Constraint ** loadaddrvars=sls->getAddrVars(cg, load); + + RecordIterator *sri=mrfSet->iterator(); + while(sri->hasNext()) { + EPRecord *store=sri->next(); + Constraint ** storevalvars=sls->getValVars(cg, store); + + + Constraint *rfconst=(numvars==0)?&ctrue:generateConstraint(numvars, vars, storeindex); + //if we read from a store, it should happen before us +#ifdef TSO + Constraint *storebeforeload; + if (store->getEP()->get_tid()==load->getEP()->get_tid()) { + if (store->getEP()->compare(load->getEP())==CR_AFTER) { + storebeforeload=&ctrue; + } else + storebeforeload=&cfalse; + } else + storebeforeload=cg->getOrderConstraint(store, load); +#else + Constraint * storebeforeload=cg->getOrderConstraint(store, load); +#endif + //if we read from a store, we should have the same value + Constraint *storevalmatch=generateEquivConstraint(numvalvars, loadvalvars, storevalvars); + //if we read from a store, it must have been executed + Constraint *storeexecuted=cg->getExecutionConstraint(store); + + + + //if we read from a store, we should have the same address + Constraint ** storeaddrvars=sls->getAddrVars(cg, store); + Constraint * storeaddressmatch=generateEquivConstraint(numaddrvars, loadaddrvars, storeaddrvars); + Constraint *array[] = {storebeforeload, storevalmatch, storeexecuted, storeaddressmatch}; + + + ADDCONSTRAINT2(cg, new Constraint(IMPLIES, rfconst, new Constraint(AND, 4, array)), "storeaddressmatch"); + + + //Also need to make sure that we don't have conflicting stores + //ordered between the load and store + + RecordSet *conflictSet=cg->computeConflictSet(store, load, mrfSet); + RecordIterator *sit=conflictSet!=NULL?conflictSet->iterator():mrfSet->iterator(); + + while(sit->hasNext()) { + EPRecord *conflictstore=sit->next(); + Constraint ** confstoreaddrvars=sls->getAddrVars(cg, conflictstore); + Constraint * storebeforeconflict=cg->getOrderConstraint(store, conflictstore); + if (storebeforeconflict->isFalse()) + continue; + Constraint * conflictbeforeload=cg->getOrderConstraint(conflictstore, load); + if (conflictbeforeload->isFalse()) { + storebeforeconflict->freerec(); + continue; + } + + rfconst=generateConstraint(numvars, vars, storeindex); + Constraint *array[]={storebeforeconflict, + conflictbeforeload, + rfconst, + cg->getExecutionConstraint(conflictstore)}; + Constraint *confstore=new Constraint(IMPLIES, + new Constraint(AND, 4, array), + generateEquivConstraint(numaddrvars, loadaddrvars, confstoreaddrvars)->negate()); + + ADDCONSTRAINT2(cg, confstore, "confstore"); + } + delete sit; + if (conflictSet != NULL) + delete conflictSet; + + storeindex++; + } + delete sri; + + Constraint *mustrf=generateLTConstraint(cg, numvars, vars, storeindex); + Constraint *validrf=new Constraint(IMPLIES, cg->getExecutionConstraint(load), mustrf); + ADDCONSTRAINT2(cg, validrf, "validrf"); +} diff --git a/loadrf.h b/loadrf.h new file mode 100644 index 0000000..8ef7a19 --- /dev/null +++ b/loadrf.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef LOADRF_H +#define LOADRF_H +#include "classlist.h" + +class LoadRF { + public: + LoadRF(EPRecord *_load, ConstGen *cg); + ~LoadRF(); + void genConstraints(ConstGen *cg); + + MEMALLOC; + private: + EPRecord *load; + uint numvars; + Constraint ** vars; +}; +#endif diff --git a/main.cc b/main.cc new file mode 100644 index 0000000..d8d4193 --- /dev/null +++ b/main.cc @@ -0,0 +1,133 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file main.cc + * @brief Entry point for the model checker. + */ + +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "model.h" + +/* global "model" object */ +#include "params.h" +#include "snapshot-interface.h" + +static void param_defaults(struct model_params *params) +{ + params->branches = false; + params->noyields = false; + params->verbose = !!DBG_ENABLED(); +} + +static void print_usage(const char *program_name, struct model_params *params) +{ + /* Reset defaults before printing */ + param_defaults(params); + + model_print( + "Model-checker options:\n" + "-h, --help Display this help message and exit\n" + "-Y, --avoidyields Fairness support by not executing yields\n" + "-b, --branches Only explore all branches\n" + "-v[NUM], --verbose[=NUM] Print verbose execution information. NUM is optional:\n" + " -- Program arguments follow.\n\n"); + exit(EXIT_SUCCESS); +} + +static void parse_options(struct model_params *params, int argc, char **argv) +{ + const char *shortopts = "hbYv::"; + const struct option longopts[] = { + {"help", no_argument, NULL, 'h'}, + {"avoidyields", no_argument, NULL, 'Y'}, + {"branches", no_argument, NULL, 'b'}, + {"verbose", optional_argument, NULL, 'v'}, + {0, 0, 0, 0} /* Terminator */ + }; + int opt, longindex; + bool error = false; + while (!error && (opt = getopt_long(argc, argv, shortopts, longopts, &longindex)) != -1) { + switch (opt) { + case 'h': + print_usage(argv[0], params); + break; + case 'b': + params->branches = true; + break; + case 'Y': + params->noyields = true; + break; + case 'v': + params->verbose = optarg ? atoi(optarg) : 1; + break; + default: /* '?' */ + error = true; + break; + } + } + + /* Pass remaining arguments to user program */ + params->argc = argc - (optind - 1); + params->argv = argv + (optind - 1); + + /* Reset program name */ + params->argv[0] = argv[0]; + + /* Reset (global) optind for potential use by user program */ + optind = 1; + + if (error) + print_usage(argv[0], params); +} + +int main_argc; +char **main_argv; + +/** The model_main function contains the main model checking loop. */ +static void model_main() +{ + struct model_params params; + + param_defaults(¶ms); + + parse_options(¶ms, main_argc, main_argv); + +#ifdef TSO + model_print("TSO\n"); +#endif + snapshot_stack_init(); + + model = new MC(params); + + model->check(); + delete model; + DEBUG("Exiting\n"); +} + +/** + * Main function. Just initializes snapshotting library and the + * snapshotting library calls the model_main function. + */ +int main(int argc, char **argv) +{ + main_argc = argc; + main_argv = argv; + + /* Configure output redirection for the model-checker */ + redirect_output(); + + /* Let's jump in quickly and start running stuff */ + snapshot_system_init(200000, 1024, 1024, 90000, &model_main); +} diff --git a/malloc.c b/malloc.c new file mode 100644 index 0000000..7189353 --- /dev/null +++ b/malloc.c @@ -0,0 +1,6252 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain, as explained at + http://creativecommons.org/publicdomain/zero/1.0/ Send questions, + comments, complaints, performance data, etc to dl@cs.oswego.edu + +* Version 2.8.5 Sun May 22 10:26:02 2011 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + +* Quickstart + + This library is all in one file to simplify the most common usage: + ftp it, compile it (-O3), and link it into another program. All of + the compile-time options default to reasonable values for use on + most platforms. You might later want to step through various + compile-time and dynamic tuning options. + + For convenience, an include file for code using this malloc is at: + ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.5.h + You don't really need this .h file unless you call functions not + defined in your system include files. The .h file contains only the + excerpts from this file needed for using this malloc on ANSI C/C++ + systems, so long as you haven't changed compile-time options about + naming and tuning parameters. If you do, then you can create your + own malloc.h that does include all settings by cutting at the point + indicated below. Note that you may already by default be using a C + library containing a malloc that is based on some version of this + malloc (for example in linux). You might still want to use the one + in this file to customize settings or to avoid overheads associated + with library versions. + +* Vital statistics: + + Supported pointer/size_t representation: 4 or 8 bytes + size_t MUST be an unsigned type of the same width as + pointers. (If you are using an ancient system that declares + size_t as a signed type, or need it to be a different width + than pointers, you can use a previous release of this malloc + (e.g. 2.7.2) supporting these.) + + Alignment: 8 bytes (default) + This suffices for nearly all current machines and C compilers. + However, you can define MALLOC_ALIGNMENT to be wider than this + if necessary (up to 128bytes), at the expense of using more space. + + Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) + 8 or 16 bytes (if 8byte sizes) + Each malloced chunk has a hidden word of overhead holding size + and status information, and additional cross-check word + if FOOTERS is defined. + + Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) + 8-byte ptrs: 32 bytes (including overhead) + + Even a request for zero bytes (i.e., malloc(0)) returns a + pointer to something of the minimum allocatable size. + The maximum overhead wastage (i.e., number of extra bytes + allocated than were requested in malloc) is less than or equal + to the minimum size, except for requests >= mmap_threshold that + are serviced via mmap(), where the worst case wastage is about + 32 bytes plus the remainder from a system page (the minimal + mmap unit); typically 4096 or 8192 bytes. + + Security: static-safe; optionally more or less + The "security" of malloc refers to the ability of malicious + code to accentuate the effects of errors (for example, freeing + space that is not currently malloc'ed or overwriting past the + ends of chunks) in code that calls malloc. This malloc + guarantees not to modify any memory locations below the base of + heap, i.e., static variables, even in the presence of usage + errors. The routines additionally detect most improper frees + and reallocs. All this holds as long as the static bookkeeping + for malloc itself is not corrupted by some other means. This + is only one aspect of security -- these checks do not, and + cannot, detect all possible programming errors. + + If FOOTERS is defined nonzero, then each allocated chunk + carries an additional check word to verify that it was malloced + from its space. These check words are the same within each + execution of a program using malloc, but differ across + executions, so externally crafted fake chunks cannot be + freed. This improves security by rejecting frees/reallocs that + could corrupt heap memory, in addition to the checks preventing + writes to statics that are always on. This may further improve + security at the expense of time and space overhead. (Note that + FOOTERS may also be worth using with MSPACES.) + + By default detected errors cause the program to abort (calling + "abort()"). You can override this to instead proceed past + errors by defining PROCEED_ON_ERROR. In this case, a bad free + has no effect, and a malloc that encounters a bad address + caused by user overwrites will ignore the bad address by + dropping pointers and indices to all known memory. This may + be appropriate for programs that should continue if at all + possible in the face of programming errors, although they may + run out of memory because dropped memory is never reclaimed. + + If you don't like either of these options, you can define + CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything + else. And if if you are sure that your program using malloc has + no errors or vulnerabilities, you can define INSECURE to 1, + which might (or might not) provide a small performance improvement. + + It is also possible to limit the maximum total allocatable + space, using malloc_set_footprint_limit. This is not + designed as a security feature in itself (calls to set limits + are not screened or privileged), but may be useful as one + aspect of a secure implementation. + + Thread-safety: NOT thread-safe unless USE_LOCKS defined non-zero + When USE_LOCKS is defined, each public call to malloc, free, + etc is surrounded with a lock. By default, this uses a plain + pthread mutex, win32 critical section, or a spin-lock if if + available for the platform and not disabled by setting + USE_SPIN_LOCKS=0. However, if USE_RECURSIVE_LOCKS is defined, + recursive versions are used instead (which are not required for + base functionality but may be needed in layered extensions). + Using a global lock is not especially fast, and can be a major + bottleneck. It is designed only to provide minimal protection + in concurrent environments, and to provide a basis for + extensions. If you are using malloc in a concurrent program, + consider instead using nedmalloc + (http://www.nedprod.com/programs/portable/nedmalloc/) or + ptmalloc (See http://www.malloc.de), which are derived from + versions of this malloc. + + System requirements: Any combination of MORECORE and/or MMAP/MUNMAP + This malloc can use unix sbrk or any emulation (invoked using + the CALL_MORECORE macro) and/or mmap/munmap or any emulation + (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system + memory. On most unix systems, it tends to work best if both + MORECORE and MMAP are enabled. On Win32, it uses emulations + based on VirtualAlloc. It also uses common C library functions + like memset. + + Compliance: I believe it is compliant with the Single Unix Specification + (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably + others as well. + +* Overview of algorithms + + This is not the fastest, most space-conserving, most portable, or + most tunable malloc ever written. However it is among the fastest + while also being among the most space-conserving, portable and + tunable. Consistent balance across these factors results in a good + general-purpose allocator for malloc-intensive programs. + + In most ways, this malloc is a best-fit allocator. Generally, it + chooses the best-fitting existing chunk for a request, with ties + broken in approximately least-recently-used order. (This strategy + normally maintains low fragmentation.) However, for requests less + than 256bytes, it deviates from best-fit when there is not an + exactly fitting available chunk by preferring to use space adjacent + to that used for the previous small request, as well as by breaking + ties in approximately most-recently-used order. (These enhance + locality of series of small allocations.) And for very large requests + (>= 256Kb by default), it relies on system memory mapping + facilities, if supported. (This helps avoid carrying around and + possibly fragmenting memory used only for large chunks.) + + All operations (except malloc_stats and mallinfo) have execution + times that are bounded by a constant factor of the number of bits in + a size_t, not counting any clearing in calloc or copying in realloc, + or actions surrounding MORECORE and MMAP that have times + proportional to the number of non-contiguous regions returned by + system allocation routines, which is often just 1. In real-time + applications, you can optionally suppress segment traversals using + NO_SEGMENT_TRAVERSAL, which assures bounded execution even when + system allocators return non-contiguous spaces, at the typical + expense of carrying around more memory and increased fragmentation. + + The implementation is not very modular and seriously overuses + macros. Perhaps someday all C compilers will do as good a job + inlining modular code as can now be done by brute-force expansion, + but now, enough of them seem not to. + + Some compilers issue a lot of warnings about code that is + dead/unreachable only on some platforms, and also about intentional + uses of negation on unsigned types. All known cases of each can be + ignored. + + For a longer but out of date high-level description, see + http://gee.cs.oswego.edu/dl/html/malloc.html + +* MSPACES + If MSPACES is defined, then in addition to malloc, free, etc., + this file also defines mspace_malloc, mspace_free, etc. These + are versions of malloc routines that take an "mspace" argument + obtained using create_mspace, to control all internal bookkeeping. + If ONLY_MSPACES is defined, only these versions are compiled. + So if you would like to use this allocator for only some allocations, + and your system malloc for others, you can compile with + ONLY_MSPACES and then do something like... + static mspace mymspace = create_mspace(0,0); // for example + #define mymalloc(bytes) mspace_malloc(mymspace, bytes) + + (Note: If you only need one instance of an mspace, you can instead + use "USE_DL_PREFIX" to relabel the global malloc.) + + You can similarly create thread-local allocators by storing + mspaces as thread-locals. For example: + static __thread mspace tlms = 0; + void* tlmalloc(size_t bytes) { + if (tlms == 0) tlms = create_mspace(0, 0); + return mspace_malloc(tlms, bytes); + } + void tlfree(void* mem) { mspace_free(tlms, mem); } + + Unless FOOTERS is defined, each mspace is completely independent. + You cannot allocate from one and free to another (although + conformance is only weakly checked, so usage errors are not always + caught). If FOOTERS is defined, then each chunk carries around a tag + indicating its originating mspace, and frees are directed to their + originating spaces. Normally, this requires use of locks. + + ------------------------- Compile-time options --------------------------- + +Be careful in setting #define values for numerical constants of type +size_t. On some systems, literal values are not automatically extended +to size_t precision unless they are explicitly casted. You can also +use the symbolic values MAX_SIZE_T, SIZE_T_ONE, etc below. + +WIN32 default: defined if _WIN32 defined + Defining WIN32 sets up defaults for MS environment and compilers. + Otherwise defaults are for unix. Beware that there seem to be some + cases where this malloc might not be a pure drop-in replacement for + Win32 malloc: Random-looking failures from Win32 GDI API's (eg; + SetDIBits()) may be due to bugs in some video driver implementations + when pixel buffers are malloc()ed, and the region spans more than + one VirtualAlloc()ed region. Because dlmalloc uses a small (64Kb) + default granularity, pixel buffers may straddle virtual allocation + regions more often than when using the Microsoft allocator. You can + avoid this by using VirtualAlloc() and VirtualFree() for all pixel + buffers rather than using malloc(). If this is not possible, + recompile this malloc with a larger DEFAULT_GRANULARITY. Note: + in cases where MSC and gcc (cygwin) are known to differ on WIN32, + conditions use _MSC_VER to distinguish them. + +DLMALLOC_EXPORT default: extern + Defines how public APIs are declared. If you want to export via a + Windows DLL, you might define this as + #define DLMALLOC_EXPORT extern __declspace(dllexport) + If you want a POSIX ELF shared object, you might use + #define DLMALLOC_EXPORT extern __attribute__((visibility("default"))) + +MALLOC_ALIGNMENT default: (size_t)8 + Controls the minimum alignment for malloc'ed chunks. It must be a + power of two and at least 8, even on machines for which smaller + alignments would suffice. It may be defined as larger than this + though. Note however that code and data structures are optimized for + the case of 8-byte alignment. + +MSPACES default: 0 (false) + If true, compile in support for independent allocation spaces. + This is only supported if HAVE_MMAP is true. + +ONLY_MSPACES default: 0 (false) + If true, only compile in mspace versions, not regular versions. + +USE_LOCKS default: 0 (false) + Causes each call to each public routine to be surrounded with + pthread or WIN32 mutex lock/unlock. (If set true, this can be + overridden on a per-mspace basis for mspace versions.) If set to a + non-zero value other than 1, locks are used, but their + implementation is left out, so lock functions must be supplied manually, + as described below. + +USE_SPIN_LOCKS default: 1 iff USE_LOCKS and spin locks available + If true, uses custom spin locks for locking. This is currently + supported only gcc >= 4.1, older gccs on x86 platforms, and recent + MS compilers. Otherwise, posix locks or win32 critical sections are + used. + +USE_RECURSIVE_LOCKS default: not defined + If defined nonzero, uses recursive (aka reentrant) locks, otherwise + uses plain mutexes. This is not required for malloc proper, but may + be needed for layered allocators such as nedmalloc. + +FOOTERS default: 0 + If true, provide extra checking and dispatching by placing + information in the footers of allocated chunks. This adds + space and time overhead. + +INSECURE default: 0 + If true, omit checks for usage errors and heap space overwrites. + +USE_DL_PREFIX default: NOT defined + Causes compiler to prefix all public routines with the string 'dl'. + This can be useful when you only want to use this malloc in one part + of a program, using your regular system malloc elsewhere. + +MALLOC_INSPECT_ALL default: NOT defined + If defined, compiles malloc_inspect_all and mspace_inspect_all, that + perform traversal of all heap space. Unless access to these + functions is otherwise restricted, you probably do not want to + include them in secure implementations. + +ABORT default: defined as abort() + Defines how to abort on failed checks. On most systems, a failed + check cannot die with an "assert" or even print an informative + message, because the underlying print routines in turn call malloc, + which will fail again. Generally, the best policy is to simply call + abort(). It's not very useful to do more than this because many + errors due to overwriting will show up as address faults (null, odd + addresses etc) rather than malloc-triggered checks, so will also + abort. Also, most compilers know that abort() does not return, so + can better optimize code conditionally calling it. + +PROCEED_ON_ERROR default: defined as 0 (false) + Controls whether detected bad addresses cause them to bypassed + rather than aborting. If set, detected bad arguments to free and + realloc are ignored. And all bookkeeping information is zeroed out + upon a detected overwrite of freed heap space, thus losing the + ability to ever return it from malloc again, but enabling the + application to proceed. If PROCEED_ON_ERROR is defined, the + static variable malloc_corruption_error_count is compiled in + and can be examined to see if errors have occurred. This option + generates slower code than the default abort policy. + +DEBUG default: NOT defined + The DEBUG setting is mainly intended for people trying to modify + this code or diagnose problems when porting to new platforms. + However, it may also be able to better isolate user errors than just + using runtime checks. The assertions in the check routines spell + out in more detail the assumptions and invariants underlying the + algorithms. The checking is fairly extensive, and will slow down + execution noticeably. Calling malloc_stats or mallinfo with DEBUG + set will attempt to check every non-mmapped allocated and free chunk + in the course of computing the summaries. + +ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) + Debugging assertion failures can be nearly impossible if your + version of the assert macro causes malloc to be called, which will + lead to a cascade of further failures, blowing the runtime stack. + ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), + which will usually make debugging easier. + +MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 + The action to take before "return 0" when malloc fails to be able to + return memory because there is none available. + +HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES + True if this system supports sbrk or an emulation of it. + +MORECORE default: sbrk + The name of the sbrk-style system routine to call to obtain more + memory. See below for guidance on writing custom MORECORE + functions. The type of the argument to sbrk/MORECORE varies across + systems. It cannot be size_t, because it supports negative + arguments, so it is normally the signed type of the same width as + size_t (sometimes declared as "intptr_t"). It doesn't much matter + though. Internally, we only call it with arguments less than half + the max value of a size_t, which should work across all reasonable + possibilities, although sometimes generating compiler warnings. + +MORECORE_CONTIGUOUS default: 1 (true) if HAVE_MORECORE + If true, take advantage of fact that consecutive calls to MORECORE + with positive arguments always return contiguous increasing + addresses. This is true of unix sbrk. It does not hurt too much to + set it true anyway, since malloc copes with non-contiguities. + Setting it false when definitely non-contiguous saves time + and possibly wasted space it would take to discover this though. + +MORECORE_CANNOT_TRIM default: NOT defined + True if MORECORE cannot release space back to the system when given + negative arguments. This is generally necessary only if you are + using a hand-crafted MORECORE function that cannot handle negative + arguments. + +NO_SEGMENT_TRAVERSAL default: 0 + If non-zero, suppresses traversals of memory segments + returned by either MORECORE or CALL_MMAP. This disables + merging of segments that are contiguous, and selectively + releasing them to the OS if unused, but bounds execution times. + +HAVE_MMAP default: 1 (true) + True if this system supports mmap or an emulation of it. If so, and + HAVE_MORECORE is not true, MMAP is used for all system + allocation. If set and HAVE_MORECORE is true as well, MMAP is + primarily used to directly allocate very large blocks. It is also + used as a backup strategy in cases where MORECORE fails to provide + space from system. Note: A single call to MUNMAP is assumed to be + able to unmap memory that may have be allocated using multiple calls + to MMAP, so long as they are adjacent. + +HAVE_MREMAP default: 1 on linux, else 0 + If true realloc() uses mremap() to re-allocate large blocks and + extend or shrink allocation spaces. + +MMAP_CLEARS default: 1 except on WINCE. + True if mmap clears memory so calloc doesn't need to. This is true + for standard unix mmap using /dev/zero and on WIN32 except for WINCE. + +USE_BUILTIN_FFS default: 0 (i.e., not used) + Causes malloc to use the builtin ffs() function to compute indices. + Some compilers may recognize and intrinsify ffs to be faster than the + supplied C version. Also, the case of x86 using gcc is special-cased + to an asm instruction, so is already as fast as it can be, and so + this setting has no effect. Similarly for Win32 under recent MS compilers. + (On most x86s, the asm version is only slightly faster than the C version.) + +malloc_getpagesize default: derive from system includes, or 4096. + The system page size. To the extent possible, this malloc manages + memory from the system in page-size units. This may be (and + usually is) a function rather than a constant. This is ignored + if WIN32, where page size is determined using getSystemInfo during + initialization. + +USE_DEV_RANDOM default: 0 (i.e., not used) + Causes malloc to use /dev/random to initialize secure magic seed for + stamping footers. Otherwise, the current time is used. + +NO_MALLINFO default: 0 + If defined, don't compile "mallinfo". This can be a simple way + of dealing with mismatches between system declarations and + those in this file. + +MALLINFO_FIELD_TYPE default: size_t + The type of the fields in the mallinfo struct. This was originally + defined as "int" in SVID etc, but is more usefully defined as + size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set + +NO_MALLOC_STATS default: 0 + If defined, don't compile "malloc_stats". This avoids calls to + fprintf and bringing in stdio dependencies you might not want. + +REALLOC_ZERO_BYTES_FREES default: not defined + This should be set if a call to realloc with zero bytes should + be the same as a call to free. Some people think it should. Otherwise, + since this malloc returns a unique pointer for malloc(0), so does + realloc(p, 0). + +LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H +LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H +LACKS_STDLIB_H LACKS_SCHED_H LACKS_TIME_H default: NOT defined unless on WIN32 + Define these if your system does not have these header files. + You might need to manually insert some of the declarations they provide. + +DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, + system_info.dwAllocationGranularity in WIN32, + otherwise 64K. + Also settable using mallopt(M_GRANULARITY, x) + The unit for allocating and deallocating memory from the system. On + most systems with contiguous MORECORE, there is no reason to + make this more than a page. However, systems with MMAP tend to + either require or encourage larger granularities. You can increase + this value to prevent system allocation functions to be called so + often, especially if they are slow. The value must be at least one + page and must be a power of two. Setting to 0 causes initialization + to either page size or win32 region size. (Note: In previous + versions of malloc, the equivalent of this option was called + "TOP_PAD") + +DEFAULT_TRIM_THRESHOLD default: 2MB + Also settable using mallopt(M_TRIM_THRESHOLD, x) + The maximum amount of unused top-most memory to keep before + releasing via malloc_trim in free(). Automatic trimming is mainly + useful in long-lived programs using contiguous MORECORE. Because + trimming via sbrk can be slow on some systems, and can sometimes be + wasteful (in cases where programs immediately afterward allocate + more large chunks) the value should be high enough so that your + overall system performance would improve by releasing this much + memory. As a rough guide, you might set to a value close to the + average size of a process (program) running on your system. + Releasing this much memory would allow such a process to run in + memory. Generally, it is worth tuning trim thresholds when a + program undergoes phases where several large chunks are allocated + and released in ways that can reuse each other's storage, perhaps + mixed with phases where there are no such chunks at all. The trim + value must be greater than page size to have any useful effect. To + disable trimming completely, you can set to MAX_SIZE_T. Note that the trick + some people use of mallocing a huge space and then freeing it at + program startup, in an attempt to reserve system memory, doesn't + have the intended effect under automatic trimming, since that memory + will immediately be returned to the system. + +DEFAULT_MMAP_THRESHOLD default: 256K + Also settable using mallopt(M_MMAP_THRESHOLD, x) + The request size threshold for using MMAP to directly service a + request. Requests of at least this size that cannot be allocated + using already-existing space will be serviced via mmap. (If enough + normal freed space already exists it is used instead.) Using mmap + segregates relatively large chunks of memory so that they can be + individually obtained and released from the host system. A request + serviced through mmap is never reused by any other request (at least + not directly; the system may just so happen to remap successive + requests to the same locations). Segregating space in this way has + the benefits that: Mmapped space can always be individually released + back to the system, which helps keep the system level memory demands + of a long-lived program low. Also, mapped memory doesn't become + `locked' between other chunks, as can happen with normally allocated + chunks, which means that even trimming via malloc_trim would not + release them. However, it has the disadvantage that the space + cannot be reclaimed, consolidated, and then used to service later + requests, as happens with normal chunks. The advantages of mmap + nearly always outweigh disadvantages for "large" chunks, but the + value of "large" may vary across systems. The default is an + empirically derived value that works well in most systems. You can + disable mmap by setting to MAX_SIZE_T. + +MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP + The number of consolidated frees between checks to release + unused segments when freeing. When using non-contiguous segments, + especially with multiple mspaces, checking only for topmost space + doesn't always suffice to trigger trimming. To compensate for this, + free() will, with a period of MAX_RELEASE_CHECK_RATE (or the + current number of segments, if greater) try to release unused + segments to the OS when freeing chunks that result in + consolidation. The best value for this parameter is a compromise + between slowing down frees with relatively costly checks that + rarely trigger versus holding on to unused memory. To effectively + disable, set to MAX_SIZE_T. This may lead to a very slight speed + improvement at the expense of carrying around more memory. +*/ + +/* Version identifier to allow people to support multiple versions */ +#ifndef DLMALLOC_VERSION +#define DLMALLOC_VERSION 20805 +#endif /* DLMALLOC_VERSION */ + +#ifndef DLMALLOC_EXPORT +#define DLMALLOC_EXPORT extern +#endif + +#ifndef WIN32 +#ifdef _WIN32 +#define WIN32 1 +#endif /* _WIN32 */ +#ifdef _WIN32_WCE +#define LACKS_FCNTL_H +#define WIN32 1 +#endif /* _WIN32_WCE */ +#endif /* WIN32 */ +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#define HAVE_MMAP 1 +#define HAVE_MORECORE 0 +#define LACKS_UNISTD_H +#define LACKS_SYS_PARAM_H +#define LACKS_SYS_MMAN_H +#define LACKS_STRING_H +#define LACKS_STRINGS_H +#define LACKS_SYS_TYPES_H +#define LACKS_ERRNO_H +#define LACKS_SCHED_H +#ifndef MALLOC_FAILURE_ACTION +#define MALLOC_FAILURE_ACTION +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef MMAP_CLEARS +#ifdef _WIN32_WCE /* WINCE reportedly does not clear */ +#define MMAP_CLEARS 0 +#else +#define MMAP_CLEARS 1 +#endif /* _WIN32_WCE */ +#endif /*MMAP_CLEARS */ +#endif /* WIN32 */ + +#if defined(DARWIN) || defined(_DARWIN) +/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ +#ifndef HAVE_MORECORE +#define HAVE_MORECORE 0 +#define HAVE_MMAP 1 +/* OSX allocators provide 16 byte alignment */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)16U) +#endif +#endif /* HAVE_MORECORE */ +#endif /* DARWIN */ + +#ifndef LACKS_SYS_TYPES_H +#include /* For size_t */ +#endif /* LACKS_SYS_TYPES_H */ + +/* The maximum possible size_t value has all bits set */ +#define MAX_SIZE_T (~(size_t)0) + +#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ +#define USE_LOCKS ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ + (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) +#endif /* USE_LOCKS */ + +#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */ +#if ((defined(__GNUC__) && \ + ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \ + defined(__i386__) || defined(__x86_64__))) || \ + (defined(_MSC_VER) && _MSC_VER>=1310)) +#ifndef USE_SPIN_LOCKS +#define USE_SPIN_LOCKS 1 +#endif /* USE_SPIN_LOCKS */ +#elif USE_SPIN_LOCKS +#error "USE_SPIN_LOCKS defined without implementation" +#endif /* ... locks available... */ +#elif !defined(USE_SPIN_LOCKS) +#define USE_SPIN_LOCKS 0 +#endif /* USE_LOCKS */ + +#ifndef ONLY_MSPACES +#define ONLY_MSPACES 0 +#endif /* ONLY_MSPACES */ +#ifndef MSPACES +#if ONLY_MSPACES +#define MSPACES 1 +#else /* ONLY_MSPACES */ +#define MSPACES 0 +#endif /* ONLY_MSPACES */ +#endif /* MSPACES */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)8U) +#endif /* MALLOC_ALIGNMENT */ +#ifndef FOOTERS +#define FOOTERS 0 +#endif /* FOOTERS */ +#ifndef ABORT +#define ABORT abort() +#endif /* ABORT */ +#ifndef ABORT_ON_ASSERT_FAILURE +#define ABORT_ON_ASSERT_FAILURE 1 +#endif /* ABORT_ON_ASSERT_FAILURE */ +#ifndef PROCEED_ON_ERROR +#define PROCEED_ON_ERROR 0 +#endif /* PROCEED_ON_ERROR */ + +#ifndef INSECURE +#define INSECURE 0 +#endif /* INSECURE */ +#ifndef MALLOC_INSPECT_ALL +#define MALLOC_INSPECT_ALL 0 +#endif /* MALLOC_INSPECT_ALL */ +#ifndef HAVE_MMAP +#define HAVE_MMAP 1 +#endif /* HAVE_MMAP */ +#ifndef MMAP_CLEARS +#define MMAP_CLEARS 1 +#endif /* MMAP_CLEARS */ +#ifndef HAVE_MREMAP +#ifdef linux +#define HAVE_MREMAP 1 +#define _GNU_SOURCE /* Turns on mremap() definition */ +#else /* linux */ +#define HAVE_MREMAP 0 +#endif /* linux */ +#endif /* HAVE_MREMAP */ +#ifndef MALLOC_FAILURE_ACTION +#define MALLOC_FAILURE_ACTION errno = ENOMEM; +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef HAVE_MORECORE +#if ONLY_MSPACES +#define HAVE_MORECORE 0 +#else /* ONLY_MSPACES */ +#define HAVE_MORECORE 1 +#endif /* ONLY_MSPACES */ +#endif /* HAVE_MORECORE */ +#if !HAVE_MORECORE +#define MORECORE_CONTIGUOUS 0 +#else /* !HAVE_MORECORE */ +#define MORECORE_DEFAULT sbrk +#ifndef MORECORE_CONTIGUOUS +#define MORECORE_CONTIGUOUS 1 +#endif /* MORECORE_CONTIGUOUS */ +#endif /* HAVE_MORECORE */ +#ifndef DEFAULT_GRANULARITY +#if (MORECORE_CONTIGUOUS || defined(WIN32)) +#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ +#else /* MORECORE_CONTIGUOUS */ +#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) +#endif /* MORECORE_CONTIGUOUS */ +#endif /* DEFAULT_GRANULARITY */ +#ifndef DEFAULT_TRIM_THRESHOLD +#ifndef MORECORE_CANNOT_TRIM +#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) +#else /* MORECORE_CANNOT_TRIM */ +#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T +#endif /* MORECORE_CANNOT_TRIM */ +#endif /* DEFAULT_TRIM_THRESHOLD */ +#ifndef DEFAULT_MMAP_THRESHOLD +#if HAVE_MMAP +#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) +#else /* HAVE_MMAP */ +#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* DEFAULT_MMAP_THRESHOLD */ +#ifndef MAX_RELEASE_CHECK_RATE +#if HAVE_MMAP +#define MAX_RELEASE_CHECK_RATE 4095 +#else +#define MAX_RELEASE_CHECK_RATE MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* MAX_RELEASE_CHECK_RATE */ +#ifndef USE_BUILTIN_FFS +#define USE_BUILTIN_FFS 0 +#endif /* USE_BUILTIN_FFS */ +#ifndef USE_DEV_RANDOM +#define USE_DEV_RANDOM 0 +#endif /* USE_DEV_RANDOM */ +#ifndef NO_MALLINFO +#define NO_MALLINFO 0 +#endif /* NO_MALLINFO */ +#ifndef MALLINFO_FIELD_TYPE +#define MALLINFO_FIELD_TYPE size_t +#endif /* MALLINFO_FIELD_TYPE */ +#ifndef NO_MALLOC_STATS +#define NO_MALLOC_STATS 0 +#endif /* NO_MALLOC_STATS */ +#ifndef NO_SEGMENT_TRAVERSAL +#define NO_SEGMENT_TRAVERSAL 0 +#endif /* NO_SEGMENT_TRAVERSAL */ + +/* + mallopt tuning options. SVID/XPG defines four standard parameter + numbers for mallopt, normally defined in malloc.h. None of these + are used in this malloc, so setting them has no effect. But this + malloc does support the following options. +*/ + +#define M_TRIM_THRESHOLD (-1) +#define M_GRANULARITY (-2) +#define M_MMAP_THRESHOLD (-3) + +/* ------------------------ Mallinfo declarations ------------------------ */ + +#if !NO_MALLINFO +/* + This version of malloc supports the standard SVID/XPG mallinfo + routine that returns a struct containing usage properties and + statistics. It should work on any system that has a + /usr/include/malloc.h defining struct mallinfo. The main + declaration needed is the mallinfo struct that is returned (by-copy) + by mallinfo(). The malloinfo struct contains a bunch of fields that + are not even meaningful in this version of malloc. These fields are + are instead filled by mallinfo() with other numbers that might be of + interest. + + HAVE_USR_INCLUDE_MALLOC_H should be set if you have a + /usr/include/malloc.h file that includes a declaration of struct + mallinfo. If so, it is included; else a compliant version is + declared below. These must be precisely the same for mallinfo() to + work. The original SVID version of this struct, defined on most + systems with mallinfo, declares all fields as ints. But some others + define as unsigned long. If your system defines the fields using a + type of different width than listed here, you MUST #include your + system version and #define HAVE_USR_INCLUDE_MALLOC_H. +*/ + +/* #define HAVE_USR_INCLUDE_MALLOC_H */ + +#ifdef HAVE_USR_INCLUDE_MALLOC_H +#include "/usr/include/malloc.h" +#else /* HAVE_USR_INCLUDE_MALLOC_H */ +#ifndef STRUCT_MALLINFO_DECLARED +/* HP-UX (and others?) redefines mallinfo unless _STRUCT_MALLINFO is defined */ +#define _STRUCT_MALLINFO +#define STRUCT_MALLINFO_DECLARED 1 +struct mallinfo { + MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ + MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ + MALLINFO_FIELD_TYPE smblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ + MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ + MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ + MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ + MALLINFO_FIELD_TYPE fordblks; /* total free space */ + MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ +}; +#endif /* STRUCT_MALLINFO_DECLARED */ +#endif /* HAVE_USR_INCLUDE_MALLOC_H */ +#endif /* NO_MALLINFO */ + +/* + Try to persuade compilers to inline. The most critical functions for + inlining are defined as macros, so these aren't used for them. +*/ + +#ifndef FORCEINLINE + #if defined(__GNUC__) +#define FORCEINLINE __inline __attribute__ ((always_inline)) + #elif defined(_MSC_VER) + #define FORCEINLINE __forceinline + #endif +#endif +#ifndef NOINLINE + #if defined(__GNUC__) + #define NOINLINE __attribute__ ((noinline)) + #elif defined(_MSC_VER) + #define NOINLINE __declspec(noinline) + #else + #define NOINLINE + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#ifndef FORCEINLINE + #define FORCEINLINE inline +#endif +#endif /* __cplusplus */ +#ifndef FORCEINLINE + #define FORCEINLINE +#endif + +#if !ONLY_MSPACES + +/* ------------------- Declarations of public routines ------------------- */ + +#ifndef USE_DL_PREFIX +#define dlcalloc calloc +#define dlfree free +#define dlmalloc malloc +#define dlmemalign memalign +#define dlposix_memalign posix_memalign +#define dlrealloc realloc +#define dlrealloc_in_place realloc_in_place +#define dlvalloc valloc +#define dlpvalloc pvalloc +#define dlmallinfo mallinfo +#define dlmallopt mallopt +#define dlmalloc_trim malloc_trim +#define dlmalloc_stats malloc_stats +#define dlmalloc_usable_size malloc_usable_size +#define dlmalloc_footprint malloc_footprint +#define dlmalloc_max_footprint malloc_max_footprint +#define dlmalloc_footprint_limit malloc_footprint_limit +#define dlmalloc_set_footprint_limit malloc_set_footprint_limit +#define dlmalloc_inspect_all malloc_inspect_all +#define dlindependent_calloc independent_calloc +#define dlindependent_comalloc independent_comalloc +#define dlbulk_free bulk_free +#endif /* USE_DL_PREFIX */ + +/* + malloc(size_t n) + Returns a pointer to a newly allocated chunk of at least n bytes, or + null if no space is available, in which case errno is set to ENOMEM + on ANSI C systems. + + If n is zero, malloc returns a minimum-sized chunk. (The minimum + size is 16 bytes on most 32bit systems, and 32 bytes on 64bit + systems.) Note that size_t is an unsigned type, so calls with + arguments that would be negative if signed are interpreted as + requests for huge amounts of space, which will often fail. The + maximum supported value of n differs across systems, but is in all + cases less than the maximum representable value of a size_t. +*/ +DLMALLOC_EXPORT void* dlmalloc(size_t); + +/* + free(void* p) + Releases the chunk of memory pointed to by p, that had been previously + allocated using malloc or a related routine such as realloc. + It has no effect if p is null. If p was not malloced or already + freed, free(p) will by default cause the current program to abort. +*/ +DLMALLOC_EXPORT void dlfree(void*); + +/* + calloc(size_t n_elements, size_t element_size); + Returns a pointer to n_elements * element_size bytes, with all locations + set to zero. +*/ +DLMALLOC_EXPORT void* dlcalloc(size_t, size_t); + +/* + realloc(void* p, size_t n) + Returns a pointer to a chunk of size n that contains the same data + as does chunk p up to the minimum of (n, p's size) bytes, or null + if no space is available. + + The returned pointer may or may not be the same as p. The algorithm + prefers extending p in most cases when possible, otherwise it + employs the equivalent of a malloc-copy-free sequence. + + If p is null, realloc is equivalent to malloc. + + If space is not available, realloc returns null, errno is set (if on + ANSI) and p is NOT freed. + + if n is for fewer bytes than already held by p, the newly unused + space is lopped off and freed if possible. realloc with a size + argument of zero (re)allocates a minimum-sized chunk. + + The old unix realloc convention of allowing the last-free'd chunk + to be used as an argument to realloc is not supported. +*/ +DLMALLOC_EXPORT void* dlrealloc(void*, size_t); + +/* + realloc_in_place(void* p, size_t n) + Resizes the space allocated for p to size n, only if this can be + done without moving p (i.e., only if there is adjacent space + available if n is greater than p's current allocated size, or n is + less than or equal to p's size). This may be used instead of plain + realloc if an alternative allocation strategy is needed upon failure + to expand space; for example, reallocation of a buffer that must be + memory-aligned or cleared. You can use realloc_in_place to trigger + these alternatives only when needed. + + Returns p if successful; otherwise null. +*/ +DLMALLOC_EXPORT void* dlrealloc_in_place(void*, size_t); + +/* + memalign(size_t alignment, size_t n); + Returns a pointer to a newly allocated chunk of n bytes, aligned + in accord with the alignment argument. + + The alignment argument should be a power of two. If the argument is + not a power of two, the nearest greater power is used. + 8-byte alignment is guaranteed by normal malloc calls, so don't + bother calling memalign with an argument of 8 or less. + + Overreliance on memalign is a sure way to fragment space. +*/ +DLMALLOC_EXPORT void* dlmemalign(size_t, size_t); + +/* + int posix_memalign(void** pp, size_t alignment, size_t n); + Allocates a chunk of n bytes, aligned in accord with the alignment + argument. Differs from memalign only in that it (1) assigns the + allocated memory to *pp rather than returning it, (2) fails and + returns EINVAL if the alignment is not a power of two (3) fails and + returns ENOMEM if memory cannot be allocated. +*/ +DLMALLOC_EXPORT int dlposix_memalign(void**, size_t, size_t); + +/* + valloc(size_t n); + Equivalent to memalign(pagesize, n), where pagesize is the page + size of the system. If the pagesize is unknown, 4096 is used. +*/ +DLMALLOC_EXPORT void* dlvalloc(size_t); + +/* + mallopt(int parameter_number, int parameter_value) + Sets tunable parameters The format is to provide a + (parameter-number, parameter-value) pair. mallopt then sets the + corresponding parameter to the argument value if it can (i.e., so + long as the value is meaningful), and returns 1 if successful else + 0. To workaround the fact that mallopt is specified to use int, + not size_t parameters, the value -1 is specially treated as the + maximum unsigned size_t value. + + SVID/XPG/ANSI defines four standard param numbers for mallopt, + normally defined in malloc.h. None of these are use in this malloc, + so setting them has no effect. But this malloc also supports other + options in mallopt. See below for details. Briefly, supported + parameters are as follows (listed defaults are for "typical" + configurations). + + Symbol param # default allowed param values + M_TRIM_THRESHOLD -1 2*1024*1024 any (-1 disables) + M_GRANULARITY -2 page size any power of 2 >= page size + M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) +*/ +DLMALLOC_EXPORT int dlmallopt(int, int); + +/* + malloc_footprint(); + Returns the number of bytes obtained from the system. The total + number of bytes allocated by malloc, realloc etc., is less than this + value. Unlike mallinfo, this function returns only a precomputed + result, so can be called frequently to monitor memory consumption. + Even if locks are otherwise defined, this function does not use them, + so results might not be up to date. +*/ +DLMALLOC_EXPORT size_t dlmalloc_footprint(void); + +/* + malloc_max_footprint(); + Returns the maximum number of bytes obtained from the system. This + value will be greater than current footprint if deallocated space + has been reclaimed by the system. The peak number of bytes allocated + by malloc, realloc etc., is less than this value. Unlike mallinfo, + this function returns only a precomputed result, so can be called + frequently to monitor memory consumption. Even if locks are + otherwise defined, this function does not use them, so results might + not be up to date. +*/ +DLMALLOC_EXPORT size_t dlmalloc_max_footprint(void); + +/* + malloc_footprint_limit(); + Returns the number of bytes that the heap is allowed to obtain from + the system, returning the last value returned by + malloc_set_footprint_limit, or the maximum size_t value if + never set. The returned value reflects a permission. There is no + guarantee that this number of bytes can actually be obtained from + the system. +*/ +DLMALLOC_EXPORT size_t dlmalloc_footprint_limit(); + +/* + malloc_set_footprint_limit(); + Sets the maximum number of bytes to obtain from the system, causing + failure returns from malloc and related functions upon attempts to + exceed this value. The argument value may be subject to page + rounding to an enforceable limit; this actual value is returned. + Using an argument of the maximum possible size_t effectively + disables checks. If the argument is less than or equal to the + current malloc_footprint, then all future allocations that require + additional system memory will fail. However, invocation cannot + retroactively deallocate existing used memory. +*/ +DLMALLOC_EXPORT size_t dlmalloc_set_footprint_limit(size_t bytes); + +#if MALLOC_INSPECT_ALL +/* + malloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg); + Traverses the heap and calls the given handler for each managed + region, skipping all bytes that are (or may be) used for bookkeeping + purposes. Traversal does not include include chunks that have been + directly memory mapped. Each reported region begins at the start + address, and continues up to but not including the end address. The + first used_bytes of the region contain allocated data. If + used_bytes is zero, the region is unallocated. The handler is + invoked with the given callback argument. If locks are defined, they + are held during the entire traversal. It is a bad idea to invoke + other malloc functions from within the handler. + + For example, to count the number of in-use chunks with size greater + than 1000, you could write: + static int count = 0; + void count_chunks(void* start, void* end, size_t used, void* arg) { + if (used >= 1000) ++count; + } + then: + malloc_inspect_all(count_chunks, NULL); + + malloc_inspect_all is compiled only if MALLOC_INSPECT_ALL is defined. +*/ +DLMALLOC_EXPORT void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), + void* arg); + +#endif /* MALLOC_INSPECT_ALL */ + +#if !NO_MALLINFO +/* + mallinfo() + Returns (by copy) a struct containing various summary statistics: + + arena: current total non-mmapped bytes allocated from system + ordblks: the number of free chunks + smblks: always zero. + hblks: current number of mmapped regions + hblkhd: total bytes held in mmapped regions + usmblks: the maximum total allocated space. This will be greater + than current total if trimming has occurred. + fsmblks: always zero + uordblks: current total allocated space (normal or mmapped) + fordblks: total free space + keepcost: the maximum number of bytes that could ideally be released + back to system via malloc_trim. ("ideally" means that + it ignores page restrictions etc.) + + Because these fields are ints, but internal bookkeeping may + be kept as longs, the reported values may wrap around zero and + thus be inaccurate. +*/ +DLMALLOC_EXPORT struct mallinfo dlmallinfo(void); +#endif /* NO_MALLINFO */ + +/* + independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); + + independent_calloc is similar to calloc, but instead of returning a + single cleared space, it returns an array of pointers to n_elements + independent elements that can hold contents of size elem_size, each + of which starts out cleared, and can be independently freed, + realloc'ed etc. The elements are guaranteed to be adjacently + allocated (this is not guaranteed to occur with multiple callocs or + mallocs), which may also improve cache locality in some + applications. + + The "chunks" argument is optional (i.e., may be null, which is + probably the most typical usage). If it is null, the returned array + is itself dynamically allocated and should also be freed when it is + no longer needed. Otherwise, the chunks array must be of at least + n_elements in length. It is filled in with the pointers to the + chunks. + + In either case, independent_calloc returns this pointer array, or + null if the allocation failed. If n_elements is zero and "chunks" + is null, it returns a chunk representing an array with zero elements + (which should be freed if not wanted). + + Each element must be freed when it is no longer needed. This can be + done all at once using bulk_free. + + independent_calloc simplifies and speeds up implementations of many + kinds of pools. It may also be useful when constructing large data + structures that initially have a fixed number of fixed-sized nodes, + but the number is not known at compile time, and some of the nodes + may later need to be freed. For example: + + struct Node { int item; struct Node* next; }; + + struct Node* build_list() { + struct Node** pool; + int n = read_number_of_nodes_needed(); + if (n <= 0) return 0; + pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); + if (pool == 0) die(); + // organize into a linked list... + struct Node* first = pool[0]; + for (i = 0; i < n-1; ++i) + pool[i]->next = pool[i+1]; + free(pool); // Can now free the array (or not, if it is needed later) + return first; + } +*/ +DLMALLOC_EXPORT void** dlindependent_calloc(size_t, size_t, void**); + +/* + independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); + + independent_comalloc allocates, all at once, a set of n_elements + chunks with sizes indicated in the "sizes" array. It returns + an array of pointers to these elements, each of which can be + independently freed, realloc'ed etc. The elements are guaranteed to + be adjacently allocated (this is not guaranteed to occur with + multiple callocs or mallocs), which may also improve cache locality + in some applications. + + The "chunks" argument is optional (i.e., may be null). If it is null + the returned array is itself dynamically allocated and should also + be freed when it is no longer needed. Otherwise, the chunks array + must be of at least n_elements in length. It is filled in with the + pointers to the chunks. + + In either case, independent_comalloc returns this pointer array, or + null if the allocation failed. If n_elements is zero and chunks is + null, it returns a chunk representing an array with zero elements + (which should be freed if not wanted). + + Each element must be freed when it is no longer needed. This can be + done all at once using bulk_free. + + independent_comallac differs from independent_calloc in that each + element may have a different size, and also that it does not + automatically clear elements. + + independent_comalloc can be used to speed up allocation in cases + where several structs or objects must always be allocated at the + same time. For example: + + struct Head { ... } + struct Foot { ... } + + void send_message(char* msg) { + int msglen = strlen(msg); + size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; + void* chunks[3]; + if (independent_comalloc(3, sizes, chunks) == 0) + die(); + struct Head* head = (struct Head*)(chunks[0]); + char* body = (char*)(chunks[1]); + struct Foot* foot = (struct Foot*)(chunks[2]); + // ... + } + + In general though, independent_comalloc is worth using only for + larger values of n_elements. For small values, you probably won't + detect enough difference from series of malloc calls to bother. + + Overuse of independent_comalloc can increase overall memory usage, + since it cannot reuse existing noncontiguous small chunks that + might be available for some of the elements. +*/ +DLMALLOC_EXPORT void** dlindependent_comalloc(size_t, size_t*, void**); + +/* + bulk_free(void* array[], size_t n_elements) + Frees and clears (sets to null) each non-null pointer in the given + array. This is likely to be faster than freeing them one-by-one. + If footers are used, pointers that have been allocated in different + mspaces are not freed or cleared, and the count of all such pointers + is returned. For large arrays of pointers with poor locality, it + may be worthwhile to sort this array before calling bulk_free. +*/ +DLMALLOC_EXPORT size_t dlbulk_free(void**, size_t n_elements); + +/* + pvalloc(size_t n); + Equivalent to valloc(minimum-page-that-holds(n)), that is, + round up n to nearest pagesize. + */ +DLMALLOC_EXPORT void* dlpvalloc(size_t); + +/* + malloc_trim(size_t pad); + + If possible, gives memory back to the system (via negative arguments + to sbrk) if there is unused memory at the `high' end of the malloc + pool or in unused MMAP segments. You can call this after freeing + large blocks of memory to potentially reduce the system-level memory + requirements of a program. However, it cannot guarantee to reduce + memory. Under some allocation patterns, some large free blocks of + memory will be locked between two used chunks, so they cannot be + given back to the system. + + The `pad' argument to malloc_trim represents the amount of free + trailing space to leave untrimmed. If this argument is zero, only + the minimum amount of memory to maintain internal data structures + will be left. Non-zero arguments can be supplied to maintain enough + trailing space to service future expected allocations without having + to re-obtain memory from the system. + + Malloc_trim returns 1 if it actually released any memory, else 0. +*/ +DLMALLOC_EXPORT int dlmalloc_trim(size_t); + +/* + malloc_stats(); + Prints on stderr the amount of space obtained from the system (both + via sbrk and mmap), the maximum amount (which may be more than + current if malloc_trim and/or munmap got called), and the current + number of bytes allocated via malloc (or realloc, etc) but not yet + freed. Note that this is the number of bytes allocated, not the + number requested. It will be larger than the number requested + because of alignment and bookkeeping overhead. Because it includes + alignment wastage as being in use, this figure may be greater than + zero even when no user-level chunks are allocated. + + The reported current and maximum system memory can be inaccurate if + a program makes other calls to system memory allocation functions + (normally sbrk) outside of malloc. + + malloc_stats prints only the most commonly interesting statistics. + More information can be obtained by calling mallinfo. +*/ +DLMALLOC_EXPORT void dlmalloc_stats(void); + +#endif /* ONLY_MSPACES */ + +/* + malloc_usable_size(void* p); + + Returns the number of bytes you can actually use in + an allocated chunk, which may be more than you requested (although + often not) due to alignment and minimum size constraints. + You can use this many bytes without worrying about + overwriting other allocated objects. This is not a particularly great + programming practice. malloc_usable_size can be more useful in + debugging and assertions, for example: + + p = malloc(n); + assert(malloc_usable_size(p) >= 256); +*/ +size_t dlmalloc_usable_size(void*); + +#if MSPACES + +/* + mspace is an opaque type representing an independent + region of space that supports mspace_malloc, etc. +*/ +typedef void* mspace; + +/* + create_mspace creates and returns a new independent space with the + given initial capacity, or, if 0, the default granularity size. It + returns null if there is no system memory available to create the + space. If argument locked is non-zero, the space uses a separate + lock to control access. The capacity of the space will grow + dynamically as needed to service mspace_malloc requests. You can + control the sizes of incremental increases of this space by + compiling with a different DEFAULT_GRANULARITY or dynamically + setting with mallopt(M_GRANULARITY, value). +*/ +DLMALLOC_EXPORT mspace create_mspace(size_t capacity, int locked); + +/* + destroy_mspace destroys the given space, and attempts to return all + of its memory back to the system, returning the total number of + bytes freed. After destruction, the results of access to all memory + used by the space become undefined. +*/ +DLMALLOC_EXPORT size_t destroy_mspace(mspace msp); + +/* + create_mspace_with_base uses the memory supplied as the initial base + of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this + space is used for bookkeeping, so the capacity must be at least this + large. (Otherwise 0 is returned.) When this initial space is + exhausted, additional memory will be obtained from the system. + Destroying this space will deallocate all additionally allocated + space (if possible) but not the initial base. +*/ +DLMALLOC_EXPORT mspace create_mspace_with_base(void* base, size_t capacity, int locked); + +/* + mspace_track_large_chunks controls whether requests for large chunks + are allocated in their own untracked mmapped regions, separate from + others in this mspace. By default large chunks are not tracked, + which reduces fragmentation. However, such chunks are not + necessarily released to the system upon destroy_mspace. Enabling + tracking by setting to true may increase fragmentation, but avoids + leakage when relying on destroy_mspace to release all memory + allocated using this space. The function returns the previous + setting. +*/ +DLMALLOC_EXPORT int mspace_track_large_chunks(mspace msp, int enable); + + +/* + mspace_malloc behaves as malloc, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_malloc(mspace msp, size_t bytes); + +/* + mspace_free behaves as free, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_free is not actually needed. + free may be called instead of mspace_free because freed chunks from + any space are handled by their originating spaces. +*/ +DLMALLOC_EXPORT void mspace_free(mspace msp, void* mem); + +/* + mspace_realloc behaves as realloc, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_realloc is not actually + needed. realloc may be called instead of mspace_realloc because + realloced chunks from any space are handled by their originating + spaces. +*/ +DLMALLOC_EXPORT void* mspace_realloc(mspace msp, void* mem, size_t newsize); + +/* + mspace_calloc behaves as calloc, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); + +/* + mspace_memalign behaves as memalign, but operates within + the given space. +*/ +DLMALLOC_EXPORT void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); + +/* + mspace_independent_calloc behaves as independent_calloc, but + operates within the given space. +*/ +DLMALLOC_EXPORT void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]); + +/* + mspace_independent_comalloc behaves as independent_comalloc, but + operates within the given space. +*/ +DLMALLOC_EXPORT void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]); + +/* + mspace_footprint() returns the number of bytes obtained from the + system for this space. +*/ +DLMALLOC_EXPORT size_t mspace_footprint(mspace msp); + +/* + mspace_max_footprint() returns the peak number of bytes obtained from the + system for this space. +*/ +DLMALLOC_EXPORT size_t mspace_max_footprint(mspace msp); + + +#if !NO_MALLINFO +/* + mspace_mallinfo behaves as mallinfo, but reports properties of + the given space. +*/ +DLMALLOC_EXPORT struct mallinfo mspace_mallinfo(mspace msp); +#endif /* NO_MALLINFO */ + +/* + malloc_usable_size(void* p) behaves the same as malloc_usable_size; +*/ +DLMALLOC_EXPORT size_t mspace_usable_size(void* mem); + +/* + mspace_malloc_stats behaves as malloc_stats, but reports + properties of the given space. +*/ +DLMALLOC_EXPORT void mspace_malloc_stats(mspace msp); + +/* + mspace_trim behaves as malloc_trim, but + operates within the given space. +*/ +DLMALLOC_EXPORT int mspace_trim(mspace msp, size_t pad); + +/* + An alias for mallopt. +*/ +DLMALLOC_EXPORT int mspace_mallopt(int, int); + +#endif /* MSPACES */ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif /* __cplusplus */ + +/* + ======================================================================== + To make a fully customizable malloc.h header file, cut everything + above this line, put into file malloc.h, edit to suit, and #include it + on the next line, as well as in programs that use this malloc. + ======================================================================== +*/ + +/* #include "malloc.h" */ + +/*------------------------------ internal #includes ---------------------- */ + +#ifdef _MSC_VER +#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ +#endif /* _MSC_VER */ +#if !NO_MALLOC_STATS +#include /* for printing in malloc_stats */ +#endif /* NO_MALLOC_STATS */ +#ifndef LACKS_ERRNO_H +#include /* for MALLOC_FAILURE_ACTION */ +#endif /* LACKS_ERRNO_H */ +#ifdef DEBUG +#if ABORT_ON_ASSERT_FAILURE +#undef assert +#define assert(x) if(!(x)) ABORT +#else /* ABORT_ON_ASSERT_FAILURE */ +#include +#endif /* ABORT_ON_ASSERT_FAILURE */ +#else /* DEBUG */ +#ifndef assert +#define assert(x) +#endif +#define DEBUG 0 +#endif /* DEBUG */ +#if !defined(WIN32) && !defined(LACKS_TIME_H) +#include /* for magic initialization */ +#endif /* WIN32 */ +#ifndef LACKS_STDLIB_H +#include /* for abort() */ +#endif /* LACKS_STDLIB_H */ +#ifndef LACKS_STRING_H +#include /* for memset etc */ +#endif /* LACKS_STRING_H */ +#if USE_BUILTIN_FFS +#ifndef LACKS_STRINGS_H +#include /* for ffs */ +#endif /* LACKS_STRINGS_H */ +#endif /* USE_BUILTIN_FFS */ +#if HAVE_MMAP +#ifndef LACKS_SYS_MMAN_H +/* On some versions of linux, mremap decl in mman.h needs __USE_GNU set */ +#if (defined(linux) && !defined(__USE_GNU)) +#define __USE_GNU 1 +#include /* for mmap */ +#undef __USE_GNU +#else +#include /* for mmap */ +#endif /* linux */ +#endif /* LACKS_SYS_MMAN_H */ +#ifndef LACKS_FCNTL_H +#include +#endif /* LACKS_FCNTL_H */ +#endif /* HAVE_MMAP */ +#ifndef LACKS_UNISTD_H +#include /* for sbrk, sysconf */ +#else /* LACKS_UNISTD_H */ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +extern void* sbrk(ptrdiff_t); +#endif /* FreeBSD etc */ +#endif /* LACKS_UNISTD_H */ + +/* Declarations for locking */ +#if USE_LOCKS +#ifndef WIN32 +#if defined (__SVR4) && defined (__sun) /* solaris */ +#include +#elif !defined(LACKS_SCHED_H) +#include +#endif /* solaris or LACKS_SCHED_H */ +#if (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) || !USE_SPIN_LOCKS +#include +#endif /* USE_RECURSIVE_LOCKS ... */ +#elif defined(_MSC_VER) +#ifndef _M_AMD64 +/* These are already defined on AMD64 builds */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +LONG __cdecl _InterlockedCompareExchange(LONG volatile *Dest, LONG Exchange, LONG Comp); +LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value); +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _M_AMD64 */ +#pragma intrinsic (_InterlockedCompareExchange) +#pragma intrinsic (_InterlockedExchange) +#define interlockedcompareexchange _InterlockedCompareExchange +#define interlockedexchange _InterlockedExchange +#elif defined(WIN32) && defined(__GNUC__) +#define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b) +#define interlockedexchange __sync_lock_test_and_set +#endif /* Win32 */ +#endif /* USE_LOCKS */ + +/* Declarations for bit scanning on win32 */ +#if defined(_MSC_VER) && _MSC_VER>=1300 +#ifndef BitScanForward /* Try to avoid pulling in WinNT.h */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +unsigned char _BitScanForward(unsigned long *index, unsigned long mask); +unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#define BitScanForward _BitScanForward +#define BitScanReverse _BitScanReverse +#pragma intrinsic(_BitScanForward) +#pragma intrinsic(_BitScanReverse) +#endif /* BitScanForward */ +#endif /* defined(_MSC_VER) && _MSC_VER>=1300 */ + +#ifndef WIN32 +#ifndef malloc_getpagesize +# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ +# ifndef _SC_PAGE_SIZE +# define _SC_PAGE_SIZE _SC_PAGESIZE +# endif +# endif +# ifdef _SC_PAGE_SIZE +# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) +# else +# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) + extern size_t getpagesize(); +# define malloc_getpagesize getpagesize() +# else +# ifdef WIN32 /* use supplied emulation of getpagesize */ +# define malloc_getpagesize getpagesize() +# else +# ifndef LACKS_SYS_PARAM_H +# include +# endif +# ifdef EXEC_PAGESIZE +# define malloc_getpagesize EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define malloc_getpagesize NBPG +# else +# define malloc_getpagesize (NBPG * CLSIZE) +# endif +# else +# ifdef NBPC +# define malloc_getpagesize NBPC +# else +# ifdef PAGESIZE +# define malloc_getpagesize PAGESIZE +# else /* just guess */ +# define malloc_getpagesize ((size_t)4096U) +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif +#endif + +/* ------------------- size_t and alignment properties -------------------- */ + +/* The byte and bit size of a size_t */ +#define SIZE_T_SIZE (sizeof(size_t)) +#define SIZE_T_BITSIZE (sizeof(size_t) << 3) + +/* Some constants coerced to size_t */ +/* Annoying but necessary to avoid errors on some platforms */ +#define SIZE_T_ZERO ((size_t)0) +#define SIZE_T_ONE ((size_t)1) +#define SIZE_T_TWO ((size_t)2) +#define SIZE_T_FOUR ((size_t)4) +#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) +#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) +#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) +#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) + +/* The bit mask value corresponding to MALLOC_ALIGNMENT */ +#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) + +/* True if address a has acceptable alignment */ +#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) + +/* the number of bytes to offset an address to align it */ +#define align_offset(A)\ + ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ + ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) + +/* -------------------------- MMAP preliminaries ------------------------- */ + +/* + If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and + checks to fail so compiler optimizer can delete code rather than + using so many "#if"s. +*/ + + +/* MORECORE and MMAP must return MFAIL on failure */ +#define MFAIL ((void*)(MAX_SIZE_T)) +#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ + +#if HAVE_MMAP + +#ifndef WIN32 +#define MUNMAP_DEFAULT(a, s) munmap((a), (s)) +#define MMAP_PROT (PROT_READ|PROT_WRITE) +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif /* MAP_ANON */ +#ifdef MAP_ANONYMOUS +#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) +#define MMAP_DEFAULT(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) +#else /* MAP_ANONYMOUS */ +/* + Nearly all versions of mmap support MAP_ANONYMOUS, so the following + is unlikely to be needed, but is supplied just in case. +*/ +#define MMAP_FLAGS (MAP_PRIVATE) +static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ +#define MMAP_DEFAULT(s) ((dev_zero_fd < 0) ? \ + (dev_zero_fd = open("/dev/zero", O_RDWR), \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) +#endif /* MAP_ANONYMOUS */ + +#define DIRECT_MMAP_DEFAULT(s) MMAP_DEFAULT(s) + +#else /* WIN32 */ + +/* Win32 MMAP via VirtualAlloc */ +static FORCEINLINE void* win32mmap(size_t size) { + void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + return (ptr != 0)? ptr: MFAIL; +} + +/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ +static FORCEINLINE void* win32direct_mmap(size_t size) { + void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, + PAGE_READWRITE); + return (ptr != 0)? ptr: MFAIL; +} + +/* This function supports releasing coalesed segments */ +static FORCEINLINE int win32munmap(void* ptr, size_t size) { + MEMORY_BASIC_INFORMATION minfo; + char* cptr = (char*)ptr; + while (size) { + if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) + return -1; + if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || + minfo.State != MEM_COMMIT || minfo.RegionSize > size) + return -1; + if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) + return -1; + cptr += minfo.RegionSize; + size -= minfo.RegionSize; + } + return 0; +} + +#define MMAP_DEFAULT(s) win32mmap(s) +#define MUNMAP_DEFAULT(a, s) win32munmap((a), (s)) +#define DIRECT_MMAP_DEFAULT(s) win32direct_mmap(s) +#endif /* WIN32 */ +#endif /* HAVE_MMAP */ + +#if HAVE_MREMAP +#ifndef WIN32 +#define MREMAP_DEFAULT(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) +#endif /* WIN32 */ +#endif /* HAVE_MREMAP */ + +/** + * Define CALL_MORECORE + */ +#if HAVE_MORECORE + #ifdef MORECORE + #define CALL_MORECORE(S) MORECORE(S) + #else /* MORECORE */ + #define CALL_MORECORE(S) MORECORE_DEFAULT(S) + #endif /* MORECORE */ +#else /* HAVE_MORECORE */ + #define CALL_MORECORE(S) MFAIL +#endif /* HAVE_MORECORE */ + +/** + * Define CALL_MMAP/CALL_MUNMAP/CALL_DIRECT_MMAP + */ +#if HAVE_MMAP + #define USE_MMAP_BIT (SIZE_T_ONE) + + #ifdef MMAP + #define CALL_MMAP(s) MMAP(s) + #else /* MMAP */ + #define CALL_MMAP(s) MMAP_DEFAULT(s) + #endif /* MMAP */ + #ifdef MUNMAP + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) + #else /* MUNMAP */ + #define CALL_MUNMAP(a, s) MUNMAP_DEFAULT((a), (s)) + #endif /* MUNMAP */ + #ifdef DIRECT_MMAP + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #else /* DIRECT_MMAP */ + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP_DEFAULT(s) + #endif /* DIRECT_MMAP */ +#else /* HAVE_MMAP */ + #define USE_MMAP_BIT (SIZE_T_ZERO) + + #define MMAP(s) MFAIL + #define MUNMAP(a, s) (-1) + #define DIRECT_MMAP(s) MFAIL + #define CALL_DIRECT_MMAP(s) DIRECT_MMAP(s) + #define CALL_MMAP(s) MMAP(s) + #define CALL_MUNMAP(a, s) MUNMAP((a), (s)) +#endif /* HAVE_MMAP */ + +/** + * Define CALL_MREMAP + */ +#if HAVE_MMAP && HAVE_MREMAP + #ifdef MREMAP + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP((addr), (osz), (nsz), (mv)) + #else /* MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MREMAP_DEFAULT((addr), (osz), (nsz), (mv)) + #endif /* MREMAP */ +#else /* HAVE_MMAP && HAVE_MREMAP */ + #define CALL_MREMAP(addr, osz, nsz, mv) MFAIL +#endif /* HAVE_MMAP && HAVE_MREMAP */ + +/* mstate bit set if continguous morecore disabled or failed */ +#define USE_NONCONTIGUOUS_BIT (4U) + +/* segment bit set in create_mspace_with_base */ +#define EXTERN_BIT (8U) + + +/* --------------------------- Lock preliminaries ------------------------ */ + +/* + When locks are defined, there is one global lock, plus + one per-mspace lock. + + The global lock_ensures that mparams.magic and other unique + mparams values are initialized only once. It also protects + sequences of calls to MORECORE. In many cases sys_alloc requires + two calls, that should not be interleaved with calls by other + threads. This does not protect against direct calls to MORECORE + by other threads not using this lock, so there is still code to + cope the best we can on interference. + + Per-mspace locks surround calls to malloc, free, etc. + By default, locks are simple non-reentrant mutexes. + + Because lock-protected regions generally have bounded times, it is + OK to use the supplied simple spinlocks. Spinlocks are likely to + improve performance for lightly contended applications, but worsen + performance under heavy contention. + + If USE_LOCKS is > 1, the definitions of lock routines here are + bypassed, in which case you will need to define the type MLOCK_T, + and at least INITIAL_LOCK, DESTROY_LOCK, ACQUIRE_LOCK, RELEASE_LOCK + and TRY_LOCK. You must also declare a + static MLOCK_T malloc_global_mutex = { initialization values };. + +*/ + +#if !USE_LOCKS +#define USE_LOCK_BIT (0U) +#define INITIAL_LOCK(l) (0) +#define DESTROY_LOCK(l) (0) +#define ACQUIRE_MALLOC_GLOBAL_LOCK() +#define RELEASE_MALLOC_GLOBAL_LOCK() + +#else +#if USE_LOCKS > 1 +/* ----------------------- User-defined locks ------------------------ */ +/* Define your own lock implementation here */ +/* #define INITIAL_LOCK(lk) ... */ +/* #define DESTROY_LOCK(lk) ... */ +/* #define ACQUIRE_LOCK(lk) ... */ +/* #define RELEASE_LOCK(lk) ... */ +/* #define TRY_LOCK(lk) ... */ +/* static MLOCK_T malloc_global_mutex = ... */ + +#elif USE_SPIN_LOCKS + +/* First, define CAS_LOCK and CLEAR_LOCK on ints */ +/* Note CAS_LOCK defined to return 0 on success */ + +#if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +#define CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1) +#define CLEAR_LOCK(sl) __sync_lock_release(sl) + +#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) +/* Custom spin locks for older gcc on x86 */ +static FORCEINLINE int x86_cas_lock(int *sl) { + int ret; + int val = 1; + int cmp = 0; + __asm__ __volatile__ ("lock; cmpxchgl %1, %2" + : "=a" (ret) + : "r" (val), "m" (*(sl)), "0"(cmp) + : "memory", "cc"); + return ret; +} + +static FORCEINLINE void x86_clear_lock(int* sl) { + assert(*sl != 0); + int prev = 0; + int ret; + __asm__ __volatile__ ("lock; xchgl %0, %1" + : "=r" (ret) + : "m" (*(sl)), "0"(prev) + : "memory"); +} + +#define CAS_LOCK(sl) x86_cas_lock(sl) +#define CLEAR_LOCK(sl) x86_clear_lock(sl) + +#else /* Win32 MSC */ +#define CAS_LOCK(sl) interlockedexchange(sl, 1) +#define CLEAR_LOCK(sl) interlockedexchange (sl, 0) + +#endif /* ... gcc spins locks ... */ + +/* How to yield for a spin lock */ +#define SPINS_PER_YIELD 63 +#if defined(_MSC_VER) +#define SLEEP_EX_DURATION 50 /* delay for yield/sleep */ +#define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE) +#elif defined (__SVR4) && defined (__sun) /* solaris */ +#define SPIN_LOCK_YIELD thr_yield(); +#elif !defined(LACKS_SCHED_H) +#define SPIN_LOCK_YIELD sched_yield(); +#else +#define SPIN_LOCK_YIELD +#endif /* ... yield ... */ + +#if !defined(USE_RECURSIVE_LOCKS) || USE_RECURSIVE_LOCKS == 0 +/* Plain spin locks use single word (embedded in malloc_states) */ +static int spin_acquire_lock(int *sl) { + int spins = 0; + while (*(volatile int *)sl != 0 || CAS_LOCK(sl)) { + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } + } + return 0; +} + +#define MLOCK_T int +#define TRY_LOCK(sl) !CAS_LOCK(sl) +#define RELEASE_LOCK(sl) CLEAR_LOCK(sl) +#define ACQUIRE_LOCK(sl) (CAS_LOCK(sl)? spin_acquire_lock(sl) : 0) +#define INITIAL_LOCK(sl) (*sl = 0) +#define DESTROY_LOCK(sl) (0) +static MLOCK_T malloc_global_mutex = 0; + +#else /* USE_RECURSIVE_LOCKS */ +/* types for lock owners */ +#ifdef WIN32 +#define THREAD_ID_T DWORD +#define CURRENT_THREAD GetCurrentThreadId() +#define EQ_OWNER(X,Y) ((X) == (Y)) +#else +/* + Note: the following assume that pthread_t is a type that can be + initialized to (casted) zero. If this is not the case, you will need to + somehow redefine these or not use spin locks. +*/ +#define THREAD_ID_T pthread_t +#define CURRENT_THREAD pthread_self() +#define EQ_OWNER(X,Y) pthread_equal(X, Y) +#endif + +struct malloc_recursive_lock { + int sl; + unsigned int c; + THREAD_ID_T threadid; +}; + +#define MLOCK_T struct malloc_recursive_lock +static MLOCK_T malloc_global_mutex = { 0, 0, (THREAD_ID_T)0}; + +static FORCEINLINE void recursive_release_lock(MLOCK_T *lk) { + assert(lk->sl != 0); + if (--lk->c == 0) { + CLEAR_LOCK(&lk->sl); + } +} + +static FORCEINLINE int recursive_acquire_lock(MLOCK_T *lk) { + THREAD_ID_T mythreadid = CURRENT_THREAD; + int spins = 0; + for (;;) { + if (*((volatile int *)(&lk->sl)) == 0) { + if (!CAS_LOCK(&lk->sl)) { + lk->threadid = mythreadid; + lk->c = 1; + return 0; + } + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { + ++lk->c; + return 0; + } + if ((++spins & SPINS_PER_YIELD) == 0) { + SPIN_LOCK_YIELD; + } + } +} + +static FORCEINLINE int recursive_try_lock(MLOCK_T *lk) { + THREAD_ID_T mythreadid = CURRENT_THREAD; + if (*((volatile int *)(&lk->sl)) == 0) { + if (!CAS_LOCK(&lk->sl)) { + lk->threadid = mythreadid; + lk->c = 1; + return 1; + } + } + else if (EQ_OWNER(lk->threadid, mythreadid)) { + ++lk->c; + return 1; + } + return 0; +} + +#define RELEASE_LOCK(lk) recursive_release_lock(lk) +#define TRY_LOCK(lk) recursive_try_lock(lk) +#define ACQUIRE_LOCK(lk) recursive_acquire_lock(lk) +#define INITIAL_LOCK(lk) ((lk)->threadid = (THREAD_ID_T)0, (lk)->sl = 0, (lk)->c = 0) +#define DESTROY_LOCK(lk) (0) +#endif /* USE_RECURSIVE_LOCKS */ + +#elif defined(WIN32) /* Win32 critical sections */ +#define MLOCK_T CRITICAL_SECTION +#define ACQUIRE_LOCK(lk) (EnterCriticalSection(lk), 0) +#define RELEASE_LOCK(lk) LeaveCriticalSection(lk) +#define TRY_LOCK(lk) TryEnterCriticalSection(lk) +#define INITIAL_LOCK(lk) (!InitializeCriticalSectionAndSpinCount((lk), 0x80000000|4000)) +#define DESTROY_LOCK(lk) (DeleteCriticalSection(lk), 0) +#define NEED_GLOBAL_LOCK_INIT + +static MLOCK_T malloc_global_mutex; +static volatile long malloc_global_mutex_status; + +/* Use spin loop to initialize global lock */ +static void init_malloc_global_mutex() { + for (;;) { + long stat = malloc_global_mutex_status; + if (stat > 0) + return; + /* transition to < 0 while initializing, then to > 0) */ + if (stat == 0 && + interlockedcompareexchange(&malloc_global_mutex_status, -1, 0) == 0) { + InitializeCriticalSection(&malloc_global_mutex); + interlockedexchange(&malloc_global_mutex_status,1); + return; + } + SleepEx(0, FALSE); + } +} + +#else /* pthreads-based locks */ +#define MLOCK_T pthread_mutex_t +#define ACQUIRE_LOCK(lk) pthread_mutex_lock(lk) +#define RELEASE_LOCK(lk) pthread_mutex_unlock(lk) +#define TRY_LOCK(lk) (!pthread_mutex_trylock(lk)) +#define INITIAL_LOCK(lk) pthread_init_lock(lk) +#define DESTROY_LOCK(lk) pthread_mutex_destroy(lk) + +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 && defined(linux) && !defined(PTHREAD_MUTEX_RECURSIVE) +/* Cope with old-style linux recursive lock initialization by adding */ +/* skipped internal declaration from pthread.h */ +extern int pthread_mutexattr_setkind_np __P ((pthread_mutexattr_t *__attr, + int __kind)); +#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#define pthread_mutexattr_settype(x,y) pthread_mutexattr_setkind_np(x,y) +#endif /* USE_RECURSIVE_LOCKS ... */ + +static MLOCK_T malloc_global_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int pthread_init_lock (MLOCK_T *lk) { + pthread_mutexattr_t attr; + if (pthread_mutexattr_init(&attr)) return 1; +#if defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0 + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) return 1; +#endif + if (pthread_mutex_init(lk, &attr)) return 1; + if (pthread_mutexattr_destroy(&attr)) return 1; + return 0; +} + +#endif /* ... lock types ... */ + +/* Common code for all lock types */ +#define USE_LOCK_BIT (2U) + +#ifndef ACQUIRE_MALLOC_GLOBAL_LOCK +#define ACQUIRE_MALLOC_GLOBAL_LOCK() ACQUIRE_LOCK(&malloc_global_mutex); +#endif + +#ifndef RELEASE_MALLOC_GLOBAL_LOCK +#define RELEASE_MALLOC_GLOBAL_LOCK() RELEASE_LOCK(&malloc_global_mutex); +#endif + +#endif /* USE_LOCKS */ + +/* ----------------------- Chunk representations ------------------------ */ + +/* + (The following includes lightly edited explanations by Colin Plumb.) + + The malloc_chunk declaration below is misleading (but accurate and + necessary). It declares a "view" into memory allowing access to + necessary fields at known offsets from a given base. + + Chunks of memory are maintained using a `boundary tag' method as + originally described by Knuth. (See the paper by Paul Wilson + ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such + techniques.) Sizes of free chunks are stored both in the front of + each chunk and at the end. This makes consolidating fragmented + chunks into bigger chunks fast. The head fields also hold bits + representing whether chunks are free or in use. + + Here are some pictures to make it clearer. They are "exploded" to + show that the state of a chunk can be thought of as extending from + the high 31 bits of the head field of its header through the + prev_foot and PINUSE_BIT bit of the following chunk header. + + A chunk that's in use looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk (if P = 0) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 1| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +- -+ + | | + +- -+ + | : + +- size - sizeof(size_t) available payload bytes -+ + : | + chunk-> +- -+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| + | Size of next chunk (may or may not be in use) | +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + And if it's free, it looks like this: + + chunk-> +- -+ + | User payload (must be in use, or we would have merged!) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 0| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Prev pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- size - sizeof(struct chunk) unused bytes -+ + : | + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| + | Size of next chunk (must be in use, or we would have merged)| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- User payload -+ + : | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0| + +-+ + Note that since we always merge adjacent free chunks, the chunks + adjacent to a free chunk must be in use. + + Given a pointer to a chunk (which can be derived trivially from the + payload pointer) we can, in O(1) time, find out whether the adjacent + chunks are free, and if so, unlink them from the lists that they + are on and merge them with the current chunk. + + Chunks always begin on even word boundaries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus at least double-word aligned. + + The P (PINUSE_BIT) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + The very first chunk allocated always has this bit set, preventing + access to non-existent (or non-owned) memory. If pinuse is set for + any given chunk, then you CANNOT determine the size of the + previous chunk, and might even get a memory addressing fault when + trying to do so. + + The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of + the chunk size redundantly records whether the current chunk is + inuse (unless the chunk is mmapped). This redundancy enables usage + checks within free and realloc, and reduces indirection when freeing + and consolidating chunks. + + Each freshly allocated chunk must have both cinuse and pinuse set. + That is, each allocated chunk borders either a previously allocated + and still in-use chunk, or the base of its memory arena. This is + ensured by making all allocations from the `lowest' part of any + found chunk. Further, no free chunk physically borders another one, + so each free chunk is known to be preceded and followed by either + inuse chunks or the ends of memory. + + Note that the `foot' of the current chunk is actually represented + as the prev_foot of the NEXT chunk. This makes it easier to + deal with alignments etc but can be very confusing when trying + to extend or adapt this code. + + The exceptions to all this are + + 1. The special chunk `top' is the top-most available chunk (i.e., + the one bordering the end of available memory). It is treated + specially. Top is never included in any bin, is used only if + no other chunk is available, and is released back to the + system if it is very large (see M_TRIM_THRESHOLD). In effect, + the top chunk is treated as larger (and thus less well + fitting) than any other available chunk. The top chunk + doesn't update its trailing size field since there is no next + contiguous chunk that would have to index off it. However, + space is still allocated for it (TOP_FOOT_SIZE) to enable + separation or merging when space is extended. + + 3. Chunks allocated via mmap, have both cinuse and pinuse bits + cleared in their head fields. Because they are allocated + one-by-one, each must carry its own prev_foot field, which is + also used to hold the offset this chunk has within its mmapped + region, which is needed to preserve alignment. Each mmapped + chunk is trailed by the first two fields of a fake next-chunk + for sake of usage checks. + +*/ + +struct malloc_chunk { + size_t prev_foot; /* Size of previous chunk (if free). */ + size_t head; /* Size and inuse bits. */ + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +}; + +typedef struct malloc_chunk mchunk; +typedef struct malloc_chunk* mchunkptr; +typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ +typedef unsigned int bindex_t; /* Described below */ +typedef unsigned int binmap_t; /* Described below */ +typedef unsigned int flag_t; /* The type of various bit flag sets */ + +/* ------------------- Chunks sizes and alignments ----------------------- */ + +#define MCHUNK_SIZE (sizeof(mchunk)) + +#if FOOTERS +#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +#else /* FOOTERS */ +#define CHUNK_OVERHEAD (SIZE_T_SIZE) +#endif /* FOOTERS */ + +/* MMapped chunks need a second word of overhead ... */ +#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +/* ... and additional padding for fake next-chunk at foot */ +#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) + +/* The smallest size we can malloc is an aligned minimal chunk */ +#define MIN_CHUNK_SIZE\ + ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* conversion from malloc headers to user pointers, and back */ +#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) +/* chunk associated with aligned address A */ +#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) + +/* Bounds on request (not chunk) sizes. */ +#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) +#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) + +/* pad request bytes into a usable size */ +#define pad_request(req) \ + (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* pad request, checking for minimum (but not maximum) */ +#define request2size(req) \ + (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) + + +/* ------------------ Operations on head and foot fields ----------------- */ + +/* + The head field of a chunk is or'ed with PINUSE_BIT when previous + adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in + use, unless mmapped, in which case both bits are cleared. + + FLAG4_BIT is not used by this malloc, but might be useful in extensions. +*/ + +#define PINUSE_BIT (SIZE_T_ONE) +#define CINUSE_BIT (SIZE_T_TWO) +#define FLAG4_BIT (SIZE_T_FOUR) +#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) +#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT) + +/* Head value for fenceposts */ +#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) + +/* extraction of fields from head words */ +#define cinuse(p) ((p)->head & CINUSE_BIT) +#define pinuse(p) ((p)->head & PINUSE_BIT) +#define flag4inuse(p) ((p)->head & FLAG4_BIT) +#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT) +#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0) + +#define chunksize(p) ((p)->head & ~(FLAG_BITS)) + +#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) +#define set_flag4(p) ((p)->head |= FLAG4_BIT) +#define clear_flag4(p) ((p)->head &= ~FLAG4_BIT) + +/* Treat space at ptr +/- offset as a chunk */ +#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) +#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) + +/* Ptr to next or previous physical malloc_chunk. */ +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS))) +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) + +/* extract next chunk's pinuse bit */ +#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) + +/* Get/set size at footer */ +#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) + +/* Set size, pinuse bit, and foot */ +#define set_size_and_pinuse_of_free_chunk(p, s)\ + ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) + +/* Set size, pinuse bit, foot, and clear next pinuse */ +#define set_free_with_pinuse(p, s, n)\ + (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) + +/* Get the internal overhead associated with chunk p */ +#define overhead_for(p)\ + (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) + +/* Return true if malloced space is not necessarily cleared */ +#if MMAP_CLEARS +#define calloc_must_clear(p) (!is_mmapped(p)) +#else /* MMAP_CLEARS */ +#define calloc_must_clear(p) (1) +#endif /* MMAP_CLEARS */ + +/* ---------------------- Overlaid data structures ----------------------- */ + +/* + When chunks are not in use, they are treated as nodes of either + lists or trees. + + "Small" chunks are stored in circular doubly-linked lists, and look + like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Larger chunks are kept in a form of bitwise digital trees (aka + tries) keyed on chunksizes. Because malloc_tree_chunks are only for + free chunks greater than 256 bytes, their size doesn't impose any + constraints on user chunk sizes. Each node looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to left child (child[0]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to right child (child[1]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to parent | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | bin index of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Each tree holding treenodes is a tree of unique chunk sizes. Chunks + of the same size are arranged in a circularly-linked list, with only + the oldest chunk (the next to be used, in our FIFO ordering) + actually in the tree. (Tree members are distinguished by a non-null + parent pointer.) If a chunk with the same size an an existing node + is inserted, it is linked off the existing node using pointers that + work in the same way as fd/bk pointers of small chunks. + + Each tree contains a power of 2 sized range of chunk sizes (the + smallest is 0x100 <= x < 0x180), which is is divided in half at each + tree level, with the chunks in the smaller half of the range (0x100 + <= x < 0x140 for the top nose) in the left subtree and the larger + half (0x140 <= x < 0x180) in the right subtree. This is, of course, + done by inspecting individual bits. + + Using these rules, each node's left subtree contains all smaller + sizes than its right subtree. However, the node at the root of each + subtree has no particular ordering relationship to either. (The + dividing line between the subtree sizes is based on trie relation.) + If we remove the last chunk of a given size from the interior of the + tree, we need to replace it with a leaf node. The tree ordering + rules permit a node to be replaced by any leaf below it. + + The smallest chunk in a tree (a common operation in a best-fit + allocator) can be found by walking a path to the leftmost leaf in + the tree. Unlike a usual binary tree, where we follow left child + pointers until we reach a null, here we follow the right child + pointer any time the left one is null, until we reach a leaf with + both child pointers null. The smallest chunk in the tree will be + somewhere along that path. + + The worst case number of steps to add, find, or remove a node is + bounded by the number of bits differentiating chunks within + bins. Under current bin calculations, this ranges from 6 up to 21 + (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case + is of course much better. +*/ + +struct malloc_tree_chunk { + /* The first four fields must be compatible with malloc_chunk */ + size_t prev_foot; + size_t head; + struct malloc_tree_chunk* fd; + struct malloc_tree_chunk* bk; + + struct malloc_tree_chunk* child[2]; + struct malloc_tree_chunk* parent; + bindex_t index; +}; + +typedef struct malloc_tree_chunk tchunk; +typedef struct malloc_tree_chunk* tchunkptr; +typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ + +/* A little helper macro for trees */ +#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) + +/* ----------------------------- Segments -------------------------------- */ + +/* + Each malloc space may include non-contiguous segments, held in a + list headed by an embedded malloc_segment record representing the + top-most space. Segments also include flags holding properties of + the space. Large chunks that are directly allocated by mmap are not + included in this list. They are instead independently created and + destroyed without otherwise keeping track of them. + + Segment management mainly comes into play for spaces allocated by + MMAP. Any call to MMAP might or might not return memory that is + adjacent to an existing segment. MORECORE normally contiguously + extends the current space, so this space is almost always adjacent, + which is simpler and faster to deal with. (This is why MORECORE is + used preferentially to MMAP when both are available -- see + sys_alloc.) When allocating using MMAP, we don't use any of the + hinting mechanisms (inconsistently) supported in various + implementations of unix mmap, or distinguish reserving from + committing memory. Instead, we just ask for space, and exploit + contiguity when we get it. It is probably possible to do + better than this on some systems, but no general scheme seems + to be significantly better. + + Management entails a simpler variant of the consolidation scheme + used for chunks to reduce fragmentation -- new adjacent memory is + normally prepended or appended to an existing segment. However, + there are limitations compared to chunk consolidation that mostly + reflect the fact that segment processing is relatively infrequent + (occurring only when getting memory from system) and that we + don't expect to have huge numbers of segments: + + * Segments are not indexed, so traversal requires linear scans. (It + would be possible to index these, but is not worth the extra + overhead and complexity for most programs on most platforms.) + * New segments are only appended to old ones when holding top-most + memory; if they cannot be prepended to others, they are held in + different segments. + + Except for the top-most segment of an mstate, each segment record + is kept at the tail of its segment. Segments are added by pushing + segment records onto the list headed by &mstate.seg for the + containing mstate. + + Segment flags control allocation/merge/deallocation policies: + * If EXTERN_BIT set, then we did not allocate this segment, + and so should not try to deallocate or merge with others. + (This currently holds only for the initial segment passed + into create_mspace_with_base.) + * If USE_MMAP_BIT set, the segment may be merged with + other surrounding mmapped segments and trimmed/de-allocated + using munmap. + * If neither bit is set, then the segment was obtained using + MORECORE so can be merged with surrounding MORECORE'd segments + and deallocated/trimmed using MORECORE with negative arguments. +*/ + +struct malloc_segment { + char* base; /* base address */ + size_t size; /* allocated size */ + struct malloc_segment* next; /* ptr to next segment */ + flag_t sflags; /* mmap and extern flag */ +}; + +#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT) +#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) + +typedef struct malloc_segment msegment; +typedef struct malloc_segment* msegmentptr; + +/* ---------------------------- malloc_state ----------------------------- */ + +/* + A malloc_state holds all of the bookkeeping for a space. + The main fields are: + + Top + The topmost chunk of the currently active segment. Its size is + cached in topsize. The actual size of topmost space is + topsize+TOP_FOOT_SIZE, which includes space reserved for adding + fenceposts and segment records if necessary when getting more + space from the system. The size at which to autotrim top is + cached from mparams in trim_check, except that it is disabled if + an autotrim fails. + + Designated victim (dv) + This is the preferred chunk for servicing small requests that + don't have exact fits. It is normally the chunk split off most + recently to service another small request. Its size is cached in + dvsize. The link fields of this chunk are not maintained since it + is not kept in a bin. + + SmallBins + An array of bin headers for free chunks. These bins hold chunks + with sizes less than MIN_LARGE_SIZE bytes. Each bin contains + chunks of all the same size, spaced 8 bytes apart. To simplify + use in double-linked lists, each bin header acts as a malloc_chunk + pointing to the real first node, if it exists (else pointing to + itself). This avoids special-casing for headers. But to avoid + waste, we allocate only the fd/bk pointers of bins, and then use + repositioning tricks to treat these as the fields of a chunk. + + TreeBins + Treebins are pointers to the roots of trees holding a range of + sizes. There are 2 equally spaced treebins for each power of two + from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything + larger. + + Bin maps + There is one bit map for small bins ("smallmap") and one for + treebins ("treemap). Each bin sets its bit when non-empty, and + clears the bit when empty. Bit operations are then used to avoid + bin-by-bin searching -- nearly all "search" is done without ever + looking at bins that won't be selected. The bit maps + conservatively use 32 bits per map word, even if on 64bit system. + For a good description of some of the bit-based techniques used + here, see Henry S. Warren Jr's book "Hacker's Delight" (and + supplement at http://hackersdelight.org/). Many of these are + intended to reduce the branchiness of paths through malloc etc, as + well as to reduce the number of memory locations read or written. + + Segments + A list of segments headed by an embedded malloc_segment record + representing the initial space. + + Address check support + The least_addr field is the least address ever obtained from + MORECORE or MMAP. Attempted frees and reallocs of any address less + than this are trapped (unless INSECURE is defined). + + Magic tag + A cross-check field that should always hold same value as mparams.magic. + + Max allowed footprint + The maximum allowed bytes to allocate from system (zero means no limit) + + Flags + Bits recording whether to use MMAP, locks, or contiguous MORECORE + + Statistics + Each space keeps track of current and maximum system memory + obtained via MORECORE or MMAP. + + Trim support + Fields holding the amount of unused topmost memory that should trigger + trimming, and a counter to force periodic scanning to release unused + non-topmost segments. + + Locking + If USE_LOCKS is defined, the "mutex" lock is acquired and released + around every public call using this mspace. + + Extension support + A void* pointer and a size_t field that can be used to help implement + extensions to this malloc. +*/ + +/* Bin types, widths and sizes */ +#define NSMALLBINS (32U) +#define NTREEBINS (32U) +#define SMALLBIN_SHIFT (3U) +#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) +#define TREEBIN_SHIFT (8U) +#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) +#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) +#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) + +struct malloc_state { + binmap_t smallmap; + binmap_t treemap; + size_t dvsize; + size_t topsize; + char* least_addr; + mchunkptr dv; + mchunkptr top; + size_t trim_check; + size_t release_checks; + size_t magic; + mchunkptr smallbins[(NSMALLBINS+1)*2]; + tbinptr treebins[NTREEBINS]; + size_t footprint; + size_t max_footprint; + size_t footprint_limit; /* zero means no limit */ + flag_t mflags; +#if USE_LOCKS + MLOCK_T mutex; /* locate lock among fields that rarely change */ +#endif /* USE_LOCKS */ + msegment seg; + void* extp; /* Unused but available for extensions */ + size_t exts; +}; + +typedef struct malloc_state* mstate; + +/* ------------- Global malloc_state and malloc_params ------------------- */ + +/* + malloc_params holds global properties, including those that can be + dynamically set using mallopt. There is a single instance, mparams, + initialized in init_mparams. Note that the non-zeroness of "magic" + also serves as an initialization flag. +*/ + +struct malloc_params { + size_t magic; + size_t page_size; + size_t granularity; + size_t mmap_threshold; + size_t trim_threshold; + flag_t default_mflags; +}; + +static struct malloc_params mparams; + +/* Ensure mparams initialized */ +#define ensure_initialization() (void)(mparams.magic != 0 || init_mparams()) + +#if !ONLY_MSPACES + +/* The global malloc_state used for all non-"mspace" calls */ +static struct malloc_state _gm_; +#define gm (&_gm_) +#define is_global(M) ((M) == &_gm_) + +#endif /* !ONLY_MSPACES */ + +#define is_initialized(M) ((M)->top != 0) + +/* -------------------------- system alloc setup ------------------------- */ + +/* Operations on mflags */ + +#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) +#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) +#if USE_LOCKS +#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) +#else +#define disable_lock(M) +#endif + +#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) +#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) +#if HAVE_MMAP +#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) +#else +#define disable_mmap(M) +#endif + +#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) +#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) + +#define set_lock(M,L)\ + ((M)->mflags = (L)?\ + ((M)->mflags | USE_LOCK_BIT) :\ + ((M)->mflags & ~USE_LOCK_BIT)) + +/* page-align a size */ +#define page_align(S)\ + (((S) + (mparams.page_size - SIZE_T_ONE)) & ~(mparams.page_size - SIZE_T_ONE)) + +/* granularity-align a size */ +#define granularity_align(S)\ + (((S) + (mparams.granularity - SIZE_T_ONE))\ + & ~(mparams.granularity - SIZE_T_ONE)) + + +/* For mmap, use granularity alignment on windows, else page-align */ +#ifdef WIN32 +#define mmap_align(S) granularity_align(S) +#else +#define mmap_align(S) page_align(S) +#endif + +/* For sys_alloc, enough padding to ensure can malloc request on success */ +#define SYS_ALLOC_PADDING (TOP_FOOT_SIZE + MALLOC_ALIGNMENT) + +#define is_page_aligned(S)\ + (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) +#define is_granularity_aligned(S)\ + (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) + +/* True if segment S holds address A */ +#define segment_holds(S, A)\ + ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) + +/* Return segment holding given address */ +static msegmentptr segment_holding(mstate m, char* addr) { + msegmentptr sp = &m->seg; + for (;;) { + if (addr >= sp->base && addr < sp->base + sp->size) + return sp; + if ((sp = sp->next) == 0) + return 0; + } +} + +/* Return true if segment contains a segment link */ +static int has_segment_link(mstate m, msegmentptr ss) { + msegmentptr sp = &m->seg; + for (;;) { + if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) + return 1; + if ((sp = sp->next) == 0) + return 0; + } +} + +#ifndef MORECORE_CANNOT_TRIM +#define should_trim(M,s) ((s) > (M)->trim_check) +#else /* MORECORE_CANNOT_TRIM */ +#define should_trim(M,s) (0) +#endif /* MORECORE_CANNOT_TRIM */ + +/* + TOP_FOOT_SIZE is padding at the end of a segment, including space + that may be needed to place segment records and fenceposts when new + noncontiguous segments are added. +*/ +#define TOP_FOOT_SIZE\ + (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) + + +/* ------------------------------- Hooks -------------------------------- */ + +/* + PREACTION should be defined to return 0 on success, and nonzero on + failure. If you are not using locking, you can redefine these to do + anything you like. +*/ + +#if USE_LOCKS +#define PREACTION(M) ((use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) +#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } +#else /* USE_LOCKS */ + +#ifndef PREACTION +#define PREACTION(M) (0) +#endif /* PREACTION */ + +#ifndef POSTACTION +#define POSTACTION(M) +#endif /* POSTACTION */ + +#endif /* USE_LOCKS */ + +/* + CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. + USAGE_ERROR_ACTION is triggered on detected bad frees and + reallocs. The argument p is an address that might have triggered the + fault. It is ignored by the two predefined actions, but might be + useful in custom actions that try to help diagnose errors. +*/ + +#if PROCEED_ON_ERROR + +/* A count of the number of corruption errors causing resets */ +int malloc_corruption_error_count; + +/* default corruption action */ +static void reset_on_error(mstate m); + +#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) +#define USAGE_ERROR_ACTION(m, p) + +#else /* PROCEED_ON_ERROR */ + +#ifndef CORRUPTION_ERROR_ACTION +#define CORRUPTION_ERROR_ACTION(m) ABORT +#endif /* CORRUPTION_ERROR_ACTION */ + +#ifndef USAGE_ERROR_ACTION +#define USAGE_ERROR_ACTION(m,p) ABORT +#endif /* USAGE_ERROR_ACTION */ + +#endif /* PROCEED_ON_ERROR */ + + +/* -------------------------- Debugging setup ---------------------------- */ + +#if ! DEBUG + +#define check_free_chunk(M,P) +#define check_inuse_chunk(M,P) +#define check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) +#define check_malloc_state(M) +#define check_top_chunk(M,P) + +#else /* DEBUG */ +#define check_free_chunk(M,P) do_check_free_chunk(M,P) +#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) +#define check_top_chunk(M,P) do_check_top_chunk(M,P) +#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) +#define check_malloc_state(M) do_check_malloc_state(M) + +static void do_check_any_chunk(mstate m, mchunkptr p); +static void do_check_top_chunk(mstate m, mchunkptr p); +static void do_check_mmapped_chunk(mstate m, mchunkptr p); +static void do_check_inuse_chunk(mstate m, mchunkptr p); +static void do_check_free_chunk(mstate m, mchunkptr p); +static void do_check_malloced_chunk(mstate m, void* mem, size_t s); +static void do_check_tree(mstate m, tchunkptr t); +static void do_check_treebin(mstate m, bindex_t i); +static void do_check_smallbin(mstate m, bindex_t i); +static void do_check_malloc_state(mstate m); +static int bin_find(mstate m, mchunkptr x); +static size_t traverse_and_check(mstate m); +#endif /* DEBUG */ + +/* ---------------------------- Indexing Bins ---------------------------- */ + +#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) +#define small_index(s) (bindex_t)((s) >> SMALLBIN_SHIFT) +#define small_index2size(i) ((i) << SMALLBIN_SHIFT) +#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) + +/* addressing by index. See above about smallbin repositioning */ +#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) +#define treebin_at(M,i) (&((M)->treebins[i])) + +/* assign tree index for size S to variable I. Use x86 asm if possible */ +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#define compute_tree_index(S, I)\ +{\ + unsigned int X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = (unsigned) sizeof(X)*__CHAR_BIT__ - 1 - (unsigned) __builtin_clz(X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#elif defined (__INTEL_COMPILER) +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K = _bit_scan_reverse (X); \ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K;\ + _BitScanReverse((DWORD *) &K, (DWORD) X);\ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} + +#else /* GNUC */ +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int Y = (unsigned int)X;\ + unsigned int N = ((Y - 0x100) >> 16) & 8;\ + unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ + N += K;\ + N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ + K = 14 - N + ((Y <<= K) >> 15);\ + I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ + }\ +} +#endif /* GNUC */ + +/* Bit representing maximum resolved size in a treebin at i */ +#define bit_for_tree_index(i) \ + (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) + +/* Shift placing maximum resolved bit in a treebin at i as sign bit */ +#define leftshift_for_tree_index(i) \ + ((i == NTREEBINS-1)? 0 : \ + ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) + +/* The size of the smallest chunk held in bin with index i */ +#define minsize_for_tree_index(i) \ + ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ + (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) + + +/* ------------------------ Operations on bin maps ----------------------- */ + +/* bit corresponding to given index */ +#define idx2bit(i) ((binmap_t)(1) << (i)) + +/* Mark/Clear bits with given index */ +#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) +#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) +#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) + +#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) +#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) +#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) + +/* isolate the least set bit of a bitmap */ +#define least_bit(x) ((x) & -(x)) + +/* mask with all bits to left of least bit of x on */ +#define left_bits(x) ((x<<1) | -(x<<1)) + +/* mask with all bits to left of or equal to least bit of x on */ +#define same_or_left_bits(x) ((x) | -(x)) + +/* index corresponding to given bit. Use x86 asm if possible */ + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = __builtin_ctz(X); \ + I = (bindex_t)J;\ +} + +#elif defined (__INTEL_COMPILER) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + J = _bit_scan_forward (X); \ + I = (bindex_t)J;\ +} + +#elif defined(_MSC_VER) && _MSC_VER>=1300 +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + _BitScanForward((DWORD *) &J, X);\ + I = (bindex_t)J;\ +} + +#elif USE_BUILTIN_FFS +#define compute_bit2idx(X, I) I = ffs(X)-1 + +#else +#define compute_bit2idx(X, I)\ +{\ + unsigned int Y = X - 1;\ + unsigned int K = Y >> (16-4) & 16;\ + unsigned int N = K; Y >>= K;\ + N += K = Y >> (8-3) & 8; Y >>= K;\ + N += K = Y >> (4-2) & 4; Y >>= K;\ + N += K = Y >> (2-1) & 2; Y >>= K;\ + N += K = Y >> (1-0) & 1; Y >>= K;\ + I = (bindex_t)(N + Y);\ +} +#endif /* GNUC */ + + +/* ----------------------- Runtime Check Support ------------------------- */ + +/* + For security, the main invariant is that malloc/free/etc never + writes to a static address other than malloc_state, unless static + malloc_state itself has been corrupted, which cannot occur via + malloc (because of these checks). In essence this means that we + believe all pointers, sizes, maps etc held in malloc_state, but + check all of those linked or offsetted from other embedded data + structures. These checks are interspersed with main code in a way + that tends to minimize their run-time cost. + + When FOOTERS is defined, in addition to range checking, we also + verify footer fields of inuse chunks, which can be used guarantee + that the mstate controlling malloc/free is intact. This is a + streamlined version of the approach described by William Robertson + et al in "Run-time Detection of Heap-based Overflows" LISA'03 + http://www.usenix.org/events/lisa03/tech/robertson.html The footer + of an inuse chunk holds the xor of its mstate and a random seed, + that is checked upon calls to free() and realloc(). This is + (probabalistically) unguessable from outside the program, but can be + computed by any code successfully malloc'ing any chunk, so does not + itself provide protection against code that has already broken + security through some other means. Unlike Robertson et al, we + always dynamically check addresses of all offset chunks (previous, + next, etc). This turns out to be cheaper than relying on hashes. +*/ + +#if !INSECURE +/* Check if address a is at least as high as any from MORECORE or MMAP */ +#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) +/* Check if address of next chunk n is higher than base chunk p */ +#define ok_next(p, n) ((char*)(p) < (char*)(n)) +/* Check if p has inuse status */ +#define ok_inuse(p) is_inuse(p) +/* Check if p has its pinuse bit on */ +#define ok_pinuse(p) pinuse(p) + +#else /* !INSECURE */ +#define ok_address(M, a) (1) +#define ok_next(b, n) (1) +#define ok_inuse(p) (1) +#define ok_pinuse(p) (1) +#endif /* !INSECURE */ + +#if (FOOTERS && !INSECURE) +/* Check if (alleged) mstate m has expected magic field */ +#define ok_magic(M) ((M)->magic == mparams.magic) +#else /* (FOOTERS && !INSECURE) */ +#define ok_magic(M) (1) +#endif /* (FOOTERS && !INSECURE) */ + +/* In gcc, use __builtin_expect to minimize impact of checks */ +#if !INSECURE +#if defined(__GNUC__) && __GNUC__ >= 3 +#define RTCHECK(e) __builtin_expect(e, 1) +#else /* GNUC */ +#define RTCHECK(e) (e) +#endif /* GNUC */ +#else /* !INSECURE */ +#define RTCHECK(e) (1) +#endif /* !INSECURE */ + +/* macros to set up inuse chunks with or without footers */ + +#if !FOOTERS + +#define mark_inuse_foot(M,p,s) + +/* Macros for setting head/foot of non-mmapped chunks */ + +/* Set cinuse bit and pinuse bit of next chunk */ +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set size, cinuse and pinuse bit of this chunk */ +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) + +#else /* FOOTERS */ + +/* Set foot of inuse chunk to be xor of mstate and seed */ +#define mark_inuse_foot(M,p,s)\ + (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) + +#define get_mstate_for(p)\ + ((mstate)(((mchunkptr)((char*)(p) +\ + (chunksize(p))))->prev_foot ^ mparams.magic)) + +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ + mark_inuse_foot(M,p,s)) + +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ + mark_inuse_foot(M,p,s)) + +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + mark_inuse_foot(M, p, s)) + +#endif /* !FOOTERS */ + +/* ---------------------------- setting mparams -------------------------- */ + +/* Initialize mparams */ +static int init_mparams(void) { +#ifdef NEED_GLOBAL_LOCK_INIT + if (malloc_global_mutex_status <= 0) + init_malloc_global_mutex(); +#endif + + ACQUIRE_MALLOC_GLOBAL_LOCK(); + if (mparams.magic == 0) { + size_t magic; + size_t psize; + size_t gsize; + +#ifndef WIN32 + psize = malloc_getpagesize; + gsize = ((DEFAULT_GRANULARITY != 0)? DEFAULT_GRANULARITY : psize); +#else /* WIN32 */ + { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + psize = system_info.dwPageSize; + gsize = ((DEFAULT_GRANULARITY != 0)? + DEFAULT_GRANULARITY : system_info.dwAllocationGranularity); + } +#endif /* WIN32 */ + + /* Sanity-check configuration: + size_t must be unsigned and as wide as pointer type. + ints must be at least 4 bytes. + alignment must be at least 8. + Alignment, min chunk size, and page size must all be powers of 2. + */ + if ((sizeof(size_t) != sizeof(char*)) || + (MAX_SIZE_T < MIN_CHUNK_SIZE) || + (sizeof(int) < 4) || + (MALLOC_ALIGNMENT < (size_t)8U) || + ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || + ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || + ((gsize & (gsize-SIZE_T_ONE)) != 0) || + ((psize & (psize-SIZE_T_ONE)) != 0)) + ABORT; + + mparams.granularity = gsize; + mparams.page_size = psize; + mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; + mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; +#if MORECORE_CONTIGUOUS + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; +#else /* MORECORE_CONTIGUOUS */ + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; +#endif /* MORECORE_CONTIGUOUS */ + +#if !ONLY_MSPACES + /* Set up lock for main malloc area */ + gm->mflags = mparams.default_mflags; + (void)INITIAL_LOCK(&gm->mutex); +#endif + + { +#if USE_DEV_RANDOM + int fd; + unsigned char buf[sizeof(size_t)]; + /* Try to use /dev/urandom, else fall back on using time */ + if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && + read(fd, buf, sizeof(buf)) == sizeof(buf)) { + magic = *((size_t *) buf); + close(fd); + } + else +#endif /* USE_DEV_RANDOM */ +#ifdef WIN32 + magic = (size_t)(GetTickCount() ^ (size_t)0x55555555U); +#elif defined(LACKS_TIME_H) + magic = (size_t)&magic ^ (size_t)0x55555555U; +#else + magic = (size_t)(time(0) ^ (size_t)0x55555555U); +#endif + magic |= (size_t)8U; /* ensure nonzero */ + magic &= ~(size_t)7U; /* improve chances of fault for bad values */ + /* Until memory modes commonly available, use volatile-write */ + (*(volatile size_t *)(&(mparams.magic))) = magic; + } + } + + RELEASE_MALLOC_GLOBAL_LOCK(); + return 1; +} + +/* support for mallopt */ +static int change_mparam(int param_number, int value) { + size_t val; + ensure_initialization(); + val = (value == -1)? MAX_SIZE_T : (size_t)value; + switch(param_number) { + case M_TRIM_THRESHOLD: + mparams.trim_threshold = val; + return 1; + case M_GRANULARITY: + if (val >= mparams.page_size && ((val & (val-1)) == 0)) { + mparams.granularity = val; + return 1; + } + else + return 0; + case M_MMAP_THRESHOLD: + mparams.mmap_threshold = val; + return 1; + default: + return 0; + } +} + +#if DEBUG +/* ------------------------- Debugging Support --------------------------- */ + +/* Check properties of any chunk, whether free, inuse, mmapped etc */ +static void do_check_any_chunk(mstate m, mchunkptr p) { + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); +} + +/* Check properties of top chunk */ +static void do_check_top_chunk(mstate m, mchunkptr p) { + msegmentptr sp = segment_holding(m, (char*)p); + size_t sz = p->head & ~INUSE_BITS; /* third-lowest bit can be set! */ + assert(sp != 0); + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); + assert(sz == m->topsize); + assert(sz > 0); + assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); + assert(pinuse(p)); + assert(!pinuse(chunk_plus_offset(p, sz))); +} + +/* Check properties of (inuse) mmapped chunks */ +static void do_check_mmapped_chunk(mstate m, mchunkptr p) { + size_t sz = chunksize(p); + size_t len = (sz + (p->prev_foot) + MMAP_FOOT_PAD); + assert(is_mmapped(p)); + assert(use_mmap(m)); + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); + assert(!is_small(sz)); + assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); + assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); + assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); +} + +/* Check properties of inuse chunks */ +static void do_check_inuse_chunk(mstate m, mchunkptr p) { + do_check_any_chunk(m, p); + assert(is_inuse(p)); + assert(next_pinuse(p)); + /* If not pinuse and not mmapped, previous chunk has OK offset */ + assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); + if (is_mmapped(p)) + do_check_mmapped_chunk(m, p); +} + +/* Check properties of free chunks */ +static void do_check_free_chunk(mstate m, mchunkptr p) { + size_t sz = chunksize(p); + mchunkptr next = chunk_plus_offset(p, sz); + do_check_any_chunk(m, p); + assert(!is_inuse(p)); + assert(!next_pinuse(p)); + assert (!is_mmapped(p)); + if (p != m->dv && p != m->top) { + if (sz >= MIN_CHUNK_SIZE) { + assert((sz & CHUNK_ALIGN_MASK) == 0); + assert(is_aligned(chunk2mem(p))); + assert(next->prev_foot == sz); + assert(pinuse(p)); + assert (next == m->top || is_inuse(next)); + assert(p->fd->bk == p); + assert(p->bk->fd == p); + } + else /* markers are always of size SIZE_T_SIZE */ + assert(sz == SIZE_T_SIZE); + } +} + +/* Check properties of malloced chunks at the point they are malloced */ +static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t sz = p->head & ~INUSE_BITS; + do_check_inuse_chunk(m, p); + assert((sz & CHUNK_ALIGN_MASK) == 0); + assert(sz >= MIN_CHUNK_SIZE); + assert(sz >= s); + /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ + assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); + } +} + +/* Check a tree and its subtrees. */ +static void do_check_tree(mstate m, tchunkptr t) { + tchunkptr head = 0; + tchunkptr u = t; + bindex_t tindex = t->index; + size_t tsize = chunksize(t); + bindex_t idx; + compute_tree_index(tsize, idx); + assert(tindex == idx); + assert(tsize >= MIN_LARGE_SIZE); + assert(tsize >= minsize_for_tree_index(idx)); + assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); + + do { /* traverse through chain of same-sized nodes */ + do_check_any_chunk(m, ((mchunkptr)u)); + assert(u->index == tindex); + assert(chunksize(u) == tsize); + assert(!is_inuse(u)); + assert(!next_pinuse(u)); + assert(u->fd->bk == u); + assert(u->bk->fd == u); + if (u->parent == 0) { + assert(u->child[0] == 0); + assert(u->child[1] == 0); + } + else { + assert(head == 0); /* only one node on chain has parent */ + head = u; + assert(u->parent != u); + assert (u->parent->child[0] == u || + u->parent->child[1] == u || + *((tbinptr*)(u->parent)) == u); + if (u->child[0] != 0) { + assert(u->child[0]->parent == u); + assert(u->child[0] != u); + do_check_tree(m, u->child[0]); + } + if (u->child[1] != 0) { + assert(u->child[1]->parent == u); + assert(u->child[1] != u); + do_check_tree(m, u->child[1]); + } + if (u->child[0] != 0 && u->child[1] != 0) { + assert(chunksize(u->child[0]) < chunksize(u->child[1])); + } + } + u = u->fd; + } while (u != t); + assert(head != 0); +} + +/* Check all the chunks in a treebin. */ +static void do_check_treebin(mstate m, bindex_t i) { + tbinptr* tb = treebin_at(m, i); + tchunkptr t = *tb; + int empty = (m->treemap & (1U << i)) == 0; + if (t == 0) + assert(empty); + if (!empty) + do_check_tree(m, t); +} + +/* Check all the chunks in a smallbin. */ +static void do_check_smallbin(mstate m, bindex_t i) { + sbinptr b = smallbin_at(m, i); + mchunkptr p = b->bk; + unsigned int empty = (m->smallmap & (1U << i)) == 0; + if (p == b) + assert(empty); + if (!empty) { + for (; p != b; p = p->bk) { + size_t size = chunksize(p); + mchunkptr q; + /* each chunk claims to be free */ + do_check_free_chunk(m, p); + /* chunk belongs in bin */ + assert(small_index(size) == i); + assert(p->bk == b || chunksize(p->bk) == chunksize(p)); + /* chunk is followed by an inuse chunk */ + q = next_chunk(p); + if (q->head != FENCEPOST_HEAD) + do_check_inuse_chunk(m, q); + } + } +} + +/* Find x in a bin. Used in other check functions. */ +static int bin_find(mstate m, mchunkptr x) { + size_t size = chunksize(x); + if (is_small(size)) { + bindex_t sidx = small_index(size); + sbinptr b = smallbin_at(m, sidx); + if (smallmap_is_marked(m, sidx)) { + mchunkptr p = b; + do { + if (p == x) + return 1; + } while ((p = p->fd) != b); + } + } + else { + bindex_t tidx; + compute_tree_index(size, tidx); + if (treemap_is_marked(m, tidx)) { + tchunkptr t = *treebin_at(m, tidx); + size_t sizebits = size << leftshift_for_tree_index(tidx); + while (t != 0 && chunksize(t) != size) { + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + sizebits <<= 1; + } + if (t != 0) { + tchunkptr u = t; + do { + if (u == (tchunkptr)x) + return 1; + } while ((u = u->fd) != t); + } + } + } + return 0; +} + +/* Traverse each chunk and check it; return total */ +static size_t traverse_and_check(mstate m) { + size_t sum = 0; + if (is_initialized(m)) { + msegmentptr s = &m->seg; + sum += m->topsize + TOP_FOOT_SIZE; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + mchunkptr lastq = 0; + assert(pinuse(q)); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + sum += chunksize(q); + if (is_inuse(q)) { + assert(!bin_find(m, q)); + do_check_inuse_chunk(m, q); + } + else { + assert(q == m->dv || bin_find(m, q)); + assert(lastq == 0 || is_inuse(lastq)); /* Not 2 consecutive free */ + do_check_free_chunk(m, q); + } + lastq = q; + q = next_chunk(q); + } + s = s->next; + } + } + return sum; +} + + +/* Check all properties of malloc_state. */ +static void do_check_malloc_state(mstate m) { + bindex_t i; + size_t total; + /* check bins */ + for (i = 0; i < NSMALLBINS; ++i) + do_check_smallbin(m, i); + for (i = 0; i < NTREEBINS; ++i) + do_check_treebin(m, i); + + if (m->dvsize != 0) { /* check dv chunk */ + do_check_any_chunk(m, m->dv); + assert(m->dvsize == chunksize(m->dv)); + assert(m->dvsize >= MIN_CHUNK_SIZE); + assert(bin_find(m, m->dv) == 0); + } + + if (m->top != 0) { /* check top chunk */ + do_check_top_chunk(m, m->top); + /*assert(m->topsize == chunksize(m->top)); redundant */ + assert(m->topsize > 0); + assert(bin_find(m, m->top) == 0); + } + + total = traverse_and_check(m); + assert(total <= m->footprint); + assert(m->footprint <= m->max_footprint); +} +#endif /* DEBUG */ + +/* ----------------------------- statistics ------------------------------ */ + +#if !NO_MALLINFO +static struct mallinfo internal_mallinfo(mstate m) { + struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + ensure_initialization(); + if (!PREACTION(m)) { + check_malloc_state(m); + if (is_initialized(m)) { + size_t nfree = SIZE_T_ONE; /* top always free */ + size_t mfree = m->topsize + TOP_FOOT_SIZE; + size_t sum = mfree; + msegmentptr s = &m->seg; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + size_t sz = chunksize(q); + sum += sz; + if (!is_inuse(q)) { + mfree += sz; + ++nfree; + } + q = next_chunk(q); + } + s = s->next; + } + + nm.arena = sum; + nm.ordblks = nfree; + nm.hblkhd = m->footprint - sum; + nm.usmblks = m->max_footprint; + nm.uordblks = m->footprint - mfree; + nm.fordblks = mfree; + nm.keepcost = m->topsize; + } + + POSTACTION(m); + } + return nm; +} +#endif /* !NO_MALLINFO */ + +#if !NO_MALLOC_STATS +static void internal_malloc_stats(mstate m) { + ensure_initialization(); + if (!PREACTION(m)) { + size_t maxfp = 0; + size_t fp = 0; + size_t used = 0; + check_malloc_state(m); + if (is_initialized(m)) { + msegmentptr s = &m->seg; + maxfp = m->max_footprint; + fp = m->footprint; + used = fp - (m->topsize + TOP_FOOT_SIZE); + + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + if (!is_inuse(q)) + used -= chunksize(q); + q = next_chunk(q); + } + s = s->next; + } + } + POSTACTION(m); /* drop lock */ + fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); + fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); + fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); + } +} +#endif /* NO_MALLOC_STATS */ + +/* ----------------------- Operations on smallbins ----------------------- */ + +/* + Various forms of linking and unlinking are defined as macros. Even + the ones for trees, which are very long but have very short typical + paths. This is ugly but reduces reliance on inlining support of + compilers. +*/ + +/* Link a free chunk into a smallbin */ +#define insert_small_chunk(M, P, S) {\ + bindex_t I = small_index(S);\ + mchunkptr B = smallbin_at(M, I);\ + mchunkptr F = B;\ + assert(S >= MIN_CHUNK_SIZE);\ + if (!smallmap_is_marked(M, I))\ + mark_smallmap(M, I);\ + else if (RTCHECK(ok_address(M, B->fd)))\ + F = B->fd;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + B->fd = P;\ + F->bk = P;\ + P->fd = F;\ + P->bk = B;\ +} + +/* Unlink a chunk from a smallbin */ +#define unlink_small_chunk(M, P, S) {\ + mchunkptr F = P->fd;\ + mchunkptr B = P->bk;\ + bindex_t I = small_index(S);\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(B == smallbin_at(M,I) ||\ + (ok_address(M, B) && B->fd == P))) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Unlink the first chunk from a smallbin */ +#define unlink_first_small_chunk(M, B, P, I) {\ + mchunkptr F = P->fd;\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (B == F) {\ + clear_smallmap(M, I);\ + }\ + else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Replace dv node, binning the old one */ +/* Used only when dvsize known to be small */ +#define replace_dv(M, P, S) {\ + size_t DVS = M->dvsize;\ + assert(is_small(DVS));\ + if (DVS != 0) {\ + mchunkptr DV = M->dv;\ + insert_small_chunk(M, DV, DVS);\ + }\ + M->dvsize = S;\ + M->dv = P;\ +} + +/* ------------------------- Operations on trees ------------------------- */ + +/* Insert chunk into tree */ +#define insert_large_chunk(M, X, S) {\ + tbinptr* H;\ + bindex_t I;\ + compute_tree_index(S, I);\ + H = treebin_at(M, I);\ + X->index = I;\ + X->child[0] = X->child[1] = 0;\ + if (!treemap_is_marked(M, I)) {\ + mark_treemap(M, I);\ + *H = X;\ + X->parent = (tchunkptr)H;\ + X->fd = X->bk = X;\ + }\ + else {\ + tchunkptr T = *H;\ + size_t K = S << leftshift_for_tree_index(I);\ + for (;;) {\ + if (chunksize(T) != S) {\ + tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ + K <<= 1;\ + if (*C != 0)\ + T = *C;\ + else if (RTCHECK(ok_address(M, C))) {\ + *C = X;\ + X->parent = T;\ + X->fd = X->bk = X;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + else {\ + tchunkptr F = T->fd;\ + if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ + T->fd = F->bk = X;\ + X->fd = F;\ + X->bk = T;\ + X->parent = 0;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + }\ + }\ +} + +/* + Unlink steps: + + 1. If x is a chained node, unlink it from its same-sized fd/bk links + and choose its bk node as its replacement. + 2. If x was the last node of its size, but not a leaf node, it must + be replaced with a leaf node (not merely one with an open left or + right), to make sure that lefts and rights of descendents + correspond properly to bit masks. We use the rightmost descendent + of x. We could use any other leaf, but this is easy to locate and + tends to counteract removal of leftmosts elsewhere, and so keeps + paths shorter than minimally guaranteed. This doesn't loop much + because on average a node in a tree is near the bottom. + 3. If x is the base of a chain (i.e., has parent links) relink + x's parent and children to x's replacement (or null if none). +*/ + +#define unlink_large_chunk(M, X) {\ + tchunkptr XP = X->parent;\ + tchunkptr R;\ + if (X->bk != X) {\ + tchunkptr F = X->fd;\ + R = X->bk;\ + if (RTCHECK(ok_address(M, F) && F->bk == X && R->fd == X)) {\ + F->bk = R;\ + R->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + tchunkptr* RP;\ + if (((R = *(RP = &(X->child[1]))) != 0) ||\ + ((R = *(RP = &(X->child[0]))) != 0)) {\ + tchunkptr* CP;\ + while ((*(CP = &(R->child[1])) != 0) ||\ + (*(CP = &(R->child[0])) != 0)) {\ + R = *(RP = CP);\ + }\ + if (RTCHECK(ok_address(M, RP)))\ + *RP = 0;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + }\ + if (XP != 0) {\ + tbinptr* H = treebin_at(M, X->index);\ + if (X == *H) {\ + if ((*H = R) == 0) \ + clear_treemap(M, X->index);\ + }\ + else if (RTCHECK(ok_address(M, XP))) {\ + if (XP->child[0] == X) \ + XP->child[0] = R;\ + else \ + XP->child[1] = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + if (R != 0) {\ + if (RTCHECK(ok_address(M, R))) {\ + tchunkptr C0, C1;\ + R->parent = XP;\ + if ((C0 = X->child[0]) != 0) {\ + if (RTCHECK(ok_address(M, C0))) {\ + R->child[0] = C0;\ + C0->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + if ((C1 = X->child[1]) != 0) {\ + if (RTCHECK(ok_address(M, C1))) {\ + R->child[1] = C1;\ + C1->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ +} + +/* Relays to large vs small bin operations */ + +#define insert_chunk(M, P, S)\ + if (is_small(S)) insert_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } + +#define unlink_chunk(M, P, S)\ + if (is_small(S)) unlink_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } + + +/* Relays to internal calls to malloc/free from realloc, memalign etc */ + +#if ONLY_MSPACES +#define internal_malloc(m, b) mspace_malloc(m, b) +#define internal_free(m, mem) mspace_free(m,mem); +#else /* ONLY_MSPACES */ +#if MSPACES +#define internal_malloc(m, b)\ + ((m == gm)? dlmalloc(b) : mspace_malloc(m, b)) +#define internal_free(m, mem)\ + if (m == gm) dlfree(mem); else mspace_free(m,mem); +#else /* MSPACES */ +#define internal_malloc(m, b) dlmalloc(b) +#define internal_free(m, mem) dlfree(mem) +#endif /* MSPACES */ +#endif /* ONLY_MSPACES */ + +/* ----------------------- Direct-mmapping chunks ----------------------- */ + +/* + Directly mmapped chunks are set up with an offset to the start of + the mmapped region stored in the prev_foot field of the chunk. This + allows reconstruction of the required argument to MUNMAP when freed, + and also allows adjustment of the returned chunk to meet alignment + requirements (especially in memalign). +*/ + +/* Malloc using mmap */ +static void* mmap_alloc(mstate m, size_t nb) { + size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + if (m->footprint_limit != 0) { + size_t fp = m->footprint + mmsize; + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; + } + if (mmsize > nb) { /* Check for wrap around 0 */ + char* mm = (char*)(CALL_DIRECT_MMAP(mmsize)); + if (mm != CMFAIL) { + size_t offset = align_offset(chunk2mem(mm)); + size_t psize = mmsize - offset - MMAP_FOOT_PAD; + mchunkptr p = (mchunkptr)(mm + offset); + p->prev_foot = offset; + p->head = psize; + mark_inuse_foot(m, p, psize); + chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; + chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; + + if (m->least_addr == 0 || mm < m->least_addr) + m->least_addr = mm; + if ((m->footprint += mmsize) > m->max_footprint) + m->max_footprint = m->footprint; + assert(is_aligned(chunk2mem(p))); + check_mmapped_chunk(m, p); + return chunk2mem(p); + } + } + return 0; +} + +/* Realloc using mmap */ +static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) { + size_t oldsize = chunksize(oldp); + (void)flags; /* placate people compiling -Wunused */ + if (is_small(nb)) /* Can't shrink mmap regions below small size */ + return 0; + /* Keep old chunk if big enough but not too big */ + if (oldsize >= nb + SIZE_T_SIZE && + (oldsize - nb) <= (mparams.granularity << 1)) + return oldp; + else { + size_t offset = oldp->prev_foot; + size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; + size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + char* cp = (char*)CALL_MREMAP((char*)oldp - offset, + oldmmsize, newmmsize, flags); + if (cp != CMFAIL) { + mchunkptr newp = (mchunkptr)(cp + offset); + size_t psize = newmmsize - offset - MMAP_FOOT_PAD; + newp->head = psize; + mark_inuse_foot(m, newp, psize); + chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; + chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; + + if (cp < m->least_addr) + m->least_addr = cp; + if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) + m->max_footprint = m->footprint; + check_mmapped_chunk(m, newp); + return newp; + } + } + return 0; +} + + +/* -------------------------- mspace management -------------------------- */ + +/* Initialize top chunk and its size */ +static void init_top(mstate m, mchunkptr p, size_t psize) { + /* Ensure alignment */ + size_t offset = align_offset(chunk2mem(p)); + p = (mchunkptr)((char*)p + offset); + psize -= offset; + + m->top = p; + m->topsize = psize; + p->head = psize | PINUSE_BIT; + /* set size of fake trailing chunk holding overhead space only once */ + chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; + m->trim_check = mparams.trim_threshold; /* reset on each update */ +} + +/* Initialize bins for a new mstate that is otherwise zeroed out */ +static void init_bins(mstate m) { + /* Establish circular links for smallbins */ + bindex_t i; + for (i = 0; i < NSMALLBINS; ++i) { + sbinptr bin = smallbin_at(m,i); + bin->fd = bin->bk = bin; + } +} + +#if PROCEED_ON_ERROR + +/* default corruption action */ +static void reset_on_error(mstate m) { + int i; + ++malloc_corruption_error_count; + /* Reinitialize fields to forget about all memory */ + m->smallmap = m->treemap = 0; + m->dvsize = m->topsize = 0; + m->seg.base = 0; + m->seg.size = 0; + m->seg.next = 0; + m->top = m->dv = 0; + for (i = 0; i < NTREEBINS; ++i) + *treebin_at(m, i) = 0; + init_bins(m); +} +#endif /* PROCEED_ON_ERROR */ + +/* Allocate chunk and prepend remainder with chunk in successor base. */ +static void* prepend_alloc(mstate m, char* newbase, char* oldbase, + size_t nb) { + mchunkptr p = align_as_chunk(newbase); + mchunkptr oldfirst = align_as_chunk(oldbase); + size_t psize = (char*)oldfirst - (char*)p; + mchunkptr q = chunk_plus_offset(p, nb); + size_t qsize = psize - nb; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + + assert((char*)oldfirst > (char*)q); + assert(pinuse(oldfirst)); + assert(qsize >= MIN_CHUNK_SIZE); + + /* consolidate remainder with first chunk of old base */ + if (oldfirst == m->top) { + size_t tsize = m->topsize += qsize; + m->top = q; + q->head = tsize | PINUSE_BIT; + check_top_chunk(m, q); + } + else if (oldfirst == m->dv) { + size_t dsize = m->dvsize += qsize; + m->dv = q; + set_size_and_pinuse_of_free_chunk(q, dsize); + } + else { + if (!is_inuse(oldfirst)) { + size_t nsize = chunksize(oldfirst); + unlink_chunk(m, oldfirst, nsize); + oldfirst = chunk_plus_offset(oldfirst, nsize); + qsize += nsize; + } + set_free_with_pinuse(q, qsize, oldfirst); + insert_chunk(m, q, qsize); + check_free_chunk(m, q); + } + + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); +} + +/* Add a segment to hold a new noncontiguous region */ +static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { + /* Determine locations and sizes of segment, fenceposts, old top */ + char* old_top = (char*)m->top; + msegmentptr oldsp = segment_holding(m, old_top); + char* old_end = oldsp->base + oldsp->size; + size_t ssize = pad_request(sizeof(struct malloc_segment)); + char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + size_t offset = align_offset(chunk2mem(rawsp)); + char* asp = rawsp + offset; + char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; + mchunkptr sp = (mchunkptr)csp; + msegmentptr ss = (msegmentptr)(chunk2mem(sp)); + mchunkptr tnext = chunk_plus_offset(sp, ssize); + mchunkptr p = tnext; + int nfences = 0; + + /* reset top to new space */ + init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); + + /* Set up segment record */ + assert(is_aligned(ss)); + set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); + *ss = m->seg; /* Push current record */ + m->seg.base = tbase; + m->seg.size = tsize; + m->seg.sflags = mmapped; + m->seg.next = ss; + + /* Insert trailing fenceposts */ + for (;;) { + mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); + p->head = FENCEPOST_HEAD; + ++nfences; + if ((char*)(&(nextp->head)) < old_end) + p = nextp; + else + break; + } + assert(nfences >= 2); + + /* Insert the rest of old top into a bin as an ordinary free chunk */ + if (csp != old_top) { + mchunkptr q = (mchunkptr)old_top; + size_t psize = csp - old_top; + mchunkptr tn = chunk_plus_offset(q, psize); + set_free_with_pinuse(q, psize, tn); + insert_chunk(m, q, psize); + } + + check_top_chunk(m, m->top); +} + +/* -------------------------- System allocation -------------------------- */ + +/* Get memory from system using MORECORE or MMAP */ +static void* sys_alloc(mstate m, size_t nb) { + char* tbase = CMFAIL; + size_t tsize = 0; + flag_t mmap_flag = 0; + size_t asize; /* allocation size */ + + ensure_initialization(); + + /* Directly map large chunks, but only if already initialized */ + if (use_mmap(m) && nb >= mparams.mmap_threshold && m->topsize != 0) { + void* mem = mmap_alloc(m, nb); + if (mem != 0) + return mem; + } + + asize = granularity_align(nb + SYS_ALLOC_PADDING); + if (asize <= nb) + return 0; /* wraparound */ + if (m->footprint_limit != 0) { + size_t fp = m->footprint + asize; + if (fp <= m->footprint || fp > m->footprint_limit) + return 0; + } + + /* + Try getting memory in any of three ways (in most-preferred to + least-preferred order): + 1. A call to MORECORE that can normally contiguously extend memory. + (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or + or main space is mmapped or a previous contiguous call failed) + 2. A call to MMAP new space (disabled if not HAVE_MMAP). + Note that under the default settings, if MORECORE is unable to + fulfill a request, and HAVE_MMAP is true, then mmap is + used as a noncontiguous system allocator. This is a useful backup + strategy for systems with holes in address spaces -- in this case + sbrk cannot contiguously expand the heap, but mmap may be able to + find space. + 3. A call to MORECORE that cannot usually contiguously extend memory. + (disabled if not HAVE_MORECORE) + + In all cases, we need to request enough bytes from system to ensure + we can malloc nb bytes upon success, so pad with enough space for + top_foot, plus alignment-pad to make sure we don't lose bytes if + not on boundary, and round this up to a granularity unit. + */ + + if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { + char* br = CMFAIL; + msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); + ACQUIRE_MALLOC_GLOBAL_LOCK(); + + if (ss == 0) { /* First time through or recovery */ + char* base = (char*)CALL_MORECORE(0); + if (base != CMFAIL) { + size_t fp; + /* Adjust to end on a page boundary */ + if (!is_page_aligned(base)) + asize += (page_align((size_t)base) - (size_t)base); + fp = m->footprint + asize; /* recheck limits */ + if (asize > nb && asize < HALF_MAX_SIZE_T && + (m->footprint_limit == 0 || + (fp > m->footprint && fp <= m->footprint_limit)) && + (br = (char*)(CALL_MORECORE(asize))) == base) { + tbase = base; + tsize = asize; + } + } + } + else { + /* Subtract out existing available top space from MORECORE request. */ + asize = granularity_align(nb - m->topsize + SYS_ALLOC_PADDING); + /* Use mem here only if it did continuously extend old space */ + if (asize < HALF_MAX_SIZE_T && + (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) { + tbase = br; + tsize = asize; + } + } + + if (tbase == CMFAIL) { /* Cope with partial failure */ + if (br != CMFAIL) { /* Try to use/extend the space we did get */ + if (asize < HALF_MAX_SIZE_T && + asize < nb + SYS_ALLOC_PADDING) { + size_t esize = granularity_align(nb + SYS_ALLOC_PADDING - asize); + if (esize < HALF_MAX_SIZE_T) { + char* end = (char*)CALL_MORECORE(esize); + if (end != CMFAIL) + asize += esize; + else { /* Can't use; try to release */ + (void) CALL_MORECORE(-asize); + br = CMFAIL; + } + } + } + } + if (br != CMFAIL) { /* Use the space we did get */ + tbase = br; + tsize = asize; + } + else + disable_contiguous(m); /* Don't try contiguous path in the future */ + } + + RELEASE_MALLOC_GLOBAL_LOCK(); + } + + if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ + char* mp = (char*)(CALL_MMAP(asize)); + if (mp != CMFAIL) { + tbase = mp; + tsize = asize; + mmap_flag = USE_MMAP_BIT; + } + } + + if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ + if (asize < HALF_MAX_SIZE_T) { + char* br = CMFAIL; + char* end = CMFAIL; + ACQUIRE_MALLOC_GLOBAL_LOCK(); + br = (char*)(CALL_MORECORE(asize)); + end = (char*)(CALL_MORECORE(0)); + RELEASE_MALLOC_GLOBAL_LOCK(); + if (br != CMFAIL && end != CMFAIL && br < end) { + size_t ssize = end - br; + if (ssize > nb + TOP_FOOT_SIZE) { + tbase = br; + tsize = ssize; + } + } + } + } + + if (tbase != CMFAIL) { + + if ((m->footprint += tsize) > m->max_footprint) + m->max_footprint = m->footprint; + + if (!is_initialized(m)) { /* first-time initialization */ + if (m->least_addr == 0 || tbase < m->least_addr) + m->least_addr = tbase; + m->seg.base = tbase; + m->seg.size = tsize; + m->seg.sflags = mmap_flag; + m->magic = mparams.magic; + m->release_checks = MAX_RELEASE_CHECK_RATE; + init_bins(m); +#if !ONLY_MSPACES + if (is_global(m)) + init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); + else +#endif + { + /* Offset top by embedded malloc_state */ + mchunkptr mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); + } + } + + else { + /* Try to merge with an existing segment */ + msegmentptr sp = &m->seg; + /* Only consider most recent segment if traversal suppressed */ + while (sp != 0 && tbase != sp->base + sp->size) + sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; + if (sp != 0 && + !is_extern_segment(sp) && + (sp->sflags & USE_MMAP_BIT) == mmap_flag && + segment_holds(sp, m->top)) { /* append */ + sp->size += tsize; + init_top(m, m->top, m->topsize + tsize); + } + else { + if (tbase < m->least_addr) + m->least_addr = tbase; + sp = &m->seg; + while (sp != 0 && sp->base != tbase + tsize) + sp = (NO_SEGMENT_TRAVERSAL) ? 0 : sp->next; + if (sp != 0 && + !is_extern_segment(sp) && + (sp->sflags & USE_MMAP_BIT) == mmap_flag) { + char* oldbase = sp->base; + sp->base = tbase; + sp->size += tsize; + return prepend_alloc(m, tbase, oldbase, nb); + } + else + add_segment(m, tbase, tsize, mmap_flag); + } + } + + if (nb < m->topsize) { /* Allocate from new or extended top space */ + size_t rsize = m->topsize -= nb; + mchunkptr p = m->top; + mchunkptr r = m->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + check_top_chunk(m, m->top); + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); + } + } + + MALLOC_FAILURE_ACTION; + return 0; +} + +/* ----------------------- system deallocation -------------------------- */ + +/* Unmap and unlink any mmapped segments that don't contain used chunks */ +static size_t release_unused_segments(mstate m) { + size_t released = 0; + int nsegs = 0; + msegmentptr pred = &m->seg; + msegmentptr sp = pred->next; + while (sp != 0) { + char* base = sp->base; + size_t size = sp->size; + msegmentptr next = sp->next; + ++nsegs; + if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { + mchunkptr p = align_as_chunk(base); + size_t psize = chunksize(p); + /* Can unmap if first chunk holds entire segment and not pinned */ + if (!is_inuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { + tchunkptr tp = (tchunkptr)p; + assert(segment_holds(sp, (char*)sp)); + if (p == m->dv) { + m->dv = 0; + m->dvsize = 0; + } + else { + unlink_large_chunk(m, tp); + } + if (CALL_MUNMAP(base, size) == 0) { + released += size; + m->footprint -= size; + /* unlink obsoleted record */ + sp = pred; + sp->next = next; + } + else { /* back out if cannot unmap */ + insert_large_chunk(m, tp, psize); + } + } + } + if (NO_SEGMENT_TRAVERSAL) /* scan only first segment */ + break; + pred = sp; + sp = next; + } + /* Reset check counter */ + m->release_checks = ((nsegs > MAX_RELEASE_CHECK_RATE)? + nsegs : MAX_RELEASE_CHECK_RATE); + return released; +} + +static int sys_trim(mstate m, size_t pad) { + size_t released = 0; + ensure_initialization(); + if (pad < MAX_REQUEST && is_initialized(m)) { + pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ + + if (m->topsize > pad) { + /* Shrink top space in granularity-size units, keeping at least one */ + size_t unit = mparams.granularity; + size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - + SIZE_T_ONE) * unit; + msegmentptr sp = segment_holding(m, (char*)m->top); + + if (!is_extern_segment(sp)) { + if (is_mmapped_segment(sp)) { + if (HAVE_MMAP && + sp->size >= extra && + !has_segment_link(m, sp)) { /* can't shrink if pinned */ + size_t newsize = sp->size - extra; + /* Prefer mremap, fall back to munmap */ + if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || + (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { + released = extra; + } + } + } + else if (HAVE_MORECORE) { + if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ + extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; + ACQUIRE_MALLOC_GLOBAL_LOCK(); + { + /* Make sure end of memory is where we last set it. */ + char* old_br = (char*)(CALL_MORECORE(0)); + if (old_br == sp->base + sp->size) { + char* rel_br = (char*)(CALL_MORECORE(-extra)); + char* new_br = (char*)(CALL_MORECORE(0)); + if (rel_br != CMFAIL && new_br < old_br) + released = old_br - new_br; + } + } + RELEASE_MALLOC_GLOBAL_LOCK(); + } + } + + if (released != 0) { + sp->size -= released; + m->footprint -= released; + init_top(m, m->top, m->topsize - released); + check_top_chunk(m, m->top); + } + } + + /* Unmap any unused mmapped segments */ + if (HAVE_MMAP) + released += release_unused_segments(m); + + /* On failure, disable autotrim to avoid repeated failed future calls */ + if (released == 0 && m->topsize > m->trim_check) + m->trim_check = MAX_SIZE_T; + } + + return (released != 0)? 1 : 0; +} + +/* Consolidate and bin a chunk. Differs from exported versions + of free mainly in that the chunk need not be marked as inuse. +*/ +static void dispose_chunk(mstate m, mchunkptr p, size_t psize) { + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + mchunkptr prev; + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + m->footprint -= psize; + return; + } + prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(m, prev))) { /* consolidate backward */ + if (p != m->dv) { + unlink_chunk(m, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + m->dvsize = psize; + set_free_with_pinuse(p, psize, next); + return; + } + } + else { + CORRUPTION_ERROR_ACTION(m); + return; + } + } + if (RTCHECK(ok_address(m, next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == m->top) { + size_t tsize = m->topsize += psize; + m->top = p; + p->head = tsize | PINUSE_BIT; + if (p == m->dv) { + m->dv = 0; + m->dvsize = 0; + } + return; + } + else if (next == m->dv) { + size_t dsize = m->dvsize += psize; + m->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + return; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(m, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == m->dv) { + m->dvsize = psize; + return; + } + } + } + else { + set_free_with_pinuse(p, psize, next); + } + insert_chunk(m, p, psize); + } + else { + CORRUPTION_ERROR_ACTION(m); + } +} + +/* ---------------------------- malloc --------------------------- */ + +/* allocate a large request from the best fitting chunk in a treebin */ +static void* tmalloc_large(mstate m, size_t nb) { + tchunkptr v = 0; + size_t rsize = -nb; /* Unsigned negation */ + tchunkptr t; + bindex_t idx; + compute_tree_index(nb, idx); + if ((t = *treebin_at(m, idx)) != 0) { + /* Traverse tree for this bin looking for node with size == nb */ + size_t sizebits = nb << leftshift_for_tree_index(idx); + tchunkptr rst = 0; /* The deepest untaken right subtree */ + for (;;) { + tchunkptr rt; + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + v = t; + if ((rsize = trem) == 0) + break; + } + rt = t->child[1]; + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + if (rt != 0 && rt != t) + rst = rt; + if (t == 0) { + t = rst; /* set t to least subtree holding sizes > nb */ + break; + } + sizebits <<= 1; + } + } + if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ + binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; + if (leftbits != 0) { + bindex_t i; + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + t = *treebin_at(m, i); + } + } + + while (t != 0) { /* find smallest of tree or subtree */ + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + t = leftmost_child(t); + } + + /* If dv is a better fit, return 0 so malloc will use it */ + if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { + if (RTCHECK(ok_address(m, v))) { /* split */ + mchunkptr r = chunk_plus_offset(v, nb); + assert(chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + insert_chunk(m, r, rsize); + } + return chunk2mem(v); + } + } + CORRUPTION_ERROR_ACTION(m); + } + return 0; +} + +/* allocate a small request from the best fitting chunk in a treebin */ +static void* tmalloc_small(mstate m, size_t nb) { + tchunkptr t, v; + size_t rsize; + bindex_t i; + binmap_t leastbit = least_bit(m->treemap); + compute_bit2idx(leastbit, i); + v = t = *treebin_at(m, i); + rsize = chunksize(t) - nb; + + while ((t = leftmost_child(t)) != 0) { + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + } + + if (RTCHECK(ok_address(m, v))) { + mchunkptr r = chunk_plus_offset(v, nb); + assert(chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(m, r, rsize); + } + return chunk2mem(v); + } + } + + CORRUPTION_ERROR_ACTION(m); + return 0; +} + +#if !ONLY_MSPACES + +void* dlmalloc(size_t bytes) { + /* + Basic algorithm: + If a small request (< 256 bytes minus per-chunk overhead): + 1. If one exists, use a remainderless chunk in associated smallbin. + (Remainderless means that there are too few excess bytes to + represent as a chunk.) + 2. If it is big enough, use the dv chunk, which is normally the + chunk adjacent to the one used for the most recent small request. + 3. If one exists, split the smallest available chunk in a bin, + saving remainder in dv. + 4. If it is big enough, use the top chunk. + 5. If available, get memory from system and use it + Otherwise, for a large request: + 1. Find the smallest available binned chunk that fits, and use it + if it is better fitting than dv chunk, splitting if necessary. + 2. If better fitting than any binned chunk, use the dv chunk. + 3. If it is big enough, use the top chunk. + 4. If request size >= mmap threshold, try to directly mmap this chunk. + 5. If available, get memory from system and use it + + The ugly goto's here ensure that postaction occurs along all paths. + */ + +#if USE_LOCKS + ensure_initialization(); /* initialize in sys_alloc if not using locks */ +#endif + + if (!PREACTION(gm)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = gm->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(gm, idx); + p = b->fd; + assert(chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(gm, b, p, idx); + set_inuse_and_pinuse(gm, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (nb > gm->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(gm, i); + p = b->fd; + assert(chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(gm, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(gm, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(gm, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + } + + if (nb <= gm->dvsize) { + size_t rsize = gm->dvsize - nb; + mchunkptr p = gm->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = gm->dv = chunk_plus_offset(p, nb); + gm->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + } + else { /* exhaust dv */ + size_t dvs = gm->dvsize; + gm->dvsize = 0; + gm->dv = 0; + set_inuse_and_pinuse(gm, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (nb < gm->topsize) { /* Split top */ + size_t rsize = gm->topsize -= nb; + mchunkptr p = gm->top; + mchunkptr r = gm->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + mem = chunk2mem(p); + check_top_chunk(gm, gm->top); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + mem = sys_alloc(gm, nb); + + postaction: + POSTACTION(gm); + return mem; + } + + return 0; +} + +/* ---------------------------- free --------------------------- */ + +void dlfree(void* mem) { + /* + Consolidate freed chunks with preceeding or succeeding bordering + free chunks, if they exist, and then place in a bin. Intermixed + with special cases for top, dv, mmapped chunks, and usage errors. + */ + + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } +#else /* FOOTERS */ +#define fm gm +#endif /* FOOTERS */ + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + fm->footprint -= psize; + goto postaction; + } + else { + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + if (should_trim(fm, tsize)) + sys_trim(fm, 0); + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + + if (is_small(psize)) { + insert_small_chunk(fm, p, psize); + check_free_chunk(fm, p); + } + else { + tchunkptr tp = (tchunkptr)p; + insert_large_chunk(fm, tp, psize); + check_free_chunk(fm, p); + if (--fm->release_checks == 0) + release_unused_segments(fm); + } + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +#if !FOOTERS +#undef fm +#endif /* FOOTERS */ +} + +void* dlcalloc(size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = dlmalloc(req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + memset(mem, 0, req); + return mem; +} + +#endif /* !ONLY_MSPACES */ + +/* ------------ Internal support for realloc, memalign, etc -------------- */ + +/* Try to realloc; only in-place unless can_move true */ +static mchunkptr try_realloc_chunk(mstate m, mchunkptr p, size_t nb, + int can_move) { + mchunkptr newp = 0; + size_t oldsize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, oldsize); + if (RTCHECK(ok_address(m, p) && ok_inuse(p) && + ok_next(p, next) && ok_pinuse(next))) { + if (is_mmapped(p)) { + newp = mmap_resize(m, p, nb, can_move); + } + else if (oldsize >= nb) { /* already big enough */ + size_t rsize = oldsize - nb; + if (rsize >= MIN_CHUNK_SIZE) { /* split off remainder */ + mchunkptr r = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, r, rsize); + dispose_chunk(m, r, rsize); + } + newp = p; + } + else if (next == m->top) { /* extend into top */ + if (oldsize + m->topsize > nb) { + size_t newsize = oldsize + m->topsize; + size_t newtopsize = newsize - nb; + mchunkptr newtop = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + newtop->head = newtopsize |PINUSE_BIT; + m->top = newtop; + m->topsize = newtopsize; + newp = p; + } + } + else if (next == m->dv) { /* extend into dv */ + size_t dvs = m->dvsize; + if (oldsize + dvs >= nb) { + size_t dsize = oldsize + dvs - nb; + if (dsize >= MIN_CHUNK_SIZE) { + mchunkptr r = chunk_plus_offset(p, nb); + mchunkptr n = chunk_plus_offset(r, dsize); + set_inuse(m, p, nb); + set_size_and_pinuse_of_free_chunk(r, dsize); + clear_pinuse(n); + m->dvsize = dsize; + m->dv = r; + } + else { /* exhaust dv */ + size_t newsize = oldsize + dvs; + set_inuse(m, p, newsize); + m->dvsize = 0; + m->dv = 0; + } + newp = p; + } + } + else if (!cinuse(next)) { /* extend into next free chunk */ + size_t nextsize = chunksize(next); + if (oldsize + nextsize >= nb) { + size_t rsize = oldsize + nextsize - nb; + unlink_chunk(m, next, nextsize); + if (rsize < MIN_CHUNK_SIZE) { + size_t newsize = oldsize + nextsize; + set_inuse(m, p, newsize); + } + else { + mchunkptr r = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, r, rsize); + dispose_chunk(m, r, rsize); + } + newp = p; + } + } + } + else { + USAGE_ERROR_ACTION(m, oldmem); + } + return newp; +} + +static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ + alignment = MIN_CHUNK_SIZE; + if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ + size_t a = MALLOC_ALIGNMENT << 1; + while (a < alignment) a <<= 1; + alignment = a; + } + if (bytes >= MAX_REQUEST - alignment) { + if (m != 0) { /* Test isn't needed but avoids compiler warning */ + MALLOC_FAILURE_ACTION; + } + } + else { + size_t nb = request2size(bytes); + size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; + mem = internal_malloc(m, req); + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (PREACTION(m)) + return 0; + if ((((size_t)(mem)) & (alignment - 1)) != 0) { /* misaligned */ + /* + Find an aligned spot inside chunk. Since we need to give + back leading space in a chunk of at least MIN_CHUNK_SIZE, if + the first calculation places us at a spot with less than + MIN_CHUNK_SIZE leader, we can move to the next aligned spot. + We've allocated enough total room so that this is always + possible. + */ + char* br = (char*)mem2chunk((size_t)(((size_t)((char*)mem + alignment - + SIZE_T_ONE)) & + -alignment)); + char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? + br : br+alignment; + mchunkptr newp = (mchunkptr)pos; + size_t leadsize = pos - (char*)(p); + size_t newsize = chunksize(p) - leadsize; + + if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ + newp->prev_foot = p->prev_foot + leadsize; + newp->head = newsize; + } + else { /* Otherwise, give back leader, use the rest */ + set_inuse(m, newp, newsize); + set_inuse(m, p, leadsize); + dispose_chunk(m, p, leadsize); + } + p = newp; + } + + /* Give back spare room at the end */ + if (!is_mmapped(p)) { + size_t size = chunksize(p); + if (size > nb + MIN_CHUNK_SIZE) { + size_t remainder_size = size - nb; + mchunkptr remainder = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, remainder, remainder_size); + dispose_chunk(m, remainder, remainder_size); + } + } + + mem = chunk2mem(p); + assert (chunksize(p) >= nb); + assert(((size_t)mem & (alignment - 1)) == 0); + check_inuse_chunk(m, p); + POSTACTION(m); + } + } + return mem; +} + +/* + Common support for independent_X routines, handling + all of the combinations that can result. + The opts arg has: + bit 0 set if all elements are same size (using sizes[0]) + bit 1 set if elements should be zeroed +*/ +static void** ialloc(mstate m, + size_t n_elements, + size_t* sizes, + int opts, + void* chunks[]) { + + size_t element_size; /* chunksize of each element, if all same */ + size_t contents_size; /* total size of elements */ + size_t array_size; /* request size of pointer array */ + void* mem; /* malloced aggregate space */ + mchunkptr p; /* corresponding chunk */ + size_t remainder_size; /* remaining bytes while splitting */ + void** marray; /* either "chunks" or malloced ptr array */ + mchunkptr array_chunk; /* chunk for malloced ptr array */ + flag_t was_enabled; /* to disable mmap */ + size_t size; + size_t i; + + ensure_initialization(); + /* compute array length, if needed */ + if (chunks != 0) { + if (n_elements == 0) + return chunks; /* nothing to do */ + marray = chunks; + array_size = 0; + } + else { + /* if empty req, must still return chunk representing empty array */ + if (n_elements == 0) + return (void**)internal_malloc(m, 0); + marray = 0; + array_size = request2size(n_elements * (sizeof(void*))); + } + + /* compute total element size */ + if (opts & 0x1) { /* all-same-size */ + element_size = request2size(*sizes); + contents_size = n_elements * element_size; + } + else { /* add up all the sizes */ + element_size = 0; + contents_size = 0; + for (i = 0; i != n_elements; ++i) + contents_size += request2size(sizes[i]); + } + + size = contents_size + array_size; + + /* + Allocate the aggregate chunk. First disable direct-mmapping so + malloc won't use it, since we would not be able to later + free/realloc space internal to a segregated mmap region. + */ + was_enabled = use_mmap(m); + disable_mmap(m); + mem = internal_malloc(m, size - CHUNK_OVERHEAD); + if (was_enabled) + enable_mmap(m); + if (mem == 0) + return 0; + + if (PREACTION(m)) return 0; + p = mem2chunk(mem); + remainder_size = chunksize(p); + + assert(!is_mmapped(p)); + + if (opts & 0x2) { /* optionally clear the elements */ + memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); + } + + /* If not provided, allocate the pointer array as final part of chunk */ + if (marray == 0) { + size_t array_chunk_size; + array_chunk = chunk_plus_offset(p, contents_size); + array_chunk_size = remainder_size - contents_size; + marray = (void**) (chunk2mem(array_chunk)); + set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); + remainder_size = contents_size; + } + + /* split out elements */ + for (i = 0; ; ++i) { + marray[i] = chunk2mem(p); + if (i != n_elements-1) { + if (element_size != 0) + size = element_size; + else + size = request2size(sizes[i]); + remainder_size -= size; + set_size_and_pinuse_of_inuse_chunk(m, p, size); + p = chunk_plus_offset(p, size); + } + else { /* the final element absorbs any overallocation slop */ + set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); + break; + } + } + +#if DEBUG + if (marray != chunks) { + /* final element must have exactly exhausted chunk */ + if (element_size != 0) { + assert(remainder_size == element_size); + } + else { + assert(remainder_size == request2size(sizes[i])); + } + check_inuse_chunk(m, mem2chunk(marray)); + } + for (i = 0; i != n_elements; ++i) + check_inuse_chunk(m, mem2chunk(marray[i])); + +#endif /* DEBUG */ + + POSTACTION(m); + return marray; +} + +/* Try to free all pointers in the given array. + Note: this could be made faster, by delaying consolidation, + at the price of disabling some user integrity checks, We + still optimize some consolidations by combining adjacent + chunks before freeing, which will occur often if allocated + with ialloc or the array is sorted. +*/ +static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) { + size_t unfreed = 0; + if (!PREACTION(m)) { + void** a; + void** fence = &(array[nelem]); + for (a = array; a != fence; ++a) { + void* mem = *a; + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t psize = chunksize(p); +#if FOOTERS + if (get_mstate_for(p) != m) { + ++unfreed; + continue; + } +#endif + check_inuse_chunk(m, p); + *a = 0; + if (RTCHECK(ok_address(m, p) && ok_inuse(p))) { + void ** b = a + 1; /* try to merge with next chunk */ + mchunkptr next = next_chunk(p); + if (b != fence && *b == chunk2mem(next)) { + size_t newsize = chunksize(next) + psize; + set_inuse(m, p, newsize); + *b = chunk2mem(p); + } + else + dispose_chunk(m, p, psize); + } + else { + CORRUPTION_ERROR_ACTION(m); + break; + } + } + } + if (should_trim(m, m->topsize)) + sys_trim(m, 0); + POSTACTION(m); + } + return unfreed; +} + +/* Traversal */ +#if MALLOC_INSPECT_ALL +static void internal_inspect_all(mstate m, + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + if (is_initialized(m)) { + mchunkptr top = m->top; + msegmentptr s; + for (s = &m->seg; s != 0; s = s->next) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && q->head != FENCEPOST_HEAD) { + mchunkptr next = next_chunk(q); + size_t sz = chunksize(q); + size_t used; + void* start; + if (is_inuse(q)) { + used = sz - CHUNK_OVERHEAD; /* must not be mmapped */ + start = chunk2mem(q); + } + else { + used = 0; + if (is_small(sz)) { /* offset by possible bookkeeping */ + start = (void*)((char*)q + sizeof(malloc_chunk)); + } + else { + start = (void*)((char*)q + sizeof(malloc_tree_chunk)); + } + } + if (start < (void*)next) /* skip if all space is bookkeeping */ + handler(start, next, used, arg); + if (q == top) + break; + q = next; + } + } + } +} +#endif /* MALLOC_INSPECT_ALL */ + +/* ------------------ Exported realloc, memalign, etc -------------------- */ + +#if !ONLY_MSPACES + +void* dlrealloc(void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem == 0) { + mem = dlmalloc(bytes); + } + else if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } +#ifdef REALLOC_ZERO_BYTES_FREES + else if (bytes == 0) { + dlfree(oldmem); + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = gm; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); + POSTACTION(m); + if (newp != 0) { + check_inuse_chunk(m, newp); + mem = chunk2mem(newp); + } + else { + mem = internal_malloc(m, bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); + internal_free(m, oldmem); + } + } + } + } + return mem; +} + +void* dlrealloc_in_place(void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem != 0) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = gm; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); + POSTACTION(m); + if (newp == oldp) { + check_inuse_chunk(m, newp); + mem = oldmem; + } + } + } + } + return mem; +} + +void* dlmemalign(size_t alignment, size_t bytes) { + if (alignment <= MALLOC_ALIGNMENT) { + return dlmalloc(bytes); + } + return internal_memalign(gm, alignment, bytes); +} + +int dlposix_memalign(void** pp, size_t alignment, size_t bytes) { + void* mem = 0; + if (alignment == MALLOC_ALIGNMENT) + mem = dlmalloc(bytes); + else { + size_t d = alignment / sizeof(void*); + size_t r = alignment % sizeof(void*); + if (r != 0 || d == 0 || (d & (d-SIZE_T_ONE)) != 0) + return EINVAL; + else if (bytes >= MAX_REQUEST - alignment) { + if (alignment < MIN_CHUNK_SIZE) + alignment = MIN_CHUNK_SIZE; + mem = internal_memalign(gm, alignment, bytes); + } + } + if (mem == 0) + return ENOMEM; + else { + *pp = mem; + return 0; + } +} + +void* dlvalloc(size_t bytes) { + size_t pagesz; + ensure_initialization(); + pagesz = mparams.page_size; + return dlmemalign(pagesz, bytes); +} + +void* dlpvalloc(size_t bytes) { + size_t pagesz; + ensure_initialization(); + pagesz = mparams.page_size; + return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); +} + +void** dlindependent_calloc(size_t n_elements, size_t elem_size, + void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + return ialloc(gm, n_elements, &sz, 3, chunks); +} + +void** dlindependent_comalloc(size_t n_elements, size_t sizes[], + void* chunks[]) { + return ialloc(gm, n_elements, sizes, 0, chunks); +} + +size_t dlbulk_free(void* array[], size_t nelem) { + return internal_bulk_free(gm, array, nelem); +} + +#if MALLOC_INSPECT_ALL +void dlmalloc_inspect_all(void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + ensure_initialization(); + if (!PREACTION(gm)) { + internal_inspect_all(gm, handler, arg); + POSTACTION(gm); + } +} +#endif /* MALLOC_INSPECT_ALL */ + +int dlmalloc_trim(size_t pad) { + int result = 0; + ensure_initialization(); + if (!PREACTION(gm)) { + result = sys_trim(gm, pad); + POSTACTION(gm); + } + return result; +} + +size_t dlmalloc_footprint(void) { + return gm->footprint; +} + +size_t dlmalloc_max_footprint(void) { + return gm->max_footprint; +} + +size_t dlmalloc_footprint_limit(void) { + size_t maf = gm->footprint_limit; + return maf == 0 ? MAX_SIZE_T : maf; +} + +size_t dlmalloc_set_footprint_limit(size_t bytes) { + size_t result; /* invert sense of 0 */ + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ + if (bytes == MAX_SIZE_T) + result = 0; /* disable */ + else + result = granularity_align(bytes); + return gm->footprint_limit = result; +} + +#if !NO_MALLINFO +struct mallinfo dlmallinfo(void) { + return internal_mallinfo(gm); +} +#endif /* NO_MALLINFO */ + +#if !NO_MALLOC_STATS +void dlmalloc_stats() { + internal_malloc_stats(gm); +} +#endif /* NO_MALLOC_STATS */ + +int dlmallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + +size_t dlmalloc_usable_size(void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + +#endif /* !ONLY_MSPACES */ + +/* ----------------------------- user mspaces ---------------------------- */ + +#if MSPACES + +static mstate init_user_mstate(char* tbase, size_t tsize) { + size_t msize = pad_request(sizeof(struct malloc_state)); + mchunkptr mn; + mchunkptr msp = align_as_chunk(tbase); + mstate m = (mstate)(chunk2mem(msp)); + memset(m, 0, msize); + (void)INITIAL_LOCK(&m->mutex); + msp->head = (msize|INUSE_BITS); + m->seg.base = m->least_addr = tbase; + m->seg.size = m->footprint = m->max_footprint = tsize; + m->magic = mparams.magic; + m->release_checks = MAX_RELEASE_CHECK_RATE; + m->mflags = mparams.default_mflags; + m->extp = 0; + m->exts = 0; + disable_contiguous(m); + init_bins(m); + mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); + check_top_chunk(m, m->top); + return m; +} + +mspace create_mspace(size_t capacity, int locked) { + mstate m = 0; + size_t msize; + ensure_initialization(); + msize = pad_request(sizeof(struct malloc_state)); + if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + size_t rs = ((capacity == 0)? mparams.granularity : + (capacity + TOP_FOOT_SIZE + msize)); + size_t tsize = granularity_align(rs); + char* tbase = (char*)(CALL_MMAP(tsize)); + if (tbase != CMFAIL) { + m = init_user_mstate(tbase, tsize); + m->seg.sflags = USE_MMAP_BIT; + set_lock(m, locked); + } + } + return (mspace)m; +} + +mspace create_mspace_with_base(void* base, size_t capacity, int locked) { + mstate m = 0; + size_t msize; + ensure_initialization(); + msize = pad_request(sizeof(struct malloc_state)); + if (capacity > msize + TOP_FOOT_SIZE && + capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + m = init_user_mstate((char*)base, capacity); + m->seg.sflags = EXTERN_BIT; + set_lock(m, locked); + } + return (mspace)m; +} + +int mspace_track_large_chunks(mspace msp, int enable) { + int ret = 0; + mstate ms = (mstate)msp; + if (!PREACTION(ms)) { + if (!use_mmap(ms)) + ret = 1; + if (!enable) + enable_mmap(ms); + else + disable_mmap(ms); + POSTACTION(ms); + } + return ret; +} + +size_t destroy_mspace(mspace msp) { + size_t freed = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + msegmentptr sp = &ms->seg; + (void)DESTROY_LOCK(&ms->mutex); /* destroy before unmapped */ + while (sp != 0) { + char* base = sp->base; + size_t size = sp->size; + flag_t flag = sp->sflags; + sp = sp->next; + if ((flag & USE_MMAP_BIT) && !(flag & EXTERN_BIT) && + CALL_MUNMAP(base, size) == 0) + freed += size; + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return freed; +} + +/* + mspace versions of routines are near-clones of the global + versions. This is not so nice but better than the alternatives. +*/ + +void* mspace_malloc(mspace msp, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (!PREACTION(ms)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = ms->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(ms, idx); + p = b->fd; + assert(chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(ms, b, p, idx); + set_inuse_and_pinuse(ms, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb > ms->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(ms, i); + p = b->fd; + assert(chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(ms, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(ms, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(ms, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + + if (nb <= ms->dvsize) { + size_t rsize = ms->dvsize - nb; + mchunkptr p = ms->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = ms->dv = chunk_plus_offset(p, nb); + ms->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + } + else { /* exhaust dv */ + size_t dvs = ms->dvsize; + ms->dvsize = 0; + ms->dv = 0; + set_inuse_and_pinuse(ms, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb < ms->topsize) { /* Split top */ + size_t rsize = ms->topsize -= nb; + mchunkptr p = ms->top; + mchunkptr r = ms->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + mem = chunk2mem(p); + check_top_chunk(ms, ms->top); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + mem = sys_alloc(ms, nb); + + postaction: + POSTACTION(ms); + return mem; + } + + return 0; +} + +void mspace_free(mspace msp, void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); + (void)msp; /* placate people compiling -Wunused */ +#else /* FOOTERS */ + mstate fm = (mstate)msp; +#endif /* FOOTERS */ + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_inuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + if (is_mmapped(p)) { + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + fm->footprint -= psize; + goto postaction; + } + else { + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + if (should_trim(fm, tsize)) + sys_trim(fm, 0); + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + + if (is_small(psize)) { + insert_small_chunk(fm, p, psize); + check_free_chunk(fm, p); + } + else { + tchunkptr tp = (tchunkptr)p; + insert_large_chunk(fm, tp, psize); + check_free_chunk(fm, p); + if (--fm->release_checks == 0) + release_unused_segments(fm); + } + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +} + +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = internal_malloc(ms, req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + memset(mem, 0, req); + return mem; +} + +void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem == 0) { + mem = mspace_malloc(msp, bytes); + } + else if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } +#ifdef REALLOC_ZERO_BYTES_FREES + else if (bytes == 0) { + mspace_free(msp, oldmem); + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = (mstate)msp; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 1); + POSTACTION(m); + if (newp != 0) { + check_inuse_chunk(m, newp); + mem = chunk2mem(newp); + } + else { + mem = mspace_malloc(m, bytes); + if (mem != 0) { + size_t oc = chunksize(oldp) - overhead_for(oldp); + memcpy(mem, oldmem, (oc < bytes)? oc : bytes); + mspace_free(m, oldmem); + } + } + } + } + return mem; +} + +void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes) { + void* mem = 0; + if (oldmem != 0) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + } + else { + size_t nb = request2size(bytes); + mchunkptr oldp = mem2chunk(oldmem); +#if ! FOOTERS + mstate m = (mstate)msp; +#else /* FOOTERS */ + mstate m = get_mstate_for(oldp); + (void)msp; /* placate people compiling -Wunused */ + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + if (!PREACTION(m)) { + mchunkptr newp = try_realloc_chunk(m, oldp, nb, 0); + POSTACTION(m); + if (newp == oldp) { + check_inuse_chunk(m, newp); + mem = oldmem; + } + } + } + } + return mem; +} + +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (alignment <= MALLOC_ALIGNMENT) + return mspace_malloc(msp, bytes); + return internal_memalign(ms, alignment, bytes); +} + +void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return ialloc(ms, n_elements, &sz, 3, chunks); +} + +void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return ialloc(ms, n_elements, sizes, 0, chunks); +} + +size_t mspace_bulk_free(mspace msp, void* array[], size_t nelem) { + return internal_bulk_free((mstate)msp, array, nelem); +} + +#if MALLOC_INSPECT_ALL +void mspace_inspect_all(mspace msp, + void(*handler)(void *start, + void *end, + size_t used_bytes, + void* callback_arg), + void* arg) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (!PREACTION(ms)) { + internal_inspect_all(ms, handler, arg); + POSTACTION(ms); + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} +#endif /* MALLOC_INSPECT_ALL */ + +int mspace_trim(mspace msp, size_t pad) { + int result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (!PREACTION(ms)) { + result = sys_trim(ms, pad); + POSTACTION(ms); + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +#if !NO_MALLOC_STATS +void mspace_malloc_stats(mspace msp) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + internal_malloc_stats(ms); + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} +#endif /* NO_MALLOC_STATS */ + +size_t mspace_footprint(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->footprint; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_max_footprint(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->max_footprint; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_footprint_limit(mspace msp) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + size_t maf = ms->footprint_limit; + result = (maf == 0) ? MAX_SIZE_T : maf; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +size_t mspace_set_footprint_limit(mspace msp, size_t bytes) { + size_t result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (bytes == 0) + result = granularity_align(1); /* Use minimal size */ + if (bytes == MAX_SIZE_T) + result = 0; /* disable */ + else + result = granularity_align(bytes); + ms->footprint_limit = result; + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +#if !NO_MALLINFO +struct mallinfo mspace_mallinfo(mspace msp) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + } + return internal_mallinfo(ms); +} +#endif /* NO_MALLINFO */ + +size_t mspace_usable_size(void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (is_inuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + +int mspace_mallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + +#endif /* MSPACES */ + + +/* -------------------- Alternative MORECORE functions ------------------- */ + +/* + Guidelines for creating a custom version of MORECORE: + + * For best performance, MORECORE should allocate in multiples of pagesize. + * MORECORE may allocate more memory than requested. (Or even less, + but this will usually result in a malloc failure.) + * MORECORE must not allocate memory when given argument zero, but + instead return one past the end address of memory from previous + nonzero call. + * For best performance, consecutive calls to MORECORE with positive + arguments should return increasing addresses, indicating that + space has been contiguously extended. + * Even though consecutive calls to MORECORE need not return contiguous + addresses, it must be OK for malloc'ed chunks to span multiple + regions in those cases where they do happen to be contiguous. + * MORECORE need not handle negative arguments -- it may instead + just return MFAIL when given negative arguments. + Negative arguments are always multiples of pagesize. MORECORE + must not misinterpret negative args as large positive unsigned + args. You can suppress all such calls from even occurring by defining + MORECORE_CANNOT_TRIM, + + As an example alternative MORECORE, here is a custom allocator + kindly contributed for pre-OSX macOS. It uses virtually but not + necessarily physically contiguous non-paged memory (locked in, + present and won't get swapped out). You can use it by uncommenting + this section, adding some #includes, and setting up the appropriate + defines above: + + #define MORECORE osMoreCore + + There is also a shutdown routine that should somehow be called for + cleanup upon program exit. + + #define MAX_POOL_ENTRIES 100 + #define MINIMUM_MORECORE_SIZE (64 * 1024U) + static int next_os_pool; + void *our_os_pools[MAX_POOL_ENTRIES]; + + void *osMoreCore(int size) + { + void *ptr = 0; + static void *sbrk_top = 0; + + if (size > 0) + { + if (size < MINIMUM_MORECORE_SIZE) + size = MINIMUM_MORECORE_SIZE; + if (CurrentExecutionLevel() == kTaskLevel) + ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); + if (ptr == 0) + { + return (void *) MFAIL; + } + // save ptrs so they can be freed during cleanup + our_os_pools[next_os_pool] = ptr; + next_os_pool++; + ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); + sbrk_top = (char *) ptr + size; + return ptr; + } + else if (size < 0) + { + // we don't currently support shrink behavior + return (void *) MFAIL; + } + else + { + return sbrk_top; + } + } + + // cleanup any allocated memory pools + // called as last thing before shutting down driver + + void osCleanupMem(void) + { + void **ptr; + + for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) + if (*ptr) + { + PoolDeallocate(*ptr); + *ptr = 0; + } + } + +*/ + + +/* ----------------------------------------------------------------------- +History: + v2.8.5 Sun May 22 10:26:02 2011 Doug Lea (dl at gee) + * Always perform unlink checks unless INSECURE + * Add posix_memalign. + * Improve realloc to expand in more cases; expose realloc_in_place. + Thanks to Peter Buhr for the suggestion. + * Add footprint_limit, inspect_all, bulk_free. Thanks + to Barry Hayes and others for the suggestions. + * Internal refactorings to avoid calls while holding locks + * Use non-reentrant locks by default. Thanks to Roland McGrath + for the suggestion. + * Small fixes to mspace_destroy, reset_on_error. + * Various configuration extensions/changes. Thanks + to all who contributed these. + + V2.8.4a Thu Apr 28 14:39:43 2011 (dl at gee.cs.oswego.edu) + * Update Creative Commons URL + + V2.8.4 Wed May 27 09:56:23 2009 Doug Lea (dl at gee) + * Use zeros instead of prev foot for is_mmapped + * Add mspace_track_large_chunks; thanks to Jean Brouwers + * Fix set_inuse in internal_realloc; thanks to Jean Brouwers + * Fix insufficient sys_alloc padding when using 16byte alignment + * Fix bad error check in mspace_footprint + * Adaptations for ptmalloc; thanks to Wolfram Gloger. + * Reentrant spin locks; thanks to Earl Chew and others + * Win32 improvements; thanks to Niall Douglas and Earl Chew + * Add NO_SEGMENT_TRAVERSAL and MAX_RELEASE_CHECK_RATE options + * Extension hook in malloc_state + * Various small adjustments to reduce warnings on some compilers + * Various configuration extensions/changes for more platforms. Thanks + to all who contributed these. + + V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) + * Add max_footprint functions + * Ensure all appropriate literals are size_t + * Fix conditional compilation problem for some #define settings + * Avoid concatenating segments with the one provided + in create_mspace_with_base + * Rename some variables to avoid compiler shadowing warnings + * Use explicit lock initialization. + * Better handling of sbrk interference. + * Simplify and fix segment insertion, trimming and mspace_destroy + * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x + * Thanks especially to Dennis Flanagan for help on these. + + V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) + * Fix memalign brace error. + + V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) + * Fix improper #endif nesting in C++ + * Add explicit casts needed for C++ + + V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) + * Use trees for large bins + * Support mspaces + * Use segments to unify sbrk-based and mmap-based system allocation, + removing need for emulation on most platforms without sbrk. + * Default safety checks + * Optional footer checks. Thanks to William Robertson for the idea. + * Internal code refactoring + * Incorporate suggestions and platform-specific changes. + Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, + Aaron Bachmann, Emery Berger, and others. + * Speed up non-fastbin processing enough to remove fastbins. + * Remove useless cfree() to avoid conflicts with other apps. + * Remove internal memcpy, memset. Compilers handle builtins better. + * Remove some options that no one ever used and rename others. + + V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + * Fix malloc_state bitmap array misdeclaration + + V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) + * Allow tuning of FIRST_SORTED_BIN_SIZE + * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. + * Better detection and support for non-contiguousness of MORECORE. + Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger + * Bypass most of malloc if no frees. Thanks To Emery Berger. + * Fix freeing of old top non-contiguous chunk im sysmalloc. + * Raised default trim and map thresholds to 256K. + * Fix mmap-related #defines. Thanks to Lubos Lunak. + * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. + * Branch-free bin calculation + * Default trim and mmap thresholds now 256K. + + V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) + * Introduce independent_comalloc and independent_calloc. + Thanks to Michael Pachos for motivation and help. + * Make optional .h file available + * Allow > 2GB requests on 32bit systems. + * new WIN32 sbrk, mmap, munmap, lock code from . + Thanks also to Andreas Mueller , + and Anonymous. + * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for + helping test this.) + * memalign: check alignment arg + * realloc: don't try to shift chunks backwards, since this + leads to more fragmentation in some programs and doesn't + seem to help in any others. + * Collect all cases in malloc requiring system memory into sysmalloc + * Use mmap as backup to sbrk + * Place all internal state in malloc_state + * Introduce fastbins (although similar to 2.5.1) + * Many minor tunings and cosmetic improvements + * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK + * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS + Thanks to Tony E. Bennett and others. + * Include errno.h to support default failure action. + + V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) + * return null for negative arguments + * Added Several WIN32 cleanups from Martin C. Fong + * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' + (e.g. WIN32 platforms) + * Cleanup header file inclusion for WIN32 platforms + * Cleanup code to avoid Microsoft Visual C++ compiler complaints + * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing + memory allocation routines + * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) + * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to + usage of 'assert' in non-WIN32 code + * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to + avoid infinite loop + * Always call 'fREe()' rather than 'free()' + + V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) + * Fixed ordering problem with boundary-stamping + + V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) + * Added pvalloc, as recommended by H.J. Liu + * Added 64bit pointer support mainly from Wolfram Gloger + * Added anonymously donated WIN32 sbrk emulation + * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen + * malloc_extend_top: fix mask error that caused wastage after + foreign sbrks + * Add linux mremap support code from HJ Liu + + V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) + * Integrated most documentation with the code. + * Add support for mmap, with help from + Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Use last_remainder in more cases. + * Pack bins using idea from colin@nyx10.cs.du.edu + * Use ordered bins instead of best-fit threshhold + * Eliminate block-local decls to simplify tracing and debugging. + * Support another case of realloc via move into top + * Fix error occuring when initial sbrk_base not word-aligned. + * Rely on page size for units instead of SBRK_UNIT to + avoid surprises about sbrk alignment conventions. + * Add mallinfo, mallopt. Thanks to Raymond Nijssen + (raymond@es.ele.tue.nl) for the suggestion. + * Add `pad' argument to malloc_trim and top_pad mallopt parameter. + * More precautions for cases where other routines call sbrk, + courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Added macros etc., allowing use in linux libc from + H.J. Lu (hjl@gnu.ai.mit.edu) + * Inverted this history list + + V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) + * Re-tuned and fixed to behave more nicely with V2.6.0 changes. + * Removed all preallocation code since under current scheme + the work required to undo bad preallocations exceeds + the work saved in good cases for most test programs. + * No longer use return list or unconsolidated bins since + no scheme using them consistently outperforms those that don't + given above changes. + * Use best fit for very large chunks to prevent some worst-cases. + * Added some support for debugging + + V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) + * Removed footers when chunks are in use. Thanks to + Paul Wilson (wilson@cs.texas.edu) for the suggestion. + + V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) + * Added malloc_trim, with help from Wolfram Gloger + (wmglo@Dent.MED.Uni-Muenchen.DE). + + V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) + + V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) + * realloc: try to expand in both directions + * malloc: swap order of clean-bin strategy; + * realloc: only conditionally expand backwards + * Try not to scavenge used bins + * Use bin counts as a guide to preallocation + * Occasionally bin return list chunks in first scan + * Add a few optimizations from colin@nyx10.cs.du.edu + + V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) + * faster bin computation & slightly different binning + * merged all consolidations to one part of malloc proper + (eliminating old malloc_find_space & malloc_clean_bin) + * Scan 2 returns chunks (not just 1) + * Propagate failure in realloc if malloc returns 0 + * Add stuff to allow compilation on non-ANSI compilers + from kpv@research.att.com + + V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) + * removed potential for odd address access in prev_chunk + * removed dependency on getpagesize.h + * misc cosmetics and a bit more internal documentation + * anticosmetics: mangled names in macros to evade debugger strangeness + * tested on sparc, hp-700, dec-mips, rs6000 + with gcc & native cc (hp, dec only) allowing + Detlefs & Zorn comparison study (in SIGPLAN Notices.) + + Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) + * Based loosely on libg++-1.2X malloc. (It retains some of the overall + structure of old version, but most details differ.) + +*/ + diff --git a/mcexecution.cc b/mcexecution.cc new file mode 100644 index 0000000..1166731 --- /dev/null +++ b/mcexecution.cc @@ -0,0 +1,1012 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "mcexecution.h" +#include "mcschedule.h" +#include "planner.h" +#include +#include "cgoal.h" +#include "change.h" +#include "mcutil.h" +#include "model.h" +#include +#include +#include +#include "constgen.h" + +MCExecution_snapshot::MCExecution_snapshot() : + next_thread_id(0) +{ +} + +MCExecution_snapshot::~MCExecution_snapshot() { +} + + +MCExecution::MCExecution() : + EPTable(new EPHashTable()), + EPValueTable(new EPValueHashTable()), + memtable(new MemHashTable()), + storetable(new StoreLoadHashTable()), + loadtable(new StoreLoadHashTable()), + EPList(new SnapVector()), + ThreadList(new SnapVector()), + ExecPointList(new SnapVector()), + CurrBranchList(new SnapVector()), + currexecpoint(NULL), + scheduler(new MCScheduler(this)), + planner(new Planner(this)), + snap_fields(new MCExecution_snapshot()), + curr_thread(NULL), + currbranch(NULL), + eprecorddep(new EPRecordDepHashTable()), + revrecorddep(new RevDepHashTable()), + alwaysexecuted(new ModelVector()), + lastloopexit(new ModelVector()), + joinvec(new ModelVector()), + sharedgoals(new ModelVector()), + sharedfuncrecords(new ModelVector()), + currid(MCID_INIT), + schedule_graph(0) +{ + EPList->push_back(NULL);//avoid using MCID of 0 +#ifdef TSO + storebuffer = new SnapVector *>(); +#endif +} + +MCExecution::~MCExecution() { + reset(); + delete EPTable; + delete EPValueTable; + delete memtable; + delete EPList; + delete ThreadList; + delete ExecPointList; + delete scheduler; + delete snap_fields; + delete eprecorddep; + delete revrecorddep; + delete joinvec; + delete alwaysexecuted; + delete lastloopexit; +#ifdef TSO + for(uint i=0;isize();i++) { + SnapList *list=(*storebuffer)[i]; + if (list != NULL) + delete list; + } + delete storebuffer; +#endif + for(uint i=0;isize();i++) { + CGoalSet *c=(*sharedgoals)[i]; + if (c != NULL) + delete c; + } + delete sharedgoals; + for(uint i=0;isize();i++) { + RecordSet *rs=(*sharedfuncrecords)[i]; + if (rs != NULL) + delete rs; + } + delete sharedfuncrecords; +} + +/** @brief Resets MCExecution object for next execution. */ + +void MCExecution::reset() { + currid=MCID_INIT; + currbranch=NULL; + alwaysexecuted->clear(); +} + +void MCExecution::dumpExecution() { + char buffer[128]; + sprintf(buffer, "exec%u.dot",schedule_graph); + schedule_graph++; + int file=open(buffer,O_WRONLY|O_TRUNC|O_CREAT, S_IRWXU); + dprintf(file, "digraph execution {\n"); + EPRecord *last=NULL; + for(uint i=0;isize();i++) { + EPValue *epv=(*EPList)[i]; + if (epv==NULL) + continue; + EPRecord *record=epv->getRecord(); + dprintf(file, "%lu[label=\"",(uintptr_t)record); + record->print(file); + dprintf(file, "\"];\n"); + if (last!=NULL) + dprintf(file, "%lu->%lu;", (uintptr_t) last, (uintptr_t) record); + last=record; + } + dprintf(file, "}\n"); + close(file); +} + +/** @brief Records the MCID and returns the next MCID */ + +MCID MCExecution::loadMCID(MCID maddr, uintptr_t offset) { + scheduler->check_preempt(); + id_addr=maddr; + id_addr_offset=offset; + return id_retval=getNextMCID(); +} + +/** @brief Records the address and value MCIDs. */ + +void MCExecution::storeMCID(MCID maddr, uintptr_t offset, MCID val) { +#ifndef TSO + scheduler->check_preempt(); +#endif + id_addr=maddr; + id_addr_offset=offset; + id_value=val; +} + +/** @brief Records MCIDs for a RMW. */ + +MCID MCExecution::nextRMW(MCID maddr, uintptr_t offset, MCID oldval, MCID valarg) { + scheduler->check_preempt(); + id_addr=maddr; + id_addr_offset=offset; + id_oldvalue=oldval; + id_value=valarg; + id_retval=getNextMCID(); + return id_retval; +} + +uint64_t dormwaction(enum atomicop op, void *addr, uint len, uint64_t currval, uint64_t oldval, uint64_t valarg, uint64_t *newval) { + uint64_t retval; + uint64_t memval; + switch(op) { + case ADD: + retval=currval; + memval=currval+valarg; + break; + case CAS: + retval=currval; + if (currval==oldval) { + memval=valarg; + } else { + memval=currval; + } + break; + case EXC: + retval=currval; + memval=valarg; + break; + default: + ASSERT(false); + return -1; + } + + *newval=memval&getmask(len); + + if (op==ADD || (op==CAS && (currval==oldval)) || (op == EXC)) { + switch(len) { + case 1: + *((uint8_t *)addr)=*newval; + break; + case 2: + *((uint16_t *)addr)=*newval; + break; + case 4: + *((uint32_t *)addr)=*newval; + break; + case 8: + *((uint64_t *)addr)=*newval; + break; + } + } + return retval; +} + +/** @brief Implement atomic RMW. */ +uint64_t MCExecution::rmw(enum atomicop op, void *addr, uint len, uint64_t currval, uint64_t oldval, uint64_t valarg) { + uint64_t newval; + uint64_t retval=dormwaction(op, addr, len, currval, oldval, valarg, &newval); + if (DBG_ENABLED()) { + model_print("RMW %p oldval=%lu valarg=%lu retval=%lu", addr, oldval, valarg, retval); + currexecpoint->print(); + model_print("\n"); + } + + int num_mcids=(op==ADD)?1:2; + EPRecord * record=getOrCreateCurrRecord(RMW, NULL, id_addr_offset, VC_RMWOUTINDEX-VC_RFINDEX, len, false); + record->setRMW(op); + + recordRMWChange(record, addr, valarg, oldval, newval); + addLoadTable(addr, record); + addStoreTable(addr, record); + EPValue * epvalue=getEPValue(record, NULL, addr, retval, len); + MCID vcrf=memtable->get(addr); + MCID mcids[]={id_value, id_oldvalue}; + recordContext(epvalue, vcrf, id_addr, num_mcids, mcids); + ASSERT(EPList->size()==id_retval); + EPList->push_back(epvalue); + memtable->put(addr, id_retval); + currexecpoint->incrementTop(); + return retval; +} + +/** @brief Gets an EPRecord for the current execution point. */ + +EPRecord * MCExecution::getOrCreateCurrRecord(EventType et, bool * isNew, uintptr_t offset, unsigned int numinputs, uint len, bool br_anyvalue) { + EPRecord *record=EPTable->get(currexecpoint); + if (isNew!=NULL) + *isNew=(record==NULL); + if (record==NULL) { + ExecPoint * ep=new ExecPoint(currexecpoint); + record=new EPRecord(et, ep, currbranch, offset, numinputs, len, br_anyvalue); + if (et==THREADJOIN) { + joinvec->push_back(record); + } + EPTable->put(ep, record); + } else { + ASSERT(record->getOffset()==offset); + } + if (currbranch==NULL) { + uint tid=id_to_int(currexecpoint->get_tid()); + if (alwaysexecuted->size()<=tid) { + alwaysexecuted->resize(tid+1); + } + if ((*alwaysexecuted)[tid]!=NULL && et != LABEL && et != LOOPSTART) + (*alwaysexecuted)[tid]->setNextRecord(record); + (*alwaysexecuted)[tid]=record; + } else { + if (currbranch->firstrecord==NULL) + currbranch->firstrecord=record; + if (currbranch->lastrecord!=NULL && et != LABEL && et != LOOPSTART) + currbranch->lastrecord->setNextRecord(record); + currbranch->lastrecord=record; + } + + return record; +} + +/** @brief Gets an EPValue for the current record and value. */ + +EPValue * MCExecution::getEPValue(EPRecord * record, bool * isNew, const void *addr, uint64_t val, int len) { + ExecPoint * ep=record->getEP(); + EPValue * epvalue=new EPValue(ep, record, addr, val,len); + EPValue * curr=EPValueTable->get(epvalue); + if (curr!=NULL) { + if (isNew!=NULL) + *isNew=false; + delete epvalue; + } else { + if (isNew!=NULL) + *isNew=true; + EPValueTable->put(epvalue, epvalue); + record->addEPValue(epvalue); + curr=epvalue; + } + return curr; +} + +/** @brief Lookup EPRecord for the MCID. */ + +EPRecord * MCExecution::getEPRecord(MCID id) { + return (*EPList)[id]->getRecord(); +} + +/** @brief Lookup EPValue for the MCID. */ + +EPValue * MCExecution::getEPValue(MCID id) { + return (*EPList)[id]; +} + +#ifdef TSO +bool MCExecution::isEmptyStoreBuffer(thread_id_t tid) { + SnapList * list=(*storebuffer)[id_to_int(tid)]; + return list->empty(); +} + +void MCExecution::doStore(thread_id_t tid) { + SnapList * list=(*storebuffer)[id_to_int(tid)]; + EPValue * epval=list->front(); + list->pop_front(); + doStore(epval); +} + +void MCExecution::doStore(EPValue *epval) { + const void *addr=epval->getAddr(); + uint64_t val=epval->getValue(); + int len=epval->getLen(); + if (DBG_ENABLED()) { + model_print("flushing %d bytes *(%p) = %lu", len, addr, val); + currexecpoint->print(); + model_print("\n"); + } + switch(len) { + case 1: + (*(uint8_t *)addr) = (uint8_t)val; + break; + case 2: + (*(uint16_t *)addr) = (uint16_t)val; + break; + case 4: + (*(uint32_t *)addr) = (uint32_t)val; + break; + case 8: + (*(uint64_t *)addr) = (uint64_t)val; + break; + } +} + +void MCExecution::fence() { + scheduler->check_preempt(); + getOrCreateCurrRecord(FENCE, NULL, 0, 0, 8, false); + currexecpoint->incrementTop(); + uint tid=id_to_int(currexecpoint->get_tid()); + SnapList * list=(*storebuffer)[tid]; + while(!list->empty()) { + EPValue * epval=list->front(); + list->pop_front(); + doStore(epval); + } +} +#endif + +/** @brief EPValue is the corresponding epvalue object. + For loads rf is the store we read from. + For loads or stores, addr is the MCID for the provided address. + numids is the number of MCID's we take in. + We then list that number of MCIDs for everything we depend on. +*/ + +void MCExecution::recordContext(EPValue * epv, MCID rf, MCID addr, int numids, MCID *mcids) { + EPRecord *currrecord=epv->getRecord(); + + for(int i=0;iprint(); + model_print("\n"); + } + EPRecord * record=getOrCreateCurrRecord(STORE, NULL, id_addr_offset, 1, len, false); + recordStoreChange(record, addr, val); + addStoreTable(addr, record); + EPValue * epvalue=getEPValue(record, NULL, addr, val, len); +#ifdef TSO + uint tid=id_to_int(currexecpoint->get_tid()); + (*storebuffer)[tid]->push_back(epvalue); +#endif + MCID mcids[]={id_value}; + recordContext(epvalue, MCID_NODEP, id_addr, 1, mcids); + MCID stmcid=getNextMCID(); + ASSERT(stmcid==EPList->size()); + EPList->push_back(epvalue); + memtable->put(addr, stmcid); + currexecpoint->incrementTop(); +} + +void MCExecution::recordFunctionChange(EPRecord *function, uint64_t val) { + if (function->getSet(VC_FUNCOUTINDEX)->add(val)) + planner->addChange(new MCChange(function, val, VC_FUNCOUTINDEX)); +} + +void MCExecution::recordRMWChange(EPRecord *rmw, const void *addr, uint64_t valarg, uint64_t oldval, uint64_t newval) { + if (!rmw->hasAddr(addr)) { + rmw->getSet(VC_ADDRINDEX)->add((uint64_t)addr); + planner->addChange(new MCChange(rmw, (uint64_t)addr, VC_ADDRINDEX)); + } + rmw->getSet(VC_BASEINDEX)->add(valarg); + if (rmw->getOp()==CAS) + rmw->getSet(VC_OLDVALCASINDEX)->add(oldval); + if (!rmw->getSet(VC_RMWOUTINDEX)->contains(newval)) { + rmw->getSet(VC_RMWOUTINDEX)->add(newval); + planner->addChange(new MCChange(rmw, newval, VC_RMWOUTINDEX)); + } +} + +void MCExecution::recordLoadChange(EPRecord *load, const void *addr) { + if (!load->hasAddr(addr)) { + load->getSet(VC_ADDRINDEX)->add((uint64_t)addr); + planner->addChange(new MCChange(load, (uint64_t)addr, VC_ADDRINDEX)); + } +} + +void MCExecution::recordStoreChange(EPRecord *store, const void *addr, uint64_t val) { + if (!store->hasAddr(addr)) { + store->getSet(VC_ADDRINDEX)->add((uint64_t)addr); + planner->addChange(new MCChange(store, (uint64_t)addr, VC_ADDRINDEX)); + } + if (!store->hasValue(val)) { + store->getSet(VC_BASEINDEX)->add(val); + planner->addChange(new MCChange(store, val, VC_BASEINDEX)); + } +} + +/** @brief Processes a load. */ + +uint64_t MCExecution::load(const void *addr, int len) { +#ifdef TSO + uint64_t val=0; + bool found=false; + uint tid=id_to_int(currexecpoint->get_tid()); + SnapList *list=(*storebuffer)[tid]; + for(SnapList::reverse_iterator it=list->rbegin(); it != list->rend(); it++) { + EPValue *epval=*it; + const void *epaddr=epval->getAddr(); + if (epaddr == addr) { + val = epval->getValue(); + found = true; + break; + } + } + if (!found) { + switch(len) { + case 1: + val=*(uint8_t *) addr; + break; + case 2: + val=*(uint16_t *) addr; + break; + case 4: + val=*(uint32_t *) addr; + break; + case 8: + val=*(uint64_t *) addr; + break; + } + } +#else + uint64_t val=0; + switch(len) { + case 1: + val=*(uint8_t *) addr; + break; + case 2: + val=*(uint16_t *) addr; + break; + case 4: + val=*(uint32_t *) addr; + break; + case 8: + val=*(uint64_t *) addr; + break; + } +#endif + + if (DBG_ENABLED()) { + model_print("%lu(mid=%u)=LOAD %p ", val, id_retval, addr); + currexecpoint->print(); + model_print("\n"); + } + ASSERT(id_addr==MCID_NODEP || (getEPValue(id_addr)->getValue()+id_addr_offset)==((uint64_t)addr)); + EPRecord * record=getOrCreateCurrRecord(LOAD, NULL, id_addr_offset, 0, len, false); + recordLoadChange(record, addr); + addLoadTable(addr, record); + EPValue * epvalue=getEPValue(record, NULL, addr, val, len); + MCID vcrf=memtable->get(addr); + recordContext(epvalue, vcrf, id_addr, 0, NULL); + ASSERT(EPList->size()==id_retval); + EPList->push_back(epvalue); + currexecpoint->incrementTop(); + return val; +} + +/** @brief Processes a branch. */ + +MCID MCExecution::branchDir(MCID dirid, int direction, int numdirs, bool anyvalue) { + if (DBG_ENABLED()) { + model_print("BRANCH dir=%u mid=%u", direction, dirid); + currexecpoint->print(); + model_print("\n"); + } + EPRecord * record=getOrCreateCurrRecord(BRANCHDIR, NULL, 0, 1, numdirs, anyvalue); + bool isNew; + EPValue * epvalue=getEPValue(record, &isNew, NULL, direction, 32); + if (isNew) { +#ifdef PRINT_ACHIEVED_GOALS + model_print("Achieved Goal: BRANCH dir=%u mid=%u", direction, dirid); + currexecpoint->print();model_print("\n"); +#endif +#ifdef STATS + planner->getConstGen()->curr_stat->bgoals++; +#endif + planner->getConstGen()->achievedGoal(record); + scheduler->setNewFlag(); + } + //record that we took a branch + currbranch=epvalue; + currbranch->lastrecord=NULL; + MCID mcids[]={dirid}; + recordContext(epvalue, MCID_NODEP, MCID_NODEP, 1, mcids); + MCID brmcid=getNextMCID(); + ASSERT(EPList->size()==brmcid); + EPList->push_back(epvalue); + //push the direction of the branch + currexecpoint->push(EP_BRANCH,direction); + //push the statement counter for the branch + currexecpoint->push(EP_COUNTER,0); + + return brmcid; +} + +/** @brief Processes a merge with a previous branch. mcid gives the + branch we merged. */ + +void MCExecution::merge(MCID mcid) { + EPValue * epvalue=getEPValue(mcid); + ExecPoint *ep=epvalue->getEP(); + //rollback current branch + currbranch=EPTable->get(ep)->getBranch(); + int orig_length=ep->getSize(); + int curr_length=currexecpoint->getSize(); + for(int i=0;ipop(); + //increment top + currexecpoint->incrementTop(); + //now we can create the merge point + if (DBG_ENABLED()) { + model_print("MERGE mid=%u", mcid); + currexecpoint->print(); + model_print("\n"); + } + getOrCreateCurrRecord(MERGE, NULL, 0, 0, 8, false); + currexecpoint->incrementTop(); +} + +/** @brief Phi function. */ +MCID MCExecution::phi(MCID input) { + EPRecord * record=getOrCreateCurrRecord(FUNCTION, NULL, 0, 1, 8, false); + record->setPhi(); + EPValue *epinput=getEPValue(input); + EPValue * epvalue=getEPValue(record, NULL, NULL, epinput->getValue(), 8); + + MCID mcids[]={input}; + recordContext(epvalue, MCID_NODEP, MCID_NODEP, 1, mcids); + + MCID fnmcid=getNextMCID(); + ASSERT(EPList->size()==fnmcid); + EPList->push_back(epvalue); + currexecpoint->incrementTop(); + + return fnmcid; +} + +/** @brief Phi function for loops. */ +MCID MCExecution::loop_phi(MCID input) { + EPRecord * record=getOrCreateCurrRecord(FUNCTION, NULL, 0, 1, 8, false); + record->setLoopPhi(); + EPValue *epinput=getEPValue(input); + EPValue * epvalue=getEPValue(record, NULL, NULL, epinput->getValue(), 8); + + MCID mcids[]={input}; + recordContext(epvalue, MCID_NODEP, MCID_NODEP, 1, mcids); + + uint tid=id_to_int(currexecpoint->get_tid()); + EPRecord *exitrec=(*lastloopexit)[tid]; + + EPRecordIDSet *phiset=record->getPhiLoopTable(); + struct RecordIDPair rip={exitrec,getEPRecord(input)}; + if (!phiset->contains(&rip)) { + struct RecordIDPair *p=(struct RecordIDPair *)model_malloc(sizeof(struct RecordIDPair)); + *p=rip; + phiset->add(p); + } + + MCID fnmcid=getNextMCID(); + ASSERT(EPList->size()==fnmcid); + EPList->push_back(epvalue); + currexecpoint->incrementTop(); + + return fnmcid; +} + +uint64_t MCExecution::equals(MCID op1, uint64_t val1, MCID op2, uint64_t val2, MCID *retval) { + uint64_t eq=(val1==val2); + bool isNew=false; + int len=8; + EPRecord * record=getOrCreateCurrRecord(EQUALS, &isNew, 0, 2, len, false); + EPValue * epvalue=getEPValue(record, NULL, NULL, eq, len); + getEPValue(record, NULL, NULL, 1-eq, len); + MCID mcids[]={op1, op2}; + recordContext(epvalue, MCID_NODEP, MCID_NODEP, 2, mcids); + if (isNew) { + recordFunctionChange(record, 0); + recordFunctionChange(record, 1); + } + MCID eqmcid=getNextMCID(); + ASSERT(EPList->size()==eqmcid); + EPList->push_back(epvalue); + currexecpoint->incrementTop(); + *retval=eqmcid; + return eq; +} + +/** @brief Processes an uninterpretted function. */ + +MCID MCExecution::function(uint functionidentifier, int len, uint64_t val, uint numids, MCID *mcids) { + bool isNew=false; + EPRecord * record=getOrCreateCurrRecord(FUNCTION, &isNew, 0, numids, len, false); + if (isNew) { + if (functionidentifier == 0) + record->setCompletedGoal(new CGoalSet(), false); + else { + if (sharedgoals->size()<=functionidentifier) { + sharedgoals->resize(functionidentifier+1); + sharedfuncrecords->resize(functionidentifier+1); + } + if ((*sharedgoals)[functionidentifier]==NULL) { + (*sharedgoals)[functionidentifier]=new CGoalSet(); + (*sharedfuncrecords)[functionidentifier]=new RecordSet(); + } + record->setCompletedGoal((*sharedgoals)[functionidentifier], true); + (*sharedfuncrecords)[functionidentifier]->add(record); + + for(uint i=VC_BASEINDEX;i<(numids+VC_BASEINDEX);i++) { + EPRecord *input=getEPRecord(mcids[i-VC_BASEINDEX]); + IntIterator *inputit=input->getReturnValueSet()->iterator(); + IntHashSet *recinputset=record->getSet(i); + while(inputit->hasNext()) { + uint64_t inputval=inputit->next(); + recinputset->add(inputval); + } + delete inputit; + } + + CGoalIterator *cit=(*sharedgoals)[functionidentifier]->iterator(); + while(cit->hasNext()) { + CGoal *goal=cit->next(); + evalGoal(record, goal); + } + delete cit; + } + } + val=val&getmask(len); + EPValue * epvalue=getEPValue(record, NULL, NULL, val, len); + recordContext(epvalue, MCID_NODEP, MCID_NODEP, numids, mcids); + + uint64_t valarray[numids+VC_BASEINDEX]; + for(uint i=0;igetValue(); + } + + MCID fnmcid=getNextMCID(); + ASSERT(EPList->size()==fnmcid); + EPList->push_back(epvalue); + currexecpoint->incrementTop(); + + CGoal *goal=new CGoal(numids+VC_BASEINDEX, valarray); + if (record->completedGoalSet()->contains(goal)) { + delete goal; + } else { + scheduler->setNewFlag(); + planner->getConstGen()->achievedGoal(record); +#ifdef PRINT_ACHIEVED_GOALS + model_print("Achieved goal:");goal->print();model_print("\n"); +#endif +#ifdef STATS + planner->getConstGen()->curr_stat->fgoals++; +#endif + goal->setOutput(val); + record->completedGoalSet()->add(goal); + recordFunctionChange(record, val); + if (functionidentifier != 0) { + RecordIterator *rit=(*sharedfuncrecords)[functionidentifier]->iterator(); + while(rit->hasNext()) { + EPRecord *func=rit->next(); + if (func == record) + continue; + evalGoal(func, goal); + } + delete rit; + } + } + + return fnmcid; +} + +void MCExecution::evalGoal(EPRecord *record, CGoal *goal) { + for(uint i=VC_BASEINDEX;igetNum();i++) { + uint64_t input=goal->getValue(i); + if (!record->getSet(i)->contains(input)) + return; + } + //Have all input, propagate output + recordFunctionChange(record, goal->getOutput()); +} + +/** @brief Returns the next thread id. */ + +thread_id_t MCExecution::get_next_tid() { + return int_to_id(snap_fields->next_thread_id++); +} + +/** @brief Registers a new thread */ + +void MCExecution::add_thread(Thread *t) { + ThreadList->push_back(t); + ExecPoint * ep=new ExecPoint(4, t->get_id()); + ep->push(EP_COUNTER,0); + ExecPointList->push_back(ep); + CurrBranchList->push_back(NULL); +#ifdef TSO + storebuffer->push_back(new SnapList()); +#endif +} + +/** @brief Records currently executing thread. */ + +void MCExecution::set_current_thread(Thread *t) { + if (curr_thread) { + uint oldtid=id_to_int(curr_thread->get_id()); + (*CurrBranchList)[oldtid]=currbranch; + } + curr_thread=t; + currexecpoint=(t==NULL)?NULL:(*ExecPointList)[id_to_int(t->get_id())]; + currbranch=(t==NULL)?NULL:(*CurrBranchList)[id_to_int(t->get_id())]; +} + +void MCExecution::threadStart(EPRecord *parent) { + EPRecord *threadstart=getOrCreateCurrRecord(THREADBEGIN, NULL, 0, 0, 8, false); + if (parent!=NULL) { + parent->setChildRecord(threadstart); + } + currexecpoint->incrementTop(); +} + +/** @brief Create a new thread. */ + +void MCExecution::threadCreate(thrd_t *t, thrd_start_t start, void *arg) { + EPRecord *threadstart=getOrCreateCurrRecord(THREADCREATE, NULL, 0, 0, 8, false); + currexecpoint->incrementTop(); + Thread *th = new Thread(get_next_tid(), t, start, arg, curr_thread, threadstart); + add_thread(th); +} + +/** @brief Joins with a thread. */ + +void MCExecution::threadJoin(Thread *blocking) { + while(true) { + if (blocking->is_complete()) { + EPRecord *join=getOrCreateCurrRecord(THREADJOIN, NULL, 0, 0, 8, false); + currexecpoint->incrementTop(); + join->setJoinThread(blocking->get_id()); + return; + } + get_current_thread()->set_waiting(blocking); + scheduler->check_preempt(); + get_current_thread()->set_waiting(NULL); + } +} + +/** @brief Finishes a thread. */ + +void MCExecution::threadFinish() { + Thread *th = get_current_thread(); + /* Wake up any joining threads */ + for (unsigned int i = 0; i < get_num_threads(); i++) { + Thread *waiting = get_thread(int_to_id(i)); + if (waiting->waiting_on() == th) { + waiting->set_waiting(NULL); + } + } + th->complete(); + scheduler->check_preempt(); +} + +/** @brief Thread yield. */ + +void MCExecution::threadYield() { + getOrCreateCurrRecord(YIELD, NULL, 0, 0, 8, false); + currexecpoint->incrementTop(); +} + +/** @brief Thread yield. */ + +void * MCExecution::alloc(size_t size) { + bool isNew; + EPRecord *record=getOrCreateCurrRecord(ALLOC, &isNew, 0, 0, 8, false); + currexecpoint->incrementTop(); + if (isNew) { + size_t allocsize=((size<<1)+7)&~((size_t)(7)); + record->setSize(allocsize); + void *ptr=real_user_malloc(size); + record->setPtr(ptr); + return ptr; + } else { + if (size>record->getSize()) { + model_print("Allocation size changed too much\n"); + exit(-1); + } + void *ptr=record->getPtr(); + return ptr; + } +} + +/** @brief Record enter loop. */ + +void MCExecution::enterLoop() { + EPRecord * record=getOrCreateCurrRecord(LOOPENTER, NULL, 0, 0, 8, false); + + //push the loop iteration counter + currexecpoint->push(EP_LOOP,0); + //push the curr iteration statement counter + currexecpoint->push(EP_COUNTER,0); + EPRecord * lpstartrecord=getOrCreateCurrRecord(LOOPSTART, NULL, 0, 0, 8, false); + record->setChildRecord(lpstartrecord); + + currexecpoint->incrementTop(); + if (DBG_ENABLED()) { + model_print("ENLOOP "); + currexecpoint->print(); + model_print("\n"); + } +} + +/** @brief Record exit loop. */ + +void MCExecution::exitLoop() { + ExecPointType type; + EPRecord *breakstate=NULL; + + /* Record last statement */ + uint tid=id_to_int(currexecpoint->get_tid()); + + if (!currexecpoint->directInLoop()) { + breakstate=getOrCreateCurrRecord(NONLOCALTRANS, NULL, 0, 0, 8, false); + currexecpoint->incrementTop(); + } + + /* Get Last Record */ + EPRecord *lastrecord=(currbranch==NULL)?(*alwaysexecuted)[tid]:currbranch->lastrecord; + + /* Remember last record as loop exit for this execution. */ + if (lastloopexit->size()<=tid) { + lastloopexit->resize(tid+1); + } + (*lastloopexit)[tid]=lastrecord; + + do { + type=currexecpoint->getType(); + currexecpoint->pop(); + if (type==EP_BRANCH) { + //we crossed a branch, fix currbranch + EPRecord *branch=currbranch->getRecord(); + currbranch=branch->getBranch(); + } + } while(type!=EP_LOOP); + + if (DBG_ENABLED()) { + model_print("EXLOOP "); + currexecpoint->print(); + model_print("\n"); + } + EPRecord *loopenter=EPTable->get(currexecpoint); + currexecpoint->incrementTop(); + EPRecord *labelrec=getOrCreateCurrRecord(LABEL, NULL, 0, 0, 8, false); + if (loopenter->getNextRecord()==NULL) { + loopenter->setNextRecord(labelrec); + } + if (breakstate!=NULL) { + breakstate->setNextRecord(labelrec); + } + currexecpoint->incrementTop(); +} + +/** @brief Record next loop iteration. */ +void MCExecution::loopIterate() { + currexecpoint->pop(); + //increment the iteration counter + currexecpoint->incrementTop(); + currexecpoint->push(EP_COUNTER,0); +} + +/** @brief Helper function to add new item to a StoreLoadHashTable */ + +void addTable(StoreLoadHashTable *table, const void *addr, EPRecord *record) { + RecordSet * rset=table->get(addr); + if (rset==NULL) { + rset=new RecordSet(); + table->put(addr, rset); + } + rset->add(record); +} + +/** @brief Update mapping from address to stores to that address. */ + +void MCExecution::addStoreTable(const void *addr, EPRecord *record) { + addTable(storetable, addr, record); +} + +/** @brief Update mapping from address to loads from that address. */ + +void MCExecution::addLoadTable(const void *addr, EPRecord *record) { + addTable(loadtable, addr, record); +} + +/** @brief Update mapping from address to loads from that address. */ + +RecordSet * MCExecution::getLoadTable(const void *addr) { + return loadtable->get(addr); +} + +/** @brief Update mapping from address to stores to that address. */ + +RecordSet * MCExecution::getStoreTable(const void *addr) { + return storetable->get(addr); +} + +/** @brief Registers that component index of deprecord depends on record. */ + +void MCExecution::addRecordDepTable(EPRecord *record, EPRecord *deprecord, unsigned int index) { + EPRecordSet *set=eprecorddep->get(record); + if (set==NULL) { + set=new EPRecordSet(); + eprecorddep->put(record, set); + } + struct RecordIntPair pair={deprecord, index}; + + if (!set->contains(&pair)) { + struct RecordIntPair *p=(struct RecordIntPair *)model_malloc(sizeof(struct RecordIntPair)); + *p=pair; + set->add(p); + } + + if (!revrecorddep->contains(&pair)) { + struct RecordIntPair *p=(struct RecordIntPair *)model_malloc(sizeof(struct RecordIntPair)); + *p=pair; + revrecorddep->put(p, new ModelVector()); + } + + ModelVector * recvec=revrecorddep->get(&pair); + for(uint i=0;isize();i++) { + if ((*recvec)[i]==record) + return; + } + recvec->push_back(record); +} + +ModelVector * MCExecution::getRevDependences(EPRecord *record, uint index) { + struct RecordIntPair pair={record, index}; + return revrecorddep->get(&pair); +} diff --git a/mcexecution.h b/mcexecution.h new file mode 100644 index 0000000..dca4228 --- /dev/null +++ b/mcexecution.h @@ -0,0 +1,158 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MCEXECUTION_H +#define MCEXECUTION_H +#include "hashtable.h" +#include "execpoint.h" +#include "stl-model.h" +#include "classlist.h" +#include +#include "eprecord.h" +#include "epvalue.h" +#include "threads-model.h" + +typedef HashTable EPHashTable; +typedef HashTable MemHashTable; +typedef HashTable EPValueHashTable; +typedef HashTable StoreLoadHashTable; + + +struct RecordIntPair { + EPRecord *record; + unsigned int index; +}; +inline unsigned int RP_hash_function(struct RecordIntPair * pair) { + return (unsigned int)(((uintptr_t)pair->record) >> 4) ^ pair->index; +} +inline bool RP_equals(struct RecordIntPair * key1, struct RecordIntPair * key2) { + if (key1==NULL) + return key1==key2; + return key1->record == key2->record && key1->index == key2->index; +} +typedef HashSet EPRecordSet; +typedef HSIterator EPRecordIterator; +typedef HashTable EPRecordDepHashTable; +typedef HashTable *, uintptr_t, 4, model_malloc, model_calloc, model_free, RP_hash_function, RP_equals> RevDepHashTable; + +struct MCExecution_snapshot { + MCExecution_snapshot(); + ~MCExecution_snapshot(); + unsigned int next_thread_id; + + SNAPSHOTALLOC; +}; + +class MCExecution { + public: + MCExecution(); + ~MCExecution(); + EPRecord * getOrCreateCurrRecord(EventType et, bool * isNew, uintptr_t offset, unsigned int numinputs, uint len, bool br_anyvalue); + MCID getNextMCID() { return ++currid; } + MCID loadMCID(MCID maddr, uintptr_t offset); + void storeMCID(MCID maddr, uintptr_t offset, MCID val); + MCID nextRMW(MCID addr, uintptr_t offset, MCID oldval, MCID valarg); + void store(void *addr, uint64_t val, int len); + uint64_t load(const void *addr, int len); + uint64_t rmw(enum atomicop op, void *addr, uint size, uint64_t currval, uint64_t oldval, uint64_t valarg); + void reset(); + MCID branchDir(MCID dir, int direction, int numdirs, bool anyvalue); + void merge(MCID mcid); + MCID function(uint functionidentifier, int numbytesretval, uint64_t val, uint num_args, MCID *mcids); + uint64_t equals(MCID op1, uint64_t val1, MCID op2, uint64_t val2, MCID *retval); + MCID phi(MCID input); + MCID loop_phi(MCID input); + void * alloc(size_t bytes); +#ifdef TSO + void fence(); + void doStore(EPValue *epval); + void doStore(thread_id_t tid); + bool isEmptyStoreBuffer(thread_id_t tid); + EPValue *getStoreBuffer(thread_id_t tid) {int thread=id_to_int(tid); if ((*storebuffer)[thread]->empty()) return NULL; else return (*storebuffer)[id_to_int(tid)]->front();} +#endif + void enterLoop(); + void exitLoop(); + void loopIterate(); + void threadCreate(thrd_t *t, thrd_start_t start, void *arg); + void threadJoin(Thread *th); + void threadYield(); + void threadFinish(); + MCScheduler * get_scheduler() const { return scheduler; } + Planner * get_planner() const { return planner; } + EPValue * getEPValue(EPRecord * record, bool * isNew, const void *addr, uint64_t val, int len); + void recordContext(EPValue * epv, MCID rf, MCID addr, int numids, MCID *mcids); + void add_thread(Thread *t); + thread_id_t get_next_tid(); + unsigned int get_num_threads() {return snap_fields->next_thread_id;}; + void set_current_thread(Thread *t); + Thread * get_current_thread() {return curr_thread;} + ExecPoint * get_execpoint(thread_id_t tid) {return (*ExecPointList)[id_to_int(tid)];} + Thread * get_thread(thread_id_t tid) {return (*ThreadList)[id_to_int(tid)];} + void addStoreTable(const void *addr, EPRecord *record); + void addLoadTable(const void *addr, EPRecord *record); + RecordSet * getStoreTable(const void *addr); + RecordSet * getLoadTable(const void *addr); + void recordRMWChange(EPRecord *load, const void *addr, uint64_t valarg, uint64_t oldval, uint64_t newval); + void recordFunctionChange(EPRecord *function, uint64_t val); + void recordLoadChange(EPRecord *function, const void *addr); + void recordStoreChange(EPRecord *function, const void *addr, uint64_t val); + EPRecord * getEPRecord(MCID id); + EPValue * getEPValue(MCID id); + void addRecordDepTable(EPRecord *record, EPRecord *deprecord, unsigned int index); + EPRecordSet *getDependences(EPRecord *record) {return eprecorddep->get(record);} + ModelVector * getRevDependences(EPRecord *record, uint index); + void threadStart(EPRecord *parent); + + bool compatibleStoreLoad(EPRecord *store, EPRecord *load) { + return store!=load; + } + ModelVector * getAlwaysExecuted() {return alwaysexecuted;} + ModelVector * getJoins() {return joinvec;} + void evalGoal(EPRecord *record, CGoal *goal); + void dumpExecution(); + EPRecord * getRecord(ExecPoint * ep) {return EPTable->get(ep);} + + MEMALLOC; + private: + EPHashTable * EPTable; + EPValueHashTable * EPValueTable; + MemHashTable *memtable; + StoreLoadHashTable *storetable; + StoreLoadHashTable *loadtable; + SnapVector *EPList; + SnapVector *ThreadList; +#ifdef TSO + SnapVector *> *storebuffer; +#endif + SnapVector *ExecPointList; + SnapVector *CurrBranchList; + ExecPoint * currexecpoint; + MCScheduler * scheduler; + Planner * planner; + struct MCExecution_snapshot * const snap_fields; + Thread * curr_thread; + EPValue *currbranch; + EPRecordDepHashTable *eprecorddep; + RevDepHashTable *revrecorddep; + ModelVector * alwaysexecuted; + ModelVector * lastloopexit; + ModelVector * joinvec; + ModelVector * sharedgoals; + ModelVector * sharedfuncrecords; + + MCID currid; + MCID id_addr; + MCID id_oldvalue; + MCID id_value; + MCID id_retval; + uintptr_t id_addr_offset; + uint schedule_graph; +}; + +#endif diff --git a/mcschedule.cc b/mcschedule.cc new file mode 100644 index 0000000..a86b0ff --- /dev/null +++ b/mcschedule.cc @@ -0,0 +1,244 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "mcschedule.h" +#include "mcexecution.h" + +WaitPair::WaitPair(ExecPoint *stoppoint, ExecPoint *waitpoint) : + stop_point(stoppoint), + wait_point(waitpoint) { +} + +WaitPair::~WaitPair() { +} + +ExecPoint * WaitPair::getStop() { + return stop_point; +} + +ExecPoint * WaitPair::getWait() { + return wait_point; +} + +MCScheduler::MCScheduler(MCExecution *e) : + waitsetlen(4), + execution(e), + waitset(new ModelVector *>()), + waitsetindex((unsigned int *)model_calloc(sizeof(unsigned int)*waitsetlen, 1)), + newbehavior(false) +{ +#ifdef TSO + storesetindex=(unsigned int *)model_calloc(sizeof(unsigned int)*waitsetlen, 1); + storeset=new ModelVector *>(); +#endif +} + +MCScheduler::~MCScheduler() { +} + +void MCScheduler::setNewFlag() { + newbehavior=true; +} + +void MCScheduler::addWaitPair(EPRecord *stoprec, EPRecord *waitrec) { + ExecPoint *stoppoint=stoprec->getEP(); + ExecPoint *waitpoint=waitrec->getEP(); + + uint tid=id_to_int(stoppoint->get_tid()); + if (waitset->size()<=tid) { + uint oldsize=waitset->size(); + waitset->resize(tid+1); + for(uint i=oldsize;i<=tid;i++) { + (*waitset)[i]=new ModelVector(); + } +#ifdef TSO + storeset->resize(tid+1); + for(uint i=oldsize;i<=tid;i++) { + (*storeset)[i]=new ModelVector(); + } +#endif + } + if (tid>=waitsetlen) { + waitsetindex=(uint *) model_realloc(waitsetindex, sizeof(uint)*(tid << 1)); + for(uint i=waitsetlen;i<(tid<<1);i++) + waitsetindex[i]=0; +#ifdef TSO + storesetindex=(uint *) model_realloc(storesetindex, sizeof(uint)*(tid << 1)); + for(uint i=waitsetlen;i<(tid<<1);i++) + storesetindex[i]=0; +#endif + waitsetlen=tid<<1; + } +#ifdef TSO + if (stoprec->getType()==STORE) + (*storeset)[tid]->push_back(new WaitPair(stoppoint, waitpoint)); + else + (*waitset)[tid]->push_back(new WaitPair(stoppoint, waitpoint)); +#else + (*waitset)[tid]->push_back(new WaitPair(stoppoint, waitpoint)); +#endif +} + +void MCScheduler::reset() { + for(unsigned int i=0;isize();i++) { + ModelVector * v=(*waitset)[i]; + for(unsigned int j=0;jsize();j++) { + WaitPair *wp=(*v)[j]; + delete wp; + } + v->clear(); + } + for(unsigned int i=0;isize();i++) { + ModelVector * v=(*storeset)[i]; + for(unsigned int j=0;jsize();j++) { + WaitPair *wp=(*v)[j]; + delete wp; + } + v->clear(); + } + for(unsigned int i=0;iget_current_thread(); +#ifdef TSO + restart_search: + //start at the next thread + unsigned int tid=id_to_int(t->get_id()); + bool storebuffer=true; + for(unsigned int i=0;i<(2*execution->get_num_threads());i++) { + if (storebuffer) { + //Don't try to do a store from an empty store buffer + if (!execution->isEmptyStoreBuffer(int_to_id(tid))&& + check_store_buffer(tid)) { + execution->doStore(int_to_id(tid)); + goto restart_search; + } + tid=(tid+1)%execution->get_num_threads(); + storebuffer=false; + } else { + //don't try to schedule finished threads + if (!execution->get_thread(int_to_id(tid))->is_complete() && + check_thread(tid)) { + break; + } + storebuffer=true; + } + } +#else + //start at the next thread + unsigned int tid=(id_to_int(t->get_id())+1)%execution->get_num_threads(); + + for(unsigned int i=0;iget_num_threads();i++,tid=(tid+1)%execution->get_num_threads()) { + //don't try to schedule finished threads + if (execution->get_thread(int_to_id(tid))->is_complete()) + continue; + if (check_thread(tid)) { + break; + } + } +#endif + + Thread *next_thread=execution->get_thread(int_to_id(tid)); + if (next_thread->is_complete()) + next_thread=NULL; + + swap_threads(t,next_thread); +} + +#ifdef TSO +bool MCScheduler::check_store_buffer(unsigned int tid) { + ExecPoint *current=execution->getStoreBuffer(tid)->getEP(); + return checkSet(tid, storeset, storesetindex, current); +} +#endif + +bool MCScheduler::check_thread(unsigned int tid) { + ExecPoint *current=execution->get_execpoint(tid); + return checkSet(tid, waitset, waitsetindex, current); +} + + +bool MCScheduler::checkSet(unsigned int tid, ModelVector * > *set, unsigned int *setindex, ExecPoint *current) { + if (tid >= set->size()) + return true; + ModelVector * wps=&(*((*set)[tid])); + + if (!newbehavior) { + for(;setindex[tid]size();setindex[tid]++) { + WaitPair *nextwp=(*wps)[setindex[tid]]; + ExecPoint *stoppoint=nextwp->getStop(); + CompareResult compare=stoppoint->compare(current); + if (compare==CR_EQUALS) { + //hit stop point + ExecPoint *waitpoint=nextwp->getWait(); + thread_id_t waittid=waitpoint->get_tid(); + ExecPoint *waitthread=execution->get_execpoint(waittid); + CompareResult comparewt=waitthread->compare(waitpoint); + //we've resolved this wait, keep going + if (comparewt==CR_BEFORE||comparewt==CR_INCOMPARABLE) { +#ifdef TSO + EPRecord *waitrec=execution->getRecord(waitpoint); + if (waitrec->getType()==STORE) { + EPValue *first_store=execution->getStoreBuffer(waittid); + if (first_store==NULL) + continue; + ExecPoint *storebuffer_ep=first_store->getEP(); + CompareResult sb_comparewt=storebuffer_ep->compare(waitpoint); + if (sb_comparewt==CR_BEFORE||sb_comparewt==CR_INCOMPARABLE) + continue; + //need to wait to commit store out of buffer + return false; + } else + continue; +#else + continue; +#endif + } +#ifdef TSO + //wait for store buffer to empty + if (!execution->isEmptyStoreBuffer(waittid)) { + return false; + } +#endif + //don't wait on a completed thread if store buffer is empty + if (execution->get_thread(id_to_int(waittid))->is_complete()) + continue; + //Need to wait for another thread to take a step + return false; + } else if (compare==CR_BEFORE) { + //we haven't reached the context switch point + return true; + } else { + return true; + //oops..missed the point... + //this means we are past the point of our model's validity... + } + } + } + return true; +} + +/** Swap context from thread from to thread to. If a thread is NULL, + * then we switch to the system context. */ + +void MCScheduler::swap_threads(Thread * from, Thread *to) { + ucontext_t * fromcontext=(from==NULL) ? get_system_context() : from->get_context(); + ucontext_t * tocontext=(to==NULL) ? get_system_context() : to->get_context(); + execution->set_current_thread(to); + model_swapcontext(fromcontext, tocontext); +} diff --git a/mcschedule.h b/mcschedule.h new file mode 100644 index 0000000..d7fb852 --- /dev/null +++ b/mcschedule.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MCSCHEDULER_H +#define MCSCHEDULER_H +#include "classlist.h" +#include "mymemory.h" +#include "context.h" +#include "stl-model.h" + +class WaitPair { + public: + WaitPair(ExecPoint * stoppoint, ExecPoint * waitpoint); + ~WaitPair(); + ExecPoint * getStop(); + ExecPoint * getWait(); + + MEMALLOC; + private: + ExecPoint *stop_point; + ExecPoint *wait_point; +}; + +class MCScheduler { + public: + MCScheduler(MCExecution * e); + ~MCScheduler(); + ucontext_t * get_system_context() { return &system_context; } + void swap_threads(Thread * from, Thread *to); + void reset(); + void check_preempt(); +#ifdef TSO + bool check_store_buffer(unsigned int tid); +#endif + bool checkSet(unsigned int tid, ModelVector * > *set, unsigned int *setindex, ExecPoint *current); + bool check_thread(unsigned int tid); + void addWaitPair(EPRecord *stoprec, EPRecord *waitrec); + void setNewFlag(); + + MEMALLOC; + private: + unsigned int waitsetlen; + ucontext_t system_context; + MCExecution *execution; + ModelVector * > *waitset; + unsigned int * waitsetindex; +#ifdef TSO + ModelVector * > *storeset; + unsigned int * storesetindex; +#endif + bool newbehavior; +}; + + +#endif diff --git a/mcutil.h b/mcutil.h new file mode 100644 index 0000000..9699d7f --- /dev/null +++ b/mcutil.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MC_UTIL_H +#define MC_UTIL_H +#include + +static inline unsigned int rotate_left(unsigned int val, int bytestorotate) { + return (val << bytestorotate) | (val >> (sizeof(val)*8-bytestorotate)); +} + +static inline unsigned int rotate_right(unsigned int val, int bytestorotate) { + return (val >> bytestorotate) | (val << (sizeof(val)*8-bytestorotate)); +} + +static inline uint64_t keepbytes(uint64_t val, int len) { + int shift=8-len; + return (val << shift)>>shift; +} + +static inline uint64_t getmask(uint len) { + return 0xffffffffffffffff>>(64-(len*8)); +} + + +#define NUMBITS(x) ((x==0)?0:8*sizeof(x)-__builtin_clz(x)) + +#endif diff --git a/model.cc b/model.cc new file mode 100644 index 0000000..7da359b --- /dev/null +++ b/model.cc @@ -0,0 +1,60 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "model.h" +#include "snapshot-interface.h" +#include "mcschedule.h" +#include "output.h" +#include "planner.h" + +MC * model; + +MC::MC(struct model_params params) : + params(params), + execution(new MCExecution()) +{ +} + +MC::~MC() { + delete execution; +} + +/** Wrapper to run the user's main function, with appropriate arguments */ +void user_main_wrapper(void *) { + user_main(model->params.argc, model->params.argv); +} + +/** Implements the main loop for model checking test case + */ +void MC::check() { + snapshot_record(0); + do { + run_execution(); + execution->get_planner()->plan(); + print_program_output(); +#if SUPPORT_MOD_ORDER_DUMP + execution->dumpExecution(); +#endif + execution->reset(); + snapshot_backtrack_before(0); + } while(!execution->get_planner()->is_finished()); + dprintf(2, "Finished!\n"); +} + + +/** Executes a single execution. */ + +void MC::run_execution() { + thrd_t user_thread; + Thread *t = new Thread(execution->get_next_tid(), &user_thread, &user_main_wrapper, NULL, NULL, NULL); + execution->add_thread(t); + execution->get_scheduler()->swap_threads(NULL, t); +} + + diff --git a/model.h b/model.h new file mode 100644 index 0000000..f977117 --- /dev/null +++ b/model.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file model.h + * @brief Core model checker. + */ + +#ifndef __MODEL_H__ +#define __MODEL_H__ + +#include +#include +#include "mcexecution.h" +#include "mymemory.h" +#include "hashtable.h" +#include "config.h" +#include "context.h" +#include "params.h" + +class MC { + public: + MC(struct model_params params); + ~MC(); + MCExecution * get_execution() const { return execution; } + MCScheduler * get_scheduler() const { return execution->get_scheduler(); } + void check(); + const model_params params; + + MEMALLOC; + private: + MCExecution *execution; + void run_execution(); + + friend void user_main_wrapper(); +}; + +extern MC *model; +#endif /* __MODEL_H__ */ diff --git a/mymemory.cc b/mymemory.cc new file mode 100644 index 0000000..d911f5d --- /dev/null +++ b/mymemory.cc @@ -0,0 +1,315 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include "mymemory.h" +#include "snapshot.h" +#include "common.h" +#include "threads-model.h" +#include "model.h" +#include "mcexecution.h" + +#define REQUESTS_BEFORE_ALLOC 1024 + +size_t allocatedReqs[REQUESTS_BEFORE_ALLOC] = { 0 }; +int nextRequest = 0; +int howManyFreed = 0; +#if !USE_MPROTECT_SNAPSHOT +static mspace sStaticSpace = NULL; +#endif + +/** Non-snapshotting calloc for our use. */ +void *model_calloc(size_t count, size_t size) +{ +#if USE_MPROTECT_SNAPSHOT + static void *(*callocp)(size_t count, size_t size) = NULL; + char *error; + void *ptr; + + /* get address of libc malloc */ + if (!callocp) { + callocp = (void * (*)(size_t, size_t))dlsym(RTLD_NEXT, "calloc"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(EXIT_FAILURE); + } + } + ptr = callocp(count, size); + return ptr; +#else + if (!sStaticSpace) + sStaticSpace = create_shared_mspace(); + return mspace_calloc(sStaticSpace, count, size); +#endif +} + +/** Non-snapshotting malloc for our use. */ +void *model_malloc(size_t size) +{ +#if USE_MPROTECT_SNAPSHOT + static void *(*mallocp)(size_t size) = NULL; + char *error; + void *ptr; + + /* get address of libc malloc */ + if (!mallocp) { + mallocp = (void * (*)(size_t))dlsym(RTLD_NEXT, "malloc"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(EXIT_FAILURE); + } + } + ptr = mallocp(size); + return ptr; +#else + if (!sStaticSpace) + sStaticSpace = create_shared_mspace(); + return mspace_malloc(sStaticSpace, size); +#endif +} + +/** @brief Snapshotting realloc, for use by model-checker (not user progs) */ +void *model_realloc(void *ptr, size_t size) +{ +#if USE_MPROTECT_SNAPSHOT + static void *(*reallocp)(void *ptr, size_t size) = NULL; + char *error; + void *tmpptr; + + /* get address of libc malloc */ + if (!reallocp) { + reallocp = (void * (*)(void *,size_t))dlsym(RTLD_NEXT, "realloc"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(EXIT_FAILURE); + } + } + tmpptr = reallocp(ptr, size); + return tmpptr; +#else + if (!sStaticSpace) + sStaticSpace = create_shared_mspace(); + return mspace_realloc(sStaticSpace, ptr, size); +#endif +} + +/** @brief Snapshotting malloc, for use by model-checker (not user progs) */ +void * snapshot_malloc(size_t size) +{ + void *tmp = mspace_malloc(model_snapshot_space, size); + ASSERT(tmp); + return tmp; +} + +/** @brief Snapshotting calloc, for use by model-checker (not user progs) */ +void * snapshot_calloc(size_t count, size_t size) +{ + void *tmp = mspace_calloc(model_snapshot_space, count, size); + ASSERT(tmp); + return tmp; +} + +/** @brief Snapshotting realloc, for use by model-checker (not user progs) */ +void *snapshot_realloc(void *ptr, size_t size) +{ + void *tmp = mspace_realloc(model_snapshot_space, ptr, size); + ASSERT(tmp); + return tmp; +} + +/** @brief Snapshotting free, for use by model-checker (not user progs) */ +void snapshot_free(void *ptr) +{ + mspace_free(model_snapshot_space, ptr); +} + +/** Non-snapshotting free for our use. */ +void model_free(void *ptr) +{ +#if USE_MPROTECT_SNAPSHOT + static void (*freep)(void *); + char *error; + + /* get address of libc free */ + if (!freep) { + freep = (void (*)(void *))dlsym(RTLD_NEXT, "free"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(EXIT_FAILURE); + } + } + freep(ptr); +#else + mspace_free(sStaticSpace, ptr); +#endif +} + +/** Bootstrap allocation. Problem is that the dynamic linker calls require + * calloc to work and calloc requires the dynamic linker to work. */ + +#define BOOTSTRAPBYTES 4096 +char bootstrapmemory[BOOTSTRAPBYTES]; +size_t offset = 0; + +void * HandleEarlyAllocationRequest(size_t sz) +{ + /* Align to 8 byte boundary */ + sz = (sz + 7) & ~7; + + if (sz > (BOOTSTRAPBYTES-offset)) { + model_print("OUT OF BOOTSTRAP MEMORY\n"); + exit(EXIT_FAILURE); + } + + void *pointer = (void *)&bootstrapmemory[offset]; + offset += sz; + return pointer; +} + +/** @brief Global mspace reference for the model-checker's snapshotting heap */ +mspace model_snapshot_space = NULL; + +#if USE_MPROTECT_SNAPSHOT + +/** @brief Global mspace reference for the user's snapshotting heap */ +void * user_snapshot_space = NULL; +mspace thread_snapshot_space = NULL; + +struct snapshot_heap_data * snapshot_struct; + +/** Check whether this is bootstrapped memory that we should not free */ +static bool DontFree(void *ptr) +{ + return (ptr >= (&bootstrapmemory[0]) && ptr < (&bootstrapmemory[BOOTSTRAPBYTES])); +} + + +static void * user_malloc(size_t size) { + return model->get_execution()->alloc(size); +} + +/** + * @brief The allocator function for "user" allocation + * + * Should only be used for allocations which will not disturb the allocation + * patterns of a user thread. + */ +void * real_user_malloc(size_t size) +{ + size=(size+7)&~((size_t)7); + void *tmp = snapshot_struct->allocation_ptr; + snapshot_struct->allocation_ptr = (void *)((char *) snapshot_struct->allocation_ptr +size); + + ASSERT(snapshot_struct->allocation_ptr <= snapshot_struct->top_ptr); + return tmp; +} + +/** + * @brief Snapshotting malloc implementation for user programs + * + * Do NOT call this function from a model-checker context. Doing so may disrupt + * the allocation patterns of a user thread. + */ +void *malloc(size_t size) +{ + if (user_snapshot_space) { + /* Only perform user allocations from user context */ + return user_malloc(size); + } else + return HandleEarlyAllocationRequest(size); +} + +/** @brief Snapshotting free implementation for user programs */ +void free(void * ptr) +{ + if (!DontFree(ptr)) + mspace_free(user_snapshot_space, ptr); +} + +/** @brief Snapshotting realloc implementation for user programs */ +void *realloc(void *ptr, size_t size) +{ + ASSERT(false); + return NULL; +} + +/** @brief Snapshotting calloc implementation for user programs */ +void * calloc(size_t num, size_t size) +{ + if (user_snapshot_space) { + void *tmp = user_malloc(num * size); + bzero(tmp, num*size); + ASSERT(tmp); + return tmp; + } else { + void *tmp = HandleEarlyAllocationRequest(size * num); + memset(tmp, 0, size * num); + return tmp; + } +} + +/** @brief Snapshotting allocation function for use by the Thread class only */ +void * Thread_malloc(size_t size) +{ + void *tmp = mspace_malloc(thread_snapshot_space, size); + ASSERT(tmp); + return tmp; +} + +/** @brief Snapshotting free function for use by the Thread class only */ +void Thread_free(void *ptr) +{ + free(ptr); +} + +/** @brief Snapshotting new operator for user programs */ +void * operator new(size_t size) throw(std::bad_alloc) +{ + return malloc(size); +} + +/** @brief Snapshotting delete operator for user programs */ +void operator delete(void *p) throw() +{ + free(p); +} + +/** @brief Snapshotting new[] operator for user programs */ +void * operator new[](size_t size) throw(std::bad_alloc) +{ + return malloc(size); +} + +/** @brief Snapshotting delete[] operator for user programs */ +void operator delete[](void *p, size_t size) +{ + free(p); +} + +#else /* !USE_MPROTECT_SNAPSHOT */ + +/** @brief Snapshotting allocation function for use by the Thread class only */ +void * Thread_malloc(size_t size) +{ + return malloc(size); +} + +/** @brief Snapshotting free function for use by the Thread class only */ +void Thread_free(void *ptr) +{ + free(ptr); +} + +#endif /* !USE_MPROTECT_SNAPSHOT */ diff --git a/mymemory.h b/mymemory.h new file mode 100644 index 0000000..0eca0a3 --- /dev/null +++ b/mymemory.h @@ -0,0 +1,288 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file mymemory.h + * @brief Memory allocation functions. + */ + +#ifndef _MY_MEMORY_H +#define _MY_MEMORY_H +#include +#include + +#include "config.h" + +/** MEMALLOC declares the allocators for a class to allocate + * memory in the non-snapshotting heap. */ +#define MEMALLOC \ + void * operator new(size_t size) { \ + return model_malloc(size); \ + } \ + void operator delete(void *p, size_t size) { \ + model_free(p); \ + } \ + void * operator new[](size_t size) { \ + return model_malloc(size); \ + } \ + void operator delete[](void *p, size_t size) { \ + model_free(p); \ + } \ + void * operator new(size_t size, void *p) { /* placement new */ \ + return p; \ + } + +/** SNAPSHOTALLOC declares the allocators for a class to allocate + * memory in the snapshotting heap. */ +#define SNAPSHOTALLOC \ + void * operator new(size_t size) { \ + return snapshot_malloc(size); \ + } \ + void operator delete(void *p, size_t size) { \ + snapshot_free(p); \ + } \ + void * operator new[](size_t size) { \ + return snapshot_malloc(size); \ + } \ + void operator delete[](void *p, size_t size) { \ + snapshot_free(p); \ + } \ + void * operator new(size_t size, void *p) { /* placement new */ \ + return p; \ + } + + +void *real_user_malloc(size_t size); +void *model_malloc(size_t size); +void *model_calloc(size_t count, size_t size); +void * model_realloc(void *ptr, size_t size); +void model_free(void *ptr); + +void * snapshot_malloc(size_t size); +void * snapshot_calloc(size_t count, size_t size); +void * snapshot_realloc(void *ptr, size_t size); +void snapshot_free(void *ptr); + +void * Thread_malloc(size_t size); +void Thread_free(void *ptr); + + +/** @brief Provides a non-snapshotting allocator for use in STL classes. + * + * The code was adapted from a code example from the book The C++ + * Standard Library - A Tutorial and Reference by Nicolai M. Josuttis, + * Addison-Wesley, 1999 © Copyright Nicolai M. Josuttis 1999 + * Permission to copy, use, modify, sell and distribute this software + * is granted provided this copyright notice appears in all copies. + * This software is provided "as is" without express or implied + * warranty, and with no claim as to its suitability for any purpose. + */ +template +class ModelAlloc { + public: + // type definitions + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef size_t difference_type; + + // rebind allocator to type U + template + struct rebind { + typedef ModelAlloc other; + }; + + // return address of values + pointer address(reference value) const { + return &value; + } + const_pointer address(const_reference value) const { + return &value; + } + + /* constructors and destructor + * - nothing to do because the allocator has no state + */ + ModelAlloc() throw() { + } + ModelAlloc(const ModelAlloc&) throw() { + } + template + ModelAlloc(const ModelAlloc&) throw() { + } + ~ModelAlloc() throw() { + } + + // return maximum number of elements that can be allocated + size_type max_size() const throw() { + return std::numeric_limits::max() / sizeof(T); + } + + // allocate but don't initialize num elements of type T + pointer allocate(size_type num, const void * = 0) { + pointer p = (pointer)model_malloc(num * sizeof(T)); + return p; + } + + // initialize elements of allocated storage p with value value + void construct(pointer p, const T& value) { + // initialize memory with placement new + new((void*)p)T(value); + } + + // destroy elements of initialized storage p + void destroy(pointer p) { + // destroy objects by calling their destructor + p->~T(); + } + + // deallocate storage p of deleted elements + void deallocate(pointer p, size_type num) { + model_free((void*)p); + } +}; + +/** Return that all specializations of this allocator are interchangeable. */ +template +bool operator ==(const ModelAlloc&, + const ModelAlloc&) throw() { + return true; +} + +/** Return that all specializations of this allocator are interchangeable. */ +template +bool operator!= (const ModelAlloc&, + const ModelAlloc&) throw() { + return false; +} + +/** @brief Provides a snapshotting allocator for use in STL classes. + * + * The code was adapted from a code example from the book The C++ + * Standard Library - A Tutorial and Reference by Nicolai M. Josuttis, + * Addison-Wesley, 1999 © Copyright Nicolai M. Josuttis 1999 + * Permission to copy, use, modify, sell and distribute this software + * is granted provided this copyright notice appears in all copies. + * This software is provided "as is" without express or implied + * warranty, and with no claim as to its suitability for any purpose. + */ +template +class SnapshotAlloc { + public: + // type definitions + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef size_t difference_type; + + // rebind allocator to type U + template + struct rebind { + typedef SnapshotAlloc other; + }; + + // return address of values + pointer address(reference value) const { + return &value; + } + const_pointer address(const_reference value) const { + return &value; + } + + /* constructors and destructor + * - nothing to do because the allocator has no state + */ + SnapshotAlloc() throw() { + } + SnapshotAlloc(const SnapshotAlloc&) throw() { + } + template + SnapshotAlloc(const SnapshotAlloc&) throw() { + } + ~SnapshotAlloc() throw() { + } + + // return maximum number of elements that can be allocated + size_type max_size() const throw() { + return std::numeric_limits::max() / sizeof(T); + } + + // allocate but don't initialize num elements of type T + pointer allocate(size_type num, const void * = 0) { + pointer p = (pointer)snapshot_malloc(num * sizeof(T)); + return p; + } + + // initialize elements of allocated storage p with value value + void construct(pointer p, const T& value) { + // initialize memory with placement new + new((void*)p)T(value); + } + + // destroy elements of initialized storage p + void destroy(pointer p) { + // destroy objects by calling their destructor + p->~T(); + } + + // deallocate storage p of deleted elements + void deallocate(pointer p, size_type num) { + snapshot_free((void*)p); + } +}; + +/** Return that all specializations of this allocator are interchangeable. */ +template +bool operator ==(const SnapshotAlloc&, + const SnapshotAlloc&) throw() { + return true; +} + +/** Return that all specializations of this allocator are interchangeable. */ +template +bool operator!= (const SnapshotAlloc&, + const SnapshotAlloc&) throw() { + return false; +} + +#ifdef __cplusplus +extern "C" { +#endif + typedef void * mspace; + extern void * mspace_malloc(mspace msp, size_t bytes); + extern void mspace_free(mspace msp, void* mem); + extern void * mspace_realloc(mspace msp, void* mem, size_t newsize); + extern void * mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); + extern mspace create_mspace_with_base(void* base, size_t capacity, int locked); + extern mspace create_mspace(size_t capacity, int locked); + + struct snapshot_heap_data { + void *allocation_ptr; + void *top_ptr; + }; + + extern struct snapshot_heap_data * snapshot_struct; + +#if USE_MPROTECT_SNAPSHOT + extern void * user_snapshot_space; + extern mspace thread_snapshot_space; +#endif + + extern mspace model_snapshot_space; + +#ifdef __cplusplus +}; /* end of extern "C" */ +#endif + +#endif /* _MY_MEMORY_H */ diff --git a/notes b/notes new file mode 100644 index 0000000..03b5954 --- /dev/null +++ b/notes @@ -0,0 +1,20 @@ +1) Every branch gets a goal for each direction. +2) Need single definition point...SSA like semantics + +Model checking is complete when +For each branch it is either +1) Each exit is covered +2) The incoming function is covered +3) A function is covered if + A) all addresses of all stores are resolved + and either + B) all inputs to function are covered and + + C) each combination of inputs to a function are either + i) covered or + ii) unschedulable + +4) A read is covered if for each value stored by a store that can access the same address it: + a) has seen all values + b) the store can't store the value to same address + c) it isn't schedulable... diff --git a/output.h b/output.h new file mode 100644 index 0000000..f8aba6c --- /dev/null +++ b/output.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file output.h + * @brief Functions for redirecting program output + */ + +#ifndef __OUTPUT_H__ +#define __OUTPUT_H__ + +#include "config.h" + +#ifdef CONFIG_DEBUG +static inline void redirect_output() { } +static inline void clear_program_output() { } +static inline void print_program_output() { } +#else +void redirect_output(); +void clear_program_output(); +void print_program_output(); +#endif /* ! CONFIG_DEBUG */ + +#endif /* __OUTPUT_H__ */ diff --git a/params.h b/params.h new file mode 100644 index 0000000..31e9267 --- /dev/null +++ b/params.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef __PARAMS_H__ +#define __PARAMS_H__ + +/** + * Model checker parameter structure. Holds run-time configuration options for + * the model checker. + */ +struct model_params { + /** @brief Verbosity (0 = quiet; 1 = noisy; 2 = noisier) */ + int verbose; + + /** @brief Avoid executiny yields. */ + bool noyields; + + /** @brief Only explore branches. */ + bool branches; + + /** @brief Command-line argument count to pass to user program */ + int argc; + + /** @brief Command-line arguments to pass to user program */ + char **argv; +}; + +#endif /* __PARAMS_H__ */ diff --git a/planner.cc b/planner.cc new file mode 100644 index 0000000..5ca24af --- /dev/null +++ b/planner.cc @@ -0,0 +1,422 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "planner.h" +#include "mcexecution.h" +#include "mcschedule.h" +#include "mcutil.h" +#include "constgen.h" +#include "change.h" + +Planner::Planner(MCExecution * execution) : + e(execution), + changeset(new ChangeHashSet()), + completedset(new ChangeHashSet()), + cgen(new ConstGen(execution)), + finished(false) +{ +} + +Planner::~Planner() { + delete changeset; + delete completedset; + delete cgen; +} + +bool Planner::is_finished() { + return finished; +} + +void Planner::plan() { + DEBUG("Planning\n"); + e->get_scheduler()->reset(); + + if (!cgen->canReuseEncoding()) { + processChanges(); + cgen->reset(); + if (cgen->process()) + finished=true; + } +} + +void Planner::addChange(MCChange *change) { + if (!changeset->add(change)) { + delete change; + } +} + +void Planner::processChanges() { + ChangeIterator *cit=changeset->iterator(); + for(;cit->hasNext();) { + MCChange *change=cit->next(); + cit->remove(); + if (completedset->contains(change)) { + delete change; + continue; + } + if (change->isFunction()) { + processFunction(change); + } else if (change->isEquals()) { + processEquals(change); + } else if (change->isLoad()) { + processLoad(change); + } else if (change->isRMW()) { + processRMW(change); + } else if (change->isStore()) { + processStore(change); + } else ASSERT(false); + completedset->add(change); + } + delete cit; + + for(cit=completedset->iterator();cit->hasNext();) { + MCChange *change=cit->next(); + cit->remove(); + delete change; + } + delete cit; +} + +void Planner::processFunction(MCChange * change) { + processNewReturnValue(change); +} + +void Planner::processEquals(MCChange * change) { + processNewReturnValue(change); +} + +void Planner::processRMW(MCChange * change) { + switch(change->getIndex()) { + case VC_ADDRINDEX: + processNewStoreAddress(change); + break; + case VC_RMWOUTINDEX: + processNewStoreValue(change); + break; + case VC_VALOUTINDEX: + //Return value of the RMW action + processNewReturnValue(change); + break; + default: + ASSERT(false); + } +} + +void Planner::processLoad(MCChange * change) { + switch(change->getIndex()) { + case VC_ADDRINDEX: + processNewLoadAddress(change); + break; + case VC_VALOUTINDEX: + processNewReturnValue(change); + break; + default: + ASSERT(0); + } +} + +void Planner::processStore(MCChange * change) { + switch(change->getIndex()) { + case VC_ADDRINDEX: + processNewStoreAddress(change); + break; + case VC_BASEINDEX: + processNewStoreValue(change); + break; + default: + ASSERT(0); + } +} + +/** This function propagate news values that a function or add + operation may generate. +*/ + +void Planner::processNewReturnValue(MCChange *change) { + EPRecord *record=change->getRecord(); + EPRecordSet *dependences=e->getDependences(record); + if (dependences==NULL) + return; + EPRecordIterator *rit=dependences->iterator(); + while(rit->hasNext()) { + struct RecordIntPair *deprecord=rit->next(); + registerValue(deprecord->record, change->getValue(), deprecord->index); + } + delete rit; +} + +/** This function registers a new address for a load operation. We + iterate over all stores to that new address and grab their values + and propagate them. +*/ + +void Planner::processNewLoadAddress(MCChange *change) { + EPRecord *load=change->getRecord(); + void *addr=(void *)change->getValue(); + RecordSet *storeset=e->getStoreTable(addr); + if (storeset == NULL) + return; + RecordIterator *rit=storeset->iterator(); + while(rit->hasNext()) { + EPRecord *store=rit->next(); + if (e->compatibleStoreLoad(store, load)) { + IntIterator * it=store->getStoreSet()->iterator(); + while(it->hasNext()) { + uint64_t st_val=it->next(); + //should propagate value further + //we should worry about redudant values... + registerValue(load, st_val, VC_RFINDEX); + } + delete it; + } + } + delete rit; +} + +/** This function processes a new address for a store. We push our + values to all loads from that address. */ + +void Planner::processNewStoreAddress(MCChange *change) { + EPRecord *store=change->getRecord(); + void *addr=(void *)change->getValue(); + RecordSet *rset=e->getLoadTable(addr); + if (rset == NULL) + return; + RecordIterator *rit=rset->iterator(); + IntHashSet *valset=store->getStoreSet(); + while(rit->hasNext()) { + EPRecord *load=rit->next(); + if (e->compatibleStoreLoad(store, load)) { + //iterate through all values + IntIterator *iit=valset->iterator(); + while(iit->hasNext()) { + uint64_t val=iit->next(); + registerValue(load, val, VC_RFINDEX); + } + delete iit; + } + } + delete rit; +} + + +/** This function pushes a new store value to all loads that share an + address. */ + +void Planner::processNewStoreValue(MCChange *change) { + EPRecord *store=change->getRecord(); + uint64_t val=change->getValue(); + IntHashSet *addrset=store->getSet(VC_ADDRINDEX); + IntIterator *ait=addrset->iterator(); + while(ait->hasNext()) { + void *addr=(void*)ait->next(); + RecordSet *rset=e->getLoadTable(addr); + if (rset == NULL) + continue; + RecordIterator *rit=rset->iterator(); + while(rit->hasNext()) { + EPRecord *load=rit->next(); + if (e->compatibleStoreLoad(store, load)) { + registerValue(load, val, VC_RFINDEX); + } + } + delete rit; + } + delete ait; +} + + +void Planner::registerValue(EPRecord *record, uint64_t val, unsigned int index) { + switch(record->getType()) { + case LOAD: + registerLoadValue(record, val, index); + break; + case RMW: + registerRMWValue(record, val, index); + break; + case STORE: + registerStoreValue(record, val, index); + break; + case FUNCTION: + registerFunctionValue(record, val, index); + break; + case EQUALS: + registerEqualsValue(record, val, index); + break; + case BRANCHDIR: + registerBranchValue(record, val, index); + break; + case MERGE: + break; + default: + model_print("Unrecognized event %u\n",record->getType()); + } +} + +void Planner::registerBranchValue(EPRecord *record, uint64_t val, unsigned int index) { + record->getSet(index)->add(val); +} + +void Planner::registerLoadValue(EPRecord *record, uint64_t val, unsigned int index) { + if (index==VC_ADDRINDEX) + val+=record->getOffset(); + + bool is_new=record->getSet(index)->add(val); + if (is_new) { + switch(index) { + case VC_ADDRINDEX: { + e->addLoadTable((void *)val, record); + MCChange *change=new MCChange(record, val, VC_ADDRINDEX); + addChange(change); + break; + } + case VC_RFINDEX: { + //New value we can read...Push it... + MCChange *change=new MCChange(record, val, VC_VALOUTINDEX); + addChange(change); + break; + } + default: + ASSERT(0); + } + } +} + + +void Planner::registerRMWValue(EPRecord *record, uint64_t val, unsigned int index) { + if (index==VC_ADDRINDEX) + val+=record->getOffset(); + + bool is_new=record->getSet(index)->add(val); + if (is_new) { + switch(index) { + case VC_ADDRINDEX: + doRMWNewAddrChange(record, val); + break; + case VC_RFINDEX: + doRMWRFChange(record, val); + break; + case VC_BASEINDEX: + doRMWBaseChange(record, val); + break; + case VC_OLDVALCASINDEX: + ASSERT(record->getOp()==CAS); + doRMWOldValChange(record); + break; + default: + ASSERT(0); + } + } +} + +void Planner::doRMWNewAddrChange(EPRecord *record, uint64_t val) { + e->addLoadTable((void *)val, record); + e->addStoreTable((void *)val, record); + + //propagate our value to new loads + MCChange * change=new MCChange(record, val, VC_ADDRINDEX); + addChange(change); + + //look at new stores and update our read from set + RecordSet *storeset=e->getStoreTable((void *)val); + RecordIterator *rit=storeset->iterator(); + while(rit->hasNext()) { + EPRecord *store=rit->next(); + + if (e->compatibleStoreLoad(store, record)) { + IntIterator * it=store->getStoreSet()->iterator(); + while(it->hasNext()) { + uint64_t st_val=it->next(); + //should propagate value further + //we should worry about redudant values... + registerRMWValue(record, st_val, VC_RFINDEX); + } + delete it; + } + } + delete rit; +} + +void Planner::doRMWRFChange(EPRecord *record, uint64_t readval) { + //Register the new value we might return + MCChange *change=new MCChange(record, readval, VC_VALOUTINDEX); + addChange(change); + + if (record->getOp()==CAS) { + //Register the new value we might store if we are a CAS + bool is_new=record->getStoreSet()->add(readval); + if (is_new) { + MCChange *change=new MCChange(record, readval, VC_RMWOUTINDEX); + addChange(change); + } + } +} + +void Planner::doRMWBaseChange(EPRecord *record, uint64_t baseval) { + if (record->getOp()==CAS) { + //Just push the value as though it is our output + bool is_new=record->getStoreSet()->add(baseval); + if (is_new) { + MCChange *change=new MCChange(record, baseval, VC_RMWOUTINDEX); + addChange(change); + } + } else if (record->getOp()==ADD) { + //Tricky here because we could create an infinite propagation... + //So we drop it... + //TODO: HANDLE THIS CASE + } else if (record->getOp()==EXC) { + //no need to propagate output + } else { + ASSERT(0); + } +} + +void Planner::doRMWOldValChange(EPRecord *record) { + //Do nothing, no need to propagate old value... +} + +void Planner::registerStoreValue(EPRecord *record, uint64_t val, unsigned int index) { + if (index==VC_ADDRINDEX) + val+=record->getOffset(); + + bool is_new=record->getSet(index)->add(val); + + if (index==VC_ADDRINDEX) { + if (is_new) + e->addStoreTable((void *)val, record); + MCChange * change=new MCChange(record, val, index); + addChange(change); + } else if (index==VC_BASEINDEX) { + MCChange * change=new MCChange(record, val, index); + addChange(change); + } else model_print("ERROR in RSV\n"); +} + +void Planner::registerEqualsValue(EPRecord *record, uint64_t val, unsigned int index) { + record->getSet(index)->add(val); +} + +void Planner::registerFunctionValue(EPRecord *record, uint64_t val, unsigned int index) { + bool newval=record->getSet(index)->add(val); + + if (record->getPhi()) { + MCChange * change=new MCChange(record, val, VC_FUNCOUTINDEX); + addChange(change); + return; + } else if (newval && record->isSharedGoals()) { + CGoalIterator *cit=record->completedGoalSet()->iterator(); + while(cit->hasNext()) { + CGoal *goal=cit->next(); + if (goal->getValue(index)==val) { + e->evalGoal(record, goal); + } + } + delete cit; + } +} diff --git a/planner.h b/planner.h new file mode 100644 index 0000000..9f35ddd --- /dev/null +++ b/planner.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef PLANNER_H +#define PLANNER_H +#include "classlist.h" +#include "hashset.h" +#include "mymemory.h" +#include "change.h" + +typedef HashSet ChangeHashSet; +typedef HSIterator ChangeIterator; + +enum PlanResult {NOSCHEDULE, SCHEDULED}; + +class Planner { + public: + Planner(MCExecution * e); + ~Planner(); + bool is_finished(); + void plan(); + void addChange(MCChange *change); + void processChanges(); + void processEquals(MCChange * change); + void processFunction(MCChange * change); + void processRMW(MCChange * change); + void processLoad(MCChange * change); + void processStore(MCChange * change); + bool checkConstGraph(EPRecord *record, uint64_t val); + void registerValue(EPRecord *record, uint64_t val, unsigned int index); + ConstGen * getConstGen() {return cgen;} + + MEMALLOC; + +private: + void registerBranchValue(EPRecord *record, uint64_t val, unsigned int index); + void registerLoadValue(EPRecord *record, uint64_t val, unsigned int index); + void registerRMWValue(EPRecord *record, uint64_t val, unsigned int index); + void registerStoreValue(EPRecord *record, uint64_t val, unsigned int index); + void registerFunctionValue(EPRecord *record, uint64_t val, unsigned int index); + void registerEqualsValue(EPRecord *record, uint64_t val, unsigned int index); + void doRMWRFChange(EPRecord *record, uint64_t readval); + void doRMWBaseChange(EPRecord *record, uint64_t baseval); + void doRMWOldValChange(EPRecord *record); + void doRMWNewAddrChange(EPRecord *record, uint64_t addr); + + + + void processNewStoreAddress(MCChange *change); + void processNewStoreValue(MCChange *change); + void processNewReturnValue(MCChange *change); + void processNewLoadAddress(MCChange *change); + MCExecution * e; + ChangeHashSet * changeset; + ChangeHashSet * completedset; + ConstGen *cgen; + bool finished; +}; +#endif diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..fab71a7 --- /dev/null +++ b/run.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# Runs a simple test (default: ./test/userprog.o) +# Syntax: +# ./run.sh [test program] [OPTIONS] +# ./run.sh [OPTIONS] +# ./run.sh [gdb [test program]] +# +# If you include a 'gdb' argument, the your program will be launched with gdb. +# You can also supply a test program argument to run something besides the +# default program. +# + +BIN=./test/userprog.o +PREFIX= + +export LD_LIBRARY_PATH=. +# For Mac OSX +export DYLD_LIBRARY_PATH=. +export PATH=.:$PATH +[ $# -gt 0 ] && [ "$1" = "gdb" ] && PREFIX=gdb && shift +[ $# -gt 0 ] && [ "$1" = "apple" ] && PREFIX=gdb-apple && shift +[ $# -gt 0 ] && [ "$1" = "lldb" ] && PREFIX=lldb && shift +[ $# -gt 0 ] && [ -e "$1" ] && BIN="$1" && shift + +set -xe +$PREFIX $BIN $@ diff --git a/schedulebuilder.cc b/schedulebuilder.cc new file mode 100644 index 0000000..4473c74 --- /dev/null +++ b/schedulebuilder.cc @@ -0,0 +1,219 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "schedulebuilder.h" +#include "mcexecution.h" +#include "mcschedule.h" +#include "constgen.h" +#include "branchrecord.h" +#include "storeloadset.h" + +ScheduleBuilder::ScheduleBuilder(MCExecution *_execution, ConstGen *cgen) : + cg(cgen), + execution(_execution), + scheduler(execution->get_scheduler()) +{ +} + +ScheduleBuilder::~ScheduleBuilder() { +} + + +void neatPrint(EPRecord *r, ConstGen *cgen, bool *satsolution) { + StoreLoadSet * sls=cgen->getStoreLoadSet(r); + r->print(); + model_print("address=%p ", sls->getAddressEncoding(cgen, r, satsolution)); + switch(r->getType()) { + case LOAD: { + model_print("rd=%lu ", sls->getValueEncoding(cgen, r, satsolution)); + } + break; + case STORE: { + model_print("wr=%lu ", sls->getValueEncoding(cgen, r, satsolution)); + + } + break; + case RMW: { + model_print("rd=%lu ", sls->getRMWRValueEncoding(cgen, r, satsolution)); + model_print("wr=%lu ", sls->getValueEncoding(cgen, r, satsolution)); + } + default: + ; + } + model_print("\n"); +} + +void ScheduleBuilder::buildSchedule(bool * satsolution) { + threads.push_back(execution->getEPRecord(MCID_FIRST)); + lastoperation.push_back(NULL); +#ifdef TSO + stores.push_back(new SnapList()); + storelastoperation.push_back(NULL); +#endif + while(true) { + //Loop over threads...getting rid of non-load/store actions + for(uint index=0;indexgetType()==STORE) { + stores[index]->push_back(next); + next=getNextRecord(next); + } else if (next->getType()==FENCE) { + if (!stores[index]->empty()) + scheduler->addWaitPair(next, stores[index]->back()); + next=getNextRecord(next); + } else if (next->getType()==RMW) { + if (!stores[index]->empty()) + scheduler->addWaitPair(next, stores[index]->back()); + } + } +#endif + if (next!=record) { + threads[index]=next; + index=index-1; + } + } + //Now we have just memory operations, find the first one...make it go first + EPRecord *earliest=NULL; + + for(uint index=0;indexgetOrder(record, earliest, satsolution))) { + earliest=record; + } +#ifdef TSO + if (!stores[index]->empty()) { + record=stores[index]->front(); + + if (record!=NULL && (earliest==NULL || + cg->getOrder(record, earliest, satsolution))) { + earliest=record; + } + } +#endif + } + + if (earliest == NULL) + break; + + for(uint index=0;indexaddWaitPair(earliest, last); + } + } +#ifdef TSO + EPRecord *recstore; + if (!stores[index]->empty() && (recstore=stores[index]->front())==earliest) { + //Update index in vector for current thread + stores[index]->pop_front(); + storelastoperation[index]=recstore; + } else { + EPRecord *last=storelastoperation[index]; + if (last!=NULL) { + scheduler->addWaitPair(earliest, last); + } + } +#endif + } + } +} + +EPRecord * ScheduleBuilder::getNextRecord(EPRecord *record) { + EPRecord *next=record->getNextRecord(); + + //If this branch exit isn't in the current model, we should not go + //there... + if (record->getType()==BRANCHDIR && next!=NULL) { + BranchRecord *br=cg->getBranchRecord(record); + if (!br->hasNextRecord()) + next=NULL; + } + + if (next==NULL && record->getBranch()!=NULL) { + EPValue * epbr=record->getBranch(); + EPRecord *branch=epbr->getRecord(); + if (branch!=NULL) { + return getNextRecord(branch); + } + } + return next; +} + +EPRecord * ScheduleBuilder::processRecord(EPRecord *record, bool *satsolution) { + switch(record->getType()) { + case LOAD: + case STORE: + case RMW: +#ifdef TSO + case FENCE: +#endif + return record; + case LOOPENTER: { + return record->getChildRecord(); + break; + } + case BRANCHDIR: { + BranchRecord *br=cg->getBranchRecord(record); + int index=br->getBranchValue(satsolution); + + if (index>=0 && index < br->numDirections()) { + EPValue *val=record->getValue(index); + EPRecord *branchrecord=val->getFirstRecord(); + if (branchrecord!=NULL) + return branchrecord; + } + //otherwise just go past the branch...we don't know what this code is going to do + break; + } + case LOOPSTART: + case MERGE: + case ALLOC: + case EQUALS: + case FUNCTION: + /* Continue executing */ + break; + case THREADCREATE: + /* Start next thread */ + threads.push_back(record->getChildRecord()); + lastoperation.push_back(NULL); +#ifdef TSO + stores.push_back(new SnapList()); + storelastoperation.push_back(NULL); +#endif + break; + case THREADBEGIN: + break; + case THREADJOIN: + break; + case NONLOCALTRANS: + break; + case LABEL: + break; + case YIELD: + break; + default: + ASSERT(0); + } + return getNextRecord(record); +} diff --git a/schedulebuilder.h b/schedulebuilder.h new file mode 100644 index 0000000..be27aac --- /dev/null +++ b/schedulebuilder.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef SCHEDULEBUILDER_H +#define SCHEDULEBUILDER_H +#include "classlist.h" +#include "stl-model.h" + +class ScheduleBuilder { + public: + ScheduleBuilder(MCExecution *_execution, ConstGen *cgen); + ~ScheduleBuilder(); + void buildSchedule(bool *satsolution); + + SNAPSHOTALLOC; + private: + EPRecord * getNextRecord(EPRecord *record); + EPRecord * processRecord(EPRecord *record, bool * satsolution); + ConstGen * cg; + MCExecution *execution; + MCScheduler *scheduler; + SnapVector threads; +#ifdef TSO + SnapVector *> stores; + SnapVector storelastoperation; +#endif + SnapVector lastoperation; +}; +#endif diff --git a/snapshot-interface.cc b/snapshot-interface.cc new file mode 100644 index 0000000..4f9a4d5 --- /dev/null +++ b/snapshot-interface.cc @@ -0,0 +1,198 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include "snapshot-interface.h" +#include "snapshot.h" +#include "common.h" +#include "mymemory.h" +#include "stl-model.h" + +/* MYBINARYNAME only works because our pathname usually includes 'model' (e.g., + * /.../model-checker/test/userprog.o) */ +#define MYBINARYNAME "model" +#define MAPFILE "/proc/self/maps" + +struct snapshot_entry { + snapshot_entry(snapshot_id id, int idx) : snapshotid(id), index(idx) { } + snapshot_id snapshotid; + int index; + MEMALLOC; +}; + +class SnapshotStack { + public: + int backTrackBeforeStep(int seq_index); + void snapshotStep(int seq_index); + + MEMALLOC; + private: + ModelVector stack; +}; + +static SnapshotStack *snap_stack; + +#ifdef MAC +/** The SnapshotGlobalSegments function computes the memory regions + * that may contain globals and then configures the snapshotting + * library to snapshot them. + */ +static void SnapshotGlobalSegments() +{ + int pid = getpid(); + char buf[9000], execname[100]; + FILE *map; + + sprintf(execname, "vmmap -interleaved %d", pid); + map = popen(execname, "r"); + + if (!map) { + perror("popen"); + exit(EXIT_FAILURE); + } + + /* Wait for correct part */ + while (fgets(buf, sizeof(buf), map)) { + if (strstr(buf, "==== regions for process")) + break; + } + + while (fgets(buf, sizeof(buf), map)) { + char regionname[200] = ""; + char type[23]; + char smstr[23]; + char r, w, x; + char mr, mw, mx; + int size; + void *begin, *end; + + //Skip out at the end of the section + if (buf[0] == '\n') + break; + + sscanf(buf, "%22s %p-%p [%5dK] %c%c%c/%c%c%c SM=%3s %200s\n", type, &begin, &end, &size, &r, &w, &x, &mr, &mw, &mx, smstr, regionname); + + if (w == 'w' && strstr(regionname, MYBINARYNAME)) { + size_t len = ((uintptr_t)end - (uintptr_t)begin) / PAGESIZE; + if (len != 0) + snapshot_add_memory_region(begin, len); + } + } + pclose(map); +} +#else + +static void get_binary_name(char *buf, size_t len) +{ + ssize_t size = readlink("/proc/self/exe", buf, len); + if (size < 0) { + perror("readlink"); + exit(EXIT_FAILURE); + } + + /* Terminate string */ + if ((size_t)size > len) + size = len; + buf[size] = '\0'; +} + +/** The SnapshotGlobalSegments function computes the memory regions + * that may contain globals and then configures the snapshotting + * library to snapshot them. + */ +static void SnapshotGlobalSegments() +{ + char buf[9000]; + char binary_name[800]; + + int map = open(MAPFILE, O_RDONLY); + if (!map) { + perror("fopen"); + exit(EXIT_FAILURE); + } + get_binary_name(binary_name, sizeof(binary_name)); + bool done=false; + while (!done) { + for(uint i=0;i= 0; i++) + if (stack[i].index <= seqindex) + break; + else + stack.pop_back(); + + ASSERT(i >= 0); + snapshot_roll_back(stack[i].snapshotid); + return stack[i].index; +} + +/** This method takes a snapshot at the given sequence number. */ +void SnapshotStack::snapshotStep(int seqindex) +{ + stack.push_back(snapshot_entry(take_snapshot(), seqindex)); +} + +void snapshot_stack_init() +{ + snap_stack = new SnapshotStack(); + SnapshotGlobalSegments(); +} + +void snapshot_record(int seq_index) +{ + snap_stack->snapshotStep(seq_index); +} + +int snapshot_backtrack_before(int seq_index) +{ + return snap_stack->backTrackBeforeStep(seq_index); +} diff --git a/snapshot-interface.h b/snapshot-interface.h new file mode 100644 index 0000000..7c8516c --- /dev/null +++ b/snapshot-interface.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** + * @file snapshot-interface.h + * @brief C interface layer on top of snapshotting system + */ + +#ifndef __SNAPINTERFACE_H +#define __SNAPINTERFACE_H + +typedef unsigned int snapshot_id; + +typedef void (*VoidFuncPtr)(); +void snapshot_system_init(unsigned int numbackingpages, + unsigned int numsnapshots, unsigned int nummemoryregions, + unsigned int numheappages, VoidFuncPtr entryPoint); + +void snapshot_stack_init(); +void snapshot_record(int seq_index); +int snapshot_backtrack_before(int seq_index); + +#endif diff --git a/snapshot.cc b/snapshot.cc new file mode 100644 index 0000000..d06b887 --- /dev/null +++ b/snapshot.cc @@ -0,0 +1,495 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hashtable.h" +#include "snapshot.h" +#include "mymemory.h" +#include "common.h" +#include "context.h" + +/** PageAlignedAdressUpdate return a page aligned address for the + * address being added as a side effect the numBytes are also changed. + */ +static void * PageAlignAddressUpward(void *addr) +{ + return (void *)((((uintptr_t)addr) + PAGESIZE - 1) & ~(PAGESIZE - 1)); +} + +#if USE_MPROTECT_SNAPSHOT + +/* Each SnapShotRecord lists the firstbackingpage that must be written to + * revert to that snapshot */ +struct SnapShotRecord { + unsigned int firstBackingPage; +}; + +/** @brief Backing store page */ +typedef unsigned char snapshot_page_t[PAGESIZE]; + +/* List the base address of the corresponding page in the backing store so we + * know where to copy it to */ +struct BackingPageRecord { + void *basePtrOfPage; +}; + +/* Struct for each memory region */ +struct MemoryRegion { + void *basePtr; // base of memory region + int sizeInPages; // size of memory region in pages +}; + +/** ReturnPageAlignedAddress returns a page aligned address for the + * address being added as a side effect the numBytes are also changed. + */ +static void * ReturnPageAlignedAddress(void *addr) +{ + return (void *)(((uintptr_t)addr) & ~(PAGESIZE - 1)); +} + +/* Primary struct for snapshotting system */ +struct mprot_snapshotter { + mprot_snapshotter(unsigned int numbackingpages, unsigned int numsnapshots, unsigned int nummemoryregions); + ~mprot_snapshotter(); + + struct MemoryRegion *regionsToSnapShot; //This pointer references an array of memory regions to snapshot + snapshot_page_t *backingStore; //This pointer references an array of snapshotpage's that form the backing store + void *backingStoreBasePtr; //This pointer references an array of snapshotpage's that form the backing store + struct BackingPageRecord *backingRecords; //This pointer references an array of backingpagerecord's (same number of elements as backingstore + struct SnapShotRecord *snapShots; //This pointer references the snapshot array + + unsigned int lastSnapShot; //Stores the next snapshot record we should use + unsigned int lastBackingPage; //Stores the next backingpage we should use + unsigned int lastRegion; //Stores the next memory region to be used + + unsigned int maxRegions; //Stores the max number of memory regions we support + unsigned int maxBackingPages; //Stores the total number of backing pages + unsigned int maxSnapShots; //Stores the total number of snapshots we allow + + MEMALLOC; +}; + +static struct mprot_snapshotter *mprot_snap = NULL; + +mprot_snapshotter::mprot_snapshotter(unsigned int backing_pages, unsigned int snapshots, unsigned int regions) : + lastSnapShot(0), + lastBackingPage(0), + lastRegion(0), + maxRegions(regions), + maxBackingPages(backing_pages), + maxSnapShots(snapshots) +{ + regionsToSnapShot = (struct MemoryRegion *)model_malloc(sizeof(struct MemoryRegion) * regions); + backingStoreBasePtr = (void *)model_malloc(sizeof(snapshot_page_t) * (backing_pages + 1)); + //Page align the backingstorepages + backingStore = (snapshot_page_t *)PageAlignAddressUpward(backingStoreBasePtr); + backingRecords = (struct BackingPageRecord *)model_malloc(sizeof(struct BackingPageRecord) * backing_pages); + snapShots = (struct SnapShotRecord *)model_malloc(sizeof(struct SnapShotRecord) * snapshots); +} + +mprot_snapshotter::~mprot_snapshotter() +{ + model_free(regionsToSnapShot); + model_free(backingStoreBasePtr); + model_free(backingRecords); + model_free(snapShots); +} + +/** mprot_handle_pf is the page fault handler for mprotect based snapshotting + * algorithm. + */ +static void mprot_handle_pf(int sig, siginfo_t *si, void *unused) +{ + if (si->si_code == SEGV_MAPERR) { + model_print("Segmentation fault at %p\n", si->si_addr); + model_print("For debugging, place breakpoint at: %s:%d\n", + __FILE__, __LINE__); + // print_trace(); // Trace printing may cause dynamic memory allocation + exit(EXIT_FAILURE); + } + void* addr = ReturnPageAlignedAddress(si->si_addr); + + unsigned int backingpage = mprot_snap->lastBackingPage++; //Could run out of pages... + if (backingpage == mprot_snap->maxBackingPages) { + model_print("Out of backing pages at %p\n", si->si_addr); + exit(EXIT_FAILURE); + } + + //copy page + memcpy(&(mprot_snap->backingStore[backingpage]), addr, sizeof(snapshot_page_t)); + //remember where to copy page back to + mprot_snap->backingRecords[backingpage].basePtrOfPage = addr; + //set protection to read/write + if (mprotect(addr, sizeof(snapshot_page_t), PROT_READ | PROT_WRITE)) { + perror("mprotect"); + // Handle error by quitting? + } +} + +static void mprot_snapshot_init(unsigned int numbackingpages, + unsigned int numsnapshots, unsigned int nummemoryregions, + unsigned int numheappages, VoidFuncPtr entryPoint) +{ + /* Setup a stack for our signal handler.... */ + stack_t ss; + ss.ss_sp = PageAlignAddressUpward(model_malloc(SIGSTACKSIZE + PAGESIZE - 1)); + ss.ss_size = SIGSTACKSIZE; + ss.ss_flags = 0; + sigaltstack(&ss, NULL); + + struct sigaction sa; + sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_RESTART | SA_ONSTACK; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = mprot_handle_pf; +#ifdef MAC + if (sigaction(SIGBUS, &sa, NULL) == -1) { + perror("sigaction(SIGBUS)"); + exit(EXIT_FAILURE); + } +#endif + if (sigaction(SIGSEGV, &sa, NULL) == -1) { + perror("sigaction(SIGSEGV)"); + exit(EXIT_FAILURE); + } + + mprot_snap = new mprot_snapshotter(numbackingpages, numsnapshots, nummemoryregions); + + // EVIL HACK: We need to make sure that calls into the mprot_handle_pf method don't cause dynamic links + // The problem is that we end up protecting state in the dynamic linker... + // Solution is to call our signal handler before we start protecting stuff... + + siginfo_t si; + memset(&si, 0, sizeof(si)); + si.si_addr = ss.ss_sp; + mprot_handle_pf(SIGSEGV, &si, NULL); + mprot_snap->lastBackingPage--; //remove the fake page we copied + + + void *basemySpace = model_malloc((numheappages -32 + 1) * PAGESIZE); + void *pagealignedbase = PageAlignAddressUpward(basemySpace); + user_snapshot_space = pagealignedbase; + snapshot_add_memory_region(pagealignedbase, numheappages-32); + + void *basethreadSpace = model_malloc(33 * PAGESIZE); + pagealignedbase = PageAlignAddressUpward(basethreadSpace); + thread_snapshot_space = create_mspace_with_base(pagealignedbase, 32 * PAGESIZE, 1); + snapshot_add_memory_region(pagealignedbase, 32); + + void *base_model_snapshot_space = model_malloc((numheappages + 1) * PAGESIZE); + pagealignedbase = PageAlignAddressUpward(base_model_snapshot_space); + model_snapshot_space = create_mspace_with_base(pagealignedbase, numheappages * PAGESIZE, 1); + snapshot_add_memory_region(pagealignedbase, numheappages); + + snapshot_struct = (struct snapshot_heap_data *) model_malloc(sizeof(struct snapshot_heap_data)); + snapshot_struct->allocation_ptr=user_snapshot_space; + snapshot_struct->top_ptr=(void *)(((char *)user_snapshot_space)+((numheappages-32)*PAGESIZE)); + + entryPoint(); +} + +static void mprot_add_to_snapshot(void *addr, unsigned int numPages) +{ + unsigned int memoryregion = mprot_snap->lastRegion++; + if (memoryregion == mprot_snap->maxRegions) { + model_print("Exceeded supported number of memory regions!\n"); + exit(EXIT_FAILURE); + } + + DEBUG("snapshot region %p-%p (%u page%s)\n", + addr, (char *)addr + numPages * PAGESIZE, numPages, + numPages > 1 ? "s" : ""); + mprot_snap->regionsToSnapShot[memoryregion].basePtr = addr; + mprot_snap->regionsToSnapShot[memoryregion].sizeInPages = numPages; +} + +static snapshot_id mprot_take_snapshot() +{ + for (unsigned int region = 0; region < mprot_snap->lastRegion; region++) { + if (mprotect(mprot_snap->regionsToSnapShot[region].basePtr, mprot_snap->regionsToSnapShot[region].sizeInPages * sizeof(snapshot_page_t), PROT_READ) == -1) { + perror("mprotect"); + model_print("Failed to mprotect inside of takeSnapShot\n"); + exit(EXIT_FAILURE); + } + } + unsigned int snapshot = mprot_snap->lastSnapShot++; + if (snapshot == mprot_snap->maxSnapShots) { + model_print("Out of snapshots\n"); + exit(EXIT_FAILURE); + } + mprot_snap->snapShots[snapshot].firstBackingPage = mprot_snap->lastBackingPage; + + return snapshot; +} + +static void mprot_roll_back(snapshot_id theID) +{ +#if USE_MPROTECT_SNAPSHOT == 2 + if (mprot_snap->lastSnapShot == (theID + 1)) { + for (unsigned int page = mprot_snap->snapShots[theID].firstBackingPage; page < mprot_snap->lastBackingPage; page++) { + memcpy(mprot_snap->backingRecords[page].basePtrOfPage, &mprot_snap->backingStore[page], sizeof(snapshot_page_t)); + } + return; + } +#endif + + HashTable< void *, bool, uintptr_t, 4, model_malloc, model_calloc, model_free> duplicateMap; + for (unsigned int region = 0; region < mprot_snap->lastRegion; region++) { + if (mprotect(mprot_snap->regionsToSnapShot[region].basePtr, mprot_snap->regionsToSnapShot[region].sizeInPages * sizeof(snapshot_page_t), PROT_READ | PROT_WRITE) == -1) { + perror("mprotect"); + model_print("Failed to mprotect inside of takeSnapShot\n"); + exit(EXIT_FAILURE); + } + } + for (unsigned int page = mprot_snap->snapShots[theID].firstBackingPage; page < mprot_snap->lastBackingPage; page++) { + if (!duplicateMap.contains(mprot_snap->backingRecords[page].basePtrOfPage)) { + duplicateMap.put(mprot_snap->backingRecords[page].basePtrOfPage, true); + memcpy(mprot_snap->backingRecords[page].basePtrOfPage, &mprot_snap->backingStore[page], sizeof(snapshot_page_t)); + } + } + mprot_snap->lastSnapShot = theID; + mprot_snap->lastBackingPage = mprot_snap->snapShots[theID].firstBackingPage; + mprot_take_snapshot(); //Make sure current snapshot is still good...All later ones are cleared +} + +#else /* !USE_MPROTECT_SNAPSHOT */ + +#define SHARED_MEMORY_DEFAULT (100 * ((size_t)1 << 20)) // 100mb for the shared memory +#define STACK_SIZE_DEFAULT (((size_t)1 << 20) * 20) // 20 mb out of the above 100 mb for my stack + +struct fork_snapshotter { + /** @brief Pointer to the shared (non-snapshot) memory heap base + * (NOTE: this has size SHARED_MEMORY_DEFAULT - sizeof(*fork_snap)) */ + void *mSharedMemoryBase; + + /** @brief Pointer to the shared (non-snapshot) stack region */ + void *mStackBase; + + /** @brief Size of the shared stack */ + size_t mStackSize; + + /** + * @brief Stores the ID that we are attempting to roll back to + * + * Used in inter-process communication so that each process can + * determine whether or not to take over execution (w/ matching ID) or + * exit (we're rolling back even further). Dubiously marked 'volatile' + * to prevent compiler optimizations from messing with the + * inter-process behavior. + */ + volatile snapshot_id mIDToRollback; + + /** + * @brief The context for the shared (non-snapshot) stack + * + * This context is passed between the various processes which represent + * various snapshot states. It should be used primarily for the + * "client-side" code, not the main snapshot loop. + */ + ucontext_t shared_ctxt; + + /** @brief Inter-process tracking of the next snapshot ID */ + snapshot_id currSnapShotID; +}; + +static struct fork_snapshotter *fork_snap = NULL; + +/** @statics +* These variables are necessary because the stack is shared region and +* there exists a race between all processes executing the same function. +* To avoid the problem above, we require variables allocated in 'safe' regions. +* The bug was actually observed with the forkID, these variables below are +* used to indicate the various contexts to which to switch to. +* +* @private_ctxt: the context which is internal to the current process. Used +* for running the internal snapshot/rollback loop. +* @exit_ctxt: a special context used just for exiting from a process (so we +* can use swapcontext() instead of setcontext() + hacks) +* @snapshotid: it is a running counter for the various forked processes +* snapshotid. it is incremented and set in a persistently shared record +*/ +static ucontext_t private_ctxt; +static ucontext_t exit_ctxt; +static snapshot_id snapshotid = 0; + +/** + * @brief Create a new context, with a given stack and entry function + * @param ctxt The context structure to fill + * @param stack The stack to run the new context in + * @param stacksize The size of the stack + * @param func The entry point function for the context + */ +static void create_context(ucontext_t *ctxt, void *stack, size_t stacksize, + void (*func)(void)) +{ + getcontext(ctxt); + ctxt->uc_stack.ss_sp = stack; + ctxt->uc_stack.ss_size = stacksize; + makecontext(ctxt, func, 0); +} + +/** @brief An empty function, used for an "empty" context which just exits a + * process */ +static void fork_exit() +{ + /* Intentionally empty */ +} + +static void createSharedMemory() +{ + //step 1. create shared memory. + void *memMapBase = mmap(0, SHARED_MEMORY_DEFAULT + STACK_SIZE_DEFAULT, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + if (memMapBase == MAP_FAILED) { + perror("mmap"); + exit(EXIT_FAILURE); + } + + //Setup snapshot record at top of free region + fork_snap = (struct fork_snapshotter *)memMapBase; + fork_snap->mSharedMemoryBase = (void *)((uintptr_t)memMapBase + sizeof(*fork_snap)); + fork_snap->mStackBase = (void *)((uintptr_t)memMapBase + SHARED_MEMORY_DEFAULT); + fork_snap->mStackSize = STACK_SIZE_DEFAULT; + fork_snap->mIDToRollback = -1; + fork_snap->currSnapShotID = 0; +} + +/** + * Create a new mspace pointer for the non-snapshotting (i.e., inter-process + * shared) memory region. Only for fork-based snapshotting. + * + * @return The shared memory mspace + */ +mspace create_shared_mspace() +{ + if (!fork_snap) + createSharedMemory(); + return create_mspace_with_base((void *)(fork_snap->mSharedMemoryBase), SHARED_MEMORY_DEFAULT - sizeof(*fork_snap), 1); +} + +static void fork_snapshot_init(unsigned int numbackingpages, + unsigned int numsnapshots, unsigned int nummemoryregions, + unsigned int numheappages, VoidFuncPtr entryPoint) +{ + if (!fork_snap) + createSharedMemory(); + + void *base_model_snapshot_space = malloc((numheappages + 1) * PAGESIZE); + void *pagealignedbase = PageAlignAddressUpward(base_model_snapshot_space); + model_snapshot_space = create_mspace_with_base(pagealignedbase, numheappages * PAGESIZE, 1); + + /* setup an "exiting" context */ + char stack[128]; + create_context(&exit_ctxt, stack, sizeof(stack), fork_exit); + + /* setup the shared-stack context */ + create_context(&fork_snap->shared_ctxt, fork_snap->mStackBase, + STACK_SIZE_DEFAULT, entryPoint); + /* switch to a new entryPoint context, on a new stack */ + model_swapcontext(&private_ctxt, &fork_snap->shared_ctxt); + + /* switch back here when takesnapshot is called */ + snapshotid = fork_snap->currSnapShotID; + + while (true) { + pid_t forkedID; + fork_snap->currSnapShotID = snapshotid + 1; + forkedID = fork(); + + if (0 == forkedID) { + setcontext(&fork_snap->shared_ctxt); + } else { + DEBUG("parent PID: %d, child PID: %d, snapshot ID: %d\n", + getpid(), forkedID, snapshotid); + + while (waitpid(forkedID, NULL, 0) < 0) { + /* waitpid() may be interrupted */ + if (errno != EINTR) { + perror("waitpid"); + exit(EXIT_FAILURE); + } + } + + if (fork_snap->mIDToRollback != snapshotid) + exit(EXIT_SUCCESS); + } + } +} + +static snapshot_id fork_take_snapshot() +{ + model_swapcontext(&fork_snap->shared_ctxt, &private_ctxt); + DEBUG("TAKESNAPSHOT RETURN\n"); + return snapshotid; +} + +static void fork_roll_back(snapshot_id theID) +{ + DEBUG("Rollback\n"); + fork_snap->mIDToRollback = theID; + model_swapcontext(&fork_snap->shared_ctxt, &exit_ctxt); + fork_snap->mIDToRollback = -1; +} + +#endif /* !USE_MPROTECT_SNAPSHOT */ + +/** + * @brief Initializes the snapshot system + * @param entryPoint the function that should run the program. + */ +void snapshot_system_init(unsigned int numbackingpages, + unsigned int numsnapshots, unsigned int nummemoryregions, + unsigned int numheappages, VoidFuncPtr entryPoint) +{ +#if USE_MPROTECT_SNAPSHOT + mprot_snapshot_init(numbackingpages, numsnapshots, nummemoryregions, numheappages, entryPoint); +#else + fork_snapshot_init(numbackingpages, numsnapshots, nummemoryregions, numheappages, entryPoint); +#endif +} + +/** Assumes that addr is page aligned. */ +void snapshot_add_memory_region(void *addr, unsigned int numPages) +{ +#if USE_MPROTECT_SNAPSHOT + mprot_add_to_snapshot(addr, numPages); +#else + /* not needed for fork-based snapshotting */ +#endif +} + +/** Takes a snapshot of memory. + * @return The snapshot identifier. + */ +snapshot_id take_snapshot() +{ +#if USE_MPROTECT_SNAPSHOT + return mprot_take_snapshot(); +#else + return fork_take_snapshot(); +#endif +} + +/** Rolls the memory state back to the given snapshot identifier. + * @param theID is the snapshot identifier to rollback to. + */ +void snapshot_roll_back(snapshot_id theID) +{ +#if USE_MPROTECT_SNAPSHOT + mprot_roll_back(theID); +#else + fork_roll_back(theID); +#endif +} diff --git a/snapshot.h b/snapshot.h new file mode 100644 index 0000000..fae55bb --- /dev/null +++ b/snapshot.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file snapshot.h + * @brief Snapshotting interface header file. + */ + +#ifndef _SNAPSHOT_H +#define _SNAPSHOT_H + +#include "snapshot-interface.h" +#include "config.h" +#include "mymemory.h" + +void snapshot_add_memory_region(void *ptr, unsigned int numPages); +snapshot_id take_snapshot(); +void snapshot_roll_back(snapshot_id theSnapShot); + +#if !USE_MPROTECT_SNAPSHOT +mspace create_shared_mspace(); +#endif + +#endif diff --git a/solver_interface.h b/solver_interface.h new file mode 100644 index 0000000..4fd2dea --- /dev/null +++ b/solver_interface.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef SOLVER_INTERFACE_H +#define SOLVER_INTERFACE_H + +#define IS_OUT_FD 3 + +#define IS_UNSAT 0 +#define IS_SAT 1 +#define IS_INDETER 2 +#define IS_FREEZE 3 +#define IS_RUNSOLVER 4 + +#define IS_BUFFERSIZE 1024 + +#endif diff --git a/stacktrace.h b/stacktrace.h new file mode 100644 index 0000000..7a3ac50 --- /dev/null +++ b/stacktrace.h @@ -0,0 +1,94 @@ +// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/ +// published under the WTFPL v2.0 + +#ifndef __STACKTRACE_H__ +#define __STACKTRACE_H__ + +#include +#include +#include +#include + +/** + * @brief Print a demangled stack backtrace of the caller function to file + * descriptor fd. + */ +static inline void print_stacktrace(int fd = STDERR_FILENO, unsigned int max_frames = 63) +{ + dprintf(fd, "stack trace:\n"); + + // storage array for stack trace address data + void* addrlist[max_frames+1]; + + // retrieve current stack addresses + int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*)); + + if (addrlen == 0) { + dprintf(fd, " \n"); + return; + } + + // resolve addresses into strings containing "filename(function+address)", + // this array must be free()-ed + char** symbollist = backtrace_symbols(addrlist, addrlen); + + // allocate string which will be filled with the demangled function name + size_t funcnamesize = 256; + char* funcname = (char*)malloc(funcnamesize); + + // iterate over the returned symbol lines. skip the first, it is the + // address of this function. + for (int i = 1; i < addrlen; i++) { + char *begin_name = 0, *begin_offset = 0, *end_offset = 0; + + // find parentheses and +address offset surrounding the mangled name: + // ./module(function+0x15c) [0x8048a6d] + for (char *p = symbollist[i]; *p; ++p) { + if (*p == '(') + begin_name = p; + else if (*p == '+') + begin_offset = p; + else if (*p == ')' && begin_offset) { + end_offset = p; + break; + } + } + + if (begin_name && begin_offset && end_offset && begin_name < begin_offset) { + *begin_name++ = '\0'; + *begin_offset++ = '\0'; + *end_offset = '\0'; + + // mangled name is now in [begin_name, begin_offset) and caller + // offset in [begin_offset, end_offset). now apply + // __cxa_demangle(): + + int status; + char* ret = abi::__cxa_demangle(begin_name, + funcname, &funcnamesize, &status); + if (status == 0) { + funcname = ret; // use possibly realloc()-ed string + dprintf(fd, " %s : %s+%s\n", + symbollist[i], funcname, begin_offset); + } else { + // demangling failed. Output function name as a C function with + // no arguments. + dprintf(fd, " %s : %s()+%s\n", + symbollist[i], begin_name, begin_offset); + } + } else { + // couldn't parse the line? print the whole line. + dprintf(fd, " %s\n", symbollist[i]); + } + } + + free(funcname); + free(symbollist); +} + +static inline void print_stacktrace(FILE *out, unsigned int max_frames = 63) +{ + print_stacktrace(fileno(out), max_frames); +} + +#endif // __STACKTRACE_H__ diff --git a/stl-model.h b/stl-model.h new file mode 100644 index 0000000..85bb311 --- /dev/null +++ b/stl-model.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef __STL_MODEL_H__ +#define __STL_MODEL_H__ + +#include +#include +#include "mymemory.h" + +template +class ModelList : public std::list<_Tp, ModelAlloc<_Tp> > +{ + public: + typedef std::list< _Tp, ModelAlloc<_Tp> > list; + + ModelList() : + list() + { } + + ModelList(size_t n, const _Tp& val = _Tp()) : + list(n, val) + { } + + MEMALLOC; +}; + +template +class SnapList : public std::list<_Tp, SnapshotAlloc<_Tp> > +{ + public: + typedef std::list<_Tp, SnapshotAlloc<_Tp> > list; + + SnapList() : + list() + { } + + SnapList(size_t n, const _Tp& val = _Tp()) : + list(n, val) + { } + + SNAPSHOTALLOC; +}; + +template +class ModelVector : public std::vector<_Tp, ModelAlloc<_Tp> > +{ + public: + typedef std::vector< _Tp, ModelAlloc<_Tp> > vector; + + ModelVector() : + vector() + { } + + ModelVector(size_t n, const _Tp& val = _Tp()) : + vector(n, val) + { } + + MEMALLOC; +}; + +template +class SnapVector : public std::vector<_Tp, SnapshotAlloc<_Tp> > +{ + public: + typedef std::vector< _Tp, SnapshotAlloc<_Tp> > vector; + + SnapVector() : + vector() + { } + + SnapVector(size_t n, const _Tp& val = _Tp()) : + vector(n, val) + { } + + SNAPSHOTALLOC; +}; + +#endif /* __STL_MODEL_H__ */ diff --git a/storeloadset.cc b/storeloadset.cc new file mode 100644 index 0000000..7deebb6 --- /dev/null +++ b/storeloadset.cc @@ -0,0 +1,130 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "storeloadset.h" +#include "eprecord.h" +#include "valuerecord.h" +#include "constgen.h" + +StoreLoadSet::StoreLoadSet() : + addrencodings(NULL), + valencodings(NULL) { +} + +StoreLoadSet::~StoreLoadSet() { + if (addrencodings!=NULL) { + delete addrencodings; + delete valencodings; + } + addrvars.resetandfree(); + valvars.resetandfree(); + valrmwrvars.resetandfree(); +} + +void StoreLoadSet::add(EPRecord *op) { + storeloadset.add(op); + IntIterator * it=op->getSet(VC_ADDRINDEX)->iterator(); + while(it->hasNext()) + addresses.add(it->next()); + delete it; + + if (op->getType()==STORE || + op->getType()==RMW) { + it=op->getStoreSet()->iterator(); + while(it->hasNext()) + values.add(it->next()); + delete it; + } +} + +void StoreLoadSet::genEncoding() { + addrencodings=new ValueRecord(&addresses); + valencodings=new ValueRecord(&values); +} + +const void * StoreLoadSet::getAddressEncoding(ConstGen *cg, EPRecord *op, bool *sat) { + Constraint **vars=getAddrVars(cg, op); + return (const void *) addrencodings->getValue(vars, sat); +} + +uint64_t StoreLoadSet::getValueEncoding(ConstGen *cg, EPRecord *op, bool *sat) { + Constraint **vars=getValVars(cg, op); + return valencodings->getValue(vars, sat); +} + +uint64_t StoreLoadSet::getRMWRValueEncoding(ConstGen *cg, EPRecord *op, bool *sat) { + Constraint **vars=getRMWRValVars(cg, op); + return valencodings->getValue(vars, sat); +} + +Constraint * StoreLoadSet::getAddressEncoding(ConstGen *cg, EPRecord *op, const void * addr) { + if (addrencodings==NULL) + genEncoding(); + Constraint **vars=getAddrVars(cg, op); + return addrencodings->getValueEncoding(vars, (uint64_t) addr); +} + +Constraint * StoreLoadSet::getValueEncoding(ConstGen *cg, EPRecord *op, uint64_t val) { + if (valencodings==NULL) + genEncoding(); + Constraint **vars=getValVars(cg, op); + return valencodings->getValueEncoding(vars, val); +} + +Constraint * StoreLoadSet::getRMWRValueEncoding(ConstGen *cg, EPRecord *op, uint64_t val) { + if (valencodings==NULL) + genEncoding(); + Constraint **vars=getRMWRValVars(cg, op); + return valencodings->getValueEncoding(vars, val); +} + +Constraint ** StoreLoadSet::getAddrVars(ConstGen *cg, EPRecord * op) { + Constraint **vars=addrvars.get(op); + if (vars==NULL) { + int numvars=addrencodings->getNumVars(); + vars=(Constraint **)model_malloc(numvars*sizeof(Constraint *)); + cg->getArrayNewVars(numvars, vars); + addrvars.put(op, vars); + } + return vars; +} + +Constraint ** StoreLoadSet::getValVars(ConstGen *cg, EPRecord * op) { + Constraint **vars=valvars.get(op); + if (vars==NULL) { + int numvars=valencodings->getNumVars(); + vars=(Constraint **)model_malloc(numvars*sizeof(Constraint *)); + cg->getArrayNewVars(numvars, vars); + valvars.put(op, vars); + } + return vars; +} + +Constraint ** StoreLoadSet::getRMWRValVars(ConstGen *cg, EPRecord * op) { + Constraint **vars=valrmwrvars.get(op); + if (vars==NULL) { + int numvars=valencodings->getNumVars(); + vars=(Constraint **)model_malloc(numvars*sizeof(Constraint *)); + cg->getArrayNewVars(numvars, vars); + valrmwrvars.put(op, vars); + } + return vars; +} + +uint StoreLoadSet::getNumValVars() { + if (valencodings==NULL) + genEncoding(); + return valencodings->getNumVars(); +} + +uint StoreLoadSet::getNumAddrVars() { + if (addrencodings==NULL) + genEncoding(); + return addrencodings->getNumVars(); +} diff --git a/storeloadset.h b/storeloadset.h new file mode 100644 index 0000000..45e2465 --- /dev/null +++ b/storeloadset.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef STORELOADSET_H +#define STORELOADSET_H +#include "classlist.h" +#include "stl-model.h" + +class StoreLoadSet { + public: + StoreLoadSet(); + ~StoreLoadSet(); + void add(EPRecord *op); + RecordIterator * iterator() {return storeloadset.iterator();} + Constraint * getAddressEncoding(ConstGen *cg, EPRecord *op, const void * addr); + Constraint * getValueEncoding(ConstGen *cg, EPRecord *op, uint64_t val); + Constraint * getRMWRValueEncoding(ConstGen *cg, EPRecord *op, uint64_t val); + + const void * getAddressEncoding(ConstGen *cg, EPRecord *op, bool *); + uint64_t getValueEncoding(ConstGen *cg, EPRecord *op, bool *); + uint64_t getRMWRValueEncoding(ConstGen *cg, EPRecord *op, bool *); + uint getNumAddrVars(); + uint getNumValVars(); + Constraint ** getAddrVars(ConstGen *cg, EPRecord * op); + Constraint ** getValVars(ConstGen *cg, EPRecord * op); + Constraint ** getRMWRValVars(ConstGen *cg, EPRecord * op); + IntHashSet * getValues() {return &values;} + bool removeAddress(const void *addr) {addresses.remove((uint64_t)addr);return addresses.isEmpty();} + + MEMALLOC; + private: + void genEncoding(); + RecordSet storeloadset; + IntHashSet addresses; + IntHashSet values; + VarTable addrvars; + VarTable valvars; + VarTable valrmwrvars; + ValueRecord *addrencodings; + ValueRecord *valencodings; +}; +#endif diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..2a44231 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,23 @@ +BASE := .. + +OBJECTS := $(patsubst %.c, %.o, $(wildcard *.c)) +OBJECTS += $(patsubst %.cc, %.o, $(wildcard *.cc)) + +include $(BASE)/common.mk + +DEPS := $(join $(addsuffix ., $(dir $(OBJECTS))), $(addsuffix .d, $(notdir $(OBJECTS)))) + +CPPFLAGS += -I$(BASE) -I$(BASE)/include + +all: $(OBJECTS) + +-include $(DEPS) + +%.o: %.c + $(CC) -MMD -MF $(@D)/.$(@F).d -o $@ $< $(CPPFLAGS) -L$(BASE) -l$(LIB_NAME) + +%.o: %.cc + $(CXX) -MMD -MF $(@D)/.$(@F).d -o $@ $< $(CPPFLAGS) -L$(BASE) -l$(LIB_NAME) + +clean:: + rm -f $(OBJECTS) $(DEPS) diff --git a/test/dekker-fences.c b/test/dekker-fences.c new file mode 100644 index 0000000..ae26a33 --- /dev/null +++ b/test/dekker-fences.c @@ -0,0 +1,148 @@ +/* + * Dekker's critical section algorithm, implemented with fences. + * Translated to C by Patrick Lam + * + * URL: + * http://www.justsoftwaresolutions.co.uk/threading/ + */ + +#include +#include +#include "libinterface.h" + +/* atomic */ int flag0, flag1; +/* atomic */ int turn; + +#define true 1 +#define false 0 +#define NULL 0 + +/* uint32_t */ int var = 0; + +void p0(void *arg) +{ + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag0, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + + MCID _mt; MCID _fn0; int f1, t; + MC2_enterLoop(); + while (true) + { + _fn0=MC2_nextOpLoad(MCID_NODEP), f1 = load_32(&flag1); + _fn0 = MC2_function(1, sizeof (f1), f1, _fn0); + MCID _br0; + if (!f1) { + _br0 = MC2_branchUsesID(_fn0, 1, 2, true); + break; + } else { + _br0 = MC2_branchUsesID(_fn0, 0, 2, true); + ; + MC2_merge(_br0); + } + + if ((_mt=MC2_nextOpLoad(MCID_NODEP), t = load_32(&turn)) != 0) + { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag0, false); + MC2_enterLoop(); + while ((_mt=MC2_nextOpLoad(MCID_NODEP), t = load_32(&turn)) != 0) + { + // thrd_yield(); + ; + } +MC2_exitLoop(); + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag0, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + } else { + ; + // thrd_yield(); + } + } +MC2_exitLoop(); + + // std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&var, 1); + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&turn, 1); + // std::atomic_thread_fence(std::memory_order_release); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag0, false); +} + +void p1(void *arg) +{ + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + + MCID _mt; int f0, t; + MC2_enterLoop(); + while (true) + { + MCID _mf0; _mf0=MC2_nextOpLoad(MCID_NODEP); int f0 = load_32(&flag0); + MCID _br1; + if (f0) { + _br1 = MC2_branchUsesID(_mf0, 1, 2, true); + ; + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_mf0, 0, 2, true); + break; + } + if ((_mt=MC2_nextOpLoad(MCID_NODEP), t = load_32(&turn)) != 1) + { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, false); + MC2_enterLoop(); + while ((_mt=MC2_nextOpLoad(MCID_NODEP), t = load_32(&turn)) != 1) + { + thrd_yield(); + } +MC2_exitLoop(); + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, true); + // std::atomic_thread_fence(std::memory_order_seq_cst); + } else { + ; + thrd_yield(); + } + } +MC2_exitLoop(); + + // std::atomic_thread_fence(std::memory_order_acquire); + + // critical section + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&var, 2); + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&turn, 0); + // std::atomic_thread_fence(std::memory_order_release); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&flag1, false); +} + +int user_main(int argc, char **argv) +{ + thrd_t a, b; + + flag0 = false; + flag1 = false; + turn = 0; + + thrd_create(&a, p0, NULL); + thrd_create(&b, p1, NULL); + + thrd_join(a); + thrd_join(b); + + return 0; +} diff --git a/test/function_microbenchmarks.c b/test/function_microbenchmarks.c new file mode 100644 index 0000000..c703a10 --- /dev/null +++ b/test/function_microbenchmarks.c @@ -0,0 +1,58 @@ +#include +#include +#include + +#include "libinterface.h" + +int x; +int y; +int gr1; +int gr2; + +static void a(void *obj) +{ + int r1=load_32(&y); + if (r1) { + r1=42; + store_32(&x, r1); + } else { + r1=0; + } + + store_32(&x, r1); + + int r2 = load_32(&x); + int cond = r1 == r2; + if (cond) { + r2++; + } + + int cas_value = rmw_32(CAS, &x, r1, r2); + int cas_value1; + cas_value1 = rmw_32(ADD, &y, r1, r1); +} + +int user_main(int argc, char **argv) +{ + thrd_t t1; thrd_t t2; + + store_32(&x, 0); + store_32(&y, 0); + + printf("Main thread: creating 2 threads\n"); + thrd_create(&t1, (thrd_start_t)&a, NULL); + + thrd_join(t1); + printf("Main thread is finished\n"); + int lgr1=load_32(&gr1); + + int lgr2=load_32(&gr2); + if (lgr1==42) { + if (lgr2==42) { + } else { + } + } else { + } + + return 0; +} diff --git a/test/linuxlock.c b/test/linuxlock.c new file mode 100644 index 0000000..5f93025 --- /dev/null +++ b/test/linuxlock.c @@ -0,0 +1,69 @@ +#include +#include +#include + +#include "libinterface.h" + + +/** Example implementation of linux rw lock along with 2 thread test + * driver... */ + +typedef union { + int lock; +} rwlock_t; + +static inline bool write_trylock(rwlock_t *rw, MCID *retval) +{ + MCID m_priorval=MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + int priorvalue=rmw_32(CAS, &rw->lock, 0, 1); + *retval=m_priorval; + return priorvalue; +} + +static inline void write_unlock(rwlock_t *rw) +{ + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&rw->lock, 0); +} + +rwlock_t mylock; + +static void foo() { + MCID val; + bool flag=write_trylock(&mylock,&val); + MCID br; + if (flag) { + br=MC2_branchUsesID(val, 1, 2, true); + MC2_merge(br); + } else { + br=MC2_branchUsesID(val, 0, 2, true); + write_unlock(&mylock); + MC2_merge(br); + } +} + +static void a(void *obj) +{ + int i; + for(i=0;i<2;i++) + foo(); +} + +int user_main(int argc, char **argv) +{ + thrd_t t1, t2;//, t3, t4; + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&mylock.lock, 0); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&a, NULL); + //thrd_create(&t3, (thrd_start_t)&a, NULL); + //thrd_create(&t4, (thrd_start_t)&a, NULL); + + thrd_join(t1); + thrd_join(t2); + //thrd_join(t3); + //thrd_join(t4); + + return 0; +} diff --git a/test/load_in_if_cond.c b/test/load_in_if_cond.c new file mode 100644 index 0000000..9b91ed0 --- /dev/null +++ b/test/load_in_if_cond.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include "libinterface.h" + +struct node { + struct node * next; +}; + + +void foo() +{ + int i; + int x = 0; + + struct node * n = malloc(sizeof(struct node)); + n->next = 0; + + i = load_32(&x); + + if ((i = load_32(&x))) { + printf("%d\n", i); + } + + while (load_32(&n->next)) { + ; + } +} diff --git a/test/mcs-lock.cc b/test/mcs-lock.cc new file mode 100644 index 0000000..8036987 --- /dev/null +++ b/test/mcs-lock.cc @@ -0,0 +1,193 @@ +#include +#include + +#include "libinterface.h" + +// mcs on stack + +struct mcs_node { + MCID _mnext; mcs_node * next; + int gate; + + mcs_node() { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_64(&next, 0); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&gate, 0); + } +}; + +struct mcs_mutex { +public: + // tail is null when lock is not held + mcs_node * m_tail; + + mcs_mutex() { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_64(&m_tail, (uint64_t)NULL); + } + ~mcs_mutex() { + // ASSERT( m_tail.load() == NULL ); + } + + class guard { + public: + mcs_mutex * m_t; + mcs_node m_node; // node held on the stack + + guard(MCID _mt, mcs_mutex * t) : m_t(t) { t->lock(MCID_NODEP, this); } + ~guard() { m_t->unlock(MCID_NODEP, this); } + }; + + void lock(MCID _mI, guard * I) { + MCID _mme; mcs_node * me = &(I->m_node); + + // set up my node : + // not published yet so relaxed : + + void * _p0 = &me->next; + MCID _fn0 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p0, (uint64_t)_mme); MC2_nextOpStore(_fn0, MCID_NODEP); + store_64(_p0, (uint64_t)NULL); + + void * _p1 = &me->gate; + MCID _fn1 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p1, (uint64_t)_mme); MC2_nextOpStore(_fn1, MCID_NODEP); + store_32(_p1, 1); + + // publish my node as the new tail : + // mcs_node * pred = m_tail.exchange(me, std::mo_acq_rel); + MCID _rmw0 = MC2_nextRMW(MCID_NODEP, _mme, MCID_NODEP); + MCID _mpred; mcs_node * pred = (mcs_node *)rmw_64(EXC, &m_tail, (uint64_t) me, (uint64_t) NULL); + MCID _br0; + if ( pred != NULL ) { + // (*1) race here + // unlock of pred can see me in the tail before I fill next + + // publish me to previous lock-holder : + _br0 = MC2_branchUsesID(_rmw0, 1, 2, true); + + void * _p2 = &pred->next; + MCID _fn2 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p2, (uint64_t)_mpred); MC2_nextOpStore(_fn2, _mme); + store_64(_p2, (uint64_t)me); + + // (*2) pred not touched any more + + // now this is the spin - + // wait on predecessor setting my flag - + MC2_enterLoop(); + while ( true ) { + MCID _br1; + void * _p99 = &me->gate; + MCID _fn99 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p99, (uint64_t)_mme); MC2_nextOpLoad(_fn99); + int c88 = !load_32(_p99); + MCID _fn88 = MC2_function(1, MC2_PTR_LENGTH, c88, _p99); + if (c88) { + _br1 = MC2_branchUsesID(_fn88, 1, 2, true); + break; + } else { + _br1 = MC2_branchUsesID(_fn88, 0, 2, true); + ; + MC2_merge(_br1); + } + thrd_yield(); + } +MC2_exitLoop(); + + MC2_merge(_br0); + } else { _br0 = MC2_branchUsesID(_rmw0, 0, 2, true); MC2_merge(_br0); + } + } + + void unlock(MCID _mI, guard * I) { + MCID _mme; mcs_node * me; + me = &(I->m_node); + + MCID _fn6; + void * _p3 = &me->next; + MCID _mnext; MCID _fn3 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p3, _mme); _mnext=MC2_nextOpLoad(_fn3); mcs_node * next = (mcs_node *)load_64(_p3); + MCID _br2; + if ( next == NULL ) + { + _br2 = MC2_branchUsesID(_mnext, 1, 2, true); + mcs_node * tail_was_me = me; + //if ( m_tail.compare_exchange_strong( tail_was_me,NULL,std::mo_acq_rel) ) { + MCID _br3; + MCID _rmw77 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + if (rmw_64(CAS, &m_tail, (uint64_t)tail_was_me, (uint64_t)NULL)) { + // got null in tail, mutex is unlocked + _br3 = MC2_branchUsesID(_rmw77, 1, 2, true); + return; + } else { _br3 = MC2_branchUsesID(_rmw77, 0, 2, true); MC2_merge(_br3); + } + + // (*1) catch the race : + MC2_enterLoop(); + while(true) { + + void * _p4 = &me->next; + MCID _fn4 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p4, _mme); _fn6=MC2_nextOpLoad(_fn4), next = (mcs_node *)load_64(_p4); + _fn6 = MC2_function(1, sizeof (next), (uint64_t)next, (uint64_t)_fn6); + MCID _br4; + if ( next != NULL ) { + _br4 = MC2_branchUsesID(_fn6, 1, 2, true); + break; + } else { + _br4 = MC2_branchUsesID(_fn6, 0, 2, true); + ; + MC2_merge(_br4); + } + thrd_yield(); + } +MC2_exitLoop(); + + MC2_merge(_br2); + } else { _br2 = MC2_branchUsesID(_mnext, 0, 2, true); MC2_merge(_br2); + } + + // (*2) - store to next must be done, + // so no locker can be viewing my node any more + + // let next guy in : + + void * _p5 = &next->gate; + MCID _fn5 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p5, _fn6); MC2_nextOpStore(_fn5, MCID_NODEP); + store_32(_p5, 0); + } +}; + +struct mcs_mutex *mutex; +static uint32_t shared; + +void threadA(void *arg) +{ + mcs_mutex::guard g(MCID_NODEP, mutex); + printf("store: %d\n", 17); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&shared, 17); + mutex->unlock(MCID_NODEP, &g); + mutex->lock(MCID_NODEP, &g); + printf("load: %u\n", load_32(&shared)); +} + +void threadB(void *arg) +{ + mcs_mutex::guard g(MCID_NODEP, mutex); + printf("load: %u\n", load_32(&shared)); + mutex->unlock(MCID_NODEP, &g); + mutex->lock(MCID_NODEP, &g); + printf("store: %d\n", 17); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&shared, 17); +} + +int user_main(int argc, char **argv) +{ + thrd_t A; thrd_t B; + + mutex = new mcs_mutex(); + + thrd_create(&A, &threadA, NULL); + thrd_create(&B, &threadB, NULL); + thrd_join(A); + thrd_join(B); + return 0; +} diff --git a/test/ms-queue-freelist.c b/test/ms-queue-freelist.c new file mode 100644 index 0000000..4179206 --- /dev/null +++ b/test/ms-queue-freelist.c @@ -0,0 +1,237 @@ +#include "threads.h" +#include +// #include "librace.h" +// #include "model-assert.h" + +#include "ms-queue-freelist.h" +#include "libinterface.h" + +#define MAX_FREELIST 4 /* Each thread can own up to MAX_FREELIST free nodes */ +#define INITIAL_FREE 2 /* Each thread starts with INITIAL_FREE free nodes */ + +#define POISON_IDX 0x666 + +static unsigned int (*free_lists)[MAX_FREELIST]; + +/* Search this thread's free list for a "new" node */ +static unsigned int new_node() +{ + int i; + int t = get_thread_num(); + for (i = 0; i < MAX_FREELIST; i++) { + unsigned int node = load_32(&free_lists[t][i]); + if (node) { + store_32(&free_lists[t][i], 0); + return node; + } + } + /* free_list is empty? */ + // MODEL_ASSERT(0); + return 0; +} + +/* Place this node index back on this thread's free list */ +static void reclaim(unsigned int node) +{ + int i; + int t = get_thread_num(); + + /* Don't reclaim NULL node */ + // MODEL_ASSERT(node); + + for (i = 0; i < MAX_FREELIST; i++) { + /* Should never race with our own thread here */ + unsigned int idx = load_32(&free_lists[t][i]); + + /* Found empty spot in free list */ + if (idx == 0) { + store_32(&free_lists[t][i], node); + return; + } + } + /* free list is full? */ + // MODEL_ASSERT(0); +} + +void init_queue(queue_t *q, int num_threads) +{ + int i, j; + + /* Initialize each thread's free list with INITIAL_FREE pointers */ + /* The actual nodes are initialized with poison indexes */ + free_lists = malloc(num_threads * sizeof(*free_lists)); + for (i = 0; i < num_threads; i++) { + for (j = 0; j < INITIAL_FREE; j++) { + free_lists[i][j] = 2 + i * MAX_FREELIST + j; + store_32(&q->nodes[free_lists[i][j]].next, MAKE_POINTER(POISON_IDX, 0)); + } + } + + /* initialize queue */ + store_32(&q->head, MAKE_POINTER(1, 0)); + store_32(&q->tail, MAKE_POINTER(1, 0)); + store_32(&q->nodes[1].next, MAKE_POINTER(0, 0)); +} + +void enqueue(queue_t *q, unsigned int val) +{ + int success = 0; + unsigned int node; + pointer tail; + pointer next; + pointer tmp; + + node = new_node(); + store_32(&q->nodes[node].value, val); + tmp = load_32(&q->nodes[node].next); + // manually inlined macro: set_ptr(&tmp, 0); // NULL + tmp = (tmp & ~PTR_MASK); + store_32(&q->nodes[node].next, tmp); + + while (!success) { + pointer_t * qt = &q->tail; + tail = load_32(qt); + pointer_t * qn = &q->nodes[tail & PTR_MASK].next; + next = load_32(qn); + if (tail == load_32(&q->tail)) { + + /* Check for uninitialized 'next' */ + // MODEL_ASSERT(get_ptr(next) != POISON_IDX); + + if ((next & PTR_MASK) == 0) { // == NULL + pointer value = MAKE_POINTER(node, ((next & COUNT_MASK) >> 32) + 1); + success = rmw_32(CAS, &q->nodes[tail & PTR_MASK].next, + (uint32_t)&next, value); + } + if (!success) { + unsigned int ptr = (load_32(&q->nodes[tail & PTR_MASK].next) & PTR_MASK); + pointer value = MAKE_POINTER(ptr, + ((tail & COUNT_MASK) >> 32) + 1); + rmw_32(CAS, &q->tail, + (uint32_t)&tail, value); + thrd_yield(); + } + } + } + rmw_32(CAS, &q->tail, + (uint32_t)&tail, + MAKE_POINTER(node, ((tail & COUNT_MASK) >> 32) + 1)); +} + +bool dequeue(queue_t *q, unsigned int *retVal) +{ + int success = 0; + pointer head; + pointer tail; + pointer next; + + while (!success) { + head = load_32(&q->head); + tail = load_32(&q->tail); + next = load_32(&q->nodes[(head & PTR_MASK)].next); + if (load_32(&q->head) == head) { + if ((head & PTR_MASK) == (tail & PTR_MASK)) { + + /* Check for uninitialized 'next' */ + // MODEL_ASSERT(get_ptr(next) != POISON_IDX); + + if (get_ptr(next) == 0) { // NULL + return false; // NULL + } + rmw_32(CAS, &q->tail, + (uint32_t)&tail, + MAKE_POINTER((next & PTR_MASK), ((tail & COUNT_MASK) >> 32) + 1)); + thrd_yield(); + } else { + *retVal = load_32(&q->nodes[(next & PTR_MASK)].value); + success = rmw_32(CAS, &q->head, + (uint32_t)&head, + MAKE_POINTER((next & PTR_MASK), ((head & COUNT_MASK) >> 32) + 1)); + if (!success) + thrd_yield(); + } + } + } + reclaim((head & PTR_MASK)); + return true; +} + +/* ms-queue-main */ +static int procs = 2; +static queue_t *queue; +static thrd_t *threads; +static unsigned int *input; +static unsigned int *output; +static int num_threads; + +int get_thread_num() +{ + thrd_t curr = thrd_current(); + int i; + for (i = 0; i < num_threads; i++) + if (curr.priv == threads[i].priv) + return i; + /* MODEL_ASSERT(0); */ + return -1; +} + +bool succ1, succ2; + +static void main_task(void *param) +{ + unsigned int val; + int pid = *((int *)param); + if (!pid) { + input[0] = 17; + enqueue(queue, input[0]); + succ1 = dequeue(queue, &output[0]); + //printf("Dequeue: %d\n", output[0]); + } else { + input[1] = 37; + enqueue(queue, input[1]); + succ2 = dequeue(queue, &output[1]); + } +} + +int user_main(int argc, char **argv) +{ + int i; + int *param; + unsigned int in_sum = 0, out_sum = 0; + + queue = calloc(1, sizeof(*queue)); + // MODEL_ASSERT(queue); + + num_threads = procs; + threads = malloc(num_threads * sizeof(thrd_t)); + param = malloc(num_threads * sizeof(*param)); + input = calloc(num_threads, sizeof(*input)); + output = calloc(num_threads, sizeof(*output)); + + init_queue(queue, num_threads); + for (i = 0; i < num_threads; i++) { + param[i] = i; + thrd_create(&threads[i], main_task, ¶m[i]); + } + for (i = 0; i < num_threads; i++) + thrd_join(threads[i]); + + for (i = 0; i < num_threads; i++) { + in_sum += input[i]; + out_sum += output[i]; + } + for (i = 0; i < num_threads; i++) + printf("input[%d] = %u\n", i, input[i]); + for (i = 0; i < num_threads; i++) + printf("output[%d] = %u\n", i, output[i]); + /* if (succ1 && succ2) */ + /* MODEL_ASSERT(in_sum == out_sum); */ + /* else */ + /* MODEL_ASSERT (false); */ + + free(param); + free(threads); + free(queue); + + return 0; +} diff --git a/test/ms-queue-freelist.h b/test/ms-queue-freelist.h new file mode 100644 index 0000000..5926b72 --- /dev/null +++ b/test/ms-queue-freelist.h @@ -0,0 +1,29 @@ +#include + +#define MAX_NODES 0xf + +typedef unsigned long long pointer; +typedef atomic_ullong pointer_t; + +#define MAKE_POINTER(ptr, count) ((((pointer)count) << 32) | ptr) +#define PTR_MASK 0xffffffffLL +#define COUNT_MASK (0xffffffffLL << 32) + +static inline unsigned int get_count(pointer p) { return (p & COUNT_MASK) >> 32; } +static inline unsigned int get_ptr(pointer p) { return p & PTR_MASK; } + +typedef struct node { + unsigned int value; + pointer_t next; +} node_t; + +typedef struct { + pointer_t head; + pointer_t tail; + node_t nodes[MAX_NODES + 1]; +} queue_t; + +void init_queue(queue_t *q, int num_threads); +void enqueue(queue_t *q, unsigned int val); +bool dequeue(queue_t *q, unsigned int *retVal); +int get_thread_num(); diff --git a/test/ms-queue.c b/test/ms-queue.c new file mode 100644 index 0000000..f8172ef --- /dev/null +++ b/test/ms-queue.c @@ -0,0 +1,213 @@ +#include +#include +#include +#define true 1 +#define false 0 +#define bool int + +#include "ms-queue.h" +#include "libinterface.h" + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads); +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val); +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal); + +void init_queue(MCID _mq, queue_t *q, MCID _mnum_threads, int num_threads) { + int i, j; + MCID _fn11; struct node *newnode=malloc(sizeof (struct node)); + _fn11 = MC2_function(0, sizeof (newnode), newnode); + + void * _p0 = &newnode->value; + MCID _fn0 = MC2_function(1, MC2_PTR_LENGTH, _p0, _fn11); MC2_nextOpStore(_fn0, MCID_NODEP); + store_32(_p0, 0); + + + void * _p1 = &newnode->next; + MCID _fn1 = MC2_function(1, MC2_PTR_LENGTH, _p1, _fn11); MC2_nextOpStore(_fn1, MCID_NODEP); + store_64(_p1, (uintptr_t) MAKE_POINTER(NULL, 0LL)); + /* initialize queue */ + + void * _p2 = &q->head; + MCID _fn2 = MC2_function(1, MC2_PTR_LENGTH, _p2, _mq); MC2_nextOpStore(_fn2, _fn11); + store_64(_p2, (uintptr_t) MAKE_POINTER(newnode, 0LL)); + + + void * _p3 = &q->tail; + MCID _fn3 = MC2_function(1, MC2_PTR_LENGTH, _p3, _mq); MC2_nextOpStore(_fn3, _fn11); + store_64(_p3, (uintptr_t) MAKE_POINTER(newnode, 0LL)); +} + +void enqueue(MCID _mq, queue_t *q, MCID _mval, unsigned int val) { + MCID _fn13; struct node *tail; + MCID _fn12; struct node * node_ptr = malloc(sizeof(struct node)); + _fn12 = MC2_function(0, sizeof (node_ptr), node_ptr); + + void * _p4 = &node_ptr->value; + MCID _fn4 = MC2_function(1, MC2_PTR_LENGTH, _p4, _fn12); MC2_nextOpStore(_fn4, _mval); + store_32(_p4, val); + + + void * _p5 = &node_ptr->next; + MCID _fn5 = MC2_function(1, MC2_PTR_LENGTH, _p5, _fn12); MC2_nextOpStore(_fn5, MCID_NODEP); + store_64(_p5, (uintptr_t) MAKE_POINTER(NULL, GET_COUNT(1))); + + MC2_enterLoop(); + while (true) { + + void * _p6 = &q->tail; + MCID _fn6 = MC2_function(1, MC2_PTR_LENGTH, _p6, _mq); _fn13=MC2_nextOpLoad(_fn6), tail = (struct node *) load_64(_p6); + _fn13 = MC2_function(1, sizeof (tail), tail, _fn13); + MCID _fn14; struct node ** tail_ptr_next= & GET_PTR(tail)->next; + _fn14 = MC2_function(1, sizeof (tail_ptr_next), tail_ptr_next, _fn13); + + MCID _mnext; _mnext=MC2_nextOpLoad(_fn14); struct node * next = (struct node *) load_64(tail_ptr_next); + + MCID _mqtail; + void * _p7 = &q->tail; + MCID _fn7 = MC2_function(1, MC2_PTR_LENGTH, _p7, _mq); _mqtail=MC2_nextOpLoad(_fn7); struct node * qtail = (struct node *) load_64(_p7); + MCID _fn15; int tqt = (tail == qtail); + _fn15 = MC2_function(2, sizeof (tqt), tqt, _fn13, _mqtail); + MCID _br0; + if (tqt) { + MCID _fn16; _br0 = MC2_branchUsesID(_fn15, 1, 2, true); + struct node *next_ptr=GET_PTR(next); + _fn16 = MC2_function(1, sizeof (next_ptr), next_ptr, _mnext); + + MCID _fn17; int npn = (next_ptr == NULL); + _fn17 = MC2_function(1, sizeof (npn), npn, _fn16); + MCID _br1; + if (npn) { + MCID _fn18; _br1 = MC2_branchUsesID(_fn17, 1, 2, true); + struct node * new_node = MAKE_POINTER(node_ptr, GET_COUNT(next) +1); + _fn18 = MC2_function(2, sizeof (new_node), new_node, _fn12, _mnext); + MCID _rmw0 = MC2_nextRMW(_fn14, _mnext, _fn18); + struct node * valread = (struct node *) rmw_64(CAS, tail_ptr_next, (uintptr_t) next, (uintptr_t) new_node); + MCID _fn19; int vn = (valread == next); + _fn19 = MC2_function(2, sizeof (vn), vn, _mnext, _rmw0); + MCID _br2; + if (vn) { + _br2 = MC2_branchUsesID(_fn19, 1, 2, true); + break; + } else { + _br2 = MC2_branchUsesID(_fn19, 0, 2, true); + MC2_yield(); + MC2_merge(_br2); + } + MC2_merge(_br1); + } else { + _br1 = MC2_branchUsesID(_fn17, 0, 2, true); + MC2_yield(); + MC2_merge(_br1); + } + MCID _mnew_tailptr; _mnew_tailptr=MC2_nextOpLoad(_fn14); struct node * new_tailptr = GET_PTR(load_64( tail_ptr_next)); + MCID _fn20; struct node * newtail = MAKE_POINTER(new_tailptr, GET_COUNT(tail) + 1); + _fn20 = MC2_function(2, sizeof (newtail), newtail, _fn13, _mnew_tailptr); + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, _fn13, _fn20); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) newtail); + MC2_yield(); + MC2_merge(_br0); + } else { + _br0 = MC2_branchUsesID(_fn15, 0, 2, true); + MC2_yield(); + MC2_merge(_br0); + } + } +MC2_exitLoop(); + + MCID _rmw2 = MC2_nextRMW(MCID_NODEP, _fn13, _fn13); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t)MAKE_POINTER(node_ptr, GET_COUNT(tail) + 1)); +} + +bool dequeue(MCID _mq, queue_t *q, MCID _mretVal, unsigned int *retVal) { + MC2_enterLoop(); + while (true) { + MCID _mhead; + void * _p8 = &q->head; + MCID _fn8 = MC2_function(1, MC2_PTR_LENGTH, _p8, _mq); _mhead=MC2_nextOpLoad(_fn8); struct node * head = (struct node *) load_64(_p8); + MCID _mtail; + void * _p9 = &q->tail; + MCID _fn9 = MC2_function(1, MC2_PTR_LENGTH, _p9, _mq); _mtail=MC2_nextOpLoad(_fn9); struct node * tail = (struct node *) load_64(_p9); + MCID _mnext; _mnext=MC2_nextOpLoad(_mhead); struct node * next = (struct node *) load_64(&(GET_PTR(head)->next)); + + MCID _mt; + void * _p10 = &q->head; + MCID _fn10 = MC2_function(1, MC2_PTR_LENGTH, _p10, _mq); _mt=MC2_nextOpLoad(_fn10); int t = ((struct node *) load_64(_p10)) == head; + MCID _br3; + if (t) { + _br3 = MC2_branchUsesID(_mt, 1, 2, true); + if (GET_PTR(head) == GET_PTR(tail)) { + + MCID _br4; + if (GET_PTR(next) == NULL) { + _br4 = MC2_branchUsesID(_mnext, 1, 2, true); + MC2_exitLoop(); + return false; // NULL + } else { + _br4 = MC2_branchUsesID(_mnext, 0, 2, true); + MC2_yield(); + MC2_merge(_br4); + } + MCID _rmw3 = MC2_nextRMW(MCID_NODEP, _mtail, _mtail); + rmw_64(CAS, &q->tail, (uintptr_t) tail, (uintptr_t) MAKE_POINTER(GET_PTR(next), GET_COUNT(tail) + 1)); + MC2_yield(); + } else { + MCID _mnv; _mnv=MC2_nextOpLoad(_mnext); int nv = load_32(&GET_PTR(next)->value); + MC2_nextOpStore(_mretVal, _mnv); + store_32(retVal, nv); + MCID _fn21; struct node * nh = MAKE_POINTER(GET_PTR(next), GET_COUNT(head)+1); + _fn21 = MC2_function(2, sizeof (nh), nh, _mhead, _mnext); + MCID _rmw4 = MC2_nextRMW(MCID_NODEP, _mhead, _fn21); + struct node *old_head = (struct node *) rmw_64(CAS, &q->head, + (uintptr_t) head, + (uintptr_t) nh); + if (old_head == head) { + MC2_exitLoop(); + return true; + } else { + MC2_yield(); + } + } + MC2_merge(_br3); + } else { _br3 = MC2_branchUsesID(_mt, 0, 2, true); MC2_merge(_br3); + } + } +MC2_exitLoop(); + +} + +/* ms-queue-main */ +static queue_t queue; +bool succ1, succ2; + +static void e(void *p) { + int i; + MC2_enterLoop(); + for(i=0;i<2;i++) + enqueue(MCID_NODEP, &queue, MCID_NODEP, 1); +MC2_exitLoop(); + +} + +static void d(void *p) { + unsigned int val; + int i; + MC2_enterLoop(); + for(i=0;i<2;i++) + dequeue(MCID_NODEP, &queue, MCID_NODEP, &val); +MC2_exitLoop(); + +} + +int user_main(int argc, char **argv) +{ + init_queue(MCID_NODEP, &queue, MCID_NODEP, 2); + + thrd_t t1,t2; + thrd_create(&t1, e, NULL); + thrd_create(&t2, d, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} diff --git a/test/ms-queue.h b/test/ms-queue.h new file mode 100644 index 0000000..0c7386a --- /dev/null +++ b/test/ms-queue.h @@ -0,0 +1,20 @@ +typedef struct node { + unsigned int value; + struct node * next; +} node_t; + +typedef struct { + struct node * head; + struct node * tail; +} queue_t; + +//void init_queue(queue_t *q, int num_threads); +//void enqueue(queue_t *q, unsigned int val); +//bool dequeue(queue_t *q, unsigned int *retVal); +int get_thread_num(); + +#define MAKE_POINTER(ptr, count) (struct node *) (((count) << 48) | (uintptr_t)(ptr)) +#define PTR_MASK 0xffffffffffffLL +#define COUNT_MASK (0xffffLL << 48) +#define GET_PTR(x) ((struct node *)(((uintptr_t) x) & PTR_MASK)) +#define GET_COUNT(x) (((uintptr_t) x) >> 48) diff --git a/test/reference/README.md b/test/reference/README.md new file mode 100644 index 0000000..f9067c3 --- /dev/null +++ b/test/reference/README.md @@ -0,0 +1 @@ +Files in this directory are non-compilable original versions of benchmarks in the parent test/ directory. \ No newline at end of file diff --git a/test/reference/ms-queue-atomics.c b/test/reference/ms-queue-atomics.c new file mode 100644 index 0000000..7a99133 --- /dev/null +++ b/test/reference/ms-queue-atomics.c @@ -0,0 +1,165 @@ +#include "threads.h" +#include +// #include "librace.h" +// #include "model-assert.h" + +#include "ms-queue.h" +#include "libinterface.h" + +#define relaxed memory_order_relaxed +#define release memory_order_release +#define acquire memory_order_acquire + +#define MAX_FREELIST 4 /* Each thread can own up to MAX_FREELIST free nodes */ +#define INITIAL_FREE 2 /* Each thread starts with INITIAL_FREE free nodes */ + +#define POISON_IDX 0x666 + +static unsigned int (*free_lists)[MAX_FREELIST]; + +/* Search this thread's free list for a "new" node */ +static unsigned int new_node() +{ + int i; + int t = get_thread_num(); + for (i = 0; i < MAX_FREELIST; i++) { + unsigned int node = load_32(&free_lists[t][i]); + if (node) { + store_32(&free_lists[t][i], 0); + return node; + } + } + /* free_list is empty? */ + // MODEL_ASSERT(0); + return 0; +} + +/* Place this node index back on this thread's free list */ +static void reclaim(unsigned int node) +{ + int i; + int t = get_thread_num(); + + /* Don't reclaim NULL node */ + // MODEL_ASSERT(node); + + for (i = 0; i < MAX_FREELIST; i++) { + /* Should never race with our own thread here */ + unsigned int idx = load_32(&free_lists[t][i]); + + /* Found empty spot in free list */ + if (idx == 0) { + store_32(&free_lists[t][i], node); + return; + } + } + /* free list is full? */ + // MODEL_ASSERT(0); +} + +void init_queue(queue_t *q, int num_threads) +{ + int i, j; + + /* Initialize each thread's free list with INITIAL_FREE pointers */ + /* The actual nodes are initialized with poison indexes */ + free_lists = malloc(num_threads * sizeof(*free_lists)); + for (i = 0; i < num_threads; i++) { + for (j = 0; j < INITIAL_FREE; j++) { + free_lists[i][j] = 2 + i * MAX_FREELIST + j; + atomic_init(&q->nodes[free_lists[i][j]].next, MAKE_POINTER(POISON_IDX, 0)); + } + } + + /* initialize queue */ + atomic_init(&q->head, MAKE_POINTER(1, 0)); + atomic_init(&q->tail, MAKE_POINTER(1, 0)); + atomic_init(&q->nodes[1].next, MAKE_POINTER(0, 0)); +} + +void enqueue(queue_t *q, unsigned int val) +{ + int success = 0; + unsigned int node; + pointer tail; + pointer next; + pointer tmp; + + node = new_node(); + store_32(&q->nodes[node].value, val); + tmp = atomic_load_explicit(&q->nodes[node].next, relaxed); + // manually inlined macro: set_ptr(&tmp, 0); // NULL + tmp = (tmp & ~PTR_MASK); + atomic_store_explicit(&q->nodes[node].next, tmp, relaxed); + + while (!success) { + pointer_t * qt = &q->tail; + tail = atomic_load_explicit(qt, acquire); + pointer_t * qn = &q->nodes[tail & PTR_MASK].next; + next = atomic_load_explicit(qn, acquire); + if (tail == atomic_load_explicit(&q->tail, relaxed)) { + + /* Check for uninitialized 'next' */ + // MODEL_ASSERT(get_ptr(next) != POISON_IDX); + + if ((next & PTR_MASK) == 0) { // == NULL + pointer value = MAKE_POINTER(node, ((next & COUNT_MASK) >> 32) + 1); + success = atomic_compare_exchange_strong_explicit(&q->nodes[tail & PTR_MASK].next, + &next, value, release, release); + } + if (!success) { + unsigned int ptr = (atomic_load_explicit(&q->nodes[tail & PTR_MASK].next, acquire) & PTR_MASK); + pointer value = MAKE_POINTER(ptr, + ((tail & COUNT_MASK) >> 32) + 1); + atomic_compare_exchange_strong_explicit(&q->tail, + &tail, value, + release, release); + thrd_yield(); + } + } + } + atomic_compare_exchange_strong_explicit(&q->tail, + &tail, + MAKE_POINTER(node, ((tail & COUNT_MASK) >> 32) + 1), + release, release); +} + +bool dequeue(queue_t *q, unsigned int *retVal) +{ + int success = 0; + pointer head; + pointer tail; + pointer next; + + while (!success) { + head = atomic_load_explicit(&q->head, acquire); + tail = atomic_load_explicit(&q->tail, relaxed); + next = atomic_load_explicit(&q->nodes[(head & PTR_MASK)].next, acquire); + if (atomic_load_explicit(&q->head, relaxed) == head) { + if ((head & PTR_MASK) == (tail & PTR_MASK)) { + + /* Check for uninitialized 'next' */ + // MODEL_ASSERT(get_ptr(next) != POISON_IDX); + + if (get_ptr(next) == 0) { // NULL + return false; // NULL + } + atomic_compare_exchange_strong_explicit(&q->tail, + &tail, + MAKE_POINTER((next & PTR_MASK), ((tail & COUNT_MASK) >> 32) + 1), + release, release); + thrd_yield(); + } else { + *retVal = load_32(&q->nodes[(next & PTR_MASK)].value); + success = atomic_compare_exchange_strong_explicit(&q->head, + &head, + MAKE_POINTER((next & PTR_MASK), ((head & COUNT_MASK) >> 32) + 1), + release, release); + if (!success) + thrd_yield(); + } + } + } + reclaim((head & PTR_MASK)); + return true; +} diff --git a/test/seqlock.c b/test/seqlock.c new file mode 100644 index 0000000..496c495 --- /dev/null +++ b/test/seqlock.c @@ -0,0 +1,121 @@ +#include +#include +#include + +#include +#include "threads.h" +#include "libinterface.h" + +/*atomic_*/ int _seq; +/*atomic_*/ int _data; + +void seqlock_init() { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_seq, 0); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_data, 0); +} + +int seqlock_read() { + MC2_enterLoop(); + while (true) { + MCID _mold_seq; _mold_seq=MC2_nextOpLoad(MCID_NODEP); int old_seq = load_32(&_seq); + + MCID _fn0; int c0 = (old_seq % 2 == 1); + _fn0 = MC2_function(1, sizeof (c0), c0, _mold_seq); + MCID _br0; + if (c0) { + _br0 = MC2_branchUsesID(_fn0, 1, 2, true); + MC2_yield(); + MC2_merge(_br0); + } else { + MCID _mres; _br0 = MC2_branchUsesID(_fn0, 0, 2, true); + _mres=MC2_nextOpLoad(MCID_NODEP); int res = load_32(&_data); + MCID _mseq; _mseq=MC2_nextOpLoad(MCID_NODEP); int seq = load_32(&_seq); + + MCID _fn1; int c1; + c1 = seq == old_seq; + + _fn1 = MC2_function(2, sizeof (c1), c1, _mold_seq, _mseq); MCID _br1; + if (c1) { // relaxed + _br1 = MC2_branchUsesID(_fn1, 1, 2, true); + MC2_exitLoop(); + MCID res_phi = MC2_loop_phi(_mres); + return res; + } else { + _br1 = MC2_branchUsesID(_fn1, 0, 2, true); + MC2_yield(); + MC2_merge(_br1); + } + MC2_merge(_br0); + } + } + MC2_exitLoop(); + +} + +void seqlock_write(MCID _mnew_data, int new_data) { + MC2_enterLoop(); + while (true) { + MCID _mold_seq; _mold_seq=MC2_nextOpLoad(MCID_NODEP); int old_seq = load_32(&_seq); + MCID _fn2; int c2 = (old_seq % 2 == 1); + _fn2 = MC2_function(1, sizeof (c2), c2, _mold_seq); + MCID _br2; + if (c2) { + _br2 = MC2_branchUsesID(_fn2, 1, 2, true); + MC2_yield(); + MC2_merge(_br2); + } else { + MCID _fn3; _br2 = MC2_branchUsesID(_fn2, 0, 2, true); + int new_seq = old_seq + 1; + _fn3 = MC2_function(1, sizeof (new_seq), new_seq, _mold_seq); + MCID _rmw0 = MC2_nextRMW(MCID_NODEP, _mold_seq, _fn3); + int cas_value = rmw_32(CAS, &_seq, old_seq, new_seq); + MCID _fn4; int c3 = old_seq == cas_value; + _fn4 = MC2_function(2, sizeof (c3), c3, _mold_seq, _rmw0); + MCID _br3; + if (c3) { + _br3 = MC2_branchUsesID(_fn4, 1, 2, true); + break; + } else { + _br3 = MC2_branchUsesID(_fn4, 0, 2, true); + MC2_yield(); + MC2_merge(_br3); + } + MC2_merge(_br2); + } + } + MC2_exitLoop(); + + MC2_nextOpStore(MCID_NODEP, _mnew_data); + store_32(&_data, new_data); + + MCID _rmw1 = MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &_seq, /*dummy */0, 1); +} + +static void a(void *obj) { + seqlock_write(MCID_NODEP, 3); +} + +static void b(void *obj) { + seqlock_write(MCID_NODEP, 2); +} + +static void c(void *obj) { + int r1 = seqlock_read(); +} + +int user_main(int argc, char **argv) { + thrd_t t1; thrd_t t2; thrd_t t3; + seqlock_init(); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + thrd_create(&t3, (thrd_start_t)&c, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + return 0; +} diff --git a/test/seqlock2.cc b/test/seqlock2.cc new file mode 100644 index 0000000..a733d8e --- /dev/null +++ b/test/seqlock2.cc @@ -0,0 +1,143 @@ +#include +#include +#include + +#include "libinterface.h" + +typedef struct seqlock { + // Sequence for reader consistency check + int _seq; + // It needs to be atomic to avoid data races + int _data; + + seqlock() { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_seq, 0); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_data, 10); + } + + int read() { + int res; + MC2_enterLoop(); + while (true) { + //int old_seq = _seq.load(memory_order_acquire); // acquire + MCID mold_seq = MC2_nextOpLoad(MCID_NODEP); + int old_seq = load_32(&_seq); + + int cond0 = (old_seq % 2 == 1); + MCID mcond0 = MC2_function(1, 4, cond0, mold_seq); + MCID br0; + + if (cond0) { + br0 = MC2_branchUsesID(mcond0, 1, 2, true); + MC2_yield(); + MC2_merge(br0); + } else { + br0 = MC2_branchUsesID(mcond0, 0, 2, true); + + MCID mres = MC2_nextOpLoad(MCID_NODEP); + res = load_32(&_data); + + MCID mseq = MC2_nextOpLoad(MCID_NODEP); + int seq = load_32(&_seq); // _seq.load(memory_order_relaxed) + + int cond1 = seq == old_seq; + MCID mcond1 = MC2_function(2, 4, cond1, mseq, mold_seq); + MCID br1; + if (cond1) { // relaxed + br1 = MC2_branchUsesID(mcond1, 1, 2, true); + break; + } else { + br1 = MC2_branchUsesID(mcond1, 0, 2, true); + MC2_yield(); + MC2_merge(br1); + } + + MC2_merge(br0); + } + } + MC2_exitLoop(); + return res; + } + + void write(int new_data) { + MC2_enterLoop(); + while (true) { + // This might be a relaxed too + //int old_seq = _seq.load(memory_order_acquire); // acquire + MCID mold_seq = MC2_nextOpLoad(MCID_NODEP); + int old_seq = load_32(&_seq); + + int cond0 = (old_seq % 2 == 1); + MCID mcond0 = MC2_function(1, 4, cond0, mold_seq); + MCID br0; + if (cond0) { + //retry as the integer is odd + br0 = MC2_branchUsesID(mcond0, 1, 2, true); + MC2_yield(); + MC2_merge(br0); + } else { + br0 = MC2_branchUsesID(mcond0, 0, 2, true); + + int new_seq=old_seq+1; + MCID mnew_seq=MC2_function(1, 4, new_seq, mold_seq); + MCID m_priorval=MC2_nextRMW(MCID_NODEP, mold_seq, mnew_seq); + int cas_value=rmw_32(CAS, &_seq, old_seq, new_seq); + int exit=cas_value==old_seq; + MCID m_exit=MC2_function(2, 4, exit, m_priorval, mold_seq); + + if (exit) { + MCID br2=MC2_branchUsesID(m_exit, 1, 2, true); + break; + } else { + MCID br2=MC2_branchUsesID(m_exit, 0, 2, true); + MC2_yield(); + MC2_merge(br2); + } + //if cas fails, we have to retry as someone else succeeded + MC2_merge(br0); + } + } + MC2_exitLoop(); + + // Update the data + //_data.store(new_data, memory_order_release); // release + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&_data, new_data); + + // _seq.fetch_add(1, memory_order_release); // release + MC2_nextRMW(MCID_NODEP, MCID_NODEP, MCID_NODEP); + rmw_32(ADD, &_seq, /* dummy */0, 1); + } + +} seqlock_t; + + +seqlock_t *lock; + +static void a(void *obj) { + lock->write(30); +} + +static void b(void *obj) { + lock->write(20); +} + +static void c(void *obj) { + int r1 = lock->read(); +} + +int user_main(int argc, char **argv) { + thrd_t t1, t2, t3; + lock = new seqlock_t(); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + thrd_create(&t3, (thrd_start_t)&c, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + return 0; +} diff --git a/test/spsc-queue.cc b/test/spsc-queue.cc new file mode 100644 index 0000000..4c97d9a --- /dev/null +++ b/test/spsc-queue.cc @@ -0,0 +1,111 @@ +#include +#include "libinterface.h" + +struct node { + // atomic next; + struct node * next; + int data; + + node(MCID _md, int d = 0) : data(d) { + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_64(&next, 0); + } +}; + + +class spsc_queue { +public: + spsc_queue() + { + MCID _mn; node* n = new node (MCID_NODEP); _mn = MC2_function(0, MC2_PTR_LENGTH, (uint64_t) n); + head = n; + tail = n; + } + + ~spsc_queue() + { + } + + void enqueue(MCID _mdata, int data) + { + MCID _mn; node* n = new node(MCID_NODEP, data); _mn = MC2_function(0, MC2_PTR_LENGTH, (uint64_t) n); + MC2_nextOpStore(MCID_NODEP, _mn); + store_64(&head->next->data, (uint64_t)n); + head = n; + } + + int dequeue() { + int data=0; + MC2_enterLoop(); + while (0 == data) { + data = try_dequeue(); + } +MC2_exitLoop(); + + return data; + } + +private: + + struct node* head; + struct node* tail; + + int try_dequeue() { + node* t = tail; + MCID _mn; + void * _p0 = &t->next; + MCID _fn0 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p0, MCID_NODEP); _mn=MC2_nextOpLoad(_fn0); node* n = (node *)load_64(_p0); + MCID _br0; + if (0 == n) { + _br0 = MC2_branchUsesID(_mn, 1, 2, true); + return 0; + } else { _br0 = MC2_branchUsesID(_mn, 0, 2, true); MC2_merge(_br0); + } + MCID _mdata; + void * _p1 = &n->data; + MCID _fn1 = MC2_function(1, MC2_PTR_LENGTH, (uint64_t)_p1, _mn); _mdata=MC2_nextOpLoad(_fn1); int data = load_64(_p1); + tail = n; + return data; + } +}; + + +spsc_queue *q; + +void thread(unsigned thread_index) +{ + MC2_enterLoop(); + for (int i = 0; i < 40; i++) { + MCID _br1; + if (0 == thread_index) + { + _br1 = MC2_branchUsesID(MCID_NODEP, 1, 2, true); + q->enqueue(MCID_NODEP, 11); + MC2_merge(_br1); + } + else + { + _br1 = MC2_branchUsesID(MCID_NODEP, 0, 2, true); + int d = q->dequeue(); + // RL_ASSERT(11 == d); + MC2_merge(_br1); + } + } +MC2_exitLoop(); + +} + +int user_main(int argc, char **argv) +{ + thrd_t A; thrd_t B; + + q = new spsc_queue(); + + thrd_create(&A, (thrd_start_t)&thread, (void *)0); + thrd_create(&B, (thrd_start_t)&thread, (void *)1); + thrd_join(A); + thrd_join(B); + + + return 0; +} diff --git a/test/userprog.c b/test/userprog.c new file mode 100644 index 0000000..94633dc --- /dev/null +++ b/test/userprog.c @@ -0,0 +1,76 @@ +#include +#include +#include "threads.h" +#include "libinterface.h" + +int x; +int y; +int gr1; +int gr2; + +static void a(void *obj) +{ + MCID mr1=MC2_nextOpLoad(MCID_NODEP); + int r1 = load_32(&y); + MC2_nextOpStore(MCID_NODEP, mr1); + store_32(&x, r1); + + MC2_nextOpStore(MCID_NODEP, mr1); + store_32(&gr1, r1); + printf("r1=%d\n",r1); +} + +static void b(void *obj) +{ + MCID mr2=MC2_nextOpLoad(MCID_NODEP); + int r2=load_32(&x); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&y, 42); + + MC2_nextOpStore(MCID_NODEP, mr2); + store_32(&gr2, r2); + printf("r2=%d\n",r2); +} + +int user_main(int argc, char **argv) +{ + thrd_t t1, t2; + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&x, 0); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&y, 0); + + printf("Main thread: creating 2 threads\n"); + MC2_nextOpThrd_create(MCID_NODEP, MCID_NODEP); + thrd_create(&t1, (thrd_start_t)&a, NULL); + MC2_nextOpThrd_create(MCID_NODEP, MCID_NODEP); + thrd_create(&t2, (thrd_start_t)&b, NULL); + + MC2_nextOpThrd_join(MCID_NODEP); + thrd_join(t1); + MC2_nextOpThrd_join(MCID_NODEP); + thrd_join(t2); + printf("Main thread is finished\n"); + MCID mlgr1=MC2_nextOpLoad(MCID_NODEP); + int lgr1=load_32(&gr1); + + MCID mlgr2=MC2_nextOpLoad(MCID_NODEP); + int lgr2=load_32(&gr2); + printf("lrg1=%d lrg2=%d\n", lgr1, lgr2); + MCID br1,br2; + if (lgr1==42) { + br1=MC2_branchUsesID(mlgr1, 1, 2, true); + if (lgr2==42) { + br2=MC2_branchUsesID(mlgr2, 1, 2, true); + } else { + br2=MC2_branchUsesID(mlgr2, 0, 2, true); + } + MC2_merge(br2); + } else { + br1=MC2_branchUsesID(mlgr1, 0, 2, true); + } + MC2_merge(br1); + + return 0; +} diff --git a/test/userprog2.c b/test/userprog2.c new file mode 100644 index 0000000..836e326 --- /dev/null +++ b/test/userprog2.c @@ -0,0 +1,89 @@ +#include +#include +#include + +#include "libinterface.h" + +int x; +int y; +int gr1; +int gr2; + +static void a(void *obj) +{ + MCID mr1=MC2_nextOpLoad(MCID_NODEP); + int r1=load_32(&y); + MCID br1; + if (r1) { + br1=MC2_branchUsesID(mr1, 1, 2, true); + r1=42; + mr1=MC2_function(0, 4, r1); + } else { + br1=MC2_branchUsesID(mr1, 0, 2, true); + r1=0; + mr1=MC2_function(0, 4, r1); + } + MC2_merge(br1); + mr1=MC2_phi(mr1); + + MC2_nextOpStore(MCID_NODEP, mr1); + store_32(&x, r1); + + MC2_nextOpStore(MCID_NODEP, mr1); + store_32(&gr1, r1); + printf("r1=%d\n",r1); +} + +static void b(void *obj) +{ + MCID mr2=MC2_nextOpLoad(MCID_NODEP); + int r2=load_32(&x); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&y, 42); + + MC2_nextOpStore(MCID_NODEP, mr2); + store_32(&gr2, r2); + printf("r2=%d\n",r2); +} + +int user_main(int argc, char **argv) +{ + thrd_t t1, t2; + + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&x, 0); + MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&y, 0); + + printf("Main thread: creating 2 threads\n"); + MC2_nextOpThrd_create(MCID_NODEP, MCID_NODEP); + thrd_create(&t1, (thrd_start_t)&a, NULL); + MC2_nextOpThrd_create(MCID_NODEP, MCID_NODEP); + thrd_create(&t2, (thrd_start_t)&b, NULL); + + MC2_nextOpThrd_join(MCID_NODEP); + thrd_join(t1); + MC2_nextOpThrd_join(MCID_NODEP); + thrd_join(t2); + printf("Main thread is finished\n"); + MCID mr1=MC2_nextOpLoad(MCID_NODEP); + int lgr1=load_32(&gr1); + + MCID mr2=MC2_nextOpLoad(MCID_NODEP); + int lgr2=load_32(&gr2); + MCID br1,br2; + if (lgr1==42) { + br1=MC2_branchUsesID(mr1, 1, 2, true); + if (lgr2==42) { + br2=MC2_branchUsesID(mr2, 1, 2, true); + } else { + br2=MC2_branchUsesID(mr2, 0, 2, true); + } + MC2_merge(br2); + } else { + br1=MC2_branchUsesID(mr1, 0, 2, true); + } + MC2_merge(br1); + + return 0; +} diff --git a/test/userprog_pointers.c b/test/userprog_pointers.c new file mode 100644 index 0000000..e1efc8e --- /dev/null +++ b/test/userprog_pointers.c @@ -0,0 +1,44 @@ +#include +#include +#include "threads.h" +#include "libinterface.h" + +int x; +int y; +int z; +int *px; +int *py; +int gr1; +int gr2; + +int user_main(int argc, char **argv) +{ + // thrd_t t1, t2; + + // MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&x, 0); // x = 0 + // MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&y, 0); // y = 0 + + // MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&py, (uint32_t)&z); // py = &z + // MCID mpx = MC2_nextOpLoad(MCID_NODEP); + px = (int *)load_32(&py); // px = y; + // MC2_nextOpStore(mpx, MCID_NODEP); + store_32(px, 25); // *px = 25; + + // MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&px, (uint32_t)&x); // px = &x + + // MC2_nextOpStore(MCID_NODEP, mx); + store_32(&y, x); + // MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&y, (uint32_t) &x); + + // MC2_nextOpStore(MCID_NODEP, mpx); + store_32(&y, (uint32_t) px); + // MC2_nextOpStore(MCID_NODEP, MCID_NODEP); + store_32(&y, (uint32_t) &px); + + return 0; +} diff --git a/threads-model.h b/threads-model.h new file mode 100644 index 0000000..37ab6c9 --- /dev/null +++ b/threads-model.h @@ -0,0 +1,147 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file threads-model.h + * @brief Model Checker Thread class. + */ + +#ifndef __THREADS_MODEL_H__ +#define __THREADS_MODEL_H__ + +#include + +#include "mymemory.h" +#include +#include "modeltypes.h" +#include "stl-model.h" +#include "context.h" +#include "classlist.h" + +struct thread_params { + thrd_start_t func; + void *arg; +}; + +/** @brief Represents the state of a user Thread */ +typedef enum thread_state { + /** Thread was just created and hasn't run yet */ + THREAD_CREATED, + /** Thread is running */ + THREAD_RUNNING, + /** Thread is not currently running but is ready to run */ + THREAD_READY, + /** + * Thread is waiting on another action (e.g., thread completion, lock + * release, etc.) + */ + THREAD_BLOCKED, + /** Thread has completed its execution */ + THREAD_COMPLETED +} thread_state; + + +/** @brief A Thread is created for each user-space thread */ +class Thread { + public: + Thread(thread_id_t tid); + Thread(thread_id_t tid, thrd_t *t, void (*func)(void *), void *a, Thread *parent, EPRecord *r); + ~Thread(); + void complete(); + + ucontext_t * get_context() { + return &context; + } + + thread_state get_state() const { return state; } + void set_state(thread_state s); + thread_id_t get_id() const; + thrd_t get_thrd_t() const { return *user_thread; } + Thread * get_parent() const { return parent; } + + /** @return True if this thread is finished executing */ + bool is_complete() const { return state == THREAD_COMPLETED; } + + /** @return True if this thread is blocked */ + bool is_blocked() const { return state == THREAD_BLOCKED; } + + Thread * waiting_on(); + void set_waiting(Thread *); + + bool is_waiting_on(const Thread *t); + + bool is_model_thread() const { return model_thread; } + + friend void thread_startup(); + + /** + * Intentionally NOT allocated with MODELALLOC or SNAPSHOTALLOC. + * Threads should be allocated on the user's normal (snapshotting) heap + * to allow their allocation/deallocation to follow the same pattern as + * the rest of the backtracked/replayed program. + */ + void * operator new(size_t size) { + return Thread_malloc(size); + } + void operator delete(void *p, size_t size) { + Thread_free(p); + } + void * operator new[](size_t size) { + return Thread_malloc(size); + } + void operator delete[](void *p, size_t size) { + Thread_free(p); + } + EPRecord * getParentRecord() {return parentrecord;} + private: + int create_context(); + + /** @brief The parent Thread which created this Thread */ + Thread * const parent; + EPRecord * parentrecord; + void (*start_routine)(void *); + void *arg; + ucontext_t context; + void *stack; + thrd_t *user_thread; + Thread *waiting; + thread_id_t id; + thread_state state; + + /** @brief Is this Thread a special model-checker thread? */ + const bool model_thread; +}; + +Thread * thread_current(); + +static inline thread_id_t thrd_to_id(thrd_t t) +{ + return t.priv->get_id(); +} + +/** + * @brief Map a zero-based integer index to a unique thread ID + * + * This is the inverse of id_to_int + */ +static inline thread_id_t int_to_id(int i) +{ + return i; +} + +/** + * @brief Map a unique thread ID to a zero-based integer index + * + * This is the inverse of int_to_id + */ +static inline int id_to_int(thread_id_t id) +{ + return id; +} + +#endif /* __THREADS_MODEL_H__ */ diff --git a/threads.cc b/threads.cc new file mode 100644 index 0000000..b7927c4 --- /dev/null +++ b/threads.cc @@ -0,0 +1,196 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +/** @file threads.cc + * @brief Thread functions. + */ + +#include + +#include +#include +#include "common.h" +#include "threads-model.h" +#include "mcschedule.h" +/* global "model" object */ +#include "model.h" + +/** Allocate a stack for a new thread. */ +static void * stack_allocate(size_t size) +{ + return snapshot_malloc(size); +} + +/** Free a stack for a terminated thread. */ +static void stack_free(void *stack) +{ + snapshot_free(stack); +} + +/** + * @brief Get the current Thread + * + * Must be called from a user context + * + * @return The currently executing thread + */ +Thread * thread_current(void) +{ + ASSERT(model); + return model->get_execution()->get_current_thread(); +} + +/** + * Provides a startup wrapper for each thread, allowing some initial + * model-checking data to be recorded. This method also gets around makecontext + * not being 64-bit clean + */ +void thread_startup() +{ + Thread * curr_thread = thread_current(); + model->get_execution()->threadStart(curr_thread->getParentRecord()); + /* Call the actual thread function */ + curr_thread->start_routine(curr_thread->arg); + model->get_execution()->threadFinish(); +} + +/** + * Create a thread context for a new thread so we can use + * setcontext/getcontext/swapcontext to swap it out. + * @return 0 on success; otherwise, non-zero error condition + */ +int Thread::create_context() +{ + int ret; + + ret = getcontext(&context); + if (ret) + return ret; + + /* Initialize new managed context */ + stack = stack_allocate(STACK_SIZE); + context.uc_stack.ss_sp = stack; + context.uc_stack.ss_size = STACK_SIZE; + context.uc_stack.ss_flags = 0; + context.uc_link = model->get_scheduler()->get_system_context(); + makecontext(&context, thread_startup, 0); + + return 0; +} + + +/** Terminate a thread and free its stack. */ +void Thread::complete() +{ + ASSERT(!is_complete()); + DEBUG("completed thread %d\n", id_to_int(get_id())); + state = THREAD_COMPLETED; +} + +/** + * @brief Construct a new model-checker Thread + * + * A model-checker Thread is used for accounting purposes only. It will never + * have its own stack, and it should never be inserted into the Scheduler. + * + * @param tid The thread ID to assign + */ +Thread::Thread(thread_id_t tid) : + parent(NULL), + start_routine(NULL), + arg(NULL), + stack(NULL), + user_thread(NULL), + waiting(NULL), + id(tid), + state(THREAD_READY), /* Thread is always ready? */ + model_thread(true) +{ + memset(&context, 0, sizeof(context)); +} + +/** + * Construct a new thread. + * @param t The thread identifier of the newly created thread. + * @param func The function that the thread will call. + * @param a The parameter to pass to this function. + */ +Thread::Thread(thread_id_t tid, thrd_t *t, void (*func)(void *), void *a, Thread *parent, EPRecord *record) : + parent(parent), + parentrecord(record), + start_routine(func), + arg(a), + user_thread(t), + waiting(NULL), + id(tid), + state(THREAD_CREATED), + model_thread(false) +{ + int ret; + + /* Initialize state */ + ret = create_context(); + if (ret) + model_print("Error in create_context\n"); + + user_thread->priv = this; +} + +/** Destructor */ +Thread::~Thread() +{ + if (!is_complete()) + complete(); + if (stack) + stack_free(stack); +} + +/** @return The thread_id_t corresponding to this Thread object. */ +thread_id_t Thread::get_id() const +{ + return id; +} + +/** + * Set a thread's THREAD_* state (@see thread_state) + * @param s The state to enter + */ +void Thread::set_state(thread_state s) +{ + ASSERT(s == THREAD_COMPLETED || state != THREAD_COMPLETED); + state = s; +} + +/** + * Get the Thread that this Thread is immediately waiting on + * @return The thread we are waiting on, if any; otherwise NULL + */ +Thread * Thread::waiting_on() +{ + return waiting; +} + +void Thread::set_waiting(Thread *th) { + waiting=th; +} + +/** + * Check if this Thread is waiting (blocking) on a given Thread, directly or + * indirectly (via a chain of waiting threads) + * + * @param t The Thread on which we may be waiting + * @return True if we are waiting on Thread t; false otherwise + */ +bool Thread::is_waiting_on(const Thread *t) { + Thread *wait; + for (wait = waiting_on(); wait != NULL; wait = wait->waiting_on()) + if (wait == t) + return true; + return false; +} diff --git a/valuerecord.cc b/valuerecord.cc new file mode 100644 index 0000000..180407f --- /dev/null +++ b/valuerecord.cc @@ -0,0 +1,67 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "valuerecord.h" +#include "mymemory.h" +#include "constraint.h" +#include "constgen.h" +#include "mcutil.h" + +ValueRecord::ValueRecord(IntHashSet *_set) : set(_set) +{ + uint numvalue=set->getSize(); + numvars=NUMBITS(numvalue-1); +} + +ValueRecord::~ValueRecord() { +} + +uint64_t ValueRecord::getValue(Constraint **vars, bool *satsolution) { + uint value=0; + for(int j=numvars-1;j>=0;j--) { + value=value<<1; + if (satsolution[vars[j]->getVar()]) + value|=1; + } + uint i=0; + IntIterator * it=set->iterator(); + while(it->hasNext()) { + uint64_t val=it->next(); + if (numvars==0) { + delete it; + return val; + } + if (i==value) { + delete it; + return val; + } + i++; + } + delete it; + return 111111111; +} + +Constraint * ValueRecord::getValueEncoding(Constraint **vars, uint64_t value) { + uint i=0; + IntIterator * it=set->iterator(); + while(it->hasNext()) { + if (it->next()==value) { + delete it; + if (numvars==0) { + return &ctrue; + } + return generateConstraint(numvars, vars, i); + } + i++; + } + delete it; + + + return NULL; +} diff --git a/valuerecord.h b/valuerecord.h new file mode 100644 index 0000000..9269223 --- /dev/null +++ b/valuerecord.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef VALUERECORD_H +#define VALUERECORD_H +#include "classlist.h" + +class ValueRecord { + public: + ValueRecord(IntHashSet *set); + ~ValueRecord(); + Constraint * getValueEncoding(Constraint **vars, uint64_t value); + uint64_t getValue(Constraint **vars, bool *satsolution); + uint getNumVars() {return numvars;} + MEMALLOC; + private: + IntHashSet *set; + uint numvars; +}; +#endif -- 2.34.1