From 889516917e3a2ac6da50262f64f73875be2f7aea Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 9 Oct 2012 10:46:58 +0100 Subject: [PATCH 01/99] New branch for writing a user guide and improving the existing documentation. Copied from Perforce Change: 179787 ServerID: perforce.ravenbrook.com --- mps/INSTALL | 1 - mps/Makefile.in | 69 - mps/README | 1 - mps/code/.gdbinit | 1 - mps/code/.p4ignore | 45 - mps/code/abq.c | 353 -- mps/code/abq.h | 100 - mps/code/abqtest.c | 219 -- mps/code/amcss.c | 389 -- mps/code/amcsshe.c | 314 -- mps/code/amcssth.c | 382 -- mps/code/amsss.c | 295 -- mps/code/amssshe.c | 218 -- mps/code/apss.c | 239 -- mps/code/arena.c | 791 ---- mps/code/arenacl.c | 518 --- mps/code/arenacv.c | 464 --- mps/code/arenavm.c | 1856 --------- mps/code/awlut.c | 364 -- mps/code/awluthe.c | 367 -- mps/code/awlutth.c | 375 -- mps/code/boot.c | 167 - mps/code/boot.h | 76 - mps/code/bt.c | 1060 ------ mps/code/bt.h | 116 - mps/code/btcv.c | 611 --- mps/code/bttest.c | 426 --- mps/code/buffer.c | 1580 -------- mps/code/cbs.c | 1695 --------- mps/code/cbs.h | 156 - mps/code/cbstest.c | 696 ---- mps/code/chain.h | 140 - mps/code/check.h | 354 -- mps/code/clock.h | 191 - mps/code/comm.gmk | 561 --- mps/code/commpost.nmk | 334 -- mps/code/commpre.nmk | 203 - mps/code/config.h | 446 --- mps/code/dbgpool.c | 713 ---- mps/code/dbgpool.h | 111 - mps/code/dbgpooli.c | 96 - mps/code/diag.c | 773 ---- mps/code/event.c | 505 --- mps/code/event.h | 184 - mps/code/eventcnv.c | 728 ---- mps/code/eventcom.h | 173 - mps/code/eventdef.h | 665 ---- mps/code/eventpro.c | 463 --- mps/code/eventpro.h | 81 - mps/code/eventrep.c | 784 ---- mps/code/eventrep.h | 66 - mps/code/exposet0.c | 314 -- mps/code/expt825.c | 314 -- mps/code/finalcv.c | 273 -- mps/code/finaltest.c | 299 -- mps/code/fmtdy.c | 884 ----- mps/code/fmtdy.h | 85 - mps/code/fmtdytst.c | 262 -- mps/code/fmtdytst.h | 81 - mps/code/fmthe.c | 241 -- mps/code/fmthe.h | 70 - mps/code/fmtno.c | 177 - mps/code/fmtno.h | 66 - mps/code/format.c | 205 - mps/code/fri3gc.gmk | 62 - mps/code/fri6gc.gmk | 60 - mps/code/gc.gmk | 70 - mps/code/global.c | 1120 ------ mps/code/gp.gmk | 72 - mps/code/ld.c | 252 -- mps/code/libcbt.c | 111 - mps/code/lii3gc.gmk | 61 - mps/code/lii6gc.gmk | 61 - mps/code/lo.h | 83 - mps/code/locbwcss.c | 247 -- mps/code/lock.h | 267 -- mps/code/lockan.c | 164 - mps/code/lockcov.c | 92 - mps/code/lockix.c | 285 -- mps/code/lockli.c | 299 -- mps/code/lockutw3.c | 135 - mps/code/lockw3.c | 198 - mps/code/locus.c | 528 --- mps/code/locusss.c | 289 -- mps/code/locv.c | 208 - mps/code/message.c | 467 --- mps/code/messtest.c | 315 -- mps/code/meter.c | 144 - mps/code/meter.h | 99 - mps/code/misc.h | 230 -- mps/code/mpm.c | 642 ---- mps/code/mpm.h | 1151 ------ mps/code/mpmss.c | 245 -- mps/code/mpmst.h | 746 ---- mps/code/mpmtypes.h | 492 --- mps/code/mps.c | 256 -- mps/code/mps.h | 708 ---- mps/code/mps.xcodeproj/project.pbxproj | 3952 ------------------- mps/code/mpsacl.h | 58 - mps/code/mpsavm.h | 63 - mps/code/mpscamc.h | 61 - mps/code/mpscams.h | 58 - mps/code/mpscawl.h | 56 - mps/code/mpsclo.h | 57 - mps/code/mpscmv.h | 59 - mps/code/mpscmv2.h | 77 - mps/code/mpscmvff.h | 59 - mps/code/mpscsnc.h | 56 - mps/code/mpsi.c | 1918 ---------- mps/code/mpsicv.c | 646 ---- mps/code/mpsio.h | 67 - mps/code/mpsioan.c | 126 - mps/code/mpsiw3.c | 73 - mps/code/mpslib.h | 88 - mps/code/mpsliban.c | 187 - mps/code/mpstd.h | 301 -- mps/code/mpsw3.h | 79 - mps/code/mpswin.h | 73 - mps/code/mv2test.c | 366 -- mps/code/ntbuild.cmd | 122 - mps/code/osxc.h | 59 - mps/code/pool.c | 662 ---- mps/code/poolabs.c | 704 ---- mps/code/poolamc.c | 2539 ------------ mps/code/poolams.c | 1748 --------- mps/code/poolams.h | 237 -- mps/code/poolamsi.c | 69 - mps/code/poolawl.c | 1325 ------- mps/code/poollo.c | 859 ----- mps/code/poolmfs.c | 345 -- mps/code/poolmfs.h | 91 - mps/code/poolmrg.c | 907 ----- mps/code/poolmrg.h | 61 - mps/code/poolmv.c | 906 ----- mps/code/poolmv.h | 98 - mps/code/poolmv2.c | 1190 ------ mps/code/poolmv2.h | 60 - mps/code/poolmvff.c | 733 ---- mps/code/pooln.c | 353 -- mps/code/pooln.h | 82 - mps/code/poolncv.c | 91 - mps/code/poolsnc.c | 738 ---- mps/code/prmcan.c | 79 - mps/code/prmci3.h | 65 - mps/code/prmci3fr.c | 93 - mps/code/prmci3li.c | 146 - mps/code/prmci3w3.c | 120 - mps/code/prmci6.h | 65 - mps/code/prmci6fr.c | 87 - mps/code/prmci6li.c | 150 - mps/code/prmci6w3.c | 126 - mps/code/prmcix.h | 64 - mps/code/prmcw3.h | 65 - mps/code/protan.c | 120 - mps/code/proti3.c | 283 -- mps/code/proti6.c | 124 - mps/code/protix.c | 175 - mps/code/protli.c | 182 - mps/code/protocol.c | 166 - mps/code/protocol.h | 228 -- mps/code/protsgix.c | 183 - mps/code/protw3.c | 178 - mps/code/pthrdext.c | 405 -- mps/code/pthrdext.h | 110 - mps/code/qs.c | 569 --- mps/code/ref.c | 123 - mps/code/replay.c | 225 -- mps/code/reserv.c | 447 --- mps/code/ring.c | 171 - mps/code/ring.h | 155 - mps/code/root.c | 711 ---- mps/code/sac.c | 424 --- mps/code/sac.h | 94 - mps/code/sacss.c | 245 -- mps/code/sc.h | 205 - mps/code/seg.c | 1716 --------- mps/code/segsmss.c | 904 ----- mps/code/shield.c | 374 -- mps/code/span.c | 67 - mps/code/spi3.c | 65 - mps/code/splay.c | 1069 ------ mps/code/splay.h | 126 - mps/code/ss.c | 106 - mps/code/ss.h | 85 - mps/code/ssan.c | 64 - mps/code/ssixi3.c | 108 - mps/code/ssixi6.c | 108 - mps/code/ssw3i3mv.c | 85 - mps/code/ssw3i6mv.c | 104 - mps/code/steptest.c | 555 --- mps/code/table.c | 422 -- mps/code/table.h | 100 - mps/code/teletest.c | 262 -- mps/code/test.c | 2 - mps/code/testlib.c | 426 --- mps/code/testlib.h | 250 -- mps/code/th.h | 115 - mps/code/than.c | 186 - mps/code/thix.c | 332 -- mps/code/thw3.c | 273 -- mps/code/thw3.h | 75 - mps/code/thw3i3.c | 168 - mps/code/thw3i6.c | 168 - mps/code/trace.c | 2042 ---------- mps/code/traceanc.c | 842 ---- mps/code/tract.c | 689 ---- mps/code/tract.h | 323 -- mps/code/version.c | 104 - mps/code/vman.c | 246 -- mps/code/vmix.c | 352 -- mps/code/vmw3.c | 312 -- mps/code/w3i3mv.nmk | 221 -- mps/code/w3i6mv.nmk | 221 -- mps/code/w3mv/amcss/amcss.vcxproj | 153 - mps/code/w3mv/eventcnv/eventcnv.vcxproj | 149 - mps/code/w3mv/mps.sln | 44 - mps/code/w3mv/mps/mps.vcxproj | 132 - mps/code/walk.c | 406 -- mps/code/walkt0.c | 258 -- mps/code/xci3gc.gmk | 62 - mps/code/zcoll.c | 977 ----- mps/code/zmess.c | 611 --- mps/configure | 4023 -------------------- mps/configure.ac | 100 - mps/design/alloc-frame/index.html | 517 --- mps/design/arena/index.html | 559 --- mps/design/arenavm/index.html | 280 -- mps/design/bt/index.html | 723 ---- mps/design/buffer/index.html | 858 ----- mps/design/cbs/index.html | 672 ---- mps/design/check/index.html | 182 - mps/design/class-interface/index.html | 311 -- mps/design/collection/index.html | 400 -- mps/design/config/index.html | 537 --- mps/design/critical-path.txt | 391 -- mps/design/cstyle/index.html | 614 --- mps/design/diag/index.html | 482 --- mps/design/finalize/index.html | 214 -- mps/design/fix/index.html | 153 - mps/design/index.html | 667 ---- mps/design/interface-c/index.html | 376 -- mps/design/io/index.html | 494 --- mps/design/lib/index.html | 203 - mps/design/lock/index.html | 256 -- mps/design/locus/index.html | 645 ---- mps/design/message-gc/index.html | 346 -- mps/design/message/index.html | 637 ---- mps/design/object-debug/index.html | 452 --- mps/design/pool/index.html | 157 - mps/design/poolamc/index.html | 770 ---- mps/design/poolams/index.html | 534 --- mps/design/poolawl/index.html | 577 --- mps/design/poollo/index.html | 313 -- mps/design/poolmfs/index.html | 129 - mps/design/poolmrg/index.html | 628 --- mps/design/poolmv/index.html | 125 - mps/design/poolmvff/index.html | 219 -- mps/design/poolmvt/index.html | 873 ----- mps/design/prot/index.html | 198 - mps/design/protan/index.html | 180 - mps/design/protli/index.html | 268 -- mps/design/protocol/index.html | 554 --- mps/design/protsu/index.html | 218 -- mps/design/pthreadext/index.html | 387 -- mps/design/reservoir/index.html | 208 - mps/design/ring/index.html | 267 -- mps/design/root/index.html | 178 - mps/design/scan/index.html | 189 - mps/design/seg/index.html | 386 -- mps/design/shield/index.html | 183 - mps/design/sig/index.html | 151 - mps/design/splay/index.html | 905 ----- mps/design/sso1al/index.html | 203 - mps/design/telemetry/index.html | 506 --- mps/design/template-with-guide.html | 146 - mps/design/tests/index.html | 160 - mps/design/thread-manager/index.html | 205 - mps/design/thread-safety/index.html | 390 -- mps/design/trace/index.html | 326 -- mps/design/type/index.html | 515 --- mps/design/version-library/index.html | 203 - mps/design/version/index.html | 136 - mps/design/vm/index.html | 208 - mps/design/vman/index.html | 127 - mps/design/vmo1/index.html | 147 - mps/design/vmso/index.html | 210 - mps/design/writef/index.html | 201 - mps/example/scheme/Makefile.in | 8 - mps/example/scheme/scheme.c | 3048 --------------- mps/license.txt | 83 - mps/procedure/index.html | 154 - mps/procedure/release-build/index.html | 351 -- mps/procedure/version-create/index.html | 217 -- mps/readme.txt | 168 - mps/test/argerr/0.c | 23 - mps/test/argerr/1.c | 23 - mps/test/argerr/10.c | 53 - mps/test/argerr/100.c | 38 - mps/test/argerr/101.c | 38 - mps/test/argerr/102.c | 39 - mps/test/argerr/103.c | 39 - mps/test/argerr/104.c | 39 - mps/test/argerr/105.c | 39 - mps/test/argerr/106.c | 39 - mps/test/argerr/107.c | 39 - mps/test/argerr/108.c | 39 - mps/test/argerr/109.c | 39 - mps/test/argerr/11.c | 53 - mps/test/argerr/110.c | 39 - mps/test/argerr/111.c | 39 - mps/test/argerr/112.c | 39 - mps/test/argerr/113.c | 39 - mps/test/argerr/114.c | 39 - mps/test/argerr/115.c | 44 - mps/test/argerr/116.c | 44 - mps/test/argerr/117.c | 45 - mps/test/argerr/118.c | 45 - mps/test/argerr/119.c | 45 - mps/test/argerr/12.c | 54 - mps/test/argerr/120.c | 45 - mps/test/argerr/121.c | 45 - mps/test/argerr/122.c | 45 - mps/test/argerr/123.c | 45 - mps/test/argerr/124.c | 45 - mps/test/argerr/125.c | 45 - mps/test/argerr/126.c | 45 - mps/test/argerr/127.c | 45 - mps/test/argerr/128.c | 45 - mps/test/argerr/129.c | 45 - mps/test/argerr/13.c | 54 - mps/test/argerr/130.c | 37 - mps/test/argerr/131.c | 37 - mps/test/argerr/132.c | 38 - mps/test/argerr/133.c | 38 - mps/test/argerr/134.c | 38 - mps/test/argerr/135.c | 38 - mps/test/argerr/136.c | 39 - mps/test/argerr/137.c | 39 - mps/test/argerr/138.c | 39 - mps/test/argerr/139.c | 39 - mps/test/argerr/14.c | 54 - mps/test/argerr/140.c | 38 - mps/test/argerr/141.c | 38 - mps/test/argerr/142.c | 38 - mps/test/argerr/143.c | 38 - mps/test/argerr/144.c | 35 - mps/test/argerr/145.c | 35 - mps/test/argerr/146.c | 489 --- mps/test/argerr/147.c | 489 --- mps/test/argerr/148.c | 489 --- mps/test/argerr/149.c | 490 --- mps/test/argerr/15.c | 54 - mps/test/argerr/150.c | 489 --- mps/test/argerr/151.c | 490 --- mps/test/argerr/152.c | 50 - mps/test/argerr/153.c | 33 - mps/test/argerr/154.c | 66 - mps/test/argerr/16.c | 54 - mps/test/argerr/17.c | 54 - mps/test/argerr/18.c | 56 - mps/test/argerr/19.c | 56 - mps/test/argerr/2.c | 26 - mps/test/argerr/20.c | 48 - mps/test/argerr/21.c | 48 - mps/test/argerr/22.c | 48 - mps/test/argerr/23.c | 48 - mps/test/argerr/24.c | 48 - mps/test/argerr/25.c | 48 - mps/test/argerr/26.c | 48 - mps/test/argerr/27.c | 49 - mps/test/argerr/28.c | 49 - mps/test/argerr/29.c | 49 - mps/test/argerr/3.c | 26 - mps/test/argerr/30.c | 49 - mps/test/argerr/31.c | 49 - mps/test/argerr/32.c | 49 - mps/test/argerr/33.c | 49 - mps/test/argerr/34.c | 47 - mps/test/argerr/35.c | 48 - mps/test/argerr/36.c | 50 - mps/test/argerr/37.c | 48 - mps/test/argerr/38.c | 42 - mps/test/argerr/39.c | 42 - mps/test/argerr/4.c | 46 - mps/test/argerr/40.c | 42 - mps/test/argerr/41.c | 43 - mps/test/argerr/42.c | 43 - mps/test/argerr/43.c | 43 - mps/test/argerr/44.c | 43 - mps/test/argerr/45.c | 58 - mps/test/argerr/46.c | 58 - mps/test/argerr/47.c | 59 - mps/test/argerr/48.c | 59 - mps/test/argerr/49.c | 59 - mps/test/argerr/5.c | 46 - mps/test/argerr/50.c | 59 - mps/test/argerr/51.c | 59 - mps/test/argerr/52.c | 61 - mps/test/argerr/53.c | 61 - mps/test/argerr/54.c | 65 - mps/test/argerr/55.c | 65 - mps/test/argerr/56.c | 66 - mps/test/argerr/57.c | 66 - mps/test/argerr/58.c | 66 - mps/test/argerr/59.c | 66 - mps/test/argerr/6.c | 48 - mps/test/argerr/60.c | 66 - mps/test/argerr/61.c | 69 - mps/test/argerr/62.c | 69 - mps/test/argerr/63.c | 69 - mps/test/argerr/64.c | 69 - mps/test/argerr/65.c | 69 - mps/test/argerr/66.c | 69 - mps/test/argerr/67.c | 69 - mps/test/argerr/68.c | 32 - mps/test/argerr/69.c | 32 - mps/test/argerr/7.c | 48 - mps/test/argerr/70.c | 33 - mps/test/argerr/71.c | 33 - mps/test/argerr/72.c | 35 - mps/test/argerr/73.c | 35 - mps/test/argerr/74.c | 35 - mps/test/argerr/75.c | 35 - mps/test/argerr/76.c | 36 - mps/test/argerr/77.c | 36 - mps/test/argerr/78.c | 38 - mps/test/argerr/79.c | 38 - mps/test/argerr/8.c | 50 - mps/test/argerr/80.c | 38 - mps/test/argerr/81.c | 38 - mps/test/argerr/82.c | 38 - mps/test/argerr/83.c | 38 - mps/test/argerr/84.c | 40 - mps/test/argerr/85.c | 40 - mps/test/argerr/86.c | 40 - mps/test/argerr/87.c | 40 - mps/test/argerr/88.c | 40 - mps/test/argerr/89.c | 40 - mps/test/argerr/9.c | 50 - mps/test/argerr/90.c | 42 - mps/test/argerr/91.c | 42 - mps/test/argerr/92.c | 43 - mps/test/argerr/93.c | 43 - mps/test/argerr/94.c | 43 - mps/test/argerr/95.c | 43 - mps/test/argerr/96.c | 43 - mps/test/argerr/97.c | 43 - mps/test/argerr/98.c | 43 - mps/test/argerr/99.c | 43 - mps/test/conerr/0.c | 27 - mps/test/conerr/1.c | 24 - mps/test/conerr/10.c | 56 - mps/test/conerr/11.c | 58 - mps/test/conerr/12.c | 62 - mps/test/conerr/13.c | 45 - mps/test/conerr/14.c | 40 - mps/test/conerr/15.c | 45 - mps/test/conerr/16.c | 46 - mps/test/conerr/17.c | 74 - mps/test/conerr/18.c | 68 - mps/test/conerr/19.c | 49 - mps/test/conerr/2.c | 25 - mps/test/conerr/20.c | 47 - mps/test/conerr/21.c | 50 - mps/test/conerr/22.c | 50 - mps/test/conerr/23.c | 53 - mps/test/conerr/24.c | 68 - mps/test/conerr/25.c | 70 - mps/test/conerr/26.c | 51 - mps/test/conerr/27.c | 57 - mps/test/conerr/28.c | 74 - mps/test/conerr/29.c | 72 - mps/test/conerr/3.c | 25 - mps/test/conerr/30.c | 74 - mps/test/conerr/31.c | 75 - mps/test/conerr/32.c | 49 - mps/test/conerr/33.c | 72 - mps/test/conerr/33a.c | 80 - mps/test/conerr/34.c | 78 - mps/test/conerr/35.c | 76 - mps/test/conerr/36.c | 80 - mps/test/conerr/37.c | 84 - mps/test/conerr/37f.c | 87 - mps/test/conerr/38.c | 84 - mps/test/conerr/38f.c | 87 - mps/test/conerr/39.c | 85 - mps/test/conerr/39f.c | 88 - mps/test/conerr/4.c | 39 - mps/test/conerr/40.c | 83 - mps/test/conerr/40f.c | 86 - mps/test/conerr/41.c | 45 - mps/test/conerr/42.c | 44 - mps/test/conerr/43.c | 45 - mps/test/conerr/44.c | 46 - mps/test/conerr/44a.c | 53 - mps/test/conerr/45.c | 42 - mps/test/conerr/46.c | 43 - mps/test/conerr/47.c | 42 - mps/test/conerr/48.c | 43 - mps/test/conerr/49.c | 46 - mps/test/conerr/5.c | 51 - mps/test/conerr/50.c | 35 - mps/test/conerr/51.c | 33 - mps/test/conerr/52.c | 37 - mps/test/conerr/53.c | 39 - mps/test/conerr/54.c | 43 - mps/test/conerr/55.c | 42 - mps/test/conerr/56.c | 40 - mps/test/conerr/57.c | 38 - mps/test/conerr/58.c | 37 - mps/test/conerr/59.c | 51 - mps/test/conerr/6.c | 41 - mps/test/conerr/7.c | 35 - mps/test/conerr/8.c | 53 - mps/test/conerr/9.c | 53 - mps/test/function/0.c | 18 - mps/test/function/1.c | 25 - mps/test/function/10.c | 118 - mps/test/function/100.c | 139 - mps/test/function/101.c | 175 - mps/test/function/103.c | 159 - mps/test/function/104.c | 244 -- mps/test/function/105.c | 99 - mps/test/function/106.c | 124 - mps/test/function/107.c | 125 - mps/test/function/108.c | 106 - mps/test/function/109.c | 296 -- mps/test/function/11.c | 99 - mps/test/function/110.c | 304 -- mps/test/function/111.c | 222 -- mps/test/function/112.c | 94 - mps/test/function/113.c | 126 - mps/test/function/114.c | 126 - mps/test/function/116.c | 116 - mps/test/function/117.c | 114 - mps/test/function/118.c | 146 - mps/test/function/119.c | 38 - mps/test/function/12.c | 203 - mps/test/function/120.c | 126 - mps/test/function/121.c | 61 - mps/test/function/122.c | 195 - mps/test/function/123.c | 115 - mps/test/function/124.c | 159 - mps/test/function/125.c | 102 - mps/test/function/126.c | 104 - mps/test/function/127.c | 160 - mps/test/function/128.c | 160 - mps/test/function/129.c | 160 - mps/test/function/12p.c | 215 -- mps/test/function/13.c | 211 - mps/test/function/130.c | 117 - mps/test/function/131.c | 122 - mps/test/function/132.c | 187 - mps/test/function/133.c | 139 - mps/test/function/134.c | 160 - mps/test/function/135.c | 64 - mps/test/function/136.c | 164 - mps/test/function/137.c | 106 - mps/test/function/138.c | 85 - mps/test/function/139.c | 85 - mps/test/function/14.c | 122 - mps/test/function/140.c | 190 - mps/test/function/144.c | 65 - mps/test/function/147.c | 104 - mps/test/function/148.c | 144 - mps/test/function/149.c | 198 - mps/test/function/15.c | 78 - mps/test/function/150.c | 326 -- mps/test/function/151.c | 84 - mps/test/function/152.c | 124 - mps/test/function/153.c | 83 - mps/test/function/158.c | 53 - mps/test/function/159.c | 57 - mps/test/function/16.c | 112 - mps/test/function/160.c | 64 - mps/test/function/161.c | 58 - mps/test/function/162.c | 57 - mps/test/function/163.c | 106 - mps/test/function/164.c | 184 - mps/test/function/165.c | 110 - mps/test/function/167.c | 103 - mps/test/function/17.c | 63 - mps/test/function/170.c | 230 -- mps/test/function/171.c | 161 - mps/test/function/18.c | 78 - mps/test/function/19.c | 78 - mps/test/function/2.c | 102 - mps/test/function/20.c | 57 - mps/test/function/200.c | 176 - mps/test/function/203.c | 216 -- mps/test/function/204.c | 216 -- mps/test/function/205.c | 216 -- mps/test/function/206.c | 189 - mps/test/function/207.c | 184 - mps/test/function/21.c | 36 - mps/test/function/214.c | 77 - mps/test/function/215.c | 173 - mps/test/function/22.c | 38 - mps/test/function/223.c | 173 - mps/test/function/224.c | 53 - mps/test/function/226.c | 194 - mps/test/function/227.c | 202 - mps/test/function/23.c | 129 - mps/test/function/24.c | 120 - mps/test/function/25.c | 125 - mps/test/function/26.c | 62 - mps/test/function/27.c | 93 - mps/test/function/28.c | 118 - mps/test/function/29.c | 125 - mps/test/function/3.c | 102 - mps/test/function/30.c | 106 - mps/test/function/31.c | 111 - mps/test/function/32.c | 107 - mps/test/function/33.c | 106 - mps/test/function/34.c | 109 - mps/test/function/35.c | 129 - mps/test/function/36.c | 114 - mps/test/function/37.c | 132 - mps/test/function/38.c | 183 - mps/test/function/39.c | 114 - mps/test/function/4.c | 114 - mps/test/function/40.c | 99 - mps/test/function/41.c | 134 - mps/test/function/42.c | 130 - mps/test/function/43.c | 141 - mps/test/function/44.c | 191 - mps/test/function/45.c | 212 -- mps/test/function/46.c | 163 - mps/test/function/47.c | 120 - mps/test/function/48.c | 140 - mps/test/function/49.c | 302 -- mps/test/function/5.c | 114 - mps/test/function/50.c | 305 -- mps/test/function/500.txt | 42 - mps/test/function/501.txt | 31 - mps/test/function/502.txt | 34 - mps/test/function/503.txt | 39 - mps/test/function/504.txt | 19 - mps/test/function/51.c | 222 -- mps/test/function/52.c | 110 - mps/test/function/53.c | 129 - mps/test/function/54.c | 129 - mps/test/function/55.c | 128 - mps/test/function/56.c | 126 - mps/test/function/57.c | 122 - mps/test/function/6.c | 101 - mps/test/function/60.c | 110 - mps/test/function/61.c | 103 - mps/test/function/62.c | 103 - mps/test/function/63.c | 95 - mps/test/function/64.c | 128 - mps/test/function/65.c | 211 - mps/test/function/66.c | 179 - mps/test/function/67.c | 124 - mps/test/function/68.c | 107 - mps/test/function/69.c | 116 - mps/test/function/7.c | 35 - mps/test/function/70.c | 39 - mps/test/function/71.c | 33 - mps/test/function/72.c | 103 - mps/test/function/73.c | 93 - mps/test/function/74.c | 93 - mps/test/function/75.c | 96 - mps/test/function/76.c | 150 - mps/test/function/77.c | 119 - mps/test/function/78.c | 122 - mps/test/function/79.c | 119 - mps/test/function/8.c | 65 - mps/test/function/80.c | 119 - mps/test/function/81.c | 101 - mps/test/function/83.c | 131 - mps/test/function/9.c | 80 - mps/test/function/96.c | 148 - mps/test/function/97.c | 249 -- mps/test/function/98.c | 35 - mps/test/function/99.c | 119 - mps/test/misc/0.c | 36 - mps/test/misc/1.c | 38 - mps/test/misc/2.c | 40 - mps/test/test/README | 10 - mps/test/test/qa | 76 - mps/test/test/script/clib | 384 -- mps/test/test/script/commands/clib | 22 - mps/test/test/script/commands/help | 53 - mps/test/test/script/commands/index | 88 - mps/test/test/script/commands/options | 9 - mps/test/test/script/commands/run | 20 - mps/test/test/script/commands/runset | 19 - mps/test/test/script/commands/try | 9 - mps/test/test/script/compile | 119 - mps/test/test/script/dirs | 36 - mps/test/test/script/display | 35 - mps/test/test/script/headconv | 53 - mps/test/test/script/headread | 270 -- mps/test/test/script/help/clib | 16 - mps/test/test/script/help/index | 10 - mps/test/test/script/help/install | 44 - mps/test/test/script/help/naming | 22 - mps/test/test/script/help/options | 119 - mps/test/test/script/help/output | 37 - mps/test/test/script/help/problems | 14 - mps/test/test/script/help/run | 15 - mps/test/test/script/help/runset | 22 - mps/test/test/script/init | 19 - mps/test/test/script/logging | 305 -- mps/test/test/script/ntx86bin/blat.exe | Bin 37888 -> 0 bytes mps/test/test/script/ntx86bin/cat.exe | Bin 28672 -> 0 bytes mps/test/test/script/ntx86bin/cygwin.dll | Bin 1317533 -> 0 bytes mps/test/test/script/ntx86bin/gwinsock.dll | Bin 22016 -> 0 bytes mps/test/test/script/ntx86bin/strings.exe | Bin 28160 -> 0 bytes mps/test/test/script/ntx86bin/tee.exe | Bin 8704 -> 0 bytes mps/test/test/script/options | 92 - mps/test/test/script/optproc | 211 - mps/test/test/script/platform | 242 -- mps/test/test/script/require | 27 - mps/test/test/script/runtest | 264 -- mps/test/test/script/useful | 53 - mps/test/test/script/version | 36 - mps/test/test/testlib/arg.h | 36 - mps/test/test/testlib/assumed | 31 - mps/test/test/testlib/awlfmt.c | 566 --- mps/test/test/testlib/awlfmt.h | 89 - mps/test/test/testlib/exfmt.c | 553 --- mps/test/test/testlib/exfmt.h | 126 - mps/test/test/testlib/fastfmt.c | 349 -- mps/test/test/testlib/fastfmt.h | 73 - mps/test/test/testlib/lofmt.c | 194 - mps/test/test/testlib/lofmt.h | 62 - mps/test/test/testlib/manifest | 11 - mps/test/test/testlib/myfmt.c | 219 -- mps/test/test/testlib/myfmt.h | 46 - mps/test/test/testlib/newfmt.c | 525 --- mps/test/test/testlib/newfmt.h | 88 - mps/test/test/testlib/platform.c | 33 - mps/test/test/testlib/platform.h | 15 - mps/test/test/testlib/postBQ.h | 7 - mps/test/test/testlib/postGR.h | 29 - mps/test/test/testlib/postHU.h | 7 - mps/test/test/testlib/postMO.h | 5 - mps/test/test/testlib/preBQ.h | 6 - mps/test/test/testlib/preGR.h | 29 - mps/test/test/testlib/preHU.h | 14 - mps/test/test/testlib/preMO.h | 14 - mps/test/test/testlib/rankfmt.c | 725 ---- mps/test/test/testlib/rankfmt.h | 155 - mps/test/test/testlib/testlib.c | 656 ---- mps/test/test/testlib/testlib.h | 179 - mps/test/test/testlib/versind.h | 120 - mps/test/testsets/daily | 90 - mps/test/testsets/dailydw | 96 - mps/test/testsets/dylan1 | 78 - mps/tool/autoconf/build-aux/config.guess | 1530 -------- mps/tool/autoconf/build-aux/config.sub | 1782 --------- mps/tool/autoconf/build-aux/install-sh | 527 --- mps/tool/index.html | 122 - mps/tool/mpsclasses.py | 297 -- mps/tool/test-runner.py | 187 - 757 files changed, 158114 deletions(-) delete mode 120000 mps/INSTALL delete mode 100644 mps/Makefile.in delete mode 120000 mps/README delete mode 100644 mps/code/.gdbinit delete mode 100644 mps/code/.p4ignore delete mode 100644 mps/code/abq.c delete mode 100644 mps/code/abq.h delete mode 100644 mps/code/abqtest.c delete mode 100644 mps/code/amcss.c delete mode 100644 mps/code/amcsshe.c delete mode 100644 mps/code/amcssth.c delete mode 100644 mps/code/amsss.c delete mode 100644 mps/code/amssshe.c delete mode 100644 mps/code/apss.c delete mode 100644 mps/code/arena.c delete mode 100644 mps/code/arenacl.c delete mode 100644 mps/code/arenacv.c delete mode 100644 mps/code/arenavm.c delete mode 100644 mps/code/awlut.c delete mode 100644 mps/code/awluthe.c delete mode 100644 mps/code/awlutth.c delete mode 100644 mps/code/boot.c delete mode 100644 mps/code/boot.h delete mode 100644 mps/code/bt.c delete mode 100644 mps/code/bt.h delete mode 100644 mps/code/btcv.c delete mode 100644 mps/code/bttest.c delete mode 100644 mps/code/buffer.c delete mode 100644 mps/code/cbs.c delete mode 100644 mps/code/cbs.h delete mode 100644 mps/code/cbstest.c delete mode 100644 mps/code/chain.h delete mode 100644 mps/code/check.h delete mode 100644 mps/code/clock.h delete mode 100644 mps/code/comm.gmk delete mode 100644 mps/code/commpost.nmk delete mode 100644 mps/code/commpre.nmk delete mode 100644 mps/code/config.h delete mode 100644 mps/code/dbgpool.c delete mode 100644 mps/code/dbgpool.h delete mode 100644 mps/code/dbgpooli.c delete mode 100644 mps/code/diag.c delete mode 100644 mps/code/event.c delete mode 100644 mps/code/event.h delete mode 100644 mps/code/eventcnv.c delete mode 100644 mps/code/eventcom.h delete mode 100644 mps/code/eventdef.h delete mode 100644 mps/code/eventpro.c delete mode 100644 mps/code/eventpro.h delete mode 100644 mps/code/eventrep.c delete mode 100644 mps/code/eventrep.h delete mode 100644 mps/code/exposet0.c delete mode 100644 mps/code/expt825.c delete mode 100644 mps/code/finalcv.c delete mode 100644 mps/code/finaltest.c delete mode 100644 mps/code/fmtdy.c delete mode 100644 mps/code/fmtdy.h delete mode 100644 mps/code/fmtdytst.c delete mode 100644 mps/code/fmtdytst.h delete mode 100644 mps/code/fmthe.c delete mode 100644 mps/code/fmthe.h delete mode 100644 mps/code/fmtno.c delete mode 100644 mps/code/fmtno.h delete mode 100644 mps/code/format.c delete mode 100644 mps/code/fri3gc.gmk delete mode 100644 mps/code/fri6gc.gmk delete mode 100644 mps/code/gc.gmk delete mode 100644 mps/code/global.c delete mode 100644 mps/code/gp.gmk delete mode 100644 mps/code/ld.c delete mode 100644 mps/code/libcbt.c delete mode 100644 mps/code/lii3gc.gmk delete mode 100644 mps/code/lii6gc.gmk delete mode 100644 mps/code/lo.h delete mode 100644 mps/code/locbwcss.c delete mode 100644 mps/code/lock.h delete mode 100644 mps/code/lockan.c delete mode 100644 mps/code/lockcov.c delete mode 100644 mps/code/lockix.c delete mode 100644 mps/code/lockli.c delete mode 100644 mps/code/lockutw3.c delete mode 100644 mps/code/lockw3.c delete mode 100644 mps/code/locus.c delete mode 100644 mps/code/locusss.c delete mode 100644 mps/code/locv.c delete mode 100644 mps/code/message.c delete mode 100644 mps/code/messtest.c delete mode 100644 mps/code/meter.c delete mode 100644 mps/code/meter.h delete mode 100644 mps/code/misc.h delete mode 100644 mps/code/mpm.c delete mode 100644 mps/code/mpm.h delete mode 100644 mps/code/mpmss.c delete mode 100644 mps/code/mpmst.h delete mode 100644 mps/code/mpmtypes.h delete mode 100644 mps/code/mps.c delete mode 100644 mps/code/mps.h delete mode 100644 mps/code/mps.xcodeproj/project.pbxproj delete mode 100644 mps/code/mpsacl.h delete mode 100644 mps/code/mpsavm.h delete mode 100644 mps/code/mpscamc.h delete mode 100644 mps/code/mpscams.h delete mode 100644 mps/code/mpscawl.h delete mode 100644 mps/code/mpsclo.h delete mode 100644 mps/code/mpscmv.h delete mode 100644 mps/code/mpscmv2.h delete mode 100644 mps/code/mpscmvff.h delete mode 100644 mps/code/mpscsnc.h delete mode 100644 mps/code/mpsi.c delete mode 100644 mps/code/mpsicv.c delete mode 100644 mps/code/mpsio.h delete mode 100644 mps/code/mpsioan.c delete mode 100644 mps/code/mpsiw3.c delete mode 100644 mps/code/mpslib.h delete mode 100644 mps/code/mpsliban.c delete mode 100644 mps/code/mpstd.h delete mode 100644 mps/code/mpsw3.h delete mode 100644 mps/code/mpswin.h delete mode 100644 mps/code/mv2test.c delete mode 100644 mps/code/ntbuild.cmd delete mode 100644 mps/code/osxc.h delete mode 100644 mps/code/pool.c delete mode 100644 mps/code/poolabs.c delete mode 100644 mps/code/poolamc.c delete mode 100644 mps/code/poolams.c delete mode 100644 mps/code/poolams.h delete mode 100644 mps/code/poolamsi.c delete mode 100644 mps/code/poolawl.c delete mode 100644 mps/code/poollo.c delete mode 100644 mps/code/poolmfs.c delete mode 100644 mps/code/poolmfs.h delete mode 100644 mps/code/poolmrg.c delete mode 100644 mps/code/poolmrg.h delete mode 100644 mps/code/poolmv.c delete mode 100644 mps/code/poolmv.h delete mode 100644 mps/code/poolmv2.c delete mode 100644 mps/code/poolmv2.h delete mode 100644 mps/code/poolmvff.c delete mode 100644 mps/code/pooln.c delete mode 100644 mps/code/pooln.h delete mode 100644 mps/code/poolncv.c delete mode 100644 mps/code/poolsnc.c delete mode 100644 mps/code/prmcan.c delete mode 100644 mps/code/prmci3.h delete mode 100644 mps/code/prmci3fr.c delete mode 100644 mps/code/prmci3li.c delete mode 100644 mps/code/prmci3w3.c delete mode 100644 mps/code/prmci6.h delete mode 100644 mps/code/prmci6fr.c delete mode 100644 mps/code/prmci6li.c delete mode 100644 mps/code/prmci6w3.c delete mode 100644 mps/code/prmcix.h delete mode 100644 mps/code/prmcw3.h delete mode 100644 mps/code/protan.c delete mode 100644 mps/code/proti3.c delete mode 100644 mps/code/proti6.c delete mode 100644 mps/code/protix.c delete mode 100644 mps/code/protli.c delete mode 100644 mps/code/protocol.c delete mode 100644 mps/code/protocol.h delete mode 100644 mps/code/protsgix.c delete mode 100644 mps/code/protw3.c delete mode 100644 mps/code/pthrdext.c delete mode 100644 mps/code/pthrdext.h delete mode 100644 mps/code/qs.c delete mode 100644 mps/code/ref.c delete mode 100644 mps/code/replay.c delete mode 100644 mps/code/reserv.c delete mode 100644 mps/code/ring.c delete mode 100644 mps/code/ring.h delete mode 100644 mps/code/root.c delete mode 100644 mps/code/sac.c delete mode 100644 mps/code/sac.h delete mode 100644 mps/code/sacss.c delete mode 100644 mps/code/sc.h delete mode 100644 mps/code/seg.c delete mode 100644 mps/code/segsmss.c delete mode 100644 mps/code/shield.c delete mode 100644 mps/code/span.c delete mode 100644 mps/code/spi3.c delete mode 100644 mps/code/splay.c delete mode 100644 mps/code/splay.h delete mode 100644 mps/code/ss.c delete mode 100644 mps/code/ss.h delete mode 100644 mps/code/ssan.c delete mode 100644 mps/code/ssixi3.c delete mode 100644 mps/code/ssixi6.c delete mode 100644 mps/code/ssw3i3mv.c delete mode 100644 mps/code/ssw3i6mv.c delete mode 100644 mps/code/steptest.c delete mode 100644 mps/code/table.c delete mode 100644 mps/code/table.h delete mode 100644 mps/code/teletest.c delete mode 100644 mps/code/test.c delete mode 100644 mps/code/testlib.c delete mode 100644 mps/code/testlib.h delete mode 100644 mps/code/th.h delete mode 100644 mps/code/than.c delete mode 100644 mps/code/thix.c delete mode 100644 mps/code/thw3.c delete mode 100644 mps/code/thw3.h delete mode 100644 mps/code/thw3i3.c delete mode 100644 mps/code/thw3i6.c delete mode 100644 mps/code/trace.c delete mode 100644 mps/code/traceanc.c delete mode 100644 mps/code/tract.c delete mode 100644 mps/code/tract.h delete mode 100644 mps/code/version.c delete mode 100644 mps/code/vman.c delete mode 100644 mps/code/vmix.c delete mode 100644 mps/code/vmw3.c delete mode 100644 mps/code/w3i3mv.nmk delete mode 100644 mps/code/w3i6mv.nmk delete mode 100755 mps/code/w3mv/amcss/amcss.vcxproj delete mode 100755 mps/code/w3mv/eventcnv/eventcnv.vcxproj delete mode 100755 mps/code/w3mv/mps.sln delete mode 100755 mps/code/w3mv/mps/mps.vcxproj delete mode 100644 mps/code/walk.c delete mode 100644 mps/code/walkt0.c delete mode 100644 mps/code/xci3gc.gmk delete mode 100644 mps/code/zcoll.c delete mode 100644 mps/code/zmess.c delete mode 100755 mps/configure delete mode 100644 mps/configure.ac delete mode 100644 mps/design/alloc-frame/index.html delete mode 100644 mps/design/arena/index.html delete mode 100644 mps/design/arenavm/index.html delete mode 100644 mps/design/bt/index.html delete mode 100644 mps/design/buffer/index.html delete mode 100644 mps/design/cbs/index.html delete mode 100644 mps/design/check/index.html delete mode 100644 mps/design/class-interface/index.html delete mode 100644 mps/design/collection/index.html delete mode 100644 mps/design/config/index.html delete mode 100644 mps/design/critical-path.txt delete mode 100644 mps/design/cstyle/index.html delete mode 100644 mps/design/diag/index.html delete mode 100644 mps/design/finalize/index.html delete mode 100644 mps/design/fix/index.html delete mode 100644 mps/design/index.html delete mode 100644 mps/design/interface-c/index.html delete mode 100644 mps/design/io/index.html delete mode 100644 mps/design/lib/index.html delete mode 100644 mps/design/lock/index.html delete mode 100644 mps/design/locus/index.html delete mode 100644 mps/design/message-gc/index.html delete mode 100644 mps/design/message/index.html delete mode 100644 mps/design/object-debug/index.html delete mode 100644 mps/design/pool/index.html delete mode 100644 mps/design/poolamc/index.html delete mode 100644 mps/design/poolams/index.html delete mode 100644 mps/design/poolawl/index.html delete mode 100644 mps/design/poollo/index.html delete mode 100644 mps/design/poolmfs/index.html delete mode 100644 mps/design/poolmrg/index.html delete mode 100644 mps/design/poolmv/index.html delete mode 100644 mps/design/poolmvff/index.html delete mode 100644 mps/design/poolmvt/index.html delete mode 100644 mps/design/prot/index.html delete mode 100644 mps/design/protan/index.html delete mode 100644 mps/design/protli/index.html delete mode 100644 mps/design/protocol/index.html delete mode 100644 mps/design/protsu/index.html delete mode 100644 mps/design/pthreadext/index.html delete mode 100644 mps/design/reservoir/index.html delete mode 100644 mps/design/ring/index.html delete mode 100644 mps/design/root/index.html delete mode 100644 mps/design/scan/index.html delete mode 100644 mps/design/seg/index.html delete mode 100644 mps/design/shield/index.html delete mode 100644 mps/design/sig/index.html delete mode 100644 mps/design/splay/index.html delete mode 100644 mps/design/sso1al/index.html delete mode 100644 mps/design/telemetry/index.html delete mode 100644 mps/design/template-with-guide.html delete mode 100644 mps/design/tests/index.html delete mode 100644 mps/design/thread-manager/index.html delete mode 100644 mps/design/thread-safety/index.html delete mode 100644 mps/design/trace/index.html delete mode 100644 mps/design/type/index.html delete mode 100644 mps/design/version-library/index.html delete mode 100644 mps/design/version/index.html delete mode 100644 mps/design/vm/index.html delete mode 100644 mps/design/vman/index.html delete mode 100644 mps/design/vmo1/index.html delete mode 100644 mps/design/vmso/index.html delete mode 100644 mps/design/writef/index.html delete mode 100644 mps/example/scheme/Makefile.in delete mode 100644 mps/example/scheme/scheme.c delete mode 100644 mps/license.txt delete mode 100644 mps/procedure/index.html delete mode 100644 mps/procedure/release-build/index.html delete mode 100644 mps/procedure/version-create/index.html delete mode 100644 mps/readme.txt delete mode 100644 mps/test/argerr/0.c delete mode 100644 mps/test/argerr/1.c delete mode 100644 mps/test/argerr/10.c delete mode 100644 mps/test/argerr/100.c delete mode 100644 mps/test/argerr/101.c delete mode 100644 mps/test/argerr/102.c delete mode 100644 mps/test/argerr/103.c delete mode 100644 mps/test/argerr/104.c delete mode 100644 mps/test/argerr/105.c delete mode 100644 mps/test/argerr/106.c delete mode 100644 mps/test/argerr/107.c delete mode 100644 mps/test/argerr/108.c delete mode 100644 mps/test/argerr/109.c delete mode 100644 mps/test/argerr/11.c delete mode 100644 mps/test/argerr/110.c delete mode 100644 mps/test/argerr/111.c delete mode 100644 mps/test/argerr/112.c delete mode 100644 mps/test/argerr/113.c delete mode 100644 mps/test/argerr/114.c delete mode 100644 mps/test/argerr/115.c delete mode 100644 mps/test/argerr/116.c delete mode 100644 mps/test/argerr/117.c delete mode 100644 mps/test/argerr/118.c delete mode 100644 mps/test/argerr/119.c delete mode 100644 mps/test/argerr/12.c delete mode 100644 mps/test/argerr/120.c delete mode 100644 mps/test/argerr/121.c delete mode 100644 mps/test/argerr/122.c delete mode 100644 mps/test/argerr/123.c delete mode 100644 mps/test/argerr/124.c delete mode 100644 mps/test/argerr/125.c delete mode 100644 mps/test/argerr/126.c delete mode 100644 mps/test/argerr/127.c delete mode 100644 mps/test/argerr/128.c delete mode 100644 mps/test/argerr/129.c delete mode 100644 mps/test/argerr/13.c delete mode 100644 mps/test/argerr/130.c delete mode 100644 mps/test/argerr/131.c delete mode 100644 mps/test/argerr/132.c delete mode 100644 mps/test/argerr/133.c delete mode 100644 mps/test/argerr/134.c delete mode 100644 mps/test/argerr/135.c delete mode 100644 mps/test/argerr/136.c delete mode 100644 mps/test/argerr/137.c delete mode 100644 mps/test/argerr/138.c delete mode 100644 mps/test/argerr/139.c delete mode 100644 mps/test/argerr/14.c delete mode 100644 mps/test/argerr/140.c delete mode 100644 mps/test/argerr/141.c delete mode 100644 mps/test/argerr/142.c delete mode 100644 mps/test/argerr/143.c delete mode 100644 mps/test/argerr/144.c delete mode 100644 mps/test/argerr/145.c delete mode 100644 mps/test/argerr/146.c delete mode 100644 mps/test/argerr/147.c delete mode 100644 mps/test/argerr/148.c delete mode 100644 mps/test/argerr/149.c delete mode 100644 mps/test/argerr/15.c delete mode 100644 mps/test/argerr/150.c delete mode 100644 mps/test/argerr/151.c delete mode 100644 mps/test/argerr/152.c delete mode 100644 mps/test/argerr/153.c delete mode 100644 mps/test/argerr/154.c delete mode 100644 mps/test/argerr/16.c delete mode 100644 mps/test/argerr/17.c delete mode 100644 mps/test/argerr/18.c delete mode 100644 mps/test/argerr/19.c delete mode 100644 mps/test/argerr/2.c delete mode 100644 mps/test/argerr/20.c delete mode 100644 mps/test/argerr/21.c delete mode 100644 mps/test/argerr/22.c delete mode 100644 mps/test/argerr/23.c delete mode 100644 mps/test/argerr/24.c delete mode 100644 mps/test/argerr/25.c delete mode 100644 mps/test/argerr/26.c delete mode 100644 mps/test/argerr/27.c delete mode 100644 mps/test/argerr/28.c delete mode 100644 mps/test/argerr/29.c delete mode 100644 mps/test/argerr/3.c delete mode 100644 mps/test/argerr/30.c delete mode 100644 mps/test/argerr/31.c delete mode 100644 mps/test/argerr/32.c delete mode 100644 mps/test/argerr/33.c delete mode 100644 mps/test/argerr/34.c delete mode 100644 mps/test/argerr/35.c delete mode 100644 mps/test/argerr/36.c delete mode 100644 mps/test/argerr/37.c delete mode 100644 mps/test/argerr/38.c delete mode 100644 mps/test/argerr/39.c delete mode 100644 mps/test/argerr/4.c delete mode 100644 mps/test/argerr/40.c delete mode 100644 mps/test/argerr/41.c delete mode 100644 mps/test/argerr/42.c delete mode 100644 mps/test/argerr/43.c delete mode 100644 mps/test/argerr/44.c delete mode 100644 mps/test/argerr/45.c delete mode 100644 mps/test/argerr/46.c delete mode 100644 mps/test/argerr/47.c delete mode 100644 mps/test/argerr/48.c delete mode 100644 mps/test/argerr/49.c delete mode 100644 mps/test/argerr/5.c delete mode 100644 mps/test/argerr/50.c delete mode 100644 mps/test/argerr/51.c delete mode 100644 mps/test/argerr/52.c delete mode 100644 mps/test/argerr/53.c delete mode 100644 mps/test/argerr/54.c delete mode 100644 mps/test/argerr/55.c delete mode 100644 mps/test/argerr/56.c delete mode 100644 mps/test/argerr/57.c delete mode 100644 mps/test/argerr/58.c delete mode 100644 mps/test/argerr/59.c delete mode 100644 mps/test/argerr/6.c delete mode 100644 mps/test/argerr/60.c delete mode 100644 mps/test/argerr/61.c delete mode 100644 mps/test/argerr/62.c delete mode 100644 mps/test/argerr/63.c delete mode 100644 mps/test/argerr/64.c delete mode 100644 mps/test/argerr/65.c delete mode 100644 mps/test/argerr/66.c delete mode 100644 mps/test/argerr/67.c delete mode 100644 mps/test/argerr/68.c delete mode 100644 mps/test/argerr/69.c delete mode 100644 mps/test/argerr/7.c delete mode 100644 mps/test/argerr/70.c delete mode 100644 mps/test/argerr/71.c delete mode 100644 mps/test/argerr/72.c delete mode 100644 mps/test/argerr/73.c delete mode 100644 mps/test/argerr/74.c delete mode 100644 mps/test/argerr/75.c delete mode 100644 mps/test/argerr/76.c delete mode 100644 mps/test/argerr/77.c delete mode 100644 mps/test/argerr/78.c delete mode 100644 mps/test/argerr/79.c delete mode 100644 mps/test/argerr/8.c delete mode 100644 mps/test/argerr/80.c delete mode 100644 mps/test/argerr/81.c delete mode 100644 mps/test/argerr/82.c delete mode 100644 mps/test/argerr/83.c delete mode 100644 mps/test/argerr/84.c delete mode 100644 mps/test/argerr/85.c delete mode 100644 mps/test/argerr/86.c delete mode 100644 mps/test/argerr/87.c delete mode 100644 mps/test/argerr/88.c delete mode 100644 mps/test/argerr/89.c delete mode 100644 mps/test/argerr/9.c delete mode 100644 mps/test/argerr/90.c delete mode 100644 mps/test/argerr/91.c delete mode 100644 mps/test/argerr/92.c delete mode 100644 mps/test/argerr/93.c delete mode 100644 mps/test/argerr/94.c delete mode 100644 mps/test/argerr/95.c delete mode 100644 mps/test/argerr/96.c delete mode 100644 mps/test/argerr/97.c delete mode 100644 mps/test/argerr/98.c delete mode 100644 mps/test/argerr/99.c delete mode 100644 mps/test/conerr/0.c delete mode 100644 mps/test/conerr/1.c delete mode 100644 mps/test/conerr/10.c delete mode 100644 mps/test/conerr/11.c delete mode 100644 mps/test/conerr/12.c delete mode 100644 mps/test/conerr/13.c delete mode 100644 mps/test/conerr/14.c delete mode 100644 mps/test/conerr/15.c delete mode 100644 mps/test/conerr/16.c delete mode 100644 mps/test/conerr/17.c delete mode 100644 mps/test/conerr/18.c delete mode 100644 mps/test/conerr/19.c delete mode 100644 mps/test/conerr/2.c delete mode 100644 mps/test/conerr/20.c delete mode 100644 mps/test/conerr/21.c delete mode 100644 mps/test/conerr/22.c delete mode 100644 mps/test/conerr/23.c delete mode 100644 mps/test/conerr/24.c delete mode 100644 mps/test/conerr/25.c delete mode 100644 mps/test/conerr/26.c delete mode 100644 mps/test/conerr/27.c delete mode 100644 mps/test/conerr/28.c delete mode 100644 mps/test/conerr/29.c delete mode 100644 mps/test/conerr/3.c delete mode 100644 mps/test/conerr/30.c delete mode 100644 mps/test/conerr/31.c delete mode 100644 mps/test/conerr/32.c delete mode 100644 mps/test/conerr/33.c delete mode 100644 mps/test/conerr/33a.c delete mode 100644 mps/test/conerr/34.c delete mode 100644 mps/test/conerr/35.c delete mode 100644 mps/test/conerr/36.c delete mode 100644 mps/test/conerr/37.c delete mode 100644 mps/test/conerr/37f.c delete mode 100644 mps/test/conerr/38.c delete mode 100644 mps/test/conerr/38f.c delete mode 100644 mps/test/conerr/39.c delete mode 100644 mps/test/conerr/39f.c delete mode 100644 mps/test/conerr/4.c delete mode 100644 mps/test/conerr/40.c delete mode 100644 mps/test/conerr/40f.c delete mode 100644 mps/test/conerr/41.c delete mode 100644 mps/test/conerr/42.c delete mode 100644 mps/test/conerr/43.c delete mode 100644 mps/test/conerr/44.c delete mode 100644 mps/test/conerr/44a.c delete mode 100644 mps/test/conerr/45.c delete mode 100644 mps/test/conerr/46.c delete mode 100644 mps/test/conerr/47.c delete mode 100644 mps/test/conerr/48.c delete mode 100644 mps/test/conerr/49.c delete mode 100644 mps/test/conerr/5.c delete mode 100644 mps/test/conerr/50.c delete mode 100644 mps/test/conerr/51.c delete mode 100644 mps/test/conerr/52.c delete mode 100644 mps/test/conerr/53.c delete mode 100644 mps/test/conerr/54.c delete mode 100644 mps/test/conerr/55.c delete mode 100644 mps/test/conerr/56.c delete mode 100644 mps/test/conerr/57.c delete mode 100644 mps/test/conerr/58.c delete mode 100644 mps/test/conerr/59.c delete mode 100644 mps/test/conerr/6.c delete mode 100644 mps/test/conerr/7.c delete mode 100644 mps/test/conerr/8.c delete mode 100644 mps/test/conerr/9.c delete mode 100644 mps/test/function/0.c delete mode 100644 mps/test/function/1.c delete mode 100644 mps/test/function/10.c delete mode 100644 mps/test/function/100.c delete mode 100644 mps/test/function/101.c delete mode 100644 mps/test/function/103.c delete mode 100644 mps/test/function/104.c delete mode 100644 mps/test/function/105.c delete mode 100644 mps/test/function/106.c delete mode 100644 mps/test/function/107.c delete mode 100644 mps/test/function/108.c delete mode 100644 mps/test/function/109.c delete mode 100644 mps/test/function/11.c delete mode 100644 mps/test/function/110.c delete mode 100644 mps/test/function/111.c delete mode 100644 mps/test/function/112.c delete mode 100644 mps/test/function/113.c delete mode 100644 mps/test/function/114.c delete mode 100644 mps/test/function/116.c delete mode 100644 mps/test/function/117.c delete mode 100644 mps/test/function/118.c delete mode 100644 mps/test/function/119.c delete mode 100644 mps/test/function/12.c delete mode 100644 mps/test/function/120.c delete mode 100644 mps/test/function/121.c delete mode 100644 mps/test/function/122.c delete mode 100644 mps/test/function/123.c delete mode 100644 mps/test/function/124.c delete mode 100644 mps/test/function/125.c delete mode 100644 mps/test/function/126.c delete mode 100644 mps/test/function/127.c delete mode 100644 mps/test/function/128.c delete mode 100644 mps/test/function/129.c delete mode 100644 mps/test/function/12p.c delete mode 100644 mps/test/function/13.c delete mode 100644 mps/test/function/130.c delete mode 100644 mps/test/function/131.c delete mode 100644 mps/test/function/132.c delete mode 100644 mps/test/function/133.c delete mode 100644 mps/test/function/134.c delete mode 100644 mps/test/function/135.c delete mode 100644 mps/test/function/136.c delete mode 100644 mps/test/function/137.c delete mode 100644 mps/test/function/138.c delete mode 100644 mps/test/function/139.c delete mode 100644 mps/test/function/14.c delete mode 100644 mps/test/function/140.c delete mode 100644 mps/test/function/144.c delete mode 100644 mps/test/function/147.c delete mode 100644 mps/test/function/148.c delete mode 100644 mps/test/function/149.c delete mode 100644 mps/test/function/15.c delete mode 100644 mps/test/function/150.c delete mode 100644 mps/test/function/151.c delete mode 100644 mps/test/function/152.c delete mode 100644 mps/test/function/153.c delete mode 100644 mps/test/function/158.c delete mode 100644 mps/test/function/159.c delete mode 100644 mps/test/function/16.c delete mode 100644 mps/test/function/160.c delete mode 100644 mps/test/function/161.c delete mode 100644 mps/test/function/162.c delete mode 100644 mps/test/function/163.c delete mode 100644 mps/test/function/164.c delete mode 100644 mps/test/function/165.c delete mode 100644 mps/test/function/167.c delete mode 100644 mps/test/function/17.c delete mode 100644 mps/test/function/170.c delete mode 100644 mps/test/function/171.c delete mode 100644 mps/test/function/18.c delete mode 100644 mps/test/function/19.c delete mode 100644 mps/test/function/2.c delete mode 100644 mps/test/function/20.c delete mode 100644 mps/test/function/200.c delete mode 100644 mps/test/function/203.c delete mode 100644 mps/test/function/204.c delete mode 100644 mps/test/function/205.c delete mode 100644 mps/test/function/206.c delete mode 100644 mps/test/function/207.c delete mode 100644 mps/test/function/21.c delete mode 100644 mps/test/function/214.c delete mode 100644 mps/test/function/215.c delete mode 100644 mps/test/function/22.c delete mode 100644 mps/test/function/223.c delete mode 100644 mps/test/function/224.c delete mode 100644 mps/test/function/226.c delete mode 100644 mps/test/function/227.c delete mode 100644 mps/test/function/23.c delete mode 100644 mps/test/function/24.c delete mode 100644 mps/test/function/25.c delete mode 100644 mps/test/function/26.c delete mode 100644 mps/test/function/27.c delete mode 100644 mps/test/function/28.c delete mode 100644 mps/test/function/29.c delete mode 100644 mps/test/function/3.c delete mode 100644 mps/test/function/30.c delete mode 100644 mps/test/function/31.c delete mode 100644 mps/test/function/32.c delete mode 100644 mps/test/function/33.c delete mode 100644 mps/test/function/34.c delete mode 100644 mps/test/function/35.c delete mode 100644 mps/test/function/36.c delete mode 100644 mps/test/function/37.c delete mode 100644 mps/test/function/38.c delete mode 100644 mps/test/function/39.c delete mode 100644 mps/test/function/4.c delete mode 100644 mps/test/function/40.c delete mode 100644 mps/test/function/41.c delete mode 100644 mps/test/function/42.c delete mode 100644 mps/test/function/43.c delete mode 100644 mps/test/function/44.c delete mode 100644 mps/test/function/45.c delete mode 100644 mps/test/function/46.c delete mode 100644 mps/test/function/47.c delete mode 100644 mps/test/function/48.c delete mode 100644 mps/test/function/49.c delete mode 100644 mps/test/function/5.c delete mode 100644 mps/test/function/50.c delete mode 100644 mps/test/function/500.txt delete mode 100644 mps/test/function/501.txt delete mode 100644 mps/test/function/502.txt delete mode 100644 mps/test/function/503.txt delete mode 100644 mps/test/function/504.txt delete mode 100644 mps/test/function/51.c delete mode 100644 mps/test/function/52.c delete mode 100644 mps/test/function/53.c delete mode 100644 mps/test/function/54.c delete mode 100644 mps/test/function/55.c delete mode 100644 mps/test/function/56.c delete mode 100644 mps/test/function/57.c delete mode 100644 mps/test/function/6.c delete mode 100644 mps/test/function/60.c delete mode 100644 mps/test/function/61.c delete mode 100644 mps/test/function/62.c delete mode 100644 mps/test/function/63.c delete mode 100644 mps/test/function/64.c delete mode 100644 mps/test/function/65.c delete mode 100644 mps/test/function/66.c delete mode 100644 mps/test/function/67.c delete mode 100644 mps/test/function/68.c delete mode 100644 mps/test/function/69.c delete mode 100644 mps/test/function/7.c delete mode 100644 mps/test/function/70.c delete mode 100644 mps/test/function/71.c delete mode 100644 mps/test/function/72.c delete mode 100644 mps/test/function/73.c delete mode 100644 mps/test/function/74.c delete mode 100644 mps/test/function/75.c delete mode 100644 mps/test/function/76.c delete mode 100644 mps/test/function/77.c delete mode 100644 mps/test/function/78.c delete mode 100644 mps/test/function/79.c delete mode 100644 mps/test/function/8.c delete mode 100644 mps/test/function/80.c delete mode 100644 mps/test/function/81.c delete mode 100644 mps/test/function/83.c delete mode 100644 mps/test/function/9.c delete mode 100644 mps/test/function/96.c delete mode 100644 mps/test/function/97.c delete mode 100644 mps/test/function/98.c delete mode 100644 mps/test/function/99.c delete mode 100644 mps/test/misc/0.c delete mode 100644 mps/test/misc/1.c delete mode 100644 mps/test/misc/2.c delete mode 100644 mps/test/test/README delete mode 100644 mps/test/test/qa delete mode 100644 mps/test/test/script/clib delete mode 100644 mps/test/test/script/commands/clib delete mode 100644 mps/test/test/script/commands/help delete mode 100644 mps/test/test/script/commands/index delete mode 100644 mps/test/test/script/commands/options delete mode 100644 mps/test/test/script/commands/run delete mode 100644 mps/test/test/script/commands/runset delete mode 100644 mps/test/test/script/commands/try delete mode 100644 mps/test/test/script/compile delete mode 100644 mps/test/test/script/dirs delete mode 100644 mps/test/test/script/display delete mode 100644 mps/test/test/script/headconv delete mode 100644 mps/test/test/script/headread delete mode 100644 mps/test/test/script/help/clib delete mode 100644 mps/test/test/script/help/index delete mode 100644 mps/test/test/script/help/install delete mode 100644 mps/test/test/script/help/naming delete mode 100644 mps/test/test/script/help/options delete mode 100644 mps/test/test/script/help/output delete mode 100644 mps/test/test/script/help/problems delete mode 100644 mps/test/test/script/help/run delete mode 100644 mps/test/test/script/help/runset delete mode 100644 mps/test/test/script/init delete mode 100644 mps/test/test/script/logging delete mode 100644 mps/test/test/script/ntx86bin/blat.exe delete mode 100644 mps/test/test/script/ntx86bin/cat.exe delete mode 100644 mps/test/test/script/ntx86bin/cygwin.dll delete mode 100644 mps/test/test/script/ntx86bin/gwinsock.dll delete mode 100644 mps/test/test/script/ntx86bin/strings.exe delete mode 100644 mps/test/test/script/ntx86bin/tee.exe delete mode 100644 mps/test/test/script/options delete mode 100644 mps/test/test/script/optproc delete mode 100644 mps/test/test/script/platform delete mode 100644 mps/test/test/script/require delete mode 100644 mps/test/test/script/runtest delete mode 100644 mps/test/test/script/useful delete mode 100644 mps/test/test/script/version delete mode 100644 mps/test/test/testlib/arg.h delete mode 100644 mps/test/test/testlib/assumed delete mode 100644 mps/test/test/testlib/awlfmt.c delete mode 100644 mps/test/test/testlib/awlfmt.h delete mode 100644 mps/test/test/testlib/exfmt.c delete mode 100644 mps/test/test/testlib/exfmt.h delete mode 100644 mps/test/test/testlib/fastfmt.c delete mode 100644 mps/test/test/testlib/fastfmt.h delete mode 100644 mps/test/test/testlib/lofmt.c delete mode 100644 mps/test/test/testlib/lofmt.h delete mode 100644 mps/test/test/testlib/manifest delete mode 100644 mps/test/test/testlib/myfmt.c delete mode 100644 mps/test/test/testlib/myfmt.h delete mode 100644 mps/test/test/testlib/newfmt.c delete mode 100644 mps/test/test/testlib/newfmt.h delete mode 100644 mps/test/test/testlib/platform.c delete mode 100644 mps/test/test/testlib/platform.h delete mode 100644 mps/test/test/testlib/postBQ.h delete mode 100644 mps/test/test/testlib/postGR.h delete mode 100644 mps/test/test/testlib/postHU.h delete mode 100644 mps/test/test/testlib/postMO.h delete mode 100644 mps/test/test/testlib/preBQ.h delete mode 100644 mps/test/test/testlib/preGR.h delete mode 100644 mps/test/test/testlib/preHU.h delete mode 100644 mps/test/test/testlib/preMO.h delete mode 100644 mps/test/test/testlib/rankfmt.c delete mode 100644 mps/test/test/testlib/rankfmt.h delete mode 100644 mps/test/test/testlib/testlib.c delete mode 100644 mps/test/test/testlib/testlib.h delete mode 100644 mps/test/test/testlib/versind.h delete mode 100644 mps/test/testsets/daily delete mode 100644 mps/test/testsets/dailydw delete mode 100644 mps/test/testsets/dylan1 delete mode 100644 mps/tool/autoconf/build-aux/config.guess delete mode 100644 mps/tool/autoconf/build-aux/config.sub delete mode 100644 mps/tool/autoconf/build-aux/install-sh delete mode 100644 mps/tool/index.html delete mode 100755 mps/tool/mpsclasses.py delete mode 100755 mps/tool/test-runner.py diff --git a/mps/INSTALL b/mps/INSTALL deleted file mode 120000 index e989720e22b..00000000000 --- a/mps/INSTALL +++ /dev/null @@ -1 +0,0 @@ -manual/build.txt \ No newline at end of file diff --git a/mps/Makefile.in b/mps/Makefile.in deleted file mode 100644 index 6152cf4d11c..00000000000 --- a/mps/Makefile.in +++ /dev/null @@ -1,69 +0,0 @@ -# Makefile.in -- source for autoconf Makefile -# -# $Id$ -# Copyright (C) 2012 Ravenbrook Limited. See end of file for license. -# -# YOU DON'T NEED AUTOCONF TO BUILD THE MPS -# This is just here for people who want or expect a configure script. -# See [Building the Memory Pool System](manual/build.txt) for how best -# to build and integrate the MPS. -# - -INSTALL=@INSTALL@ -INSTALL_DATA=@INSTALL_DATA@ -INSTALL_PROGRAM=@INSTALL_PROGRAM@ -MAKE=@MAKE@ -MPS_TARGET_NAME=@MPS_TARGET_NAME@ -prefix=$(DESTDIR)@prefix@ - -all: @BUILD_TARGET@ - -build-via-make: - $(MAKE) -C code -f $(MPS_TARGET_NAME).gmk - -clean-make-build: - $(MAKE) -C code -f $(MPS_TARGET_NAME).gmk clean - -install-make-build: make-install-dirs build-via-make - $(INSTALL_DATA) code/mps*.h $(prefix)/include/ - $(INSTALL_DATA) code/$(MPS_TARGET_NAME)/cool/mps.a $(prefix)/lib/libmps-debug.a - $(INSTALL_DATA) code/$(MPS_TARGET_NAME)/hot/mps.a $(prefix)/lib/libmps.a - $(INSTALL_PROGRAM) code/$(MPS_TARGET_NAME)/hot/eventcnv $(prefix)/bin/mpseventcnv - -build-via-xcode: - xcodebuild -project code/mps.xcodeproj -config Release - xcodebuild -project code/mps.xcodeproj -config Debug - -clean-xcode-build: - xcodebuild -project code/mps.xcodeproj -config Release clean - xcodebuild -project code/mps.xcodeproj -config Debug clean - -install-xcode-build: make-install-dirs build-via-xcode - $(INSTALL_DATA) code/mps*.h $(prefix)/include/ - $(INSTALL_DATA) code/build/Debug/libmps.a $(prefix)/lib/libmps-debug.a - $(INSTALL_DATA) code/build/Release/libmps.a $(prefix)/lib/libmps.a - $(INSTALL_PROGRAM) code/build/Release/eventcnv $(prefix)/bin/mpseventcnv - -Makefile: Makefile.in config.status - ./config.status Makefile - -clean: @CLEAN_TARGET@ - -config.status: configure - -configure: configure.ac - autoreconf -vif - -distclean: clean - rm -rf autom4te.cache/ config.log config.status Makefile - -make-install-dirs: - mkdir -p $(prefix)/bin - mkdir -p $(prefix)/lib - mkdir -p $(prefix)/include - -install: @INSTALL_TARGET@ - -test: @BUILD_TARGET@ - $(MAKE) -C code VARIETY=cool testrun - $(MAKE) -C code VARIETY=hot testrun diff --git a/mps/README b/mps/README deleted file mode 120000 index 0d79d56d9fb..00000000000 --- a/mps/README +++ /dev/null @@ -1 +0,0 @@ -readme.txt \ No newline at end of file diff --git a/mps/code/.gdbinit b/mps/code/.gdbinit deleted file mode 100644 index cbdac5f7cce..00000000000 --- a/mps/code/.gdbinit +++ /dev/null @@ -1 +0,0 @@ -handle SIGBUS nostop diff --git a/mps/code/.p4ignore b/mps/code/.p4ignore deleted file mode 100644 index a41c0513277..00000000000 --- a/mps/code/.p4ignore +++ /dev/null @@ -1,45 +0,0 @@ -# code/.p4ignore -- Perforce files to ignore list -# $Id$ -# Make output -xci3gc -w3i3mv -w3i6mv -lii6gc -lii3gc -fri3gc -fri6gc -# Visual Studio junk -Debug -Release -*.filters -*.user -*.suo -# Telemetry event logs -mpsio.log -mpsio*.log -mpsio.log.txt -# Build products -*.o -*.obj -*.a -*.so -*.lib -*.exe -# Xcode junk -xc -mps.xcodeproj/xcuserdata -mps.xcodeproj/project.xcworkspace -tags -# Temporary files -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -# Mac OS X Finder turds -.DS_Store diff --git a/mps/code/abq.c b/mps/code/abq.c deleted file mode 100644 index e29a9786599..00000000000 --- a/mps/code/abq.c +++ /dev/null @@ -1,353 +0,0 @@ -/* abq.c: AVAILABLE BLOCK QUEUE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: Any MPS developer - * - * .purpose: A FIFO queue substrate for - * - * .design: See - */ - -#include "meter.h" -#include "abq.h" -#include "cbs.h" -#include "mpm.h" - -SRCID(abq, "$Id$"); - - -/* Private prototypes */ - -static Size ABQQueueSize(Count elements); -static Index ABQNextIndex(ABQ abq, Index index); - - -/* Methods */ - -/* ABQInit -- Initialize an ABQ - * - * items is the number of items the queue can hold - */ -Res ABQInit(Arena arena, ABQ abq, void *owner, Count items) -{ - Count elements; - void *p; - Res res; - - AVERT(Arena, arena); - AVER(abq != NULL); - AVER(items > 0); - - elements = items + 1; - - res = ControlAlloc(&p, arena, ABQQueueSize(elements), - /* withReservoirPermit */ FALSE); - if (res != ResOK) - return res; - - abq->elements = elements; - abq->in = 0; - abq->out = 0; - abq->queue = (CBSBlock *)p; - - METER_INIT(abq->push, "push", owner); - METER_INIT(abq->pop, "pop", owner); - METER_INIT(abq->peek, "peek", owner); - METER_INIT(abq->delete, "delete", owner); - - abq->sig = ABQSig; - - AVERT(ABQ, abq); - return ResOK; -} - - -/* ABQCheck -- validate an ABQ */ -Bool ABQCheck(ABQ abq) -{ - Index index; - - CHECKS(ABQ, abq); - CHECKL(abq->elements > 0); - CHECKL(abq->in < abq->elements); - CHECKL(abq->out < abq->elements); - CHECKL(abq->queue != NULL); - /* Is this really a local check? */ - for (index = abq->out; index != abq->in; ) { - CHECKL(CBSBlockCheck(abq->queue[index])); - if (++index == abq->elements) - index = 0; - } - - return TRUE; -} - - -/* ABQFinish -- finish an ABQ */ -void ABQFinish(Arena arena, ABQ abq) -{ - AVERT(Arena, arena); - AVERT(ABQ, abq); - - METER_EMIT(&abq->push); - METER_EMIT(&abq->pop); - METER_EMIT(&abq->peek); - METER_EMIT(&abq->delete); - ControlFree(arena, abq->queue, ABQQueueSize(abq->elements)); - - abq->elements = 0; - abq->queue = NULL; - - abq->sig = SigInvalid; -} - - -/* ABQPush -- push a block onto the tail of the ABQ */ -Res ABQPush(ABQ abq, CBSBlock block) -{ - AVERT(ABQ, abq); - AVERT(CBSBlock, block); - - METER_ACC(abq->push, ABQDepth(abq)); - - if (ABQIsFull(abq)) - return ResFAIL; - - abq->queue[abq->in] = block; - abq->in = ABQNextIndex(abq, abq->in); - - AVERT(ABQ, abq); - return ResOK; -} - - -/* ABQPop -- pop a block from the head of the ABQ */ -Res ABQPop(ABQ abq, CBSBlock *blockReturn) -{ - AVER(blockReturn != NULL); - AVERT(ABQ, abq); - - METER_ACC(abq->pop, ABQDepth(abq)); - - if (ABQIsEmpty(abq)) - return ResFAIL; - - *blockReturn = abq->queue[abq->out]; - AVERT(CBSBlock, *blockReturn); - - abq->out = ABQNextIndex(abq, abq->out); - - AVERT(ABQ, abq); - return ResOK; -} - - -/* ABQPeek -- peek at the head of the ABQ */ -Res ABQPeek(ABQ abq, CBSBlock *blockReturn) -{ - AVER(blockReturn != NULL); - AVERT(ABQ, abq); - - METER_ACC(abq->peek, ABQDepth(abq)); - - if (ABQIsEmpty(abq)) - return ResFAIL; - - *blockReturn = abq->queue[abq->out]; - AVERT(CBSBlock, *blockReturn); - - /* Identical to pop, but don't increment out */ - - AVERT(ABQ, abq); - return ResOK; -} - - -/* ABQDelete -- delete a block from the ABQ */ -Res ABQDelete(ABQ abq, CBSBlock block) -{ - Index index, next, in; - CBSBlock *queue; - - AVERT(ABQ, abq); - AVERT(CBSBlock, block); - - METER_ACC(abq->delete, ABQDepth(abq)); - - index = abq->out; - in = abq->in; - queue = abq->queue; - - while (index != in) { - if (queue[index] == block) { - goto found; - } - index = ABQNextIndex(abq, index); - } - - return ResFAIL; - -found: - /* index points to the node to be removed */ - next = ABQNextIndex(abq, index); - while (next != in) { - queue[index] = queue[next]; - index = next; - next = ABQNextIndex(abq, index); - } - abq->in = index; - AVERT(ABQ, abq); - return ResOK; -} - - -/* ABQDescribe -- Describe an ABQ */ -Res ABQDescribe(ABQ abq, mps_lib_FILE *stream) -{ - Res res; - Index index; - - AVERT(ABQ, abq); - - AVER(stream != NULL); - - res = WriteF(stream, - "ABQ $P\n{\n", (WriteFP)abq, - " elements: $U \n", (WriteFU)abq->elements, - " in: $U \n", (WriteFU)abq->in, - " out: $U \n", (WriteFU)abq->out, - " queue: \n", - NULL); - if(res != ResOK) - return res; - - for (index = abq->out; index != abq->in; ) { - res = CBSBlockDescribe(abq->queue[index], stream); - if(res != ResOK) - return res; - if (++index == abq->elements) - index = 0; - } - - res = WriteF(stream, "\n", NULL); - if(res != ResOK) - return res; - - res = METER_WRITE(abq->push, stream); - if(res != ResOK) - return res; - res = METER_WRITE(abq->pop, stream); - if(res != ResOK) - return res; - res = METER_WRITE(abq->peek, stream); - if(res != ResOK) - return res; - res = METER_WRITE(abq->delete, stream); - if(res != ResOK) - return res; - - res = WriteF(stream, "}\n", NULL); - if(res != ResOK) - return res; - - return ResOK; -} - - -/* ABQIsEmpty -- Is an ABQ empty? */ -Bool ABQIsEmpty(ABQ abq) -{ - AVERT(ABQ, abq); - - return abq->out == abq->in; -} - - -/* ABQIsFull -- Is an ABQ full? */ -Bool ABQIsFull(ABQ abq) -{ - AVERT(ABQ, abq); - - return ABQNextIndex(abq, abq->in) == abq->out; -} - - -/* ABQDepth -- return the number of items in an ABQ */ -Count ABQDepth(ABQ abq) -{ - Index out, in; - - AVERT(ABQ, abq); - out = abq->out; - in = abq->in; - - if (in >= out) - return in - out; - else - return in + abq->elements - out; -} - - -/* ABQQueueSize -- calculate the storage required for the vector to - store elements items */ -static Size ABQQueueSize(Count elements) -{ - /* strange but true: the sizeof expression calculates the size of a - single queue element */ - return (Size)(sizeof(((ABQ)NULL)->queue[0]) * elements); -} - - -/* ABQNextIndex -- calculate the next index into the queue vector from - the current one */ -static Index ABQNextIndex(ABQ abq, Index index) -{ - Index next = index + 1; - if (next == abq->elements) - next = 0; - return next; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/abq.h b/mps/code/abq.h deleted file mode 100644 index e39635dfcaa..00000000000 --- a/mps/code/abq.h +++ /dev/null @@ -1,100 +0,0 @@ -/* abq.h: ABQ INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: A FIFO queue substrate for - * - * .source: - */ - -#ifndef abq_h -#define abq_h - -#include "meter.h" -#include "cbs.h" -#include "mpm.h" - - -/* Signatures */ - -#define ABQSig ((Sig)0x519AB099) /* SIGnature ABQ */ - - -/* Prototypes */ - -typedef struct ABQStruct *ABQ; -extern Res ABQInit(Arena arena, ABQ abq, void *owner, Count items); -extern Bool ABQCheck(ABQ abq); -extern void ABQFinish(Arena arena, ABQ abq); -extern Res ABQPush(ABQ abq, CBSBlock block); -extern Res ABQPop(ABQ abq, CBSBlock *blockReturn); -extern Res ABQPeek(ABQ abq, CBSBlock *blockReturn); -extern Res ABQDelete(ABQ abq, CBSBlock block); -extern Res ABQDescribe(ABQ abq, mps_lib_FILE *stream); -extern Bool ABQIsEmpty(ABQ abq); -extern Bool ABQIsFull(ABQ abq); -extern Count ABQDepth(ABQ abq); - - -/* Types */ - -typedef struct ABQStruct -{ - Count elements; - Index in; - Index out; - CBSBlock *queue; - - /* Meter queue depth at each operation */ - METER_DECL(push); - METER_DECL(pop); - METER_DECL(peek); - METER_DECL(delete); - - Sig sig; -} ABQStruct; - -#endif /* abq_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/abqtest.c b/mps/code/abqtest.c deleted file mode 100644 index 27288a40437..00000000000 --- a/mps/code/abqtest.c +++ /dev/null @@ -1,219 +0,0 @@ -/* abqtest.c: AVAILABLE BLOCK QUEUE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "abq.h" -#include "cbs.h" -#include "mpm.h" -#include "mps.h" -#include "mpsavm.h" -#include "testlib.h" -#include -#include -#include "mpstd.h" -#ifdef MPS_OS_IA -struct itimerspec; /* stop complaints from time.h */ -#endif -#include -#include - - -SRCID(abqtest, "$Id$"); - - -static ABQStruct abq; /* the ABQ which we will use */ -static Size abqSize; /* the size of the current ABQ */ - -#define ABQ_SIZE 10 -#define TEST_ITER 10000 - - -static unsigned long abqRnd(unsigned long n) -{ - return rnd()%n; -} - - -static unsigned pushee = 1; -static unsigned popee = 1; -static unsigned deleted = 0; - - -typedef struct TestStruct *Test; - -typedef struct TestStruct -{ - Test next; - unsigned id; - CBSBlockStruct cbsBlockStruct; -} TestStruct; - - -static CBSBlock TestCBSBlock(Test t) -{ - return &t->cbsBlockStruct; -} - -static Test CBSBlockTest(CBSBlock c) -{ - return PARENT(TestStruct, cbsBlockStruct, c); -} - - -static Test testBlocks = NULL; - - -static CBSBlock CreateCBSBlock(unsigned no) -{ - Test b = malloc(sizeof(TestStruct)); - cdie(b != NULL, "malloc"); - - b->next = testBlocks; - b->id = no; - b->cbsBlockStruct.base = 0; - b->cbsBlockStruct.limit = 0; - - testBlocks = b; - - return TestCBSBlock(b); -} - - -static void DestroyCBSBlock(CBSBlock c) -{ - Test b = CBSBlockTest(c); - - if (b == testBlocks) - testBlocks = b->next; - else { - Test prev; - - for (prev = testBlocks; prev != 0; prev = prev->next) - if (prev->next == b) { - prev->next = b->next; - break; - } - } - - free(b); -} - - -static void step(void) -{ - Res res; - CBSBlock a; - - switch (abqRnd(9)) { - case 0: case 1: case 2: case 3: - push: - res = ABQPush(&abq, CreateCBSBlock(pushee)); - if (res != ResOK) { - goto pop; - } - pushee++; - break; - case 5: case 6: case 7: case 8: - pop: - res = ABQPop(&abq, &a); - if (res != ResOK){ - goto push; - } - if (popee == deleted) { - popee++; - deleted = 0; - } - cdie(CBSBlockTest(a)->id == popee, "pop"); - popee++; - DestroyCBSBlock(a); - break; - default: - if (!deleted & (pushee > popee)) { - Test b; - - deleted = (unsigned)abqRnd (pushee - popee) + popee; - for (b = testBlocks; b != NULL; b = b->next) - if (b->id == deleted) - break; - cdie(b != NULL, "found to delete"); - res = ABQDelete(&abq, TestCBSBlock(b)); - cdie(res == ResOK, "ABQDelete"); - } - } -} - - -#define testArenaSIZE (((size_t)4)<<20) - -extern int main(int argc, char *argv[]) -{ - Res res; - mps_arena_t arena; - int i; - - randomize(argc, argv); - - abqSize = 0; - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "mps_arena_create"); - - res = ABQInit((Arena)arena, &abq, NULL, ABQ_SIZE); - if (res == ResOK) { - abqSize = ABQ_SIZE; - } else { - printf("ABQCreate returned %d\n",res); - return 1; - } - - for (i = 0; i < TEST_ITER; i++) { - step(); - } - - printf("All tests passed.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/amcss.c b/mps/code/amcss.c deleted file mode 100644 index 1be8d62811f..00000000000 --- a/mps/code/amcss.c +++ /dev/null @@ -1,389 +0,0 @@ -/* amcss.c: POOL CLASS AMC STRESS TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - */ - -#include "fmtdy.h" -#include "fmtdytst.h" -#include "testlib.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include "mps.h" -#include -#include - - -/* These values have been tuned in the hope of getting one dynamic collection. */ -#define testArenaSIZE ((size_t)1000*1024) -#define gen1SIZE ((size_t)150) -#define gen2SIZE ((size_t)170) -#define avLEN 3 -#define exactRootsCOUNT 180 -#define ambigRootsCOUNT 50 -#define genCOUNT 2 -#define collectionsCOUNT 37 -#define rampSIZE 9 -#define initTestFREQ 6000 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { gen1SIZE, 0.85 }, { gen2SIZE, 0.45 } }; - - -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) - - -static mps_pool_t pool; -static mps_ap_t ap; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; - - -/* alert -- synchronous alert of collection start/stop */ - -static void alertfn(int alertcode, int whycode) -{ - switch(alertcode) { - case MPS_ALERT_COLLECTION_BEGIN: { - printf("\n^^^^^^ BEGIN (why: %d) ^^^^^^\n", whycode); - break; - } - case MPS_ALERT_COLLECTION_END: { - printf("vvvvvv END (why: %d) vvvvvv\n", whycode); - break; - } - default: { - cdie(0, "unknown alertcode"); - break; - } - } -} - -/* report -- report statistics from any messages */ - -static void report(mps_arena_t arena) -{ - static int nCollsStart = 0; - static int nCollsDone = 0; - mps_message_type_t type; - - while(mps_message_queue_type(&type, arena)) { - mps_message_t message; - - cdie(mps_message_get(&message, arena, type), "message get"); - - if (type == mps_message_type_gc_start()) { - nCollsStart += 1; - printf("\n{\n Collection %d started. Because:\n", nCollsStart); - printf(" %s\n", mps_message_gc_start_why(arena, message)); - printf(" clock: %"PRIuLONGEST"\n", (ulongest_t)mps_message_clock(arena, message)); - - } else if (type == mps_message_type_gc()) { - size_t live, condemned, not_condemned; - - nCollsDone += 1; - live = mps_message_gc_live_size(arena, message); - condemned = mps_message_gc_condemned_size(arena, message); - not_condemned = mps_message_gc_not_condemned_size(arena, message); - - printf("\n Collection %d finished:\n", nCollsDone); - printf(" live %"PRIuLONGEST"\n", (ulongest_t)live); - printf(" condemned %"PRIuLONGEST"\n", (ulongest_t)condemned); - printf(" not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned); - printf(" clock: %"PRIuLONGEST"\n", (ulongest_t)mps_message_clock(arena, message)); - printf("}\n"); - - if(condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024) { - /* When condemned size is larger than could happen in a gen 2 - * collection (discounting ramps, natch), guess that was a dynamic - * collection, and reset the commit limit, so it doesn't run out. */ - die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), - "set limit"); - } - - } else { - cdie(0, "unknown message type"); - break; - } - - mps_message_discard(arena, message); - } - - return; -} - - -/* make -- create one new object */ - -static mps_addr_t make(void) -{ - size_t length = rnd() % (2*avLEN); - size_t size = (length+2) * sizeof(mps_word_t); - mps_addr_t p; - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, p, ap, size); - if (res) - die(res, "MPS_RESERVE_BLOCK"); - res = dylan_init(p, size, exactRoots, exactRootsCOUNT); - if (res) - die(res, "dylan_init"); - } while(!mps_commit(ap, p, size)); - - return p; -} - - -/* test_stepper -- stepping function for walk */ - -static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pol, - void *p, size_t s) -{ - testlib_unused(object); testlib_unused(fmt); testlib_unused(pol); - testlib_unused(s); - (*(unsigned long *)p)++; -} - - -/* test -- the body of the test */ - -static void *test(void *arg, size_t s) -{ - mps_arena_t arena; - mps_fmt_t format; - mps_chain_t chain; - mps_root_t exactRoot, ambigRoot; - unsigned long objs; size_t i; - mps_word_t collections, rampSwitch; - mps_alloc_pattern_t ramp = mps_alloc_pattern_ramp(); - int ramping; - mps_ap_t busy_ap; - mps_addr_t busy_init; - - arena = (mps_arena_t)arg; - (void)s; /* unused */ - - die(dylan_fmt(&format, arena), "fmt_create"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - - die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain), - "pool_create(amc)"); - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2"); - - for(i = 0; i < exactRootsCOUNT; ++i) - exactRoots[i] = objNULL; - for(i = 0; i < ambigRootsCOUNT; ++i) - ambigRoots[i] = rnd_addr(); - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); - - /* create an ap, and leave it busy */ - die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); - - collections = 0; - rampSwitch = rampSIZE; - die(mps_ap_alloc_pattern_begin(ap, ramp), "pattern begin (ap)"); - die(mps_ap_alloc_pattern_begin(busy_ap, ramp), "pattern begin (busy_ap)"); - ramping = 1; - objs = 0; - while (collections < collectionsCOUNT) { - mps_word_t c; - size_t r; - - c = mps_collections(arena); - if (collections != c) { - collections = c; - report(arena); - - printf("%lu objects (mps_collections says: %lu)\n", objs, c); - - /* test mps_arena_has_addr */ - { - size_t hitRatio; - unsigned hitsWanted = 4; /* aim for 4 hits (on average) */ - /* [Note: The for-loop condition used to be "i < 4 * hitRatio", - * with "4" an unexplained naked constant. I have now labelled - * it "hitsWanted", as I think that is the intent. RHSK] - */ - - /* how many random addrs must we try, to hit the arena once? */ - hitRatio = (0xfffffffful / mps_arena_committed(arena)); - for (i = 0; i < hitsWanted * hitRatio ; i++) { - /* An exact root maybe in the arena, so add a random 32-bit - * offset to it. We may get no hits if it is objNULL. - */ - mps_addr_t p = (char *)exactRoots[rnd() % exactRootsCOUNT] - + rnd()-0x80000000ul; - if (mps_arena_has_addr(arena, p)) { - printf("%p is in the arena\n", p); - } - } - } - - for (i = 0; i < exactRootsCOUNT; ++i) - cdie(exactRoots[i] == objNULL - || (dylan_check(exactRoots[i]) - && mps_arena_has_addr(arena, exactRoots[i])), - "all roots check"); - cdie(!mps_arena_has_addr(arena, NULL), - "NULL in arena"); - - if (collections == collectionsCOUNT / 2) { - unsigned long object_count = 0; - mps_arena_park(arena); - mps_arena_formatted_objects_walk(arena, test_stepper, &object_count, 0); - mps_arena_release(arena); - printf("stepped on %lu objects.\n", object_count); - } - if (collections == rampSwitch) { - int begin_ramp = !ramping - || /* Every other time, switch back immediately. */ (collections & 1); - - rampSwitch += rampSIZE; - if (ramping) { - die(mps_ap_alloc_pattern_end(ap, ramp), "pattern end (ap)"); - die(mps_ap_alloc_pattern_end(busy_ap, ramp), "pattern end (busy_ap)"); - ramping = 0; - /* kill half of the roots */ - for(i = 0; i < exactRootsCOUNT; i += 2) { - if (exactRoots[i] != objNULL) { - cdie(dylan_check(exactRoots[i]), "ramp kill check"); - exactRoots[i] = objNULL; - } - } - } - if (begin_ramp) { - die(mps_ap_alloc_pattern_begin(ap, ramp), - "pattern rebegin (ap)"); - die(mps_ap_alloc_pattern_begin(busy_ap, ramp), - "pattern rebegin (busy_ap)"); - ramping = 1; - } - } - } - - r = (size_t)rnd(); - if (r & 1) { - i = (r >> 1) % exactRootsCOUNT; - if (exactRoots[i] != objNULL) - cdie(dylan_check(exactRoots[i]), "dying root check"); - exactRoots[i] = make(); - if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL) - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - } else { - i = (r >> 1) % ambigRootsCOUNT; - ambigRoots[(ambigRootsCOUNT-1) - i] = make(); - /* Create random interior pointers */ - ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); - } - - if (r % initTestFREQ == 0) - *(int*)busy_init = -1; /* check that the buffer is still there */ - - if (objs % 1024 == 0) { - report(arena); - putchar('.'); - fflush(stdout); - } - - ++objs; - } - - (void)mps_commit(busy_ap, busy_init, 64); - mps_ap_destroy(busy_ap); - mps_ap_destroy(ap); - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); - mps_pool_destroy(pool); - mps_chain_destroy(chain); - mps_fmt_destroy(format); - - return NULL; -} - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), 2*testArenaSIZE), - "arena_create"); - mps_message_type_enable(arena, mps_message_type_gc()); - mps_message_type_enable(arena, mps_message_type_gc_start()); - mps_alert_collection_set(arena, &alertfn); - die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - report(arena); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/amcsshe.c b/mps/code/amcsshe.c deleted file mode 100644 index 770870cfe8b..00000000000 --- a/mps/code/amcsshe.c +++ /dev/null @@ -1,314 +0,0 @@ -/* amcsshe.c: POOL CLASS AMC STRESS TEST WITH HEADER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - */ - -#include "fmthe.h" -#include "fmtdytst.h" -#include "testlib.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include "mps.h" -#include -#include - - -/* These values have been tuned in the hope of getting one dynamic collection. */ -#define headerFACTOR ((float)(20 + headerSIZE) / 20) -/* headerFACTOR measures how much larger objects are compared to fmtdy. */ -#define testArenaSIZE ((size_t)(1000*headerFACTOR)*1024) -#define gen1SIZE ((size_t)(150*headerFACTOR)) -#define gen2SIZE ((size_t)(170*headerFACTOR)) -#define avLEN 3 -#define exactRootsCOUNT 200 -#define ambigRootsCOUNT 50 -#define bogusRootsCOUNT 4096 -#define collectionsCOUNT 37 -#define rampSIZE 9 -#define initTestFREQ 6000 -#define genCOUNT 2 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { gen1SIZE, 0.85 }, { gen2SIZE, 0.45 } }; - - -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) - - -static mps_pool_t pool; -static mps_ap_t ap; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; -static mps_addr_t bogusRoots[bogusRootsCOUNT]; - -static mps_addr_t make(void) -{ - size_t length = rnd() % (2*avLEN); - size_t size = (length+2) * sizeof(mps_word_t); - mps_addr_t p, userP; - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, p, ap, size + headerSIZE); - if (res) - die(res, "MPS_RESERVE_BLOCK"); - userP = (mps_addr_t)((char*)p + headerSIZE); - res = dylan_init(userP, size, exactRoots, exactRootsCOUNT); - if (res) - die(res, "dylan_init"); - ((int*)p)[0] = realHeader; - ((int*)p)[1] = 0xED0ED; - } while(!mps_commit(ap, p, size + headerSIZE)); - - return userP; -} - - -/* report - report statistics from any terminated GCs */ - -static void report(mps_arena_t arena) -{ - mps_message_t message; - static int nCollections = 0; - - while (mps_message_get(&message, arena, mps_message_type_gc())) { - size_t live, condemned, not_condemned; - - live = mps_message_gc_live_size(arena, message); - condemned = mps_message_gc_condemned_size(arena, message); - not_condemned = mps_message_gc_not_condemned_size(arena, message); - - printf("\nCollection %d finished:\n", ++nCollections); - printf("live %"PRIuLONGEST"\n", (ulongest_t)live); - printf("condemned %"PRIuLONGEST"\n", (ulongest_t)condemned); - printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned); - - mps_message_discard(arena, message); - - if (condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024) - /* When condemned size is larger than could happen in a gen 2 - * collection (discounting ramps, natch), guess that was a dynamic - * collection, and reset the commit limit, so it doesn't run out. */ - die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit"); - } -} - - -/* test -- the body of the test */ - -static void *test(void *arg, size_t s) -{ - mps_arena_t arena; - mps_fmt_t format; - mps_chain_t chain; - mps_root_t exactRoot, ambigRoot, bogusRoot; - unsigned long objs; size_t i; - mps_word_t collections, rampSwitch; - mps_alloc_pattern_t ramp = mps_alloc_pattern_ramp(); - int ramping; - mps_ap_t busy_ap; - mps_addr_t busy_init; - - arena = (mps_arena_t)arg; - (void)s; /* unused */ - - die(EnsureHeaderFormat(&format, arena), "fmt_create"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - - die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain), - "pool_create(amc)"); - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2"); - - for(i = 0; i < exactRootsCOUNT; ++i) - exactRoots[i] = objNULL; - for(i = 0; i < ambigRootsCOUNT; ++i) - ambigRoots[i] = rnd_addr(); - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); - die(mps_root_create_table(&bogusRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &bogusRoots[0], bogusRootsCOUNT), - "root_create_table(bogus)"); - - /* create an ap, and leave it busy */ - die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); - - collections = 0; - rampSwitch = rampSIZE; - die(mps_ap_alloc_pattern_begin(ap, ramp), "pattern begin (ap)"); - die(mps_ap_alloc_pattern_begin(busy_ap, ramp), "pattern begin (busy_ap)"); - ramping = 1; - objs = 0; - while (collections < collectionsCOUNT) { - unsigned long c; - size_t r; - - c = mps_collections(arena); - - if (collections != c) { - collections = c; - printf("\nCollection %lu, %lu objects.\n", c, objs); - report(arena); - for (r = 0; r < exactRootsCOUNT; ++r) { - if (exactRoots[r] != objNULL) - die(HeaderFormatCheck(exactRoots[r]), "wrapper check"); - } - if (collections == rampSwitch) { - int begin_ramp = !ramping - || /* Every other time, switch back immediately. */ (collections & 1); - - rampSwitch += rampSIZE; - if (ramping) { - die(mps_ap_alloc_pattern_end(ap, ramp), "pattern end (ap)"); - die(mps_ap_alloc_pattern_end(busy_ap, ramp), "pattern end (busy_ap)"); - ramping = 0; - /* kill half of the roots */ - for(i = 0; i < exactRootsCOUNT; i += 2) { - if (exactRoots[i] != objNULL) { - die(HeaderFormatCheck(exactRoots[i]), "ramp kill check"); - exactRoots[i] = objNULL; - } - } - } - if (begin_ramp) { - die(mps_ap_alloc_pattern_begin(ap, ramp), - "pattern rebegin (ap)"); - die(mps_ap_alloc_pattern_begin(busy_ap, ramp), - "pattern rebegin (busy_ap)"); - ramping = 1; - } - } - /* fill bogusRoots with variations of a real pointer */ - r = rnd() % exactRootsCOUNT; - if (exactRoots[r] != objNULL) { - char *p = (char*)exactRoots[r]; - - for(i = 0; i < bogusRootsCOUNT; ++i, ++p) - bogusRoots[i] = (mps_addr_t)p; - } - } - - r = (size_t)rnd(); - if (r & 1) { - i = (r >> 1) % exactRootsCOUNT; - if (exactRoots[i] != objNULL) - die(HeaderFormatCheck(exactRoots[i]), "wrapper check"); - exactRoots[i] = make(); - if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL) - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - } else { - i = (r >> 1) % ambigRootsCOUNT; - ambigRoots[(ambigRootsCOUNT-1) - i] = make(); - /* Create random interior pointers */ - ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); - } - - if (r % initTestFREQ == 0) - *(int*)busy_init = -1; /* check that the buffer is still there */ - - if (objs % 1024 == 0) { - report(arena); - putchar('.'); - fflush(stdout); - } - - ++objs; - } - - (void)mps_commit(busy_ap, busy_init, 64); - mps_ap_destroy(busy_ap); - mps_ap_destroy(ap); - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); - mps_root_destroy(bogusRoot); - mps_pool_destroy(pool); - mps_chain_destroy(chain); - mps_fmt_destroy(format); - - return NULL; -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), 3*testArenaSIZE), - "arena_create\n"); - mps_message_type_enable(arena, mps_message_type_gc()); - die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/amcssth.c b/mps/code/amcssth.c deleted file mode 100644 index 81eb0ad9b0d..00000000000 --- a/mps/code/amcssth.c +++ /dev/null @@ -1,382 +0,0 @@ -/* amcssth.c: POOL CLASS AMC STRESS TEST WITH TWO THREADS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * .posix: This is Posix only. - */ - -#define _POSIX_C_SOURCE 199309L - -#include "fmtdy.h" -#include "testlib.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include -#include -#include -#include - - -/* These values have been tuned in the hope of getting one dynamic collection. */ -#define testArenaSIZE ((size_t)1000*1024) -#define gen1SIZE ((size_t)150) -#define gen2SIZE ((size_t)170) -#define avLEN 3 -#define exactRootsCOUNT 180 -#define ambigRootsCOUNT 50 -#define genCOUNT 2 -#define collectionsCOUNT 37 -#define rampSIZE 9 -#define initTestFREQ 6000 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { gen1SIZE, 0.85 }, { gen2SIZE, 0.45 } }; - - -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) - - -static mps_pool_t pool; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; - -mps_arena_t arena; -mps_fmt_t format; -mps_chain_t chain; -mps_root_t exactRoot, ambigRoot; -unsigned long objs = 0; - - -/* report - report statistics from any terminated GCs */ - -static void report(mps_arena_t arena) -{ - mps_message_t message; - static int nCollections = 0; - - while (mps_message_get(&message, arena, mps_message_type_gc())) { - size_t live, condemned, not_condemned; - - live = mps_message_gc_live_size(arena, message); - condemned = mps_message_gc_condemned_size(arena, message); - not_condemned = mps_message_gc_not_condemned_size(arena, message); - - printf("\nCollection %d finished:\n", ++nCollections); - printf("live %"PRIuLONGEST"\n", (ulongest_t)live); - printf("condemned %"PRIuLONGEST"\n", (ulongest_t)condemned); - printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned); - - mps_message_discard(arena, message); - - if (condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024) - /* When condemned size is larger than could happen in a gen 2 - * collection (discounting ramps, natch), guess that was a dynamic - * collection, and reset the commit limit, so it doesn't run out. */ - die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit"); - } -} - - -/* make -- create one new object */ - -static mps_addr_t make(mps_ap_t ap) -{ - size_t length = rnd() % (2*avLEN); - size_t size = (length+2) * sizeof(mps_word_t); - mps_addr_t p; - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, p, ap, size); - if (res) - die(res, "MPS_RESERVE_BLOCK"); - res = dylan_init(p, size, exactRoots, exactRootsCOUNT); - if (res) - die(res, "dylan_init"); - } while(!mps_commit(ap, p, size)); - - return p; -} - - -/* test_stepper -- stepping function for walk */ - -static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pol, - void *p, size_t s) -{ - testlib_unused(object); testlib_unused(fmt); testlib_unused(pol); - testlib_unused(s); - (*(unsigned long *)p)++; -} - - -/* init -- initialize pool and roots */ - -static void init(void) -{ - size_t i; - - die(dylan_fmt(&format, arena), "fmt_create"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - - die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain), - "pool_create(amc)"); - - for(i = 0; i < exactRootsCOUNT; ++i) - exactRoots[i] = objNULL; - for(i = 0; i < ambigRootsCOUNT; ++i) - ambigRoots[i] = rnd_addr(); - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); -} - - -/* finish -- finish pool and roots */ - -static void finish(void) -{ - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); - mps_pool_destroy(pool); - mps_chain_destroy(chain); - mps_fmt_destroy(format); -} - - -/* churn -- create an object and install into roots */ - -static void churn(mps_ap_t ap) -{ - size_t i; - size_t r; - - ++objs; - r = (size_t)rnd(); - if (r & 1) { - i = (r >> 1) % exactRootsCOUNT; - if (exactRoots[i] != objNULL) - cdie(dylan_check(exactRoots[i]), "dying root check"); - exactRoots[i] = make(ap); - if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL) - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - } else { - i = (r >> 1) % ambigRootsCOUNT; - ambigRoots[(ambigRootsCOUNT-1) - i] = make(ap); - /* Create random interior pointers */ - ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); - } -} - - -/* test -- the body of the test */ - -static void *test(void *arg, size_t s) -{ - size_t i; - mps_word_t collections, rampSwitch; - mps_alloc_pattern_t ramp = mps_alloc_pattern_ramp(); - int ramping; - mps_ap_t ap, busy_ap; - mps_addr_t busy_init; - - arena = (mps_arena_t)arg; - (void)s; /* unused */ - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2"); - - /* create an ap, and leave it busy */ - die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); - - collections = 0; - rampSwitch = rampSIZE; - die(mps_ap_alloc_pattern_begin(ap, ramp), "pattern begin (ap)"); - die(mps_ap_alloc_pattern_begin(busy_ap, ramp), "pattern begin (busy_ap)"); - ramping = 1; - while (collections < collectionsCOUNT) { - unsigned long c; - size_t r; - - c = mps_collections(arena); - - if (collections != c) { - collections = c; - printf("\nCollection %lu started, %lu objects.\n", c, objs); - report(arena); - - for (i = 0; i < exactRootsCOUNT; ++i) - cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]), - "all roots check"); - - if (collections == collectionsCOUNT / 2) { - unsigned long object_count = 0; - mps_arena_park(arena); - mps_arena_formatted_objects_walk(arena, test_stepper, &object_count, 0); - mps_arena_release(arena); - printf("stepped on %lu objects.\n", object_count); - } - if (collections == rampSwitch) { - int begin_ramp = !ramping - || /* Every other time, switch back immediately. */ (collections & 1); - - rampSwitch += rampSIZE; - if (ramping) { - die(mps_ap_alloc_pattern_end(ap, ramp), "pattern end (ap)"); - die(mps_ap_alloc_pattern_end(busy_ap, ramp), "pattern end (busy_ap)"); - ramping = 0; - /* kill half of the roots */ - for(i = 0; i < exactRootsCOUNT; i += 2) { - if (exactRoots[i] != objNULL) { - cdie(dylan_check(exactRoots[i]), "ramp kill check"); - exactRoots[i] = objNULL; - } - } - } - if (begin_ramp) { - die(mps_ap_alloc_pattern_begin(ap, ramp), - "pattern rebegin (ap)"); - die(mps_ap_alloc_pattern_begin(busy_ap, ramp), - "pattern rebegin (busy_ap)"); - ramping = 1; - } - } - } - - churn(ap); - - if (r % initTestFREQ == 0) - *(int*)busy_init = -1; /* check that the buffer is still there */ - - if (objs % 1024 == 0) { - report(arena); - putchar('.'); - fflush(stdout); - } - } - - (void)mps_commit(busy_ap, busy_init, 64); - mps_ap_destroy(busy_ap); - mps_ap_destroy(ap); - - return NULL; -} - - -static void *fooey2(void *arg, size_t s) -{ - mps_ap_t ap; - - (void)arg; (void)s; /* unused */ - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate(fooey)"); - while(mps_collections(arena) < collectionsCOUNT) { - churn(ap); - } - mps_ap_destroy(ap); - return NULL; -} - - -static void *fooey(void* childIsFinishedReturn) -{ - void *r; - mps_thr_t thread; - mps_thr_t thread2; - - /* register the thread twice, just to make sure it works */ - die(mps_thread_reg(&thread, (mps_arena_t)arena), "thread_reg"); - die(mps_thread_reg(&thread2, (mps_arena_t)arena), "thread2_reg"); - mps_tramp(&r, fooey2, NULL, 0); - mps_thread_dereg(thread); - mps_thread_dereg(thread2); - *(int *)childIsFinishedReturn = 1; - return r; -} - - -int main(int argc, char **argv) -{ - mps_thr_t thread; - pthread_t pthread1; - void *r; - int childIsFinished = 0; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create"); - mps_message_type_enable(arena, mps_message_type_gc()); - init(); - die(mps_thread_reg(&thread, arena), "thread_reg"); - pthread_create(&pthread1, NULL, fooey, (void *)&childIsFinished); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - - while (!childIsFinished) { - struct timespec req = {1, 0}; - (void)nanosleep(&req, NULL); - } - - finish(); - report(arena); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/amsss.c b/mps/code/amsss.c deleted file mode 100644 index 7906c8805bf..00000000000 --- a/mps/code/amsss.c +++ /dev/null @@ -1,295 +0,0 @@ -/* amsss.c: POOL CLASS AMS STRESS TEST - * - * $Id$ - * Copyright (c) 2001-2002, 2006 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * .design: Adapted from amcss.c, but not counting collections, just - * total size of objects allocated (because epoch doesn't increment when - * AMS is collected). */ - -#include "fmtdy.h" -#include "fmtdytst.h" -#include "testlib.h" -#include "mpscams.h" -#include "mpsavm.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include "mps.h" -#include -#include -#include -#include - - -#define exactRootsCOUNT 50 -#define ambigRootsCOUNT 100 -/* This is enough for three GCs. */ -#define totalSizeMAX 800 * (size_t)1024 -#define totalSizeSTEP 200 * (size_t)1024 -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) -#define testArenaSIZE ((size_t)16<<20) -#define initTestFREQ 3000 -#define splatTestFREQ 6000 -static mps_gen_param_s testChain[1] = { { 160, 0.90 } }; - - -static mps_arena_t arena; -static mps_ap_t ap; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; -static size_t totalSize = 0; - - -/* report - report statistics from any messages */ - -static void report(void) -{ - static int nStart = 0; - static int nComplete = 0; - mps_message_type_t type; - - while(mps_message_queue_type(&type, arena)) { - mps_message_t message; - - cdie(mps_message_get(&message, arena, type), "message get"); - - if (type == mps_message_type_gc_start()) { - printf("\nCollection start %d. Because:\n", ++nStart); - printf("%s\n", mps_message_gc_start_why(arena, message)); - - } else if (type == mps_message_type_gc()) { - size_t live, condemned, not_condemned; - - live = mps_message_gc_live_size(arena, message); - condemned = mps_message_gc_condemned_size(arena, message); - not_condemned = mps_message_gc_not_condemned_size(arena, message); - - printf("\nCollection complete %d:\n", ++nComplete); - printf("live %"PRIuLONGEST"\n", (ulongest_t)live); - printf("condemned %"PRIuLONGEST"\n", (ulongest_t)condemned); - printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned); - - } else { - cdie(0, "unknown message type"); - } - - mps_message_discard(arena, message); - } - - return; -} - - -/* make -- object allocation and init */ - -static mps_addr_t make(void) -{ - size_t length = rnd() % 20, size = (length+2) * sizeof(mps_word_t); - mps_addr_t p; - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, p, ap, size); - if (res) - die(res, "MPS_RESERVE_BLOCK"); - res = dylan_init(p, size, exactRoots, exactRootsCOUNT); - if (res) - die(res, "dylan_init"); - } while(!mps_commit(ap, p, size)); - - totalSize += size; - return p; -} - - -/* test -- the actual stress test */ - -static mps_pool_debug_option_s freecheckOptions = - { NULL, 0, (void *)"Dead", 4 }; - -static void *test(void *arg, size_t haveAmbigous) -{ - mps_pool_t pool; - mps_root_t exactRoot, ambigRoot = NULL; - size_t lastStep = 0, i, r; - unsigned long objs; - mps_ap_t busy_ap; - mps_addr_t busy_init; - - pool = (mps_pool_t)arg; - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2"); - - for(i = 0; i < exactRootsCOUNT; ++i) - exactRoots[i] = objNULL; - if (haveAmbigous) - for(i = 0; i < ambigRootsCOUNT; ++i) - ambigRoots[i] = rnd_addr(); - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - if (haveAmbigous) - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); - - /* create an ap, and leave it busy */ - die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); - - objs = 0; totalSize = 0; - while(totalSize < totalSizeMAX) { - if (totalSize > lastStep + totalSizeSTEP) { - lastStep = totalSize; - printf("\nSize %"PRIuLONGEST" bytes, %lu objects.\n", - (ulongest_t)totalSize, objs); - fflush(stdout); - for(i = 0; i < exactRootsCOUNT; ++i) - cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]), - "all roots check"); - } - - r = (size_t)rnd(); - if (!haveAmbigous || (r & 1)) { - i = (r >> 1) % exactRootsCOUNT; - if (exactRoots[i] != objNULL) - cdie(dylan_check(exactRoots[i]), "dying root check"); - exactRoots[i] = make(); - if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL) - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - } else { - i = (r >> 1) % ambigRootsCOUNT; - ambigRoots[(ambigRootsCOUNT-1) - i] = make(); - /* Create random interior pointers */ - ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); - } - - if (rnd() % initTestFREQ == 0) - *(int*)busy_init = -1; /* check that the buffer is still there */ - - if (rnd() % splatTestFREQ == 0) - mps_pool_check_free_space(pool); - - ++objs; - if (objs % 256 == 0) { - printf("."); - report(); - fflush(stdout); - } - } - - (void)mps_commit(busy_ap, busy_init, 64); - mps_ap_destroy(busy_ap); - mps_ap_destroy(ap); - mps_root_destroy(exactRoot); - if (haveAmbigous) - mps_root_destroy(ambigRoot); - - return NULL; -} - - -int main(int argc, char **argv) -{ - mps_thr_t thread; - mps_fmt_t format; - mps_chain_t chain; - mps_pool_t pool; - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create"); - mps_message_type_enable(arena, mps_message_type_gc_start()); - mps_message_type_enable(arena, mps_message_type_gc()); - die(mps_thread_reg(&thread, arena), "thread_reg"); - die(mps_fmt_create_A(&format, arena, dylan_fmt_A()), "fmt_create"); - die(mps_chain_create(&chain, arena, 1, testChain), "chain_create"); - - printf("\n\n****************************** Testing AMS Debug\n"); - die(mps_pool_create(&pool, arena, mps_class_ams_debug(), &freecheckOptions, - format, chain, FALSE), - "pool_create(ams_debug,share)"); - mps_tramp(&r, test, pool, 0); - mps_pool_destroy(pool); - - printf("\n\n****************************** Testing AMS Debug\n"); - die(mps_pool_create(&pool, arena, mps_class_ams_debug(), &freecheckOptions, - format, chain, TRUE), - "pool_create(ams_debug,ambig)"); - mps_tramp(&r, test, pool, 1); - mps_pool_destroy(pool); - - printf("\n\n****************************** Testing AMS\n"); - die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain, TRUE), - "pool_create(ams,ambig)"); - mps_tramp(&r, test, pool, 1); - mps_pool_destroy(pool); - - printf("\n\n****************************** Testing AMS\n"); - die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain, FALSE), - "pool_create(ams,share)"); - mps_tramp(&r, test, pool, 0); - mps_pool_destroy(pool); - - mps_chain_destroy(chain); - mps_fmt_destroy(format); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2006 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/amssshe.c b/mps/code/amssshe.c deleted file mode 100644 index 5457c13ee25..00000000000 --- a/mps/code/amssshe.c +++ /dev/null @@ -1,218 +0,0 @@ -/* amssshe.c: POOL CLASS AMS STRESS TEST WITH HEADERS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .design: Adapted from amsss.c. - */ - -#include "fmthe.h" -#include "fmtdytst.h" -#include "testlib.h" -#include "mpscams.h" -#include "mpsavm.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include "mps.h" -#include -#include -#include -#include - - -#define exactRootsCOUNT 50 -#define ambigRootsCOUNT 100 -/* This is enough for five GCs. */ -#define totalSizeMAX 800 * (size_t)1024 -#define totalSizeSTEP 200 * (size_t)1024 -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) -#define testArenaSIZE ((size_t)16<<20) -#define initTestFREQ 6000 -static mps_gen_param_s testChain[1] = { { 160, 0.90 } }; - - -static mps_pool_t pool; -static mps_ap_t ap; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; -static size_t totalSize = 0; - - -static mps_addr_t make(void) -{ - size_t length = rnd() % 20, size = (length+2) * sizeof(mps_word_t); - mps_addr_t p, userP; - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, p, ap, size + headerSIZE); - if(res) - die(res, "MPS_RESERVE_BLOCK"); - userP = (mps_addr_t)((char*)p + headerSIZE); - res = dylan_init(userP, size, exactRoots, exactRootsCOUNT); - if(res) - die(res, "dylan_init"); - ((int*)p)[0] = realHeader; - ((int*)p)[1] = 0xED0ED; - } while(!mps_commit(ap, p, size + headerSIZE)); - - totalSize += size; - return userP; -} - - -static void *test(void *arg, size_t s) -{ - mps_arena_t arena; - mps_fmt_t format; - mps_chain_t chain; - mps_root_t exactRoot, ambigRoot; - size_t lastStep = 0, i, r; - unsigned long objs; - mps_ap_t busy_ap; - mps_addr_t busy_init; - - arena = (mps_arena_t)arg; - (void)s; /* unused */ - - die(EnsureHeaderFormat(&format, arena), "make header format"); - die(mps_chain_create(&chain, arena, 1, testChain), "chain_create"); - die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain, - TRUE), "pool_create(ams)"); - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2"); - - for(i = 0; i < exactRootsCOUNT; ++i) - exactRoots[i] = objNULL; - for(i = 0; i < ambigRootsCOUNT; ++i) - ambigRoots[i] = rnd_addr(); - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); - - /* create an ap, and leave it busy */ - die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); - - objs = 0; - while(totalSize < totalSizeMAX) { - if(totalSize > lastStep + totalSizeSTEP) { - lastStep = totalSize; - printf("\nSize %"PRIuLONGEST" bytes, %lu objects.\n", - (ulongest_t)totalSize, objs); - fflush(stdout); - for(i = 0; i < exactRootsCOUNT; ++i) - cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]), - "all roots check"); - } - - r = (size_t)rnd(); - if(r & 1) { - i = (r >> 1) % exactRootsCOUNT; - if(exactRoots[i] != objNULL) - cdie(dylan_check(exactRoots[i]), "dying root check"); - exactRoots[i] = make(); - if(exactRoots[(exactRootsCOUNT-1) - i] != objNULL) - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - } else { - i = (r >> 1) % ambigRootsCOUNT; - ambigRoots[(ambigRootsCOUNT-1) - i] = make(); - /* Create random interior pointers */ - ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); - } - - if(rnd() % initTestFREQ == 0) - *(int*)busy_init = -1; /* check that the buffer is still there */ - - ++objs; - if (objs % 256 == 0) { - printf("."); - fflush(stdout); - } - } - - (void)mps_commit(busy_ap, busy_init, 64); - mps_ap_destroy(busy_ap); - mps_ap_destroy(ap); - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); - mps_pool_destroy(pool); - mps_chain_destroy(chain); - mps_fmt_destroy(format); - - return NULL; -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/apss.c b/mps/code/apss.c deleted file mode 100644 index e23aee22f24..00000000000 --- a/mps/code/apss.c +++ /dev/null @@ -1,239 +0,0 @@ -/* apss.c: AP MANUAL ALLOC STRESS TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - */ - - -#include "mpscmv.h" -#include "mpscmvff.h" -#include "mpslib.h" -#include "mpsavm.h" - -#include "testlib.h" - -#include -#include - - -#define testArenaSIZE ((((size_t)3)<<24) - 4) -#define testSetSIZE 200 -#define testLOOPS 10 - - -/* make -- allocate one object */ - -static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size) -{ - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, *p, ap, size); - if(res != MPS_RES_OK) - return res; - } while(!mps_commit(ap, *p, size)); - - return MPS_RES_OK; -} - - -/* stress -- create a pool of the requested type and allocate in it */ - -static mps_res_t stress(mps_class_t class, size_t (*size)(int i), - mps_arena_t arena, ...) -{ - mps_res_t res = MPS_RES_OK; - mps_pool_t pool; - mps_ap_t ap; - va_list arg; - int i, k; - int *ps[testSetSIZE]; - size_t ss[testSetSIZE]; - - va_start(arg, arena); - res = mps_pool_create_v(&pool, arena, class, arg); - va_end(arg); - if (res != MPS_RES_OK) - return res; - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - - /* allocate a load of objects */ - for (i=0; i= sizeof(ps[i])) - *ps[i] = 1; /* Write something, so it gets swap. */ - } - - mps_pool_check_fenceposts(pool); - - for (k=0; k (b)) ? (a) : (b)) - -#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - - -/* randomSizeAligned -- produce sizes both large and small, - * aligned by platform alignment */ - -static size_t randomSizeAligned(int i) -{ - size_t maxSize = 2 * 160 * 0x2000; - /* Reduce by a factor of 2 every 10 cycles. Total allocation about 40 MB. */ - return alignUp(rnd() % max((maxSize >> (i / 10)), 2) + 1, MPS_PF_ALIGN); -} - - -static mps_pool_debug_option_s bothOptions8 = { - /* .fence_template = */ (void *)"postpost", - /* .fence_size = */ 8, - /* .free_template = */ (void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_pool_debug_option_s bothOptions16 = { - /* .fence_template = */ (void *)"postpostpostpost", - /* .fence_size = */ 16, - /* .free_template = */ (void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_pool_debug_option_s fenceOptions = { - /* .fence_template = */ (void *)"\0XXX ''\"\"'' XXX\0", - /* .fence_size = */ 16, - /* .free_template = */ NULL, - /* .free_size = */ 0 -}; - -/* testInArena -- test all the pool classes in the given arena */ - -static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options) -{ - mps_res_t res; - - /* IWBN to test MVFFDebug, but the MPS doesn't support debugging APs, */ - /* yet (MV Debug works here, because it fakes it through PoolAlloc). */ - printf("MVFF\n\n"); - res = stress(mps_class_mvff(), randomSizeAligned, arena, - (size_t)65536, (size_t)32, sizeof(void *), TRUE, TRUE, TRUE); - if (res == MPS_RES_COMMIT_LIMIT) return; - die(res, "stress MVFF"); - printf("MV debug\n\n"); - res = stress(mps_class_mv_debug(), randomSizeAligned, arena, - options, (size_t)65536, (size_t)32, (size_t)65536); - if (res == MPS_RES_COMMIT_LIMIT) return; - die(res, "stress MV debug"); - printf("MV\n\n"); - res = stress(mps_class_mv(), randomSizeAligned, arena, - (size_t)65536, (size_t)32, (size_t)65536); - if (res == MPS_RES_COMMIT_LIMIT) return; - die(res, "stress MV"); -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_pool_debug_option_s *bothOptions; - - bothOptions = MPS_PF_ALIGN == 8 ? &bothOptions8 : &bothOptions16; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), 2*testArenaSIZE), - "mps_arena_create"); - die(mps_arena_commit_limit_set(arena, testArenaSIZE), "commit limit"); - testInArena(arena, &fenceOptions); - mps_arena_destroy(arena); - - die(mps_arena_create(&arena, mps_arena_class_vmnz(), 2*testArenaSIZE), - "mps_arena_create"); - testInArena(arena, bothOptions); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/arena.c b/mps/code/arena.c deleted file mode 100644 index 2e71a67c17c..00000000000 --- a/mps/code/arena.c +++ /dev/null @@ -1,791 +0,0 @@ -/* arena.c: ARENA ALLOCATION FEATURES - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .sources: is the main design document. */ - -#include "tract.h" -#include "poolmv.h" -#include "mpm.h" - -SRCID(arena, "$Id$"); - - -/* ArenaControlPool -- get the control pool */ - -#define ArenaControlPool(arena) MV2Pool(&(arena)->controlPoolStruct) - - -/* Forward declarations */ - -static void ArenaTrivCompact(Arena arena, Trace trace); - - -/* ArenaTrivDescribe -- produce trivial description of an arena */ - -static Res ArenaTrivDescribe(Arena arena, mps_lib_FILE *stream) -{ - if (!TESTT(Arena, arena)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - /* .describe.triv.never-called-from-subclass-method: - * This Triv method seems to assume that it will never get called - * from a subclass-method invoking ARENA_SUPERCLASS()->describe. - * It assumes that it only gets called if the describe method has - * not been subclassed. (That's the only reason for printing the - * "No class-specific description available" message). - * This is bogus, but that's the status quo. RHSK 2007-04-27. - */ - /* .describe.triv.dont-upcall: Therefore (for now) the last - * subclass describe method should avoid invoking - * ARENA_SUPERCLASS()->describe. RHSK 2007-04-27. - */ - return WriteF(stream, - " No class-specific description available.\n", NULL); -} - - -/* AbstractArenaClass -- The abstact arena class definition - * - * .null: Most abstract class methods are set to NULL. See - * . */ - -typedef ArenaClassStruct AbstractArenaClassStruct; - -DEFINE_CLASS(AbstractArenaClass, class) -{ - INHERIT_CLASS(&class->protocol, ProtocolClass); - class->name = "ABSARENA"; - class->size = 0; - class->offset = 0; - class->init = NULL; - class->finish = NULL; - class->reserved = NULL; - class->spareCommitExceeded = ArenaNoSpareCommitExceeded; - class->extend = ArenaNoExtend; - class->alloc = NULL; - class->free = NULL; - class->chunkInit = NULL; - class->chunkFinish = NULL; - class->compact = ArenaTrivCompact; - class->describe = ArenaTrivDescribe; - class->sig = ArenaClassSig; -} - - -/* ArenaClassCheck -- check the consistency of an arena class */ - -Bool ArenaClassCheck(ArenaClass class) -{ - CHECKL(ProtocolClassCheck(&class->protocol)); - CHECKL(class->name != NULL); /* Should be <=6 char C identifier */ - CHECKL(class->size >= sizeof(ArenaStruct)); - /* Offset of generic Pool within class-specific instance cannot be */ - /* greater than the size of the class-specific portion of the */ - /* instance. */ - CHECKL(class->offset <= (size_t)(class->size - sizeof(ArenaStruct))); - CHECKL(FUNCHECK(class->init)); - CHECKL(FUNCHECK(class->finish)); - CHECKL(FUNCHECK(class->reserved)); - CHECKL(FUNCHECK(class->spareCommitExceeded)); - CHECKL(FUNCHECK(class->extend)); - CHECKL(FUNCHECK(class->alloc)); - CHECKL(FUNCHECK(class->free)); - CHECKL(FUNCHECK(class->chunkInit)); - CHECKL(FUNCHECK(class->chunkFinish)); - CHECKL(FUNCHECK(class->compact)); - CHECKL(FUNCHECK(class->describe)); - CHECKS(ArenaClass, class); - return TRUE; -} - - -/* ArenaCheck -- check the arena */ - -Bool ArenaCheck(Arena arena) -{ - CHECKS(Arena, arena); - CHECKD(Globals, ArenaGlobals(arena)); - CHECKD(ArenaClass, arena->class); - - CHECKL(BoolCheck(arena->poolReady)); - if (arena->poolReady) { /* */ - CHECKD(MV, &arena->controlPoolStruct); - CHECKD(Reservoir, &arena->reservoirStruct); - } - /* Can't check that limit>=size because we may call ArenaCheck */ - /* while the size is being adjusted. */ - - CHECKL(arena->committed <= arena->commitLimit); - CHECKL(arena->spareCommitted <= arena->committed); - CHECKL(arena->spareCommitted <= arena->spareCommitLimit); - - CHECKL(ShiftCheck(arena->zoneShift)); - CHECKL(AlignCheck(arena->alignment)); - /* Tract allocation must be platform-aligned. */ - CHECKL(arena->alignment >= MPS_PF_ALIGN); - /* Stripes can't be smaller than pages. */ - CHECKL(((Size)1 << arena->zoneShift) >= arena->alignment); - - if (arena->lastTract == NULL) { - CHECKL(arena->lastTractBase == (Addr)0); - } else { - CHECKL(TractBase(arena->lastTract) == arena->lastTractBase); - } - - if (arena->primary != NULL) { - CHECKD(Chunk, arena->primary); - } - CHECKL(RingCheck(&arena->chunkRing)); - /* nothing to check for chunkSerial */ - CHECKD(ChunkCacheEntry, &arena->chunkCache); - - CHECKL(LocusCheck(arena)); - - /* nothing to check for alertCollection */ - - return TRUE; -} - - -/* ArenaInit -- initialize the generic part of the arena - * - * .init.caller: Unlike PoolInit, this is called by the class init - * methods, not the generic Create. This is because the class is - * responsible for allocating the descriptor. */ - -Res ArenaInit(Arena arena, ArenaClass class) -{ - Res res; - - /* We do not check the arena argument, because it's _supposed_ to */ - /* point to an uninitialized block of memory. */ - AVERT(ArenaClass, class); - - arena->class = class; - - arena->committed = (Size)0; - /* commitLimit may be overridden by init (but probably not */ - /* as there's not much point) */ - arena->commitLimit = (Size)-1; - arena->spareCommitted = (Size)0; - arena->spareCommitLimit = ARENA_INIT_SPARE_COMMIT_LIMIT; - /* alignment is usually overridden by init */ - arena->alignment = (Align)1 << ARENA_ZONESHIFT; - /* zoneShift is usually overridden by init */ - arena->zoneShift = ARENA_ZONESHIFT; - arena->poolReady = FALSE; /* */ - arena->lastTract = NULL; - arena->lastTractBase = NULL; - - arena->primary = NULL; - RingInit(&arena->chunkRing); - arena->chunkSerial = (Serial)0; - ChunkCacheEntryInit(&arena->chunkCache); - - LocusInit(arena); - - arena->alertCollection = 0; - - res = GlobalsInit(ArenaGlobals(arena)); - if (res != ResOK) - goto failGlobalsInit; - - arena->sig = ArenaSig; - - /* initialize the reservoir, */ - res = ReservoirInit(&arena->reservoirStruct, arena); - if (res != ResOK) - goto failReservoirInit; - - AVERT(Arena, arena); - return ResOK; - -failReservoirInit: - GlobalsFinish(ArenaGlobals(arena)); -failGlobalsInit: - return res; -} - - -/* ArenaCreateV -- create the arena and call initializers */ - -Res ArenaCreateV(Arena *arenaReturn, ArenaClass class, va_list args) -{ - Arena arena; - Res res; - - AVER(arenaReturn != NULL); - AVERT(ArenaClass, class); - - /* We must initialise the event subsystem very early, because event logging - will start as soon as anything interesting happens and expect to write - to the EventLast pointers. */ - EventInit(); - - /* Do initialization. This will call ArenaInit (see .init.caller). */ - res = (*class->init)(&arena, class, args); - if (res != ResOK) - goto failInit; - - arena->alignment = ChunkPageSize(arena->primary); - if (arena->alignment > ((Size)1 << arena->zoneShift)) { - res = ResMEMORY; /* size was too small */ - goto failStripeSize; - } - - res = ControlInit(arena); - if (res != ResOK) - goto failControlInit; - - res = GlobalsCompleteCreate(ArenaGlobals(arena)); - if (res != ResOK) - goto failGlobalsCompleteCreate; - - AVERT(Arena, arena); - *arenaReturn = arena; - return ResOK; - -failGlobalsCompleteCreate: - ControlFinish(arena); -failControlInit: -failStripeSize: - (*class->finish)(arena); -failInit: - return res; -} - - -/* ArenaFinish -- finish the generic part of the arena - * - * .finish.caller: Unlike PoolFinish, this is called by the class finish - * methods, not the generic Destroy. This is because the class is - * responsible for deallocating the descriptor. */ - -void ArenaFinish(Arena arena) -{ - ReservoirFinish(ArenaReservoir(arena)); - arena->sig = SigInvalid; - GlobalsFinish(ArenaGlobals(arena)); - LocusFinish(arena); - RingFinish(&arena->chunkRing); -} - - -/* ArenaDestroy -- destroy the arena */ - -void ArenaDestroy(Arena arena) -{ - AVERT(Arena, arena); - - GlobalsPrepareToDestroy(ArenaGlobals(arena)); - - /* Empty the reservoir - see */ - ReservoirSetLimit(ArenaReservoir(arena), 0); - - arena->poolReady = FALSE; - ControlFinish(arena); - - /* Call class-specific finishing. This will call ArenaFinish. */ - (*arena->class->finish)(arena); - - EventFinish(); -} - - -/* ControlInit -- initialize the control pool */ - -Res ControlInit(Arena arena) -{ - Res res; - - AVERT(Arena, arena); - res = PoolInit(&arena->controlPoolStruct.poolStruct, - arena, PoolClassMV(), - ARENA_CONTROL_EXTENDBY, ARENA_CONTROL_AVGSIZE, - ARENA_CONTROL_MAXSIZE); - if (res != ResOK) - return res; - arena->poolReady = TRUE; /* */ - return ResOK; -} - - -/* ControlFinish -- finish the control pool */ - -void ControlFinish(Arena arena) -{ - AVERT(Arena, arena); - arena->poolReady = FALSE; - PoolFinish(&arena->controlPoolStruct.poolStruct); -} - - -/* ArenaDescribe -- describe the arena */ - -Res ArenaDescribe(Arena arena, mps_lib_FILE *stream) -{ - Res res; - Size reserved; - - if (!TESTT(Arena, arena)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, "Arena $P {\n", (WriteFP)arena, - " class $P (\"$S\")\n", - (WriteFP)arena->class, arena->class->name, - NULL); - if (res != ResOK) return res; - - if (arena->poolReady) { - res = WriteF(stream, - " controlPool $P\n", (WriteFP)&arena->controlPoolStruct, - NULL); - if (res != ResOK) return res; - } - - /* Note: this Describe clause calls a function */ - reserved = ArenaReserved(arena); - res = WriteF(stream, - " reserved $W <-- " - "total size of address-space reserved\n", - (WriteFW)reserved, - NULL); - if (res != ResOK) return res; - - res = WriteF(stream, - " committed $W <-- " - "total bytes currently stored (in RAM or swap)\n", - (WriteFW)arena->committed, - " commitLimit $W\n", (WriteFW)arena->commitLimit, - " spareCommitted $W\n", (WriteFW)arena->spareCommitted, - " spareCommitLimit $W\n", (WriteFW)arena->spareCommitLimit, - " zoneShift $U\n", (WriteFU)arena->zoneShift, - " alignment $W\n", (WriteFW)arena->alignment, - NULL); - if (res != ResOK) return res; - - res = WriteF(stream, - " droppedMessages $U$S\n", (WriteFU)arena->droppedMessages, - (arena->droppedMessages == 0 ? "" : " -- MESSAGES DROPPED!"), - NULL); - if (res != ResOK) return res; - - res = (*arena->class->describe)(arena, stream); - if (res != ResOK) return res; - - /* Do not call GlobalsDescribe: it makes too much output, thanks. - * RHSK 2007-04-27 - */ -#if 0 - res = GlobalsDescribe(ArenaGlobals(arena), stream); - if (res != ResOK) return res; -#endif - - res = WriteF(stream, - "} Arena $P ($U)\n", (WriteFP)arena, - (WriteFU)arena->serial, - NULL); - return res; -} - - -/* ArenaDescribeTracts -- describe all the tracts in the arena */ - -Res ArenaDescribeTracts(Arena arena, mps_lib_FILE *stream) -{ - Res res; - Tract tract; - Bool b; - Addr oldLimit, base, limit; - Size size; - - if (!TESTT(Arena, arena)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - b = TractFirst(&tract, arena); - oldLimit = TractBase(tract); - while (b) { - base = TractBase(tract); - limit = TractLimit(tract); - size = ArenaAlign(arena); - - if (TractBase(tract) > oldLimit) { - res = WriteF(stream, - "[$P, $P) $W $U ---\n", - (WriteFP)oldLimit, (WriteFP)base, - (WriteFW)AddrOffset(oldLimit, base), - (WriteFU)AddrOffset(oldLimit, base), - NULL); - if (res != ResOK) return res; - } - - res = WriteF(stream, - "[$P, $P) $W $U $P ($S)\n", - (WriteFP)base, (WriteFP)limit, - (WriteFW)size, (WriteFW)size, - (WriteFP)TractPool(tract), - (WriteFS)(TractPool(tract)->class->name), - NULL); - if (res != ResOK) return res; - b = TractNext(&tract, arena, TractBase(tract)); - oldLimit = limit; - } - return ResOK; -} - - -/* ControlAlloc -- allocate a small block directly from the control pool - * - * .arena.control-pool: Actually the block will be allocated from the - * control pool, which is an MV pool embedded in the arena itself. - * - * .controlalloc.addr: In implementations where Addr is not compatible - * with void* (), ControlAlloc must take care of - * allocating so that the block can be addressed with a void*. */ - -Res ControlAlloc(void **baseReturn, Arena arena, size_t size, - Bool withReservoirPermit) -{ - Addr base; - Res res; - - AVERT(Arena, arena); - AVER(baseReturn != NULL); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - AVER(arena->poolReady); - - res = PoolAlloc(&base, ArenaControlPool(arena), (Size)size, - withReservoirPermit); - if (res != ResOK) - return res; - - *baseReturn = (void *)base; /* see .controlalloc.addr */ - return ResOK; -} - - -/* ControlFree -- free a block allocated using ControlAlloc */ - -void ControlFree(Arena arena, void* base, size_t size) -{ - AVERT(Arena, arena); - AVER(base != NULL); - AVER(size > 0); - AVER(arena->poolReady); - - PoolFree(ArenaControlPool(arena), (Addr)base, (Size)size); -} - - -/* ControlDescribe -- describe the arena's control pool */ - -Res ControlDescribe(Arena arena, mps_lib_FILE *stream) -{ - Res res; - - if (!TESTT(Arena, arena)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = PoolDescribe(ArenaControlPool(arena), stream); - - return res; -} - - -/* ArenaAlloc -- allocate some tracts from the arena */ - -Res ArenaAlloc(Addr *baseReturn, SegPref pref, Size size, Pool pool, - Bool withReservoirPermit) -{ - Res res; - Arena arena; - Addr base; - Tract baseTract; - Reservoir reservoir; - - AVER(baseReturn != NULL); - AVERT(SegPref, pref); - AVER(size > (Size)0); - AVERT(Pool, pool); - AVER(BoolCheck(withReservoirPermit)); - - arena = PoolArena(pool); - AVERT(Arena, arena); - AVER(SizeIsAligned(size, arena->alignment)); - reservoir = ArenaReservoir(arena); - AVERT(Reservoir, reservoir); - - res = ReservoirEnsureFull(reservoir); - if (res != ResOK) { - AVER(ResIsAllocFailure(res)); - if (!withReservoirPermit) - return res; - } - - res = (*arena->class->alloc)(&base, &baseTract, pref, size, pool); - if (res == ResOK) { - goto goodAlloc; - } else if (withReservoirPermit) { - AVER(ResIsAllocFailure(res)); - res = ReservoirWithdraw(&base, &baseTract, reservoir, size, pool); - if (res == ResOK) - goto goodAlloc; - } - EVENT3(ArenaAllocFail, arena, size, pool); - return res; - -goodAlloc: - /* cache the tract - */ - arena->lastTract = baseTract; - arena->lastTractBase = base; - - EVENT5(ArenaAlloc, arena, baseTract, base, size, pool); - *baseReturn = base; - return ResOK; -} - - -/* ArenaFree -- free some tracts to the arena */ - -void ArenaFree(Addr base, Size size, Pool pool) -{ - Arena arena; - Addr limit; - Reservoir reservoir; - Res res; - - AVERT(Pool, pool); - AVER(base != NULL); - AVER(size > (Size)0); - arena = PoolArena(pool); - AVERT(Arena, arena); - reservoir = ArenaReservoir(arena); - AVERT(Reservoir, reservoir); - AVER(AddrIsAligned(base, arena->alignment)); - AVER(SizeIsAligned(size, arena->alignment)); - - /* uncache the tract if in range - */ - limit = AddrAdd(base, size); - if ((arena->lastTractBase >= base) && (arena->lastTractBase < limit)) { - arena->lastTract = NULL; - arena->lastTractBase = (Addr)0; - } - - res = ReservoirEnsureFull(reservoir); - if (res == ResOK) { - (*arena->class->free)(base, size, pool); - } else { - AVER(ResIsAllocFailure(res)); - ReservoirDeposit(reservoir, base, size); - } - - EVENT3(ArenaFree, arena, base, size); - return; -} - - -Size ArenaReserved(Arena arena) -{ - AVERT(Arena, arena); - return (*arena->class->reserved)(arena); -} - -Size ArenaCommitted(Arena arena) -{ - AVERT(Arena, arena); - return arena->committed; -} - -Size ArenaSpareCommitted(Arena arena) -{ - AVERT(Arena, arena); - return arena->spareCommitted; -} - -Size ArenaSpareCommitLimit(Arena arena) -{ - AVERT(Arena, arena); - return arena->spareCommitLimit; -} - -void ArenaSetSpareCommitLimit(Arena arena, Size limit) -{ - AVERT(Arena, arena); - /* Can't check limit, as all possible values are allowed. */ - - arena->spareCommitLimit = limit; - if (arena->spareCommitLimit < arena->spareCommitted) { - arena->class->spareCommitExceeded(arena); - } - - EVENT2(SpareCommitLimitSet, arena, limit); - return; -} - -/* Used by arenas which don't use spare committed memory */ -void ArenaNoSpareCommitExceeded(Arena arena) -{ - AVERT(Arena, arena); - return; -} - - -Size ArenaCommitLimit(Arena arena) -{ - AVERT(Arena, arena); - return arena->commitLimit; -} - -Res ArenaSetCommitLimit(Arena arena, Size limit) -{ - Size committed; - Res res; - - AVERT(Arena, arena); - AVER(ArenaCommitted(arena) <= arena->commitLimit); - - committed = ArenaCommitted(arena); - if (limit < committed) { - /* Attempt to set the limit below current committed */ - if (limit >= committed - arena->spareCommitted) { - /* could set the limit by flushing any spare committed memory */ - arena->class->spareCommitExceeded(arena); - AVER(limit >= ArenaCommitted(arena)); - arena->commitLimit = limit; - res = ResOK; - } else { - res = ResFAIL; - } - } else { - arena->commitLimit = limit; - res = ResOK; - } - EVENT3(CommitLimitSet, arena, limit, (res == ResOK)); - return res; -} - - -/* ArenaAvail -- return available memory in the arena */ - -Size ArenaAvail(Arena arena) -{ - Size sSwap; - - sSwap = ArenaReserved(arena); - if (sSwap > arena->commitLimit) - sSwap = arena->commitLimit; - - /* TODO: sSwap should take into account the amount of backing store - available to supply the arena with memory. This would be the amount - available in the paging file, which is possibly the amount of free - disk space in some circumstances. We'd have to see whether we can get - this information from the operating system. It also depends on the - arena class, of course. */ - - return sSwap - arena->committed + arena->spareCommitted; -} - - -/* ArenaExtend -- Add a new chunk in the arena */ - -Res ArenaExtend(Arena arena, Addr base, Size size) -{ - Res res; - - AVERT(Arena, arena); - AVER(base != (Addr)0); - AVER(size > 0); - - res = (*arena->class->extend)(arena, base, size); - if (res != ResOK) - return res; - - EVENT3(ArenaExtend, arena, base, size); - return ResOK; -} - - -/* ArenaNoExtend -- fail to extend the arena by a chunk */ - -Res ArenaNoExtend(Arena arena, Addr base, Size size) -{ - AVERT(Arena, arena); - AVER(base != (Addr)0); - AVER(size > (Size)0); - - NOTREACHED; - return ResUNIMPL; -} - - -/* ArenaCompact -- respond (or not) to trace reclaim */ - -void ArenaCompact(Arena arena, Trace trace) -{ - AVERT(Arena, arena); - AVERT(Trace, trace); - (*arena->class->compact)(arena, trace); -} - -static void ArenaTrivCompact(Arena arena, Trace trace) -{ - UNUSED(arena); - UNUSED(trace); - return; -} - - -/* Has Addr */ - -Bool ArenaHasAddr(Arena arena, Addr addr) -{ - Seg seg; - - AVERT(Arena, arena); - return SegOfAddr(&seg, arena, addr); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/arenacl.c b/mps/code/arenacl.c deleted file mode 100644 index d76a6d9a485..00000000000 --- a/mps/code/arenacl.c +++ /dev/null @@ -1,518 +0,0 @@ -/* arenacl.c: ARENA CLASS USING CLIENT MEMORY - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .design: See . - * - * .improve.remember: One possible performance improvement is to - * remember (a conservative approximation to) the indices of the first - * and last free pages in each chunk, and start searching from these - * in ChunkAlloc. See request.epcore.170534. - */ - -#include "boot.h" -#include "tract.h" -#include "bt.h" -#include "mpm.h" -#include "mpsacl.h" - -SRCID(arenacl, "$Id$"); - - -/* ClientArenaStruct -- Client Arena Structure */ - -#define ClientArenaSig ((Sig)0x519A6EC7) /* SIGnature AREna CLient */ - -typedef struct ClientArenaStruct { - ArenaStruct arenaStruct; /* generic arena structure */ - Sig sig; /* */ -} ClientArenaStruct; -typedef struct ClientArenaStruct *ClientArena; - -#define Arena2ClientArena(arena) PARENT(ClientArenaStruct, arenaStruct, arena) -#define ClientArena2Arena(clArena) (&(clArena)->arenaStruct) - - -/* CLChunk -- chunk structure */ - -typedef struct ClientChunkStruct *ClientChunk; - -#define ClientChunkSig ((Sig)0x519A6C2C) /* SIGnature ARena CLient Chunk */ - -typedef struct ClientChunkStruct { - ChunkStruct chunkStruct; /* generic chunk */ - Size freePages; /* number of free pages in chunk */ - Addr pageBase; /* base of first managed page in chunk */ - Sig sig; /* */ -} ClientChunkStruct; - -#define ClientChunk2Chunk(clchunk) (&(clchunk)->chunkStruct) -#define Chunk2ClientChunk(chunk) PARENT(ClientChunkStruct, chunkStruct, chunk) - - -/* ClientChunkClientArena -- get the client arena from a client chunk */ - -#define ClientChunkClientArena(clchunk) \ - Arena2ClientArena(ChunkArena(ClientChunk2Chunk(clchunk))) - - -/* ClientChunkCheck -- check the consistency of a client chunk */ - -static Bool ClientChunkCheck(ClientChunk clChunk) -{ - Chunk chunk; - - CHECKS(ClientChunk, clChunk); - chunk = ClientChunk2Chunk(clChunk); - CHECKL(ChunkCheck(chunk)); - CHECKL(clChunk->freePages <= chunk->pages); - /* check they don't overlap (knowing the order) */ - CHECKL((Addr)(chunk + 1) < (Addr)chunk->allocTable); - return TRUE; -} - - -/* ClientArenaCheck -- check the consistency of a client arena */ - -static Bool ClientArenaCheck(ClientArena clientArena) -{ - CHECKS(ClientArena, clientArena); - CHECKD(Arena, ClientArena2Arena(clientArena)); - return TRUE; -} - - -/* clientChunkCreate -- create a ClientChunk */ - -static Res clientChunkCreate(Chunk *chunkReturn, Addr base, Addr limit, - ClientArena clientArena) -{ - ClientChunk clChunk; - Chunk chunk; - Addr alignedBase; - BootBlockStruct bootStruct; - BootBlock boot = &bootStruct; - Res res; - void *p; - - AVER(chunkReturn != NULL); - AVER(base != (Addr)0); - /* @@@@ Should refuse on small chunks, instead of AVERring. */ - AVER(limit != (Addr)0); - AVER(limit > base); - - /* Initialize boot block. */ - /* Chunk has to be page-aligned, and the boot allocs must be within it. */ - alignedBase = AddrAlignUp(base, ARENA_CLIENT_PAGE_SIZE); - AVER(alignedBase < limit); - res = BootBlockInit(boot, (void *)alignedBase, (void *)limit); - if (res != ResOK) - goto failBootInit; - - /* Allocate the chunk. */ - /* See .@@@@ */ - res = BootAlloc(&p, boot, sizeof(ClientChunkStruct), MPS_PF_ALIGN); - if (res != ResOK) - goto failChunkAlloc; - clChunk = p; chunk = ClientChunk2Chunk(clChunk); - - res = ChunkInit(chunk, ClientArena2Arena(clientArena), - alignedBase, AddrAlignDown(limit, ARENA_CLIENT_PAGE_SIZE), - ARENA_CLIENT_PAGE_SIZE, boot); - if (res != ResOK) - goto failChunkInit; - - ClientArena2Arena(clientArena)->committed += - AddrOffset(base, PageIndexBase(chunk, chunk->allocBase)); - BootBlockFinish(boot); - - clChunk->sig = ClientChunkSig; - AVERT(ClientChunk, clChunk); - *chunkReturn = chunk; - return ResOK; - -failChunkInit: -failChunkAlloc: -failBootInit: - return res; -} - - -/* ClientChunkInit -- initialize a ClientChunk */ - -static Res ClientChunkInit(Chunk chunk, BootBlock boot) -{ - ClientChunk clChunk; - - /* chunk is supposed to be uninitialized, so don't check it. */ - clChunk = Chunk2ClientChunk(chunk); - AVERT(BootBlock, boot); - UNUSED(boot); - - clChunk->freePages = chunk->pages; /* too large @@@@ */ - - return ResOK; -} - - -/* clientChunkDestroy -- destroy a ClientChunk */ - -static void clientChunkDestroy(Chunk chunk) -{ - ClientChunk clChunk; - - clChunk = Chunk2ClientChunk(chunk); - AVERT(ClientChunk, clChunk); - - clChunk->sig = SigInvalid; - ChunkFinish(chunk); -} - - -/* ClientChunkFinish -- finish a ClientChunk */ - -static void ClientChunkFinish(Chunk chunk) -{ - /* Can't check chunk as it's not valid anymore. */ - UNUSED(chunk); NOOP; -} - - -/* ClientArenaInit -- create and initialize the client arena - * - * .init.memory: Creates the arena structure in the chuck given, and - * makes the first chunk from the memory left over. - * .arena.init: Once the arena has been allocated, we call ArenaInit - * to do the generic part of init. - */ -static Res ClientArenaInit(Arena *arenaReturn, ArenaClass class, - va_list args) -{ - Arena arena; - ClientArena clientArena; - Size size; - Size clArenaSize; /* aligned size of ClientArenaStruct */ - Addr base, limit, chunkBase; - Res res; - Chunk chunk; - - size = va_arg(args, Size); - base = va_arg(args, Addr); - AVER(arenaReturn != NULL); - AVER((ArenaClass)mps_arena_class_cl() == class); - AVER(base != (Addr)0); - - clArenaSize = SizeAlignUp(sizeof(ClientArenaStruct), MPS_PF_ALIGN); - if (size < clArenaSize) - return ResMEMORY; - - limit = AddrAdd(base, size); - - /* allocate the arena */ - base = AddrAlignUp(base, MPS_PF_ALIGN); - clientArena = (ClientArena)base; - chunkBase = AddrAlignUp(AddrAdd(base, clArenaSize), MPS_PF_ALIGN); - if (chunkBase > limit) - return ResMEMORY; - - arena = ClientArena2Arena(clientArena); - /* */ - res = ArenaInit(arena, class); - if (res != ResOK) - return res; - - /* have to have a valid arena before calling ChunkCreate */ - clientArena->sig = ClientArenaSig; - - res = clientChunkCreate(&chunk, chunkBase, limit, clientArena); - if (res != ResOK) - goto failChunkCreate; - arena->primary = chunk; - - /* Set the zone shift to divide the initial chunk into the same */ - /* number of zones as will fit into a reference set (the number of */ - /* bits in a word). Note that some zones are discontiguous in the */ - /* arena if the size is not a power of 2. */ - arena->zoneShift = SizeFloorLog2(size >> MPS_WORD_SHIFT); - - EVENT3(ArenaCreateCL, arena, size, base); - AVERT(ClientArena, clientArena); - *arenaReturn = arena; - return ResOK; - -failChunkCreate: - ArenaFinish(arena); - return res; -} - - -/* ClientArenaFinish -- finish the arena */ - -static void ClientArenaFinish(Arena arena) -{ - ClientArena clientArena; - Ring node, next; - - clientArena = Arena2ClientArena(arena); - AVERT(ClientArena, clientArena); - - /* destroy all chunks */ - RING_FOR(node, &arena->chunkRing, next) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - clientChunkDestroy(chunk); - } - - clientArena->sig = SigInvalid; - - ArenaFinish(arena); /* */ -} - - -/* ClientArenaExtend -- extend the arena */ - -static Res ClientArenaExtend(Arena arena, Addr base, Size size) -{ - ClientArena clientArena; - Chunk chunk; - Res res; - Addr limit; - - AVERT(Arena, arena); - AVER(base != (Addr)0); - AVER(size > 0); - limit = AddrAdd(base, size); - - clientArena = Arena2ClientArena(arena); - res = clientChunkCreate(&chunk, base, limit, clientArena); - return res; -} - - -/* ClientArenaReserved -- return the amount of reserved address space */ - -static Size ClientArenaReserved(Arena arena) -{ - Size size; - Ring node, nextNode; - - AVERT(Arena, arena); - - size = 0; - /* .req.extend.slow */ - RING_FOR(node, &arena->chunkRing, nextNode) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - AVERT(Chunk, chunk); - size += AddrOffset(chunk->base, chunk->limit); - } - - return size; -} - - -/* chunkAlloc -- allocate some tracts in a chunk */ - -static Res chunkAlloc(Addr *baseReturn, Tract *baseTractReturn, - SegPref pref, Size pages, Pool pool, Chunk chunk) -{ - Index baseIndex, limitIndex, index; - Bool b; - Arena arena; - ClientChunk clChunk; - - AVER(baseReturn != NULL); - AVER(baseTractReturn != NULL); - clChunk = Chunk2ClientChunk(chunk); - - if (pages > clChunk->freePages) - return ResRESOURCE; - - arena = chunk->arena; - - if (pref->high) - b = BTFindShortResRangeHigh(&baseIndex, &limitIndex, chunk->allocTable, - chunk->allocBase, chunk->pages, pages); - else - b = BTFindShortResRange(&baseIndex, &limitIndex, chunk->allocTable, - chunk->allocBase, chunk->pages, pages); - - if (!b) - return ResRESOURCE; - - /* Check commit limit. Note that if there are multiple reasons */ - /* for failing the allocation we attempt to return other result codes */ - /* in preference to ResCOMMIT_LIMIT. See */ - if (ArenaCommitted(arena) + pages * ChunkPageSize(chunk) - > arena->commitLimit) { - return ResCOMMIT_LIMIT; - } - - /* Initialize the generic tract structures. */ - AVER(limitIndex > baseIndex); - for(index = baseIndex; index < limitIndex; ++index) { - PageAlloc(chunk, index, pool); - } - - clChunk->freePages -= pages; - - *baseReturn = PageIndexBase(chunk, baseIndex); - *baseTractReturn = PageTract(&chunk->pageTable[baseIndex]); - - return ResOK; -} - - -/* ClientAlloc -- allocate a region from the arena */ - -static Res ClientAlloc(Addr *baseReturn, Tract *baseTractReturn, - SegPref pref, Size size, Pool pool) -{ - Arena arena; - Res res; - Ring node, nextNode; - Size pages; - - AVER(baseReturn != NULL); - AVER(baseTractReturn != NULL); - AVERT(SegPref, pref); - AVER(size > 0); - AVERT(Pool, pool); - - arena = PoolArena(pool); - AVERT(Arena, arena); - /* All chunks have same pageSize. */ - AVER(SizeIsAligned(size, ChunkPageSize(arena->primary))); - /* NULL is used as a discriminator (see */ - /* ), therefore the real pool */ - /* must be non-NULL. */ - AVER(pool != NULL); - - pages = ChunkSizeToPages(arena->primary, size); - - /* .req.extend.slow */ - RING_FOR(node, &arena->chunkRing, nextNode) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - res = chunkAlloc(baseReturn, baseTractReturn, pref, pages, pool, chunk); - if (res == ResOK || res == ResCOMMIT_LIMIT) { - return res; - } - } - return ResRESOURCE; -} - - -/* ClientFree - free a region in the arena */ - -static void ClientFree(Addr base, Size size, Pool pool) -{ - Arena arena; - Chunk chunk = NULL; /* suppress "may be used uninitialized" */ - Size pages; - ClientArena clientArena; - Index pi, baseIndex, limitIndex; - Bool foundChunk; - ClientChunk clChunk; - - AVER(base != NULL); - AVER(size > (Size)0); - AVERT(Pool, pool); - arena = PoolArena(pool); - AVERT(Arena, arena); - clientArena = Arena2ClientArena(arena); - AVERT(ClientArena, clientArena); - AVER(SizeIsAligned(size, ChunkPageSize(arena->primary))); - AVER(AddrIsAligned(base, ChunkPageSize(arena->primary))); - - foundChunk = ChunkOfAddr(&chunk, arena, base); - AVER(foundChunk); - clChunk = Chunk2ClientChunk(chunk); - AVERT(ClientChunk, clChunk); - - pages = ChunkSizeToPages(chunk, size); - baseIndex = INDEX_OF_ADDR(chunk, base); - limitIndex = baseIndex + pages; - AVER(baseIndex < limitIndex); - AVER(limitIndex <= chunk->pages); - - for(pi = baseIndex; pi < limitIndex; pi++) { - Page page = &chunk->pageTable[pi]; - Tract tract = PageTract(page); - - AVER(TractPool(tract) == pool); - TractFinish(tract); - } - - AVER(BTIsSetRange(chunk->allocTable, baseIndex, limitIndex)); - BTResRange(chunk->allocTable, baseIndex, limitIndex); - - clChunk->freePages += pages; -} - - -/* ClientArenaClass -- The Client arena class definition */ - -DEFINE_ARENA_CLASS(ClientArenaClass, this) -{ - INHERIT_CLASS(this, AbstractArenaClass); - this->name = "CL"; - this->size = sizeof(ClientArenaStruct); - this->offset = offsetof(ClientArenaStruct, arenaStruct); - this->init = ClientArenaInit; - this->finish = ClientArenaFinish; - this->reserved = ClientArenaReserved; - this->extend = ClientArenaExtend; - this->alloc = ClientAlloc; - this->free = ClientFree; - this->chunkInit = ClientChunkInit; - this->chunkFinish = ClientChunkFinish; -} - - -/* mps_arena_class_cl -- return the arena class CL */ - -mps_arena_class_t mps_arena_class_cl(void) -{ - return (mps_arena_class_t)EnsureClientArenaClass(); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/arenacv.c b/mps/code/arenacv.c deleted file mode 100644 index e797116bd3d..00000000000 --- a/mps/code/arenacv.c +++ /dev/null @@ -1,464 +0,0 @@ -/* arenacv.c: ARENA COVERAGE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .coverage: At the moment, we're only trying to cover the new code - * (partial mapping of the page table and vm overflow). - * - * .note.tract-size: If the page size is divisible by sizeof(TractStruct), many - * test cases end up being essentially identical -- there just aren't that - * many different cases then. - * - * .improve.gap-below: Could test different-sized gaps below the tract - * being allocated; this requires using two adjacent zones. - */ - -#include - -#include "mpm.h" -#include "poolmv.h" -#include "testlib.h" -#include "mpsavm.h" -#include "mpsacl.h" - - -#define tractsSIZE 500 - - -/* testAllocAndIterate -- Test arena allocation and iteration - * - * .tract-seg: Test allocation and iteration, using both low-level - * tracts and higher-level segments. To do this, contrive a set of - * allocation and iteration functions which are interchangeable. - */ - -/* Type definitions for the interchangability interface */ - - -/* AllocInfo -- interchangeable info about allocated regions */ - -typedef struct AllocInfoStruct *AllocInfo; - -typedef struct AllocInfoStruct { - union { - struct { - Addr base; - Size size; - Pool pool; - } tractData; - struct { - Seg seg; - } segData; - } the; -} AllocInfoStruct; - -typedef Res (*AllocFun)(AllocInfoStruct *aiReturn, SegPref pref, - Size size, Pool pool); - -typedef void (*FreeFun)(AllocInfo ai); - -typedef Bool (*FirstFun)(AllocInfoStruct *aiReturn, Arena arena); - -typedef Bool (*NextFun)(AllocInfoStruct *nextReturn, AllocInfo ai, - Arena arena); - -typedef Count (*UnitsFun)(Count pages); - -typedef void (*TestFun)(AllocInfo ai, Arena arena); - -typedef void (*CopyFun)(AllocInfoStruct *toReturn, AllocInfo from); - - -/* AllocatorClass -- encapsulates an allocation mechanism */ - -typedef struct AllocatorClassStruct *AllocatorClass; - -typedef struct AllocatorClassStruct { - AllocFun alloc; /* allocation method */ - FreeFun free; /* deallocation method */ - FirstFun first; /* find first block for iteration */ - NextFun next; /* find next block for iteration */ - UnitsFun units; /* number of iteration objects for pages */ - TestFun test; /* consistency check a region */ - CopyFun copy; /* copy an AllocationInfo object */ -} AllocatorClassStruct; - - -/* Implementation of the tract-based interchangability interface */ - -static Res allocAsTract(AllocInfoStruct *aiReturn, SegPref pref, - Size size, Pool pool) -{ - Res res; - Addr base; - res = ArenaAlloc(&base, pref, size, pool, FALSE); - if (res == ResOK) { - aiReturn->the.tractData.base = base; - aiReturn->the.tractData.size = size; - aiReturn->the.tractData.pool = pool; - } - return res; -} - -static void freeAsTract(AllocInfo ai) -{ - ArenaFree(ai->the.tractData.base, - ai->the.tractData.size, - ai->the.tractData.pool); -} - -static Bool firstAsTract(AllocInfoStruct *aiReturn, Arena arena) -{ - Bool res; - Tract tract; - res = TractFirst(&tract, arena); - if (res) { - aiReturn->the.tractData.base = TractBase(tract); - aiReturn->the.tractData.size = ArenaAlign(arena);; - aiReturn->the.tractData.pool = TractPool(tract); - } - return res; -} - -static Bool nextAsTract(AllocInfoStruct *nextReturn, AllocInfo ai, - Arena arena) -{ - Bool res; - Tract tract; - res = TractNext(&tract, arena, ai->the.tractData.base); - if (res) { - nextReturn->the.tractData.base = TractBase(tract); - nextReturn->the.tractData.size = ArenaAlign(arena);; - nextReturn->the.tractData.pool = TractPool(tract); - } - return res; -} - -static Count unitsAsTract(Count pages) -{ - return pages; /* one tract for each page */ -} - - -static void testAsTract(AllocInfo ai, Arena arena) -{ - /* Test TractOfAddr */ - Tract tract; - Addr base; - Bool found; - - found = TractOfAddr(&tract, arena, ai->the.tractData.base); - cdie(found, "TractOfAddr"); - base = TractBase(tract); - cdie(base == ai->the.tractData.base, "base"); - -} - -static void copyAsTract(AllocInfoStruct *toReturn, AllocInfo from) -{ - toReturn->the.tractData.base = from->the.tractData.base; - toReturn->the.tractData.size = from->the.tractData.size; - toReturn->the.tractData.pool = from->the.tractData.pool; -} - -static AllocatorClassStruct allocatorTractStruct = { - allocAsTract, - freeAsTract, - firstAsTract, - nextAsTract, - unitsAsTract, - testAsTract, - copyAsTract -}; - - -/* Implementation of the segment-based interchangability interface */ - -static Res allocAsSeg(AllocInfoStruct *aiReturn, SegPref pref, - Size size, Pool pool) -{ - Res res; - Seg seg; - res = SegAlloc(&seg, SegClassGet(), pref, size, pool, FALSE); - if (res == ResOK) { - aiReturn->the.segData.seg = seg; - } - return res; -} - -static void freeAsSeg(AllocInfo ai) -{ - SegFree(ai->the.segData.seg); -} - -static Bool firstAsSeg(AllocInfoStruct *aiReturn, Arena arena) -{ - Bool res; - Seg seg; - res = SegFirst(&seg, arena); - if (res) { - aiReturn->the.segData.seg = seg; - } - return res; -} - -static Bool nextAsSeg(AllocInfoStruct *nextReturn, AllocInfo ai, - Arena arena) -{ - Bool res; - Seg seg; - res = SegNext(&seg, arena, SegBase(ai->the.segData.seg)); - if (res) { - nextReturn->the.segData.seg = seg; - } - return res; -} - -static Count unitsAsSeg(Count pages) -{ - if (0 == pages) - return 0; /* can't have a zero length seg */ - else - return 1; /* one seg no matter how many pages */ -} - -static void testAsSeg(AllocInfo ai, Arena arena) -{ - /* Test size functions */ - Seg seg = ai->the.segData.seg; - Addr base, limit; - Size size; - - UNUSED(arena); - base = SegBase(seg); - limit = SegLimit(seg); - size = SegSize(seg); - cdie(size == AddrOffset(base, limit), "size"); -} - -static void copyAsSeg(AllocInfoStruct *toReturn, AllocInfo from) -{ - toReturn->the.segData.seg = from->the.segData.seg; -} - -static AllocatorClassStruct allocatorSegStruct = { - allocAsSeg, - freeAsSeg, - firstAsSeg, - nextAsSeg, - unitsAsSeg, - testAsSeg, - copyAsSeg -}; - - -/* The main function can use either tracts or segs */ - -static void testAllocAndIterate(Arena arena, Pool pool, - Size pageSize, Count numPerPage, - AllocatorClass allocator) -{ - AllocInfoStruct offsetRegion, gapRegion, newRegion, topRegion; - SegPrefStruct pref = *SegPrefDefault(); - Count offset, gap, new; - ZoneSet zone = (ZoneSet)2; - int i; - - /* Testing the behaviour with various sizes of gaps in the page table. */ - - /* Assume the allocation strategy is first-fit. The idea of the tests is */ - /* to allocate a region of memory, then deallocate a gap in the middle, */ - /* then allocate a new region that fits in the gap with various amounts */ - /* left over. Like this: */ - /* |-offsetRegion-||----gapRegion----||-topRegion-| */ - /* |-offsetRegion-||-newRegion-| |-topRegion-| */ - /* This is done with three different sizes of offsetRegion, in two */ - /* different zones to ensure that all page boundary cases are tested. */ - for(i = 0; i < 2; ++i) { /* zone loop */ - for(offset = 0; offset <= 2*numPerPage; offset += numPerPage) { - if(offset != 0) - die(allocator->alloc(&offsetRegion, &pref, offset * pageSize, pool), - "offsetRegion"); - for(gap = numPerPage+1; gap <= 3 * (numPerPage+1); - gap += (numPerPage+1)) { - die(allocator->alloc(&gapRegion, &pref, gap * pageSize, pool), - "gapRegion"); - die(allocator->alloc(&topRegion, &pref, pageSize, pool), - "topRegion"); - allocator->free(&gapRegion); - for(new = 1; new <= gap; new += numPerPage) { - AllocInfoStruct thisRegion, nextRegion; - Count regionNum, expected; - Res enoughRegions; - - die(allocator->alloc(&newRegion, &pref, new * pageSize, pool), - "newRegion"); - - /* Test iterators */ - cdie(allocator->first(&thisRegion, arena), "first"); - regionNum = 1; - while (allocator->next(&nextRegion, &thisRegion, arena)) { - regionNum++; - allocator->copy(&thisRegion, &nextRegion); - } - - /* Should be able to iterate over at least offset, new, top */ - expected = - allocator->units(offset) + - allocator->units(new) + - allocator->units(1); - - if (regionNum >= expected) - enoughRegions = ResOK; - else - enoughRegions = ResFAIL; - - die(enoughRegions, "Not enough regions"); - - allocator->free(&newRegion); - } - - allocator->free(&topRegion); - } - if(offset != 0) { - allocator->test(&offsetRegion, arena); - allocator->free(&offsetRegion); - } - } - SegPrefExpress(&pref, SegPrefZoneSet, &zone); - } - -} - - -static void testPageTable(ArenaClass class, ...) -{ - Arena arena; Pool pool; - Size pageSize; - Count tractsPerPage; - va_list args; - - va_start(args, class); - die(ArenaCreateV(&arena, class, args), "ArenaCreate"); - va_end(args); - - die(PoolCreate(&pool, arena, PoolClassMV(), - (Size)65536, (Size)32, (Size)65536), - "PoolCreate"); - - pageSize = ArenaAlign(arena); - tractsPerPage = pageSize / sizeof(TractStruct); - printf("%ld tracts per page in the page table.\n", (long)tractsPerPage); - - /* test tract allocation and iteration */ - testAllocAndIterate(arena, pool, pageSize, tractsPerPage, - &allocatorTractStruct); - - /* test segment allocation and iteration */ - testAllocAndIterate(arena, pool, pageSize, tractsPerPage, - &allocatorSegStruct); - - PoolDestroy(pool); - ArenaDestroy(arena); -} - - -static Res makeArena(Arena *arenaOut, ArenaClass class, ...) -{ - va_list args; - Res res; - - va_start(args, class); - res = ArenaCreateV(arenaOut, class, args); - va_end(args); - return res; -} - - -/* testSize -- test arena size overflow - * - * Just try allocating larger arenas, doubling the size each time, until - * it fails, then check the error code. - */ - -static void testSize(Size size) -{ - ArenaClass class = (ArenaClass)mps_arena_class_vm(); - Arena arena; - Res res; - - do { - res = makeArena(&arena, class, size); - if (res == ResOK) - ArenaDestroy(arena); - else - die((res == ResRESOURCE) ? ResOK : res, "right error code"); - size *= 2; - } while (size == 0); -} - - -#define TEST_ARENA_SIZE ((Size)16<<22) - - -int main(void) -{ - void *block; - - testPageTable((ArenaClass)mps_arena_class_vm(), TEST_ARENA_SIZE); - testPageTable((ArenaClass)mps_arena_class_vmnz(), TEST_ARENA_SIZE); - - block = malloc(TEST_ARENA_SIZE); - cdie(block != NULL, "malloc"); - testPageTable((ArenaClass)mps_arena_class_cl(), TEST_ARENA_SIZE, - (Addr)block); - - testSize(TEST_ARENA_SIZE); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "Conclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c deleted file mode 100644 index ca2188c04b1..00000000000 --- a/mps/code/arenavm.c +++ /dev/null @@ -1,1856 +0,0 @@ -/* arenavm.c: VIRTUAL MEMORY ARENA CLASS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * - * DESIGN - * - * .design: See , and - * - * .vm.addr-is-star: In this file, Addr is compatible with C - * pointers, and Count with size_t (Index), because all refer to the - * virtual address space. - * - * - * IMPROVEMENTS - * - * .improve.table.zone-zero: It would be better to make sure that the - * page tables are in zone zero, since that zone is least useful for - * GC. (But it would change how pagesFindFreeInZones avoids allocating - * over the tables, see .alloc.skip.) - */ - -#include "boot.h" -#include "tract.h" -#include "bt.h" -#include "mpm.h" -#include "mpsavm.h" - -SRCID(arenavm, "$Id$"); - - -/* @@@@ Arbitrary calculation for the maximum number of distinct */ -/* object sets for generations. Should be in config.h. */ -/* .gencount.const: Must be a constant suitable for use as an */ -/* array size. */ -#define VMArenaGenCount ((Count)(MPS_WORD_WIDTH/2)) - -/* VMChunk -- chunks for VM arenas */ - -typedef struct VMChunkStruct *VMChunk; - -#define VMChunkSig ((Sig)0x519A6B3C) /* SIGnature ARena VM Chunk */ - -typedef struct VMChunkStruct { - ChunkStruct chunkStruct; /* generic chunk */ - VM vm; /* virtual memory handle */ - Addr overheadMappedLimit; /* limit of pages mapped for overhead */ - BT pageTableMapped; /* indicates mapped state of page table */ - BT noSparePages; /* 1 bit per page of pageTable */ - Sig sig; /* */ -} VMChunkStruct; - -#define VMChunk2Chunk(vmchunk) (&(vmchunk)->chunkStruct) -#define Chunk2VMChunk(chunk) PARENT(VMChunkStruct, chunkStruct, chunk) - - -/* VMChunkVMArena -- get the VM arena from a VM chunk */ - -#define VMChunkVMArena(vmchunk) \ - Arena2VMArena(ChunkArena(VMChunk2Chunk(vmchunk))) - - -/* VMArena - * - * See for description. - */ - -typedef struct VMArenaStruct *VMArena; - -#define VMArenaSig ((Sig)0x519A6EB3) /* SIGnature AREna VM */ - -typedef struct VMArenaStruct { /* VM arena structure */ - ArenaStruct arenaStruct; - VM vm; /* VM where the arena itself is stored */ - Size spareSize; /* total size of spare pages */ - ZoneSet blacklist; /* zones to use last */ - ZoneSet genZoneSet[VMArenaGenCount]; /* .gencount.const */ - ZoneSet freeSet; /* unassigned zones */ - Size extendBy; /* desired arena increment */ - Size extendMin; /* minimum arena increment */ - Sig sig; /* */ -} VMArenaStruct; - -#define Arena2VMArena(arena) PARENT(VMArenaStruct, arenaStruct, arena) -#define VMArena2Arena(vmarena) (&(vmarena)->arenaStruct) - - -/* Forward declarations */ - -static void sparePagesPurge(VMArena vmArena); -static ArenaClass VMArenaClassGet(void); -static ArenaClass VMNZArenaClassGet(void); -static void VMCompact(Arena arena, Trace trace); - - -/* VMChunkCheck -- check the consistency of a VM chunk */ - -static Bool VMChunkCheck(VMChunk vmchunk) -{ - Chunk chunk; - - CHECKS(VMChunk, vmchunk); - chunk = VMChunk2Chunk(vmchunk); - CHECKL(ChunkCheck(chunk)); - CHECKL(VMCheck(vmchunk->vm)); - CHECKL(VMAlign(vmchunk->vm) == ChunkPageSize(chunk)); - CHECKL(vmchunk->overheadMappedLimit <= (Addr)chunk->pageTable); - /* check pageTableMapped table */ - CHECKL(vmchunk->pageTableMapped != NULL); - CHECKL((Addr)vmchunk->pageTableMapped >= chunk->base); - CHECKL(AddrAdd((Addr)vmchunk->pageTableMapped, BTSize(chunk->pageTablePages)) - <= vmchunk->overheadMappedLimit); - /* check noSparePages table */ - CHECKL(vmchunk->noSparePages != NULL); - CHECKL((Addr)vmchunk->noSparePages >= chunk->base); - CHECKL(AddrAdd((Addr)vmchunk->noSparePages, BTSize(chunk->pageTablePages)) - <= vmchunk->overheadMappedLimit); - /* .improve.check-table: Could check the consistency of the tables. */ - return TRUE; -} - - -/* addrOfPageDesc -- address of the page descriptor (as an Addr) */ - -#define addrOfPageDesc(chunk, index) \ - ((Addr)&(chunk)->pageTable[index]) - - -/* PageTablePageIndex - * - * Maps from a page base address for a page occupied by the page table - * to the index of that page in the range of pages occupied by the - * page table. So that - * PageTablePageIndex(chunk, (Addr)chunk->pageTable) == 0 - * and - * PageTablePageIndex(chunk, - * AddrAlignUp(addrOfPageDesc(chunk->pages), pageSize) - * == chunk->pageTablePages - */ -#define PageTablePageIndex(chunk, pageAddr) \ - ChunkSizeToPages(chunk, AddrOffset((Addr)(chunk)->pageTable, pageAddr)) - - -/* TablePageIndexBase - * - * Takes a page table page index (i.e., the index of a page occupied - * by the page table, where the page occupied by chunk->pageTable is - * index 0) and returns the base address of that page. - * (Reverse of mapping defined by PageTablePageIndex.) - */ -#define TablePageIndexBase(chunk, index) \ - AddrAdd((Addr)(chunk)->pageTable, ChunkPagesToSize(chunk, index)) - - -/* pageIsSpare -- is page spare (free and mapped)? */ - -#define pageIsSpare(page) \ - ((page)->the.rest.pool == NULL && (page)->the.rest.type == PageTypeSpare) - - -/* VMArenaCheck -- check the consistency of an arena structure */ - -static Bool VMArenaCheck(VMArena vmArena) -{ - Index gen; - ZoneSet allocSet; - Arena arena; - VMChunk primary; - - CHECKS(VMArena, vmArena); - arena = VMArena2Arena(vmArena); - CHECKD(Arena, arena); - /* spare pages are committed, so must be less spare than committed. */ - CHECKL(vmArena->spareSize <= arena->committed); - CHECKL(vmArena->blacklist != ZoneSetUNIV); - - allocSet = ZoneSetEMPTY; - for(gen = (Index)0; gen < VMArenaGenCount; ++gen) { - allocSet = ZoneSetUnion(allocSet, vmArena->genZoneSet[gen]); - } - CHECKL(ZoneSetInter(allocSet, vmArena->freeSet) == ZoneSetEMPTY); - CHECKL(vmArena->extendBy > 0); - CHECKL(vmArena->extendMin <= vmArena->extendBy); - - if (arena->primary != NULL) { - primary = Chunk2VMChunk(arena->primary); - CHECKD(VMChunk, primary); - /* We could iterate over all chunks accumulating an accurate */ - /* count of committed, but we don't have all day. */ - CHECKL(VMMapped(primary->vm) <= arena->committed); - } - return TRUE; -} - - -/* VMArenaDescribe -- describe the VMArena - */ -static Res VMArenaDescribe(Arena arena, mps_lib_FILE *stream) -{ - Res res; - VMArena vmArena; - Index gen; - - if (!TESTT(Arena, arena)) return ResFAIL; - if (stream == NULL) return ResFAIL; - vmArena = Arena2VMArena(arena); - if (!TESTT(VMArena, vmArena)) return ResFAIL; - - /* Describe the superclass fields first via next-method call */ - /* ...but the next method is ArenaTrivDescribe, so don't call it; - * see impl.c.arena#describe.triv.dont-upcall. - * - super = ARENA_SUPERCLASS(VMArenaClass); - res = super->describe(arena, stream); - if (res != ResOK) return res; - * - */ - - for(gen = (Index)0; gen < VMArenaGenCount; gen++) { - if(vmArena->genZoneSet[gen] != ZoneSetEMPTY) { - res = WriteF(stream, - " genZoneSet[$U]: $B\n", - (WriteFU)gen, (WriteFB)vmArena->genZoneSet[gen], - NULL); - if(res != ResOK) - return res; - } - } - - res = WriteF(stream, - " freeSet: $B\n", (WriteFB)vmArena->freeSet, - " blacklist: $B\n", (WriteFB)vmArena->blacklist, - NULL); - if(res != ResOK) - return res; - - /* (incomplete: some fields are not Described) */ - - return ResOK; -} - - - -/* VM indirect functions - * - * These functions should be used to map and unmap within the arena. - * They are responsible for maintaining vmArena->committed, and for - * checking that the commit limit does not get exceeded. - */ -static Res vmArenaMap(VMArena vmArena, VM vm, Addr base, Addr limit) -{ - Arena arena; - Size size; - Res res; - - /* no checking as function is local to module */ - - arena = VMArena2Arena(vmArena); - size = AddrOffset(base, limit); - /* committed can't overflow (since we can't commit more memory than */ - /* address space), but we're paranoid. */ - AVER(arena->committed < arena->committed + size); - /* check against commit limit */ - if (arena->commitLimit < arena->committed + size) - return ResCOMMIT_LIMIT; - - res = VMMap(vm, base, limit); - if (res != ResOK) - return res; - arena->committed += size; - return ResOK; -} - - -static void vmArenaUnmap(VMArena vmArena, VM vm, Addr base, Addr limit) -{ - Arena arena; - Size size; - - /* no checking as function is local to module */ - - arena = VMArena2Arena(vmArena); - size = AddrOffset(base, limit); - AVER(size <= arena->committed); - - VMUnmap(vm, base, limit); - arena->committed -= size; - return; -} - - -/* VMChunkCreate -- create a chunk - * - * chunkReturn, return parameter for the created chunk. - * vmArena, the parent VMArena. - * size, approximate amount of virtual address that the chunk should reserve. - */ -static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size) -{ - Res res; - Addr base, limit, chunkStructLimit; - Align pageSize; - VM vm; - BootBlockStruct bootStruct; - BootBlock boot = &bootStruct; - VMChunk vmChunk; - void *p; - - AVER(chunkReturn != NULL); - AVERT(VMArena, vmArena); - AVER(size > 0); - - res = VMCreate(&vm, size); - if (res != ResOK) - goto failVMCreate; - - pageSize = VMAlign(vm); - /* The VM will have aligned the userSize; pick up the actual size. */ - base = VMBase(vm); - limit = VMLimit(vm); - - res = BootBlockInit(boot, (void *)base, (void *)limit); - if (res != ResOK) - goto failBootInit; - - /* Allocate and map the descriptor. */ - /* See .@@@@ */ - res = BootAlloc(&p, boot, sizeof(VMChunkStruct), MPS_PF_ALIGN); - if (res != ResOK) - goto failChunkAlloc; - vmChunk = p; - /* Calculate the limit of the page where the chunkStruct resides. */ - chunkStructLimit = AddrAlignUp((Addr)(vmChunk + 1), pageSize); - res = vmArenaMap(vmArena, vm, base, chunkStructLimit); - if (res != ResOK) - goto failChunkMap; - vmChunk->overheadMappedLimit = chunkStructLimit; - - vmChunk->vm = vm; - res = ChunkInit(VMChunk2Chunk(vmChunk), VMArena2Arena(vmArena), - base, limit, pageSize, boot); - if (res != ResOK) - goto failChunkInit; - - BootBlockFinish(boot); - - vmChunk->sig = VMChunkSig; - AVERT(VMChunk, vmChunk); - *chunkReturn = VMChunk2Chunk(vmChunk); - return ResOK; - -failChunkInit: - /* No need to unmap, as we're destroying the VM. */ -failChunkMap: -failChunkAlloc: -failBootInit: - VMDestroy(vm); -failVMCreate: - return res; -} - - -/* VMChunkInit -- initialize a VMChunk */ - -static Res VMChunkInit(Chunk chunk, BootBlock boot) -{ - size_t btSize; - VMChunk vmChunk; - Addr overheadLimit; - void *p; - Res res; - - /* chunk is supposed to be uninitialized, so don't check it. */ - vmChunk = Chunk2VMChunk(chunk); - AVERT(BootBlock, boot); - - btSize = (size_t)BTSize(chunk->pageTablePages); - res = BootAlloc(&p, boot, btSize, MPS_PF_ALIGN); - if (res != ResOK) - goto failPageTableMapped; - vmChunk->pageTableMapped = p; - res = BootAlloc(&p, boot, btSize, MPS_PF_ALIGN); - if (res != ResOK) - goto failnoSparePages; - vmChunk->noSparePages = p; - - /* Actually commit all the tables. .@@@@ */ - overheadLimit = AddrAdd(chunk->base, (Size)BootAllocated(boot)); - if (vmChunk->overheadMappedLimit < overheadLimit) { - overheadLimit = AddrAlignUp(overheadLimit, ChunkPageSize(chunk)); - res = vmArenaMap(VMChunkVMArena(vmChunk), vmChunk->vm, - vmChunk->overheadMappedLimit, overheadLimit); - if (res != ResOK) - goto failTableMap; - vmChunk->overheadMappedLimit = overheadLimit; - } - - BTResRange(vmChunk->pageTableMapped, 0, chunk->pageTablePages); - BTSetRange(vmChunk->noSparePages, 0, chunk->pageTablePages); - return ResOK; - - /* .no-clean: No clean-ups needed for boot, as we will discard the chunk. */ -failTableMap: -failnoSparePages: -failPageTableMapped: - return res; -} - - -/* vmChunkDestroy -- destroy a VMChunk */ - -static void vmChunkDestroy(Chunk chunk) -{ - VM vm; - VMChunk vmChunk; - - AVERT(Chunk, chunk); - vmChunk = Chunk2VMChunk(chunk); - AVERT(VMChunk, vmChunk); - AVER(BTIsSetRange(vmChunk->noSparePages, 0, chunk->pageTablePages)); - AVER(BTIsResRange(vmChunk->pageTableMapped, 0, chunk->pageTablePages)); - - vmChunk->sig = SigInvalid; - vm = vmChunk->vm; - ChunkFinish(chunk); - VMDestroy(vm); -} - - -/* VMChunkFinish -- finish a VMChunk */ - -static void VMChunkFinish(Chunk chunk) -{ - VMChunk vmChunk = Chunk2VMChunk(chunk); - - vmArenaUnmap(VMChunkVMArena(vmChunk), vmChunk->vm, - VMBase(vmChunk->vm), vmChunk->overheadMappedLimit); - /* No point in finishing the other fields, since they are unmapped. */ -} - - -/* VMArenaInit -- create and initialize the VM arena - * - * .arena.init: Once the arena has been allocated, we call ArenaInit - * to do the generic part of init. - */ -static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, va_list args) -{ - Size userSize; /* size requested by user */ - Size chunkSize; /* size actually created */ - Size vmArenaSize; /* aligned size of VMArenaStruct */ - Res res; - VMArena vmArena; - Arena arena; - Index gen; - VM arenaVM; - Chunk chunk; - - userSize = va_arg(args, Size); - AVER(arenaReturn != NULL); - AVER(class == VMArenaClassGet() || class == VMNZArenaClassGet()); - AVER(userSize > 0); - - /* Create a VM to hold the arena and map it. */ - vmArenaSize = SizeAlignUp(sizeof(VMArenaStruct), MPS_PF_ALIGN); - res = VMCreate(&arenaVM, vmArenaSize); - if (res != ResOK) - goto failVMCreate; - res = VMMap(arenaVM, VMBase(arenaVM), VMLimit(arenaVM)); - if (res != ResOK) - goto failVMMap; - vmArena = (VMArena)VMBase(arenaVM); - - arena = VMArena2Arena(vmArena); - /* */ - res = ArenaInit(arena, class); - if (res != ResOK) - goto failArenaInit; - arena->committed = VMMapped(arenaVM); - - vmArena->vm = arenaVM; - vmArena->spareSize = 0; - - /* .blacklist: We blacklist the zones that could be referenced by small - integers misinterpreted as references. This isn't a perfect simulation, - but it should catch the common cases. */ - { - union { - mps_word_t word; - mps_addr_t addr; - int i; - long l; - } nono; - vmArena->blacklist = ZoneSetEMPTY; - nono.word = 0; - nono.i = 1; - vmArena->blacklist = ZoneSetAdd(arena, vmArena->blacklist, nono.addr); - nono.i = -1; - vmArena->blacklist = ZoneSetAdd(arena, vmArena->blacklist, nono.addr); - nono.l = 1; - vmArena->blacklist = ZoneSetAdd(arena, vmArena->blacklist, nono.addr); - nono.l = -1; - vmArena->blacklist = ZoneSetAdd(arena, vmArena->blacklist, nono.addr); - } - - for(gen = (Index)0; gen < VMArenaGenCount; gen++) { - vmArena->genZoneSet[gen] = ZoneSetEMPTY; - } - vmArena->freeSet = ZoneSetUNIV; /* includes blacklist */ - /* */ - vmArena->extendBy = userSize; - vmArena->extendMin = 0; - - /* have to have a valid arena before calling ChunkCreate */ - vmArena->sig = VMArenaSig; - res = VMChunkCreate(&chunk, vmArena, userSize); - if (res != ResOK) - goto failChunkCreate; - arena->primary = chunk; - - /* .zoneshift: Set the zone shift to divide the chunk into the same */ - /* number of stripes as will fit into a reference set (the number of */ - /* bits in a word). Fail if the chunk is so small stripes are smaller */ - /* than pages. Note that some zones are discontiguous in the chunk if */ - /* the size is not a power of 2. See . */ - chunkSize = AddrOffset(chunk->base, chunk->limit); - arena->zoneShift = SizeFloorLog2(chunkSize >> MPS_WORD_SHIFT); - - AVERT(VMArena, vmArena); - if ((ArenaClass)mps_arena_class_vm() == class) - EVENT3(ArenaCreateVM, arena, userSize, chunkSize); - else - EVENT3(ArenaCreateVMNZ, arena, userSize, chunkSize); - *arenaReturn = arena; - return ResOK; - -failChunkCreate: - ArenaFinish(arena); -failArenaInit: - VMUnmap(arenaVM, VMBase(arenaVM), VMLimit(arenaVM)); -failVMMap: - VMDestroy(arenaVM); -failVMCreate: - return res; -} - - -/* VMArenaFinish -- finish the arena */ - -static void VMArenaFinish(Arena arena) -{ - VMArena vmArena; - Ring node, next; - VM arenaVM; - - vmArena = Arena2VMArena(arena); - AVERT(VMArena, vmArena); - arenaVM = vmArena->vm; - - sparePagesPurge(vmArena); - /* destroy all chunks, including the primary */ - arena->primary = NULL; - RING_FOR(node, &arena->chunkRing, next) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - vmChunkDestroy(chunk); - } - AVER(arena->committed == VMMapped(arenaVM)); - - vmArena->sig = SigInvalid; - - ArenaFinish(arena); /* */ - - VMUnmap(arenaVM, VMBase(arenaVM), VMLimit(arenaVM)); - VMDestroy(arenaVM); - EVENT1(ArenaDestroy, vmArena); -} - - -/* VMArenaReserved -- return the amount of reserved address space - * - * Add up the reserved space from all the chunks. - */ -static Size VMArenaReserved(Arena arena) -{ - Size reserved; - Ring node, next; - - reserved = 0; - RING_FOR(node, &arena->chunkRing, next) { - VMChunk vmChunk = Chunk2VMChunk(RING_ELT(Chunk, chunkRing, node)); - reserved += VMReserved(vmChunk->vm); - } - return reserved; -} - - -/* VMArenaSpareCommitExceeded -- handle excess spare pages */ - -static void VMArenaSpareCommitExceeded(Arena arena) -{ - VMArena vmArena; - - vmArena = Arena2VMArena(arena); - AVERT(VMArena, vmArena); - - sparePagesPurge(vmArena); - return; -} - - -/* Page Table Partial Mapping - * - * Some helper functions - */ - - -/* tablePageBaseIndex -- index of the first page descriptor falling - * (at least partially) on this table page - * - * .repr.table-page: Table pages are passed as the page's base address. - * - * .division: We calculate it by dividing the offset from the beginning - * of the page table by the size of a table element. This relies on - * .vm.addr-is-star. - */ -#define tablePageBaseIndex(chunk, tablePage) \ - (AddrOffset((Addr)(chunk)->pageTable, (tablePage)) \ - / sizeof(PageStruct)) - - -/* tablePageWholeBaseIndex - * - * Index of the first page descriptor wholly on this table page. - * Table page specified by address (not index). - */ -#define tablePageWholeBaseIndex(chunk, tablePage) \ - (AddrOffset((Addr)(chunk)->pageTable, \ - AddrAdd((tablePage), sizeof(PageStruct)-1)) \ - / sizeof(PageStruct)) - - -/* tablePageLimitIndex -- index of the first page descriptor falling - * (wholly) on the next table page - * - * Similar to tablePageBaseIndex, see .repr.table-page and .division. - */ -#define tablePageLimitIndex(chunk, tablePage) \ - ((AddrOffset((Addr)(chunk)->pageTable, (tablePage)) \ - + ChunkPageSize(chunk) - 1) \ - / sizeof(PageStruct) \ - + 1) - -/* tablePageWholeLimitIndex - * - * Index of the first page descriptor falling partially on the next - * table page. - */ -#define tablePageWholeLimitIndex(chunk, tablePage) \ - ((AddrOffset((Addr)(chunk)->pageTable, (tablePage)) \ - + ChunkPageSize(chunk)) \ - / sizeof(PageStruct)) - - -/* tablePageInUse -- Check whether a given page of the page table is in use - * - * Returns TRUE if and only if the table page given is in use, i.e., if - * any of the page descriptors falling on it (even partially) are being - * used. Relies on .repr.table-page and .vm.addr-is-star. - * - * .improve.limits: We don't need to check the parts we're (de)allocating. - */ -static Bool tablePageInUse(Chunk chunk, Addr tablePage) -{ - Index limitIndex; - - /* Check it's in the page table. */ - AVER((Addr)&chunk->pageTable[0] <= tablePage); - AVER(tablePage < addrOfPageDesc(chunk, chunk->pages)); - - if (tablePage == AddrPageBase(chunk, addrOfPageDesc(chunk, chunk->pages))) { - limitIndex = chunk->pages; - } else { - limitIndex = tablePageLimitIndex(chunk, tablePage); - } - AVER(limitIndex <= chunk->pages); - - return !BTIsResRange(chunk->allocTable, - tablePageBaseIndex(chunk, tablePage), limitIndex); -} - - -/* tablePagesUsed - * - * Takes a range of pages identified by [pageBase, pageLimit), and - * returns the pages occupied by the page table which store the - * PageStruct descriptors for those pages. - */ -static void tablePagesUsed(Index *tableBaseReturn, Index *tableLimitReturn, - Chunk chunk, Index pageBase, Index pageLimit) -{ - *tableBaseReturn = - PageTablePageIndex(chunk, - AddrPageBase(chunk, addrOfPageDesc(chunk, pageBase))); - *tableLimitReturn = - PageTablePageIndex(chunk, - AddrAlignUp(addrOfPageDesc(chunk, pageLimit), - ChunkPageSize(chunk))); - return; -} - - -/* tablePagesEnsureMapped -- ensure needed part of page table is mapped - * - * Pages from baseIndex to limitIndex are about to be allocated. - * Ensure that the relevant pages occupied by the page table are mapped. - */ -static Res tablePagesEnsureMapped(VMChunk vmChunk, - Index baseIndex, Index limitIndex) -{ - /* tableBaseIndex, tableLimitIndex, tableCursorIndex, */ - /* unmappedBase, unmappedLimit are all indexes of pages occupied */ - /* by the page table. */ - Index tableBaseIndex, tableLimitIndex; - Index tableCursorIndex; - Index unmappedBaseIndex, unmappedLimitIndex; - Index i; - Chunk chunk; - Res res; - - chunk = VMChunk2Chunk(vmChunk); - - tablePagesUsed(&tableBaseIndex, &tableLimitIndex, - chunk, baseIndex, limitIndex); - - tableCursorIndex = tableBaseIndex; - - while(BTFindLongResRange(&unmappedBaseIndex, &unmappedLimitIndex, - vmChunk->pageTableMapped, - tableCursorIndex, tableLimitIndex, - 1)) { - Addr unmappedBase = TablePageIndexBase(chunk, unmappedBaseIndex); - Addr unmappedLimit = TablePageIndexBase(chunk, unmappedLimitIndex); - /* There might be a page descriptor overlapping the beginning */ - /* of the range of table pages we are about to map. */ - /* We need to work out whether we should touch it. */ - if (unmappedBaseIndex == tableBaseIndex - && unmappedBaseIndex > 0 - && !BTGet(vmChunk->pageTableMapped, unmappedBaseIndex - 1)) { - /* Start with first descriptor wholly on page */ - baseIndex = tablePageWholeBaseIndex(chunk, unmappedBase); - } else { - /* start with first descriptor partially on page */ - baseIndex = tablePageBaseIndex(chunk, unmappedBase); - } - /* Similarly for the potentially overlapping page descriptor */ - /* at the end. */ - if (unmappedLimitIndex == tableLimitIndex - && unmappedLimitIndex < chunk->pageTablePages - && !BTGet(vmChunk->pageTableMapped, unmappedLimitIndex)) { - /* Finish with last descriptor wholly on page */ - limitIndex = tablePageBaseIndex(chunk, unmappedLimit); - } else if (unmappedLimitIndex == chunk->pageTablePages) { - /* Finish with last descriptor in chunk */ - limitIndex = chunk->pages; - } else { - /* Finish with last descriptor partially on page */ - limitIndex = tablePageWholeBaseIndex(chunk, unmappedLimit); - } - res = vmArenaMap(VMChunkVMArena(vmChunk), - vmChunk->vm, unmappedBase, unmappedLimit); - if (res != ResOK) - return res; - BTSetRange(vmChunk->pageTableMapped, unmappedBaseIndex, unmappedLimitIndex); - for(i = baseIndex; i < limitIndex; ++i) { - PageInit(chunk, i); - } - tableCursorIndex = unmappedLimitIndex; - if (tableCursorIndex == tableLimitIndex) - break; - } - - return ResOK; -} - - -/* tablePagesUnmapUnused - * - * Of the pages occupied by the page table from tablePageBase to - * tablePageLimit find those which are wholly unused and unmap them. - */ -static void tablePagesUnmapUnused(VMChunk vmChunk, - Addr tablePageBase, Addr tablePageLimit) -{ - Chunk chunk; - Addr cursor; - Size pageSize; - - chunk = VMChunk2Chunk(vmChunk); - pageSize = ChunkPageSize(chunk); - AVER(AddrIsAligned(tablePageBase, pageSize)); - AVER(AddrIsAligned(tablePageLimit, pageSize)); - - /* for loop indexes over base addresses of pages occupied by page table */ - for(cursor = tablePageBase; - cursor < tablePageLimit; - cursor = AddrAdd(cursor, pageSize)) { - if (!tablePageInUse(chunk, cursor)) { - vmArenaUnmap(VMChunkVMArena(vmChunk), vmChunk->vm, - cursor, AddrAdd(cursor, pageSize)); - AVER(BTGet(vmChunk->noSparePages, PageTablePageIndex(chunk, cursor))); - AVER(BTGet(vmChunk->pageTableMapped, PageTablePageIndex(chunk, cursor))); - BTRes(vmChunk->pageTableMapped, PageTablePageIndex(chunk, cursor)); - } - } - AVER(cursor == tablePageLimit); - - return; -} - - -/* pagesFindFreeInArea -- find a range of free pages in a given address range - * - * Search for a free run of pages in the free table, between the given - * base and limit. - * - * The downwards arg governs whether we use BTFindShortResRange (if - * downwards is FALSE) or BTFindShortResRangeHigh (if downwards is - * TRUE). This _roughly_ corresponds to allocating pages from top down - * (when downwards is TRUE), at least within an interval. It is used - * for implementing SegPrefHigh. - */ -static Bool pagesFindFreeInArea(Index *baseReturn, Chunk chunk, Size size, - Addr base, Addr limit, Bool downwards) -{ - Word pages; /* number of pages equiv. to size */ - Index basePage, limitPage; /* Index equiv. to base and limit */ - Index start, end; /* base and limit of free run */ - - AVER(AddrIsAligned(base, ChunkPageSize(chunk))); - AVER(AddrIsAligned(limit, ChunkPageSize(chunk))); - AVER(chunk->base <= base); - AVER(base < limit); - AVER(limit <= chunk->limit); - AVER(size <= AddrOffset(base, limit)); - AVER(size > (Size)0); - AVER(SizeIsAligned(size, ChunkPageSize(chunk))); - - basePage = INDEX_OF_ADDR(chunk, base); - limitPage = INDEX_OF_ADDR(chunk, limit); - pages = ChunkSizeToPages(chunk, size); - - if (downwards) { - if (!BTFindShortResRangeHigh(&start, &end, chunk->allocTable, - basePage, limitPage, pages)) - return FALSE; - } else { - if(!BTFindShortResRange(&start, &end, chunk->allocTable, - basePage, limitPage, pages)) - return FALSE; - } - - *baseReturn = start; - return TRUE; -} - - -/* pagesFindFreeInZones -- find a range of free pages with a ZoneSet - * - * This function finds the intersection of ZoneSet and the set of free - * pages and tries to find a free run of pages in the resulting set of - * areas. - * - * In other words, it finds space for a page whose ZoneSet (see - * ZoneSetOfPage) will be a subset of the specified ZoneSet. - * - * For meaning of downwards arg see pagesFindFreeInArea. - * .improve.findfree.downwards: This should be improved so that it - * allocates pages from top down globally, as opposed to (currently) - * just within an interval. - */ -static Bool pagesFindFreeInZones(Index *baseReturn, VMChunk *chunkReturn, - VMArena vmArena, Size size, ZoneSet zones, - Bool downwards) -{ - Arena arena; - Addr chunkBase, base, limit; - Size zoneSize; - Ring node, next; - - arena = VMArena2Arena(vmArena); - zoneSize = (Size)1 << arena->zoneShift; - - /* Should we check chunk cache first? */ - RING_FOR(node, &arena->chunkRing, next) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - AVERT(Chunk, chunk); - - /* .alloc.skip: The first address available for arena allocation, */ - /* is just after the arena tables. */ - chunkBase = PageIndexBase(chunk, chunk->allocBase); - - base = chunkBase; - while(base < chunk->limit) { - if (ZoneSetIsMember(arena, zones, base)) { - /* Search for a run of zone stripes which are in the ZoneSet */ - /* and the arena. Adding the zoneSize might wrap round (to */ - /* zero, because limit is aligned to zoneSize, which is a */ - /* power of two). */ - limit = base; - do { - /* advance limit to next higher zone stripe boundary */ - limit = AddrAlignUp(AddrAdd(limit, 1), zoneSize); - - AVER(limit > base || limit == (Addr)0); - - if (limit >= chunk->limit || limit < base) { - limit = chunk->limit; - break; - } - - AVER(base < limit); - AVER(limit < chunk->limit); - } while(ZoneSetIsMember(arena, zones, limit)); - - /* If the ZoneSet was universal, then the area found ought to */ - /* be the whole chunk. */ - AVER(zones != ZoneSetUNIV - || (base == chunkBase && limit == chunk->limit)); - - /* Try to allocate a page in the area. */ - if (AddrOffset(base, limit) >= size - && pagesFindFreeInArea(baseReturn, chunk, size, base, limit, - downwards)) { - *chunkReturn = Chunk2VMChunk(chunk); - return TRUE; - } - - base = limit; - } else { - /* Adding the zoneSize might wrap round (to zero, because */ - /* base is aligned to zoneSize, which is a power of two). */ - base = AddrAlignUp(AddrAdd(base, 1), zoneSize); - AVER(base > chunkBase || base == (Addr)0); - if (base >= chunk->limit || base < chunkBase) { - base = chunk->limit; - break; - } - } - } - - AVER(base == chunk->limit); - } - - return FALSE; -} - - -/* vmGenOfSegPref -- return generation specified by a segment preference */ - -static Serial vmGenOfSegPref(VMArena vmArena, SegPref pref) -{ - Serial gen; - - AVER(pref->isGen); - UNUSED(vmArena); - - gen = pref->gen; - if (gen >= VMArenaGenCount) { - gen = VMArenaGenCount - 1; - } - return gen; -} - - -/* pagesFindFreeWithSegPref -- find a range of free pages with given preferences - * - * Note this does not create or allocate any pages. - * - * basereturn: return parameter for the index in the - * chunk's page table of the base of the free area found. - * chunkreturn: return parameter for the chunk in which - * the free space has been found. - * pref: the SegPref object to be used when considering - * which zones to try. - * size: Size to find space for. - * barge: TRUE iff stealing space in zones used - * by other SegPrefs should be considered (if it's FALSE then only - * zones already used by this segpref or free zones will be used). - */ -static Bool pagesFindFreeWithSegPref(Index *baseReturn, VMChunk *chunkReturn, - VMArena vmArena, SegPref pref, Size size, - Bool barge) -{ - ZoneSet preferred; - - if (pref->isGen) { - Serial gen = vmGenOfSegPref(vmArena, pref); - preferred = vmArena->genZoneSet[gen]; - } else { - preferred = pref->zones; - } - - /* @@@@ Some of these tests might be duplicates. If we're about */ - /* to run out of virtual address space, then slow allocation is */ - /* probably the least of our worries. */ - - /* .alloc.improve.map: Define a function that takes a list */ - /* (say 4 long) of ZoneSets and tries pagesFindFreeInZones on */ - /* each one in turn. Extra ZoneSet args that weren't needed */ - /* could be ZoneSetEMPTY */ - - if (pref->isCollected) { /* GC'd memory */ - /* We look for space in the following places (in order) */ - /* - Zones already allocated to me (preferred) but are not */ - /* blacklisted; */ - /* - Zones that are either allocated to me, or are unallocated */ - /* but not blacklisted; */ - /* - Any non-blacklisted zone; */ - /* - Any zone; */ - /* Note that each is a superset of the previous, unless */ - /* blacklisted zones have been allocated (or the default */ - /* is used). */ - if (pagesFindFreeInZones(baseReturn, chunkReturn, vmArena, size, - ZoneSetDiff(preferred, vmArena->blacklist), - pref->high) - || pagesFindFreeInZones(baseReturn, chunkReturn, vmArena, size, - ZoneSetUnion(preferred, - ZoneSetDiff(vmArena->freeSet, - vmArena->blacklist)), - pref->high)) { - return TRUE; /* found */ - } - if (!barge) - /* do not barge into other zones, give up now */ - return FALSE; - if (pagesFindFreeInZones(baseReturn, chunkReturn, vmArena, size, - ZoneSetDiff(ZoneSetUNIV, vmArena->blacklist), - pref->high) - || pagesFindFreeInZones(baseReturn, chunkReturn, vmArena, size, - ZoneSetUNIV, pref->high)) { - return TRUE; /* found */ - } - } else { /* non-GC'd memory */ - /* We look for space in the following places (in order) */ - /* - Zones preferred (preferred) and blacklisted; */ - /* - Zones preferred; */ - /* - Zones preferred or blacklisted zone; */ - /* - Any zone. */ - /* Note that each is a superset of the previous, unless */ - /* blacklisted zones have been allocated. */ - if (pagesFindFreeInZones(baseReturn, chunkReturn, vmArena, size, - ZoneSetInter(preferred, vmArena->blacklist), - pref->high) - || pagesFindFreeInZones(baseReturn, chunkReturn, vmArena, size, - preferred, pref->high) - || pagesFindFreeInZones(baseReturn, chunkReturn, vmArena, size, - ZoneSetUnion(preferred, vmArena->blacklist), - pref->high) - || pagesFindFreeInZones(baseReturn, chunkReturn, vmArena, size, - ZoneSetUNIV, pref->high)) { - return TRUE; - } - } - return FALSE; -} - - -/* vmArenaExtend -- Extend the arena by making a new chunk - * - * The size arg specifies how much we wish to allocate after the extension. - */ -static Res vmArenaExtend(VMArena vmArena, Size size) -{ - Chunk newChunk; - Size chunkSize; - Res res; - - /* Choose chunk size. */ - /* .vmchunk.overhead: This code still lacks a proper estimate of */ - /* the overhead required by a vmChunk for chunkStruct, page tables */ - /* etc. For now, estimate it as 10%. RHSK 2007-12-21 */ - do { - Size fraction = 10; /* 10% -- see .vmchunk.overhead */ - Size chunkOverhead; - - /* 1: use extendBy, if it is big enough for size + overhead */ - chunkSize = vmArena->extendBy; - chunkOverhead = chunkSize / fraction; - if(chunkSize > size && (chunkSize - size) >= chunkOverhead) - break; - - /* 2: use size + overhead (unless it overflows SizeMAX) */ - chunkOverhead = size / (fraction - 1); - if((SizeMAX - size) >= chunkOverhead) { - chunkSize = size + chunkOverhead; - break; - } - - /* 3: use SizeMAX */ - chunkSize = SizeMAX; - break; - } while(0); - - EVENT3(vmArenaExtendStart, size, chunkSize, - VMArenaReserved(VMArena2Arena(vmArena))); - DIAG_SINGLEF(( "vmArenaExtend_Start", - "to accommodate size $W, try chunkSize $W", (WriteFW)size, (WriteFW)chunkSize, - " (VMArenaReserved currently $W bytes)\n", - (WriteFW)VMArenaReserved(VMArena2Arena(vmArena)), - NULL )); - - /* .chunk-create.fail: If we fail, try again with a smaller size */ - { - unsigned fidelity = 8; /* max fraction of addr-space we may 'waste' */ - Size chunkHalf; - Size chunkMin = 4 * 1024; /* typical single page */ - Size sliceSize; - - if (vmArena->extendMin > chunkMin) - chunkMin = vmArena->extendMin; - if (chunkSize < chunkMin) - chunkSize = chunkMin; - - for(;; chunkSize = chunkHalf) { - chunkHalf = chunkSize / 2; - sliceSize = chunkHalf / fidelity; - AVER(sliceSize > 0); - - /* remove slices, down to chunkHalf but no further */ - for(; chunkSize > chunkHalf; chunkSize -= sliceSize) { - if(chunkSize < chunkMin) { - EVENT2(vmArenaExtendFail, chunkMin, - VMArenaReserved(VMArena2Arena(vmArena))); - DIAG_SINGLEF(( "vmArenaExtend_FailMin", - "no remaining address-space chunk >= min($W)", (WriteFW)chunkMin, - " (so VMArenaReserved remains $W bytes)\n", - (WriteFW)VMArenaReserved(VMArena2Arena(vmArena)), - NULL )); - return ResRESOURCE; - } - res = VMChunkCreate(&newChunk, vmArena, chunkSize); - if(res == ResOK) - goto vmArenaExtend_Done; - } - } - } - -vmArenaExtend_Done: - - EVENT2(vmArenaExtendDone, chunkSize, VMArenaReserved(VMArena2Arena(vmArena))); - DIAG_SINGLEF(( "vmArenaExtend_Done", - "Request for new chunk of VM $W bytes succeeded", (WriteFW)chunkSize, - " (VMArenaReserved now $W bytes)\n", - (WriteFW)VMArenaReserved(VMArena2Arena(vmArena)), - NULL )); - - return res; -} - - -/* VM*AllocPolicy -- allocation policy methods */ - - -/* Used in abstracting allocation policy between VM and VMNZ */ -typedef Res (*VMAllocPolicyMethod)(Index *, VMChunk *, VMArena, SegPref, Size); - -static Res VMAllocPolicy(Index *baseIndexReturn, VMChunk *chunkReturn, - VMArena vmArena, SegPref pref, Size size) -{ - if (!pagesFindFreeWithSegPref(baseIndexReturn, chunkReturn, - vmArena, pref, size, FALSE)) { - /* try and extend, but don't worry if we can't */ - (void)vmArenaExtend(vmArena, size); - - /* We may or may not have a new chunk at this point */ - /* we proceed to try the allocation again anyway. */ - /* We specify barging, but if we have got a new chunk */ - /* then hopefully we won't need to barge. */ - if (!pagesFindFreeWithSegPref(baseIndexReturn, chunkReturn, - vmArena, pref, size, TRUE)) { - /* .improve.alloc-fail: This could be because the request was */ - /* too large, or perhaps the arena is fragmented. We could */ - /* return a more meaningful code. */ - return ResRESOURCE; - } - } - return ResOK; -} - -static Res VMNZAllocPolicy(Index *baseIndexReturn, VMChunk *chunkReturn, - VMArena vmArena, SegPref pref, Size size) -{ - if (pagesFindFreeInZones(baseIndexReturn, chunkReturn, vmArena, size, - ZoneSetUNIV, pref->high)) { - return ResOK; - } - return ResRESOURCE; -} - - -/* pageIsMapped -- checks whether a free page is mapped or not. */ - -static Bool pageIsMapped(VMChunk vmChunk, Index pi) -{ - Index pageTableBaseIndex; - Index pageTableLimitIndex; - int pageType; - Chunk chunk = VMChunk2Chunk(vmChunk); - - /* Note that unless the pi'th PageStruct crosses a page boundary */ - /* Base and Limit will differ by exactly 1. */ - /* They will differ by at most 2 assuming that */ - /* sizeof(PageStruct) <= ChunkPageSize(chunk) (!) */ - tablePagesUsed(&pageTableBaseIndex, &pageTableLimitIndex, chunk, pi, pi+1); - /* using unsigned arithmetic overflow to use just one comparison */ - AVER(pageTableLimitIndex - pageTableBaseIndex - 1 < 2); - - /* We can examine the PageStruct descriptor iff both table pages */ - /* are mapped. */ - if (BTGet(vmChunk->pageTableMapped, pageTableBaseIndex) - && BTGet(vmChunk->pageTableMapped, pageTableLimitIndex - 1)) { - pageType = PageType(&chunk->pageTable[pi]); - if (pageType == PageTypeSpare) - return TRUE; - AVER(pageType == PageTypeFree); - } - return FALSE; -} - - -/* sparePageRelease -- releases a spare page - * - * Either to allocate it or to purge it. - * Temporarily leaves it in an inconsistent state. - */ -static void sparePageRelease(VMChunk vmChunk, Index pi) -{ - Chunk chunk = VMChunk2Chunk(vmChunk); - Arena arena = ChunkArena(chunk); - - AVER(PageType(&chunk->pageTable[pi]) == PageTypeSpare); - AVER(arena->spareCommitted >= ChunkPageSize(chunk)); - arena->spareCommitted -= ChunkPageSize(chunk); - return; -} - - -/* pagesMarkAllocated -- Mark the pages allocated */ - -static Res pagesMarkAllocated(VMArena vmArena, VMChunk vmChunk, - Index baseIndex, Count pages, Pool pool) -{ - Index i; - Index limitIndex; - Index mappedBase, mappedLimit; - Index unmappedBase, unmappedLimit; - Chunk chunk = VMChunk2Chunk(vmChunk); - Res res; - - /* Ensure that the page descriptors we need are on mapped pages. */ - limitIndex = baseIndex + pages; - res = tablePagesEnsureMapped(vmChunk, baseIndex, limitIndex); - if (res != ResOK) - goto failTableMap; - - mappedBase = baseIndex; - mappedLimit = mappedBase; - - do { - while(pageIsMapped(vmChunk, mappedLimit)) { - ++mappedLimit; - if (mappedLimit >= limitIndex) - break; - } - AVER(mappedLimit <= limitIndex); - /* NB for loop will loop 0 times iff first page is not mapped */ - for(i = mappedBase; i < mappedLimit; ++i) { - sparePageRelease(vmChunk, i); - PageAlloc(chunk, i, pool); - } - if (mappedLimit >= limitIndex) - break; - unmappedBase = mappedLimit; - unmappedLimit = unmappedBase; - while(!pageIsMapped(vmChunk, unmappedLimit)) { - ++unmappedLimit; - if (unmappedLimit >= limitIndex) - break; - } - AVER(unmappedLimit <= limitIndex); - res = vmArenaMap(vmArena, vmChunk->vm, - PageIndexBase(chunk, unmappedBase), - PageIndexBase(chunk, unmappedLimit)); - if (res != ResOK) - goto failPagesMap; - for(i = unmappedBase; i < unmappedLimit; ++i) { - PageAlloc(chunk, i, pool); - } - mappedBase = unmappedLimit; - mappedLimit = mappedBase; - } while(mappedLimit < limitIndex); - AVER(mappedLimit == limitIndex); - - return ResOK; - -failPagesMap: - /* region from baseIndex to mappedLimit needs unmapping */ - if (baseIndex < mappedLimit) { - vmArenaUnmap(vmArena, vmChunk->vm, - PageIndexBase(chunk, baseIndex), - PageIndexBase(chunk, mappedLimit)); - /* mark pages as free */ - for(i = baseIndex; i < mappedLimit; ++i) { - TractFinish(PageTract(&chunk->pageTable[i])); - PageFree(chunk, i); - } - } - { - Index pageTableBaseIndex, pageTableLimitIndex; - /* find which pages of page table were affected */ - tablePagesUsed(&pageTableBaseIndex, &pageTableLimitIndex, - chunk, baseIndex, limitIndex); - /* Resetting the noSparePages bits is lazy, it means that */ - /* we don't have to bother trying to unmap unused portions */ - /* of the pageTable. */ - BTResRange(vmChunk->noSparePages, pageTableBaseIndex, pageTableLimitIndex); - } -failTableMap: - return res; -} - - -/* vmAllocComm -- allocate a region from the arena - * - * Common code used by mps_arena_class_vm and - * mps_arena_class_vmnz. - */ -static Res vmAllocComm(Addr *baseReturn, Tract *baseTractReturn, - VMAllocPolicyMethod policy, - SegPref pref, Size size, Pool pool) -{ - Addr base, limit; - Tract baseTract; - Arena arena; - Count pages; - Index baseIndex; - ZoneSet zones; - Res res; - VMArena vmArena; - VMChunk vmChunk; - Chunk chunk; - - AVER(baseReturn != NULL); - AVER(baseTractReturn != NULL); - AVER(FunCheck((Fun)policy)); - AVERT(SegPref, pref); - AVER(size > (Size)0); - AVERT(Pool, pool); - - arena = PoolArena(pool); - vmArena = Arena2VMArena(arena); - AVERT(VMArena, vmArena); - /* All chunks have same pageSize. */ - AVER(SizeIsAligned(size, ChunkPageSize(arena->primary))); - - /* NULL is used as a discriminator */ - /* (see ) therefore the real pool */ - /* must be non-NULL. */ - AVER(pool != NULL); - - /* Early check on commit limit. */ - if (arena->spareCommitted < size) { - Size necessaryCommitIncrease = size - arena->spareCommitted; - if (arena->committed + necessaryCommitIncrease > arena->commitLimit - || arena->committed + necessaryCommitIncrease < arena->committed) { - return ResCOMMIT_LIMIT; - } - } - - res = (*policy)(&baseIndex, &vmChunk, vmArena, pref, size); - if (res != ResOK) - return res; - - /* chunk (and baseIndex) should be initialised by policy */ - AVERT(VMChunk, vmChunk); - chunk = VMChunk2Chunk(vmChunk); - - /* Compute number of pages to be allocated. */ - pages = ChunkSizeToPages(chunk, size); - - res = pagesMarkAllocated(vmArena, vmChunk, baseIndex, pages, pool); - if (res != ResOK) { - if (arena->spareCommitted > 0) { - sparePagesPurge(vmArena); - res = pagesMarkAllocated(vmArena, vmChunk, baseIndex, pages, pool); - if (res != ResOK) - goto failPagesMap; - /* win! */ - } else { - goto failPagesMap; - } - } - - base = PageIndexBase(chunk, baseIndex); - baseTract = PageTract(&chunk->pageTable[baseIndex]); - limit = AddrAdd(base, size); - zones = ZoneSetOfRange(arena, base, limit); - - if (pref->isGen) { - Serial gen = vmGenOfSegPref(vmArena, pref); - vmArena->genZoneSet[gen] = ZoneSetUnion(vmArena->genZoneSet[gen], zones); - } - - vmArena->freeSet = ZoneSetDiff(vmArena->freeSet, zones); - - *baseReturn = base; - *baseTractReturn = baseTract; - return ResOK; - -failPagesMap: - return res; -} - - -static Res VMAlloc(Addr *baseReturn, Tract *baseTractReturn, - SegPref pref, Size size, Pool pool) -{ - /* All checks performed in common vmAllocComm */ - return vmAllocComm(baseReturn, baseTractReturn, - VMAllocPolicy, pref, size, pool); -} - -static Res VMNZAlloc(Addr *baseReturn, Tract *baseTractReturn, - SegPref pref, Size size, Pool pool) -{ - /* All checks performed in common vmAllocComm */ - return vmAllocComm(baseReturn, baseTractReturn, - VMNZAllocPolicy, pref, size, pool); -} - - -/* spareRangesMap -- map a function over spare ranges - * - * The function f is called on the ranges of spare pages which are - * within the range of pages from base to limit. PageStruct descriptors - * from base to limit should be mapped in the page table before calling - * this function. - */ -typedef void (*spareRangesFn)(VMChunk, Index, Index, void *); - -static void spareRangesMap(VMChunk vmChunk, Index base, Index limit, - spareRangesFn f, void *p) -{ - Index spareBase, spareLimit; - Chunk chunk = VMChunk2Chunk(vmChunk); - - AVER(base < limit); - - spareBase = base; - do { - while(!pageIsSpare(&chunk->pageTable[spareBase])) { - ++spareBase; - if (spareBase >= limit) - goto done; - } - spareLimit = spareBase; - while(pageIsSpare(&chunk->pageTable[spareLimit])) { - ++spareLimit; - if (spareLimit >= limit) - break; - } - f(vmChunk, spareBase, spareLimit, p); - spareBase = spareLimit; - } while(spareBase < limit); -done: - AVER(spareBase == limit); - - return; -} - - -/* vmArenaUnmapSpareRange - * - * Takes a range of spare pages and unmaps them, turning them into free pages. - */ -static void vmArenaUnmapSpareRange(VMChunk vmChunk, - Index rangeBase, Index rangeLimit, void *p) -{ - Index i; - Chunk chunk = VMChunk2Chunk(vmChunk); - - UNUSED(p); - for(i = rangeBase; i < rangeLimit; ++i) { - sparePageRelease(vmChunk, i); - PageInit(chunk, i); - } - vmArenaUnmap(VMChunkVMArena(vmChunk), vmChunk->vm, - PageIndexBase(chunk, rangeBase), - PageIndexBase(chunk, rangeLimit)); - - return; -} - - -/* sparePagesPurge -- all spare pages are found and purged (unmapped) - * - * This is currently the only way the spare pages are reduced. - * - * It uses the noSparePages bits to determine which areas of the - * pageTable to examine. - */ -static void sparePagesPurge(VMArena vmArena) -{ - Ring node, next; - Arena arena = VMArena2Arena(vmArena); - - RING_FOR(node, &arena->chunkRing, next) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - VMChunk vmChunk = Chunk2VMChunk(chunk); - Index spareBaseIndex, spareLimitIndex; - Index tablePageCursor = 0; - - while(BTFindLongResRange(&spareBaseIndex, &spareLimitIndex, - vmChunk->noSparePages, - tablePageCursor, chunk->pageTablePages, - 1)) { - Addr spareTableBase, spareTableLimit; - Index pageBase, pageLimit; - Index tablePage; - - spareTableBase = TablePageIndexBase(chunk, spareBaseIndex); - spareTableLimit = TablePageIndexBase(chunk, spareLimitIndex); - /* Determine whether to use initial overlapping PageStruct. */ - if (spareBaseIndex > 0 - && !BTGet(vmChunk->pageTableMapped, spareBaseIndex - 1)) { - pageBase = tablePageWholeBaseIndex(chunk, spareTableBase); - } else { - pageBase = tablePageBaseIndex(chunk, spareTableBase); - } - for(tablePage = spareBaseIndex; tablePage < spareLimitIndex; - ++tablePage) { - /* Determine whether to use final overlapping PageStruct. */ - if (tablePage == spareLimitIndex - 1 - && spareLimitIndex < chunk->pageTablePages - && !BTGet(vmChunk->pageTableMapped, spareLimitIndex)) { - pageLimit = - tablePageWholeLimitIndex(chunk, - TablePageIndexBase(chunk, tablePage)); - } else if (tablePage == chunk->pageTablePages - 1) { - pageLimit = chunk->pages; - } else { - pageLimit = - tablePageLimitIndex(chunk, TablePageIndexBase(chunk, tablePage)); - } - if (pageBase < pageLimit) { - spareRangesMap(vmChunk, pageBase, pageLimit, - vmArenaUnmapSpareRange, NULL); - } else { - /* Only happens for last page occupied by the page table */ - /* and only then when that last page has just the tail end */ - /* part of the last page descriptor and nothing more. */ - AVER(pageBase == pageLimit); - AVER(tablePage == chunk->pageTablePages - 1); - } - BTSet(vmChunk->noSparePages, tablePage); - pageBase = pageLimit; - } - tablePagesUnmapUnused(vmChunk, spareTableBase, spareTableLimit); - tablePageCursor = spareLimitIndex; - if (tablePageCursor >= chunk->pageTablePages) { - AVER(tablePageCursor == chunk->pageTablePages); - break; - } - } - - } - - AVER(arena->spareCommitted == 0); - return; -} - - -/* VMFree -- free a region in the arena */ - -static void VMFree(Addr base, Size size, Pool pool) -{ - Arena arena; - VMArena vmArena; - VMChunk vmChunk; - Chunk chunk = NULL; /* suppress "may be used uninitialized" */ - Count pages; - Index pi, piBase, piLimit; - Index pageTableBase; - Index pageTableLimit; - Bool foundChunk; - - AVER(base != NULL); - AVER(size > (Size)0); - AVERT(Pool, pool); - arena = PoolArena(pool); - AVERT(Arena, arena); - vmArena = Arena2VMArena(arena); - AVERT(VMArena, vmArena); - - /* All chunks have same pageSize. */ - AVER(SizeIsAligned(size, ChunkPageSize(arena->primary))); - AVER(AddrIsAligned(base, ChunkPageSize(arena->primary))); - - foundChunk = ChunkOfAddr(&chunk, arena, base); - AVER(foundChunk); - vmChunk = Chunk2VMChunk(chunk); - - /* Calculate the number of pages in the region */ - pages = ChunkSizeToPages(chunk, size); - piBase = INDEX_OF_ADDR(chunk, base); - piLimit = piBase + pages; - AVER(piBase < piLimit); - AVER(piLimit <= chunk->pages); - - /* loop from pageBase to pageLimit-1 inclusive */ - /* Finish each Tract found, then convert them to spare pages. */ - for(pi = piBase; pi < piLimit; ++pi) { - Page page = &chunk->pageTable[pi]; - Tract tract = PageTract(page); - AVER(TractPool(tract) == pool); - - TractFinish(tract); - PagePool(page) = NULL; - PageType(page) = PageTypeSpare; - } - arena->spareCommitted += ChunkPagesToSize(chunk, piLimit - piBase); - BTResRange(chunk->allocTable, piBase, piLimit); - - tablePagesUsed(&pageTableBase, &pageTableLimit, chunk, piBase, piLimit); - BTResRange(vmChunk->noSparePages, pageTableBase, pageTableLimit); - - if (arena->spareCommitted > arena->spareCommitLimit) { - sparePagesPurge(vmArena); - } - - /* Chunks are only freed when ArenaCompact is called. */ - - return; -} - - -/* M_whole, M_frac -- print count of bytes as Megabytes - * - * Split into a whole number of MB, "m" for the decimal point, and - * then the decimal fraction (thousandths of a MB, ie. kB). - * - * Input: 208896 - * Output: (Megabytes) 0m209 - */ -#define bPerM ((Size)1000000) /* Megabytes */ -#define bThou ((Size)1000) -DIAG_DECL( -static Count M_whole(Size bytes) -{ - Count M; /* MBs */ - M = (bytes + (bThou / 2)) / bPerM; - return M; -} -static Count M_frac(Size bytes) -{ - Count Mthou; /* thousandths of a MB */ - Mthou = (bytes + (bThou / 2)) / bThou; - Mthou = Mthou % 1000; - return Mthou; -} -) - - -static void VMCompact(Arena arena, Trace trace) -{ - VMArena vmArena; - Ring node, next; - DIAG_DECL( Size vmem1; ) - - vmArena = Arena2VMArena(arena); - AVERT(VMArena, vmArena); - AVERT(Trace, trace); - - DIAG( - vmem1 = VMArenaReserved(arena); - ); - - /* Destroy any empty chunks (except the primary). */ - sparePagesPurge(vmArena); - RING_FOR(node, &arena->chunkRing, next) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - if(chunk != arena->primary - && BTIsResRange(chunk->allocTable, 0, chunk->pages)) { - vmChunkDestroy(chunk); - } - } - - DIAG( - Size vmem0 = trace->preTraceArenaReserved; - Size vmem2 = VMArenaReserved(arena); - Size vmemD = vmem1 - vmem2; - Size live = trace->forwardedSize + trace->preservedInPlaceSize; - Size livePerc = 0; - - if(trace->condemned / 100 != 0) - livePerc = live / (trace->condemned / 100); - - /* VMCompact diag: emit for all client-requested collections, */ - /* plus any others where chunks were gained or lost during the */ - /* collection. */ - if(trace->why == TraceStartWhyCLIENTFULL_INCREMENTAL - || trace->why == TraceStartWhyCLIENTFULL_BLOCK - || vmem0 != vmem1 - || vmem1 != vmem2) { - DIAG_SINGLEF(( "VMCompact", - "pre-collection vmem was $Um$3, ", - (WriteFU)M_whole(vmem0), (WriteFU)M_frac(vmem0), - "peaked at $Um$3, ", (WriteFU)M_whole(vmem1), (WriteFU)M_frac(vmem1), - "released $Um$3, ", (WriteFU)M_whole(vmemD), (WriteFU)M_frac(vmemD), - "now $Um$3", (WriteFU)M_whole(vmem2), (WriteFU)M_frac(vmem2), - " (why $U", (WriteFU)trace->why, - ": $Um$3", - (WriteFU)M_whole(trace->condemned), (WriteFU)M_frac(trace->condemned), - "[->$Um$3", (WriteFU)M_whole(live), (WriteFU)M_frac(live), - " $U%-live", (WriteFU)livePerc, - " $Um$3-stuck]", - (WriteFU)M_whole(trace->preservedInPlaceSize), - (WriteFU)M_frac(trace->preservedInPlaceSize), - " ($Um$3-not)", - (WriteFU)M_whole(trace->notCondemned), - (WriteFU)M_frac(trace->notCondemned), - " )", - NULL)); - } - ); -} - -mps_res_t mps_arena_vm_growth(mps_arena_t mps_arena, - size_t mps_desired, size_t mps_minimum) -{ - Arena arena = (Arena)mps_arena; - Size desired = (Size)mps_desired; - Size minimum = (Size)mps_minimum; - VMArena vmArena; - - ArenaEnter(arena); - - AVERT(Arena, arena); - vmArena = Arena2VMArena(arena); - AVERT(VMArena, vmArena); - - if(desired < minimum) { - /* May not desire an increment smaller than the minimum! */ - ArenaLeave(arena); - return MPS_RES_PARAM; - } - - vmArena->extendBy = desired; - vmArena->extendMin = minimum; - - ArenaLeave(arena); - - return MPS_RES_OK; -} - - -/* VMArenaClass -- The VM arena class definition */ - -DEFINE_ARENA_CLASS(VMArenaClass, this) -{ - INHERIT_CLASS(this, AbstractArenaClass); - this->name = "VM"; - this->size = sizeof(VMArenaStruct); - this->offset = offsetof(VMArenaStruct, arenaStruct); - this->init = VMArenaInit; - this->finish = VMArenaFinish; - this->reserved = VMArenaReserved; - this->spareCommitExceeded = VMArenaSpareCommitExceeded; - this->alloc = VMAlloc; - this->free = VMFree; - this->chunkInit = VMChunkInit; - this->chunkFinish = VMChunkFinish; - this->compact = VMCompact; - this->describe = VMArenaDescribe; -} - - -/* VMNZArenaClass -- The VMNZ arena class definition - * - * VMNZ is just VMArena with a different allocation policy. - */ -DEFINE_ARENA_CLASS(VMNZArenaClass, this) -{ - INHERIT_CLASS(this, VMArenaClass); - this->name = "VMNZ"; - this->alloc = VMNZAlloc; -} - - -/* mps_arena_class_vm -- return the arena class VM */ - -mps_arena_class_t mps_arena_class_vm(void) -{ - return (mps_arena_class_t)VMArenaClassGet(); -} - - -/* mps_arena_class_vmnz -- return the arena class VMNZ */ - -mps_arena_class_t mps_arena_class_vmnz(void) -{ - return (mps_arena_class_t)VMNZArenaClassGet(); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/awlut.c b/mps/code/awlut.c deleted file mode 100644 index 74f566639d3..00000000000 --- a/mps/code/awlut.c +++ /dev/null @@ -1,364 +0,0 @@ -/* awlut.c: POOL CLASS AWL UNIT TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * DESIGN - * - * .design: see .* - */ - -#include "mpscawl.h" -#include "mpsclo.h" -#include "mpsavm.h" -#include "fmtdy.h" -#include "testlib.h" -#include "mps.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include - - -#define testArenaSIZE ((size_t)64<<20) -#define TABLE_SLOTS 49 -#define ITERATIONS 5000 -#define CHATTER 100 - - -static mps_word_t bogus_class; - -#define UNINIT 0x041412ED - -#define DYLAN_ALIGN 4 /* depends on value defined in fmtdy.c */ - - -/* size_tAlignUp -- align w up to alignment a */ - -#define size_tAlignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - - -static mps_word_t wrapper_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* Extra word */ - (mps_word_t)4<<2|2, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8), /* V */ - (mps_word_t)1<<2|1, /* VL */ - 1 /* patterns */ -}; - - -static mps_word_t string_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* extra word */ - 0, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8)|(mps_word_t)3<<3|4, /* V */ - 1 /* VL */ -}; - -static mps_word_t table_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* extra word */ - (mps_word_t)1<<2|1, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8)|2, /* V */ - 1 /* VL */ -}; - - -static void initialise_wrapper(mps_word_t *wrapper) -{ - wrapper[0] = (mps_word_t)&wrapper_wrapper; - wrapper[1] = (mps_word_t)&bogus_class; -} - - -/* alloc_string - create a dylan string object - * - * create a dylan string object (byte vector) whose contents - * are the string s (including the terminating NUL) - * .assume.dylan-obj - */ - -static mps_word_t *alloc_string(char *s, mps_ap_t ap) -{ - size_t l; - size_t objsize; - void *p; - mps_word_t *object; - - l = strlen(s)+1; - /* number of words * sizeof word */ - objsize = (2 + (l+sizeof(mps_word_t)-1)/sizeof(mps_word_t)) - * sizeof(mps_word_t); - objsize = size_tAlignUp(objsize, DYLAN_ALIGN); - do { - size_t i; - char *s2; - - die(mps_reserve(&p, ap, objsize), "Reserve Leaf\n"); - object = p; - object[0] = (mps_word_t)string_wrapper; - object[1] = l << 2 | 1; - s2 = (char *)&object[2]; - for(i = 0; i < l; ++i) { - s2[i] = s[i]; - } - } while(!mps_commit(ap, p, objsize)); - return object; -} - - -/* alloc_table -- create a table with n variable slots - * - * .assume.dylan-obj - */ - -static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) -{ - size_t objsize; - void *p; - mps_word_t *object; - - objsize = (3 + n) * sizeof(mps_word_t); - objsize = size_tAlignUp(objsize, MPS_PF_ALIGN); - do { - unsigned long i; - - die(mps_reserve(&p, ap, objsize), "Reserve Table\n"); - object = p; - object[0] = (mps_word_t)table_wrapper; - object[1] = 0; - object[2] = n << 2 | 1; - for(i = 0; i < n; ++i) { - object[3+i] = 0; - } - } while(!mps_commit(ap, p, objsize)); - return object; -} - - -/* gets the nth slot from a table - * .assume.dylan-obj - */ -static mps_word_t *table_slot(mps_word_t *table, unsigned long n) -{ - return (mps_word_t *)table[3+n]; -} - - -/* sets the nth slot in a table - * .assume.dylan-obj - */ -static void set_table_slot(mps_word_t *table, - unsigned long n, mps_word_t *p) -{ - cdie(table[0] == (mps_word_t)table_wrapper, "set_table_slot"); - table[3+n] = (mps_word_t)p; -} - - -/* links two tables together via their link slot - * (1st fixed part slot) - */ -static void table_link(mps_word_t *t1, mps_word_t *t2) -{ - cdie(t1[0] == (mps_word_t)table_wrapper, "table_link 1"); - cdie(t2[0] == (mps_word_t)table_wrapper, "table_link 2"); - t1[1] = (mps_word_t)t2; - t2[1] = (mps_word_t)t1; -} - - -static void test(mps_ap_t leafap, mps_ap_t exactap, mps_ap_t weakap, - mps_ap_t bogusap) -{ - mps_word_t *weaktable; - mps_word_t *exacttable; - mps_word_t *preserve[TABLE_SLOTS]; /* preserves objects in the weak */ - /* table by referring to them */ - unsigned long i, j; - void *p; - - exacttable = alloc_table(TABLE_SLOTS, exactap); - weaktable = alloc_table(TABLE_SLOTS, weakap); - table_link(exacttable, weaktable); - - /* Leave bogusap between reserve and commit for the duration */ - die(mps_reserve(&p, bogusap, 64), "Reserve bogus"); - - for(i = 0; i < TABLE_SLOTS; ++i) { - mps_word_t *string; - if (rnd() % 2 == 0) { - string = alloc_string("iamalive", leafap); - preserve[i] = string; - } else { - string = alloc_string("iamdead", leafap); - preserve[i] = 0; - } - set_table_slot(weaktable, i, string); - string = alloc_string("iamexact", leafap); - set_table_slot(exacttable, i, string); - } - - for(j = 0; j < ITERATIONS; ++j) { - for(i = 0; i < TABLE_SLOTS; ++i) { - (void)alloc_string("spong", leafap); - } - } - - for(i = 0; i < TABLE_SLOTS; ++i) { - if (preserve[i] == 0) { - if (table_slot(weaktable, i)) { - error("Strongly unreachable weak table entry found, slot %lu.\n", i); - } else { - if (table_slot(exacttable, i) != 0) { - error("Weak table entry deleted, but corresponding " - "exact table entry not deleted, slot %lu.\n", i); - } - } - } - } - - (void)mps_commit(bogusap, p, 64); -} - - -/* setup -- set up pools for the test - * - * v serves two purposes: - * - a pseudo stack base for the stack root. - * - pointer to a guff structure, which packages some values needed - * (arena and thr mostly) - */ - -struct guff_s { - mps_arena_t arena; - mps_thr_t thr; -}; - -static void *setup(void *v, size_t s) -{ - struct guff_s *guff; - mps_arena_t arena; - mps_pool_t leafpool; - mps_pool_t tablepool; - mps_fmt_t dylanfmt; - mps_fmt_t dylanweakfmt; - mps_ap_t leafap, exactap, weakap, bogusap; - mps_root_t stack; - mps_thr_t thr; - - guff = (struct guff_s *)v; - (void)s; - arena = guff->arena; - thr = guff->thr; - - die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr, - mps_stack_scan_ambig, v, 0), - "Root Create\n"); - die(mps_fmt_create_A(&dylanfmt, arena, dylan_fmt_A()), - "Format Create\n"); - die(mps_fmt_create_A(&dylanweakfmt, arena, dylan_fmt_A_weak()), - "Format Create (weak)\n"); - die(mps_pool_create(&leafpool, arena, mps_class_lo(), dylanfmt), - "Leaf Pool Create\n"); - die(mps_pool_create(&tablepool, arena, mps_class_awl(), dylanweakfmt, - dylan_weak_dependent), - "Table Pool Create\n"); - die(mps_ap_create(&leafap, leafpool, mps_rank_exact()), - "Leaf AP Create\n"); - die(mps_ap_create(&exactap, tablepool, mps_rank_exact()), - "Exact AP Create\n"); - die(mps_ap_create(&weakap, tablepool, mps_rank_weak()), - "Weak AP Create\n"); - die(mps_ap_create(&bogusap, tablepool, mps_rank_exact()), - "Bogus AP Create\n"); - - test(leafap, exactap, weakap, bogusap); - - mps_ap_destroy(bogusap); - mps_ap_destroy(weakap); - mps_ap_destroy(exactap); - mps_ap_destroy(leafap); - mps_pool_destroy(tablepool); - mps_pool_destroy(leafpool); - mps_fmt_destroy(dylanweakfmt); - mps_fmt_destroy(dylanfmt); - mps_root_destroy(stack); - - return NULL; -} - - -int main(int argc, char **argv) -{ - struct guff_s guff; - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - initialise_wrapper(wrapper_wrapper); - initialise_wrapper(string_wrapper); - initialise_wrapper(table_wrapper); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create\n"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - guff.arena = arena; - guff.thr = thread; - mps_tramp(&r, setup, &guff, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/awluthe.c b/mps/code/awluthe.c deleted file mode 100644 index ea08a3bdef7..00000000000 --- a/mps/code/awluthe.c +++ /dev/null @@ -1,367 +0,0 @@ -/* awluthe.c: POOL CLASS AWL UNIT TEST WITH OBJECT HEADERS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * DESIGN - * - * .design: see .* - */ - -#include "mpscawl.h" -#include "mpsclo.h" -#include "mpsavm.h" -#include "fmthe.h" -#include "fmtdy.h" -#include "testlib.h" -#include "mps.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include - - -#define testArenaSIZE ((size_t)64<<20) -#define TABLE_SLOTS 49 -#define ITERATIONS 5000 -#define CHATTER 100 - - -static mps_word_t bogus_class; - -#define UNINIT 0x041412ED - -#define DYLAN_ALIGN 4 /* depends on value defined in fmtdy.c */ - - -/* size_tAlignUp -- align w up to alignment a */ - -#define size_tAlignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - - -static mps_word_t wrapper_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* Extra word */ - (mps_word_t)4<<2|2, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8), /* V */ - (mps_word_t)1<<2|1, /* VL */ - 1 /* patterns */ -}; - - -static mps_word_t string_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* extra word */ - 0, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8)|(mps_word_t)3<<3|4, /* V */ - 1 /* VL */ -}; - -static mps_word_t table_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* extra word */ - (mps_word_t)1<<2|1, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8)|2, /* V */ - 1 /* VL */ -}; - - -static void initialise_wrapper(mps_word_t *wrapper) -{ - wrapper[0] = (mps_word_t)&wrapper_wrapper; - wrapper[1] = (mps_word_t)&bogus_class; -} - - -/* alloc_string - create a dylan string object - * - * create a dylan string object (byte vector) whose contents - * are the string s (including the terminating NUL) - * .assume.dylan-obj - */ - -static mps_word_t *alloc_string(char *s, mps_ap_t ap) -{ - size_t l; - size_t objsize; - void *p; - mps_word_t *object; - - l = strlen(s)+1; - /* number of words * sizeof word */ - objsize = (2 + (l+sizeof(mps_word_t)-1)/sizeof(mps_word_t)) - * sizeof(mps_word_t); - objsize = size_tAlignUp(objsize, DYLAN_ALIGN); - do { - size_t i; - char *s2; - - die(mps_reserve(&p, ap, objsize + headerSIZE), "Reserve Leaf\n"); - object = (mps_word_t *)((char *)p + headerSIZE); - object[0] = (mps_word_t)string_wrapper; - object[1] = l << 2 | 1; - s2 = (char *)&object[2]; - for(i = 0; i < l; ++i) { - s2[i] = s[i]; - } - ((int*)p)[0] = realHeader; - ((int*)p)[1] = 0xED0ED; - } while(!mps_commit(ap, p, objsize + headerSIZE)); - return object; -} - - -/* alloc_table -- create a table with n variable slots - * - * .assume.dylan-obj - */ - -static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) -{ - size_t objsize; - void *p; - mps_word_t *object; - - objsize = (3 + n) * sizeof(mps_word_t); - objsize = size_tAlignUp(objsize, MPS_PF_ALIGN); - do { - unsigned long i; - - die(mps_reserve(&p, ap, objsize + headerSIZE), "Reserve Table\n"); - object = (mps_word_t *)((char *)p + headerSIZE); - object[0] = (mps_word_t)table_wrapper; - object[1] = 0; - object[2] = n << 2 | 1; - for(i = 0; i < n; ++i) { - object[3+i] = 0; - } - ((int*)p)[0] = realHeader; - ((int*)p)[1] = 0xED0ED; - } while(!mps_commit(ap, p, objsize + headerSIZE)); - return object; -} - - -/* gets the nth slot from a table - * .assume.dylan-obj - */ -static mps_word_t *table_slot(mps_word_t *table, unsigned long n) -{ - return (mps_word_t *)table[3+n]; -} - - -/* sets the nth slot in a table - * .assume.dylan-obj - */ -static void set_table_slot(mps_word_t *table, - unsigned long n, mps_word_t *p) -{ - cdie(table[0] == (mps_word_t)table_wrapper, "set_table_slot"); - table[3+n] = (mps_word_t)p; -} - - -/* links two tables together via their link slot - * (1st fixed part slot) - */ -static void table_link(mps_word_t *t1, mps_word_t *t2) -{ - cdie(t1[0] == (mps_word_t)table_wrapper, "table_link 1"); - cdie(t2[0] == (mps_word_t)table_wrapper, "table_link 2"); - t1[1] = (mps_word_t)t2; - t2[1] = (mps_word_t)t1; -} - - -static void test(mps_ap_t leafap, mps_ap_t exactap, mps_ap_t weakap, - mps_ap_t bogusap) -{ - mps_word_t *weaktable; - mps_word_t *exacttable; - mps_word_t *preserve[TABLE_SLOTS]; /* preserves objects in the weak */ - /* table by referring to them */ - unsigned long i, j; - void *p; - - exacttable = alloc_table(TABLE_SLOTS, exactap); - weaktable = alloc_table(TABLE_SLOTS, weakap); - table_link(exacttable, weaktable); - - /* Leave bogusap between reserve and commit for the duration */ - die(mps_reserve(&p, bogusap, 64), "Reserve bogus"); - - for(i = 0; i < TABLE_SLOTS; ++i) { - mps_word_t *string; - if (rnd() % 2 == 0) { - string = alloc_string("iamalive", leafap); - preserve[i] = string; - } else { - string = alloc_string("iamdead", leafap); - preserve[i] = 0; - } - set_table_slot(weaktable, i, string); - string = alloc_string("iamexact", leafap); - set_table_slot(exacttable, i, string); - } - - for(j = 0; j < ITERATIONS; ++j) { - for(i = 0; i < TABLE_SLOTS; ++i) { - (void)alloc_string("spong", leafap); - } - } - - for(i = 0; i < TABLE_SLOTS; ++i) { - if (preserve[i] == 0) { - if (table_slot(weaktable, i)) { - error("Strongly unreachable weak table entry found, slot %lu.\n", i); - } else { - if (table_slot(exacttable, i) != 0) { - error("Weak table entry deleted, but corresponding " - "exact table entry not deleted, slot %lu.\n", i); - } - } - } - } - - (void)mps_commit(bogusap, p, 64); -} - - -/* setup -- set up pools for the test - * - * v serves two purposes: - * - a pseudo stack base for the stack root. - * - pointer to a guff structure, which packages some values needed - * (arena and thr mostly) - */ - -struct guff_s { - mps_arena_t arena; - mps_thr_t thr; -}; - -static void *setup(void *v, size_t s) -{ - struct guff_s *guff; - mps_arena_t arena; - mps_pool_t leafpool; - mps_pool_t tablepool; - mps_fmt_t dylanfmt; - mps_fmt_t dylanweakfmt; - mps_ap_t leafap, exactap, weakap, bogusap; - mps_root_t stack; - mps_thr_t thr; - - guff = (struct guff_s *)v; - (void)s; - arena = guff->arena; - thr = guff->thr; - - die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr, - mps_stack_scan_ambig, v, 0), - "Root Create\n"); - EnsureHeaderFormat(&dylanfmt, arena); - EnsureHeaderWeakFormat(&dylanweakfmt, arena); - die(mps_pool_create(&leafpool, arena, mps_class_lo(), dylanfmt), - "Leaf Pool Create\n"); - die(mps_pool_create(&tablepool, arena, mps_class_awl(), dylanweakfmt, - dylan_weak_dependent), - "Table Pool Create\n"); - die(mps_ap_create(&leafap, leafpool, mps_rank_exact()), - "Leaf AP Create\n"); - die(mps_ap_create(&exactap, tablepool, mps_rank_exact()), - "Exact AP Create\n"); - die(mps_ap_create(&weakap, tablepool, mps_rank_weak()), - "Weak AP Create\n"); - die(mps_ap_create(&bogusap, tablepool, mps_rank_exact()), - "Bogus AP Create\n"); - - test(leafap, exactap, weakap, bogusap); - - mps_ap_destroy(bogusap); - mps_ap_destroy(weakap); - mps_ap_destroy(exactap); - mps_ap_destroy(leafap); - mps_pool_destroy(tablepool); - mps_pool_destroy(leafpool); - mps_fmt_destroy(dylanweakfmt); - mps_fmt_destroy(dylanfmt); - mps_root_destroy(stack); - - return NULL; -} - - -int main(int argc, char **argv) -{ - struct guff_s guff; - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - initialise_wrapper(wrapper_wrapper); - initialise_wrapper(string_wrapper); - initialise_wrapper(table_wrapper); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create\n"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - guff.arena = arena; - guff.thr = thread; - mps_tramp(&r, setup, &guff, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/awlutth.c b/mps/code/awlutth.c deleted file mode 100644 index 3a5c9ee0fb1..00000000000 --- a/mps/code/awlutth.c +++ /dev/null @@ -1,375 +0,0 @@ -/* awlutth.c: THREADING UNIT TEST USING POOL CLASS AWL - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * DESIGN - * - * .design: see .* - */ - -#include "mpscawl.h" -#include "mpsclo.h" -#include "mpsavm.h" -#include "fmtdy.h" -#include "testlib.h" -#include "mps.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include -#if defined(MPS_OS_LI) || defined(MPS_OS_FR) -#include -#endif - - -#define testArenaSIZE ((size_t)64<<20) -#define TABLE_SLOTS 50 -#define ITERATIONS 5000 -#define CHATTER 100 -/* The number that a half of all numbers generated from rnd are less - * than. Hence, probability a-half, or P a-half */ -/* see */ -#define P_A_HALF (1024uL*1024uL*1024uL - 1) /* 2^30 - 1 */ - - -static mps_word_t bogus_class; - -#define UNINIT 0x041412ED - -#define DYLAN_ALIGN 4 /* depends on value defined in fmtdy.c */ - - -static mps_word_t wrapper_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* Extra word */ - (mps_word_t)4<<2|2, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8), /* V */ - (mps_word_t)1<<2|1, /* VL */ - 1 /* patterns */ -}; - - -static mps_word_t string_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* extra word */ - 0, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8)|(mps_word_t)3<<3|4, /* V */ - 1 /* VL */ -}; - -static mps_word_t table_wrapper[] = { - UNINIT, /* wrapper */ - UNINIT, /* class */ - 0, /* extra word */ - (mps_word_t)1<<2|1, /* F */ - (mps_word_t)2<<(MPS_WORD_WIDTH - 8)|2, /* V */ - 1 /* VL */ -}; - - -static void initialise_wrapper(mps_word_t *wrapper) -{ - wrapper[0] = (mps_word_t)&wrapper_wrapper; - wrapper[1] = (mps_word_t)&bogus_class; -} - - -/* create a dylan string object (byte vector) whose contents - * are the string s (including the terminating NUL) - * .assume.dylan-obj */ -static mps_word_t *alloc_string(char *s, mps_ap_t ap) -{ - size_t l; - size_t objsize; - void *p; - mps_word_t *object; - - l = strlen(s)+1; - /* number of words * sizeof word */ - objsize = (2 + (l+sizeof(mps_word_t)-1)/sizeof(mps_word_t)) * - sizeof(mps_word_t); - objsize = (objsize + DYLAN_ALIGN-1)/DYLAN_ALIGN*DYLAN_ALIGN; - do { - size_t i; - char *s2; - - die(mps_reserve(&p, ap, objsize), "Reserve Leaf\n"); - object = p; - object[0] = (mps_word_t)string_wrapper; - object[1] = l << 2 | 1; - s2 = (char *)&object[2]; - for(i = 0; i < l; ++i) { - s2[i] = s[i]; - } - } while(!mps_commit(ap, p, objsize)); - return object; -} - - -/* alloc_table -- create a table with n variable slots - * - * .assume.dylan-obj - */ -static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) -{ - size_t objsize; - void *p; - mps_word_t *object; - objsize = (4 + n) * sizeof(mps_word_t); - objsize = (objsize + MPS_PF_ALIGN-1)/MPS_PF_ALIGN*MPS_PF_ALIGN; - do { - unsigned long i; - - die(mps_reserve(&p, ap, objsize), "Reserve Table\n"); - object = p; - object[0] = (mps_word_t)table_wrapper; - object[1] = 0; - object[2] = n << 2 | 1; - for(i = 0; i < n; ++i) { - object[3+i] = 0; - } - } while(!mps_commit(ap, p, objsize)); - return object; -} - - -/* gets the nth slot from a table - * .assume.dylan-obj - */ -static mps_word_t *table_slot(mps_word_t *table, unsigned long n) -{ - return (mps_word_t *)table[3+n]; -} - -/* sets the nth slot in a table - * .assume.dylan-obj - */ -static void set_table_slot(mps_word_t *table, - unsigned long n, mps_word_t *p) -{ - cdie(table[0] == (mps_word_t)table_wrapper, "set_table_slot"); - table[3+n] = (mps_word_t)p; -} - -/* links two tables together via their link slot - * (1st fixed part slot) - */ -static void table_link(mps_word_t *t1, mps_word_t *t2) -{ - cdie(t1[0] == (mps_word_t)table_wrapper, "table_link 1"); - cdie(t2[0] == (mps_word_t)table_wrapper, "table_link 2"); - t1[1] = (mps_word_t)t2; - t2[1] = (mps_word_t)t1; -} - - -static void test(mps_ap_t leafap, mps_ap_t exactap, mps_ap_t weakap, - mps_ap_t bogusap) -{ - mps_word_t *weaktable; - mps_word_t *exacttable; - mps_word_t *preserve[TABLE_SLOTS]; /* preserves objects in the weak */ - /* table by referring to them */ - unsigned long i, j; - void *p; - - exacttable = alloc_table(TABLE_SLOTS, exactap); - weaktable = alloc_table(TABLE_SLOTS, weakap); - table_link(exacttable, weaktable); - - /* Leave bogusap between reserve and commit for the duration */ - die(mps_reserve(&p, bogusap, 64), "Reserve bogus"); - - for(i = 0; i < TABLE_SLOTS; ++i) { - mps_word_t *string; - if(rnd() < P_A_HALF) { - string = alloc_string("iamalive", leafap); - preserve[i] = string; - } else { - string = alloc_string("iamdead", leafap); - preserve[i] = 0; - } - set_table_slot(weaktable, i, string); - string = alloc_string("iamexact", leafap); - set_table_slot(exacttable, i, string); - } - - for(j = 0; j < ITERATIONS; ++j) { - for(i = 0; i < TABLE_SLOTS; ++i) { - mps_word_t *string; - - string = alloc_string("spong", leafap); - } - } - - for(i = 0; i < TABLE_SLOTS; ++i) { - if(preserve[i] == 0) { - if(table_slot(weaktable, i)) { - fprintf(stdout, - "Strongly unreachable weak table entry found, " - "slot %lu.\n", - i); - } else { - if(table_slot(exacttable, i) != 0) { - fprintf(stdout, - "Weak table entry deleted, but corresponding " - "exact table entry not deleted, slot %lu.\n", - i); - } - } - } - } - - (void)mps_commit(bogusap, p, 64); - puts("A okay\n"); -} - - -struct guff_s { - mps_arena_t arena; - mps_thr_t thr; -}; - -/* v serves two purposes: - * A pseudo stack base for the stack root. - * Pointer to a guff structure, which packages some values needed - * (arena and thr mostly) */ -static void *setup(void *v, size_t s) -{ - struct guff_s *guff; - mps_arena_t arena; - mps_pool_t leafpool; - mps_pool_t tablepool; - mps_fmt_t dylanfmt; - mps_fmt_t dylanweakfmt; - mps_ap_t leafap, exactap, weakap, bogusap; - mps_root_t stack; - mps_thr_t thr; - - guff = (struct guff_s *)v; - (void)s; - arena = guff->arena; - thr = guff->thr; - - die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr, - mps_stack_scan_ambig, v, 0), - "Root Create\n"); - die(mps_fmt_create_A(&dylanfmt, arena, dylan_fmt_A()), - "Format Create\n"); - die(mps_fmt_create_A(&dylanweakfmt, arena, dylan_fmt_A_weak()), - "Format Create (weak)\n"); - die(mps_pool_create(&leafpool, arena, mps_class_lo(), dylanfmt), - "Leaf Pool Create\n"); - die(mps_pool_create(&tablepool, arena, mps_class_awl(), dylanweakfmt, - dylan_weak_dependent), - "Table Pool Create\n"); - die(mps_ap_create(&leafap, leafpool, mps_rank_exact()), - "Leaf AP Create\n"); - die(mps_ap_create(&exactap, tablepool, mps_rank_exact()), - "Exact AP Create\n"); - die(mps_ap_create(&weakap, tablepool, mps_rank_weak()), - "Weak AP Create\n"); - die(mps_ap_create(&bogusap, tablepool, mps_rank_exact()), - "Bogus AP Create\n"); - - test(leafap, exactap, weakap, bogusap); - - mps_ap_destroy(bogusap); - mps_ap_destroy(weakap); - mps_ap_destroy(exactap); - mps_ap_destroy(leafap); - mps_pool_destroy(tablepool); - mps_pool_destroy(leafpool); - mps_fmt_destroy(dylanweakfmt); - mps_fmt_destroy(dylanfmt); - mps_root_destroy(stack); - - return NULL; -} - - -static void *setup_thr(void *v) -{ - struct guff_s guff; - mps_arena_t arena = (mps_arena_t)v; - mps_thr_t thread; - void *r; - - die(mps_thread_reg(&thread, arena), "thread_reg"); - guff.arena = arena; - guff.thr = thread; - mps_tramp(&r, setup, &guff, 0); - mps_thread_dereg(thread); - - return r; -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - pthread_t pthread1; - - randomize(argc, argv); - - initialise_wrapper(wrapper_wrapper); - initialise_wrapper(string_wrapper); - initialise_wrapper(table_wrapper); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create\n"); - pthread_create(&pthread1, NULL, setup_thr, (void *)arena); - setup_thr(arena); - pthread_join(pthread1, NULL); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/boot.c b/mps/code/boot.c deleted file mode 100644 index f42d5ded7cc..00000000000 --- a/mps/code/boot.c +++ /dev/null @@ -1,167 +0,0 @@ -/* boot.c: BOOTSTRAP ALLOCATOR - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .overview: A structure and protocols for allocating memory from a - * given block. Very simple, it basically just increments a pointer. - * - * .boot.c: The Bootstrap Allocator is used to allocate C structures - * for use in the implementation, not client objects. Therefore, - * we use "C types" (void *, size_t) not "client types" (Addr, Size). - */ - -#include "boot.h" -#include "mpm.h" - -SRCID(boot, "$Id$"); - - -#define BootBlockSig ((Sig)0x519B002B) /* SIGnature BOOT Block */ - - -/* BootBlockCheck -- check a BootBlock structure */ - -Bool BootBlockCheck(BootBlock boot) -{ - CHECKS(BootBlock, boot); - CHECKL(boot->base != NULL); - CHECKL(boot->alloc != NULL); - CHECKL(boot->limit != NULL); - CHECKL(boot->base <= boot->alloc); - CHECKL(boot->alloc <= boot->limit); - CHECKL(boot->alloc < boot->limit); - - return TRUE; -} - - -/* BootBlockInit -- initialize a BootBlock - * - * boot: a pointer to the structure to be initialized - * (must have been allocated by the caller, probably on the stack). - * base: a pointer to the base of the memory to be allocated from - * from (the memory need not be committed) - * limit: a pointer to the limit of the memory to be allocated from - */ - -Res BootBlockInit(BootBlockStruct *boot, void *base, void *limit) -{ - /* Can't check boot as we are supposed to be initializing it */ - AVER(boot != NULL); - AVER(base != NULL); - AVER(limit != NULL); - AVER(base < limit); - - boot->base = base; - boot->alloc = base; - boot->limit = limit; - boot->sig = BootBlockSig; - - AVERT(BootBlock, boot); - return ResOK; -} - - -/* BootBlockFinish -- finish a BootBlock structure */ - -void BootBlockFinish(BootBlock boot) -{ - AVERT(BootBlock, boot); - - boot->base = boot->alloc = boot->limit = NULL; - boot->sig = SigInvalid; -} - - -/* BootAllocated - * - * Returns the total amount allocated using this descriptor - */ -size_t BootAllocated(BootBlock boot) -{ - AVERT(BootBlock, boot); - - return PointerOffset(boot->base, boot->alloc); -} - - -/* BootAlloc -- allocate from BootBlock structure - * - * preturn: The returned pointer, see .boot.c. - * boot: must have been initialized with BootBlockInit(). - * size: size of requested object, see .boot.c. - * align: required alignment of object, see .boot.c. - */ - -Res BootAlloc(void **pReturn, BootBlock boot, size_t size, size_t align) -{ - void *blockBase, *blockLimit; /* base, limit of candidate block */ - - AVER(pReturn != NULL); - AVERT(BootBlock, boot); - AVER(size > 0); - AVER(AlignCheck((Align)align)); - - /* Align alloc pointer up and bounds check. */ - blockBase = PointerAlignUp(boot->alloc, align); - if(boot->limit <= blockBase || blockBase < boot->alloc) { - return ResMEMORY; - } - blockLimit = PointerAdd(blockBase, size); - /* Following checks that the ordering constraint holds: */ - /* boot->alloc <= blockBase < blockLimit <= boot->limit */ - /* (if it doesn't hold then something overallocated/wrapped round) */ - if(blockBase < boot->alloc || - blockLimit <= blockBase || - boot->limit < blockLimit) { - return ResMEMORY; - } - - /* Fits! So allocate it */ - boot->alloc = blockLimit; - *pReturn = blockBase; - return ResOK; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/boot.h b/mps/code/boot.h deleted file mode 100644 index 87445cc6322..00000000000 --- a/mps/code/boot.h +++ /dev/null @@ -1,76 +0,0 @@ -/* boot.h: BOOTSTRAP ALLOCATOR INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .overview: A protocol for allocating memory from a given block. - */ - -#ifndef boot_h -#define boot_h - -#include "mpmtypes.h" - - -/* BootBlockStruct -- descriptor of the block to allocate from */ - -typedef struct BootBlockStruct -{ - Sig sig; - void *base; - void *alloc; - void *limit; -} BootBlockStruct; - - -extern Res BootBlockInit(BootBlockStruct *boot, void *base, void *limit); -extern void BootBlockFinish(BootBlock boot); -extern Res BootAlloc(void **pReturn, BootBlock boot, size_t size, - size_t align); -extern size_t BootAllocated(BootBlock boot); -extern Bool BootBlockCheck(BootBlock boot); - - -#endif /* boot_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/bt.c b/mps/code/bt.c deleted file mode 100644 index 176b18d99f0..00000000000 --- a/mps/code/bt.c +++ /dev/null @@ -1,1060 +0,0 @@ -/* bt.c: BIT TABLES - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * READERSHIP - * - * .readership: Any MPS developer - * - * DESIGN - * - * .design: see - */ - -#include "bt.h" -#include "config.h" -#include "check.h" -#include "mpm.h" - -SRCID(bt, "$Id$"); - - -/* BTIndexAlignUp, BTIndexAlignDown -- Align bit-table indices - * - * Align bit-table indices up and down to word boundaries - */ - -#define BTIndexAlignUp(index) (IndexAlignUp((index), MPS_WORD_WIDTH)) -#define BTIndexAlignDown(index) (IndexAlignDown((index), MPS_WORD_WIDTH)) - - -/* BTMask -- generate sub-word masks - * - * Create a mask with only specified bits set - */ - -/* Return a word mask of bits set only from base and above */ -#define BTMaskLow(base) (~(Word)0 << (base)) - -/* Return a word mask of bits set only below limit */ -#define BTMaskHigh(limit) (~(Word)0 >> (MPS_WORD_WIDTH - (limit))) - -/* Return a word mask of bits set only in requested range */ -#define BTMask(base,limit) (BTMaskHigh((limit)) & BTMaskLow((base))) - - -/* BTWordIndex, BTBitIndex -- Decode BT indexes - * - * Return word and bit indexes from index - */ - -#define BTWordIndex(index) ((index) >> MPS_WORD_SHIFT) -#define BTBitIndex(index) ((index) & (MPS_WORD_WIDTH - 1)) - - -/* BTIsSmallRange -- test range size - * - * Predicate to determine whether a range is sufficiently small - * that it's not worth trying to separate words and odd bits. - * The choice of what counts as "sufficiently small" is made - * for efficiency reasons. Empirical evidence indicates that - * a good choice is ranges of size 6 or less. - */ - -#define BTIsSmallRange(base,limit) ((base) + 6 >= (limit)) - - -/* ACT_ON_RANGE -- macro to act on a base-limit range - * - * Three actions should be provided: - * - single_action(btIndex) - operates on a single bit - * - bits_action(wordIndex, base, limit) -- operates on part-words - * - word_action(wordIndex) -- Operates on full words in range - * WORD_ACTIONs should not use break or continue. - * - * If the range is small enough it will be processed a single - * bit at a time. Larger ranges are processed as words where - * possible, and part-words for boundary bits. - */ - -#define ACT_ON_RANGE(base,limit,single_action, \ - bits_action,word_action) \ - BEGIN \ - if (BTIsSmallRange((base), (limit))) { \ - /* Small ranges are processed most efficiently bit-by-bit */ \ - Index actBit; \ - for (actBit = (base); actBit < (limit); ++actBit) { \ - single_action(actBit); \ - } \ - } else { \ - Index actInnerBase = BTIndexAlignUp((base)); \ - if (actInnerBase > (limit)) { /* no inner range */ \ - AVER((base) < (limit)); /* caught by small range case */ \ - bits_action(BTWordIndex((base)), \ - BTBitIndex((base)), \ - BTBitIndex((limit))); \ - } else { \ - Index actInnerLimit = BTIndexAlignDown((limit)); \ - Index actWordIndex, actWordBase, actWordLimit; \ -\ - actWordBase = BTWordIndex(actInnerBase); \ - actWordLimit = BTWordIndex(actInnerLimit); \ -\ - if ((base) < actInnerBase) { \ - bits_action(actWordBase-1, \ - BTBitIndex((base)), \ - MPS_WORD_WIDTH); \ - } \ -\ - for (actWordIndex = actWordBase; actWordIndex < actWordLimit; \ - ++actWordIndex) { \ - word_action(actWordIndex); \ - } \ -\ - if ((limit) > actInnerLimit) { \ - bits_action(actWordLimit, 0, BTBitIndex((limit))); \ - } \ - } \ - } \ - END - - -/* ACT_ON_RANGE_HIGH -- macro to act on a base-limit range - * - * in reverse order. Usage as for ACT_ON_RANGE - */ - -#define ACT_ON_RANGE_HIGH(base,limit,single_action, \ - bits_action,word_action) \ - BEGIN \ - if (BTIsSmallRange((base), (limit))) { \ - /* Small ranges are processed most efficiently bit-by-bit */ \ - Index actBit; \ - for (actBit = (limit); actBit > (base); --actBit) { \ - single_action(actBit - 1); \ - } \ - } else { \ - Index actInnerBase = BTIndexAlignUp((base)); \ - if (actInnerBase > (limit)) { /* no inner range */ \ - AVER((base) < (limit)); /* caught by small range case */ \ - bits_action(BTWordIndex((base)), \ - BTBitIndex((base)), \ - BTBitIndex((limit))); \ - } else { \ - Index actInnerLimit = BTIndexAlignDown((limit)); \ - Index actWordIndex, actWordBase, actWordLimit; \ -\ - actWordBase = BTWordIndex(actInnerBase); \ - actWordLimit = BTWordIndex(actInnerLimit); \ -\ - if ((limit) > actInnerLimit) { \ - bits_action(actWordLimit, 0, BTBitIndex((limit))); \ - } \ -\ - for (actWordIndex = actWordLimit; actWordIndex > actWordBase; \ - --actWordIndex) { \ - word_action(actWordIndex-1); \ - } \ -\ - if ((base) < actInnerBase) { \ - bits_action(actWordBase-1, \ - BTBitIndex((base)), \ - MPS_WORD_WIDTH); \ - } \ - } \ - } \ - END - - - -/* BTCreate -- allocate a BT from the control pool - * - * See - */ - -Res BTCreate(BT *btReturn, Arena arena, Count length) -{ - Res res; - BT bt; - void *p; - - AVER(btReturn != NULL); - AVERT(Arena, arena); - AVER(length > 0); - - res = ControlAlloc(&p, arena, BTSize(length), - /* withReservoirPermit */ FALSE); - if (res != ResOK) - return res; - bt = (BT)p; - - *btReturn = bt; - return ResOK; -} - - -/* BTDestroy -- free a BT to the control pool. - * - * See - */ - -void BTDestroy(BT bt, Arena arena, Count length) -{ - AVER(bt != NULL); - AVERT(Arena, arena); - AVER(length > 0); - - ControlFree(arena, bt, BTSize(length)); -} - - -/* BTCheck -- check the validity of a bit table - * - * There's not much that can be checked at present. This is - * discussed in review.impl.c.bt.4. - */ - -static Bool BTCheck(BT bt) -{ - AVER(bt != NULL); - AVER(AddrIsAligned((Addr)bt, sizeof(Word))); - return TRUE; -} - - -/* BTSize -- return the size of a BT - * - * See - */ - -Size (BTSize)(Count n) -{ - /* check that the expression used in rounding up doesn't overflow */ - AVER(n+MPS_WORD_WIDTH-1 > n); - - return BTSize(n); -} - - -/* BTGet -- get a bit from a BT - * - * See - */ - -Bool (BTGet)(BT t, Index i) -{ - AVER(BTCheck(t)); - /* Can't check i */ - - /* see macro in */ - return BTGet(t, i); -} - - -/* BTSet -- set a bit in a BT - * - * See - */ - -void (BTSet)(BT t, Index i) -{ - AVER(BTCheck(t)); - /* Can't check i */ - - /* see macro in */ - BTSet(t, i); -} - - -/* BTRes -- reset a bit in a BT - * - * - */ - -void (BTRes)(BT t, Index i) -{ - AVER(BTCheck(t)); - /* Can't check i */ - - /* see macro in */ - BTRes(t, i); -} - - -/* BTSetRange -- set a range of bits in a BT - * - * - */ - -void BTSetRange(BT t, Index base, Index limit) -{ - AVER(BTCheck(t)); - AVER(base < limit); - -#define SINGLE_SET_RANGE(i) \ - BTSet(t, (i)) -#define BITS_SET_RANGE(i,base,limit) \ - t[(i)] |= BTMask((base),(limit)) -#define WORD_SET_RANGE(i) \ - t[(i)] = ~(Word)(0) - - ACT_ON_RANGE(base, limit, SINGLE_SET_RANGE, - BITS_SET_RANGE, WORD_SET_RANGE); -} - - -/* BTIsResRange -- test whether a range of bits is all reset - * - * See . - */ - -Bool BTIsResRange(BT bt, Index base, Index limit) -{ - AVER(BTCheck(bt)); - AVER(base < limit); - /* Can't check range of base or limit */ - -#define SINGLE_IS_RES_RANGE(i) \ - if (BTGet(bt, (i))) return FALSE -#define BITS_IS_RES_RANGE(i,base,limit) \ - if ((bt[(i)] & BTMask((base),(limit))) != (Word)0) return FALSE -#define WORD_IS_RES_RANGE(i) \ - if (bt[(i)] != (Word)0) return FALSE - - ACT_ON_RANGE(base, limit, SINGLE_IS_RES_RANGE, - BITS_IS_RES_RANGE, WORD_IS_RES_RANGE); - return TRUE; -} - - -/* BTIsSetRange -- test whether a range of bits is all set - * - * See . - */ - -Bool BTIsSetRange(BT bt, Index base, Index limit) -{ - AVER(BTCheck(bt)); - AVER(base < limit); - /* Can't check range of base or limit */ - -#define SINGLE_IS_SET_RANGE(i) \ - if (!BTGet(bt, (i))) return FALSE -#define BITS_IS_SET_RANGE(i,base,limit) \ - BEGIN \ - Word bactMask = BTMask((base),(limit)); \ - if ((bt[(i)] & bactMask) != bactMask) \ - return FALSE; \ - END -#define WORD_IS_SET_RANGE(i) \ - if (bt[(i)] != ~(Word)0) return FALSE - - ACT_ON_RANGE(base, limit, SINGLE_IS_SET_RANGE, - BITS_IS_SET_RANGE, WORD_IS_SET_RANGE); - return TRUE; -} - - -/* BTResRange -- reset a range of bits in a BT - * - * - */ - -void BTResRange(BT t, Index base, Index limit) -{ - AVER(BTCheck(t)); - AVER(base < limit); - -#define SINGLE_RES_RANGE(i) \ - BTRes(t, (i)) -#define BITS_RES_RANGE(i,base,limit) \ - t[(i)] &= ~(BTMask((base),(limit))) -#define WORD_RES_RANGE(i) t[(i)] = (Word)(0) - - ACT_ON_RANGE(base, limit, SINGLE_RES_RANGE, - BITS_RES_RANGE, WORD_RES_RANGE); -} - - -/* BTFindSet -- find the lowest set bit in a range in a bit table. - * - * Sets foundReturn to false if the range is entirely reset; - * in this case indexReturn is unset. Sets foundReturn to true - * otherwise. - * - * Implemented as a macro for efficiency reasons. - * The macro internally uses the label btFindSetLabel. - * If the macro must be used more than once within a function - * this label must be redefined to avoid a nameclash. E.g. - * #define btFindSetLabel uniqueLabel - * BTFindSet(...) - * #undef btFindSetLabel - */ - -#define BTFindSet(foundReturn,indexReturn,bt,base,limit)\ - BEGIN \ - Bool *bfsFoundReturn = (foundReturn); \ - Index *bfsIndexReturn = (indexReturn); \ - BT bfsBt = (bt); \ - ACT_ON_RANGE((base), (limit), SINGLE_FIND_SET, \ - BITS_FIND_SET, WORD_FIND_SET); \ - *bfsFoundReturn = FALSE; \ -btFindSetLabel:; \ - END - -#define SINGLE_FIND_SET(i) \ - if (BTGet(bfsBt, (i))) { \ - *bfsIndexReturn = (i); \ - *bfsFoundReturn = TRUE; \ - goto btFindSetLabel; \ - } -#define BITS_FIND_SET(wi,base,limit) \ - BEGIN \ - Index bactWi = (wi); \ - ACTION_FIND_SET(bactWi, bfsBt[bactWi], (base), (limit)); \ - END -#define WORD_FIND_SET(wi) \ - BEGIN \ - Index wactWi = (wi); \ - ACTION_FIND_SET(wactWi, bfsBt[wactWi], 0, MPS_WORD_WIDTH); \ - END -#define ACTION_FIND_SET(wi,word,base,limit) \ - ACTION_FIND_SET_BIT((wi),(word),(base),(limit),btFindSetLabel) - - -/* ACTION_FIND_SET_BIT -- Find first set bit in a range - * - * Helper macro to find the low bit in a range of a word. - * Works by first shifting the base of the range to the low - * bits of the word. Then loops performing a binary chop - * over the data looking to see if a bit is set in the lower - * half. If not, it must be in the upper half which is then - * shifted down. The loop completes after using a chop unit - * of a single single bit. - */ - -#define ACTION_FIND_SET_BIT(wi,word,base,limit,label) \ - BEGIN \ - /* no need to mask the low bits which are shifted */ \ - Index actionIndex = (base); \ - Word actionWord = ((word) & BTMaskHigh((limit))) >> actionIndex; \ - Count actionMaskWidth = (MPS_WORD_WIDTH >> 1); \ - Word actionMask = ~(Word)0 >> (MPS_WORD_WIDTH-actionMaskWidth); \ - if (actionWord != (Word)0) { \ - while (actionMaskWidth != (Count)0) { \ - if ((actionWord & actionMask) == (Word)0) { \ - actionIndex += actionMaskWidth; \ - actionWord >>= actionMaskWidth; \ - } \ - actionMaskWidth >>= 1; \ - actionMask >>= actionMaskWidth; \ - } \ - *bfsIndexReturn = ((wi) << MPS_WORD_SHIFT) | actionIndex; \ - *bfsFoundReturn = TRUE; \ - goto label; \ - } \ - END - - -/* BTFindRes -- find the lowest reset bit in a range in a bit table. - * - * Usage as for BTFindSet - * - * Internally uses the label btFindResLabel - * which must be redefined to avoid a nameclash if the macro is - * used twice in a function scope. - */ - -#define BTFindRes(foundReturn,indexReturn,bt,base,limit)\ - BEGIN \ - Bool *bfsFoundReturn = (foundReturn); \ - Index *bfsIndexReturn = (indexReturn); \ - BT bfsBt = (bt); \ - ACT_ON_RANGE((base), (limit), SINGLE_FIND_RES, \ - BITS_FIND_RES, WORD_FIND_RES); \ - *bfsFoundReturn = FALSE; \ -btFindResLabel:; \ - END - -#define SINGLE_FIND_RES(i) \ - if (!BTGet(bfsBt, (i))) { \ - *bfsIndexReturn = (i); \ - *bfsFoundReturn = TRUE; \ - goto btFindResLabel; \ - } -#define BITS_FIND_RES(wi,base,limit) \ - BEGIN \ - Index bactWi = (wi); \ - ACTION_FIND_RES(bactWi,bfsBt[bactWi], (base), (limit)); \ - END -#define WORD_FIND_RES(wi) \ - BEGIN \ - Index wactWi = (wi); \ - ACTION_FIND_RES(wactWi, bfsBt[wactWi], 0, MPS_WORD_WIDTH); \ - END -#define ACTION_FIND_RES(wi,word,base,limit) \ - ACTION_FIND_SET_BIT((wi),~(word),(base),(limit),btFindResLabel) - - -/* BTFindSetHigh -- find the highest set bit in a range in a bit table. - * - * Usage as for BTFindSet - * - * Internally uses the label btFindSetHighLabel - * which must be redefined to avoid a nameclash if the macro is - * used twice in a function scope. - */ - -#define BTFindSetHigh(foundReturn,indexReturn,bt,base,limit)\ - BEGIN \ - Bool *bfsFoundReturn = (foundReturn); \ - Index *bfsIndexReturn = (indexReturn); \ - BT bfsBt = (bt); \ - ACT_ON_RANGE_HIGH((base), (limit), SINGLE_FIND_SET_HIGH, \ - BITS_FIND_SET_HIGH, WORD_FIND_SET_HIGH); \ - *bfsFoundReturn = FALSE; \ -btFindSetHighLabel:; \ - END - -#define SINGLE_FIND_SET_HIGH(i) \ - if (BTGet(bfsBt, (i))) { \ - *bfsIndexReturn = (i); \ - *bfsFoundReturn = TRUE; \ - goto btFindSetHighLabel; \ - } -#define BITS_FIND_SET_HIGH(wi,base,limit) \ - BEGIN \ - Index bactWi = (wi); \ - ACTION_FIND_SET_HIGH(bactWi, bfsBt[bactWi], (base), (limit)); \ - END -#define WORD_FIND_SET_HIGH(wi) \ - BEGIN \ - Index wactWi = (wi); \ - ACTION_FIND_SET_HIGH(wactWi, (bfsBt[wactWi]), 0, MPS_WORD_WIDTH); \ - END -#define ACTION_FIND_SET_HIGH(wi,word,base,limit) \ - ACTION_FIND_SET_BIT_HIGH((wi),(word),(base),(limit),btFindSetHighLabel) - - -/* ACTION_FIND_SET_BIT_HIGH -- Find highest set bit in a range - * - * Helper macro to find the high bit in a range of a word. - * Essentially a mirror image of ACTION_FIND_SET - */ - -#define ACTION_FIND_SET_BIT_HIGH(wi,word,base,limit,label) \ - BEGIN \ - /* no need to mask the high bits which are shifted */ \ - Index actionShift = MPS_WORD_WIDTH - (limit); \ - Index actionIndex = MPS_WORD_WIDTH - 1 - actionShift; \ - Word actionWord = ((word) & BTMaskLow((base))) << actionShift; \ - Count actionMaskWidth = (MPS_WORD_WIDTH >> 1); \ - Word actionMask = ~(Word)0 << (MPS_WORD_WIDTH-actionMaskWidth); \ - if (actionWord != (Word)0) { \ - while (actionMaskWidth != (Count)0) { \ - if ((actionWord & actionMask) == (Word)0) { \ - actionIndex -= actionMaskWidth; \ - actionWord <<= actionMaskWidth; \ - } \ - actionMaskWidth >>= 1; \ - actionMask <<= actionMaskWidth; \ - } \ - *bfsIndexReturn = ((wi) << MPS_WORD_SHIFT) | actionIndex; \ - *bfsFoundReturn = TRUE; \ - goto label; \ - } \ - END - - -/* BTFindResHigh -- find the highest reset bit in a range - * - * Usage as for BTFindSet - * - * Internally uses the label btFindSetHighLabel - * which must be redefined to avoid a nameclash if the macro is - * used twice in a function scope. - */ - -#define BTFindResHigh(foundReturn,indexReturn,bt,base,limit)\ - BEGIN \ - Bool *bfsFoundReturn = (foundReturn); \ - Index *bfsIndexReturn = (indexReturn); \ - BT bfsBt = (bt); \ - ACT_ON_RANGE_HIGH((base), (limit), SINGLE_FIND_RES_HIGH, \ - BITS_FIND_RES_HIGH, WORD_FIND_RES_HIGH); \ - *bfsFoundReturn = FALSE; \ -btFindResHighLabel:; \ - END - -#define SINGLE_FIND_RES_HIGH(i) \ - if (!BTGet(bfsBt, (i))) { \ - *bfsIndexReturn = (i); \ - *bfsFoundReturn = TRUE; \ - goto btFindResHighLabel; \ - } -#define BITS_FIND_RES_HIGH(wi,base,limit) \ - BEGIN \ - Index bactWi = (wi); \ - ACTION_FIND_RES_HIGH(bactWi, bfsBt[bactWi], (base), (limit)); \ - END -#define WORD_FIND_RES_HIGH(wi) \ - BEGIN \ - Index wactWi = (wi); \ - ACTION_FIND_RES_HIGH(wactWi, (bfsBt[wactWi]), 0, MPS_WORD_WIDTH); \ - END -#define ACTION_FIND_RES_HIGH(wi,word,base,limit) \ - ACTION_FIND_SET_BIT_HIGH((wi),~(word),(base),(limit),btFindResHighLabel) - - -/* BTFindResRange -- find a reset range of bits in a bit table - * - * Starts searching at the low end of the search range. - * - * See . - */ - -static Bool BTFindResRange(Index *baseReturn, Index *limitReturn, - BT bt, - Index searchBase, Index searchLimit, - Count minLength, Count maxLength) -{ - Bool foundRes; /* true if a reset bit is found */ - Index resBase; /* base of a candidate reset range */ - Index unseenBase; /* base of testing so far */ - Index minLimit; /* limit of minimal acceptable range */ - Index resLimit; /* limit of search for a candidate range */ - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(BT, bt); - AVER(searchBase < searchLimit); - AVER(minLength > 0); - AVER(minLength <= maxLength); - AVER(maxLength <= searchLimit - searchBase); - - foundRes = FALSE; /* don't know first reset bit */ - minLimit = 0; /* avoid spurious compiler warning */ - resBase = searchBase; /* haven't seen anything yet */ - unseenBase = searchBase; /* haven't seen anything yet */ - resLimit = searchLimit - minLength + 1; - - while (resBase < resLimit) { - Index setIndex; /* index of last set bit found */ - Bool foundSet = FALSE; /* true if a set bit is found */ - - /* Find the first reset bit if it's not already known */ - if (!foundRes) { - BTFindRes(&foundRes, &resBase, bt, unseenBase, resLimit); - if (!foundRes) { - /* failure */ - return FALSE; - } - unseenBase = resBase + 1; - minLimit = resBase + minLength; - } - - /* Look to see if there is any set bit in the minimum range */ - BTFindSetHigh(&foundSet, &setIndex, bt, unseenBase, minLimit); - if (!foundSet) { - /* Found minimum range. Extend it. */ - Index setBase; /* base of search for set bit */ - Index setLimit; /* limit search for set bit */ - foundSet = FALSE; - setBase = minLimit; - setLimit = resBase + maxLength; - if (setLimit > searchLimit) - setLimit = searchLimit; - if (setLimit > setBase) - BTFindSet(&foundSet, &setIndex, bt, setBase, setLimit); - if (!foundSet) - setIndex = setLimit; - - AVER(setIndex - resBase >= minLength); - AVER(setIndex - resBase <= maxLength); - *baseReturn = resBase; - *limitReturn = setIndex; - return TRUE; - - } else { - /* Range was too small. Try again */ - unseenBase = minLimit; - resBase = setIndex + 1; - if (resBase != minLimit) { - /* Already found the start of next candidate range */ - minLimit = resBase + minLength; - } else { - foundRes = FALSE; - } - } - } - - /* failure */ - return FALSE; -} - - -/* BTFindResRangeHigh -- find a reset range of bits in a bit table - * - * Starts searching at the high end of the search range. - * - * See . - */ - -static Bool BTFindResRangeHigh(Index *baseReturn, Index *limitReturn, - BT bt, - Index searchBase, Index searchLimit, - Count minLength, - Count maxLength) -{ - Bool foundRes; /* true if a reset bit is found */ - Index resLimit; /* limit of a candidate reset range */ - Index resIndex; /* index of highest reset bit found */ - Index unseenLimit; /* limit of testing so far */ - Index minBase; /* base of minimal acceptable range */ - Index resBase; /* base of search for a candidate range */ - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(BT, bt); - AVER(searchBase < searchLimit); - AVER(minLength > 0); - AVER(minLength <= maxLength); - AVER(maxLength <= searchLimit - searchBase); - - foundRes = FALSE; /* don't know first reset bit */ - minBase = 0; /* avoid spurious compiler warning */ - resLimit = searchLimit; /* haven't seen anything yet */ - unseenLimit = searchLimit; /* haven't seen anything yet */ - resBase = searchBase + minLength -1; - - while (resLimit > resBase) { - Index setIndex; /* index of first set bit found */ - Bool foundSet = FALSE; /* true if a set bit is found */ - - /* Find the first reset bit if it's not already known */ - if (!foundRes) { - /* Look for the limit of a range */ - BTFindResHigh(&foundRes, &resIndex, bt, resBase, unseenLimit); - if (!foundRes) { - /* failure */ - return FALSE; - } - resLimit = resIndex + 1; - unseenLimit = resIndex; - minBase = resLimit - minLength; - } - - /* Look to see if there is any set bit in the minimum range */ - BTFindSet(&foundSet, &setIndex, bt, minBase, unseenLimit); - if (!foundSet) { - /* Found minimum range. Extend it. */ - Index setBase; /* base of search for set bit */ - Index setLimit; /* limit search for set bit */ - Index baseIndex; /* base of reset range found */ - foundSet = FALSE; - setLimit = minBase; - if ((searchBase + maxLength) > resLimit) - setBase = searchBase; - else - setBase = resLimit - maxLength; - if (setLimit > setBase) - BTFindSetHigh(&foundSet, &setIndex, bt, setBase, setLimit); - if (foundSet) - baseIndex = setIndex+1; - else - baseIndex = setBase; - - AVER(resLimit - baseIndex >= minLength); - AVER(resLimit - baseIndex <= maxLength); - *baseReturn = baseIndex; - *limitReturn = resLimit; - return TRUE; - - } else { - /* Range was too small. Try again */ - unseenLimit = minBase; - resLimit = setIndex; - if (resLimit != minBase) { - /* Already found the start of next candidate range */ - minBase = resLimit - minLength; - } else { - foundRes = FALSE; - } - } - } - - /* failure */ - return FALSE; -} - - -/* BTFindLongResRange -- find long range of reset bits in a bit table - * - * See . - */ - -Bool BTFindLongResRange(Index *baseReturn, Index *limitReturn, - BT bt, - Index searchBase, Index searchLimit, - Count length) -{ - /* All parameters are checked by BTFindResRange. */ - return BTFindResRange(baseReturn, limitReturn, - bt, - searchBase, searchLimit, - length, searchLimit - searchBase); -} - - -/* BTFindLongResRangeHigh -- find long range of reset bits in a bit table - * - * See . - */ - -Bool BTFindLongResRangeHigh(Index *baseReturn, Index *limitReturn, - BT bt, - Index searchBase, Index searchLimit, - Count length) -{ - /* All parameters are checked by BTFindResRangeHigh. */ - return BTFindResRangeHigh(baseReturn, limitReturn, - bt, - searchBase, searchLimit, - length, searchLimit - searchBase); -} - - -/* BTFindShortResRange -- find short range of reset bits in a bit table - * - * See . - */ - -Bool BTFindShortResRange(Index *baseReturn, Index *limitReturn, - BT bt, - Index searchBase, Index searchLimit, - Count length) -{ - /* All parameters are checked by BTFindResRange. */ - return BTFindResRange(baseReturn, limitReturn, - bt, - searchBase, searchLimit, - length, length); -} - -/* BTFindShortResRangeHigh -- find short range of reset bits in a bit table - * - * Starts looking from the top of the search range. - * - * See . - */ - -Bool BTFindShortResRangeHigh(Index *baseReturn, Index *limitReturn, - BT bt, - Index searchBase, Index searchLimit, - Count length) -{ - /* All parameters are checked by BTFindResRangeHigh. */ - return BTFindResRangeHigh(baseReturn, limitReturn, - bt, - searchBase, searchLimit, - length, length); -} - - -/* BTRangesSame -- check that a range of bits in two BTs are the same. - * - * See - */ - -Bool BTRangesSame(BT comparand, BT comparator, Index base, Index limit) -{ - AVER(BTCheck(comparand)); - AVER(BTCheck(comparator)); - AVER(base < limit); - -#define SINGLE_RANGES_SAME(i) \ - if (BTGet(comparand, (i)) != BTGet(comparator, (i))) \ - return FALSE -#define BITS_RANGES_SAME(i,base,limit) \ - BEGIN \ - Index bactI = (i); \ - Word bactMask = BTMask((base),(limit)); \ - if ((comparand[bactI] & (bactMask)) != \ - (comparator[bactI] & (bactMask))) \ - return FALSE; \ - END -#define WORD_RANGES_SAME(i) \ - BEGIN \ - Index wactI = (i); \ - if ((comparand[wactI]) != (comparator[wactI])) \ - return FALSE; \ - END - - ACT_ON_RANGE(base, limit, SINGLE_RANGES_SAME, - BITS_RANGES_SAME, WORD_RANGES_SAME); - return TRUE; -} - - -/* BTCopyInvertRange -- copy a range of bits from one BT to another, - * inverting them as you go. - * - * See - */ - -void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit) -{ - AVER(BTCheck(fromBT)); - AVER(BTCheck(toBT)); - AVER(fromBT != toBT); - AVER(base < limit); - -#define SINGLE_COPY_INVERT_RANGE(i) \ - if (BTGet(fromBT, (i))) \ - BTRes(toBT, (i)); \ - else \ - BTSet(toBT, (i)) -#define BITS_COPY_INVERT_RANGE(i,base,limit) \ - BEGIN \ - Index bactI = (i); \ - Word bactMask = BTMask((base),(limit)); \ - toBT[bactI] = \ - (toBT[bactI] & ~bactMask) | (~fromBT[bactI] & bactMask); \ - END -#define WORD_COPY_INVERT_RANGE(i) \ - BEGIN \ - Index wactI = (i); \ - toBT[wactI] = ~fromBT[wactI]; \ - END - - ACT_ON_RANGE(base, limit, SINGLE_COPY_INVERT_RANGE, - BITS_COPY_INVERT_RANGE, WORD_COPY_INVERT_RANGE); -} - - -/* BTCopyRange -- copy a range of bits from one BT to another - * - * See - */ - -void BTCopyRange(BT fromBT, BT toBT, Index base, Index limit) -{ - AVER(BTCheck(fromBT)); - AVER(BTCheck(toBT)); - AVER(fromBT != toBT); - AVER(base < limit); - -#define SINGLE_COPY_RANGE(i) \ - if (BTGet(fromBT, (i))) \ - BTSet(toBT, (i)); \ - else \ - BTRes(toBT, (i)) -#define BITS_COPY_RANGE(i,base,limit) \ - BEGIN \ - Index bactI = (i); \ - Word bactMask = BTMask((base),(limit)); \ - toBT[bactI] = \ - (toBT[bactI] & ~bactMask) | (fromBT[bactI] & bactMask); \ - END -#define WORD_COPY_RANGE(i) \ - BEGIN \ - Index wactI = (i); \ - toBT[wactI] = fromBT[wactI]; \ - END - - ACT_ON_RANGE(base, limit, SINGLE_COPY_RANGE, - BITS_COPY_RANGE, WORD_COPY_RANGE); -} - - -/* BTCopyOffsetRange -- copy a range of bits from one BT to an - * offset range in another BT - * - * .slow: Can't always use ACT_ON_RANGE because word alignment - * may differ for each range. We could try to be smart about - * detecting similar alignment - but we don't. - * - * See - */ - -void BTCopyOffsetRange(BT fromBT, BT toBT, - Index fromBase, Index fromLimit, - Index toBase, Index toLimit) -{ - Index fromBit, toBit; - - AVER(BTCheck(fromBT)); - AVER(BTCheck(toBT)); - AVER(fromBT != toBT); - AVER(fromBase < fromLimit); - AVER(toBase < toLimit); - AVER((fromLimit - fromBase) == (toLimit - toBase)); - - for (fromBit = fromBase, toBit = toBase; - fromBit < fromLimit; - ++fromBit, ++toBit) { - if (BTGet(fromBT, fromBit)) - BTSet(toBT, toBit); - else - BTRes(toBT, toBit); - } -} - - -/* BTCountResRange -- count number of reset bits in a range */ - -Count BTCountResRange(BT bt, Index base, Index limit) -{ - Count c = 0; - Index bit; - - AVER(BTCheck(bt)); - AVER(base < limit); - - for (bit = base; bit < limit; ++bit) - if (!BTGet(bt, bit)) ++c; - return c; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/bt.h b/mps/code/bt.h deleted file mode 100644 index 29000b957b8..00000000000 --- a/mps/code/bt.h +++ /dev/null @@ -1,116 +0,0 @@ -/* bt.h: Bit Table Interface - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .source: - */ - -#ifndef bt_h -#define bt_h - -#include "mpmtypes.h" - - -/* */ -extern Size (BTSize)(Count length); -#define BTSize(n) (((n) + MPS_WORD_WIDTH-1) / MPS_WORD_WIDTH * sizeof(Word)) - -/* */ -extern Bool (BTGet)(BT bt, Index index); -#define BTGet(a, i) \ - ((Bool)(((a)[((i) >> MPS_WORD_SHIFT)] \ - >> ((i) & ~((Word)-1 << MPS_WORD_SHIFT))) \ - & (Word)1)) - -/* */ -extern void (BTSet)(BT bt, Index index); -#define BTSet(a, i) \ - BEGIN \ - (a)[((i)>>MPS_WORD_SHIFT)] |= (Word)1<<((i)&~((Word)-1< */ -extern void (BTRes)(BT bt, Index index); -#define BTRes(a, i) \ - BEGIN \ - (a)[((i)>>MPS_WORD_SHIFT)] &= \ - ~((Word)1 << ((i) & ~((Word)-1<. - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/btcv.c b/mps/code/btcv.c deleted file mode 100644 index fd411ee461b..00000000000 --- a/mps/code/btcv.c +++ /dev/null @@ -1,611 +0,0 @@ -/* btss.c: BIT TABLE COVERAGE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS developers - * - * .coverage: Direct coverage of BTFind*ResRange*, BTRangesSame, - * BTISResRange, BTIsSetRange, BTCopyRange, BTCopyOffsetRange. - * Reasonable coverage of BTCopyInvertRange, BTResRange, - * BTSetRange, BTRes, BTSet, BTCreate, BTDestroy. - */ - - -#include "mpm.h" -#include "mpsavm.h" -#include "mps.h" -#include "testlib.h" - -#include - -SRCID(btcv, "$Id$"); - - -/* bt*Symmetric -- Symmetric operations on bit tables - * - * The operations take 2 bit tables, btlo & bthi. - * They perform the equivalent BT* operation on btlo, and - * a reflected operation on the bits of bthi from the opposite - * direction. - */ - -#define btReflectIndex(btSize, i) (btSize - (i) - 1) -#define btReflectLimit(btSize, i) (btSize - (i)) - - -static void btSetSymmetric(BT btlo, BT bthi, Count btSize, Index i) -{ - BTSet(btlo, i); - BTSet(bthi, btReflectIndex(btSize, i)); -} - -static void btResSymmetric(BT btlo, BT bthi, Count btSize, Index i) -{ - BTRes(btlo, i); - BTRes(bthi, btReflectIndex(btSize, i)); -} - -static void btSetRangeSymmetric(BT btlo, BT bthi, Count btSize, - Index base, Index limit) -{ - BTSetRange(btlo, base, limit); - BTSetRange(bthi, btReflectLimit(btSize, limit), btReflectLimit(btSize, base)); -} - -static void btResRangeSymmetric(BT btlo, BT bthi, Count btSize, - Index base, Index limit) -{ - BTResRange(btlo, base, limit); - BTResRange(bthi, btReflectLimit(btSize, limit), btReflectLimit(btSize, base)); -} - - -typedef Bool (*BTFinderFn)(Index *foundBase_o, Index *foundLimit_o, - BT bt, Index base, Index limit, Count length); - - -/* btTestSingleRange -- Test expectations for calls to BTFind*ResRange* - * - */ - -static void btTestSingleRange(BTFinderFn finder, BT bt, - Index base, Index limit, - Count length, - Bool expect, - Index expectBase, Index expectLimit) -{ - Bool found; - Index foundBase, foundLimit; - - found = finder(&foundBase, &foundLimit, bt, base, limit, length); - cdie(found == expect, "FindResRange result"); - if (expect) { - cdie(foundBase == expectBase, "FindResRange base"); - cdie(foundLimit == expectLimit, "FindResRange limit"); - } -} - - -/* btTestResRange -- Test expectations for calls to BTFindShortResRange - * - * Symmetrically call BTFindShortResRange / BTFindShortResRangeHigh - * and test the expected results - */ - -static void btTestResRange(BT btlo, BT bthi, Count btSize, - Index base, Index limit, - Count length, - Bool expect, - Index expectBase, Index expectLimit) -{ - btTestSingleRange(BTFindShortResRange, btlo, - base, limit, - length, expect, - expectBase, expectLimit); - - btTestSingleRange(BTFindShortResRangeHigh, bthi, - btReflectLimit(btSize, limit), - btReflectLimit(btSize, base), - length, expect, - btReflectLimit(btSize, expectLimit), - btReflectLimit(btSize, expectBase)); -} - - -/* btTestLongResRange -- Test expectations for calls to BTFindLongResRange - * - * Symmetrically call BTFindLongResRange / BTFindLongResRangeHigh - * and test the expected results - */ - -static void btTestLongResRange(BT btlo, BT bthi, Count btSize, - Index base, Index limit, - Count length, - Bool expect, - Index expectBase, Index expectLimit) -{ - btTestSingleRange(BTFindLongResRange, btlo, - base, limit, - length, expect, - expectBase, expectLimit); - - btTestSingleRange(BTFindLongResRangeHigh, bthi, - btReflectLimit(btSize, limit), - btReflectLimit(btSize, base), - length, expect, - btReflectLimit(btSize, expectLimit), - btReflectLimit(btSize, expectBase)); -} - - -/* btAllResTest -- tests with only a reset range - * - * Test finding reset ranges in an all-reset table. - */ - -static void btAllResTest(BT btlo, BT bthi, Count btSize, - Index base, Index limit, - Count length) -{ - btResRangeSymmetric(btlo, bthi, btSize, 0, btSize); - btTestResRange(btlo, bthi, btSize, base, limit, length, - TRUE, base, base + length); - btTestLongResRange(btlo, bthi, btSize, base, limit, length, - TRUE, base, limit); -} - - -/* btNoResTest -- tests with no reset ranges - * - * Test finding reset ranges in an all-set search area of a table. - * Reset the area outside the search to ensure it doesn't get found - * by mistake. - */ - -static void btNoResTest(BT btlo, BT bthi, Count btSize, - Index base, Index limit, - Count length) -{ - btResRangeSymmetric(btlo, bthi, btSize, 0, btSize); - btSetRangeSymmetric(btlo, bthi, btSize, base, limit); - btTestResRange(btlo, bthi, btSize, base, limit, length, - FALSE, 0, 0); - btTestLongResRange(btlo, bthi, btSize, base, limit, length, - FALSE, 0, 0); -} - - -/* btResAndFindTest -- Test finding ranges of given size - * - * Resets the range between resBase & resLimit, and then attempts - * to find it by searching in the range between base & limit. - * Expect to find the range if it's long enough, - */ - -static void btResAndFindTest(BT btlo, BT bthi, Count btSize, - Index base, Index limit, - Index resBase, Index resLimit, - Count length) -{ - btResRangeSymmetric(btlo, bthi, btSize, resBase, resLimit); - if ((resLimit - resBase) < length) { - btTestResRange(btlo, bthi, btSize, base, limit, length, - FALSE, 0, 0); - btTestLongResRange(btlo, bthi, btSize, base, limit, length, - FALSE, 0, 0); - } else { - btTestResRange(btlo, bthi, btSize, base, limit, length, - TRUE, resBase, resBase + length); - btTestLongResRange(btlo, bthi, btSize, base, limit, length, - TRUE, resBase, resLimit); - } -} - - - -/* btSingleResTest -- tests with a single reset range - * - * Test finding single ranges of various sizes - */ - -static void btSingleResTest(BT btlo, BT bthi, Count btSize, - Index base, Index limit, - Count length) -{ - Count resLen; - /* choose varying range lengths from too short to longer than needed */ - for (resLen = length - 1; resLen <= length + 1; resLen++) { - if ((resLen > 0) && (resLen < (limit - base -2))) { - /* place the ranges both near the beginning & near the end */ - /* of the search space */ - Index resBase, resLimit; - for (resBase = base; resBase <= base +2; resBase++) { - btResRangeSymmetric(btlo, bthi, btSize, 0, btSize); - btSetRangeSymmetric(btlo, bthi, btSize, base, limit); - btResAndFindTest(btlo, bthi, btSize, base, limit, - resBase, resBase + resLen, length); - } - for (resLimit = limit; resLimit >= limit -2; resLimit--) { - btResRangeSymmetric(btlo, bthi, btSize, 0, btSize); - btSetRangeSymmetric(btlo, bthi, btSize, base, limit); - btResAndFindTest(btlo, bthi, btSize, base, limit, - resLimit - resLen, resLimit, length); - } - } - } -} - - - -/* btDoubleResTest -- Test finding double ranges of various sizes - * - * Set up 2 ranges with various relative positions. The first - * range is always too small. - */ - - -/* Constants describing the type of arrangement of the 2 ranges */ -enum { - ArrangeGAP1 = 0, - ArrangeGAP2 = 1, - ArrangeSPREAD = 2, - ArrangeMAX -}; - -typedef unsigned Arrangement; - -/* Choose a limit for reset range 1 */ -static Index btArrangeRes1(Arrangement arrange, - Index base, Index res2Base, - Count length) -{ - switch (arrange) { - - case ArrangeGAP1: { - /* Gap between ranges is of length 1 */ - return res2Base - 1; - } - - case ArrangeGAP2: { - /* Gap between ranges is of length 2 */ - return res2Base - 2; - } - - case ArrangeSPREAD: { - /* range 1 starts as far before range 2 as possible */ - return base + length; - } - - default: - NOTREACHED; - return 0; /* keep the compiler happy */ - } -} - -/* Constants describing the type of pattern for the first range */ -enum { - PatternLEN1 = 0, - PatternSETMID = 1, - PatternJUSTSMALL = 2, - PatternMAX -}; - -typedef unsigned Pattern; - -/* Choose a limit for reset range 1 */ -static void btResetFirstRange(BT btlo, BT bthi, Count btSize, - Index res1Limit, - Count length, - Pattern pattern) -{ - switch (pattern) { - - case PatternLEN1: { - /* First range is a single reset bit */ - btResSymmetric(btlo, bthi, btSize, res1Limit-1); - return; - } - - case PatternSETMID: { - /* Actually make 2 ranges here by setting a bit in the middle */ - Index mid = res1Limit - length + (length / 2); - btResRangeSymmetric(btlo, bthi, btSize, res1Limit-length, res1Limit); - btSetSymmetric(btlo, bthi, btSize, mid); - return; - } - - case PatternJUSTSMALL: { - /* Range of (length - 1) */ - btResRangeSymmetric(btlo, bthi, btSize, - 1 + res1Limit - length, res1Limit); - return; - } - - default: - NOTREACHED; - } -} - - -static void btDoubleResTest(BT btlo, BT bthi, Count btSize, - Index base, Index limit, - Count length) -{ - Count res2Len; - - if (length < 2) - return; /* no possibility of making the first range too small */ - - /* choose varying range lengths for second res range */ - for (res2Len = length - 1; res2Len <= length + 1; res2Len++) { - if ((res2Len > 0) && (res2Len < (limit - base -2))) { - Index res2Limit; - /* place the second ranges near the end of the search space */ - for (res2Limit = limit; res2Limit >= limit-8; res2Limit--) { - Index res2Base = res2Limit - res2Len; - Arrangement arrange; - /* Pick one of a number of possible arrangements of the ranges */ - for (arrange = ArrangeGAP1; arrange < ArrangeMAX; arrange++) { - Index res1Limit = btArrangeRes1(arrange, base, res2Base, length); - Pattern pat; - /* Pick one of a number of pattern types for range 1 */ - for (pat = PatternLEN1; pat < PatternMAX; pat++) { - btResRangeSymmetric(btlo, bthi, btSize, 0, btSize); - btSetRangeSymmetric(btlo, bthi, btSize, base, limit); - btResetFirstRange(btlo, bthi, btSize, res1Limit, length, pat); - /* Set up range 2 and expect to find it when searching */ - btResAndFindTest(btlo, bthi, btSize, base, limit, - res2Base, res2Limit, length); - } - } - } - } - } -} - - -/* btFindRangeTests -- Test BTFind*ResRange* - * - * Run a variety of FindResRange tests with different table patterns. - */ - -static void btFindRangeTests(BT btlo, BT bthi, Count btSize, - Index base, Index limit, - Count length) -{ - btAllResTest(btlo, bthi, btSize, base, limit, length); - btNoResTest(btlo, bthi, btSize, base, limit, length); - btSingleResTest(btlo, bthi, btSize, base, limit, length); - btDoubleResTest(btlo, bthi, btSize, base, limit, length); -} - - - -/* btIsRangeTests -- Test BTIsResRange & BTIsSetRange - * - * Test ranges which are all reset or set apart from single - * bits near to the base and limit (both inside and outside - * the range). - * - * Test BTRangesSame by using the same bit patterns and comparing - * with an appropriate all-set or all-reset table. - * - * These tests also test BTCopyInvertRange - */ - -static void btIsRangeTests(BT bt1, BT bt2, Count btSize, - Index base, Index limit) -{ - Index minBase, maxLimit, b, l; - - if (base > 0) { - minBase = base - 1; - } else { - minBase = 0; - } - - if (limit < btSize) { - maxLimit = limit + 1; - } else { - maxLimit = btSize; - } - - for (b = minBase; b <= base+1; b++) { - for (l = maxLimit; l >= limit-1; l--) { - /* test a table which is all reset apart from a set bit */ - /* near each of the base and limit of the range in question */ - Bool outside; /* true if set bits are both outside test range */ - - outside = (b < base) && (l > limit); - BTResRange(bt1, 0, btSize); - BTSet(bt1, b); - BTSet(bt1, l - 1); - - /* invert the table for the inverse test */ - BTCopyInvertRange(bt1, bt2, 0, btSize); - - /* Check it with BTIsResRange, and the inverse with BTIsSetRange */ - cdie(BTIsResRange(bt1, base, limit) == outside, "BTISResRange"); - cdie(BTIsSetRange(bt2, base, limit) == outside, "BTISSetRange"); - - /* Check the same range with BTRangesSame on an empty table */ - BTResRange(bt2, 0, btSize); - cdie(BTRangesSame(bt1, bt2, base, limit) == outside, "BTRangeSame"); - - /* Check the inverse with BTRangesSame on a full table */ - BTCopyInvertRange(bt1, bt2, 0, btSize); - BTSetRange(bt1, 0, btSize); - cdie(BTRangesSame(bt1, bt2, base, limit) == outside, "BTRangeSame"); - } - } -} - - -/* btCopyTests -- Test BTCopyRange & BTCopyOffsetRange - * - * Test copying ranges which are all reset or set apart from - * single bits near to the base and limit (both inside and outside - * the range). - * - */ - -static void btCopyTests(BT bt1, BT bt2, Count btSize, - Index base, Index limit) -{ - Index minBase, maxLimit, b, l; - - if (base > 0) { - minBase = base - 1; - } else { - minBase = 0; - } - - if (limit < btSize) { - maxLimit = limit + 1; - } else { - maxLimit = btSize; - } - - for (b = minBase; b <= base+1; b++) { - for (l = maxLimit; l >= limit-1; l--) { - /* initialize a table which is all reset apart from a set bit */ - /* near each of the base and limit of the range in question */ - Bool outside; /* true if set bits are both outside test range */ - - outside = (b < base) && (l > limit); - BTResRange(bt1, 0, btSize); - BTSet(bt1, b); - BTSet(bt1, l - 1); - - /* check copying the region to the bottom of the other table */ - BTCopyOffsetRange(bt1, bt2, base, limit, 0, limit - base); - cdie(BTIsResRange(bt2, 0, limit - base) == outside, "BTIsResRange"); - - /* check copying the region to the top of the other table */ - BTCopyOffsetRange(bt1, bt2, - base, limit, btSize + base - limit, btSize); - cdie(BTIsResRange(bt2, btSize + base - limit, btSize) == outside, - "BTIsResRange"); - - /* check copying the region to the same place in the other table */ - BTCopyOffsetRange(bt1, bt2, base, limit, base, limit); - cdie(BTIsResRange(bt2, base, limit) == outside, "BTIsResRange"); - - /* copy the range and check its the same */ - BTCopyRange(bt1, bt2, base, limit); - cdie(BTRangesSame(bt1, bt2, base, limit), "BTRangeSame"); - - /* invert the table, then copy it and check it again */ - BTCopyInvertRange(bt2, bt1, 0, btSize); - BTCopyRange(bt1, bt2, base, limit); - cdie(BTRangesSame(bt1, bt2, base, limit), "BTRangeSame"); - } - } -} - - - -/* btTests -- Do all the tests - */ - -static void btTests(BT btlo, BT bthi, Count btSize) -{ - Index base, limit; - - /* Perform lots of tests over different subranges */ - for (base = 0; base < MPS_WORD_WIDTH; base++) { - for (limit = btSize; limit > (btSize-MPS_WORD_WIDTH); limit--) { - /* Perform Is*Range tests over those subranges */ - btIsRangeTests(btlo, bthi, btSize, base, limit); - - /* Perform Copy*Range tests over those subranges */ - btCopyTests(btlo, bthi, btSize, base, limit); - - /* Perform FindResRange tests with different lengths */ - btFindRangeTests(btlo, bthi, btSize, base, limit, 1); - btFindRangeTests(btlo, bthi, btSize, base, limit, 2); - btFindRangeTests(btlo, bthi, btSize, base, limit, MPS_WORD_WIDTH - 1); - btFindRangeTests(btlo, bthi, btSize, base, limit, MPS_WORD_WIDTH); - btFindRangeTests(btlo, bthi, btSize, base, limit, MPS_WORD_WIDTH + 1); - btFindRangeTests(btlo, bthi, btSize, base, limit, limit - base -1); - btFindRangeTests(btlo, bthi, btSize, base, limit, limit - base); - } - } -} - - -/* Start the world */ - -#define testArenaSIZE (((size_t)64)<<20) - -int main(int argc, char *argv[]) -{ - mps_arena_t mpsArena; - Arena arena; /* the ANSI arena which we use to allocate the BT */ - BT btlo, bthi; - Count btSize; - - /* tests need 4 whole words plus a few extra bits */ - btSize = MPS_WORD_WIDTH * 4 + 10; - - testlib_unused(argc); - testlib_unused(argv); - - die(mps_arena_create(&mpsArena, mps_arena_class_vm(), testArenaSIZE), - "mps_arena_create"); - arena = (Arena)mpsArena; /* avoid pun */ - - die((mps_res_t)BTCreate(&btlo, arena, btSize), - "failed to create low bit table"); - - die((mps_res_t)BTCreate(&bthi, arena, btSize), - "failed to create high bit table"); - - btTests(btlo, bthi, btSize); - - printf("\nNo problems detected.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/bttest.c b/mps/code/bttest.c deleted file mode 100644 index c119fe70a34..00000000000 --- a/mps/code/bttest.c +++ /dev/null @@ -1,426 +0,0 @@ -/* bttest.c: BIT TABLE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - - -#include "mpm.h" -#include "mps.h" -#include "mpsavm.h" -#include "testlib.h" - -#include -#include -#include "mpstd.h" -#include - -SRCID(bttest, "$Id$"); - - -static BT bt; /* the BT which we will use */ -static Size btSize; /* the size of the current BT */ -static Arena arena; /* the arena which we use to allocate the BT */ - - -#define MAX_ARGS 3 - - -static Word args[MAX_ARGS]; -static Count argCount; - - -static Bool argInRange(Index arg) -{ - if (bt == NULL) { - printf("no BT\n"); - return FALSE; - } - if (args[arg] >= btSize) { - printf("out of range\n"); - return FALSE; - } - return TRUE; -} - - -static Bool checkDefaultRange(Index arg) -{ - if (bt == NULL) { - printf("no BT\n"); - return FALSE; - } - if (argCount == arg+1) { - printf("range half-specified\n"); - return FALSE; - } - if (argCount == arg) { /* use default range */ - args[arg] = 0; - args[arg+1] = btSize; - return TRUE; - } - if (args[arg] >= args[arg+1]) { - printf("range ill-formed\n"); - return FALSE; - } - if (args[arg+1] > btSize) { - printf("range too high\n"); - return FALSE; - } - return TRUE; /* explicit valid range */ -} - - -static void quit(void) -{ - exit(0); -} - - -static void destroy(void) -{ - if (bt != NULL) { - BTDestroy(bt, arena, btSize); - bt = NULL; - } else { - printf("No BT to destroy\n"); - } -} - -static void create(void) -{ - Res res; - if (args[0] < 1) { - printf("can't create a BT of size 0\n"); - return; - } - if (bt != NULL) - destroy(); - res = BTCreate(&bt, arena, args[0]); - if (res == ResOK) { - btSize = args[0]; - BTResRange(bt, 0, btSize); - } else { - printf("BTCreate returned %d\n",res); - } -} - - -static void set(void) -{ - if (argInRange(0)) - (BTSet)(bt, args[0]); -} - - -static void reset(void) -{ - if (argInRange(0)) - (BTRes)(bt, args[0]); -} - - -static void get(void) -{ - if (argInRange(0)) { - Bool b = (BTGet)(bt, args[0]); - printf(b ? "TRUE\n" : "FALSE\n"); - } -} - - -static void setRange(void) -{ - if (checkDefaultRange(0)) - BTSetRange(bt, args[0], args[1]); -} - - -static void resetRange(void) -{ - if (checkDefaultRange(0)) - BTResRange(bt, args[0], args[1]); -} - - -static void isSetRange(void) -{ - if (checkDefaultRange(0)) { - Bool b = BTIsSetRange(bt, args[0], args[1]); - printf(b ? "TRUE\n" : "FALSE\n"); - } -} - - -static void isResRange(void) -{ - if (checkDefaultRange(0)) { - Bool b = BTIsResRange(bt, args[0], args[1]); - printf(b ? "TRUE\n" : "FALSE\n"); - } -} - - -static void findShortResRange(void) -{ - if (checkDefaultRange(1)) { - if (args[0] > (args[2] - args[1])) { - printf("can't fit length in range\n"); - } else { - Index base, limit; - Bool b = BTFindShortResRange(&base, &limit, bt, - args[1], args[2], args[0]); - if (b) - printf("%"PRIuLONGEST" - %"PRIuLONGEST"\n", - (ulongest_t)base, (ulongest_t)limit); - else - printf("FALSE\n"); - } - } -} - - -static void findShortResRangeHigh(void) -{ - if (checkDefaultRange(1)) { - if (args[0] > (args[2] - args[1])) { - printf("can't fit length in range\n"); - } else { - Index base, limit; - Bool b = BTFindShortResRangeHigh(&base, &limit, bt, - args[1], args[2], args[0]); - if (b) - printf("%"PRIuLONGEST" - %"PRIuLONGEST"\n", - (ulongest_t)base, (ulongest_t)limit); - else - printf("FALSE\n"); - } - } -} - -static void findLongResRange(void) -{ - if (checkDefaultRange(1)) { - if (args[0] > (args[2] - args[1])) { - printf("can't fit length in range\n"); - } else { - Index base, limit; - Bool b = BTFindLongResRange(&base, &limit, bt, - args[1], args[2], args[0]); - if (b) - printf("%"PRIuLONGEST" - %"PRIuLONGEST"\n", - (ulongest_t)base, (ulongest_t)limit); - else - printf("FALSE\n"); - } - } -} - - -static void help(void) -{ - printf("c create a BT of size 's'\n" - "d destroy the current BT\n" - "s set the bit index 'i'\n" - "r reset the bit index 'i'\n" - "g get the bit index 'i'\n"); - printf("sr [ ] set the specified range\n" - "rr [ ] reset the specified range\n" - "is [ ] is the specified range set?\n" - "ir [ ] is the specified range reset?\n"); - printf("f [ ] find a reset range of length 'l'.\n" - "fh [ ] find a reset range length 'l', working downwards\n" - "fl [ ] find a reset range of length at least 'l'\n" - "q quit\n" - "? print this message\n"); - printf("\n" - "No way of testing BTSize, BTRangesSame, or BTCopyInvertRange.\n"); -} - - -static struct commandShapeStruct { - char *name; - Count min_args; - Count max_args; - void (*fun)(void); -} commandShapes[] = { - {"c", 1, 1, create}, - {"d", 0, 0, destroy}, - {"s", 1, 1, set}, - {"r", 1, 1, reset}, - {"g", 1, 1, get}, - {"sr", 0, 2, setRange}, - {"rr", 0, 2, resetRange}, - {"is", 0, 2, isSetRange}, - {"ir", 0, 2, isResRange}, - {"f", 1, 3, findShortResRange}, - {"fh", 1, 3, findShortResRangeHigh}, - {"fl", 1, 3, findLongResRange}, - {"?", 0, 0, help}, - {"q", 0, 0, quit}, - { NULL, 0, 0, NULL} -}; - - -typedef struct commandShapeStruct *commandShape; - - -static void obeyCommand(char *command) -{ - commandShape shape = commandShapes; - while(shape->name != NULL) { - char *csp = shape->name; - char *p = command; - while (*csp == *p) { - csp++; - p++; - } - if ((*csp == 0) && ((*p == '\n') || (*p == ' '))) { /* complete match */ - argCount = 0; - while ((*p == ' ') && (argCount < shape->max_args)) { - /* get an argument */ - char *newP; - long l; - l = strtol(p, &newP, 0); - if(l < 0) { /* negative integer */ - printf("negative integer arguments are invalid\n"); - return; - } - args[argCount] = (unsigned long)l; - if (newP == p) { /* strtoul failed */ - printf("couldn't parse an integer argument\n"); - return; - } - p = newP; - ++ argCount; - } - if (argCount < shape->min_args) { - printf("insufficient arguments to command\n"); - } else if (*p != '\n') { - printf("too many arguments to command\n"); - } else { /* do the command */ - shape->fun(); - } - return; - } else { - ++ shape; /* try next command */ - } - } - printf("command not understood\n"); - help(); -} - - -#ifdef MPS_BUILD_MV -/* disable "conversion from int to char" */ -#pragma warning(disable: 4244) -#endif - -static void showBT(void) { - Index i; - char c; - if (bt == NULL) - return; - i = 0; - while((i < btSize) && (i < 50)) { - if (i % 10 == 0) - c = (char)((i / 10) % 10) + '0'; - else - c = ' '; - putchar(c); - ++ i; - } - putchar('\n'); - i = 0; - while((i < btSize) && (i < 50)) { - c = (char)(i % 10) +'0'; - putchar(c); - ++ i; - } - putchar('\n'); - i = 0; - while(i < btSize) { - if (BTGet(bt,i)) - c = 'O'; - else - c = '.'; - putchar(c); - ++ i; - if (i % 50 == 0) - putchar('\n'); - } - putchar('\n'); -} - -#ifdef MPS_BUILD_MV -/* disable "conversion from int to char" */ -#pragma warning(default: 4244) -#endif - - -#define testArenaSIZE (((size_t)64)<<20) - -extern int main(int argc, char *argv[]) -{ - bt = NULL; - btSize = 0; - - testlib_unused(argc); testlib_unused(argv); - - die(mps_arena_create((mps_arena_t*)&arena, mps_arena_class_vm(), - testArenaSIZE), - "mps_arena_create"); - while(1) { - char input[100]; - printf("bt test> "); - fflush(stdout); - if (fgets(input, 100, stdin)) { - obeyCommand(input); - showBT(); - } else { - return 0; - } - } -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/buffer.c b/mps/code/buffer.c deleted file mode 100644 index b33c08dc239..00000000000 --- a/mps/code/buffer.c +++ /dev/null @@ -1,1580 +0,0 @@ -/* buffer.c: ALLOCATION BUFFER IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This is (part of) the implementation of allocation buffers. - * Several macros which also form part of the implementation are in - * . Several macros forming part of should be - * consistent with the macros and functions in this module. - * - * DESIGN - * - * .design: See . - * - * .ap.async: The mutator is allowed to change certain AP fields - * asynchronously. Functions that can be called on buffers not - * synchronized with the mutator must take care when reading these - * fields. Such functions are marked with this tag. - * - * TRANSGRESSIONS - * - * .trans.mod: There are several instances where pool structures are - * directly accessed by this module because does not provide - * an adequate (or adequately documented) interface. They bear this - * tag. */ - -#include "mpm.h" - -SRCID(buffer, "$Id$"); - - -/* forward declarations */ -static void BufferFrameNotifyPopPending(Buffer buffer); - - -/* BufferCheck -- check consistency of a buffer - * - * See .ap.async. */ - -Bool BufferCheck(Buffer buffer) -{ - CHECKS(Buffer, buffer); - CHECKL(buffer->serial < buffer->pool->bufferSerial); /* .trans.mod */ - CHECKU(Arena, buffer->arena); - CHECKU(Pool, buffer->pool); - CHECKL(buffer->arena == buffer->pool->arena); - CHECKL(RingCheck(&buffer->poolRing)); /* */ - CHECKL(BoolCheck(buffer->isMutator)); - CHECKL(buffer->fillSize >= 0.0); - CHECKL(buffer->emptySize >= 0.0); - CHECKL(buffer->emptySize <= buffer->fillSize); - CHECKL(buffer->alignment == buffer->pool->alignment); - CHECKL(AlignCheck(buffer->alignment)); - CHECKL(BoolCheck(buffer->ap_s._enabled)); - - if (buffer->ap_s._enabled) { - /* no useful check for frameptr - mutator may be updating it */ - CHECKL(BoolCheck(buffer->ap_s._lwpoppending)); - } else { - CHECKL(buffer->ap_s._lwpoppending == FALSE); - CHECKL(buffer->ap_s._frameptr == NULL); - } - - /* If any of the buffer's fields indicate that it is reset, make */ - /* sure it is really reset. Otherwise, check various properties */ - /* of the non-reset fields. */ - if (buffer->mode & BufferModeTRANSITION) { - /* nothing to check */ - } else if ((buffer->mode & BufferModeATTACHED) == 0 - || buffer->base == (Addr)0 - || buffer->ap_s.init == (Addr)0 - || buffer->ap_s.alloc == (Addr)0 - || buffer->poolLimit == (Addr)0) { - CHECKL((buffer->mode & BufferModeATTACHED) == 0); - CHECKL(buffer->base == (Addr)0); - CHECKL(buffer->initAtFlip == (Addr)0); - CHECKL(buffer->ap_s.init == (Addr)0); - CHECKL(buffer->ap_s.alloc == (Addr)0); - CHECKL(buffer->ap_s.limit == (Addr)0); - /* Nothing reliable to check for lightweight frame state */ - CHECKL(buffer->poolLimit == (Addr)0); - } else { - Addr aplimit; - - /* The buffer is attached to a region of memory. */ - /* Check consistency. */ - CHECKL(buffer->mode & BufferModeATTACHED); - - /* These fields should obey the ordering */ - /* base <= init <= alloc <= poolLimit */ - CHECKL((mps_addr_t)buffer->base <= buffer->ap_s.init); - CHECKL(buffer->ap_s.init <= buffer->ap_s.alloc); - CHECKL(buffer->ap_s.alloc <= (mps_addr_t)buffer->poolLimit); - - /* Check that the fields are aligned to the buffer alignment. */ - CHECKL(AddrIsAligned(buffer->base, buffer->alignment)); - CHECKL(AddrIsAligned(buffer->initAtFlip, buffer->alignment)); - CHECKL(AddrIsAligned(buffer->ap_s.init, buffer->alignment)); - CHECKL(AddrIsAligned(buffer->ap_s.alloc, buffer->alignment)); - CHECKL(AddrIsAligned(buffer->ap_s.limit, buffer->alignment)); - CHECKL(AddrIsAligned(buffer->poolLimit, buffer->alignment)); - - /* .lwcheck: If LW frames are enabled, the buffer may become */ - /* trapped asynchronously. It can't become untrapped */ - /* asynchronously, though. See . */ - /* Read a snapshot value of the limit field. Use this to determine */ - /* if we are trapped, and to permit more useful checking when not */ - /* yet trapped. */ - aplimit = buffer->ap_s.limit; - - /* If the buffer isn't trapped then "limit" should be the limit */ - /* set by the owning pool. Otherwise, "init" is either at the */ - /* same place it was at flip (.commit.before) or has been set */ - /* to "alloc" (.commit.after). Also, when the buffer is */ - /* flipped, initAtFlip should hold the init at flip, which is */ - /* between the base and current init. Otherwise, initAtFlip */ - /* is kept at zero to avoid misuse (see */ - /* request.dylan.170429.sol.zero). */ - - if ((buffer->ap_s._enabled && aplimit == (Addr)0) /* see .lwcheck */ - || (!buffer->ap_s._enabled && BufferIsTrapped(buffer))) { - /* .check.use-trapped: This checking function uses BufferIsTrapped, */ - /* So BufferIsTrapped can't do checking as that would cause an */ - /* infinite loop. */ - CHECKL(aplimit == (Addr)0); - if (buffer->mode & BufferModeFLIPPED) { - CHECKL(buffer->ap_s.init == buffer->initAtFlip - || buffer->ap_s.init == buffer->ap_s.alloc); - CHECKL(buffer->base <= buffer->initAtFlip); - CHECKL(buffer->initAtFlip <= (Addr)buffer->ap_s.init); - } - /* Nothing special to check in the logged mode. */ - } else { - CHECKL(aplimit == buffer->poolLimit); /* see .lwcheck */ - CHECKL(buffer->initAtFlip == (Addr)0); - } - } - - return TRUE; -} - - -/* BufferDescribe -- write out description of buffer - * - * See for structure definitions. */ - -Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream) -{ - Res res; - char abzMode[5]; - - if (!TESTT(Buffer, buffer)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - abzMode[0] = (char)( (buffer->mode & BufferModeTRANSITION) ? 't' : '_' ); - abzMode[1] = (char)( (buffer->mode & BufferModeLOGGED) ? 'l' : '_' ); - abzMode[2] = (char)( (buffer->mode & BufferModeFLIPPED) ? 'f' : '_' ); - abzMode[3] = (char)( (buffer->mode & BufferModeATTACHED) ? 'a' : '_' ); - abzMode[4] = '\0'; - - res = WriteF(stream, - "Buffer $P ($U) {\n", - (WriteFP)buffer, (WriteFU)buffer->serial, - " class $P (\"$S\")\n", - (WriteFP)buffer->class, buffer->class->name, - " Arena $P\n", (WriteFP)buffer->arena, - " Pool $P\n", (WriteFP)buffer->pool, - buffer->isMutator ? - " Mutator Buffer\n" : " Internal Buffer\n", - " mode $S (TRANSITION, LOGGED, FLIPPED, ATTACHED)\n", - (WriteFS)abzMode, - " fillSize $UKb\n", (WriteFU)(buffer->fillSize / 1024), - " emptySize $UKb\n", (WriteFU)(buffer->emptySize / 1024), - " alignment $W\n", (WriteFW)buffer->alignment, - " base $A\n", buffer->base, - " initAtFlip $A\n", buffer->initAtFlip, - " init $A\n", buffer->ap_s.init, - " alloc $A\n", buffer->ap_s.alloc, - " limit $A\n", buffer->ap_s.limit, - " poolLimit $A\n", buffer->poolLimit, - NULL); - if (res != ResOK) return res; - - res = buffer->class->describe(buffer, stream); - if (res != ResOK) return res; - - res = WriteF(stream, "} Buffer $P ($U)\n", - (WriteFP)buffer, (WriteFU)buffer->serial, - NULL); - return res; -} - - -/* BufferInitV -- initialize an allocation buffer */ - -static Res BufferInitV(Buffer buffer, BufferClass class, - Pool pool, Bool isMutator, va_list args) -{ - Arena arena; - Res res; - - AVER(buffer != NULL); - AVERT(BufferClass, class); - AVERT(Pool, pool); - /* The PoolClass should support buffer protocols */ - AVER((pool->class->attr & AttrBUF)); /* .trans.mod */ - - arena = PoolArena(pool); - /* Initialize the buffer. See for a definition of */ - /* the structure. sig and serial comes later .init.sig-serial */ - buffer->arena = arena; - buffer->class = class; - buffer->pool = pool; - RingInit(&buffer->poolRing); - buffer->isMutator = isMutator; - if (ArenaGlobals(arena)->bufferLogging) { - buffer->mode = BufferModeLOGGED; - } else { - buffer->mode = 0; - } - buffer->fillSize = 0.0; - buffer->emptySize = 0.0; - buffer->alignment = pool->alignment; /* .trans.mod */ - buffer->base = (Addr)0; - buffer->initAtFlip = (Addr)0; - /* In the next three assignements we really mean zero, not NULL, because - the bit pattern is compared. It's pretty unlikely we'll encounter - a platform where this makes a difference. */ - buffer->ap_s.init = (mps_addr_t)0; - buffer->ap_s.alloc = (mps_addr_t)0; - buffer->ap_s.limit = (mps_addr_t)0; - buffer->ap_s._frameptr = NULL; - buffer->ap_s._enabled = FALSE; - buffer->ap_s._lwpoppending = FALSE; - buffer->poolLimit = (Addr)0; - buffer->rampCount = 0; - - /* .init.sig-serial: Now the vanilla stuff is initialized, */ - /* sign the buffer and give it a serial number. It can */ - /* then be safely checked in subclass methods. */ - buffer->sig = BufferSig; - buffer->serial = pool->bufferSerial; /* .trans.mod */ - ++pool->bufferSerial; - AVERT(Buffer, buffer); - - /* Dispatch to the buffer class method to perform any */ - /* class-specific initialization of the buffer. */ - res = (*class->init)(buffer, pool, args); - if (res != ResOK) - goto failInit; - - /* Attach the initialized buffer to the pool. */ - RingAppend(&pool->bufferRing, &buffer->poolRing); - - return ResOK; - -failInit: - RingFinish(&buffer->poolRing); - buffer->sig = SigInvalid; - return res; -} - - -/* BufferCreate -- create an allocation buffer - * - * See . */ - -Res BufferCreate(Buffer *bufferReturn, BufferClass class, - Pool pool, Bool isMutator, ...) -{ - Res res; - va_list args; - - va_start(args, isMutator); - res = BufferCreateV(bufferReturn, class, pool, isMutator, args); - va_end(args); - return res; -} - - -/* BufferCreateV -- create an allocation buffer, with varargs - * - * See . */ - -Res BufferCreateV(Buffer *bufferReturn, BufferClass class, - Pool pool, Bool isMutator, va_list args) -{ - Res res; - Buffer buffer; - Arena arena; - void *p; - - AVER(bufferReturn != NULL); - AVERT(BufferClass, class); - AVERT(Pool, pool); - - arena = PoolArena(pool); - - /* Allocate memory for the buffer descriptor structure. */ - res = ControlAlloc(&p, arena, class->size, - /* withReservoirPermit */ FALSE); - if (res != ResOK) - goto failAlloc; - buffer = p; - - /* Initialize the buffer descriptor structure. */ - res = BufferInitV(buffer, class, pool, isMutator, args); - if (res != ResOK) - goto failInit; - - *bufferReturn = buffer; - return ResOK; - -failInit: - ControlFree(arena, buffer, class->size); -failAlloc: - return res; -} - - -/* BufferDetach -- detach a buffer from a region */ - -void BufferDetach(Buffer buffer, Pool pool) -{ - AVERT(Buffer, buffer); - AVER(BufferIsReady(buffer)); - - if (!BufferIsReset(buffer)) { - Addr init, limit; - Size spare; - - buffer->mode |= BufferModeTRANSITION; - init = buffer->ap_s.init; - limit = buffer->poolLimit; - /* Ask the owning pool to do whatever it needs to before the */ - /* buffer is detached (e.g. copy buffer state into pool state). */ - (*pool->class->bufferEmpty)(pool, buffer, init, limit); - /* Use of lightweight frames must have been disabled by now */ - AVER(BufferFrameState(buffer) == BufferFrameDISABLED); - - /* run any class-specific detachment method */ - buffer->class->detach(buffer); - - spare = AddrOffset(init, limit); - buffer->emptySize += spare; - if (buffer->isMutator) { - buffer->pool->emptyMutatorSize += spare; - ArenaGlobals(buffer->arena)->emptyMutatorSize += spare; - ArenaGlobals(buffer->arena)->allocMutatorSize += - AddrOffset(buffer->base, init); - } else { - buffer->pool->emptyInternalSize += spare; - ArenaGlobals(buffer->arena)->emptyInternalSize += spare; - } - - /* Reset the buffer. */ - buffer->base = (Addr)0; - buffer->initAtFlip = (Addr)0; - buffer->ap_s.init = (mps_addr_t)0; - buffer->ap_s.alloc = (mps_addr_t)0; - buffer->ap_s.limit = (mps_addr_t)0; - buffer->poolLimit = (Addr)0; - buffer->mode &= - ~(BufferModeATTACHED|BufferModeFLIPPED|BufferModeTRANSITION); - BufferFrameSetState(buffer, BufferFrameDISABLED); - - EVENT2(BufferEmpty, buffer, spare); - } -} - - -/* BufferDestroy -- destroy an allocation buffer - * - * See . */ - -void BufferDestroy(Buffer buffer) -{ - Arena arena; - BufferClass class; - - AVERT(Buffer, buffer); - arena = buffer->arena; - class = buffer->class; - AVERT(BufferClass, class); - BufferFinish(buffer); - ControlFree(arena, buffer, class->size); -} - - -/* BufferFinish -- finish an allocation buffer */ - -void BufferFinish(Buffer buffer) -{ - Pool pool; - - AVERT(Buffer, buffer); - - pool = BufferPool(buffer); - - /* The PoolClass should support buffer protocols */ - AVER((pool->class->attr & AttrBUF)); /* .trans.mod */ - AVER(BufferIsReady(buffer)); - - /* */ - if (BufferIsTrappedByMutator(buffer)) { - BufferFrameNotifyPopPending(buffer); - } - - BufferDetach(buffer, pool); - - /* Dispatch to the buffer class method to perform any */ - /* class-specific finishing of the buffer. */ - (*buffer->class->finish)(buffer); - - /* Detach the buffer from its owning pool and unsig it. */ - RingRemove(&buffer->poolRing); - buffer->sig = SigInvalid; - - /* Finish off the generic buffer fields. */ - RingFinish(&buffer->poolRing); - - EVENT1(BufferFinish, buffer); -} - - -/* BufferIsReset -- test whether a buffer is in the "reset" state - * - * A buffer is "reset" when it is not attached. In this state all of - * the pointers into the region are zero. This condition is checked by - * BufferCheck. */ - -Bool BufferIsReset(Buffer buffer) -{ - AVERT(Buffer, buffer); - - return !(buffer->mode & BufferModeATTACHED); -} - - -/* BufferIsReady -- test whether a buffer is ready for reserve - * - * BufferIsReady returns TRUE if and only if the buffer is not between a - * reserve and commit. The result is only reliable if the client is not - * currently using the buffer, since it may update the alloc and init - * pointers asynchronously. */ - -Bool BufferIsReady(Buffer buffer) -{ - AVERT(Buffer, buffer); - - return buffer->ap_s.init == buffer->ap_s.alloc; -} - - -/* BufferIsMutator -- test whether buffer belongs to mutator - * - * Returns TRUE iff mutator was created for the mutator. */ - -Bool BufferIsMutator(Buffer buffer) -{ - AVERT(Buffer, buffer); - - return buffer->isMutator; -} - - -/* BufferSetUnflipped - * - * Unflip a buffer if it was flipped. */ - -static void BufferSetUnflipped(Buffer buffer) -{ - AVERT(Buffer, buffer); - AVER(buffer->mode & BufferModeFLIPPED); - buffer->mode &= ~BufferModeFLIPPED; - /* restore ap_s.limit if appropriate */ - if (!BufferIsTrapped(buffer)) { - buffer->ap_s.limit = buffer->poolLimit; - } - buffer->initAtFlip = (Addr)0; -} - - -/* BufferFrameState - * - * Returns the frame state of a buffer. See - * . */ - -FrameState BufferFrameState(Buffer buffer) -{ - AVERT(Buffer, buffer); - if (buffer->ap_s._enabled) { - if (buffer->ap_s._lwpoppending) { - return BufferFramePOP_PENDING; - } else { - AVER(buffer->ap_s._frameptr == NULL); - return BufferFrameVALID; - } - } else { - AVER(buffer->ap_s._frameptr == NULL); - AVER(buffer->ap_s._lwpoppending == FALSE); - return BufferFrameDISABLED; - } -} - - -/* BufferFrameSetState - * - * Sets the frame state of a buffer. Only the mutator may set the - * PopPending state. See . */ - -void BufferFrameSetState(Buffer buffer, FrameState state) -{ - AVERT(Buffer, buffer); - AVER(state == BufferFrameVALID || state == BufferFrameDISABLED); - buffer->ap_s._frameptr = NULL; - buffer->ap_s._lwpoppending = FALSE; - buffer->ap_s._enabled = (state == BufferFrameVALID); -} - - -/* BufferSetAllocAddr - * - * Sets the init & alloc pointers of a buffer. */ - -void BufferSetAllocAddr(Buffer buffer, Addr addr) -{ - AVERT(Buffer, buffer); - /* Can't check Addr */ - AVER(BufferIsReady(buffer)); - AVER(buffer->base <= addr); - AVER(buffer->poolLimit >= addr); - - buffer->ap_s.init = addr; - buffer->ap_s.alloc = addr; -} - - -/* BufferFrameNotifyPopPending - * - * Notifies the pool when a lightweight frame pop operation has been - * deferred and needs to be processed. See - * . */ - -static void BufferFrameNotifyPopPending(Buffer buffer) -{ - AllocFrame frame; - Pool pool; - AVER(BufferIsTrappedByMutator(buffer)); - AVER(BufferFrameState(buffer) == BufferFramePOP_PENDING); - frame = (AllocFrame)buffer->ap_s._frameptr; - /* Unset PopPending state & notify the pool */ - BufferFrameSetState(buffer, BufferFrameVALID); - /* If the frame is no longer trapped, undo the trap by resetting */ - /* the AP limit pointer */ - if (!BufferIsTrapped(buffer)) { - buffer->ap_s.limit = buffer->poolLimit; - } - pool = BufferPool(buffer); - (*pool->class->framePopPending)(pool, buffer, frame); -} - - - -/* BufferFramePush - * - * See . */ - -Res BufferFramePush(AllocFrame *frameReturn, Buffer buffer) -{ - Pool pool; - AVERT(Buffer, buffer); - AVER(frameReturn != NULL); - - - /* Process any flip or PopPending */ - if (!BufferIsReset(buffer) && buffer->ap_s.limit == (Addr)0) { - /* .fill.unflip: If the buffer is flipped then we unflip the buffer. */ - if (buffer->mode & BufferModeFLIPPED) { - BufferSetUnflipped(buffer); - } - - /* check for PopPending */ - if (BufferIsTrappedByMutator(buffer)) { - BufferFrameNotifyPopPending(buffer); - } - } - pool = BufferPool(buffer); - return (*pool->class->framePush)(frameReturn, pool, buffer); -} - - -/* BufferFramePop - * - * See . */ - -Res BufferFramePop(Buffer buffer, AllocFrame frame) -{ - Pool pool; - AVERT(Buffer, buffer); - /* frame is of an abstract type & can't be checked */ - pool = BufferPool(buffer); - return (*pool->class->framePop)(pool, buffer, frame); - -} - - - -/* BufferReserve -- reserve memory from an allocation buffer - * - * .reserve: Keep in sync with . */ - -Res BufferReserve(Addr *pReturn, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - Addr next; - - AVER(pReturn != NULL); - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(SizeIsAligned(size, BufferPool(buffer)->alignment)); - AVER(BufferIsReady(buffer)); - AVER(BoolCheck(withReservoirPermit)); - - /* Is there enough room in the unallocated portion of the buffer to */ - /* satisfy the request? If so, just increase the alloc marker and */ - /* return a pointer to the area below it. */ - next = AddrAdd(buffer->ap_s.alloc, size); - if (next > (Addr)buffer->ap_s.alloc && - next <= (Addr)buffer->ap_s.limit) { - buffer->ap_s.alloc = next; - *pReturn = buffer->ap_s.init; - return ResOK; - } - - /* If the buffer can't accommodate the request, call "fill". */ - return BufferFill(pReturn, buffer, size, withReservoirPermit); -} - - -/* BufferAttach -- attach a region to a buffer - * - * BufferAttach is entered because of a BufferFill, or because of a Pop - * operation on a lightweight frame. */ - -void BufferAttach(Buffer buffer, Addr base, Addr limit, - Addr init, Size size) -{ - Size filled; - - AVERT(Buffer, buffer); - AVER(BufferIsReset(buffer)); - AVER(AddrAdd(base, size) <= limit); - AVER(base <= init); - AVER(init <= limit); - - /* Set up the buffer to point at the supplied region */ - buffer->mode |= BufferModeATTACHED; - buffer->base = base; - buffer->ap_s.init = init; - buffer->ap_s.alloc = AddrAdd(init, size); - /* only set limit if not logged */ - if ((buffer->mode & BufferModeLOGGED) == 0) { - buffer->ap_s.limit = limit; - } else { - AVER(buffer->ap_s.limit == (Addr)0); - } - AVER(buffer->initAtFlip == (Addr)0); - buffer->poolLimit = limit; - - filled = AddrOffset(init, limit); - buffer->fillSize += filled; - if (buffer->isMutator) { - if (base != init) { /* see */ - Size prealloc = AddrOffset(base, init); - ArenaGlobals(buffer->arena)->allocMutatorSize -= prealloc; - } - buffer->pool->fillMutatorSize += filled; - ArenaGlobals(buffer->arena)->fillMutatorSize += filled; - } else { - buffer->pool->fillInternalSize += filled; - ArenaGlobals(buffer->arena)->fillInternalSize += filled; - } - - /* run any class-specific attachment method */ - buffer->class->attach(buffer, base, limit, init, size); - - AVERT(Buffer, buffer); - EVENT4(BufferFill, buffer, size, base, filled); -} - - -/* BufferFill -- refill an empty buffer - * - * BufferFill is entered by the "reserve" operation on a buffer if there - * isn't enough room between "alloc" and "limit" to satisfy an - * allocation request. This might be because the buffer has been - * trapped and "limit" has been set to zero. */ - -Res BufferFill(Addr *pReturn, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - Res res; - Pool pool; - Addr base, limit, next; - - AVER(pReturn != NULL); - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(SizeIsAligned(size, BufferPool(buffer)->alignment)); - AVER(BufferIsReady(buffer)); - - pool = BufferPool(buffer); - - /* If we're here because the buffer was trapped, then we attempt */ - /* the allocation here. */ - if (!BufferIsReset(buffer) && buffer->ap_s.limit == (Addr)0) { - /* .fill.unflip: If the buffer is flipped then we unflip the buffer. */ - if (buffer->mode & BufferModeFLIPPED) { - BufferSetUnflipped(buffer); - } - - /* */ - if (BufferIsTrappedByMutator(buffer)) { - BufferFrameNotifyPopPending(buffer); - } - - /* .fill.logged: If the buffer is logged then we leave it logged. */ - next = AddrAdd(buffer->ap_s.alloc, size); - if (next > (Addr)buffer->ap_s.alloc && - next <= (Addr)buffer->poolLimit) { - buffer->ap_s.alloc = next; - if (buffer->mode & BufferModeLOGGED) { - EVENT3(BufferReserve, buffer, buffer->ap_s.init, size); - } - *pReturn = buffer->ap_s.init; - return ResOK; - } - } - - /* There really isn't enough room for the allocation now. */ - AVER(AddrAdd(buffer->ap_s.alloc, size) > buffer->poolLimit || - AddrAdd(buffer->ap_s.alloc, size) < (Addr)buffer->ap_s.alloc); - - BufferDetach(buffer, pool); - - /* Ask the pool for some memory. */ - res = (*pool->class->bufferFill)(&base, &limit, - pool, buffer, size, - withReservoirPermit); - if (res != ResOK) - return res; - - /* Set up the buffer to point at the memory given by the pool */ - /* and do the allocation that was requested by the client. */ - BufferAttach(buffer, base, limit, base, size); - - if (buffer->mode & BufferModeLOGGED) { - EVENT3(BufferReserve, buffer, buffer->ap_s.init, size); - } - - *pReturn = base; - return res; -} - - - -/* BufferCommit -- commit memory previously reserved - * - * .commit: Keep in sync with . */ - -Bool BufferCommit(Buffer buffer, Addr p, Size size) -{ - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(SizeIsAligned(size, BufferPool(buffer)->alignment)); - AVER(!BufferIsReady(buffer)); - - /* See . */ - /* .commit.before: If a flip occurs before this point, when the */ - /* pool reads "initAtFlip" it will point below the object, so it */ - /* will be trashed and the commit must fail when trip is called. */ - AVER(p == buffer->ap_s.init); - AVER(AddrAdd(buffer->ap_s.init, size) == buffer->ap_s.alloc); - - /* .commit.update: Atomically update the init pointer to declare */ - /* that the object is initialized (though it may be invalid if a */ - /* flip occurred). */ - buffer->ap_s.init = buffer->ap_s.alloc; - - /* .improve.memory-barrier: Memory barrier here on the DEC Alpha */ - /* (and other relaxed memory order architectures). */ - /* .commit.after: If a flip occurs at this point, the pool will */ - /* see "initAtFlip" above the object, which is valid, so it will */ - /* be collected. The commit must succeed when trip is called. */ - /* The pointer "p" will have been fixed up. (@@@@ Will it?) */ - /* .commit.trip: Trip the buffer if a flip has occurred. */ - if (buffer->ap_s.limit == 0) - return BufferTrip(buffer, p, size); - - /* No flip occurred, so succeed. */ - - return TRUE; -} - - -/* BufferTrip -- act on a trapped buffer - * - * Called from BufferCommit (and its equivalents) when invoked on a - * trapped buffer (indicated by limit == 0). This function can decide - * whether to succeed or fail the commit. */ - -Bool BufferTrip(Buffer buffer, Addr p, Size size) -{ - Pool pool; - - AVERT(Buffer, buffer); - AVER(p != 0); - AVER(size > 0); - AVER(SizeIsAligned(size, buffer->alignment)); - - /* The limit field should be zero, because that's how trip gets */ - /* called. See .commit.trip. */ - AVER(buffer->ap_s.limit == 0); - /* Of course we should be trapped. */ - AVER(BufferIsTrapped(buffer)); - /* But the mutator shouldn't have caused the trap */ - AVER(!BufferIsTrappedByMutator(buffer)); - - /* The init and alloc fields should be equal at this point, because */ - /* the step .commit.update has happened. */ - AVER(buffer->ap_s.init == buffer->ap_s.alloc); - - /* The p parameter points at the base address of the allocated */ - /* block, the end of which should now coincide with the init and */ - /* alloc fields. */ - /* Note that we don't _really_ care about p too much. We don't */ - /* do anything else with it apart from these checks. (in particular */ - /* it seems like the algorithms could be modified to cope with the */ - /* case of the object having been copied between Commit updating i */ - /* and testing limit) */ - AVER(AddrAdd(p, size) == buffer->ap_s.init); - - pool = BufferPool(buffer); - - AVER(PoolHasAddr(pool, p)); - - /* .trip.unflip: If the flip occurred before commit set "init" */ - /* to "alloc" (see .commit.before) then the object is invalid */ - /* (won't've been scanned) so undo the allocation and fail commit. */ - /* Otherwise (see .commit.after) the object is valid (will've been */ - /* scanned) so commit can simply succeed. */ - if ((buffer->mode & BufferModeFLIPPED) - && buffer->ap_s.init != buffer->initAtFlip) { - /* Reset just enough state for Reserve/Fill to work. */ - /* The buffer is left trapped and we leave the untrapping */ - /* for the next reserve (which goes out of line to Fill */ - /* (.fill.unflip) because the buffer is still trapped) */ - buffer->ap_s.init = p; - buffer->ap_s.alloc = p; - return FALSE; - } - - /* Emit event including class if loggged */ - if (buffer->mode & BufferModeLOGGED) { - Bool b; - Format format; - Addr clientClass; - - b = PoolFormat(&format, buffer->pool); - if (b) { - clientClass = format->class(p); - } else { - clientClass = (Addr)0; - } - EVENT4(BufferCommit, buffer, p, size, clientClass); - /* Of course, it's not _really_ unused unless you're not */ - /* using telemetry. This is a HACK @@@@. It should be */ - /* removed when telemetry is fixed to use its arguments. */ - UNUSED(clientClass); - } - return TRUE; -} - - -/* BufferFlip -- trap buffer at GC flip time - * - * .flip: Tells the buffer that a flip has occurred. If the buffer is - * between reserve and commit, and has a rank (i.e. references), and has - * the two-phase protocol, then the object being initialized is - * invalidated by failing the next commit. The buffer code handles this - * automatically (ie the pool implementation is not involved). If the - * buffer is reset there is no effect, since there is no object to - * invalidate. If the buffer is already flipped there is no effect, - * since the object is already invalid by a previous trace. The buffer - * becomes unflipped at the next reserve or commit operation (actually - * reserve because commit is lazy). This is handled by BufferFill - * (.fill.unflip) or BufferTrip (.trip.unflip). */ - -void BufferFlip(Buffer buffer) -{ - AVERT(Buffer, buffer); - - if (BufferRankSet(buffer) != RankSetEMPTY - && (buffer->mode & BufferModeFLIPPED) == 0 - && !BufferIsReset(buffer)) { - AVER(buffer->initAtFlip == (Addr)0); - buffer->initAtFlip = buffer->ap_s.init; - /* Memory Barrier here? @@@@ */ - buffer->ap_s.limit = (Addr)0; - buffer->mode |= BufferModeFLIPPED; - } -} - - -/* BufferScanLimit -- return limit of data to which to scan - * - * Returns the highest address to which it is safe to scan objects in - * the buffer. When the buffer is not flipped, this is the "init" of - * the AP. When the buffer is flipped, it is the value that "init" had - * at flip time. [Could make BufferScanLimit return the AP "alloc" when - * using ambiguous scanning.] See .ap.async. */ - -Addr BufferScanLimit(Buffer buffer) -{ - if (buffer->mode & BufferModeFLIPPED) { - return buffer->initAtFlip; - } else { - return buffer->ap_s.init; - } -} - - -Seg BufferSeg(Buffer buffer) -{ - AVERT(Buffer, buffer); - return buffer->class->seg(buffer); -} - - -RankSet BufferRankSet(Buffer buffer) -{ - AVERT(Buffer, buffer); - return buffer->class->rankSet(buffer); -} - -void BufferSetRankSet(Buffer buffer, RankSet rankset) -{ - AVERT(Buffer, buffer); - AVERT(RankSet, rankset); - buffer->class->setRankSet(buffer, rankset); -} - - -/* BufferReassignSeg -- adjust the seg of an attached buffer - * - * Used for segment splitting and merging. */ - -void BufferReassignSeg(Buffer buffer, Seg seg) -{ - AVERT(Buffer, buffer); - AVERT(Seg, seg); - AVER(!BufferIsReset(buffer)); - AVER(BufferBase(buffer) >= SegBase(seg)); - AVER(BufferLimit(buffer) <= SegLimit(seg)); - AVER(BufferPool(buffer) == SegPool(seg)); - buffer->class->reassignSeg(buffer, seg); -} - - -/* BufferIsTrapped - * - * Indicates whether the buffer is trapped - either by MPS or the - * mutator. See .ap.async. */ - -Bool BufferIsTrapped(Buffer buffer) -{ - /* Can't check buffer, see .check.use-trapped */ - return BufferIsTrappedByMutator(buffer) - || ((buffer->mode & (BufferModeFLIPPED|BufferModeLOGGED)) != 0); -} - - -/* BufferIsTrappedByMutator - * - * Indicates whether the mutator trapped the buffer. See - * and .ap.async. */ - -Bool BufferIsTrappedByMutator(Buffer buffer) -{ - AVER(!buffer->ap_s._lwpoppending || buffer->ap_s._enabled); - /* Can't check buffer, see .check.use-trapped */ - return buffer->ap_s._lwpoppending; -} - - -/* Alloc pattern functions - * - * Just represent the two patterns by two different pointers to dummies. */ - -AllocPatternStruct AllocPatternRampStruct = {'\0'}; - -AllocPattern AllocPatternRamp(void) -{ - return &AllocPatternRampStruct; -} - -AllocPatternStruct AllocPatternRampCollectAllStruct = {'\0'}; - -AllocPattern AllocPatternRampCollectAll(void) -{ - return &AllocPatternRampCollectAllStruct; -} - -static Bool AllocPatternCheck(AllocPattern pattern) -{ - CHECKL(pattern == &AllocPatternRampCollectAllStruct - || pattern == &AllocPatternRampStruct); - UNUSED(pattern); /* */ - return TRUE; -} - - -/* BufferRampBegin -- note an entry into a ramp pattern - * - * .ramp.hack: We count the number of times the ap has begun ramp mode - * (and not ended), so we can do reset by ending all the current ramps. */ - -void BufferRampBegin(Buffer buffer, AllocPattern pattern) -{ - Pool pool; - - AVERT(Buffer, buffer); - AVERT(AllocPattern, pattern); - - ++buffer->rampCount; - AVER(buffer->rampCount > 0); - - pool = BufferPool(buffer); - AVERT(Pool, pool); - (*pool->class->rampBegin)(pool, buffer, - pattern == &AllocPatternRampCollectAllStruct); -} - - -/* BufferRampEnd -- note an exit from a ramp pattern */ - -Res BufferRampEnd(Buffer buffer) -{ - Pool pool; - - AVERT(Buffer, buffer); - - if (buffer->rampCount == 0) - return ResFAIL; - --buffer->rampCount; - - pool = BufferPool(buffer); - AVERT(Pool, pool); - (*pool->class->rampEnd)(pool, buffer); - return ResOK; -} - - -/* BufferRampReset -- exit from ramp mode */ - -void BufferRampReset(Buffer buffer) -{ - Pool pool; - - AVERT(Buffer, buffer); - - if (buffer->rampCount == 0) - return; - - pool = BufferPool(buffer); - AVERT(Pool, pool); - do - (*pool->class->rampEnd)(pool, buffer); - while(--buffer->rampCount > 0); -} - - - -/* BufferClass -- support for the basic Buffer class */ - - -/* bufferTrivInit -- basic buffer init method */ - -static Res bufferTrivInit (Buffer buffer, Pool pool, va_list args) -{ - /* initialization happens in BufferInitV so checks are safe */ - AVERT(Buffer, buffer); - AVERT(Pool, pool); - UNUSED(args); - EVENT3(BufferInit, buffer, pool, buffer->isMutator); - return ResOK; -} - - -/* bufferTrivFinish -- basic buffer finish method */ - -static void bufferTrivFinish (Buffer buffer) -{ - /* No special finish for simple buffers */ - AVERT(Buffer, buffer); - AVER(BufferIsReset(buffer)); - NOOP; -} - - -/* bufferTrivAttach -- basic buffer attach method */ - -static void bufferTrivAttach(Buffer buffer, Addr base, Addr limit, - Addr init, Size size) -{ - /* No special attach method for simple buffers */ - AVERT(Buffer, buffer); - /* Other parameters are consistency checked in BufferAttach */ - UNUSED(base); - UNUSED(limit); - UNUSED(init); - UNUSED(size); - NOOP; -} - - -/* bufferTrivDetach -- basic buffer detach method */ - -static void bufferTrivDetach(Buffer buffer) -{ - /* No special detach method for simple buffers */ - AVERT(Buffer, buffer); - NOOP; -} - - -/* bufferNoSeg -- basic buffer BufferSeg accessor method - * - * .noseg: basic buffers don't support segments, so this method should - * not be called. */ - -static Seg bufferNoSeg (Buffer buffer) -{ - AVERT(Buffer, buffer); - NOTREACHED; /* .noseg */ - return NULL; -} - - - -/* bufferTrivRankSet -- basic BufferRankSet accessor method */ - -static RankSet bufferTrivRankSet (Buffer buffer) -{ - AVERT(Buffer, buffer); - /* vanilla buffers can only have empty rank set */ - return RankSetEMPTY; -} - - -/* bufferNoSetRankSet -- basic BufferSetRankSet setter method - * - * .norank: basic buffers don't support ranksets, so this method should - * not be called. */ - -static void bufferNoSetRankSet (Buffer buffer, RankSet rankset) -{ - AVERT(Buffer, buffer); - AVERT(RankSet, rankset); - NOTREACHED; /* .norank */ -} - - -/* bufferNoReassignSeg -- basic BufferReassignSeg method - * - * .noseg: basic buffers don't support attachment to sements, so this - * method should not be called. */ - -static void bufferNoReassignSeg (Buffer buffer, Seg seg) -{ - AVERT(Buffer, buffer); - AVERT(Seg, seg); - NOTREACHED; /* .noseg */ -} - - -/* bufferTrivDescribe -- basic Buffer describe method */ - -static Res bufferTrivDescribe(Buffer buffer, mps_lib_FILE *stream) -{ - if (!TESTT(Buffer, buffer)) return ResFAIL; - if (stream == NULL) return ResFAIL; - /* dispatching function does it all */ - return ResOK; -} - - -/* BufferClassCheck -- check the consistency of a BufferClass */ - -Bool BufferClassCheck(BufferClass class) -{ - CHECKL(ProtocolClassCheck(&class->protocol)); - CHECKL(class->name != NULL); /* Should be <=6 char C identifier */ - CHECKL(class->size >= sizeof(BufferStruct)); - CHECKL(FUNCHECK(class->init)); - CHECKL(FUNCHECK(class->finish)); - CHECKL(FUNCHECK(class->attach)); - CHECKL(FUNCHECK(class->detach)); - CHECKL(FUNCHECK(class->seg)); - CHECKL(FUNCHECK(class->rankSet)); - CHECKL(FUNCHECK(class->setRankSet)); - CHECKL(FUNCHECK(class->reassignSeg)); - CHECKL(FUNCHECK(class->describe)); - CHECKS(BufferClass, class); - return TRUE; -} - - -/* BufferClass -- the vanilla buffer class definition - * - * See . */ - -DEFINE_CLASS(BufferClass, class) -{ - INHERIT_CLASS(&class->protocol, ProtocolClass); - class->name = "BUFFER"; - class->size = sizeof(BufferStruct); - class->init = bufferTrivInit; - class->finish = bufferTrivFinish; - class->attach = bufferTrivAttach; - class->detach = bufferTrivDetach; - class->describe = bufferTrivDescribe; - class->seg = bufferNoSeg; - class->rankSet = bufferTrivRankSet; - class->setRankSet = bufferNoSetRankSet; - class->reassignSeg = bufferNoReassignSeg; - class->sig = BufferClassSig; -} - - - -/* SegBufClass -- support for the SegBuf subclass */ - - -/* BufferSegBuf -- convert generic Buffer to a SegBuf */ - -#define BufferSegBuf(buffer) ((SegBuf)(buffer)) - - -/* SegBufCheck -- check consistency of a SegBuf */ - -Bool SegBufCheck(SegBuf segbuf) -{ - Buffer buffer; - - CHECKS(SegBuf, segbuf); - buffer = &segbuf->bufferStruct; - CHECKL(BufferCheck(buffer)); - CHECKL(RankSetCheck(segbuf->rankSet)); - - if (buffer->mode & BufferModeTRANSITION) { - /* nothing to check */ - } else if ((buffer->mode & BufferModeATTACHED) == 0) { - CHECKL(segbuf->seg == NULL); - } else { - /* The buffer is attached to a segment. */ - CHECKL(segbuf->seg != NULL); - CHECKL(SegCheck(segbuf->seg)); - /* To avoid recursive checking, leave it to SegCheck to make */ - /* sure the buffer and segment fields tally. */ - - if (buffer->mode & BufferModeFLIPPED) { - /* Only buffers that allocate pointers get flipped. */ - CHECKL(segbuf->rankSet != RankSetEMPTY); - } - } - - return TRUE; -} - - -/* segBufInit -- SegBuf init method */ - -static Res segBufInit (Buffer buffer, Pool pool, va_list args) -{ - BufferClass super; - SegBuf segbuf; - Res res; - - AVERT(Buffer, buffer); - AVERT(Pool, pool); - segbuf = BufferSegBuf(buffer); - - /* Initialize the superclass fields first via next-method call */ - super = BUFFER_SUPERCLASS(SegBufClass); - res = super->init(buffer, pool, args); - if (res != ResOK) - return res; - - segbuf->seg = NULL; - segbuf->sig = SegBufSig; - segbuf->rankSet = RankSetEMPTY; - - AVERT(SegBuf, segbuf); - EVENT3(BufferInitSeg, buffer, pool, buffer->isMutator); - return ResOK; -} - - -/* segBufFinish -- SegBuf finish method */ - -static void segBufFinish (Buffer buffer) -{ - BufferClass super; - SegBuf segbuf; - - AVERT(Buffer, buffer); - AVER(BufferIsReset(buffer)); - segbuf = BufferSegBuf(buffer); - AVERT(SegBuf, segbuf); - - segbuf->sig = SigInvalid; - - /* finish the superclass fields last */ - super = BUFFER_SUPERCLASS(SegBufClass); - super->finish(buffer); -} - - -/* segBufAttach -- SegBuf attach method */ - -static void segBufAttach(Buffer buffer, Addr base, Addr limit, - Addr init, Size size) -{ - SegBuf segbuf; - Seg seg = NULL; /* suppress "may be used uninitialized" */ - Arena arena; - Bool found; - - AVERT(Buffer, buffer); - /* Other parameters are consistency checked in BufferAttach */ - UNUSED(init); - UNUSED(size); - - segbuf = BufferSegBuf(buffer); - arena = BufferArena(buffer); - found = SegOfAddr(&seg, arena, base); - AVER(found); - AVER(segbuf->seg == NULL); - AVER(SegBuffer(seg) == NULL); - AVER(SegBase(seg) <= base); - AVER(limit <= SegLimit(seg)); - - /* attach the buffer to the segment */ - SegSetBuffer(seg, buffer); - segbuf->seg = seg; - - AVERT(SegBuf, segbuf); -} - - -/* segBufDetach -- SegBuf detach method */ - -static void segBufDetach(Buffer buffer) -{ - SegBuf segbuf; - Seg seg; - - AVERT(Buffer, buffer); - segbuf = BufferSegBuf(buffer); - AVERT(SegBuf, segbuf); - - seg = segbuf->seg; - AVER(seg != NULL); - SegSetBuffer(seg, NULL); - segbuf->seg = NULL; -} - - -/* segBufSeg -- BufferSeg accessor method for SegBuf instances */ - -static Seg segBufSeg (Buffer buffer) -{ - SegBuf segbuf; - - AVERT(Buffer, buffer); - segbuf = BufferSegBuf(buffer); - AVERT(SegBuf, segbuf); - return segbuf->seg; -} - - -/* segBufRankSet -- BufferRankSet accessor for SegBuf instances */ - -static RankSet segBufRankSet (Buffer buffer) -{ - SegBuf segbuf; - - AVERT(Buffer, buffer); - segbuf = BufferSegBuf(buffer); - AVERT(SegBuf, segbuf); - return segbuf->rankSet; -} - - -/* segBufSetRankSet -- BufferSetRankSet setter method for SegBuf */ - -static void segBufSetRankSet (Buffer buffer, RankSet rankset) -{ - SegBuf segbuf; - - AVERT(Buffer, buffer); - AVERT(RankSet, rankset); - segbuf = BufferSegBuf(buffer); - AVERT(SegBuf, segbuf); - segbuf->rankSet = rankset; -} - - -/* segBufReassignSeg -- BufferReassignSeg method for SegBuf - * - * Used to support segment merging and splitting. - * - * .invseg: On entry the buffer is attached to an invalid segment, which - * can't be checked. The method is called to make the attachment valid. */ - -static void segBufReassignSeg (Buffer buffer, Seg seg) -{ - SegBuf segbuf; - - AVERT(Buffer, buffer); - AVERT(Seg, seg); - segbuf = BufferSegBuf(buffer); - /* Can't check segbuf on entry. See .invseg */ - AVER(NULL != segbuf->seg); - AVER(seg != segbuf->seg); - segbuf->seg = seg; - AVERT(SegBuf, segbuf); -} - - -/* segBufDescribe -- describe method for SegBuf */ - -static Res segBufDescribe(Buffer buffer, mps_lib_FILE *stream) -{ - SegBuf segbuf; - BufferClass super; - Res res; - - if (!TESTT(Buffer, buffer)) return ResFAIL; - if (stream == NULL) return ResFAIL; - segbuf = BufferSegBuf(buffer); - if (!TESTT(SegBuf, segbuf)) return ResFAIL; - - /* Describe the superclass fields first via next-method call */ - super = BUFFER_SUPERCLASS(SegBufClass); - res = super->describe(buffer, stream); - if (res != ResOK) return res; - - res = WriteF(stream, - " Seg $P\n", (WriteFP)segbuf->seg, - " rankSet $U\n", (WriteFU)segbuf->rankSet, - NULL); - - return res; -} - - -/* SegBufClass -- SegBuf class definition - * - * Supports an association with a single segment when attached. See - * . */ - -typedef BufferClassStruct SegBufClassStruct; - -DEFINE_CLASS(SegBufClass, class) -{ - INHERIT_CLASS(class, BufferClass); - class->name = "SEGBUF"; - class->size = sizeof(SegBufStruct); - class->init = segBufInit; - class->finish = segBufFinish; - class->attach = segBufAttach; - class->detach = segBufDetach; - class->describe = segBufDescribe; - class->seg = segBufSeg; - class->rankSet = segBufRankSet; - class->setRankSet = segBufSetRankSet; - class->reassignSeg = segBufReassignSeg; -} - - -/* RankBufClass -- support for the RankBufClass subclass */ - - -/* rankBufInit -- RankBufClass init method */ - -static Res rankBufInit (Buffer buffer, Pool pool, va_list args) -{ - /* Assumes pun compatibility between Rank and mps_rank_t */ - /* Which is checked by mpsi_check in */ - Rank rank = va_arg(args, Rank); - BufferClass super; - Res res; - - AVERT(Buffer, buffer); - AVERT(Pool, pool); - AVER(RankCheck(rank)); - - /* Initialize the superclass fields first via next-method call */ - super = BUFFER_SUPERCLASS(RankBufClass); - res = super->init(buffer, pool, args); - if (res != ResOK) - return res; - - BufferSetRankSet(buffer, RankSetSingle(rank)); - - /* There's nothing to check that the superclass doesn't, so no AVERT. */ - EVENT4(BufferInitRank, buffer, pool, buffer->isMutator, rank); - return ResOK; -} - - -/* RankBufClass -- RankBufClass class definition - * - * A subclass of SegBufClass, sharing structure for instances. - * - * Supports initialization to a rank supplied at creation time. */ - -typedef BufferClassStruct RankBufClassStruct; - -DEFINE_CLASS(RankBufClass, class) -{ - INHERIT_CLASS(class, SegBufClass); - class->name = "RANKBUF"; - class->init = rankBufInit; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/cbs.c b/mps/code/cbs.c deleted file mode 100644 index d5958990c08..00000000000 --- a/mps/code/cbs.c +++ /dev/null @@ -1,1695 +0,0 @@ -/* cbs.c: COALESCING BLOCK STRUCTURE IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .intro: This is a portable implementation of coalescing block - * structures. - * - * .purpose: CBSs are used to manage potentially unbounded - * collections of memory blocks. - * - * .sources: . - */ - -#include "cbs.h" -#include "splay.h" -#include "meter.h" -#include "poolmfs.h" -#include "mpm.h" - -SRCID(cbs, "$Id$"); - - -/* See */ -#define cbsMinimumAlignment ((Align)sizeof(void *)) - -#define cbsOfSplayTree(tree) PARENT(CBSStruct, splayTree, (tree)) -#define cbsBlockOfSplayNode(node) PARENT(CBSBlockStruct, splayNode, (node)) -#define splayTreeOfCBS(tree) (&((cbs)->splayTree)) -#define splayNodeOfCBSBlock(block) (&((block)->splayNode)) -#define keyOfCBSBlock(block) ((void *)&((block)->base)) - - -/* CBSEmergencyBlock* -- Getters and setters for emergency blocks - * - * See . - */ - -#define CBSEmergencyBlockBase(block) ((Addr)(block)) -#define CBSEmergencyBlockLimit(block) ((Addr)((block)[1])) -#define CBSEmergencyBlockSize(block) \ - (AddrOffset(CBSEmergencyBlockBase(block), CBSEmergencyBlockLimit(block))) -#define CBSEmergencyBlockNext(block) ((CBSEmergencyBlock)((block)[0])) - -#define CBSEmergencyBlockSetNext(block, next) \ - BEGIN (block)[0] = (void *)(next); END -#define CBSEmergencyBlockSetLimit(block, limit) \ - BEGIN (block)[1] = (void *)(limit); END - - -/* CBSEmergencyGrain* -- Getters and setters for emergency grains - * - * See . - */ - -#define CBSEmergencyGrainBase(grain) ((Addr)(grain)) -#define CBSEmergencyGrainLimit(cbs, grain) \ - AddrAdd(CBSEmergencyGrainBase(grain), CBSEmergencyGrainSize(cbs)) -#define CBSEmergencyGrainSize(cbs) ((cbs)->alignment) -#define CBSEmergencyGrainNext(grain) ((CBSEmergencyGrain)((grain)[0])) - -#define CBSEmergencyGrainSetNext(grain, next) \ - BEGIN (grain)[0] = (void *)(next); END - - -static CBSEmergencyBlock CBSEmergencyBlockInit(Addr base, Addr limit) -{ - CBSEmergencyBlock block = (CBSEmergencyBlock)base; - CBSEmergencyBlockSetNext(block, NULL); - CBSEmergencyBlockSetLimit(block, limit); - return block; -} - -static CBSEmergencyGrain CBSEmergencyGrainInit(CBS cbs, Addr base, Addr limit) -{ - CBSEmergencyGrain grain = (CBSEmergencyGrain)base; - AVER(AddrOffset(base, limit) == CBSEmergencyGrainSize(cbs)); - CBSEmergencyGrainSetNext(grain, NULL); - return grain; -} - - -/* CBSEnter, CBSLeave -- Avoid re-entrance - * - * .enter-leave: The callbacks are restricted in what they may call. - * These functions enforce this. - * - * .enter-leave.simple: Simple queries may be called from callbacks. - */ - -static void CBSEnter(CBS cbs) -{ - /* Don't need to check as always called from interface function. */ - AVER(!cbs->inCBS); - cbs->inCBS = TRUE; - return; -} - -static void CBSLeave(CBS cbs) -{ - /* Don't need to check as always called from interface function. */ - AVER(cbs->inCBS); - cbs->inCBS = FALSE; - return; -} - - -/* CBSCheck -- Check CBS */ - -Bool CBSCheck(CBS cbs) -{ - /* See .enter-leave.simple. */ - CHECKS(CBS, cbs); - CHECKL(cbs != NULL); - CHECKL(SplayTreeCheck(splayTreeOfCBS(cbs))); - /* nothing to check about splayTreeSize */ - CHECKD(Pool, cbs->blockPool); - CHECKL(BoolCheck(cbs->mayUseInline)); - CHECKL(BoolCheck(cbs->fastFind)); - CHECKL(BoolCheck(cbs->inCBS)); - CHECKL(cbs->new == NULL || FUNCHECK(cbs->new)); - CHECKL(cbs->delete == NULL || FUNCHECK(cbs->delete)); - CHECKL(cbs->grow == NULL || FUNCHECK(cbs->grow)); - CHECKL(cbs->shrink == NULL || FUNCHECK(cbs->shrink)); - CHECKL(cbs->mayUseInline || cbs->emergencyBlockList == NULL); - CHECKL(cbs->mayUseInline || cbs->emergencyGrainList == NULL); - /* See */ - CHECKL(!cbs->mayUseInline || - AlignIsAligned(cbs->alignment, cbsMinimumAlignment)); - /* can't check emergencyBlockList or emergencyGrainList more */ - /* Checking eblSize and eglSize is too laborious without a List ADT */ - /* No MeterCheck */ - - return TRUE; -} - - -/* CBSBlockCheck -- See */ - -Bool CBSBlockCheck(CBSBlock block) -{ - /* See .enter-leave.simple. */ - UNUSED(block); /* Required because there is no signature */ - CHECKL(block != NULL); - CHECKL(SplayNodeCheck(splayNodeOfCBSBlock(block))); - - /* If the block is in the middle of being deleted, */ - /* the pointers will be equal. */ - CHECKL(CBSBlockBase(block) <= CBSBlockLimit(block)); - /* Can't check maxSize because it may be invalid at the time */ - return TRUE; -} - - -/* CBSBlockSize -- see */ - -Size (CBSBlockSize)(CBSBlock block) -{ - /* See .enter-leave.simple. */ - return CBSBlockSize(block); -} - - -/* cbsSplayCompare -- Compare key to [base,limit) - * - * See - */ - -static Compare cbsSplayCompare(void *key, SplayNode node) -{ - Addr base1, base2, limit2; - CBSBlock cbsBlock; - - /* NULL key compares less than everything. */ - if (key == NULL) - return CompareLESS; - - AVER(node != NULL); - - base1 = *(Addr *)key; - cbsBlock = cbsBlockOfSplayNode(node); - base2 = cbsBlock->base; - limit2 = cbsBlock->limit; - - if (base1 < base2) - return CompareLESS; - else if (base1 >= limit2) - return CompareGREATER; - else - return CompareEQUAL; -} - - -/* cbsTestNode, cbsTestTree -- test for nodes larger than the S parameter */ - -static Bool cbsTestNode(SplayTree tree, SplayNode node, - void *closureP, Size size) -{ - CBSBlock block; - - AVERT(SplayTree, tree); - AVERT(SplayNode, node); - AVER(closureP == NULL); - AVER(size > 0); - AVER(cbsOfSplayTree(tree)->fastFind); - - block = cbsBlockOfSplayNode(node); - - return CBSBlockSize(block) >= size; -} - -static Bool cbsTestTree(SplayTree tree, SplayNode node, - void *closureP, Size size) -{ - CBSBlock block; - - AVERT(SplayTree, tree); - AVERT(SplayNode, node); - AVER(closureP == NULL); - AVER(size > 0); - AVER(cbsOfSplayTree(tree)->fastFind); - - block = cbsBlockOfSplayNode(node); - - return block->maxSize >= size; -} - - -/* cbsUpdateNode -- update size info after restructuring */ - -static void cbsUpdateNode(SplayTree tree, SplayNode node, - SplayNode leftChild, SplayNode rightChild) -{ - Size maxSize; - CBSBlock block; - - AVERT(SplayTree, tree); - AVERT(SplayNode, node); - if (leftChild != NULL) - AVERT(SplayNode, leftChild); - if (rightChild != NULL) - AVERT(SplayNode, rightChild); - AVER(cbsOfSplayTree(tree)->fastFind); - - block = cbsBlockOfSplayNode(node); - maxSize = CBSBlockSize(block); - - if (leftChild != NULL) { - Size size = cbsBlockOfSplayNode(leftChild)->maxSize; - if (size > maxSize) - maxSize = size; - } - - if (rightChild != NULL) { - Size size = cbsBlockOfSplayNode(rightChild)->maxSize; - if (size > maxSize) - maxSize = size; - } - - block->maxSize = maxSize; -} - - -/* CBSInit -- Initialise a CBS structure - * - * See . - */ - -Res CBSInit(Arena arena, CBS cbs, void *owner, - CBSChangeSizeMethod new, CBSChangeSizeMethod delete, - CBSChangeSizeMethod grow, CBSChangeSizeMethod shrink, - Size minSize, Align alignment, - Bool mayUseInline, Bool fastFind) -{ - Res res; - - AVERT(Arena, arena); - AVER(new == NULL || FUNCHECK(new)); - AVER(delete == NULL || FUNCHECK(delete)); - AVER(BoolCheck(mayUseInline)); - if (mayUseInline) { - /* See */ - if (!AlignIsAligned(alignment, cbsMinimumAlignment)) - return ResPARAM; - } - - SplayTreeInit(splayTreeOfCBS(cbs), &cbsSplayCompare, - fastFind ? &cbsUpdateNode : NULL); - res = PoolCreate(&(cbs->blockPool), arena, PoolClassMFS(), - sizeof(CBSBlockStruct) * 64, sizeof(CBSBlockStruct)); - if (res != ResOK) - return res; - cbs->splayTreeSize = 0; - - cbs->new = new; - cbs->delete = delete; - cbs->grow = grow; - cbs->shrink = shrink; - cbs->minSize = minSize; - cbs->mayUseInline = mayUseInline; - cbs->fastFind = fastFind; - cbs->alignment = alignment; - cbs->inCBS = TRUE; - cbs->emergencyBlockList = NULL; - cbs->eblSize = 0; - cbs->emergencyGrainList = NULL; - cbs->eglSize = 0; - - METER_INIT(cbs->splaySearch, "size of splay tree", (void *)cbs); - METER_INIT(cbs->eblSearch, "size of emergencyBlockList", (void *)cbs); - METER_INIT(cbs->eglSearch, "size of emergencyGrainList", (void *)cbs); - - cbs->sig = CBSSig; - - AVERT(CBS, cbs); - EVENT2(CBSInit, cbs, owner); - UNUSED(owner); /* @@@@ hack: unused in non-event varieties */ - CBSLeave(cbs); - return ResOK; -} - - -/* CBSFinish -- Finish a CBS structure - * - * See . - */ - -void CBSFinish(CBS cbs) -{ - AVERT(CBS, cbs); - CBSEnter(cbs); - - METER_EMIT(&cbs->splaySearch); - METER_EMIT(&cbs->eblSearch); - METER_EMIT(&cbs->eglSearch); - - cbs->sig = SigInvalid; - - SplayTreeFinish(splayTreeOfCBS(cbs)); - PoolDestroy(cbs->blockPool); - cbs->emergencyBlockList = NULL; - cbs->emergencyGrainList = NULL; -} - - -/* Node change operators - * - * These four functions are called whenever blocks are created, - * destroyed, grow, or shrink. They report to the client, and - * perform the necessary memory management. They are responsible - * for the client interaction logic. - */ - -static void cbsBlockDelete(CBS cbs, CBSBlock block) -{ - Res res; - Size oldSize; - - AVERT(CBS, cbs); - AVERT(CBSBlock, block); - - oldSize = CBSBlockSize(block); - - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - res = SplayTreeDelete(splayTreeOfCBS(cbs), splayNodeOfCBSBlock(block), - keyOfCBSBlock(block)); - AVER(res == ResOK); /* Must be possible to delete node */ - STATISTIC(--cbs->splayTreeSize); - - /* make invalid */ - block->limit = block->base; - - if (cbs->delete != NULL && oldSize >= cbs->minSize) - (*(cbs->delete))(cbs, block, oldSize, (Size)0); - - PoolFree(cbs->blockPool, (Addr)block, sizeof(CBSBlockStruct)); - - return; -} - -static void cbsBlockShrink(CBS cbs, CBSBlock block, Size oldSize) -{ - Size newSize; - - AVERT(CBS, cbs); - AVERT(CBSBlock, block); - - newSize = CBSBlockSize(block); - AVER(oldSize > newSize); - - if (cbs->fastFind) { - SplayNodeRefresh(splayTreeOfCBS(cbs), splayNodeOfCBSBlock(block), - keyOfCBSBlock(block)); - AVER(CBSBlockSize(block) <= block->maxSize); - } - - if (cbs->delete != NULL && oldSize >= cbs->minSize && newSize < cbs->minSize) - (*(cbs->delete))(cbs, block, oldSize, newSize); - else if (cbs->shrink != NULL && newSize >= cbs->minSize) - (*(cbs->shrink))(cbs, block, oldSize, newSize); -} - -static void cbsBlockGrow(CBS cbs, CBSBlock block, Size oldSize) -{ - Size newSize; - - AVERT(CBS, cbs); - AVERT(CBSBlock, block); - - newSize = CBSBlockSize(block); - AVER(oldSize < newSize); - - if (cbs->fastFind) { - SplayNodeRefresh(splayTreeOfCBS(cbs), splayNodeOfCBSBlock(block), - keyOfCBSBlock(block)); - AVER(CBSBlockSize(block) <= block->maxSize); - } - - if (cbs->new != NULL && oldSize < cbs->minSize && newSize >= cbs->minSize) - (*(cbs->new))(cbs, block, oldSize, newSize); - else if (cbs->grow != NULL && oldSize >= cbs->minSize) - (*(cbs->grow))(cbs, block, oldSize, newSize); -} - -static Res cbsBlockNew(CBS cbs, Addr base, Addr limit) -{ - CBSBlock block; - Res res; - Addr p; - Size newSize; - - AVERT(CBS, cbs); - - res = PoolAlloc(&p, cbs->blockPool, sizeof(CBSBlockStruct), - /* withReservoirPermit */ FALSE); - if (res != ResOK) - goto failPoolAlloc; - block = (CBSBlock)p; - - SplayNodeInit(splayNodeOfCBSBlock(block)); - block->base = base; - block->limit = limit; - newSize = CBSBlockSize(block); - block->maxSize = newSize; - - AVERT(CBSBlock, block); - - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - res = SplayTreeInsert(splayTreeOfCBS(cbs), splayNodeOfCBSBlock(block), - keyOfCBSBlock(block)); - AVER(res == ResOK); - STATISTIC(++cbs->splayTreeSize); - - if (cbs->new != NULL && newSize >= cbs->minSize) - (*(cbs->new))(cbs, block, (Size)0, newSize); - - return ResOK; - -failPoolAlloc: - AVER(res != ResOK); - return res; -} - - -/* cbsInsertIntoTree -- Insert a range into the splay tree */ - -static Res cbsInsertIntoTree(Addr *baseReturn, Addr *limitReturn, - CBS cbs, Addr base, Addr limit) -{ - Res res; - Addr newBase, newLimit; - SplayNode leftSplay, rightSplay; - CBSBlock leftCBS, rightCBS; - Bool leftMerge, rightMerge; - Size oldSize; - - AVERT(CBS, cbs); - AVER(base != (Addr)0); - AVER(base < limit); - AVER(AddrIsAligned(base, cbs->alignment)); - AVER(AddrIsAligned(limit, cbs->alignment)); - - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - res = SplayTreeNeighbours(&leftSplay, &rightSplay, - splayTreeOfCBS(cbs), (void *)&base); - if (res != ResOK) - goto fail; - - if (leftSplay == NULL) { - leftCBS = NULL; - leftMerge = FALSE; - } else { - leftCBS = cbsBlockOfSplayNode(leftSplay); - AVER(leftCBS->limit <= base); /* by cbsSplayCompare */ - leftMerge = leftCBS->limit == base; - } - - if (rightSplay == NULL) { - rightCBS = NULL; - rightMerge = FALSE; - } else { - rightCBS = cbsBlockOfSplayNode(rightSplay); - if (rightCBS != NULL && limit > rightCBS->base) { - res = ResFAIL; - goto fail; - } - rightMerge = rightCBS->base == limit; - } - - newBase = leftMerge ? CBSBlockBase(leftCBS) : base; - newLimit = rightMerge ? CBSBlockLimit(rightCBS) : limit; - - if (leftMerge) { - if (rightMerge) { - Size oldLeftSize = CBSBlockSize(leftCBS); - Size oldRightSize = CBSBlockSize(rightCBS); - - /* must block larger neighbour and destroy smaller neighbour; */ - /* see */ - if (oldLeftSize >= oldRightSize) { - Addr rightLimit = rightCBS->limit; - cbsBlockDelete(cbs, rightCBS); - leftCBS->limit = rightLimit; - cbsBlockGrow(cbs, leftCBS, oldLeftSize); - } else { /* left block is smaller */ - Addr leftBase = leftCBS->base; - cbsBlockDelete(cbs, leftCBS); - rightCBS->base = leftBase; - cbsBlockGrow(cbs, rightCBS, oldRightSize); - } - } else { /* leftMerge, !rightMerge */ - oldSize = CBSBlockSize(leftCBS); - leftCBS->limit = limit; - cbsBlockGrow(cbs, leftCBS, oldSize); - } - } else { /* !leftMerge */ - if (rightMerge) { - oldSize = CBSBlockSize(rightCBS); - rightCBS->base = base; - cbsBlockGrow(cbs, rightCBS, oldSize); - } else { /* !leftMerge, !rightMerge */ - res = cbsBlockNew(cbs, base, limit); - if (res != ResOK) - goto fail; - } - } - - AVER(newBase <= base); - AVER(newLimit >= limit); - *baseReturn = newBase; - *limitReturn = newLimit; - - return ResOK; - -fail: - AVER(res != ResOK); - return res; -} - - -/* cbsCoalesceWithEmergencyLists -- coalesce received range with EBL and EGL - * - * Attempts to extend the range about to be freed by adding ranges from - * the emergency lists. May remove blocks from the emergency list. - */ - -static Res cbsCoalesceWithEmergencyLists(Addr *baseIO, Addr *limitIO, CBS cbs) -{ - Addr base, limit; - Count nCoalescences = 0; - - AVER(baseIO != NULL); - AVER(limitIO != NULL); - AVERT(CBS, cbs); - AVER(cbs->mayUseInline); - - base = *baseIO; - limit = *limitIO; - AVER(base < limit); - - if (cbs->emergencyBlockList != NULL) { - CBSEmergencyBlock prev, block, next; - Addr blockBase, blockLimit; - - METER_ACC(cbs->eblSearch, cbs->eblSize); - for(block = cbs->emergencyBlockList, prev = NULL; - block != NULL && CBSEmergencyBlockBase(block) <= limit; - block = CBSEmergencyBlockNext(block)) { - - blockBase = CBSEmergencyBlockBase(block); - blockLimit = CBSEmergencyBlockLimit(block); - AVER(blockBase < blockLimit); - - if (prev != NULL) - AVER(CBSEmergencyBlockLimit(prev) < blockBase); - - if (blockLimit == base) { - base = blockBase; - next = CBSEmergencyBlockNext(block); - if (prev == NULL) - cbs->emergencyBlockList = next; - else - CBSEmergencyBlockSetNext(prev, next); - ++nCoalescences; - STATISTIC(--cbs->eblSize); - AVER(cbs->emergencyBlockList != NULL || cbs->eblSize == 0); - } else if (blockBase == limit) { - limit = blockLimit; - next = CBSEmergencyBlockNext(block); - if (prev == NULL) - cbs->emergencyBlockList = next; - else - CBSEmergencyBlockSetNext(prev, next); - ++nCoalescences; - STATISTIC(--cbs->eblSize); - AVER(cbs->emergencyBlockList != NULL || cbs->eblSize == 0); - /* For loop will stop at next test */ - } else if (blockLimit > base) { - return ResFAIL; /* range intersects block */ - } else { - prev = block; /* Only move prev if we didn't delete */ - } - } - /* block's next is still valid, even if it's been coalesced */ - } - - if (cbs->emergencyGrainList != NULL) { - CBSEmergencyGrain prev, grain, next; - Addr grainBase, grainLimit; - - METER_ACC(cbs->eglSearch, cbs->eglSize); - for(grain = cbs->emergencyGrainList, prev = NULL; - grain != NULL && CBSEmergencyGrainBase(grain) <= limit && - nCoalescences < 2; - grain = CBSEmergencyGrainNext(grain)) { - grainBase = CBSEmergencyGrainBase(grain); - grainLimit = CBSEmergencyGrainLimit(cbs, grain); - AVER(grainBase < grainLimit); - - if (prev != NULL) - AVER(CBSEmergencyGrainLimit(cbs, prev) < grainBase); - - if (grainLimit == base) { - base = grainBase; - next = CBSEmergencyGrainNext(grain); - if (prev == NULL) - cbs->emergencyGrainList = next; - else - CBSEmergencyGrainSetNext(prev, next); - ++nCoalescences; - STATISTIC(--cbs->eglSize); - AVER(cbs->emergencyGrainList != NULL || cbs->eglSize == 0); - } else if (grainBase == limit) { - limit = grainLimit; - next = CBSEmergencyGrainNext(grain); - if (prev == NULL) - cbs->emergencyGrainList = next; - else - CBSEmergencyGrainSetNext(prev, next); - ++nCoalescences; - STATISTIC(--cbs->eglSize); - AVER(cbs->emergencyGrainList != NULL || cbs->eglSize == 0); - break; - } else if (grainLimit > base) { - return ResFAIL; /* range intersects grain */ - } else { - prev = grain; - } - } - /* grain's next is still valid, even if it's been coalesced */ - } - - /* Because the lists are known to have isolated ranges, there can */ - /* be no more than 2 coalescences. */ - AVER(nCoalescences <= 2); - - *baseIO = base; - *limitIO = limit; - return ResOK; -} - - -/* cbsAddToEmergencyLists -- Adds range to emergency lists - * - * The range must be unadjacent to any items on the emergency lists. - */ - -static Res cbsAddToEmergencyLists(CBS cbs, Addr base, Addr limit) -{ - Res res = ResOK; - Size size; - - AVERT(CBS, cbs); - AVER(base < limit); - AVER(cbs->mayUseInline); - - size = AddrOffset(base, limit); - /* Use the block list if possible. See . */ - if (size > cbsMinimumAlignment) { - CBSEmergencyBlock prev, block, new; - new = CBSEmergencyBlockInit(base, limit); - METER_ACC(cbs->eblSearch, cbs->eblSize); - for(prev = NULL, block = cbs->emergencyBlockList; - block != NULL && CBSEmergencyBlockBase(block) < base; - prev = block, block = CBSEmergencyBlockNext(block)) { - if (prev != NULL) - AVER(CBSEmergencyBlockLimit(prev) < CBSEmergencyBlockBase(block)); - AVER(CBSEmergencyBlockBase(block) < CBSEmergencyBlockLimit(block)); - } - - if (prev != NULL && block != NULL) - AVER(CBSEmergencyBlockLimit(prev) < CBSEmergencyBlockBase(block)); - - /* check ordering: prev ... new ... block */ - if (prev != NULL && CBSEmergencyBlockLimit(prev) >= base) - return ResFAIL; /* range intersects with existing block */ - - if (block != NULL && limit >= CBSEmergencyBlockBase(block)) - return ResFAIL; /* range intersects with existing block */ - - if (prev == NULL) - cbs->emergencyBlockList = new; - else - CBSEmergencyBlockSetNext(prev, new); - CBSEmergencyBlockSetNext(new, block); /* may be NULL */ - STATISTIC(++cbs->eblSize); - } else if (size == CBSEmergencyGrainSize(cbs)) { - CBSEmergencyGrain prev, grain, new; - new = CBSEmergencyGrainInit(cbs, base, limit); - METER_ACC(cbs->eglSearch, cbs->eglSize); - for(prev = NULL, grain = cbs->emergencyGrainList; - grain != NULL && CBSEmergencyGrainBase(grain) < base; - prev = grain, grain = CBSEmergencyGrainNext(grain)) { - if (prev != NULL) - AVER(CBSEmergencyGrainLimit(cbs, prev) < - CBSEmergencyGrainBase(grain)); - } - - if (prev != NULL && grain != NULL) - AVER(CBSEmergencyGrainLimit(cbs, prev) < CBSEmergencyGrainBase(grain)); - - /* check ordering: prev ... new ... grain */ - if (prev != NULL && CBSEmergencyGrainLimit(cbs, prev) >= base) - return ResFAIL; /* range intersects with existing grain */ - - if (grain != NULL && limit >= CBSEmergencyGrainBase(grain)) - return ResFAIL; /* range intersects with existing grain */ - - if (prev == NULL) - cbs->emergencyGrainList = new; - else - CBSEmergencyGrainSetNext(prev, new); - CBSEmergencyGrainSetNext(new, grain); /* may be NULL */ - STATISTIC(++cbs->eglSize); - } else { - NOTREACHED; - res = ResFAIL; /* in case AVERs are compiled out */ - } - - return res; -} - - -/* cbsFlushEmergencyLists -- Attempt to move ranges to CBS proper */ - -static void cbsFlushEmergencyLists(CBS cbs) -{ - Res res = ResOK; - Addr base, limit; - - AVERT(CBS, cbs); - AVER(cbs->mayUseInline); - - if (cbs->emergencyBlockList != NULL) { - CBSEmergencyBlock block; - METER_ACC(cbs->eblSearch, cbs->eblSize); - for(block = cbs->emergencyBlockList; - block != NULL; - block = CBSEmergencyBlockNext(block)) { - AVER(CBSEmergencyBlockBase(block) < CBSEmergencyBlockLimit(block)); - res = cbsInsertIntoTree(&base, &limit, - cbs, CBSEmergencyBlockBase(block), - CBSEmergencyBlockLimit(block)); - if (res == ResOK) { - AVER(cbs->emergencyBlockList == block); - /* Emergency block is isolated in CBS */ - AVER(base == CBSEmergencyBlockBase(block)); - AVER(limit == CBSEmergencyBlockLimit(block)); - - cbs->emergencyBlockList = CBSEmergencyBlockNext(block); - STATISTIC(--cbs->eblSize); - AVER(cbs->emergencyBlockList != NULL || cbs->eblSize == 0); - } else { - AVER(ResIsAllocFailure(res)); - goto done; - } - } - } - - if (cbs->emergencyGrainList != NULL) { - CBSEmergencyGrain grain; - METER_ACC(cbs->eglSearch, cbs->eglSize); - for(grain = cbs->emergencyGrainList; - grain != NULL; - grain = CBSEmergencyGrainNext(grain)) { - res = cbsInsertIntoTree(&base, &limit, - cbs, CBSEmergencyGrainBase(grain), - CBSEmergencyGrainLimit(cbs, grain)); - if (res == ResOK) { - AVER(cbs->emergencyGrainList == grain); - /* Emergency grain is isolated in CBS */ - AVER(base == CBSEmergencyGrainBase(grain)); - AVER(limit == CBSEmergencyGrainLimit(cbs, grain)); - - cbs->emergencyGrainList = CBSEmergencyGrainNext(grain); - STATISTIC(--cbs->eglSize); - AVER(cbs->emergencyGrainList != NULL || cbs->eglSize == 0); - } else { - AVER(ResIsAllocFailure(res)); - goto done; - } - } - } - - done: - return; -} - - -/* CBSInsert -- Insert a range into the CBS - * - * See . - */ - -Res CBSInsertReturningRange(Addr *baseReturn, Addr *limitReturn, - CBS cbs, Addr base, Addr limit) -{ - Addr newBase, newLimit; - Res res; - - AVERT(CBS, cbs); - CBSEnter(cbs); - - AVER(base != (Addr)0); - AVER(base < limit); - AVER(AddrIsAligned(base, cbs->alignment)); - AVER(AddrIsAligned(limit, cbs->alignment)); - - if (cbs->mayUseInline) { - newBase = base; - newLimit = limit; - - res = cbsCoalesceWithEmergencyLists(&newBase, &newLimit, cbs); - if (res != ResOK) { - AVER(res == ResFAIL); - goto done; - } - - res = cbsInsertIntoTree(&newBase, &newLimit, cbs, newBase, newLimit); - /* newBase and newLimit only changed if res == ResOK */ - - if (ResIsAllocFailure(res)) { - res = cbsAddToEmergencyLists(cbs, newBase, newLimit); - if (res != ResOK) { - AVER(res == ResFAIL); - goto done; - } - } else { - /* Attempt to clear emergency lists */ - cbsFlushEmergencyLists(cbs); - } - } else { - res = cbsInsertIntoTree(&newBase, &newLimit, cbs, base, limit); - } - - done: - if (res == ResOK) { - AVER(newBase <= base); - AVER(limit <= newLimit); - *baseReturn = newBase; - *limitReturn = newLimit; - } - - CBSLeave(cbs); - return res; -} - -Res CBSInsert(CBS cbs, Addr base, Addr limit) -{ - Res res; - Addr newBase, newLimit; - - /* all parameters checked by CBSInsertReturningRange */ - /* CBSEnter/Leave done by CBSInsertReturningRange */ - - res = CBSInsertReturningRange(&newBase, &newLimit, - cbs, base, limit); - - return res; -} - - -/* cbsDeleteFrom* -- delete blocks from different parts of the CBS */ - -static Res cbsDeleteFromTree(CBS cbs, Addr base, Addr limit) -{ - Res res; - CBSBlock cbsBlock; - SplayNode splayNode; - Size oldSize; - - /* parameters already checked */ - - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - res = SplayTreeSearch(&splayNode, splayTreeOfCBS(cbs), (void *)&base); - if (res != ResOK) - goto failSplayTreeSearch; - cbsBlock = cbsBlockOfSplayNode(splayNode); - - if (limit > cbsBlock->limit) { - res = ResFAIL; - goto failLimitCheck; - } - - if (base == cbsBlock->base) { - if (limit == cbsBlock->limit) { /* entire block */ - cbsBlockDelete(cbs, cbsBlock); - } else { /* remaining fragment at right */ - AVER(limit < cbsBlock->limit); - oldSize = CBSBlockSize(cbsBlock); - cbsBlock->base = limit; - cbsBlockShrink(cbs, cbsBlock, oldSize); - } - } else { - AVER(base > cbsBlock->base); - if (limit == cbsBlock->limit) { /* remaining fragment at left */ - oldSize = CBSBlockSize(cbsBlock); - cbsBlock->limit = base; - cbsBlockShrink(cbs, cbsBlock, oldSize); - } else { /* two remaining fragments */ - Size leftNewSize = AddrOffset(cbsBlock->base, base); - Size rightNewSize = AddrOffset(limit, cbsBlock->limit); - /* must shrink larger fragment and create smaller; */ - /* see */ - if (leftNewSize >= rightNewSize) { - Addr oldLimit = cbsBlock->limit; - AVER(limit < cbsBlock->limit); - oldSize = CBSBlockSize(cbsBlock); - cbsBlock->limit = base; - cbsBlockShrink(cbs, cbsBlock, oldSize); - res = cbsBlockNew(cbs, limit, oldLimit); - if (res != ResOK) { - AVER(ResIsAllocFailure(res)); - if (cbs->mayUseInline) { - res = cbsAddToEmergencyLists(cbs, limit, oldLimit); - AVER(res == ResOK); - } else { - goto failNew; - } - } - } else { /* right fragment is larger */ - Addr oldBase = cbsBlock->base; - AVER(base > cbsBlock->base); - oldSize = CBSBlockSize(cbsBlock); - cbsBlock->base = limit; - cbsBlockShrink(cbs, cbsBlock, oldSize); - res = cbsBlockNew(cbs, oldBase, base); - if (res != ResOK) { - AVER(ResIsAllocFailure(res)); - if (cbs->mayUseInline) { - res = cbsAddToEmergencyLists(cbs, oldBase, base); - AVER(res == ResOK); - } else { - goto failNew; - } - } - } - } - } - - return ResOK; - -failNew: -failLimitCheck: -failSplayTreeSearch: - AVER(res != ResOK); - return res; -} - - -static Res cbsDeleteFromEmergencyBlockList(CBS cbs, Addr base, Addr limit) -{ - Res res; - Addr blockBase, blockLimit; - CBSEmergencyBlock prev, block; - - /* parameters already checked in caller */ - AVER(cbs->mayUseInline); - - METER_ACC(cbs->eblSearch, cbs->eblSize); - for(prev = NULL, block = cbs->emergencyBlockList; - block != NULL && CBSEmergencyBlockLimit(block) < limit; - prev = block, block = CBSEmergencyBlockNext(block)) { - AVER(CBSEmergencyBlockBase(block) < CBSEmergencyBlockLimit(block)); - if (CBSEmergencyBlockBase(block) >= base) - return ResFAIL; - if (prev != NULL) - AVER(CBSEmergencyBlockLimit(prev) < CBSEmergencyBlockBase(block)); - } - - if (block != NULL) { - blockBase = CBSEmergencyBlockBase(block); - blockLimit = CBSEmergencyBlockLimit(block); - AVER(blockBase < blockLimit); - AVER(blockLimit >= limit); - - if (blockBase <= base && limit <= blockLimit) { - /* remove from list */ - if (prev == NULL) - cbs->emergencyBlockList = CBSEmergencyBlockNext(block); - else - CBSEmergencyBlockSetNext(prev, CBSEmergencyBlockNext(block)); - STATISTIC(--cbs->eblSize); - AVER(cbs->emergencyBlockList != NULL || cbs->eblSize == 0); - if (blockBase < base) { - res = cbsAddToEmergencyLists(cbs, blockBase, base); - if (res != ResOK) - return res; - } - if (limit < blockLimit) { - res = cbsAddToEmergencyLists(cbs, limit, blockLimit); - if (res != ResOK) - return res; - } - return ResOK; - } else { - return ResFAIL; /* partly in list */ - } - } - return ResFAIL; /* not in list at all */ -} - - -static Res cbsDeleteFromEmergencyGrainList(CBS cbs, Addr base, Addr limit) -{ - Addr grainBase, grainLimit; - CBSEmergencyGrain prev, grain; - - /* parameters already checked in caller */ - AVER(cbs->mayUseInline); - if (AddrOffset(base, limit) != CBSEmergencyGrainSize(cbs)) - return ResFAIL; - - METER_ACC(cbs->eglSearch, cbs->eglSize); - for(prev = NULL, grain = cbs->emergencyGrainList; - grain != NULL && CBSEmergencyGrainLimit(cbs, grain) < limit; - prev = grain, grain = CBSEmergencyGrainNext(grain)) { - if (prev != NULL) - AVER(CBSEmergencyGrainLimit(cbs, prev) < CBSEmergencyGrainBase(grain)); - } - - if (grain != NULL) { - grainBase = CBSEmergencyGrainBase(grain); - grainLimit = CBSEmergencyGrainLimit(cbs, grain); - AVER(grainLimit >= limit); - - if (grainBase <= base && limit <= grainLimit) { - AVER(grainBase == base); - AVER(grainLimit == limit); - /* remove from list */ - if (prev == NULL) - cbs->emergencyGrainList = CBSEmergencyGrainNext(grain); - else - CBSEmergencyGrainSetNext(prev, CBSEmergencyGrainNext(grain)); - STATISTIC(--cbs->eglSize); - AVER(cbs->emergencyGrainList != NULL || cbs->eglSize == 0); - return ResOK; - } else { - return ResFAIL; /* range is partly in list */ - } - } - return ResFAIL; /* range is not in list at all */ -} - - -/* CBSDelete -- Remove a range from a CBS - * - * See . - */ - -Res CBSDelete(CBS cbs, Addr base, Addr limit) -{ - Res res; - - AVERT(CBS, cbs); - CBSEnter(cbs); - - AVER(base != NULL); - AVER(limit > base); - AVER(AddrIsAligned(base, cbs->alignment)); - AVER(AddrIsAligned(limit, cbs->alignment)); - - res = cbsDeleteFromTree(cbs, base, limit); - - /* We rely on the consistency of the three free structures. */ - /* These checks don't distinguish "partially in" from "not in". */ - if (cbs->mayUseInline) { - AVER(res == ResOK || res == ResFAIL); - if (res == ResFAIL) { /* wasn't in tree */ - res = cbsDeleteFromEmergencyBlockList(cbs, base, limit); - if (res == ResFAIL) { /* wasn't in block list */ - res = cbsDeleteFromEmergencyGrainList(cbs, base, limit); - } - } - /* always worth trying, wherever we found the deleted block */ - if (res == ResOK) - cbsFlushEmergencyLists(cbs); - } - - CBSLeave(cbs); - return res; -} - - -Res CBSBlockDescribe(CBSBlock block, mps_lib_FILE *stream) -{ - Res res; - - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, - "[$P,$P) {$U}", - (WriteFP)block->base, - (WriteFP)block->limit, - (WriteFU)block->maxSize, - NULL); - return res; -} - -static Res CBSSplayNodeDescribe(SplayNode splayNode, mps_lib_FILE *stream) -{ - Res res; - - if (splayNode == NULL) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = CBSBlockDescribe(cbsBlockOfSplayNode(splayNode), stream); - return res; -} - - -/* CBSIterate -- Iterate all blocks in CBS - * - * This is not necessarily efficient. - * See . - */ - -/* Internal version without enter/leave checking. */ -static void cbsIterateInternal(CBS cbs, CBSIterateMethod iterate, void *closureP) -{ - SplayNode splayNode; - SplayTree splayTree; - CBSBlock cbsBlock; - - AVERT(CBS, cbs); - AVER(FUNCHECK(iterate)); - - splayTree = splayTreeOfCBS(cbs); - /* .splay-iterate.slow: We assume that splay tree iteration does */ - /* searches and meter it. */ - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - splayNode = SplayTreeFirst(splayTree, NULL); - while(splayNode != NULL) { - cbsBlock = cbsBlockOfSplayNode(splayNode); - if (!(*iterate)(cbs, cbsBlock, closureP)) { - break; - } - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - splayNode = SplayTreeNext(splayTree, splayNode, keyOfCBSBlock(cbsBlock)); - } - return; -} - -void CBSIterate(CBS cbs, CBSIterateMethod iterate, void *closureP) -{ - AVERT(CBS, cbs); - AVER(FUNCHECK(iterate)); - CBSEnter(cbs); - - cbsIterateInternal(cbs, iterate, closureP); - - CBSLeave(cbs); - return; -} - - -/* CBSIterateLarge -- Iterate only large blocks - * - * This function iterates only blocks that are larger than or equal - * to the minimum size. - */ - -typedef struct CBSIterateLargeClosureStruct { - void *p; - CBSIterateMethod f; -} CBSIterateLargeClosureStruct, *CBSIterateLargeClosure; - -static Bool cbsIterateLargeAction(CBS cbs, CBSBlock block, void *p) -{ - Bool b = TRUE; - CBSIterateLargeClosure closure; - - closure = (CBSIterateLargeClosure)p; - AVER(closure != NULL); - - if (CBSBlockSize(block) >= cbs->minSize) - b = (closure->f)(cbs, block, closure->p); - - return b; -} - - -void CBSIterateLarge(CBS cbs, CBSIterateMethod iterate, void *closureP) -{ - CBSIterateLargeClosureStruct closure; - - AVERT(CBS, cbs); - CBSEnter(cbs); - - AVER(FUNCHECK(iterate)); - - closure.p = closureP; - closure.f = iterate; - cbsIterateInternal(cbs, &cbsIterateLargeAction, (void *)&closure); - - CBSLeave(cbs); - return; -} - - -/* CBSSetMinSize -- Set minimum interesting size for cbs - * - * This function may invoke the shrink and grow methods as - * appropriate. See . - */ - -typedef struct { - Size old; - Size new; -} CBSSetMinSizeClosureStruct, *CBSSetMinSizeClosure; - -static Bool cbsSetMinSizeGrow(CBS cbs, CBSBlock block, void *p) -{ - CBSSetMinSizeClosure closure; - Size size; - - closure = (CBSSetMinSizeClosure)p; - AVER(closure->old > closure->new); - size = CBSBlockSize(block); - if (size < closure->old && size >= closure->new) - (*cbs->new)(cbs, block, size, size); - - return TRUE; -} - -static Bool cbsSetMinSizeShrink(CBS cbs, CBSBlock block, void *p) -{ - CBSSetMinSizeClosure closure; - Size size; - - closure = (CBSSetMinSizeClosure)p; - AVER(closure->old < closure->new); - size = CBSBlockSize(block); - if (size >= closure->old && size < closure->new) - (*cbs->delete)(cbs, block, size, size); - - return TRUE; -} - -void CBSSetMinSize(CBS cbs, Size minSize) -{ - CBSSetMinSizeClosureStruct closure; - - AVERT(CBS, cbs); - CBSEnter(cbs); - - closure.old = cbs->minSize; - closure.new = minSize; - - if (minSize < cbs->minSize) - cbsIterateInternal(cbs, &cbsSetMinSizeGrow, (void *)&closure); - else if (minSize > cbs->minSize) - cbsIterateInternal(cbs, &cbsSetMinSizeShrink, (void *)&closure); - - cbs->minSize = minSize; - - CBSLeave(cbs); -} - - -/* CBSFindDeleteCheck -- check method for a CBSFindDelete value */ - -static Bool CBSFindDeleteCheck(CBSFindDelete findDelete) -{ - CHECKL(findDelete == CBSFindDeleteNONE || findDelete == CBSFindDeleteLOW - || findDelete == CBSFindDeleteHIGH - || findDelete == CBSFindDeleteENTIRE); - UNUSED(findDelete); /* */ - - return TRUE; -} - - -/* cbsFindDeleteRange -- delete approriate range of block found */ - -typedef Res (*cbsDeleteMethod)(CBS cbs, Addr base, Addr limit); - -static void cbsFindDeleteRange(Addr *baseReturn, Addr *limitReturn, - CBS cbs, Addr base, Addr limit, Size size, - cbsDeleteMethod delete, - CBSFindDelete findDelete) -{ - Bool callDelete = TRUE; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(CBS, cbs); - AVER(base < limit); - AVER(size > 0); - AVER(AddrOffset(base, limit) >= size); - AVER(FUNCHECK(delete)); - AVERT(CBSFindDelete, findDelete); - - switch(findDelete) { - - case CBSFindDeleteNONE: { - callDelete = FALSE; - } break; - - case CBSFindDeleteLOW: { - limit = AddrAdd(base, size); - } break; - - case CBSFindDeleteHIGH: { - base = AddrSub(limit, size); - } break; - - case CBSFindDeleteENTIRE: { - /* do nothing */ - } break; - - default: { - NOTREACHED; - } break; - } - - if (callDelete) { - Res res; - res = (*delete)(cbs, base, limit); - AVER(res == ResOK); - } - - *baseReturn = base; - *limitReturn = limit; -} - - -/* CBSFindFirst -- find the first block of at least the given size */ - -Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, - CBS cbs, Size size, CBSFindDelete findDelete) -{ - Bool found; - Addr base = (Addr)0, limit = (Addr)0; /* only defined when found is TRUE */ - cbsDeleteMethod deleteMethod = NULL; - - AVERT(CBS, cbs); - CBSEnter(cbs); - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVER(size > 0); - AVER(SizeIsAligned(size, cbs->alignment)); - AVER(cbs->fastFind); - AVERT(CBSFindDelete, findDelete); - - cbsFlushEmergencyLists(cbs); /* might do some good */ - - { - SplayNode node; - - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - found = SplayFindFirst(&node, splayTreeOfCBS(cbs), &cbsTestNode, - &cbsTestTree, NULL, size); - - if (found) { - CBSBlock block; - - block = cbsBlockOfSplayNode(node); - AVER(CBSBlockSize(block) >= size); - base = CBSBlockBase(block); - limit = CBSBlockLimit(block); - deleteMethod = &cbsDeleteFromTree; - } - } - - if (cbs->emergencyBlockList != NULL) { - CBSEmergencyBlock block; - - METER_ACC(cbs->eblSearch, cbs->eblSize); - for(block = cbs->emergencyBlockList; - block != NULL && - (!found || CBSEmergencyBlockBase(block) < base); - block = CBSEmergencyBlockNext(block)) { - if (CBSEmergencyBlockSize(block) >= size) { - found = TRUE; - base = CBSEmergencyBlockBase(block); - limit = CBSEmergencyBlockLimit(block); - deleteMethod = &cbsDeleteFromEmergencyBlockList; - /* @@@@ Could remove in place more efficiently. */ - break; - } - } - } - - if (cbs->emergencyGrainList != NULL && - size <= CBSEmergencyGrainSize(cbs)) { - /* Take first grain */ - CBSEmergencyGrain grain = cbs->emergencyGrainList; - - if (!found || CBSEmergencyGrainBase(grain) < base) { - found = TRUE; - base = CBSEmergencyGrainBase(grain); - limit = CBSEmergencyGrainLimit(cbs, grain); - deleteMethod = &cbsDeleteFromEmergencyGrainList; - } - } - - if (found) { - AVER(AddrOffset(base, limit) >= size); - cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, - deleteMethod, findDelete); - } - - CBSLeave(cbs); - return found; -} - - -/* CBSFindLast -- find the last block of at least the given size */ - -Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, - CBS cbs, Size size, CBSFindDelete findDelete) -{ - Bool found; - Addr base = (Addr)0, limit = (Addr)0; /* only defined in found is TRUE */ - cbsDeleteMethod deleteMethod = NULL; - - AVERT(CBS, cbs); - CBSEnter(cbs); - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVER(size > 0); - AVER(SizeIsAligned(size, cbs->alignment)); - AVER(cbs->fastFind); - AVERT(CBSFindDelete, findDelete); - - cbsFlushEmergencyLists(cbs); /* might do some good */ - - { - SplayNode node; - - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - found = SplayFindLast(&node, splayTreeOfCBS(cbs), &cbsTestNode, - &cbsTestTree, NULL, size); - if (found) { - CBSBlock block; - - block = cbsBlockOfSplayNode(node); - AVER(CBSBlockSize(block) >= size); - base = CBSBlockBase(block); - limit = CBSBlockLimit(block); - deleteMethod = &cbsDeleteFromTree; - } - } - - if (cbs->emergencyBlockList != NULL) { - CBSEmergencyBlock block; - - METER_ACC(cbs->eblSearch, cbs->eblSize); - for(block = cbs->emergencyBlockList; - block != NULL; - block = CBSEmergencyBlockNext(block)) { - if (CBSEmergencyBlockSize(block) >= size && - (!found || CBSEmergencyBlockBase(block) > base)) { - found = TRUE; - base = CBSEmergencyBlockBase(block); - limit = CBSEmergencyBlockLimit(block); - deleteMethod = &cbsDeleteFromEmergencyBlockList; - /* @@@@ Could remove in place more efficiently. */ - } - } - } - - if (cbs->emergencyGrainList != NULL && - size <= CBSEmergencyGrainSize(cbs)) { - CBSEmergencyGrain grain; - - /* Find last grain */ - METER_ACC(cbs->eglSearch, cbs->eglSize); - for(grain = cbs->emergencyGrainList; - CBSEmergencyGrainNext(grain) != NULL; - grain = CBSEmergencyGrainNext(grain)) - NOOP; - - if (!found || CBSEmergencyGrainBase(grain) > base) { - found = TRUE; - base = CBSEmergencyGrainBase(grain); - limit = CBSEmergencyGrainLimit(cbs, grain); - deleteMethod = &cbsDeleteFromEmergencyGrainList; - /* @@@@ Could remove in place more efficiently */ - } - } - - if (found) { - AVER(AddrOffset(base, limit) >= size); - cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, - deleteMethod, findDelete); - } - - CBSLeave(cbs); - return found; -} - - -/* CBSFindLargest -- find the largest block in the CBS */ - -Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, - CBS cbs, CBSFindDelete findDelete) -{ - Bool found = FALSE; - Addr base = (Addr)0, limit = (Addr)0; /* only defined when found is TRUE */ - cbsDeleteMethod deleteMethod = NULL; - Size size = 0; /* suppress bogus warning from MSVC */ - - AVERT(CBS, cbs); - CBSEnter(cbs); - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVER(cbs->fastFind); - AVERT(CBSFindDelete, findDelete); - - cbsFlushEmergencyLists(cbs); /* might do some good */ - - { - SplayNode root; - Bool notEmpty; - - notEmpty = SplayRoot(&root, splayTreeOfCBS(cbs)); - if (notEmpty) { - CBSBlock block; - SplayNode node = NULL; /* suppress "may be used uninitialized" */ - - size = cbsBlockOfSplayNode(root)->maxSize; - METER_ACC(cbs->splaySearch, cbs->splayTreeSize); - found = SplayFindFirst(&node, splayTreeOfCBS(cbs), &cbsTestNode, - &cbsTestTree, NULL, size); - AVER(found); /* maxSize is exact, so we will find it. */ - block = cbsBlockOfSplayNode(node); - AVER(CBSBlockSize(block) >= size); - base = CBSBlockBase(block); - limit = CBSBlockLimit(block); - deleteMethod = &cbsDeleteFromTree; - } - } - - if (cbs->emergencyBlockList != NULL) { - CBSEmergencyBlock block; - - /* Scan the whole list -- could maintain a maxSize to avoid it. */ - METER_ACC(cbs->eblSearch, cbs->eblSize); - for(block = cbs->emergencyBlockList; - block != NULL; - block = CBSEmergencyBlockNext(block)) { - if (CBSEmergencyBlockSize(block) >= size) { - /* .pref: >= so that it prefers the emerg. list to the tree */ - found = TRUE; - size = CBSEmergencyBlockSize(block); - base = CBSEmergencyBlockBase(block); - limit = CBSEmergencyBlockLimit(block); - deleteMethod = &cbsDeleteFromEmergencyBlockList; - /* @@@@ Could remove in place more efficiently. */ - } - } - } - - /* If something was found, it will be larger than an emerg. grain. */ - if (!found && cbs->emergencyGrainList != NULL) { - /* Take first grain */ - CBSEmergencyGrain grain = cbs->emergencyGrainList; - - found = TRUE; - size = CBSEmergencyGrainSize(cbs); - base = CBSEmergencyGrainBase(grain); - limit = CBSEmergencyGrainLimit(cbs, grain); - deleteMethod = &cbsDeleteFromEmergencyGrainList; - } - - if (found) { - cbsFindDeleteRange(baseReturn, limitReturn, cbs, base, limit, size, - deleteMethod, findDelete); - } - - CBSLeave(cbs); - return found; -} - - -/* CBSDescribe -- describe a CBS - * - * See . - */ - -Res CBSDescribe(CBS cbs, mps_lib_FILE *stream) -{ - Res res; - - if (!TESTT(CBS, cbs)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, - "CBS $P {\n", (WriteFP)cbs, - " blockPool: $P\n", (WriteFP)cbs->blockPool, - " new: $F ", (WriteFF)cbs->new, - " delete: $F \n", (WriteFF)cbs->delete, - NULL); - if (res != ResOK) return res; - - res = SplayTreeDescribe(splayTreeOfCBS(cbs), stream, &CBSSplayNodeDescribe); - if (res != ResOK) return res; - - res = METER_WRITE(cbs->splaySearch, stream); - if (res != ResOK) return res; - res = METER_WRITE(cbs->eblSearch, stream); - if (res != ResOK) return res; - res = METER_WRITE(cbs->eglSearch, stream); - if (res != ResOK) return res; - - res = WriteF(stream, "}\n", NULL); - return res; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/cbs.h b/mps/code/cbs.h deleted file mode 100644 index b2fe4d0b27f..00000000000 --- a/mps/code/cbs.h +++ /dev/null @@ -1,156 +0,0 @@ -/* cbs.h: CBS -- Coalescing Block Structure - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .source: . - */ - -#ifndef cbs_h -#define cbs_h - -#include "meter.h" -#include "splay.h" -#include "mpmtypes.h" - - -typedef struct CBSStruct *CBS; -typedef struct CBSBlockStruct *CBSBlock; -typedef void (*CBSChangeSizeMethod)(CBS cbs, CBSBlock block, - Size oldSize, Size newSize); -typedef Bool (*CBSIterateMethod)(CBS cbs, CBSBlock block, void *closureP); - - -/* See */ -typedef void **CBSEmergencyBlock; /* next, limit */ - -/* See */ -typedef void **CBSEmergencyGrain; /* next */ - - -#define CBSSig ((Sig)0x519CB599) /* SIGnature CBS */ - -typedef struct CBSStruct { - SplayTreeStruct splayTree; - Count splayTreeSize; - Pool blockPool; - CBSChangeSizeMethod new; - CBSChangeSizeMethod delete; - CBSChangeSizeMethod grow; - CBSChangeSizeMethod shrink; - Size minSize; - Align alignment; - Bool mayUseInline; - Bool fastFind; - Bool inCBS; /* prevent reentrance */ - CBSEmergencyBlock emergencyBlockList; - Count eblSize; - CBSEmergencyGrain emergencyGrainList; - Count eglSize; - /* meters for sizes of search structures at each op */ - METER_DECL(splaySearch); - METER_DECL(eblSearch); - METER_DECL(eglSearch); - Sig sig; /* sig at end because embeded */ -} CBSStruct; - -typedef struct CBSBlockStruct { - SplayNodeStruct splayNode; - Addr base; - Addr limit; - Size maxSize; /* accurate maximum block size of sub-tree */ -} CBSBlockStruct; - - -extern Bool CBSCheck(CBS cbs); -extern Bool CBSBlockCheck(CBSBlock block); - -extern Res CBSInit(Arena arena, CBS cbs, void *owner, - CBSChangeSizeMethod new, - CBSChangeSizeMethod delete, - CBSChangeSizeMethod grow, - CBSChangeSizeMethod shrink, - Size minSize, - Align alignment, - Bool mayUseInline, - Bool fastFind); -extern void CBSFinish(CBS cbs); - -extern Res CBSInsert(CBS cbs, Addr base, Addr limit); -extern Res CBSInsertReturningRange(Addr *baseReturn, Addr *limitReturn, - CBS cbs, Addr base, Addr limit); -extern Res CBSDelete(CBS cbs, Addr base, Addr limit); -extern void CBSIterate(CBS cbs, CBSIterateMethod iterate, void *closureP); -extern void CBSIterateLarge(CBS cbs, CBSIterateMethod iterate, void *closureP); -extern void CBSSetMinSize(CBS cbs, Size minSize); - -extern Res CBSDescribe(CBS cbs, mps_lib_FILE *stream); -extern Res CBSBlockDescribe(CBSBlock block, mps_lib_FILE *stream); - -/* CBSBlockBase -- See */ -#define CBSBlockBase(block) ((block)->base) -/* CBSBlockLimit -- See */ -#define CBSBlockLimit(block) ((block)->limit) -#define CBSBlockSize(block) AddrOffset((block)->base, (block)->limit) -extern Size (CBSBlockSize)(CBSBlock block); - -typedef unsigned CBSFindDelete; -enum { - CBSFindDeleteNONE = 1,/* don't delete after finding */ - CBSFindDeleteLOW, /* delete precise size from low end */ - CBSFindDeleteHIGH, /* delete precise size from high end */ - CBSFindDeleteENTIRE /* delete entire range */ -}; - -extern Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, - CBS cbs, Size size, CBSFindDelete findDelete); -extern Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, - CBS cbs, Size size, CBSFindDelete findDelete); - -extern Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, - CBS cbs, CBSFindDelete findDelete); - - -#endif /* cbs_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/cbstest.c b/mps/code/cbstest.c deleted file mode 100644 index 818e9c61259..00000000000 --- a/mps/code/cbstest.c +++ /dev/null @@ -1,696 +0,0 @@ -/* cbstest.c: COALESCING BLOCK STRUCTURE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "cbs.h" -#include "mpm.h" -#include "mpsavm.h" -#include "mps.h" -#include "testlib.h" - -#include -#include -#include "mpstd.h" -#include - -SRCID(cbstest, "$Id$"); - - -#define ArraySize ((Size)123456) -#define NOperations ((Size)125000) -#define MinSize ((Size)120) /* Arbitrary size */ -#define Alignment ((Align)sizeof(void *)) - - -static Count NAllocateTried, NAllocateSucceeded, NDeallocateTried, - NDeallocateSucceeded, NNewBlocks, NDeleteBlocks, NGrowBlocks, - NShrinkBlocks; - - -/* Used to predict which callbacks will be called, and with which values. */ -/* At most one callback of each type will be called. */ -typedef struct CallbackPredictionStruct { - Bool shouldBeCalled; - Size oldSize; - Addr base; - Addr limit; -} CallbackPredictionStruct, *CallbackPrediction; - -static CallbackPredictionStruct CallbackNew; -static CallbackPredictionStruct CallbackDelete; -static CallbackPredictionStruct CallbackGrow; -static CallbackPredictionStruct CallbackShrink; - - -typedef struct CheckCBSClosureStruct { - BT allocTable; - Addr base; - Addr limit; - Addr oldLimit; -} CheckCBSClosureStruct, *CheckCBSClosure; - - -static Addr (addrOfIndex)(Addr block, Index i) -{ - return AddrAdd(block, (i * Alignment)); -} - - -static Index (indexOfAddr)(Addr block, Addr a) -{ - return (Index)(AddrOffset(block, a) / Alignment); -} - - -/* This function encapsulates the common tests for the callbacks. */ - -static void testCallback(CBS cbs, CBSBlock cbsBlock, - Size oldSize, Size newSize, - CallbackPrediction prediction) -{ - Insist(CBSCheck(cbs)); - Insist(CBSBlockCheck(cbsBlock)); - Insist(prediction->shouldBeCalled); - Insist(oldSize == prediction->oldSize); - - if (newSize == 0) { - Insist(prediction->base == 0); - Insist(prediction->limit == 0); - } else { - Insist(CBSBlockSize(cbsBlock) == newSize); - Insist(newSize == AddrOffset(prediction->base, prediction->limit)); - Insist(CBSBlockBase(cbsBlock) == prediction->base); - Insist(CBSBlockLimit(cbsBlock) == prediction->limit); - } - - prediction->shouldBeCalled = FALSE; -} - - -static void cbsNewCallback(CBS cbs, CBSBlock cbsBlock, - Size oldSize, Size newSize) -{ - testCallback(cbs, cbsBlock, oldSize, newSize, &CallbackNew); - Insist(oldSize < cbs->minSize); - Insist(newSize >= cbs->minSize); - - NNewBlocks++; -} - - -static void cbsDeleteCallback(CBS cbs, CBSBlock cbsBlock, - Size oldSize, Size newSize) -{ - testCallback(cbs, cbsBlock, oldSize, newSize, &CallbackDelete); - Insist(oldSize >= cbs->minSize); - Insist(newSize < cbs->minSize); - - NDeleteBlocks++; -} - - -static void cbsGrowCallback(CBS cbs, CBSBlock cbsBlock, - Size oldSize, Size newSize) -{ - testCallback(cbs, cbsBlock, oldSize, newSize, &CallbackGrow); - Insist(oldSize >= cbs->minSize); - Insist(newSize >= cbs->minSize); - Insist(oldSize < newSize); - - NGrowBlocks++; -} - - -static void cbsShrinkCallback(CBS cbs, CBSBlock cbsBlock, - Size oldSize, Size newSize) -{ - testCallback(cbs, cbsBlock, oldSize, newSize, &CallbackShrink); - Insist(oldSize >= cbs->minSize); - Insist(newSize >= cbs->minSize); - Insist(oldSize > newSize); - - NShrinkBlocks++; -} - - -static Bool checkCBSAction(CBS cbs, CBSBlock cbsBlock, void *p) -{ - Addr base, limit; - CheckCBSClosure closure = (CheckCBSClosure)p; - - /* Don't need to check cbs every time */ - UNUSED(cbs); - Insist(closure != NULL); - - base = CBSBlockBase(cbsBlock); - limit = CBSBlockLimit(cbsBlock); - - if (base > closure->oldLimit) { - Insist(BTIsSetRange(closure->allocTable, - indexOfAddr(closure->base, closure->oldLimit), - indexOfAddr(closure->base, base))); - } else { /* must be at start of table */ - Insist(base == closure->oldLimit); - Insist(closure->oldLimit == closure->base); - } - - Insist(BTIsResRange(closure->allocTable, - indexOfAddr(closure->base, base), - indexOfAddr(closure->base, limit))); - - - closure->oldLimit = limit; - - return TRUE; -} - - -static void checkCBS(CBS cbs, BT allocTable, Addr dummyBlock) -{ - CheckCBSClosureStruct closure; - - closure.allocTable = allocTable; - closure.base = dummyBlock; - closure.limit = addrOfIndex(closure.base, ArraySize); - closure.oldLimit = closure.base; - - CBSIterate(cbs, checkCBSAction, (void *)&closure); - - if (closure.oldLimit == closure.base) - Insist(BTIsSetRange(allocTable, 0, - indexOfAddr(dummyBlock, closure.limit))); - else if (closure.limit > closure.oldLimit) - Insist(BTIsSetRange(allocTable, - indexOfAddr(dummyBlock, closure.oldLimit), - indexOfAddr(dummyBlock, closure.limit))); - else - Insist(closure.oldLimit == closure.limit); -} - - -static Word cbsRnd(Word limit) -{ - /* Not very uniform, but never mind. */ - return (Word)rnd() % limit; -} - - -/* nextEdge -- Finds the next transition in the bit table - * - * Returns the index greater than such that the - * range [, ) has the same value in the bit table, - * and has a different value or does not exist. - */ - -static Index nextEdge(BT bt, Size size, Index base) -{ - Index end; - Bool baseValue; - - Insist(bt != NULL); - Insist(base < size); - - baseValue = BTGet(bt, base); - - for(end = base + 1; end < size && BTGet(bt, end) == baseValue; end++) - NOOP; - - return end; -} - - -/* lastEdge -- Finds the previous transition in the bit table - * - * Returns the index less than such that the range - * [, ] has the same value in the bit table, - * and -1 has a different value or does not exist. - */ - -static Index lastEdge(BT bt, Size size, Index base) -{ - Index end; - Bool baseValue; - - Insist(bt != NULL); - Insist(base < size); - - baseValue = BTGet(bt, base); - - for(end = base; end > (Index)0 && BTGet(bt, end - 1) == baseValue; end--) - NOOP; - - return end; -} - - -/* randomRange -- picks random range within table - * - * The function first picks a uniformly distributed within the table. - * - * It then scans forward a binary exponentially distributed - * number of "edges" in the table (that is, transitions between set and - * reset) to get . Note that there is a 50% chance that will - * be the next edge, a 25% chance it will be the edge after, etc., until - * the end of the table. - * - * Finally it picks a uniformly distributed in the range - * [base+1, limit]. - * - * Hence there is a somewhat better than 50% chance that the range will be - * all either set or reset. - */ - -static void randomRange(Addr *baseReturn, Addr *limitReturn, - BT allocTable, Addr block) -{ - Index base; /* the start of our range */ - Index end; /* an edge (i.e. different from its predecessor) */ - /* after base */ - Index limit; /* a randomly chosen value in (base, limit]. */ - - base = cbsRnd(ArraySize); - - do { - end = nextEdge(allocTable, ArraySize, base); - } while(end < ArraySize && cbsRnd(2) == 0); /* p=0.5 exponential */ - - Insist(end > base); - - limit = base + 1 + cbsRnd(end - base); - - *baseReturn = addrOfIndex(block, base); - *limitReturn = addrOfIndex(block, limit); -} - - -/* Set callback expectations */ - -static void clearExpectations(void) -{ - CallbackNew.shouldBeCalled = FALSE; - CallbackDelete.shouldBeCalled = FALSE; - CallbackGrow.shouldBeCalled = FALSE; - CallbackShrink.shouldBeCalled = FALSE; -} - -static void expectCallback(CallbackPrediction prediction, - Size oldSize, Addr base, Addr limit) -{ - Insist(prediction->shouldBeCalled == FALSE); - Insist(base == (Addr)0 || limit > base); - Insist(oldSize != (Size)0 || base != (Addr)0); - Insist(base != (Addr)0 || limit == (Addr)0); - - prediction->shouldBeCalled = TRUE; - prediction->oldSize = oldSize; - prediction->base = base; - prediction->limit = limit; -} - - -static void checkExpectations(void) -{ - Insist(!CallbackNew.shouldBeCalled); - Insist(!CallbackDelete.shouldBeCalled); - Insist(!CallbackGrow.shouldBeCalled); - Insist(!CallbackShrink.shouldBeCalled); -} - - -static void allocate(CBS cbs, Addr block, BT allocTable, - Addr base, Addr limit) -{ - Res res; - Index ib, il; /* Indexed for base and limit */ - Bool isFree; - - ib = indexOfAddr(block, base); - il = indexOfAddr(block, limit); - - isFree = BTIsResRange(allocTable, ib, il); - - /* - printf("allocate: [%p, %p) -- %s\n", - base, limit, isFree ? "succeed" : "fail"); - */ - - NAllocateTried++; - - if (isFree) { - Addr outerBase, outerLimit; /* interval containing [ib, il) */ - Size left, right, total; /* Sizes of block and two fragments */ - - outerBase = - addrOfIndex(block, lastEdge(allocTable, ArraySize, ib)); - outerLimit = - addrOfIndex(block, nextEdge(allocTable, ArraySize, il - 1)); - - left = AddrOffset(outerBase, base); - right = AddrOffset(limit, outerLimit); - total = AddrOffset(outerBase, outerLimit); - - /* based on detailed knowledge of CBS behaviour */ - checkExpectations(); - if (total >= MinSize && left < MinSize && right < MinSize) { - if (left == (Size)0 && right == (Size)0) { - expectCallback(&CallbackDelete, total, (Addr)0, (Addr)0); - } else if (left >= right) { - expectCallback(&CallbackDelete, total, outerBase, base); - } else { - expectCallback(&CallbackDelete, total, limit, outerLimit); - } - } else if (left >= MinSize && right >= MinSize) { - if (left >= right) { - expectCallback(&CallbackShrink, total, outerBase, base); - expectCallback(&CallbackNew, (Size)0, limit, outerLimit); - } else { - expectCallback(&CallbackNew, (Size)0, outerBase, base); - expectCallback(&CallbackShrink, total, limit, outerLimit); - } - } else if (total >= MinSize) { - if (left >= right) { - Insist(left >= MinSize); - Insist(right < MinSize); - expectCallback(&CallbackShrink, total, outerBase, base); - } else { - Insist(left < MinSize); - Insist(right >= MinSize); - expectCallback(&CallbackShrink, total, limit, outerLimit); - } - } - } - - res = CBSDelete(cbs, base, limit); - - if (!isFree) { - die_expect((mps_res_t)res, MPS_RES_FAIL, - "Succeeded in deleting allocated block"); - } else { /* isFree */ - die_expect((mps_res_t)res, MPS_RES_OK, - "failed to delete free block"); - NAllocateSucceeded++; - BTSetRange(allocTable, ib, il); - checkExpectations(); - } -} - - -static void deallocate(CBS cbs, Addr block, BT allocTable, - Addr base, Addr limit) -{ - Res res; - Index ib, il; - Bool isAllocated; - Addr outerBase = base, outerLimit = limit; /* interval containing [ib, il) */ - Addr freeBase, freeLimit; /* interval returned by CBS */ - - ib = indexOfAddr(block, base); - il = indexOfAddr(block, limit); - - isAllocated = BTIsSetRange(allocTable, ib, il); - - /* - printf("deallocate: [%p, %p) -- %s\n", - base, limit, isAllocated ? "succeed" : "fail"); - */ - - NDeallocateTried++; - - if (isAllocated) { - Size left, right, total; /* Sizes of block and two fragments */ - - /* Find the free blocks adjacent to the allocated block */ - if (ib > 0 && !BTGet(allocTable, ib - 1)) { - outerBase = - addrOfIndex(block, lastEdge(allocTable, ArraySize, ib - 1)); - } else { - outerBase = base; - } - - if (il < ArraySize && !BTGet(allocTable, il)) { - outerLimit = - addrOfIndex(block, nextEdge(allocTable, ArraySize, il)); - } else { - outerLimit = limit; - } - - left = AddrOffset(outerBase, base); - right = AddrOffset(limit, outerLimit); - total = AddrOffset(outerBase, outerLimit); - - /* based on detailed knowledge of CBS behaviour */ - checkExpectations(); - if (total >= MinSize && left < MinSize && right < MinSize) { - if (left >= right) - expectCallback(&CallbackNew, left, outerBase, outerLimit); - else - expectCallback(&CallbackNew, right, outerBase, outerLimit); - } else if (left >= MinSize && right >= MinSize) { - if (left >= right) { - expectCallback(&CallbackDelete, right, (Addr)0, (Addr)0); - expectCallback(&CallbackGrow, left, outerBase, outerLimit); - } else { - expectCallback(&CallbackDelete, left, (Addr)0, (Addr)0); - expectCallback(&CallbackGrow, right, outerBase, outerLimit); - } - } else if (total >= MinSize) { - if (left >= right) { - Insist(left >= MinSize); - Insist(right < MinSize); - expectCallback(&CallbackGrow, left, outerBase, outerLimit); - } else { - Insist(left < MinSize); - Insist(right >= MinSize); - expectCallback(&CallbackGrow, right, outerBase, outerLimit); - } - } - } - - res = CBSInsertReturningRange(&freeBase, &freeLimit, cbs, base, limit); - - if (!isAllocated) { - die_expect((mps_res_t)res, MPS_RES_FAIL, - "succeeded in inserting non-allocated block"); - } else { /* isAllocated */ - die_expect((mps_res_t)res, MPS_RES_OK, - "failed to insert allocated block"); - - NDeallocateSucceeded++; - BTResRange(allocTable, ib, il); - checkExpectations(); - Insist(freeBase == outerBase); - Insist(freeLimit == outerLimit); - } -} - - -static void find(CBS cbs, void *block, BT alloc, Size size, Bool high, - CBSFindDelete findDelete) -{ - Bool expected, found; - Index expectedBase, expectedLimit; - Addr foundBase, foundLimit, remainderBase, remainderLimit; - Size oldSize, newSize; - - checkExpectations(); - - expected = (high ? BTFindLongResRangeHigh : BTFindLongResRange) - (&expectedBase, &expectedLimit, alloc, - (Index)0, (Index)ArraySize, (Count)size); - - if (expected) { - oldSize = (expectedLimit - expectedBase) * Alignment; - remainderBase = addrOfIndex(block, expectedBase); - remainderLimit = addrOfIndex(block, expectedLimit); - - switch(findDelete) { - case CBSFindDeleteNONE: { - /* do nothing */ - } break; - case CBSFindDeleteENTIRE: { - remainderBase = remainderLimit; - } break; - case CBSFindDeleteLOW: { - expectedLimit = expectedBase + size; - remainderBase = addrOfIndex(block, expectedLimit); - } break; - case CBSFindDeleteHIGH: { - expectedBase = expectedLimit - size; - remainderLimit = addrOfIndex(block, expectedBase); - } break; - } - - if (findDelete != CBSFindDeleteNONE) { - newSize = AddrOffset(remainderBase, remainderLimit); - - if (oldSize >= MinSize) { - if (newSize == 0) - expectCallback(&CallbackDelete, oldSize, (Addr)0, (Addr)0); - else if (newSize < MinSize) - expectCallback(&CallbackDelete, oldSize, - remainderBase, remainderLimit); - else - expectCallback(&CallbackShrink, oldSize, - remainderBase, remainderLimit); - } - } - } - - found = (high ? CBSFindLast : CBSFindFirst) - (&foundBase, &foundLimit, cbs, size * Alignment, findDelete); - - Insist(found == expected); - - if (found) { - Insist(expectedBase == indexOfAddr(block, foundBase)); - Insist(expectedLimit == indexOfAddr(block, foundLimit)); - checkExpectations(); - - if (findDelete != CBSFindDeleteNONE) - BTSetRange(alloc, expectedBase, expectedLimit); - } - - return; -} - - -#define testArenaSIZE (((size_t)4)<<20) - -extern int main(int argc, char *argv[]) -{ - unsigned i; - Addr base, limit; - mps_arena_t mpsArena; - Arena arena; /* the ANSI arena which we use to allocate the BT */ - CBSStruct cbsStruct; - CBS cbs; - void *p; - Addr dummyBlock; - BT allocTable; - Size size; - Bool high; - CBSFindDelete findDelete = CBSFindDeleteNONE; - - randomize(argc, argv); - - NAllocateTried = NAllocateSucceeded = NDeallocateTried = - NDeallocateSucceeded = NNewBlocks = NDeleteBlocks = - NGrowBlocks = NShrinkBlocks = 0; - - clearExpectations(); - - die(mps_arena_create(&mpsArena, mps_arena_class_vm(), testArenaSIZE), - "mps_arena_create"); - arena = (Arena)mpsArena; /* avoid pun */ - - die((mps_res_t)BTCreate(&allocTable, arena, ArraySize), - "failed to create alloc table"); - - die((mps_res_t)CBSInit(arena, &cbsStruct, NULL, &cbsNewCallback, - &cbsDeleteCallback, &cbsGrowCallback, - &cbsShrinkCallback, MinSize, - Alignment, TRUE, TRUE), - "failed to initialise CBS"); - cbs = &cbsStruct; - - BTSetRange(allocTable, 0, ArraySize); /* Initially all allocated */ - - /* We're not going to use this block, but I feel unhappy just */ - /* inventing addresses. */ - die((mps_res_t)ControlAlloc(&p, arena, ArraySize * Alignment, - /* withReservoirPermit */ FALSE), - "failed to allocate block"); - dummyBlock = (Addr)p; /* avoid pun */ - - printf("Allocated block [%p, %p)\n", (void*)dummyBlock, - (char *)dummyBlock + ArraySize); - - checkCBS(cbs, allocTable, dummyBlock); - for(i = 0; i < NOperations; i++) { - switch(cbsRnd(3)) { - case 0: { - randomRange(&base, &limit, allocTable, dummyBlock); - allocate(cbs, dummyBlock, allocTable, base, limit); - } break; - case 1: { - randomRange(&base, &limit, allocTable, dummyBlock); - deallocate(cbs, dummyBlock, allocTable, base, limit); - } break; - case 2: { - size = cbsRnd(ArraySize / 10) + 1; - high = cbsRnd(2) ? TRUE : FALSE; - switch(cbsRnd(6)) { - case 0: - case 1: - case 2: findDelete = CBSFindDeleteNONE; break; - case 3: findDelete = CBSFindDeleteLOW; break; - case 4: findDelete = CBSFindDeleteHIGH; break; - case 5: findDelete = CBSFindDeleteENTIRE; break; - } - find(cbs, dummyBlock, allocTable, size, high, findDelete); - } break; - } - if (i % 5000 == 0) - checkCBS(cbs, allocTable, dummyBlock); - } - - checkExpectations(); - - /* CBSDescribe prints a very long line. */ - /* CBSDescribe(cbs, mps_lib_get_stdout()); */ - - printf("\nNumber of allocations attempted: %ld\n", NAllocateTried); - printf("Number of allocations succeeded: %ld\n", NAllocateSucceeded); - printf("Number of deallocations attempted: %ld\n", NDeallocateTried); - printf("Number of deallocations succeeded: %ld\n", NDeallocateSucceeded); - printf("Number of new large blocks: %ld\n", NNewBlocks); - printf("Number of deleted large blocks: %ld\n", NDeleteBlocks); - printf("Number of grown large blocks: %ld\n", NGrowBlocks); - printf("Number of shrunk large blocks: %ld\n", NShrinkBlocks); - printf("\nNo problems detected.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/chain.h b/mps/code/chain.h deleted file mode 100644 index 0d2be1de068..00000000000 --- a/mps/code/chain.h +++ /dev/null @@ -1,140 +0,0 @@ -/* chain.h: GENERATION CHAINS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef chain_h -#define chain_h - -#include "mpmtypes.h" -#include "ring.h" - - -/* GenParamStruct -- structure for specifying generation parameters */ -/* .gen-param: This structure must match . */ - -typedef struct GenParamStruct { - Size capacity; /* capacity in kB */ - double mortality; -} GenParamStruct; - - -/* GenDesc -- descriptor of a generation in a chain */ - -typedef struct GenDescStruct *GenDesc; - -#define GenDescSig ((Sig)0x5199E4DE) /* SIGnature GEN DEsc */ - -typedef struct GenDescStruct { - Sig sig; - ZoneSet zones; /* zoneset for this generation */ - Size capacity; /* capacity in kB */ - double mortality; - double proflow; /* predicted proportion of survivors promoted */ - RingStruct locusRing; /* Ring of all PoolGen's in this GenDesc (locus) */ -} GenDescStruct; - - -/* PoolGen -- descriptor of a generation in a pool */ - -typedef struct PoolGenStruct *PoolGen; - -#define PoolGenSig ((Sig)0x519B009E) /* SIGnature POOl GEn */ - -typedef struct PoolGenStruct { - Sig sig; - Serial nr; /* generation number */ - Pool pool; /* pool this belongs to */ - Chain chain; /* chain this belongs to */ - /* link in ring of all PoolGen's in this GenDesc (locus) */ - RingStruct genRing; - Size totalSize; /* total size of segs in gen in this pool */ - Size newSize; /* size allocated since last GC */ - /* newSize when TraceCreate is called. This is for diagnostic */ - /* purposes only. It's used in a DIAG message emitted in TraceStart; */ - /* at that time, newSize has already been diminished by Whiten so we */ - /* can't use that value. This will not work well with multiple */ - /* traces. */ - Size newSizeAtCreate; -} PoolGenStruct; - - -/* Chain -- a generation chain */ - -#define ChainSig ((Sig)0x519C8A14) /* SIGnature CHAIN */ - -typedef struct mps_chain_s { - Sig sig; - Arena arena; - RingStruct chainRing; /* list of chains in the arena */ - TraceSet activeTraces; /* set of traces collecting this chain */ - size_t genCount; /* number of generations */ - GenDescStruct *gens; /* the array of generations */ -} ChainStruct; - - -extern Res ChainCreate(Chain *chainReturn, Arena arena, size_t genCount, - GenParamStruct *params); -extern void ChainDestroy(Chain chain); -extern Bool ChainCheck(Chain chain); - -extern double ChainDeferral(Chain chain); -extern Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace); -extern Res ChainCondemnAll(Chain chain, Trace trace); -extern void ChainStartGC(Chain chain, Trace trace); -extern void ChainEndGC(Chain chain, Trace trace); -extern size_t ChainGens(Chain chain); - - -extern Bool PoolGenCheck(PoolGen gen); -extern Res PoolGenInit(PoolGen gen, Chain chain, Serial nr, Pool pool); -extern void PoolGenFinish(PoolGen gen); -extern void PoolGenFlip(PoolGen gen); -#define PoolGenNr(gen) ((gen)->nr) -extern void PoolGenUpdateZones(PoolGen gen, Seg seg); - - -#endif /* chain_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/check.h b/mps/code/check.h deleted file mode 100644 index 58e62255102..00000000000 --- a/mps/code/check.h +++ /dev/null @@ -1,354 +0,0 @@ -/* check.h: ASSERTION INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .aver: This header defines a family of AVER and NOTREACHED macros. - * These macros should be used to instrument and annotate code with - * invariants, and so provide both interface and internal consistency - * checks. - * - * .comment: Non-obvious AVER statements should always be accompanied by - * a comment. - * - * .disable: When assertions are disabled, AVER expands to something - * which contains the condition but discards the result. Compilers - * will throw the code away, but check its syntax. - * - * .trans.level-check: CheckLevel itself is not checked anywhere. - * - * .careful: BE CAREFUL when changing this file. It is easy to make mistakes - * and change the checking level in a variety and thereby its performance - * without realising it. This has happened before. Eyeball the preprocessor - * output for each variety. For example: - * - * cc -E -DCONFIG_VAR_RASH trace.c - * cc -E -DCONFIG_VAR_HOT trace.c - * cc -E -DCONFIG_VAR_COOL trace.c - * - * Then look at TraceCheck to make sure checking is right, TraceAddWhite - * for general assertions, and TraceFix for the critical path assertions. - */ - -#ifndef check_h -#define check_h - -#include "config.h" -#include "misc.h" -#include "mpslib.h" - - -/* ASSERT -- basic assertion - * - * The ASSERT macro is equivalent to the ISO C assert() except that it is - * always defined, and uses the assertion handler from the MPS plinth, which - * can be replaced by the client code. - * - * It is not intended for direct use within the MPS. Use AVER and CHECK - * macros, which can be controlled by both build and run-time configuration. - */ - -#define ASSERT(cond, condstring) \ - BEGIN \ - if (cond) NOOP; else \ - mps_lib_assert_fail(condstring "\n" __FILE__ "\n" STR(__LINE__)); \ - END - -#define ASSERT_TYPECHECK(type, val) \ - ASSERT(type ## Check(val), "TypeCheck " #type ": " #val) - -#define ASSERT_NULLCHECK(type, val) \ - ASSERT((val) != NULL, "NullCheck " #type ": " #val) - - -/* CheckLevel -- control for check method behaviour - * - * When the MPS is build with AVER_AND_CHECK_ALL (in a "cool" variety) the - * static variable CheckLevel controls the frequency and detail of - * consistency checking on structures. - * - * By default, CHECKLEVEL is defined to a static value in config.h, though - * it can be overridden on the compiler command line, e.g. - * cc -DCHECKLEVEL=CheckLevelSHALLOW ... - * - * However, if CHECKLEVEL_DYNAMIC is defined we use a variable to control - * the level of checking. The run-time overhead for this is quite high - * (observed double run-time on amcss when the variable is set to SHALLOW). - * CHECKLEVEL_DYNAMIC should be set to the initial level for the variable, - * which is in mpm.c. - * - * In general, it's better to adjust the check level by defining CHECKLEVEL - * but this is intended to meet the case where a run-time adjustable - * checking level is required -- where recompilation or relinking is - * undesirable or impossible. - * - * TODO: Should also allow the check level variable to come from an - * environment variable. - * - * TODO: CheckLevelDEEP asserts on arena creation with bootstrapping - * problems. It clearly hasn't been tried for a while. RB 2012-09-01 - */ - -enum { - CheckLevelMINIMAL = 0, /* local sig check only */ - CheckLevelSHALLOW = 1, /* local invariants, */ - /* and adjacent (up, down) sig checks */ - CheckLevelDEEP = 2 /* local invariants, */ - /* and adjacent up sig checks */ - /* and recursive down full type checks */ -}; - -#ifdef CHECKLEVEL_DYNAMIC -extern unsigned CheckLevel; -#undef CHECKLEVEL -#define CHECKLEVEL CheckLevel -#endif - - -/* AVER, AVERT -- MPM assertions - * - * AVER and AVERT are used to assert conditions in the code. AVER checks - * an expression. AVERT checks that a value is of the correct type and - * may perform consistency checks on the value. - * - * AVER and AVERT are on by default, and check conditions even in "hot" - * varieties intended to work in production. To avoid the cost of a check - * in critical parts of the code, use AVER_CRITICAL and AVERT_CRITICAL, - * but only when you've *proved* that this makes a difference to performance - * that affects requirements. - */ - -#if defined(AVER_AND_CHECK_NONE) - -#define AVER(cond) DISCARD(cond) -#define AVERT(type, val) DISCARD(type ## Check(val)) - -#else - -#define AVER(cond) ASSERT(cond, #cond) -#define AVERT ASSERT_TYPECHECK - -#endif - -#if defined(AVER_AND_CHECK_ALL) - -#define AVER_CRITICAL(cond) ASSERT(cond, #cond) -#define AVERT_CRITICAL ASSERT_TYPECHECK - -#else - -#define AVER_CRITICAL DISCARD -#define AVERT_CRITICAL(type, val) DISCARD(type ## Check(val)) - -#endif - - -/* NOTREACHED -- control should never reach this statement - * - * This is a sort of AVER; it is equivalent to AVER(FALSE), but will produce - * a more informative message. - */ - -#if defined(AVER_AND_CHECK_NONE) - -#define NOTREACHED NOOP - -#else - -#define NOTREACHED \ - BEGIN \ - mps_lib_assert_fail("unreachable code" "\n" __FILE__ "\n" STR(__LINE__)); \ - END - -#endif - - -/* TESTT -- check type simply - * - * Must be thread safe. See - * and . - */ - -#define TESTT(type, val) ((val) != NULL && (val)->sig == type ## Sig) - - -/* CHECKS -- Check Signature - * - * (if CHECKLEVEL == CheckLevelMINIMAL, this is all we check) - */ - -#if defined(AVER_AND_CHECK_NONE) -#define CHECKS(type, val) DISCARD(TESTT(type, val)) -#else -#define CHECKS(type, val) \ - ASSERT(TESTT(type, val), "SigCheck " #type ": " #val) -#endif - - -/* CHECKL, CHECKD, CHECKU -- local, "down", and "up" checks - * - * Each type should have a function defined called Check that checks - * the consistency of the type. This function should return TRUE iff the - * value passes consistency checks. In general, it should assert otherwise, - * but we allow for the possibility of returning FALSE in this case for - * configuration adaptability. - * - * For structure types, the check function should: - * - * - check its own signature with CHECKS - * - * - check fields that it "owns" with CHECKL, like asserts - * - * - check "down" values which are its "children" with CHECKD - * - * - check "up" values which are its "parents" with CHECKU. - * - * These various checks will be compiled out or compiled to be controlled - * by CHECKLEVEL. - * - * For example: - * - * Bool MessageCheck(Message message) - * { - * CHECKS(Message, message); - * CHECKU(Arena, message->arena); - * CHECKD(MessageClass, message->class); - * CHECKL(RingCheck(&message->queueRing)); - * CHECKL(MessageIsClocked(message) || (message->postedClock == 0)); - * return TRUE; - * } - * - * The parent/child distinction depends on the structure, but in the MPS - * the Arena has no parents, and has children which are Pools, which have - * children which are Segments, etc. - * - * The important thing is to have a partial order on types so that recursive - * checking will terminate. When CHECKLEVEL is set to DEEP, checking will - * recurse into check methods for children, but will only do a shallow - * signature check on parents, avoiding infinite regression. - */ - -#if defined(AVER_AND_CHECK_ALL) - -#define CHECK_BY_LEVEL(minimal, shallow, deep) \ - BEGIN \ - switch (CHECKLEVEL) { \ - case CheckLevelDEEP: deep; break; \ - case CheckLevelSHALLOW: shallow; break; \ - default: NOTREACHED; /* fall through */ \ - case CheckLevelMINIMAL: minimal; break; \ - } \ - END - -#define CHECKL(cond) \ - CHECK_BY_LEVEL(NOOP, \ - ASSERT(cond, #cond), \ - ASSERT(cond, #cond)) - -#define CHECKD(type, val) \ - CHECK_BY_LEVEL(NOOP, \ - CHECKS(type, val), \ - ASSERT_TYPECHECK(type, val)) - -#define CHECKD_NOSIG(type, val) \ - CHECK_BY_LEVEL(NOOP, \ - ASSERT_NULLCHECK(type, val), \ - ASSERT_TYPECHECK(type, val)) - -#define CHECKU(type, val) \ - CHECK_BY_LEVEL(NOOP, \ - CHECKS(type, val), \ - CHECKS(type, val)) - -#define CHECKU_NOSIG(type, val) \ - CHECK_BY_LEVEL(NOOP, \ - ASSERT_NULLCHECK(type, val), \ - ASSERT_NULLCHECK(type, val)) - -#else /* AVER_AND_CHECK_ALL, not */ - -/* TODO: This gives comparable performance to white-hot when compiling - using mps.c and -O2 (to get check methods inlined), but is it a bit - too minimal? How much do we rely on check methods? */ - -#define CHECKL(cond) DISCARD(cond) -#define CHECKD(type, val) DISCARD(TESTT(type, val)) -#define CHECKD_NOSIG(type, val) DISCARD((val) != NULL) -#define CHECKU(type, val) DISCARD(TESTT(type, val)) -#define CHECKU_NOSIG(type, val) DISCARD((val) != NULL) - -#endif /* AVER_AND_CHECK_ALL */ - - -/* COMPAT* -- type compatibility checking - * - * .check.macros: The COMPAT* macros use some C trickery to attempt to - * verify that certain types and fields are equivalent. They do not - * do a complete job. This trickery is justified by the security gained - * in knowing that matches the MPM. See also - * mail.richard.1996-08-07.09-49. [This paragraph is intended to - * satisfy rule.impl.trick.] - */ - -/* compile-time check */ -#define COMPATLVALUE(lv1, lv2) \ - ((void)sizeof((lv1) = (lv2)), (void)sizeof((lv2) = (lv1)), TRUE) - -/* aims to test whether t1 and t2 are assignment-compatible */ -#define COMPATTYPE(t1, t2) \ - (sizeof(t1) == sizeof(t2) && \ - COMPATLVALUE(*((t1 *)0), *((t2 *)0))) - -#define COMPATFIELDAPPROX(s1, f1, s2, f2) \ - (sizeof(((s1 *)0)->f1) == sizeof(((s2 *)0)->f2) && \ - offsetof(s1, f1) == offsetof(s2, f2)) - -#define COMPATFIELD(s1, f1, s2, f2) \ - (COMPATFIELDAPPROX(s1, f1, s2, f2) && \ - COMPATLVALUE(((s1 *)0)->f1, ((s2 *)0)->f2)) - - -#endif /* check_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/clock.h b/mps/code/clock.h deleted file mode 100644 index 881d74e2715..00000000000 --- a/mps/code/clock.h +++ /dev/null @@ -1,191 +0,0 @@ -/* clock.h -- Fast clocks and timers - * - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * $Id$ - */ - -#ifndef clock_h -#define clock_h - -#include -#include "mpmtypes.h" /* for Word */ - - -/* EVENT_CLOCK -- fast event timestamp clock - * - * On platforms that support it, we want to stamp events with a very cheap - * and fast high-resolution timer. - * - * TODO: This is a sufficiently complicated nest of ifdefs that it should - * be quarantined in its own header with KEEP OUT signs attached. - * RB 2012-09-11 - */ - -/* TODO: Clang supposedly provides a cross-platform builtin for a fast - timer, but it doesn't seem to be present on Mac OS X 10.8. We should - use it if it ever appears. - */ -#if defined(MPS_BUILD_LL) - -#if __has_builtin(__builtin_readcyclecounter) -#error "__builtin_readcyclecounter is available but not used" -#endif /* __has_builtin(__builtin_readcyclecounter) */ - -#endif - -/* Microsoft C provides an intrinsic for the Intel rdtsc instruction. - */ -#if (defined(MPS_ARCH_I3) || defined(MPS_ARCH_I6)) && defined(MPS_BUILD_MV) - -typedef unsigned __int64 EventClock; - -typedef union EventClockUnion { - struct { - unsigned low, high; - } half; - unsigned __int64 whole; -} EventClockUnion; - -#if _MSC_VER >= 1400 - -#pragma intrinsic(__rdtsc) - -#define EVENT_CLOCK(lvalue) \ - BEGIN \ - (lvalue) = __rdtsc(); \ - END - -#else /* _MSC_VER < 1400 */ - -/* This is mostly a patch for Open Dylan's bootstrap on Windows, which is - using Microsoft Visual Studio 6 because of support for CodeView debugging - information. */ - -#include /* KILL IT WITH FIRE! */ - -#define EVENT_CLOCK(lvalue) \ - BEGIN \ - LARGE_INTEGER _count; \ - QueryPerformanceCounter(&_count); \ - (lvalue) = _count.QuadPart; \ - END - -#endif /* _MSC_VER < 1400 */ - -#if defined(MPS_ARCH_I3) - -/* We can't use a shift to get the top half of the 64-bit event clock, - because that introduces a dependency on `__aullshr` in the C run-time. */ - -#define EVENT_CLOCK_PRINT(stream, clock) \ - fprintf(stream, "%08lX%08lX", \ - (*(EventClockUnion *)&(clock)).half.high, \ - (*(EventClockUnion *)&(clock)).half.low) - -#define EVENT_CLOCK_WRITE(stream, clock) \ - WriteF(stream, "$W$W", \ - (*(EventClockUnion *)&(clock)).half.high, \ - (*(EventClockUnion *)&(clock)).half.low, \ - NULL) - -#elif defined(MPS_ARCH_I6) - -#define EVENT_CLOCK_PRINT(stream, clock) \ - fprintf(stream, "%016lX", (clock)); - -#define EVENT_CLOCK_WRITE(stream, clock) \ - WriteF(stream, "$W", (WriteFW)(clock), NULL) - -#endif - -#endif /* Microsoft C on Intel */ - -/* If we have GCC or Clang, assemble the rdtsc instruction */ -#if !defined(EVENT_CLOCK) && \ - (defined(MPS_ARCH_I3) || defined(MPS_ARCH_I6)) && \ - (defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL)) - -/* Use __extension__ to enable use of a 64-bit type on 32-bit pedantic GCC */ -__extension__ typedef unsigned long long EventClock; - -#define EVENT_CLOCK(lvalue) \ - BEGIN \ - unsigned _l, _h; \ - __asm__ __volatile__("rdtsc" : "=a"(_l), "=d"(_h)); \ - (lvalue) = ((EventClock)_h << 32) | _l; \ - END - -/* The __extension__ keyword doesn't work on printf formats, so we - concatenate two 32-bit hex numbers to print the 64-bit value. */ -#define EVENT_CLOCK_PRINT(stream, clock) \ - fprintf(stream, "%08lX%08lX", \ - (unsigned long)((clock) >> 32), \ - (unsigned long)(clock)) - -#define EVENT_CLOCK_WRITE(stream, clock) \ - WriteF(stream, "$W$W", (WriteFW)((clock) >> 32), (WriteFW)clock, NULL) - -#endif /* Intel, GCC or Clang */ - -/* no fast clock, use plinth, probably from the C library */ -#ifndef EVENT_CLOCK - -typedef mps_clock_t EventClock; - -#define EVENT_CLOCK(lvalue) \ - BEGIN \ - (lvalue) = mps_clock(); \ - END - -#define EVENT_CLOCK_PRINT(stream, clock) \ - fprintf(stream, "%lu", (unsigned long)clock) - -#define EVENT_CLOCK_WRITE(stream, clock) \ - WriteF(stream, "$W", (WriteFW)clock, NULL) - -#endif - - -#endif /* clock_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/comm.gmk b/mps/code/comm.gmk deleted file mode 100644 index 2e16905eab7..00000000000 --- a/mps/code/comm.gmk +++ /dev/null @@ -1,561 +0,0 @@ -# comm.gmk: COMMON GNUMAKEFILE FRAGMENT -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. -# -# DESCRIPTION -# -# This makefile fragment is included in more specific makefiles for -# platforms which use GNU make. -# -# PARAMETERS -# -# Assumes the following variables and definitions: -# CFLAGSCOMPILER a list of flags for all compilations -# CFLAGSDEBUG a list of flags for compilations with maximum debug -# information, and any optimization possible -# CFLAGSOPT a list of flags for compilations with maximum -# optimization, and any debug info possible -# CC the command for the C compiler -# LINKFLAGS a list of flags passed to the linker -# ARFLAGSPFM platform-specific flags for ar -# RANLIB the command to index a library (default: none needed) -# gendep optionally defined to be a command sequence for -# generating the dependency file (.d) from a C file (.c); -# it is used in a rule of the form: -# $(PFM)/$(VARIETY)/%.d: %.c -# PFM platform code, e.g. "sus8gc" -# LIBS extra libraries to include in tests (usually "-lm") -# NOISY if defined and non-empty, causes commands to be emitted -# MPMPF platform-dependent C sources for the "mpm" part -# MPMS assembler sources for the "mpm" part (.s files) -# MPMPS pre-processor assembler sources for the "mpm" part (.S files) -# -# %%PART: When adding a new part, add a new parameter above for the -# files included in the part. -# -# EDITING -# -# To add new targets, varieties, and parts: -# Search for the string "%%TARGET", "%%VARIETY", or "%%PART" in this -# makefile and follow the instructions. If you're adding a part, you'll -# have to change the makefiles for all the platforms which use this -# makefile to define the source list for that part, and the GNUmakefile -# to include a recursive call to the name of that part. -# -# CHECK PARAMETERS -# -# GNU make doesn't really have an "error" directive, but these lines -# will cause it to exit with an error. -# [These only test to see whether the symbol is defined. We could be -# more thorough and test the syntax and content. -- richard 1995-09-07] - -ifndef CC -error "comm.gmk: CC not defined" -endif -ifndef CFLAGSCOMPILER -error "comm.gmk: CFLAGSCOMPILER not defined" -endif -ifndef CFLAGSDEBUG -error "comm.gmk: CFLAGSDEBUG not defined" -endif -ifndef CFLAGSOPT -error "comm.gmk: CFLAGSOPT not defined" -endif - -# -# %%PART: When adding a new part, add checks for the parameter with the -# sources for the new part. - -ifndef PFM -error "comm.gmk: PFM not defined" -endif -ifndef MPMPF -error "comm.gmk: MPMPF not defined" -endif - - -# DECLARATIONS - -ifdef NOISY -ECHO = : -else -.SILENT: -ECHO = echo -endif - -.PHONY: phony - - -# C FLAGS - -# These flags are included in all compilations. -# Avoid using PFMDEFS in platform makefiles, as they prevent the MPS being -# built with a simple command like "cc -c mps.c". -CFLAGSCOMMON = $(PFMDEFS) $(CFLAGSCOMPILER) - -# %%VARIETY: When adding a new variety, define a macro containing the set -# of flags for the new variety. - -# These flags are added to compilations for the indicated variety. -CFRASH = -DCONFIG_VAR_RASH -DNDEBUG $(CFLAGSOPT) -CFHOT = -DCONFIG_VAR_HOT -DNDEBUG $(CFLAGSOPT) -CFDIAG = -DCONFIG_VAR_DIAG -DNDEBUG $(CFLAGSOPT) -CFCOOL = -DCONFIG_VAR_COOL $(CFLAGSDEBUG) - -# Bind CFLAGS to the appropriate set of flags for the variety. -# %%VARIETY: When adding a new variety, add a test for the variety and set -# CFLAGS here. -ifeq ($(VARIETY),rash) -CFLAGS=$(CFLAGSCOMMON) $(CFRASH) -else -ifeq ($(VARIETY),hot) -CFLAGS=$(CFLAGSCOMMON) $(CFHOT) -else -ifeq ($(VARIETY),diag) -CFLAGS=$(CFLAGSCOMMON) $(CFDIAG) -else -ifeq ($(VARIETY),cool) -CFLAGS=$(CFLAGSCOMMON) $(CFCOOL) -else -endif -endif -endif -endif - - -ARFLAGS=rc$(ARFLAGSPFM) - - -# == Common definitions == -# %%PART: When adding a new part, add it here, unless it's platform-specific -# These values are defined here because they have no variation between -# platforms. - -AMC = poolamc.c -AMS = poolams.c poolamsi.c -AWL = poolawl.c -LO = poollo.c -SNC = poolsnc.c -POOLN = pooln.c -MVFF = poolmvff.c -TESTLIB = testlib.c -FMTDY = fmtdy.c fmtno.c -FMTDYTST = fmtdy.c fmtno.c fmtdytst.c -FMTHETST = fmthe.c fmtdy.c fmtno.c fmtdytst.c -PLINTH = mpsliban.c mpsioan.c -EVENTPROC = eventcnv.c eventpro.c table.c -MPMCOMMON = mpsi.c mpm.c arenavm.c arenacl.c arena.c global.c locus.c \ - tract.c walk.c reserv.c protocol.c pool.c poolabs.c \ - trace.c traceanc.c root.c seg.c format.c buffer.c ref.c \ - bt.c ring.c shield.c ld.c event.c sac.c message.c \ - poolmrg.c poolmfs.c poolmv.c dbgpool.c dbgpooli.c \ - boot.c meter.c splay.c cbs.c diag.c \ - ss.c table.c -MPM = $(MPMCOMMON) $(MPMPF) - - -# These map the source file lists onto object files and dependency files -# in the platform/variety directory. -# -# %%PART: When adding a new part, add a new macro which expands to the files -# included in the part. - -ifdef VARIETY -MPMOBJ = $(MPM:%.c=$(PFM)/$(VARIETY)/%.o) \ - $(MPMS:%.s=$(PFM)/$(VARIETY)/%.o) -MPMDEP = $(MPM:%.c=$(PFM)/$(VARIETY)/%.d) -AMCOBJ = $(AMC:%.c=$(PFM)/$(VARIETY)/%.o) -AMCDEP = $(AMC:%.c=$(PFM)/$(VARIETY)/%.d) -AMSOBJ = $(AMS:%.c=$(PFM)/$(VARIETY)/%.o) -AMSDEP = $(AMS:%.c=$(PFM)/$(VARIETY)/%.d) -AWLOBJ = $(AWL:%.c=$(PFM)/$(VARIETY)/%.o) -AWLDEP = $(AWL:%.c=$(PFM)/$(VARIETY)/%.d) -LOOBJ = $(LO:%.c=$(PFM)/$(VARIETY)/%.o) -LODEP = $(LO:%.c=$(PFM)/$(VARIETY)/%.d) -SNCOBJ = $(SNC:%.c=$(PFM)/$(VARIETY)/%.o) -SNCDEP = $(SNC:%.c=$(PFM)/$(VARIETY)/%.d) -POOLNOBJ = $(POOLN:%.c=$(PFM)/$(VARIETY)/%.o) -POOLNDEP = $(POOLN:%.c=$(PFM)/$(VARIETY)/%.d) -MVFFOBJ = $(MVFF:%.c=$(PFM)/$(VARIETY)/%.o) -MVFFDEP = $(MVFF:%.c=$(PFM)/$(VARIETY)/%.d) - -TESTLIBOBJ = $(TESTLIB:%.c=$(PFM)/$(VARIETY)/%.o) -TESTLIBDEP = $(TESTLIB:%.c=$(PFM)/$(VARIETY)/%.d) -FMTDYOBJ = $(FMTDY:%.c=$(PFM)/$(VARIETY)/%.o) -FMTDYDEP = $(FMTDY:%.c=$(PFM)/$(VARIETY)/%.d) -FMTDYTSTOBJ = $(FMTDYTST:%.c=$(PFM)/$(VARIETY)/%.o) -FMTHETSTOBJ = $(FMTHETST:%.c=$(PFM)/$(VARIETY)/%.o) -FMTHETSTDEP = $(FMTHETST:%.c=$(PFM)/$(VARIETY)/%.d) -PLINTHOBJ = $(PLINTH:%.c=$(PFM)/$(VARIETY)/%.o) -PLINTHDEP = $(PLINTH:%.c=$(PFM)/$(VARIETY)/%.d) -EVENTPROCOBJ = $(EVENTPROC:%.c=$(PFM)/$(VARIETY)/%.o) -EVENTPROCDEP = $(EVENTPROC:%.c=$(PFM)/$(VARIETY)/%.d) -endif - - -# == Pseudo-targets == - -# %%TARGET: When adding a new target, add it to the all dependencies - -all: mpmss sacss amcss amcsshe amsss amssshe segsmss awlut awluthe \ - mpsicv lockcov poolncv locv qs apss \ - finalcv finaltest arenacv bttest teletest \ - abqtest cbstest btcv mv2test messtest steptest \ - walkt0 zcoll zmess \ - eventcnv \ - mps.a mpsplan.a - - -# Runs the automatic tests that are built with CONFIG_PROD_MPS. -# These tests are run overnight (see design.buildsys.overnight). -# bttest & teletest cannot be run unattended -# mv2test cannot be run because MV2 is broken -# %%TARGET: When adding a new target, if target is suitable for the -# overnight tests, then add it here. -testrun: mpmss apss sacss amcss amcsshe amsss amssshe segsmss awlut awluthe \ - mpsicv lockcov poolncv locv qs finalcv finaltest arenacv \ - abqtest cbstest btcv messtest steptest walkt0 - $(^:%=date && $(PFM)/$(VARIETY)/% &&) true - -# These convenience targets allow one to type "make foo" to build target -# foo in selected varieties (or none, for the latter rule). -# -# %%TARGET: When adding a new target, add a pseudo-target for it here. - -mpmss sacss amcss amcssth amcsshe amsss amssshe segsmss awlut awlutth \ - awluthe mpsicv lockcov poolncv locv qs apss \ - finalcv finaltest arenacv bttest teletest \ - expt825 \ - abqtest cbstest btcv mv2test \ - messtest steptest \ - walkt0 \ - exposet0 \ - zcoll zmess \ - eventcnv replay replaysw \ - mps.a mpsplan.a: phony -ifdef VARIETY - $(MAKE) -f $(PFM).gmk TARGET=$@ variety -else - $(MAKE) -f $(PFM).gmk TARGET=$@ target -endif - - -# "clean" removes the directory containing the build results for the -# platform. - -clean: phony - $(ECHO) "$(PFM): $@" - rm -rf "$(PFM)" - -# "target" builds some varieties of the target named in the TARGET macro. -# %%VARIETY: When adding a new target, optionally add a recursive make call -# for the new variety, if it should be built by default. It probably -# shouldn't without a product design decision and an update of the readme -# and build manual! - -ifdef TARGET -ifndef VARIETY -target: phony - $(MAKE) -f $(PFM).gmk VARIETY=hot variety - $(MAKE) -f $(PFM).gmk VARIETY=cool variety -endif -endif - - -# "variety" builds the target named in the TARGET macro using the -# variety named in the VARIETY macro. - -ifdef VARIETY -ifdef TARGET -variety: $(PFM)/$(VARIETY)/$(TARGET) -endif -endif - - -# THE MPS LIBRARY -# -# The MPS library is built in two ways: -# -# 1. In the usual way, from a pile of object files compiled from their -# corresponding sources. -# -# 2. From mps.c, which effectively concatenates all the sources, allowing -# important global optimisation and inlining to occur. -# -# We mostly use the method (2), because it is fast to compile and execute. -# But we use method (1) for some varieties to ensure correctness of -# code (linkage errors are masked by (2)) and to maintain a correct list -# of source files in case method (1) won't work on some future constrained -# platform. -# -# %%VARIETY: When adding a new variety, add a rule for how to build the -# MPS library for the variety. - -$(PFM)/rash/mps.a: $(PFM)/rash/mps.o -$(PFM)/hot/mps.a: $(PFM)/hot/mps.o - -$(PFM)/diag/mps.a: \ - $(MPMOBJ) $(AMCOBJ) $(AMSOBJ) $(AWLOBJ) $(LOOBJ) $(SNCOBJ) \ - $(MVFFOBJ) $(PLINTHOBJ) $(POOLNOBJ) -$(PFM)/cool/mps.a: \ - $(MPMOBJ) $(AMCOBJ) $(AMSOBJ) $(AWLOBJ) $(LOOBJ) $(SNCOBJ) \ - $(MVFFOBJ) $(PLINTHOBJ) $(POOLNOBJ) - - -# OTHER GENUINE TARGETS -# -# Each line defines an executable or library target to be built and the -# object files it is built from. These lines add dependencies to the -# generic rules below, and should not include commands to execute. -# -# %%TARGET: When adding a new target, add the dependencies for the new target -# here. - -ifdef VARIETY - -$(PFM)/$(VARIETY)/finalcv: $(PFM)/$(VARIETY)/finalcv.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/finaltest: $(PFM)/$(VARIETY)/finaltest.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/expt825: $(PFM)/$(VARIETY)/expt825.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/locv: $(PFM)/$(VARIETY)/locv.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/mpmss: $(PFM)/$(VARIETY)/mpmss.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/apss: $(PFM)/$(VARIETY)/apss.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/sacss: $(PFM)/$(VARIETY)/sacss.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/bttest: $(PFM)/$(VARIETY)/bttest.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/teletest: $(PFM)/$(VARIETY)/teletest.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/lockcov: $(PFM)/$(VARIETY)/lockcov.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/mpsicv: $(PFM)/$(VARIETY)/mpsicv.o \ - $(FMTDYTSTOBJ) $(FMTHETSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/amcss: $(PFM)/$(VARIETY)/amcss.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/amcssth: $(PFM)/$(VARIETY)/amcssth.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/amcsshe: $(PFM)/$(VARIETY)/amcsshe.o \ - $(FMTHETSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/amsss: $(PFM)/$(VARIETY)/amsss.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/amssshe: $(PFM)/$(VARIETY)/amssshe.o \ - $(FMTHETSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/segsmss: $(PFM)/$(VARIETY)/segsmss.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/awlut: $(PFM)/$(VARIETY)/awlut.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/awluthe: $(PFM)/$(VARIETY)/awluthe.o \ - $(FMTHETSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/awlutth: $(PFM)/$(VARIETY)/awlutth.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/poolncv: $(PFM)/$(VARIETY)/poolncv.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/qs: $(PFM)/$(VARIETY)/qs.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/arenacv: $(PFM)/$(VARIETY)/arenacv.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/abqtest: $(PFM)/$(VARIETY)/abqtest.o \ - $(PFM)/$(VARIETY)/abq.o $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/cbstest: $(PFM)/$(VARIETY)/cbstest.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/btcv: $(PFM)/$(VARIETY)/btcv.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/mv2test: $(PFM)/$(VARIETY)/mv2test.o \ - $(PFM)/$(VARIETY)/poolmv2.o $(PFM)/$(VARIETY)/abq.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/messtest: $(PFM)/$(VARIETY)/messtest.o \ - $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/steptest: $(PFM)/$(VARIETY)/steptest.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/walkt0: $(PFM)/$(VARIETY)/walkt0.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/exposet0: $(PFM)/$(VARIETY)/exposet0.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/zcoll: $(PFM)/$(VARIETY)/zcoll.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/zmess: $(PFM)/$(VARIETY)/zmess.o \ - $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/eventcnv: $(PFM)/$(VARIETY)/eventcnv.o \ - $(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/replay: $(PFM)/$(VARIETY)/replay.o \ - $(PFM)/$(VARIETY)/eventrep.o \ - $(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/table.o \ - $(PFM)/$(VARIETY)/mps.a - -$(PFM)/$(VARIETY)/mpsplan.a: $(PLINTHOBJ) - -endif - - -# GENERIC RULES -# -# These generate build output in the / directory. - -# Object files - -define run-cc -$(ECHO) "$(PFM): $@" -mkdir -p $(PFM) -mkdir -p $(PFM)/$(VARIETY) -$(CC) $(CFLAGS) -c -o $@ $< -endef - -# .rule.c-to-o: -$(PFM)/$(VARIETY)/%.o: %.c - $(run-cc) - -$(PFM)/$(VARIETY)/%.o: %.s - $(run-cc) - -$(PFM)/$(VARIETY)/%.o: %.S - $(run-cc) - -# Dependencies -# -# These are included into _this_ makefile (see below). GNU make does the -# right thing as long as it knows how to make the dependency files before -# including them. - -ifdef gendep - -$(PFM)/$(VARIETY)/%.d: %.c - $(ECHO) "$(PFM): $@" - mkdir -p $(PFM) - mkdir -p $(PFM)/$(VARIETY) - $(gendep) - -ifdef VARIETY -ifdef TARGET - -# %%VARIETY: When adding a new variety, add the dependencies files for it -# here. -ifeq ($(VARIETY),rash) -include $(PFM)/$(VARIETY)/mps.d -else -ifeq ($(VARIETY),hot) -include $(PFM)/$(VARIETY)/mps.d -else -# %%PART: When adding a new part, add the dependency file macro for the new -# part here. -include $(MPMDEP) $(AMSDEP) $(AMCDEP) $(LODEP) \ - $(AWLDEP) $(POOLNDEP) $(TESTLIBDEP) $(FMTDYDEP) $(FMTHETSTDEP) \ - $(PLINTHDEP) $(EVENTPROCDEP) -endif -endif - -endif -endif - -endif - -# Library - -ifndef RANLIB -RANLIB = : -endif - -$(PFM)/$(VARIETY)/%.a: - $(ECHO) "$(PFM): $@" - rm -f $@ - $(CC) $(CFLAGS) -c -o $(PFM)/$(VARIETY)/version.o version.c - $(AR) $(ARFLAGS) $@ $^ $(PFM)/$(VARIETY)/version.o - $(RANLIB) $@ - -# Executable - -$(PFM)/$(VARIETY)/%: - $(ECHO) "$(PFM): $@" - $(CC) $(CFLAGS) $(LINKFLAGS) -o $@ $^ $(LIBS) - - -# Special targets for development - -# Currently FreeBSD 7 GCC 4.2.1 is the best platform we have for warning -# us about strict aliasing rule violations caused by type puns. This -# target reveals them, and produces an assembler output file that can be -# examined to see if they're actually dangerous. RB 2012-09-07 - -find-puns: phony - { echo '#include "mps.c"'; echo '#include "fmtdy.c"'; } | \ - gcc -S -fverbose-asm -ansi -pedantic -Wall -Wstrict-aliasing=2 -O3 -x c -o pun.s - - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/commpost.nmk b/mps/code/commpost.nmk deleted file mode 100644 index 15b77940b29..00000000000 --- a/mps/code/commpost.nmk +++ /dev/null @@ -1,334 +0,0 @@ -# commpost.nmk: SECOND COMMON FRAGMENT FOR PLATFORMS USING MV AND NMAKE -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. -# -# DESCRIPTION -# -# Second common makefile fragment for w3*mv.nmk. See commpre.nmk - - -# PSEUDO-TARGETS - -# "all" builds all the varieties of all targets -# %%TARGET: When adding a new target, add it to the all dependencies. - -all: mpmss.exe amcss.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awluthe.exe\ - mpsicv.exe lockutw3.exe lockcov.exe poolncv.exe locv.exe qs.exe apss.exe \ - sacss.exe finalcv.exe finaltest.exe \ - arenacv.exe bttest.exe teletest.exe \ - abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \ - locbwcss.exe locusss.exe zcoll.exe zmess.exe \ - eventcnv.exe \ - mps.lib - - -# Convenience targets - -# %%TARGET: When adding a new target, add a pseudo-target for it here, -# first rule for variety-dependent targets, and second for -# variety-independent ones. - -mpmss.exe amcss.exe amcsshe.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awluthe.exe dwstress.exe \ - mpsicv.exe lockutw3.exe lockcov.exe poolncv.exe locv.exe qs.exe apss.exe \ - sacss.exe finalcv.exe finaltest.exe \ - arenacv.exe bttest.exe teletest.exe \ - expt825.exe \ - abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \ - walkt0.exe locbwcss.exe locusss.exe \ - exposet0.exe zcoll.exe zmess.exe \ - replay.exe replaysw.exe eventcnv.exe \ - mps.lib: -!IFDEF VARIETY - $(MAKE) /nologo /f $(PFM).nmk TARGET=$@ variety -!ELSE - $(MAKE) /nologo /f $(PFM).nmk TARGET=$@ target -!ENDIF - -# "clean" removes the directory containing the build results. -# Depends on there being no file called "clean". - -clean: - $(ECHO) $(PFM): $@ - -echo y | rmdir/s $(PFM) - -# target target -# %%VARIETY: When adding a new variety, optionally, add a recursive make -# call for the new variety, if it should be built by default. It probably -# shouldn't without a product design decision and an update of the readme -# and build manual! -# Depends on there being no file called "target". - -!IFDEF TARGET -!IFNDEF VARIETY -target: - $(MAKE) /nologo /f $(PFM).nmk VARIETY=hot variety - $(MAKE) /nologo /f $(PFM).nmk VARIETY=cool variety -!ENDIF -!ENDIF - -# variety -# Depends on there being no file called "variety". - -!IFDEF VARIETY -!IFDEF TARGET -variety: $(PFM)\$(VARIETY)\$(TARGET) -!ENDIF -!ENDIF - -mpsicv.cov: - $(MAKE) /nologo /f $(PFM).nmk TARGET=$@ VARIETY=cv variety - - -# THE MPS LIBRARY -# -# The MPS library is built in two ways: -# -# 1. In the usual way, from a pile of object files compiled from their -# corresponding sources. -# -# 2. From mps.c, which effectively concatenates all the sources, allowing -# important global optimisation and inlining to occur. -# -# We mostly use the method (2), because it is fast to compile and execute. -# But we use method (1) for some varieties to ensure correctness of -# code (linkage errors are masked by (2)) and to maintain a correct list -# of source files in case method (1) won't work on some future constrained -# platform. -# -# %%VARIETY: When adding a new variety, add a rule for how to build the -# MPS library for the variety - -$(PFM)\rash\mps.lib: $(PFM)\rash\mps.obj - $(ECHO) $@ - $(LIBMAN) $(LIBFLAGS) /OUT:$@ $** - -$(PFM)\hot\mps.lib: $(PFM)\hot\mps.obj - $(ECHO) $@ - $(LIBMAN) $(LIBFLAGS) /OUT:$@ $** - -$(PFM)\cool\mps.lib: \ - $(MPMOBJ) $(AMCOBJ) $(AMSOBJ) $(AWLOBJ) $(LOOBJ) $(SNCOBJ) \ - $(MVFFOBJ) $(PLINTHOBJ) $(POOLNOBJ) - $(ECHO) $@ - cl /c $(CFLAGS) /Fd$(PFM)\$(VARIETY)\ /Fo$(PFM)\$(VARIETY)\version.o version.c - $(LIBMAN) $(LIBFLAGS) /OUT:$@ $** $(PFM)\$(VARIETY)\version.o - -$(PFM)\di\mps.lib: \ - $(MPMOBJ) $(AMCOBJ) $(AMSOBJ) $(AWLOBJ) $(LOOBJ) $(SNCOBJ) \ - $(MVFFOBJ) $(PLINTHOBJ) $(POOLNOBJ) - $(ECHO) $@ - cl /c $(CFLAGS) /Fd$(PFM)\$(VARIETY)\ /Fo$(PFM)\$(VARIETY)\version.o version.c - $(LIBMAN) $(LIBFLAGS) /OUT:$@ $** $(PFM)\$(VARIETY)\version.o - - -# OTHER GENUINE TARGETS -# -# Each line defines an executable or library target to be built and the object -# files it is build from. For an executable these lines add dependencies to -# the generic rules below, and should not include commands to execute. -# For a library this is not possible and the target should include commands -# to build it. -# %%TARGET: When adding a new target, add your new target here - -!IFDEF VARIETY - -$(PFM)\$(VARIETY)\finalcv.exe: $(PFM)\$(VARIETY)\finalcv.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\finaltest.exe: $(PFM)\$(VARIETY)\finaltest.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\expt825.exe: $(PFM)\$(VARIETY)\expt825.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\locv.exe: $(PFM)\$(VARIETY)\locv.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\mpmss.exe: $(PFM)\$(VARIETY)\mpmss.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\apss.exe: $(PFM)\$(VARIETY)\apss.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\sacss.exe: $(PFM)\$(VARIETY)\sacss.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\bttest.exe: $(PFM)\$(VARIETY)\bttest.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\teletest.exe: $(PFM)\$(VARIETY)\teletest.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\lockcov.exe: $(PFM)\$(VARIETY)\lockcov.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\lockutw3.exe: $(PFM)\$(VARIETY)\lockutw3.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\mpsicv.exe: $(PFM)\$(VARIETY)\mpsicv.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\amcss.exe: $(PFM)\$(VARIETY)\amcss.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\amcsshe.exe: $(PFM)\$(VARIETY)\amcsshe.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\amsss.exe: $(PFM)\$(VARIETY)\amsss.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\amssshe.exe: $(PFM)\$(VARIETY)\amssshe.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\segsmss.exe: $(PFM)\$(VARIETY)\segsmss.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\locbwcss.exe: $(PFM)\$(VARIETY)\locbwcss.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\locusss.exe: $(PFM)\$(VARIETY)\locusss.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\dwstress.exe: $(PFM)\$(VARIETY)\dwstress.obj \ - $(DWOBJ) $(PFM)\$(VARIETY)\mps.lib - -$(PFM)\$(VARIETY)\awlut.exe: $(PFM)\$(VARIETY)\awlut.obj \ - $(FMTTESTOBJ) \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\awluthe.exe: $(PFM)\$(VARIETY)\awluthe.obj \ - $(FMTTESTOBJ) \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\poolncv.exe: $(PFM)\$(VARIETY)\poolncv.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\qs.exe: $(PFM)\$(VARIETY)\qs.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\arenacv.exe: $(PFM)\$(VARIETY)\arenacv.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\abqtest.exe: $(PFM)\$(VARIETY)\abqtest.obj \ - $(PFM)\$(VARIETY)\abq.obj $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\cbstest.exe: $(PFM)\$(VARIETY)\cbstest.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\btcv.exe: $(PFM)\$(VARIETY)\btcv.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\mv2test.exe: $(PFM)\$(VARIETY)\mv2test.obj \ - $(PFM)\$(VARIETY)\poolmv2.obj $(PFM)\$(VARIETY)\abq.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\zcoll.exe: $(PFM)\$(VARIETY)\zcoll.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) \ - $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\zmess.exe: $(PFM)\$(VARIETY)\zmess.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) \ - $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\eventcnv.exe: $(PFM)\$(VARIETY)\eventcnv.obj \ - $(PFM)\$(VARIETY)\eventpro.obj $(PFM)\$(VARIETY)\mps.lib - -$(PFM)\$(VARIETY)\replay.exe: $(PFM)\$(VARIETY)\replay.obj \ - $(PFM)\$(VARIETY)\eventrep.obj \ - $(PFM)\$(VARIETY)\eventpro.obj $(PFM)\$(VARIETY)\table.obj \ - $(PFM)\$(VARIETY)\mps.lib - -# Have to rename the object file, because the names must match, or -# the template rule for .exe.obj won't be used. -$(PFM)\$(VARIETY)\replaysw.obj: $(PFM)\$(VARIETY)\replay.obj - $(ECHO) $@ - copy $** $@ >nul: - -$(PFM)\$(VARIETY)\messtest.exe: $(PFM)\$(VARIETY)\messtest.obj \ - $(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\steptest.exe: $(PFM)\$(VARIETY)\steptest.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\walkt0.exe: $(PFM)\$(VARIETY)\walkt0.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -$(PFM)\$(VARIETY)\exposet0.exe: $(PFM)\$(VARIETY)\exposet0.obj \ - $(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ) - -!ENDIF - - -# GENERIC RULES - -# Object files - -{}.c{$(PFM)\$(VARIETY)}.obj: - $(ECHO) $@ - @if not exist $(PFM) mkdir $(PFM) - @if not exist $(PFM)\$(VARIETY) mkdir $(PFM)\$(VARIETY) - cl /c $(CFLAGS) /Fd$(PFM)\$(VARIETY)\ /Fo$@ $< - -{}.asm{$(PFM)\$(VARIETY)}.obj: - $(ECHO) $@ - @if not exist $(PFM) mkdir $(PFM) - @if not exist $(PFM)\$(VARIETY) mkdir $(PFM)\$(VARIETY) - $(MASM) /nologo /c /Fo$@ $< - -# Coverage files -#{$(PFM)\$(VARIETY)}.exe{$(PFM)\$(VARIETY)}.cov: -# $(ECHO) $@ -# cd $(PFM)\$(VARIETY) -# prep /nologo /lv $( $(@F) - - -# Executables - -{$(PFM)\$(VARIETY)}.obj{$(PFM)\$(VARIETY)}.exe: - $(ECHO) $@ - $(LINKER) $(LINKFLAGS) /PDB:$*.pdb /OUT:$@ $(**) - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/commpre.nmk b/mps/code/commpre.nmk deleted file mode 100644 index 0afcab6fe96..00000000000 --- a/mps/code/commpre.nmk +++ /dev/null @@ -1,203 +0,0 @@ -# commpre.nmk: FIRST COMMON FRAGMENT FOR PLATFORMS USING MV AND NMAKE -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. -# -# DESCRIPTION -# -# .description: This makefile fragment is included in more specific -# makefiles for platforms which use the "mv" builder. This is -# the first of two common makefile fragements (the other is commpost.nmk). -# Alas, due to shortcomings in nmake, it is not possible to use only one -# common fragment. -# -# %%PART: When adding a new part, add a new parameter for the files included -# in the part -# Parameters: -# PFM platform code, e.g. "nti3mv" -# PFMDEFS /D options to define platforms preprocessor symbols -# to the compiler. Eg "/DOS_NT /DARCH_386 /DBUILD_MVC" -# MPM list of sources which make up the "mpm" part for this -# platform. Each source is stripped of its .c extension -# and surrounded in angle brackets (<>) -# PLINTH as above for the "plinth" part -# AMC as above for the "amc" part -# AMS as above for the "ams" part -# LO as above for the "lo" part -# MRG as above for the "mrg" part -# TESTLIB as above for the "testlib" part -# NOISY if defined, causes command to be emitted -# -# -# EDITING -# -# To add new targets. varieties, and parts: -# Search for the string "%%TARGET", "%%VARIETY", or "%%PART" in this makefile -# and follow the instructions. If you're adding a part, you'll have to change -# the makefile for all the platforms which use this makefile to define the -# source list for that part. -# - -# CHECK PARAMETERS -# -# -# %%PART: When adding a new part, add checks for the parameter with the -# sources for the new part. - -!IFNDEF PFM -!ERROR commpre.nmk: PFM not defined -!ENDIF -!IFNDEF PFMDEFS -!ERROR commpre.nmk: PFMDEFS not defined -!ENDIF -!IFNDEF MPM -!ERROR commpre.nmk: MPM not defined -!ENDIF -!IFNDEF PLINTH -!ERROR commpre.nmk: PLINTH not defined -!ENDIF -!IFNDEF LO -!ERROR commpre.nmk: LO not defined -!ENDIF -!IFNDEF AMC -!ERROR commpre.nmk: AMC not defined -!ENDIF -!IFNDEF AMS -!ERROR commpre.nmk: AMS not defined -!ENDIF -!IFNDEF TESTLIB -!ERROR commpre.nmk: TESTLIB not defined -!ENDIF - - -# DECLARATIONS - - -!IFDEF NOISY -ECHO = rem -!ELSE -.SILENT: -ECHO = echo -!ENDIF - - -# C FLAGS - -# /MD means compile for multi-threaded environment with separate C library DLL. -# /MT means compile for multi-threaded environment. -# /ML means compile for single-threaded environment. -# A 'd' at the end means compile for debugging. - -CFLAGSTARGETPRE = -CFLAGSTARGETPOST = -CRTFLAGSHOT = /MT -CRTFLAGSCOOL = /MTd -LINKFLAGSHOT = libcmt.lib -LINKFLAGSCOOL = libcmtd.lib - -CFLAGSCOMMONPRE = /nologo /W4 /WX $(PFMDEFS) $(CFLAGSTARGETPRE) -CFLAGSCOMMONPOST = $(CFLAGSTARGETPOST) - -# Flags for use in the variety combinations -CFLAGSHOT = /O2 /DNDEBUG -# (above /O2 (maximise speed) used to be set to /Ox -# (maximise optimisations) in for tool versions before VS 9) -# We used to have /GZ here (stack probe). -# Note that GZ is specific to version 12 of the cl tool. drj 2003-11-04 -# It is ignored on earlier versions of the cl tool. -# /GZ here generates a dependency on the C library and when we are -# building a DLL, mpsdy.dll, the linker step will fail (error LNK2001: -# unresolved external symbol __chkesp). See -# http://support.microsoft.com/kb/q191669/ -CFLAGSCOOL = /Od -CFLAGSINTERNAL = /Zi -CFLAGSEXTERNAL = - -# The combinations of variety -# %%VARIETY: When adding a new variety, define a macro containing the set -# of flags for the new variety. -CFRASH = /DCONFIG_VAR_RASH $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSEXTERNAL) -CFHOT = /DCONFIG_VAR_HOT $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSINTERNAL) -CFDIAG = /DCONFIG_VAR_DIAG $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSINTERNAL) -CFCOOL = /DCONFIG_VAR_COOL $(CRTFLAGSCOOL) $(CFLAGSCOOL) $(CFLAGSINTERNAL) - -# Microsoft documentation is not very clear on the point of using both -# optimization and debug information - -# LINKER FLAGS -# %%VARIETY: When adding a new variety, define a macro containing the flags -# for the new variety -LINKER = link -LINKFLAGSCOMMON = /nologo -LINKFLAGSINTERNAL = /DEBUG -# ( Internal flags used to be set to /DEBUG:full ) -LINKFLAGSEXTERNAL = /RELEASE - -LFRASH = $(LINKFLAGSHOT) $(LINKFLAGSEXTERNAL) -LFHOT = $(LINKFLAGSHOT) $(LINKFLAGSINTERNAL) -LFDIAG = $(LINKFLAGSHOT) $(LINKFLAGSINTERNAL) -LFCOOL = $(LINKFLAGSCOOL) $(LINKFLAGSINTERNAL) - -#LFCV = /PROFILE /DEBUG:full /DEBUGTYPE:cv - -# Library manager -# %%VARIETY: When adding a new variety, define a macro containing the flags -# for the new variety -LIBMAN = lib # can't call this LIB - it screws the environment -LIBFLAGSCOMMON = /nologo - -LIBFLAGSRASH = -LIBFLAGSHOT = -LIBFLAGSDIAG = -LIBFLAGSCOOL = - -# Browser database manager [not used at present] -#BSC = bscmake -#BSCFLAGS = /nologo /n - - -# == Common definitions == -# %%PART: When adding a new part, add it here, unless it's platform-specific -# [It is not possible use a macro, like $(PFM), in a substitution, -# hence all parts end up being platform-specific.] - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/config.h b/mps/code/config.h deleted file mode 100644 index 5eb8ee50e13..00000000000 --- a/mps/code/config.h +++ /dev/null @@ -1,446 +0,0 @@ -/* config.h: MPS CONFIGURATION - * - * $Id$ - * Copyright (c) 2001-2003, 2006 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * PURPOSE - * - * This module translates from high-level symbols defined by the - * external build system (gnumake, nmake, etc.) into specific sets - * of features used by MPS modules. - * - * DESIGN - * - * See . - */ - -#ifndef config_h -#define config_h - - -/* CONFIG_VAR_* -- variety Configuration - * - * These are translated into the directives CONFIG_ASSERT, CONFIG_STATS, - * CONFIG_LOG, etc. which control actual compilation features. - */ - -/* CONFIG_VAR_RASH -- the rash and reckless variety - * - * This variety switches off as many features as possible for maximum - * performance, but is therefore unsafe and undebuggable. It is not intended - * for use, but for comparison with the hot variety, to check that assertion, - * logging, etc. have negligible overhead. - */ - -#if defined(CONFIG_VAR_RASH) -/* no asserts */ -/* no statistic meters */ -/* no telemetry log events */ - - -/* CONFIG_VAR_DIAG -- diagnostic variety - * - * Deprecated. The diagnostic variety prints messages about the internals - * of the MPS to an output stream. This is being replaced by an extended - * telemetry system. RB 2012-08-31 - */ - -#elif defined(CONFIG_VAR_DIAG) /* Diagnostic variety */ -#define CONFIG_ASSERT -#ifndef CHECKLEVEL -#define CHECKLEVEL CheckLevelMINIMAL -#endif -#define CONFIG_STATS -/* For diagnostics, choose a DIAG_WITH_... output method. - * (We need to choose because the DIAG output system is under - * development. RHSK 2007-05-21). - */ -#define DIAG_WITH_STREAM_AND_WRITEF -/* #define DIAG_WITH_PRINTF */ -#define CONFIG_LOG - - -/* CONFIG_VAR_COOL -- cool variety - * - * The cool variety is intended for use when developing an integration with - * the MPS or debugging memory problems or collecting detailed telemetry - * data for performance analysis. It has more thorough consistency checking - * and data collection and output, and full debugging information. - */ - -#elif defined(CONFIG_VAR_COOL) -#define CONFIG_ASSERT -#define CONFIG_ASSERT_ALL -#define CONFIG_STATS -#ifndef CHECKLEVEL -#define CHECKLEVEL CheckLevelSHALLOW -#endif -#define CONFIG_LOG -#define CONFIG_LOG_ALL - - -#else /* CONFIG_VAR_* */ - -/* CONFIG_VAR_HOT -- the hot variety - * - * This variety is the default variety for distribution in products that use - * the MPS. It has maximum performance while retaining a good level of - * consistency checking and allowing some debugging and telemetry features. - */ - -/* #elif defined(CONFIG_VAR_HOT) */ -#define CONFIG_ASSERT -#ifndef CHECKLEVEL -#define CHECKLEVEL CheckLevelMINIMAL -#endif -/* no statistic meters */ -#define CONFIG_LOG - -#endif /* CONFIG_VAR_* */ - - -/* Build Features */ - - -#if defined(CONFIG_ASSERT) -/* asserts: AVER, AVERT, NOTREACHED, CHECKx */ -/* note: a direct call to ASSERT() will *still* fire */ -#define AVER_AND_CHECK -#if defined(CONFIG_ASSERT_ALL) -#define AVER_AND_CHECK_ALL -#define MPS_ASSERT_STRING "assertastic" -#else /* CONFIG_ASSERT_ALL, not */ -#define MPS_ASSERT_STRING "asserted" -#endif /* CONFIG_ASSERT_ALL */ -#else /* CONFIG_ASSERT, not */ -#define AVER_AND_CHECK_NONE -#define MPS_ASSERT_STRING "nonasserted" -#endif - - -#if defined(CONFIG_STATS) -/* CONFIG_STATS = STATISTICS = METERs */ -/* Note: the STATISTICS define used to be called "DIAGNOSTICS" (even */ -/* though it controls the STATISTIC system), but the term */ -/* "diagnostic" means something else now: see design/diag/. */ -/* RHSK 2007-06-28 */ -/* WARNING: this may change the size and fields of MPS structs */ -/* (...but see STATISTIC_DECL, which is invariant) */ -#define STATISTICS -#define MPS_STATS_STRING "stats" -#else -#define STATISTICS_NONE -#define MPS_STATS_STRING "nonstats" -#endif - - -#if defined(CONFIG_LOG) -/* TELEMETRY = LOG = EVENTs */ -#define EVENT -#if defined(CONFIG_LOG_ALL) -#define EVENT_ALL 1 /* log events on critical path */ -#define MPS_LOG_STRING "logtastic" -#else /* CONFIG_LOG_ALL, not */ -#define EVENT_ALL 0 /* don't log events on critical path */ -#define MPS_LOG_STRING "logging" -#endif /* CONFIG_LOG_ALL */ -#else /* CONFIG_LOG, not */ -#define EVENT_NONE -#define MPS_LOG_STRING "nonlogging" -#endif /* CONFIG_LOG */ - - -/* CONFIG_PLINTH_NONE -- exclude the ANSI plinth - * - * Some MPS deployment environments want to avoid dependencies on the - * standard C library. In this case, the plinth, defined in mpslib.h must - * be supplied when linking. - * - * For example, Open Dylan on Windows does not link the C library, but - * supplies its own plinth directly using Windows and Dylan interfaces. - * - * CONFIG_PLINTH_NONE tells mps.c to exclude the ANSI plinth and removes - * all standard C library dependencies. e.g. - * - * cc -O2 -c -DCONFIG_PLINTH_NONE mps.c - */ - -#if defined(CONFIG_PLINTH_NONE) -#define PLINTH_NONE -#endif - - -#define MPS_VARIETY_STRING \ - MPS_ASSERT_STRING "." MPS_LOG_STRING "." MPS_STATS_STRING - - -/* Platform Configuration */ - -#include "mpstd.h" - -/* Suppress Visual C warnings at warning level 4, */ -/* see mail.richard.1997-09-25.13-26. */ -/* Essentially the same settings are done in testlib.h. */ - -#ifdef MPS_BUILD_MV - -/* "unreferenced inline function has been removed" (windows.h) */ -#pragma warning(disable: 4514) - -/* "constant conditional" (MPS_END) */ -#pragma warning(disable: 4127) - -/* "unreachable code" (ASSERT, if cond is constantly true). */ -#pragma warning(disable: 4702) - -/* "expression evaluates to a function which is missing an argument list" */ -#pragma warning(disable: 4550) - -/* "local variable is initialized but not referenced" */ -#pragma warning(disable: 4189) - -/* "not all control paths return a value" */ -#pragma warning(disable: 4715) - -/* MSVC 2.0 generates a warning when using NOCHECK or UNUSED */ -#ifdef _MSC_VER -#if _MSC_VER < 1000 -#pragma warning(disable: 4705) -#endif -#else /* _MSC_VER */ -#error "Expected _MSC_VER to be defined for builder.mv" -#endif /* _MSC_VER */ - - -/* Non-checking varieties give many spurious warnings because parameters - * are suddenly unused, etc. We aren't interested in these - */ - -#if defined(AVER_AND_CHECK_NONE) - -/* "unreferenced formal parameter" */ -#pragma warning(disable: 4100) - -/* "unreferenced local function has been removed" */ -#pragma warning(disable: 4505) - -#endif /* AVER_AND_CHECK_NONE */ - -#endif /* MPS_BUILD_MV */ - - -/* EPVMDefaultSubsequentSegSIZE is a default for the alignment of - * subsequent segments (non-initial at each save level) in EPVM. See - * design.mps.poolepvm.arch.segment.size. - */ - -#define EPVMDefaultSubsequentSegSIZE ((Size)64 * 1024) - - -/* Arena Configuration -- see - * - * .client.seg-size: ARENA_CLIENT_PAGE_SIZE is the size in bytes of a - * "page" (i.e., segment granule) in the client arena. It's set at 8192 - * with no particular justification. - */ - -#define ARENA_CONTROL_EXTENDBY ((Size)4096) -#define ARENA_CONTROL_AVGSIZE ((Size)32) -#define ARENA_CONTROL_MAXSIZE ((Size)65536) - -#define ArenaPollALLOCTIME (65536.0) - -#define ARENA_ZONESHIFT ((Shift)20) - -#define ARENA_CLIENT_PAGE_SIZE ((Size)8192) - -#define ArenaDefaultZONESET (ZoneSetUNIV << (MPS_WORD_WIDTH / 2)) -/* @@@@ knows the implementation of ZoneSets */ - -/* .segpref.default: For EPcore, non-DL segments should be placed high */ -/* to reduce fragmentation of DL pools (see request.epcore.170193). */ -#define SegPrefDEFAULT { \ - SegPrefSig, /* sig */ \ - TRUE, /* high */ \ - ArenaDefaultZONESET, /* zoneSet */ \ - FALSE, /* isCollected */ \ - FALSE, /* isGen */ \ - (Serial)0, /* gen */ \ -} - -#define LDHistoryLENGTH ((Size)4) - - -/* Stack configuration */ - -/* Currently StackProbe has a useful implementation only on - * Intel platforms and only when using Microsoft build tools (builder.mv) - */ -#if defined(MPS_ARCH_I3) && defined(MPS_BUILD_MV) -#define StackProbeDEPTH ((Size)500) -#else -#define StackProbeDEPTH ((Size)0) -#endif /* MPS_ARCH_I3 */ - - -/* Shield Configuration -- see */ - -#define ShieldCacheSIZE ((size_t)16) -#define ShieldDepthWIDTH (4) - - -/* VM Configuration -- see */ - -#define VMANPageALIGNMENT ((Align)4096) -#define VMJunkBYTE ((unsigned char)0xA9) - -/* Protection Configuration see - - For each architecture/OS that uses protix.c or protsgix.c, we need to - define what signal number to use, and what si_code value to check. -*/ - -#if defined(MPS_OS_FR) -#define PROT_SIGNAL (SIGSEGV) -#elif defined(MPS_OS_XC) -#define PROT_SIGNAL (SIGBUS) -#endif - -#if defined(MPS_OS_XC) -#define PROT_SIGINFO_GOOD(info) (1) -#elif defined(MPS_OS_FR) -#define PROT_SIGINFO_GOOD(info) ((info)->si_code == SEGV_ACCERR) -#endif - - -/* Tracer Configuration -- see */ - -#define TraceLIMIT ((size_t)1) -/* I count 4 function calls to scan, 10 to copy. */ -#define TraceCopyScanRATIO (1.5) - -/* Chosen so that the RememberedSummaryBlockStruct packs nicely into - pages */ -#define RememberedSummaryBLOCK 15 - - -/* Events - * - * EventBufferSIZE is the number of words in the global event buffer. - */ - -#define EventBufferSIZE ((size_t)4096) -#define EventStringLengthMAX ((size_t)255) /* Not including NUL */ - - -/* Assert Buffer */ - -#define ASSERT_BUFFER_SIZE ((Size)512) - - -/* Diagnostics Buffer */ - -#ifdef DIAG_WITH_STREAM_AND_WRITEF -/* DIAG_BUFFER_SIZE: 100 screenfuls: 100x80x25 = 200000 */ -#define DIAG_BUFFER_SIZE ((Size)200000) -#else -#define DIAG_BUFFER_SIZE ((Size)1) -#endif - -#define DIAG_PREFIX_TAGSTART "MPS." -#define DIAG_PREFIX_LINE " " -#define DIAG_PREFIX_TAGEND "" - - -/* memory operator configuration - * - * We need efficient operators similar to memcpy, memset, and memcmp. - * In general, we cannot use the C library mem functions directly as - * that would not be freestanding. However, on some platforms we can do - * this, because they are inlined by the compiler and so do not actually - * create a dependence on an external library. - */ - -#if defined(MPS_PF_W3I3MV) -/* MSVC on Intel inlines mem* when optimizing */ -#define mps_lib_memset(p, c, l) memset(p, c, l) -#define mps_lib_memcpy(p, q, s) memcpy(p, q, s) -#define mps_lib_memcmp(p, q, s) memcmp(p, q, s) -/* get prototypes for ANSI mem* */ -#include -#endif - - -/* Product Configuration - * - * Deprecated, see design/config/#req.prod>. This now only contains the - * configuration used by the former "MPS" product, which is now the only - * product. - */ - -#define MPS_PROD_STRING "mps" -#define MPS_PROD_MPS -#define ARENA_INIT_SPARE_COMMIT_LIMIT ((Size)10uL*1024uL*1024uL) -#define THREAD_MULTI -#define PROTECTION -#define PROD_CHECKLEVEL_INITIAL CheckLevelSHALLOW - - -/* Pool Class AMC configuration */ - -/* AMC treats segments of this many pages (or more) as "Large" */ -#define AMCLargeSegPAGES ((Count)8) - - -/* Pool Class AWL configuration -- see poolawl.c for usage */ - -#define AWL_HAVE_SEG_SA_LIMIT TRUE -#define AWL_SEG_SA_LIMIT 200 /* TODO: Improve guesswork with measurements */ -#define AWL_HAVE_TOTAL_SA_LIMIT FALSE -#define AWL_TOTAL_SA_LIMIT 0 - - -#endif /* config_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003, 2006 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c deleted file mode 100644 index 8a3bc7e3034..00000000000 --- a/mps/code/dbgpool.c +++ /dev/null @@ -1,713 +0,0 @@ -/* dbgpool.c: POOL DEBUG MIXIN - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .source: design.mps.object-debug - */ - -#include "dbgpool.h" -#include "poolmfs.h" -#include "splay.h" -#include "mpm.h" -#include - -SRCID(dbgpool, "$Id$"); - - -/* tagStruct -- tags for storing info about allocated objects */ - -typedef struct tagStruct { - /* We don't want to pay the expense of a sig in every tag */ - Addr addr; - Size size; - SplayNodeStruct splayNode; - char userdata[1 /* actually variable length */]; -} tagStruct; - -#define SplayNode2Tag(node) PARENT(tagStruct, splayNode, (node)) - -typedef tagStruct *Tag; - - -/* tag init methods: copying the user-supplied data into the tag */ - -#define TagInitMethodCheck(f) FUNCHECK(f) - -static void TagTrivInit(void* tag, va_list args) -{ - UNUSED(tag); UNUSED(args); -} - - -/* TagComp -- splay comparison function for address ordering of tags */ - -static Compare TagComp(void *key, SplayNode node) -{ - Addr addr1, addr2; - - addr1 = *(Addr *)key; - addr2 = SplayNode2Tag(node)->addr; - if (addr1 < addr2) - return CompareLESS; - else if (addr1 > addr2) { - /* Check key is not inside the object of this tag */ - AVER_CRITICAL(AddrAdd(addr2, SplayNode2Tag(node)->size) <= addr1); - return CompareGREATER; - } else - return CompareEQUAL; -} - - -/* PoolDebugMixinCheck -- check a PoolDebugMixin */ - -Bool PoolDebugMixinCheck(PoolDebugMixin debug) -{ - /* Nothing to check about fenceTemplate */ - /* Nothing to check about fenceSize */ - /* Nothing to check about freeTemplate */ - /* Nothing to check about freeSize */ - if (debug->tagInit != NULL) { - CHECKL(TagInitMethodCheck(debug->tagInit)); - /* Nothing to check about tagSize */ - CHECKD(Pool, debug->tagPool); - CHECKL(COMPATTYPE(Addr, void*)); /* tagPool relies on this */ - /* Nothing to check about missingTags */ - CHECKL(SplayTreeCheck(&debug->index)); - } - UNUSED(debug); /* see */ - return TRUE; -} - - -/* DebugPoolDebugMixin -- gets the debug mixin, if any */ - -#define DebugPoolDebugMixin(pool) (((pool)->class->debugMixin)(pool)) - - -/* PoolNoDebugMixin -- debug mixin methods for pools with no mixin */ - -PoolDebugMixin PoolNoDebugMixin(Pool pool) -{ - AVERT(Pool, pool); - return NULL; -} - - -/* PoolDebugOptionsCheck -- check a PoolDebugOptions */ - -static Bool PoolDebugOptionsCheck(PoolDebugOptions opt) -{ - CHECKL(opt != NULL); - if (opt->fenceSize != 0) { - CHECKL(opt->fenceTemplate != NULL); - /* Nothing to check about fenceSize */ - } - if (opt->freeSize != 0) { - CHECKL(opt->freeTemplate != NULL); - /* Nothing to check about freeSize */ - } - return TRUE; -} - - -/* DebugPoolInit -- init method for a debug pool - * - * Someday, this could be split into fence and tag init methods. - */ - -static Res DebugPoolInit(Pool pool, va_list args) -{ - Res res; - PoolDebugOptions options; - PoolDebugMixin debug; - TagInitMethod tagInit; - Size tagSize; - - AVERT(Pool, pool); - options = va_arg(args, PoolDebugOptions); - AVERT(PoolDebugOptions, options); - /* @@@@ Tag parameters should be taken from options, but tags have */ - /* not been published yet. */ - tagInit = NULL; tagSize = 0; - - res = SuperclassOfPool(pool)->init(pool, args); - if (res != ResOK) - return res; - - debug = DebugPoolDebugMixin(pool); - AVER(debug != NULL); - - /* fencepost init */ - /* @@@@ This parses a user argument, options, so it should really */ - /* go through the MPS interface. The template needs to be copied */ - /* into Addr memory, to avoid breaking . */ - debug->fenceSize = options->fenceSize; - if (debug->fenceSize != 0) { - if (debug->fenceSize % PoolAlignment(pool) != 0) { - res = ResPARAM; - goto alignFail; - } - /* Fenceposting turns on tagging */ - if (tagInit == NULL) { - tagSize = 0; - tagInit = TagTrivInit; - } - debug->fenceTemplate = options->fenceTemplate; - } - - /* free-checking init */ - /* @@@@ This parses a user argument, options, so it should really */ - /* go through the MPS interface. The template needs to be copied */ - /* into Addr memory, to avoid breaking . */ - debug->freeSize = options->freeSize; - if (debug->freeSize != 0) { - if (PoolAlignment(pool) % debug->freeSize != 0) { - res = ResPARAM; - goto alignFail; - } - debug->freeTemplate = options->freeTemplate; - } - - /* tag init */ - debug->tagInit = tagInit; - if (debug->tagInit != NULL) { - debug->tagSize = tagSize + sizeof(tagStruct) - 1; - /* This pool has to be like the arena control pool: the blocks */ - /* allocated must be accessible using void*. */ - res = PoolCreate(&debug->tagPool, PoolArena(pool), PoolClassMFS(), - debug->tagSize, debug->tagSize); - if (res != ResOK) - goto tagFail; - debug->missingTags = 0; - SplayTreeInit(&debug->index, TagComp, NULL); - } - - debug->sig = PoolDebugMixinSig; - AVERT(PoolDebugMixin, debug); - return ResOK; - -tagFail: -alignFail: - SuperclassOfPool(pool)->finish(pool); - return res; -} - - -/* DebugPoolFinish -- finish method for a debug pool */ - -static void DebugPoolFinish(Pool pool) -{ - PoolDebugMixin debug; - - AVERT(Pool, pool); - - debug = DebugPoolDebugMixin(pool); - AVER(debug != NULL); - AVERT(PoolDebugMixin, debug); - if (debug->tagInit != NULL) { - SplayTreeFinish(&debug->index); - PoolDestroy(debug->tagPool); - } - SuperclassOfPool(pool)->finish(pool); -} - - -/* freeSplat -- splat free block with splat pattern - * - * If base is in a segment, the whole block has to be in it. - */ - -static void freeSplat(PoolDebugMixin debug, Pool pool, Addr base, Addr limit) -{ - Addr p, next; - Size freeSize = debug->freeSize; - Arena arena; - Seg seg = NULL; /* suppress "may be used uninitialized" */ - Bool inSeg; - - AVER(base < limit); - - /* If the block is in a segment, make sure any shield is up. */ - arena = PoolArena(pool); - inSeg = SegOfAddr(&seg, arena, base); - if (inSeg) { - AVER(limit <= SegLimit(seg)); - ShieldExpose(arena, seg); - } - /* Write as many copies of the template as fit in the block. */ - for (p = base, next = AddrAdd(p, freeSize); - next <= limit && p < next /* watch out for overflow in next */; - p = next, next = AddrAdd(next, freeSize)) - (void)AddrCopy(p, debug->freeTemplate, freeSize); - /* Fill the tail of the block with a partial copy of the template. */ - if (next > limit || next < p) - (void)AddrCopy(p, debug->freeTemplate, AddrOffset(p, limit)); - if (inSeg) { - ShieldCover(arena, seg); - } -} - - -/* freeCheck -- check free block for splat pattern */ - -static Bool freeCheck(PoolDebugMixin debug, Pool pool, Addr base, Addr limit) -{ - Addr p, next; - Size freeSize = debug->freeSize; - Res res; - Arena arena; - Seg seg = NULL; /* suppress "may be used uninitialized" */ - Bool inSeg; - - AVER(base < limit); - - /* If the block is in a segment, make sure any shield is up. */ - arena = PoolArena(pool); - inSeg = SegOfAddr(&seg, arena, base); - if (inSeg) { - AVER(limit <= SegLimit(seg)); - ShieldExpose(arena, seg); - } - /* Compare this to the AddrCopys in freeSplat. */ - /* Check the complete copies of the template in the block. */ - for (p = base, next = AddrAdd(p, freeSize); - next <= limit && p < next /* watch out for overflow in next */; - p = next, next = AddrAdd(next, freeSize)) - if (AddrComp(p, debug->freeTemplate, freeSize) != 0) { - res = FALSE; goto done; - } - /* Check the partial copy of the template at the tail of the block. */ - if (next > limit || next < p) - if (AddrComp(p, debug->freeTemplate, AddrOffset(p, limit)) != 0) { - res = FALSE; goto done; - } - res = TRUE; - -done: - if (inSeg) { - ShieldCover(arena, seg); - } - return res; -} - - -/* freeCheckAlloc -- allocation wrapper for free-checking */ - -static Res freeCheckAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool, - Size size, Bool withReservoir) -{ - Res res; - Addr new; - - AVER(aReturn != NULL); - - res = SuperclassOfPool(pool)->alloc(&new, pool, size, withReservoir); - if (res != ResOK) - return res; - if (debug->freeSize != 0) - ASSERT(freeCheck(debug, pool, new, AddrAdd(new, size)), - "free space corrupted on alloc"); - - *aReturn = new; - return res; -} - - -/* freeCheckFree -- freeing wrapper for free-checking */ - -static void freeCheckFree(PoolDebugMixin debug, - Pool pool, Addr old, Size size) -{ - if (debug->freeSize != 0) - freeSplat(debug, pool, old, AddrAdd(old, size)); - SuperclassOfPool(pool)->free(pool, old, size); -} - - -/* fenceAlloc -- allocation wrapper for fenceposts - * - * Allocates an object, adding fenceposts on both sides. Layout: - * - * |----------|-------------------------------------|------|----------| - * start fp client object slop end fp - * - * slop is the extra allocation from rounding up the client request to - * the pool's alignment. The fenceposting code does this, so there's a - * better chance of the end fencepost being flush with the next object - * (can't be guaranteed, since the underlying pool could have allocated - * an even larger block). The alignment slop is filled from the - * fencepost template as well (as much as fits, .fence.size guarantees - * the template is larger). - */ - -static Res fenceAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool, - Size size, Bool withReservoir) -{ - Res res; - Addr new, clientNew; - Size alignedSize; - - AVER(aReturn != NULL); - - alignedSize = SizeAlignUp(size, PoolAlignment(pool)); - res = freeCheckAlloc(&new, debug, pool, alignedSize + 2*debug->fenceSize, - withReservoir); - if (res != ResOK) - return res; - clientNew = AddrAdd(new, debug->fenceSize); - /* @@@@ shields? */ - /* start fencepost */ - (void)AddrCopy(new, debug->fenceTemplate, debug->fenceSize); - /* alignment slop */ - (void)AddrCopy(AddrAdd(clientNew, size), - debug->fenceTemplate, alignedSize - size); - /* end fencepost */ - (void)AddrCopy(AddrAdd(clientNew, alignedSize), - debug->fenceTemplate, debug->fenceSize); - - *aReturn = clientNew; - return res; -} - - -/* fenceCheck -- check fences of an object */ - -static Bool fenceCheck(PoolDebugMixin debug, Pool pool, Addr obj, Size size) -{ - Size alignedSize; - - AVERT_CRITICAL(PoolDebugMixin, debug); - AVERT_CRITICAL(Pool, pool); - /* Can't check obj */ - - alignedSize = SizeAlignUp(size, PoolAlignment(pool)); - /* @@@@ shields? */ - /* Compare this to the AddrCopys in fenceAlloc */ - return (AddrComp(AddrSub(obj, debug->fenceSize), debug->fenceTemplate, - debug->fenceSize) == 0 - && AddrComp(AddrAdd(obj, size), debug->fenceTemplate, - alignedSize - size) == 0 - && AddrComp(AddrAdd(obj, alignedSize), debug->fenceTemplate, - debug->fenceSize) == 0); -} - - -/* fenceFree -- freeing wrapper for fenceposts */ - -static void fenceFree(PoolDebugMixin debug, - Pool pool, Addr old, Size size) -{ - Size alignedSize; - - ASSERT(fenceCheck(debug, pool, old, size), "fencepost check on free"); - - alignedSize = SizeAlignUp(size, PoolAlignment(pool)); - freeCheckFree(debug, pool, AddrSub(old, debug->fenceSize), - alignedSize + 2*debug->fenceSize); -} - - -/* tagAlloc -- allocation wrapper for tagged pools */ - -static Res tagAlloc(PoolDebugMixin debug, - Pool pool, Addr new, Size size, Bool withReservoir) -{ - Tag tag; - Res res; - Addr addr; - - UNUSED(pool); - res = PoolAlloc(&addr, debug->tagPool, debug->tagSize, FALSE); - if (res != ResOK) { - if (withReservoir) { /* missingTags++; - return ResOK; - } else { - return res; - } - } - tag = (Tag)addr; - tag->addr = new; tag->size = size; - SplayNodeInit(&tag->splayNode); - /* In the future, we might call debug->tagInit here. */ - res = SplayTreeInsert(&debug->index, &tag->splayNode, (void *)&new); - AVER(res == ResOK); - return ResOK; -} - - -/* tagFree -- deallocation wrapper for tagged pools */ - -static void tagFree(PoolDebugMixin debug, Pool pool, Addr old, Size size) -{ - SplayNode node; - Tag tag; - Res res; - - AVERT(PoolDebugMixin, debug); - AVERT(Pool, pool); - AVER(size > 0); - - res = SplayTreeSearch(&node, &debug->index, (void *)&old); - if (res != ResOK) { - AVER(debug->missingTags > 0); - debug->missingTags--; - return; - } - tag = SplayNode2Tag(node); - AVER(tag->size == size); - res = SplayTreeDelete(&debug->index, node, (void *)&old); - AVER(res == ResOK); - SplayNodeFinish(node); - PoolFree(debug->tagPool, (Addr)tag, debug->tagSize); -} - - -/* DebugPoolAlloc -- alloc method for a debug pool - * - * Eventually, tag init args will need to be handled somewhere here. - */ - -static Res DebugPoolAlloc(Addr *aReturn, - Pool pool, Size size, Bool withReservoir) -{ - Res res; - Addr new = NULL; /* suppress "may be used uninitialized" warning */ - PoolDebugMixin debug; - - AVER(aReturn != NULL); - AVERT(Pool, pool); - AVER(size > 0); - AVERT(Bool, withReservoir); - - debug = DebugPoolDebugMixin(pool); - AVER(debug != NULL); - AVERT(PoolDebugMixin, debug); - if (debug->fenceSize != 0) - res = fenceAlloc(&new, debug, pool, size, withReservoir); - else - res = freeCheckAlloc(&new, debug, pool, size, withReservoir); - if (res != ResOK) - return res; - /* Allocate object first, so it fits even when the tag doesn't. */ - if (debug->tagInit != NULL) { - res = tagAlloc(debug, pool, new, size, withReservoir); - if (res != ResOK) - goto tagFail; - } - - *aReturn = new; - return res; - -tagFail: - fenceFree(debug, pool, new, size); - return res; -} - - -/* DebugPoolFree -- free method for a debug pool */ - -static void DebugPoolFree(Pool pool, Addr old, Size size) -{ - PoolDebugMixin debug; - - AVERT(Pool, pool); - /* Can't check old */ - AVER(size > 0); - - debug = DebugPoolDebugMixin(pool); - AVER(debug != NULL); - AVERT(PoolDebugMixin, debug); - - if (debug->fenceSize != 0) - fenceFree(debug, pool, old, size); - else - freeCheckFree(debug, pool, old, size); - /* Free the object first, to get fences checked before tag. */ - if (debug->tagInit != NULL) - tagFree(debug, pool, old, size); -} - - -/* TagWalk -- walk all objects in the pool using tags */ - -typedef void (*ObjectsStepMethod)(Addr addr, Size size, Format fmt, - Pool pool, void *tagData, void *p); - -#define ObjectsStepMethodCheck(f) \ - ((f) != NULL) /* that's the best we can do */ - -static void TagWalk(Pool pool, ObjectsStepMethod step, void *p) -{ - SplayNode node; - PoolDebugMixin debug; - Addr dummy = NULL; /* Breaks , but it's */ - /* only temporary until SplayTreeFirst is fixed. */ - - AVERT(Pool, pool); - AVERT(ObjectsStepMethod, step); - /* Can't check p */ - - debug = DebugPoolDebugMixin(pool); - AVER(debug != NULL); - AVERT(PoolDebugMixin, debug); - - node = SplayTreeFirst(&debug->index, (void *)&dummy); - while (node != NULL) { - Tag tag = SplayNode2Tag(node); - - step(tag->addr, tag->size, NULL, pool, &tag->userdata, p); - node = SplayTreeNext(&debug->index, node, (void *)&tag->addr); - } -} - - -/* fenceCheckingStep -- step function for DebugPoolCheckFences */ - -static void fenceCheckingStep(Addr addr, Size size, Format fmt, - Pool pool, void *tagData, void *p) -{ - /* no need to check arguments checked in the caller */ - UNUSED(fmt); UNUSED(tagData); - ASSERT(fenceCheck((PoolDebugMixin)p, pool, addr, size), - "fencepost check requested by client"); -} - - -/* DebugPoolCheckFences -- check all the fenceposts in the pool */ - -void DebugPoolCheckFences(Pool pool) -{ - PoolDebugMixin debug; - - AVERT(Pool, pool); - debug = DebugPoolDebugMixin(pool); - if (debug == NULL) - return; - AVERT(PoolDebugMixin, debug); - - if (debug->fenceSize != 0) - TagWalk(pool, fenceCheckingStep, (void *)debug); -} - - -/* DebugPoolFreeSplat -- if in a free-checking debug pool, splat free block */ - -void DebugPoolFreeSplat(Pool pool, Addr base, Addr limit) -{ - PoolDebugMixin debug; - - AVERT(Pool, pool); - AVER(PoolHasAddr(pool, base)); - AVER(PoolHasAddr(pool, AddrSub(limit, 1))); - - debug = DebugPoolDebugMixin(pool); - if (debug != NULL) { - AVERT(PoolDebugMixin, debug); - if (debug->freeSize != 0) - freeSplat(debug, pool, base, limit); - } -} - - -/* DebugPoolFreeCheck -- if in a free-checking debug pool, check free block */ - -void DebugPoolFreeCheck(Pool pool, Addr base, Addr limit) -{ - PoolDebugMixin debug; - - AVERT(Pool, pool); - AVER(PoolHasAddr(pool, base)); - AVER(PoolHasAddr(pool, AddrSub(limit, 1))); - - debug = DebugPoolDebugMixin(pool); - if (debug != NULL) { - AVERT(PoolDebugMixin, debug); - if (debug->freeSize != 0) - ASSERT(freeCheck(debug, pool, base, limit), - "free space corrupted on release"); - } -} - - -/* freeCheckingStep -- step function for DebugPoolCheckFreeSpace */ - -static void freeCheckingStep(Addr base, Addr limit, Pool pool, void *p) -{ - /* no need to check arguments checked in the caller */ - ASSERT(freeCheck((PoolDebugMixin)p, pool, base, limit), - "free space corrupted on client check"); -} - - -/* DebugPoolCheckFreeSpace -- check free space in the pool for overwrites */ - -void DebugPoolCheckFreeSpace(Pool pool) -{ - PoolDebugMixin debug; - - AVERT(Pool, pool); - debug = DebugPoolDebugMixin(pool); - if (debug == NULL) - return; - AVERT(PoolDebugMixin, debug); - - if (debug->freeSize != 0) - PoolFreeWalk(pool, freeCheckingStep, (void *)debug); -} - - -/* PoolClassMixInDebug -- mix in the debug support for class init */ - -void PoolClassMixInDebug(PoolClass class) -{ - /* Can't check class because it's not initialized yet */ - class->init = DebugPoolInit; - class->finish = DebugPoolFinish; - class->alloc = DebugPoolAlloc; - class->free = DebugPoolFree; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/dbgpool.h b/mps/code/dbgpool.h deleted file mode 100644 index 4bc96b9eede..00000000000 --- a/mps/code/dbgpool.h +++ /dev/null @@ -1,111 +0,0 @@ -/* dbgpool.h: POOL DEBUG MIXIN - * - * See . - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - */ - -#ifndef dbgpool_h -#define dbgpool_h - -#include "splay.h" -#include "mpmtypes.h" -#include - - -/* tag init methods: copying the user-supplied data into the tag */ - -typedef void (*TagInitMethod)(void* tag, va_list args); - - -/* PoolDebugOptions -- option structure for debug pool init - * - * This must be kept in sync with . - */ - -typedef struct PoolDebugOptionsStruct { - void* fenceTemplate; - Size fenceSize; - void* freeTemplate; - Size freeSize; - /* TagInitMethod tagInit; */ - /* Size tagSize; */ -} PoolDebugOptionsStruct; - -typedef PoolDebugOptionsStruct *PoolDebugOptions; - - -/* PoolDebugMixinStruct -- internal structure for debug mixins */ - -#define PoolDebugMixinSig ((Sig)0x519B0DB9) /* SIGnature POol DeBuG */ - -typedef struct PoolDebugMixinStruct { - Sig sig; - Addr fenceTemplate; - Size fenceSize; - Addr freeTemplate; - Size freeSize; - TagInitMethod tagInit; - Size tagSize; - Pool tagPool; - Count missingTags; - SplayTreeStruct index; -} PoolDebugMixinStruct; - - -extern Bool PoolDebugMixinCheck(PoolDebugMixin dbg); - -extern void PoolClassMixInDebug(PoolClass class); - -extern void DebugPoolCheckFences(Pool pool); -extern void DebugPoolCheckFreeSpace(Pool pool); - -extern void DebugPoolFreeSplat(Pool pool, Addr base, Addr limit); -extern void DebugPoolFreeCheck(Pool pool, Addr base, Addr limit); - - -#endif /* dbgpool_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/dbgpooli.c b/mps/code/dbgpooli.c deleted file mode 100644 index ebc8733e3c2..00000000000 --- a/mps/code/dbgpooli.c +++ /dev/null @@ -1,96 +0,0 @@ -/* dbgpooli.c: POOL DEBUG MIXIN C INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .source: - */ - -#include "dbgpool.h" -#include "mps.h" -#include "mpm.h" - -SRCID(dbgpooli, "$Id$"); - - -/* mps_pool_check_fenceposts -- check all the fenceposts in the pool */ - -void mps_pool_check_fenceposts(mps_pool_t mps_pool) -{ - Pool pool = (Pool)mps_pool; - Arena arena; - - /* TESTT not AVERT, see . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/diag.c b/mps/code/diag.c deleted file mode 100644 index 289e7fd77c6..00000000000 --- a/mps/code/diag.c +++ /dev/null @@ -1,773 +0,0 @@ -/* diag.c: MEMORY POOL MANAGER DIAGNOSTICS - * - * $Id$ - * Copyright (c) 2007 Ravenbrook Limited. See end of file for license. - * - * To Do: [RHSK 2007-08-13] - * @@ sigs and AVERTs for Rule, and macro for Rules initializer - * @@ deprecate un-tagged diags, remove old macros - * @@ every diag should end with \n: warn if this is missing. - */ - -#include - -#include "mpm.h" -#include "mpslib.h" /* for mps_lib_stdout */ - -#if defined(DIAG_WITH_STREAM_AND_WRITEF) - -typedef struct RuleStruct { - const char *action; - const char *tag; - const char *para; - const char *line; - int tpMatch; /* .tpmatch */ - /* @@ needs sig; (at end, to make initializer expression easy?) */ -} *Rule; - - -/* RulesGlobal -- throw away some diags (see INSTRUCTIONS below) */ - -struct RuleStruct RulesGlobal[] = { - { "-", "*", "*", "*" }, - { "+", "DiagFilter_Rules", "*", "*" }, - { "+", "VMCompact", "*", "*" }, - /* ----v---- always on please (RHSK) ----v---- */ - { "+", "MPSVersion", "*", "*" }, - { "+", "traceSetSignalEmergency", "*", "*" }, - { NULL, "", "", "" } -}; - -struct RuleStruct RulesGlobal_RHSK[] = { - { "+", "*", "*", "*" }, - { "+", "DiagFilter_Rules", "*", "*" }, - { "-", "DIAGTEST_", "*", "*" }, - { "+", "AMCTraceEnd_pageret", "*", "*" }, - { "-", "ChainCondemnAuto", "*", "*" }, - { "+", "VM_ix_", "*", "*" }, - { "-", "vmArenaExtend_", "*", "*" }, - { "-", "traceFindGrey", "*", "*" }, - { "-", "TraceStart", "*", "*" }, - { "+", "TraceStart", "*", "controlPool" }, - { "+", "TraceStart", "*", "reserved" }, - { "+", "TraceStart", "*", "committed" }, - { "+", "TraceStart", "*", "genZoneSet" }, - { "-", "TraceStart", "because code 1", "*" }, - { "+", "VMCompact", "*", "*" }, - { "-", "VMCompact_hex", "*", "*" }, - { "+", "VM_ix_Create", "*", "*" }, - /* ----v---- always on please (RHSK) ----v---- */ - { "+", "traceSetSignalEmergency", "*", "*" }, - { NULL, "", "", "" } -}; - -struct RuleStruct RulesGlobalExample[] = { - { "+", "*", "*", "*" }, - { "+", "DiagFilter_Rules", "*", "*" }, - { "-", "DIAGTEST_", "*", "*" }, - { "+", "ChainCondemnAuto", "gens [0..0]", "*" }, - { "+", "TraceStart", "*", "*" }, - { "+", "TraceStart", "because code 1:", "*" }, - { "-", "TraceStart", "*", "controlPool" }, - { "-", "TraceStart", "*", "ommit" }, - { "-", "TraceStart", "*", "zoneShift" }, - { "-", "TraceStart", "*", "alignment" }, - { "-", "amcScanNailed-loop", "*", "*" }, - { NULL, "", "", "" } -}; - -/* RulesGlobal -- INSTRUCTIONS - * - * In your local copy of diag.c, you can modify RulesGlobal as you - * wish, to control what diags you see. - * - * Each rule consists of: action, tag, para, and line. A rule that - * matches on TAG, PARA and LINE determines what ACTION is taken - * for that line of that diag. Later rules override earlier rules, - * ie. the lowest matching rule wins. (And at least one rule must - * match, so the first rule should be a catch-all). - * - * ACTION = "+" (output this line of diag), or "-" (skip this line). - * - * TAG: does pattern (text or *) appear in diag's tag? - * - * PARA: does pattern (text or *) appear anywhere in diag's text output - * (does not match the tag)? - * - * LINE: does pattern (text or *) appear on this line of the diag - * text? - * - * Note: a diag that deliberately has no output, eg. - * DIAG_SINGLEF(( "MyTag", NULL )), - * is treated as having a single empty 'line'. See .empty-diag. - * - * Note: for help debugging your ruleset, see .rules.debug below. - * - * Note: the entire filtering mechanism can be turned off, so that - * diagnostics go immediately to mps_lib_stdout: see .filter-disable. - */ - - -/* Forward declarations */ - -static mps_lib_FILE *filterStream(void); -static int filterStream_fputc(int c, mps_lib_FILE *stream); -static int filterStream_fputs(const char *s, mps_lib_FILE *stream); -static void diag_test(void); - - -/* Stream -- output to filterStream or to a real mps_lib_FILE stream - * - * There are only two functions and two destinations; a full class - * hierarchy would be overkill! RHSK 2007-08-08. - */ - -int Stream_fputc(int c, mps_lib_FILE *stream) -{ - if(stream == filterStream()) - return filterStream_fputc(c, stream); - else - return mps_lib_fputc(c, stream); -} - -int Stream_fputs(const char *s, mps_lib_FILE *stream) -{ - if(stream == filterStream()) - return filterStream_fputs(s, stream); - else - return mps_lib_fputs(s, stream); -} - - -/* Diag -- a buffer to store a diagnostic - * - */ - -#define DiagSig ((Sig)0x519D1A99) /* SIGnature DIAG */ - -typedef struct DiagStruct { - Sig sig; - const char *tag; - Bool overflow; /* diag > buf? set flag, truncate, force output */ - Count n; - char buf[DIAG_BUFFER_SIZE]; -} *Diag; - -static Bool DiagCheck(Diag diag) -{ - CHECKS(Diag, diag); - CHECKL(diag->n <= sizeof(diag->buf)); - return TRUE; -} - - - -/* filterStream -- capable of filtering diagnostics - * - * This is not really an mps_lib_FILE*; it is a single global instance - * of a DiagStruct. - * - * Output is stored in a DiagStruct, to be filtered and output - * (or not) when complete. - */ - -static struct DiagStruct filterDiagGlobal = { DiagSig, NULL, FALSE, 0 }; - -static mps_lib_FILE *filterStream(void) -{ - return (mps_lib_FILE*)&filterDiagGlobal; -} - -/* filterStream_under: the underlying stream used to output diags */ -/* that pass the filter. */ -static mps_lib_FILE *filterStream_under(void) -{ - return mps_lib_stdout; -} - -/* .tpmatch: does this rule match current diag's tag and para? */ -enum { - TPMatch_Unknown = 0, /* initial value = 0 */ - TPMatch_Yes, - TPMatch_No -}; - -static void version_diag(void) -{ - DIAG_SINGLEF(( "MPSVersion", - "$S", (WriteFS)MPSVersion(), NULL )); -} - -static void rules_diag(Rule rules) -{ - Index ir; - - AVER(rules); - DIAG_FIRSTF(( "DiagFilter_Rules", - "Only showing diags permitted by these tag/paragraph/line" - " rules:\n", NULL )); - for(ir = 0; rules[ir].action != NULL; ir++) { - DIAG_DECL( Rule rule = &rules[ir]; ) - DIAG_MOREF(( "$S$S/$S/$S\n", (WriteFS)rule->action, (WriteFS)rule->tag, - (WriteFS)rule->para, (WriteFS)rule->line, - NULL )); - } - DIAG_END("DiagFilter_Rules"); -} - - -/* patternOccurs -- does patt occur in buf[i..j)? - * - * Returns true iff patt[0..pattLen) literally occurs in buf[i..j). - */ - -static Bool patternOccurs(const char *patt, Count pattLen, - const char *buf, Index i, Index j) -{ - Index im; /* start of tentative match */ - Index ip; /* index into patt */ - - AVER(patt); - AVER(buf); - AVER(i <= j); - - /* Search (naively) for patt anywhere inside buf[i..j) */ - for(im = i; im + pattLen <= j; im++) { - /* Consider upto pattLen chars starting at patt[0] and buf[im] */ - for(ip = 0; ip < pattLen; ip++) { - if(patt[ip] != buf[im + ip]) - break; - } - if(ip == pattLen) { - return TRUE; - } - } - - return FALSE; -} - -static Bool matchLine(Rule rule, Diag diag, Index i, Index j) -{ - AVER(rule); - AVER(diag); - AVER(i <= j); - AVER(j <= diag->n); - - if(rule->line[0] == '*') - return TRUE; - - return patternOccurs(rule->line, StringLength(rule->line), - diag->buf, i, j); -} - -static Bool matchPara(Rule rule, Diag diag) -{ - AVER(rule); - AVER(diag); - - if(rule->para[0] == '*') - return TRUE; - - return patternOccurs(rule->para, StringLength(rule->para), - diag->buf, 0, diag->n); -} - -static Bool matchTag(Rule rule, const char *tag) -{ - AVER(rule); - AVER(rule->tag); - AVER(tag); - - if(rule->tag[0] == '*') - return TRUE; - - return patternOccurs(rule->tag, StringLength(rule->tag), - tag, 0, StringLength(tag)); -} - -static void filterStream_LineOut(Diag diag, Index i, Index j) -{ - int r; - - AVER(diag); - AVER(i <= j); - AVER(j <= diag->n); - - r = Stream_fputs(DIAG_PREFIX_LINE, filterStream_under()); - AVER(r != mps_lib_EOF); - - for(; i < j; i++) { - char c; - c = diag->buf[i]; - r = Stream_fputc(c, filterStream_under()); - AVER(r != mps_lib_EOF); - } -} - - -/* filterStream_Output -- output this diag, if the rules select it - * - */ - -static void filterStream_Output(Diag diag, Rule rules) -{ - static Bool inside = FALSE; - Res res; - Count nr; - Index ir; - Index i, j; - Bool nolinesyet = TRUE; - Bool emptyonce; - - AVER(!inside); - inside = TRUE; - AVER(diag); - AVER(rules); - - if(diag->tag == NULL) - diag->tag = "(no tag)"; - - /* Count the rules */ - for(ir = 0; rules[ir].action != NULL; ir++) { - rules[ir].tpMatch = TPMatch_Unknown; - } - nr = ir; - - /* Filter */ - /* .empty-diag: Treat a diag that deliberately has no output, */ - /* eg: DIAG_SINGLEF(( "Tag", NULL )), as having a single empty */ - /* 'line'. This is the only time a line may be empty. */ - emptyonce = (diag->n == 0); - for(i = 0; emptyonce || i < diag->n; i = j) { - - /* Get the next line [i..j) */ - for(j = i; j < diag->n; j++) { - if(diag->buf[j] == '\n') { - j++; - break; - } - } - AVER(emptyonce || i < j); /* .empty-diag */ - emptyonce = FALSE; - - /* Find the lowest rule that matches it. */ - ir = nr - 1; - for(;;) { - Rule rule = &rules[ir]; - if(rule->tpMatch == TPMatch_Unknown) { - /* memoize .tpMatch */ - if(matchTag(rule, diag->tag) && matchPara(rule, diag)) { - rule->tpMatch = TPMatch_Yes; - } else { - rule->tpMatch = TPMatch_No; - } - } - if(rule->tpMatch == TPMatch_Yes && matchLine(rule, diag, i, j)) - break; - AVER(ir != 0); /* there must ALWAYS be a matching rule */ - ir--; - } - - /* Do the rule's action. */ - if(0) { - /* .rules.debug: Turn this on to show which rule applied. */ - Rule rule = &rules[ir]; - (void) WriteF(filterStream_under(), "[$U/$U:", ir, nr, - " $S$S/$S/$S] ", rule->action, rule->tag, - rule->para, rule->line, NULL); - } - if(rules[ir].action[0] == '+' || diag->overflow) { - if(nolinesyet) { - res = WriteF(filterStream_under(), - DIAG_PREFIX_TAGSTART "$S {", (WriteFS)diag->tag, NULL); - AVER(res == ResOK); - nolinesyet = FALSE; - } - filterStream_LineOut(diag, i, j); - } - } - - if(diag->overflow) { - res = WriteF(filterStream_under(), - "\n--- diagnostic too large: " - "forced to output, but truncated here ---\n" - "--- (for a bigger buffer, change DIAG_BUFFER_SIZE) ---\n", NULL); - AVER(res == ResOK); - } - if(!nolinesyet) { - res = WriteF(filterStream_under(), DIAG_PREFIX_TAGEND "}\n", NULL); - AVER(res == ResOK); - } - inside = FALSE; -} - -static void filterStream_TagBegin(mps_lib_FILE *stream, const char *tag) -{ - static Bool first = TRUE; - Diag diag; - - AVER(stream); - AVER(tag); - - diag = (Diag)stream; - AVERT(Diag, diag); - - if(first) { - first = FALSE; - version_diag(); - rules_diag(&RulesGlobal[0]); - diag_test(); - } - - if(diag->tag != NULL) { - /* Be helpful to the poor programmer! */ - (void) WriteF(filterStream_under(), - "\nWARNING: diag tag \"$S\" is still current" - " (missing DIAG_END()).", - diag->tag, NULL); - } - AVER(diag->tag == NULL); - - /* @@ when all diags are tagged, the buffer must be empty */ - /* @@ but for now, as a courtesy... */ - if(diag->n > 0) { - filterStream_Output(diag, &RulesGlobal[0]); - diag->n = 0; - } - - diag->tag = tag; - diag->overflow = FALSE; - AVER(diag->n == 0); -} - -static void filterStream_TagEnd(mps_lib_FILE *stream, const char *tag) -{ - Diag diag; - diag = (Diag)stream; - AVERT(Diag, diag); - - AVER(diag->tag != NULL); - - if(!StringEqual(diag->tag, tag)) { - /* Be helpful to the poor programmer! */ - (void) WriteF(filterStream_under(), - "\nWARNING: diag tag \"$S\" is current, " - "but got DIAG_END(\"$S\"). (They must match).", - (WriteFS)diag->tag, (WriteFS)tag, NULL); - } - AVER(StringEqual(diag->tag, tag)); - - /* Output the diag */ - filterStream_Output(diag, &RulesGlobal[0]); - - diag->tag = NULL; - diag->n = 0; -} - -static int filterStream_fputc(int c, mps_lib_FILE *stream) -{ - Diag diag; - - AVER(c != mps_lib_EOF); - AVER(stream == filterStream()); - - diag = (Diag)stream; - AVERT(Diag, diag); - /* @@ when all diags are tagged: AVER(diag->tag != NULL); */ - - /* AVER(diag->n + 1 <= sizeof(diag->buf)); */ - if(!(diag->n + 1 <= sizeof(diag->buf))) { - diag->overflow = TRUE; - /* ignore failure; do not return mps_lib_EOF */ - return c; - } - - /* add c to buffer */ - diag->buf[diag->n++] = (char)c; - return c; -} - -static int filterStream_fputs(const char *s, mps_lib_FILE *stream) -{ - Diag diag; - Count l; - Index i; - - AVER(s); - AVER(stream == filterStream()); - - diag = (Diag)stream; - AVERT(Diag, diag); - /* @@ when all diags are tagged: AVER(diag->tag != NULL); */ - - l = StringLength(s); - - /* AVER(diag->n + l <= sizeof(diag->buf)); */ - if(!(diag->n + l <= sizeof(diag->buf))) { - diag->overflow = TRUE; - /* ignore failure; do not return mps_lib_EOF */ - return 1; - } - - /* add s to buffer */ - for (i = 0; i < l; i++) { - diag->buf[diag->n++] = s[i]; - } - return 1; -} - - -/* DIAG_WITH_STREAM_AND_WRITEF -- Diagnostic output channel - * - * Only used for DIAG_WITH_STREAM_AND_WRITEF; see config.h. - */ - -Bool DiagEnabledGlobal = TRUE; - -Bool DiagIsOn(void) -{ - return DiagEnabledGlobal; -} - -mps_lib_FILE *DiagStream(void) -{ - /* .filter-disable: the entire filtering mechanism can be turned */ - /* off, so that diagnostics go immediately to mps_lib_stdout, */ - /* with no buffering or filtering. */ - Bool filter = TRUE; - - if(filter) { - return filterStream(); - } else { - return mps_lib_stdout; - } -} - -static void diagTagBegin(mps_lib_FILE *stream, const char *tag) -{ - AVER(stream); - AVER(tag); - - if(stream == filterStream()) { - filterStream_TagBegin(stream, tag); - } else { - Res res; - res = WriteF(stream, DIAG_PREFIX_TAGSTART "$S {\n", (WriteFS)tag, NULL); - AVER(res == ResOK); - } -} - -static void diagTagEnd(mps_lib_FILE *stream, const char *tag) -{ - AVER(stream); - AVER(tag); - - if(stream == filterStream()) { - filterStream_TagEnd(stream, tag); - } else { - Res res; - res = WriteF(stream, DIAG_PREFIX_TAGEND "}\n", tag, NULL); - AVER(res == ResOK); - } -} - - -/* Diag*F functions -- interface for general MPS code (via macros) - * - * These function manage TagBegin/End, and WriteF the text to - * DiagStream(). - * - * Direct writing to DiagStream() is also permitted (eg. from a - * Describe method). - */ - -void DiagSingleF(const char *tag, ...) -{ - va_list args; - Res res; - - diagTagBegin(DiagStream(), tag); - - va_start(args, tag); - res = WriteF_v(DiagStream(), args); - AVER(res == ResOK); - va_end(args); - - diagTagEnd(DiagStream(), tag); -} - -void DiagFirstF(const char *tag, ...) -{ - va_list args; - Res res; - - diagTagBegin(DiagStream(), tag); - - va_start(args, tag); - res = WriteF_v(DiagStream(), args); - AVER(res == ResOK); - va_end(args); -} - -void DiagMoreF(const char *firstformat, ...) -{ - va_list args; - Res res; - - /* ISO C says there must be at least one named parameter: hence */ - /* the named firstformat. It only looks different: there is no */ - /* change from the expected WriteF protocol. (In particular, */ - /* firstformat may legally be NULL, with the variable part empty). */ - - va_start(args, firstformat); - res = WriteF_firstformat_v(DiagStream(), firstformat, args); - AVER(res == ResOK); - va_end(args); -} - -void DiagEnd(const char *tag) -{ - diagTagEnd(DiagStream(), tag); -} - - -/* Test Code -- unit tests for this source file - * - * These are for developers to run if they modify this source file. - * There's no point running them otherwise. RHSK. - */ - -static void patternOccurs_test(Bool expect, const char *patt, - const char *text) -{ - Count pattLen = StringLength(patt); - Count textLen = StringLength(text); - enum {bufLen = 100}; - char buf[bufLen]; - Index start, i; - Count padLen; - Bool occurs; - - /* Call patternOccurs with this patt and text 3 times: each time */ - /* putting the text in the buffer at a different offset, to */ - /* verify that patternOccurs is not accepting matches outside the */ - /* [i..j) portion of the buffer. */ - - for(start = 0; start < 21; start += 7) { - AVER(bufLen > (start + textLen)); - /* put text into buf at start */ - for(i = 0; i < start; i++) { - buf[i] = 'X'; - } - for(i = 0; i < textLen; i++) { - (buf+start)[i] = text[i]; - } - padLen = bufLen - (start + textLen); - for(i = 0; i < padLen; i++) { - (buf+start+textLen)[i] = 'X'; - } - occurs = patternOccurs(patt, pattLen, buf, start, start+textLen); - AVER(occurs == expect); - } -} - -static void diag_test(void) -{ - DIAG_SINGLEF(( "DIAGTEST_Tag1", "text $U.\n", (WriteFU)42, NULL )); - - DIAG_SINGLEF(( "DIAGTEST_EmptyDiag", NULL )); - - DIAG_FIRSTF(( - "DIAGTEST_StringEqual", - "Fred = Fred: $U.\n", - StringEqual("Fred", "Fred"), - NULL - )); - DIAG_MOREF(("Fred = Tom: $U.\n", (WriteFU)StringEqual("Fred", "Tom"), NULL)); - DIAG_MOREF(("Tom = Fred: $U.\n", (WriteFU)StringEqual("Tom", "Fred"), NULL)); - DIAG_MOREF(("0 = Fred: $U.\n", (WriteFU)StringEqual("", "Fred"), NULL)); - DIAG_MOREF(("Fred = 0: $U.\n", (WriteFU)StringEqual("Fred", ""), NULL)); - DIAG_MOREF(("0 = 0: $U.\n", (WriteFU)StringEqual("", ""), NULL)); - DIAG_MOREF(("0 = 000: $U.\n", (WriteFU)StringEqual("", "\0\0"), NULL)); - DIAG_END("DIAGTEST_StringEqual"); - - DIAG_FIRSTF(( "DIAGTEST_patternOccurs", NULL )); - patternOccurs_test(TRUE, "Fred", "Fred"); - patternOccurs_test(TRUE, "Fred", "XFredX"); - patternOccurs_test(TRUE, "Fred", "FFred"); - patternOccurs_test(TRUE, "Fred", "FrFred"); - patternOccurs_test(TRUE, "Fred", "FreFred"); - patternOccurs_test(TRUE, "Fred", "FreFreFFred"); - patternOccurs_test(TRUE, "Fred", "FredFred"); - patternOccurs_test(TRUE, "Fred", "FFredFre"); - patternOccurs_test(TRUE, "Fred", "FrFredFr"); - patternOccurs_test(TRUE, "Fred", "FreFredF"); - patternOccurs_test(TRUE, "Fred", "FreFreFFredFre"); - patternOccurs_test(TRUE, "Fred", "FredFredF"); - patternOccurs_test(TRUE, "X", "X"); - patternOccurs_test(TRUE, "", "X"); - patternOccurs_test(TRUE, "", "Whatever"); - patternOccurs_test(FALSE, "Fred", "Tom"); - patternOccurs_test(FALSE, "X", "Tom"); - patternOccurs_test(FALSE, "X", "x"); - patternOccurs_test(FALSE, "X", ""); - patternOccurs_test(FALSE, "Whatever", ""); - patternOccurs_test(FALSE, "Fred", "Fre"); - patternOccurs_test(FALSE, "Fred", "red"); - patternOccurs_test(FALSE, "Fred", "Fxred"); - patternOccurs_test(FALSE, "Fred", "Frexd"); - DIAG_END("DIAGTEST_patternOccurs"); - -#if 0 - DIAG_FIRSTF(( "TestTag2", "text $U.\n", (WriteFU)42, NULL )); - DIAG_MOREF(( NULL )); - DIAG_MOREF(( "string $S.\n", (WriteFS)"fooey!", NULL )); - DIAG_MOREF(( NULL )); - DIAG_MOREF(( "Another string $S.\n", (WriteFS)"baloney!", NULL )); - DIAG_END( "TestTag2" ); -#endif -} - -#endif /* DIAG_WITH_STREAM_AND_WRITEF */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2007 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/event.c b/mps/code/event.c deleted file mode 100644 index a3331d18c18..00000000000 --- a/mps/code/event.c +++ /dev/null @@ -1,505 +0,0 @@ -/* event.c: EVENT LOGGING - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .sources: mps.design.event - * - * TRANSGRESSIONS (rule.impl.trans) - * - * .trans.ref: The reference counting used to destroy the mps_io object - * isn't right. - * - * .trans.log: The log file will be re-created if the lifetimes of - * arenas don't overlap, but shared if they do. mps_io_create cannot - * be called twice, but EventInit avoids this anyway. - * - * .trans.ifdef: This file should logically be split into two, event.c - * (which contains NOOP definitions, for general use) and eventdl.c, which - * is specific to the logging variety and actually does logging (maybe). - * Unfortunately, the build system doesn't really cope, and so this file - * consists of two versions which are conditional on the EVENT symbol. - */ - -#include "mpm.h" -#include "event.h" -#include "mpsio.h" - -SRCID(event, "$Id$"); - - -#ifdef EVENT /* .trans.ifdef */ - - -static Bool eventInited = FALSE; -static Bool eventIOInited = FALSE; -static mps_io_t eventIO; -static Count eventUserCount; -static Serial EventInternSerial; - -/* Buffers in which events are recorded, from the top down. */ -char EventBuffer[EventKindLIMIT][EventBufferSIZE]; - -/* Pointers to last written event in each buffer. */ -char *EventLast[EventKindLIMIT]; - -EventControlSet EventKindControl; /* Bit set used to control output. */ - - -/* EventFlush -- flush event buffer to the event stream */ - -Res EventFlush(EventKind kind) -{ - Res res; - size_t size; - - AVER(eventInited); - AVER(0 <= kind && kind < EventKindLIMIT); - - AVER(EventBuffer[kind] <= EventLast[kind]); - AVER(EventLast[kind] <= EventBuffer[kind] + EventBufferSIZE); - - /* Is event logging enabled for this kind of event, or are or are we just - writing to the buffer for backtraces, cores, and other debugging? */ - if (BS_IS_MEMBER(EventKindControl, kind)) { - - size = (size_t)(EventBuffer[kind] + EventBufferSIZE - EventLast[kind]); - - /* Checking the size avoids creating the event stream when the arena is - destroyed and no events have been logged. */ - if (size == 0) - return ResOK; - - /* Ensure the IO stream is open. We do this late so that no stream is - created if no events are enabled by telemetry control. */ - if (!eventIOInited) { - res = (Res)mps_io_create(&eventIO); - if(res != ResOK) - goto failCreate; - eventIOInited = TRUE; - } - - /* Writing might be faster if the size is aligned to a multiple of the - C library or kernel's buffer size. We could pad out the buffer with - a marker for this purpose. */ - - res = (Res)mps_io_write(eventIO, (void *)EventLast[kind], size); - if (res != ResOK) - goto failWrite; - - } - - res = ResOK; - -failWrite: -failCreate: - - /* Flush the in-memory buffer whether or not we succeeded, so that we can - record recent events there. */ - EventLast[kind] = EventBuffer[kind] + EventBufferSIZE; - - return res; -} - - -/* EventSync -- synchronize the event stream with the buffers */ - -void EventSync(void) -{ - EventKind kind; - for (kind = 0; kind < EventKindLIMIT; ++kind) - (void)EventFlush(kind); - (void)mps_io_flush(eventIO); -} - - -/* EventInit -- start using the event system, initialize if necessary */ - -void EventInit(void) -{ - /* Make local enums for all event params in order to check that the indexes - in the parameter definition macros are in order, and that parameter - idents are unique. */ - -#define EVENT_CHECK_ENUM_PARAM(name, index, sort, ident) \ - Event##name##Param##ident, - -#define EVENT_CHECK_ENUM(X, name, code, always, kind) \ - enum Event##name##ParamEnum { \ - EVENT_##name##_PARAMS(EVENT_CHECK_ENUM_PARAM, name) \ - Event##name##ParamLIMIT \ - }; - - EVENT_LIST(EVENT_CHECK_ENUM, X) - - /* Check consistency of the event definitions. These are all compile-time - checks and should get optimised away. */ - -#define EVENT_PARAM_CHECK_P(name, index, ident) -#define EVENT_PARAM_CHECK_A(name, index, ident) -#define EVENT_PARAM_CHECK_W(name, index, ident) -#define EVENT_PARAM_CHECK_U(name, index, ident) -#define EVENT_PARAM_CHECK_D(name, index, ident) -#define EVENT_PARAM_CHECK_B(name, index, ident) -#define EVENT_PARAM_CHECK_S(name, index, ident) \ - AVER(index + 1 == Event##name##ParamLIMIT); /* strings must come last */ - -#define EVENT_PARAM_CHECK(name, index, sort, ident) \ - AVER(index == Event##name##Param##ident); \ - AVER(sizeof(EventF##sort) >= 0); /* check existence of type */ \ - EVENT_PARAM_CHECK_##sort(name, index, ident) - -#define EVENT_CHECK(X, name, code, always, kind) \ - AVER(size_tAlignUp(sizeof(Event##name##Struct), MPS_PF_ALIGN) \ - <= EventSizeMAX); \ - AVER(Event##name##Code == code); \ - AVER(0 <= code && code <= EventCodeMAX); \ - AVER(sizeof(#name) - 1 <= EventNameMAX); \ - AVER((Bool)Event##name##Always == always); \ - AVERT(Bool, always); \ - AVER(0 <= Event##name##Kind); \ - AVER((EventKind)Event##name##Kind < EventKindLIMIT); \ - EVENT_##name##_PARAMS(EVENT_PARAM_CHECK, name) - - EVENT_LIST(EVENT_CHECK, X) - - /* Ensure that no event can be larger than the maximum event size. */ - AVER(EventBufferSIZE <= EventSizeMAX); - - /* Only if this is the first call. */ - if(!eventInited) { /* See .trans.log */ - EventKind kind; - for (kind = 0; kind < EventKindLIMIT; ++kind) { - AVER(EventLast[kind] == NULL); - EventLast[kind] = EventBuffer[kind] + EventBufferSIZE; - } - eventUserCount = (Count)1; - eventInited = TRUE; - EventKindControl = (Word)mps_lib_telemetry_control(); - EventInternSerial = (Serial)1; /* 0 is reserved */ - (void)EventInternString(MPSVersion()); /* emit version */ - } else { - ++eventUserCount; - } -} - - -/* EventFinish -- stop using the event system */ - -void EventFinish(void) -{ - AVER(eventInited); - AVER(eventUserCount > 0); - - EventSync(); - - --eventUserCount; -} - - -/* EventControl -- Change or read control word - * - * Resets the bits specified in resetMask, and flips those in - * flipMask. Returns old value. - * - * Operations can be implemented as follows: - * Set(M) EventControl(M,M) - * Reset(M) EventControl(M,0) - * Flip(M) EventControl(0,M) - * Read() EventControl(0,0) - * - * TODO: Candy-machine interface is a transgression. - */ - -EventControlSet EventControl(EventControlSet resetMask, - EventControlSet flipMask) -{ - EventControlSet oldValue = EventKindControl; - - /* EventKindControl = (EventKindControl & ~resetMask) ^ flipMask */ - EventKindControl = - BS_SYM_DIFF(BS_DIFF(EventKindControl, resetMask), flipMask); - - return oldValue; -} - - -/* EventInternString -- emit an Intern event on the (null-term) string given */ - -EventStringId EventInternString(const char *label) -{ - AVER(label != NULL); - return EventInternGenString(StringLength(label), label); -} - - -/* EventInternGenString -- emit an Intern event on the string given */ - -EventStringId EventInternGenString(size_t len, const char *label) -{ - EventStringId id; - - AVER(label != NULL); - - id = EventInternSerial; - ++EventInternSerial; - - EVENT2S(Intern, id, len, label); - - return id; -} - - -/* EventLabelAddr -- emit event to label address with the given id */ - -void EventLabelAddr(Addr addr, EventStringId id) -{ - AVER((Serial)id < EventInternSerial); - - EVENT2(Label, addr, id); -} - - -/* Convert event parameter sort to WriteF arguments */ - -#define EVENT_WRITE_PARAM_MOST(name, index, sort, ident) \ - " $"#sort, (WriteF##sort)event->name.f##index, -#define EVENT_WRITE_PARAM_A EVENT_WRITE_PARAM_MOST -#define EVENT_WRITE_PARAM_P EVENT_WRITE_PARAM_MOST -#define EVENT_WRITE_PARAM_U EVENT_WRITE_PARAM_MOST -#define EVENT_WRITE_PARAM_W EVENT_WRITE_PARAM_MOST -#define EVENT_WRITE_PARAM_D EVENT_WRITE_PARAM_MOST -#define EVENT_WRITE_PARAM_S EVENT_WRITE_PARAM_MOST -#define EVENT_WRITE_PARAM_B(name, index, sort, ident) \ - " $U", (WriteFU)event->name.f##index, - - -Res EventDescribe(Event event, mps_lib_FILE *stream) -{ - Res res; - - /* TODO: Some sort of EventCheck would be good */ - if (event == NULL) - return ResFAIL; - if (stream == NULL) - return ResFAIL; - - res = WriteF(stream, - "Event $P {\n", (WriteFP)event, - " code $U\n", (WriteFU)event->any.code, - " clock ", NULL); - if (res != ResOK) return res; - res = EVENT_CLOCK_WRITE(stream, event->any.clock); - if (res != ResOK) return res; - res = WriteF(stream, "\n size $U\n", (WriteFU)event->any.size, NULL); - if (res != ResOK) return res; - - switch (event->any.code) { - -#define EVENT_DESC_PARAM(name, index, sort, ident) \ - "\n $S", (WriteFS)#ident, \ - EVENT_WRITE_PARAM_##sort(name, index, sort, ident) - -#define EVENT_DESC(X, name, _code, always, kind) \ - case _code: \ - res = WriteF(stream, \ - " event \"$S\"", (WriteFS)#name, \ - EVENT_##name##_PARAMS(EVENT_DESC_PARAM, name) \ - NULL); \ - if (res != ResOK) return res; \ - break; - - EVENT_LIST(EVENT_DESC, X) - - default: - res = WriteF(stream, " event type unknown", NULL); - if (res != ResOK) return res; - /* TODO: Hexdump unknown event contents. */ - break; - } - - res = WriteF(stream, - "\n} Event $P\n", (WriteFP)event, - NULL); - return res; -} - - -Res EventWrite(Event event, mps_lib_FILE *stream) -{ - Res res; - - if (event == NULL) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = EVENT_CLOCK_WRITE(stream, event->any.clock); - if (res != ResOK) - return res; - - switch (event->any.code) { - -#define EVENT_WRITE_PARAM(name, index, sort, ident) \ - EVENT_WRITE_PARAM_##sort(name, index, sort, ident) - -#define EVENT_WRITE(X, name, code, always, kind) \ - case code: \ - res = WriteF(stream, " $S", #name, \ - EVENT_##name##_PARAMS(EVENT_WRITE_PARAM, name) \ - NULL); \ - if (res != ResOK) return res; \ - break; - EVENT_LIST(EVENT_WRITE, X) - - default: - res = WriteF(stream, " ", event->any.code, NULL); - if (res != ResOK) return res; - /* TODO: Hexdump unknown event contents. */ - break; - } - - return ResOK; -} - - -void EventDump(mps_lib_FILE *stream) -{ - Event event; - EventKind kind; - - AVER(stream != NULL); - - for (kind = 0; kind < EventKindLIMIT; ++kind) { - for (event = (Event)EventLast[kind]; - event < (Event)(EventBuffer[kind] + EventBufferSIZE); - event = (Event)((char *)event + event->any.size)) { - /* Try to keep going even if there's an error, because this is used as a - backtrace and we'll take what we can get. */ - (void)EventWrite(event, stream); - (void)WriteF(stream, "\n", NULL); - } - } -} - - -#else /* EVENT, not */ - - -void EventSync(void) -{ - NOOP; -} - - -void EventInit(void) -{ - NOOP; -} - - -void EventFinish(void) -{ - NOOP; -} - - -EventControlSet EventControl(EventControlSet resetMask, - EventControlSet flipMask) -{ - UNUSED(resetMask); - UNUSED(flipMask); - return BS_EMPTY(EventControlSet); -} - - -EventStringId EventInternString(const char *label) -{ - UNUSED(label); - /* EventInternString is reached in varieties without events, but the result - is not used for anything. */ - return (EventStringId)0x9024EAC8; -} - - -Word EventInternGenString(size_t len, const char *label) -{ - UNUSED(len); UNUSED(label); - /* EventInternGenString is reached in varieties without events, but - the result is not used for anything. */ - return (EventStringId)0x9024EAC8; -} - - -void EventLabelAddr(Addr addr, Word id) -{ - UNUSED(addr); - UNUSED(id); - /* EventLabelAddr is reached in varieties without events, but doesn't have - to do anything. */ -} - - -Res EventDescribe(Event event, mps_lib_FILE *stream) -{ - UNUSED(event); - UNUSED(stream); - return ResUNIMPL; -} - - -Res EventWrite(Event event, mps_lib_FILE *stream) -{ - UNUSED(event); - UNUSED(stream); - return ResUNIMPL; -} - - -extern void EventDump(mps_lib_FILE *stream) -{ - UNUSED(stream); -} - - -#endif /* EVENT */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/event.h b/mps/code/event.h deleted file mode 100644 index 590b11978ae..00000000000 --- a/mps/code/event.h +++ /dev/null @@ -1,184 +0,0 @@ -/* -- Event Logging Interface - * - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * $Id$ - * - * READERSHIP - * - * .readership: MPS developers. - * - * DESIGN - * - * .design: . - */ - -#ifndef event_h -#define event_h - -#include "eventcom.h" -#include "mpm.h" -#include "eventdef.h" -#include "mpslib.h" - - -typedef Word EventStringId; -typedef Word EventControlSet; - -extern void EventSync(void); -extern void EventInit(void); -extern void EventFinish(void); -extern EventControlSet EventControl(EventControlSet resetMask, - EventControlSet flipMask); -extern EventStringId EventInternString(const char *label); -extern EventStringId EventInternGenString(size_t, const char *label); -extern void EventLabelAddr(Addr addr, Word id); -extern Res EventFlush(EventKind kind); -extern Res EventDescribe(Event event, mps_lib_FILE *stream); -extern Res EventWrite(Event event, mps_lib_FILE *stream); -extern void EventDump(mps_lib_FILE *stream); - - -#ifdef EVENT - -/* Event writing support */ - -extern char EventBuffer[EventKindLIMIT][EventBufferSIZE]; -extern char *EventLast[EventKindLIMIT]; -extern Word EventKindControl; - - -/* Events are written into the buffer from the top down, so that a backtrace - can find them all starting at EventLast. */ - -#define EVENT_BEGIN(name, structSize) \ - BEGIN \ - if(EVENT_ALL || Event##name##Always) { /* see config.h */ \ - Event##name##Struct *_event; \ - size_t _size = size_tAlignUp(structSize, MPS_PF_ALIGN); \ - if (_size > (size_t)(EventLast[Event##name##Kind] \ - - EventBuffer[Event##name##Kind])) \ - EventFlush(Event##name##Kind); \ - AVER(_size <= (size_t)(EventLast[Event##name##Kind] \ - - EventBuffer[Event##name##Kind])); \ - _event = (void *)(EventLast[Event##name##Kind] - _size); \ - _event->code = Event##name##Code; \ - _event->size = (EventSize)_size; \ - EVENT_CLOCK(_event->clock); - -#define EVENT_END(name, size) \ - EventLast[Event##name##Kind] -= _size; \ - } \ - END - - -/* EVENTn -- event emitting macros - * - * The macros EVENT0, EVENT1, etc. are used throughout the MPS to emit an - * event with parameters. They work by appending the event parameters to - * an event buffer, which is flushed to the telemetry output stream when - * full. EVENT2S is a special case that takes a variable length string. - */ - -#define EVENT2S(name, p0, length, string) \ - BEGIN \ - size_t _string_len = (length); \ - size_t size; \ - AVER(_string_len <= EventStringLengthMAX); \ - size = offsetof(Event##name##Struct, f1) + _string_len + sizeof('\0'); \ - EVENT_BEGIN(name, size) \ - _event->f0 = (p0); \ - mps_lib_memcpy(_event->f1, (string), _string_len); \ - _event->f1[_string_len] = '\0'; \ - EVENT_END(name, size); \ - END - - -#define EVENT0(name) EVENT_BEGIN(name, sizeof(EventAnyStruct)) EVENT_END(name, sizeof(EventAnyStruct)) -/* The following lines were generated with - python -c 'for i in range(1,15): print "#define EVENT%d(name, %s) EVENT_BEGIN(name, sizeof(Event##name##Struct)) %s EVENT_END(name, sizeof(Event##name##Struct))" % (i, ", ".join(["p%d" % j for j in range(0, i)]), " ".join(["_event->f%d = (p%d);" % (j, j) for j in range(0, i)]))' - */ -#define EVENT1(name, p0) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT2(name, p0, p1) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT3(name, p0, p1, p2) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT4(name, p0, p1, p2, p3) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT5(name, p0, p1, p2, p3, p4) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT6(name, p0, p1, p2, p3, p4, p5) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT7(name, p0, p1, p2, p3, p4, p5, p6) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT8(name, p0, p1, p2, p3, p4, p5, p6, p7) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT11(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); _event->f10 = (p10); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT12(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); _event->f10 = (p10); _event->f11 = (p11); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT13(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); _event->f10 = (p10); _event->f11 = (p11); _event->f12 = (p12); EVENT_END(name, sizeof(Event##name##Struct)) -#define EVENT14(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); _event->f10 = (p10); _event->f11 = (p11); _event->f12 = (p12); _event->f13 = (p13); EVENT_END(name, sizeof(Event##name##Struct)) - - -#else /* EVENT not */ - - -#define EVENT0(name) NOOP -/* The following lines were generated with - python -c 'for i in range(1,15): print "#define EVENT%d(name, %s) NOOP" % (i, ", ".join(["p%d" % j for j in range(0, i)]))' - */ -#define EVENT1(name, p0) NOOP -#define EVENT2(name, p0, p1) NOOP -#define EVENT3(name, p0, p1, p2) NOOP -#define EVENT4(name, p0, p1, p2, p3) NOOP -#define EVENT5(name, p0, p1, p2, p3, p4) NOOP -#define EVENT6(name, p0, p1, p2, p3, p4, p5) NOOP -#define EVENT7(name, p0, p1, p2, p3, p4, p5, p6) NOOP -#define EVENT8(name, p0, p1, p2, p3, p4, p5, p6, p7) NOOP -#define EVENT9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8) NOOP -#define EVENT10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) NOOP -#define EVENT11(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) NOOP -#define EVENT12(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) NOOP -#define EVENT13(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) NOOP -#define EVENT14(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) NOOP - - -#endif /* EVENT */ - - -#endif /* event_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/eventcnv.c b/mps/code/eventcnv.c deleted file mode 100644 index fcd569add74..00000000000 --- a/mps/code/eventcnv.c +++ /dev/null @@ -1,728 +0,0 @@ -/* eventcnv.c: Simple event log converter - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This is a command-line tool that converts a binary format telemetry output - * stream from the MPS into several textual formats. - * - * The default MPS library will write a telemetry stream to a file called - * "mpsio.log" when the environment variable MPS_TELEMETRY_CONTROL is set - * to an integer whose bits select event kinds. For example: - * - * MPS_TELEMETRY_CONTROL=7 amcss - * - * will run the amcss test program and emit a file with event kinds 0, 1, 2. - * The file can then be converted into text format with a command like: - * - * eventcnv -v | sort - * - * Note that the eventcnv program can only read streams that come from an - * MPS compiled on the same platform. - * - * $Id$ - */ - -#include "config.h" - -#include "eventdef.h" -#include "eventcom.h" -#include "eventpro.h" -#include "mpmtypes.h" -#include "testlib.h" /* for ulongest_t and associated print formats */ - -#include /* for size_t */ -#include /* for printf */ -#include /* for va_list */ -#include /* for EXIT_FAILURE */ -#include /* for assert */ -#include /* for strcmp */ -#include /* for sqrt */ -#include "mpstd.h" - -#ifdef MPS_BUILD_MV -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: strncpy, sscanf, fopen. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - - - -typedef unsigned int uint; -typedef unsigned long ulong; - - -static EventClock eventTime; /* current event time */ - - -/* event counters */ - -typedef unsigned long eventCountArray[EventCodeMAX+1]; -static unsigned long bucketEventCount[EventCodeMAX+1]; -static unsigned long totalEventCount[EventCodeMAX+1]; - - -static char *prog; /* program name */ - - -/* command-line arguments */ - -static Bool verbose = FALSE; -/* style: '\0' for human-readable, 'L' for Lisp, 'C' for CDF. */ -static char style = '\0'; -static Bool reportStats = FALSE; -static Bool eventEnabled[EventCodeMAX+1]; -static Word bucketSize = 0; - - -/* everror -- error signalling */ - -static void everror(const char *format, ...) -{ - va_list args; - - fflush(stdout); /* sync */ - fprintf(stderr, "%s: @", prog); - EVENT_CLOCK_PRINT(stderr, eventTime); - va_start(args, format); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - va_end(args); - exit(EXIT_FAILURE); -} - - -/* usage -- usage message */ - -static void usage(void) -{ - fprintf(stderr, - "Usage: %s [-f logfile] [-p] [-v] [-e events] [-b size]" - " [-S[LC]] [-?]\nSee guide.mps.telemetry for instructions.\n", - prog); -} - - -/* usageError -- explain usage and error */ - -static void usageError(void) -{ - usage(); - everror("Bad usage"); -} - - -/* parseEventSpec -- parses an event spec - * - * The spec is of the form: [(+|-)]... - * The first name can be 'all'. - */ - -static void parseEventSpec(const char *arg) -{ - size_t arglen; - EventCode i; - const char *end; - char name[EventNameMAX+1]; - Bool enabled = TRUE; - - end = arg + strlen(arg); - for(i = 0; i <= EventCodeMAX; ++i) - eventEnabled[i] = FALSE; - do { - arglen = strcspn(arg, "+-"); - strncpy(name, arg, arglen); name[arglen] = '\0'; - if (strcmp(name, "all") == 0) { - for(i = 0; i <= EventCodeMAX; ++i) - eventEnabled[i] = EventCodeIsValid(i); - } else - eventEnabled[EventName2Code(name)] = enabled; - enabled = (arg[arglen] == '+'); arg += arglen + 1; - } while (arg < end); -} - - -/* parseArgs -- parse command line arguments, return log file name */ - -static char *parseArgs(int argc, char *argv[]) -{ - char *name = "mpsio.log"; - int i = 1; - - if (argc >= 1) - prog = argv[0]; - else - prog = "unknown"; - - while (i < argc) { /* consider argument i */ - if (argv[i][0] == '-') { /* it's an option argument */ - switch (argv[i][1]) { - case 'f': /* file name */ - ++ i; - if (i == argc) - usageError(); - else - name = argv[i]; - break; - case 'v': /* verbosity */ - verbose = TRUE; - break; - case 'e': { /* event statistics */ - reportStats = TRUE; - ++ i; - if (i == argc) - usageError(); - else - parseEventSpec(argv[i]); - } break; - case 'b': { /* bucket size */ - ++ i; - if (i == argc) - usageError(); - else { - int n; - - n = sscanf(argv[i], "%lu", &bucketSize); - if (n != 1) usageError(); - } - } break; - case 'S': /* style */ - style = argv[i][2]; /* '\0' for human-readable, 'L' for Lisp, */ - break; /* 'C' for CDF. */ - case '?': case 'h': /* help */ - usage(); - break; - default: - usageError(); - } - } /* if option */ - ++ i; - } - return name; -} - - -/* recordEvent -- record event - * - * This is the beginning of a system to model MPS state as events are read, - * but for the moment it just records which strings have been interned - * and which addresses have been labelled with them. - * - * NOTE: Since branch/2012-08-21/diagnostic-telemetry events are no longer - * in order in the event stream, so eventcnv would need some serious - * rethinking to model state. It's questionable that it should attempt it - * or event try to label addresses, but instead leave that to later stages of - * processing. RB 2012-09-07 - */ - -static void recordEvent(EventProc proc, Event event, EventClock etime) -{ - Res res; - - res = EventRecord(proc, event, etime); - if (res != ResOK) - everror("Can't record event: error %d.", res); - switch(event->any.code) { - default: - break; - } -} - - -/* Printing routines */ - - -/* printStr -- print an EventString */ - -static void printStr(const char *str, Bool quotes) -{ - size_t i; - - if (quotes) putchar('"'); - for (i = 0; str[i] != '\0'; ++i) { - char c = str[i]; - if (quotes && (c == '"' || c == '\\')) putchar('\\'); - putchar(c); - } - if (quotes) putchar('"'); -} - - -/* printAddr -- print an Addr or its label */ - -static void printAddr(EventProc proc, Addr addr) -{ - Word label; - - label = AddrLabel(proc, addr); - if (label != 0 && addr != 0) { - /* We assume labelling zero is meant to record a point in time */ - const char *sym = LabelText(proc, label); - if (sym != NULL) { - putchar(' '); - printStr(sym, (style == 'C')); - } else { - printf((style == '\0') ? - " sym%05"PRIXLONGEST : - " \"sym %"PRIXLONGEST"\"", - (ulongest_t)label); - } - } else - printf(style != 'C' ? - " %0"PRIwWORD PRIXLONGEST : - " %"PRIuLONGEST, - (ulongest_t)addr); -} - - -/* reportEventResults -- report event counts from a count array */ - -static void reportEventResults(eventCountArray eventCounts) -{ - EventCode i; - unsigned long total = 0; - - for(i = 0; i <= EventCodeMAX; ++i) { - total += eventCounts[i]; - if (eventEnabled[i]) - switch (style) { - case '\0': - printf(" %5lu", eventCounts[i]); - break; - case 'L': - printf(" %lX", eventCounts[i]); - break; - case 'C': - printf(", %lu", eventCounts[i]); - break; - } - } - switch (style) { - case '\0': - printf(" %5lu\n", total); - break; - case 'L': - printf(" %lX)\n", total); - break; - case 'C': - printf(", %lu\n", total); - break; - } -} - - -/* reportBucketResults -- report results of the current bucket */ - -static void reportBucketResults(EventClock bucketLimit) -{ - switch (style) { - case '\0': - EVENT_CLOCK_PRINT(stdout, bucketLimit); - putchar(':'); - break; - case 'L': - putchar('('); - EVENT_CLOCK_PRINT(stdout, bucketLimit); - break; - case 'C': - EVENT_CLOCK_PRINT(stdout, bucketLimit); - break; - } - if (reportStats) { - reportEventResults(bucketEventCount); - } -} - - -/* clearBucket -- clear bucket */ - -static void clearBucket(void) -{ - EventCode i; - - for(i = 0; i <= EventCodeMAX; ++i) - bucketEventCount[i] = 0; -} - - -/* printParam* -- printing functions for event parameter types */ - -static void printParamA(EventProc proc, char *styleConv, Addr addr) -{ - if (style != 'L') { - if (style == 'C') putchar(','); - printAddr(proc, addr); - } else - printf(styleConv, (ulongest_t)addr); -} - -static void printParamP(EventProc proc, char *styleConv, void *p) -{ - UNUSED(proc); - printf(styleConv, (ulongest_t)p); -} - -static void printParamU(EventProc proc, char *styleConv, unsigned u) -{ - UNUSED(proc); - printf(styleConv, (ulongest_t)u); -} - -static void printParamW(EventProc proc, char *styleConv, Word w) -{ - UNUSED(proc); - printf(styleConv, (ulongest_t)w); -} - -static void printParamD(EventProc proc, char *styleConv, double d) -{ - UNUSED(proc); - UNUSED(styleConv); - switch (style) { - case '\0': - printf(" %#8.3g", d); break; - case 'C': - printf(", %.10G", d); break; - case 'L': - printf(" %#.10G", d); break; - } -} - -static void printParamS(EventProc proc, char *styleConv, const char *s) -{ - UNUSED(proc); - UNUSED(styleConv); - if (style == 'C') putchar(','); - putchar(' '); - printStr(s, (style == 'C' || style == 'L')); -} - -static void printParamB(EventProc proc, char *styleConv, Bool b) -{ - UNUSED(proc); - UNUSED(proc); - printf(styleConv, (ulongest_t)b); -} - - -/* readLog -- read and parse log - * - * This is the heart of eventcnv: It reads an event log using EventRead. - * It updates the counters. If verbose is true, it looks up the format, - * parses the arguments, and prints a representation of the event. Each - * argument is printed using printArg (see RELATION, below), except for - * some event types that are handled specially. - */ - -static void readLog(EventProc proc) -{ - EventCode c; - Word bucketLimit = bucketSize; - char *styleConv = NULL; /* suppress uninit warning */ - - /* Print event count header. */ - if (reportStats) { - if (style == '\0') { - printf(" bucket:"); - for(c = 0; c <= EventCodeMAX; ++c) - if (eventEnabled[c]) - printf(" %04X", (unsigned)c); - printf(" all\n"); - } - } - - /* Init event counts. */ - for(c = 0; c <= EventCodeMAX; ++c) - totalEventCount[c] = 0; - clearBucket(); - - /* Init style. */ - switch (style) { - case '\0': - styleConv = " %8"PRIXLONGEST; break; - case 'C': - styleConv = ", %"PRIuLONGEST; break; - case 'L': - styleConv = " %"PRIXLONGEST; break; - default: - everror("Unknown style code '%c'", style); - } - - while (TRUE) { /* loop for each event */ - Event event; - EventCode code; - Res res; - - /* Read and parse event. */ - res = EventRead(&event, proc); - if (res == ResFAIL) break; /* eof */ - if (res != ResOK) everror("Truncated log"); - eventTime = event->any.clock; - code = event->any.code; - - /* Output bucket, if necessary, and update counters */ - if (bucketSize != 0 && eventTime >= bucketLimit) { - reportBucketResults(bucketLimit-1); - clearBucket(); - do { - bucketLimit += bucketSize; - } while (eventTime >= bucketLimit); - } - if (reportStats) { - ++bucketEventCount[code]; - ++totalEventCount[code]; - } - - /* Output event. */ - if (verbose) { - if (style == 'L') putchar('('); - - switch (style) { - case '\0': case 'L': - EVENT_CLOCK_PRINT(stdout, eventTime); - putchar(' '); - break; - case 'C': - EVENT_CLOCK_PRINT(stdout, eventTime); - fputs(", ", stdout); - break; - } - - switch (style) { - case '\0': case 'L': { - printf("%-19s ", EventCode2Name(code)); - } break; - case 'C': - printf("%u", (unsigned)code); - break; - } - - switch (code) { - - case EventLabelCode: - switch (style) { - case '\0': case 'C': - { - const char *sym = LabelText(proc, event->Label.f1); - printf(style == '\0' ? - " %08"PRIXLONGEST" " : - ", %"PRIuLONGEST", ", - (ulongest_t)event->Label.f0); - if (sym != NULL) { - printStr(sym, (style == 'C')); - } else { - printf(style == '\0' ? - "sym %05"PRIXLONGEST : - "sym %"PRIXLONGEST"\"", - (ulongest_t)event->Label.f1); - } - } - break; - case 'L': - printf(" %"PRIXLONGEST" %"PRIXLONGEST, - (ulongest_t)event->Label.f0, - (ulongest_t)event->Label.f1); - break; - } - break; - - case EventMeterValuesCode: - switch (style) { - case '\0': - if (event->MeterValues.f3 == 0) { - printf(" %08"PRIXLONGEST" 0 N/A N/A N/A N/A", - (ulongest_t)event->MeterValues.f0); - } else { - double mean = event->MeterValues.f1 / (double)event->MeterValues.f3; - /* .stddev: stddev = sqrt(meanSquared - mean^2), but see */ - /* . */ - double stddev = sqrt(fabs(event->MeterValues.f2 - - (mean * mean))); - printf(" %08"PRIXLONGEST" %8u %8u %8u %#8.3g %#8.3g", - (ulongest_t)event->MeterValues.f0, (uint)event->MeterValues.f3, - (uint)event->MeterValues.f4, (uint)event->MeterValues.f5, - mean, stddev); - } - printAddr(proc, (Addr)event->MeterValues.f0); - break; - - case 'C': - putchar(','); - printAddr(proc, (Addr)event->MeterValues.f0); - printf(", %.10G, %.10G, %u, %u, %u", - event->MeterValues.f1, event->MeterValues.f2, - (uint)event->MeterValues.f3, (uint)event->MeterValues.f4, - (uint)event->MeterValues.f5); - break; - - case 'L': - printf(" %"PRIXLONGEST" %#.10G %#.10G %X %X %X", - (ulongest_t)event->MeterValues.f0, - event->MeterValues.f1, event->MeterValues.f2, - (uint)event->MeterValues.f3, (uint)event->MeterValues.f4, - (uint)event->MeterValues.f5); - break; - } - break; - - case EventPoolInitCode: /* pool, arena, class */ - printf(styleConv, (ulongest_t)event->PoolInit.f0); - printf(styleConv, (ulongest_t)event->PoolInit.f1); - /* class is a Pointer, but we label them, so call printAddr */ - if (style != 'L') { - if (style == 'C') putchar(','); - printAddr(proc, (Addr)event->PoolInit.f2); - } else - printf(styleConv, (ulongest_t)event->PoolInit.f2); - break; - - default: -#define EVENT_PARAM_PRINT(name, index, sort, ident) \ - printParam##sort(proc, styleConv, event->name.f##index); -#define EVENT_PRINT(X, name, code, always, kind) \ - case code: \ - EVENT_##name##_PARAMS(EVENT_PARAM_PRINT, name) \ - break; - switch (code) { EVENT_LIST(EVENT_PRINT, X) } - } - - if (style == 'L') putchar(')'); - putchar('\n'); - fflush(stdout); - } - recordEvent(proc, event, eventTime); - EventDestroy(proc, event); - } /* while(!feof(input)) */ - - /* report last bucket (partial) */ - if (bucketSize != 0) { - reportBucketResults(eventTime); - } - if (reportStats) { - /* report totals */ - switch (style) { - case '\0': - printf("\n run:"); - break; - case 'L': - printf("(t"); - break; - case 'C': - { - /* FIXME: This attempted to print the event stats on a row that - resembled a kind of final event, but the event clock no longer runs - monotonically upwards. */ - EventClock last = eventTime + 1; - EVENT_CLOCK_PRINT(stdout, last); - } - break; - } - reportEventResults(totalEventCount); - - /* explain event codes */ - if (style == '\0') { - printf("\n"); - for(c = 0; c <= EventCodeMAX; ++c) - if (eventEnabled[c]) - printf(" %04X %s\n", (unsigned)c, EventCode2Name(c)); - if (bucketSize == 0) - printf("\nevent clock stopped at "); - EVENT_CLOCK_PRINT(stdout, eventTime); - printf("\n"); - } - } -} - - -/* logReader -- reader function for a file log */ - -static FILE *input; - -static Res logReader(void *file, void *p, size_t len) -{ - size_t n; - - n = fread(p, 1, len, (FILE *)file); - return (n < len) ? (feof((FILE *)file) ? ResFAIL : ResIO) : ResOK; -} - - -/* CHECKCONV -- check t2 can be cast to t1 without loss */ - -#define CHECKCONV(t1, t2) \ - (sizeof(t1) >= sizeof(t2)) - - -/* main */ - -int main(int argc, char *argv[]) -{ - char *filename; - EventProc proc; - Res res; - - assert(CHECKCONV(ulongest_t, Word)); - assert(CHECKCONV(ulongest_t, Addr)); - assert(CHECKCONV(ulongest_t, void *)); - assert(CHECKCONV(ulongest_t, EventCode)); - assert(CHECKCONV(Addr, void *)); /* for labelled pointers */ - - filename = parseArgs(argc, argv); - - if (strcmp(filename, "-") == 0) - input = stdin; - else { - input = fopen(filename, "rb"); - if (input == NULL) - everror("unable to open \"%s\"\n", filename); - } - - res = EventProcCreate(&proc, logReader, (void *)input); - if (res != ResOK) - everror("Can't init EventProc module: error %d.", res); - - readLog(proc); - - EventProcDestroy(proc); - return EXIT_SUCCESS; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/eventcom.h b/mps/code/eventcom.h deleted file mode 100644 index 6114b045d48..00000000000 --- a/mps/code/eventcom.h +++ /dev/null @@ -1,173 +0,0 @@ -/* -- Event Logging Common Definitions - * - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * $Id$ - * - * .sources: mps.design.telemetry - */ - -#ifndef eventcom_h -#define eventcom_h - -#include -#include "mpmtypes.h" /* for Word */ -#include "eventdef.h" -#include "clock.h" - - -/* Event Kinds --- see - * - * All events are classified as being of one event type. - * They are small enough to be able to be used as members of a bit set. - */ - -#define EventKindENUM(ENUM, X) \ - ENUM(X, Arena, "Per space or arena") \ - ENUM(X, Pool, "Per pool") \ - ENUM(X, Trace, "Per trace or scan") \ - ENUM(X, Seg, "Per seg") \ - ENUM(X, Ref, "Per ref or fix") \ - ENUM(X, Object, "Per alloc or object") \ - ENUM(X, User, "User-invoked") - -#define ENUM_DECLARE(name) \ - enum name##Enum { \ - name##ENUM(ENUM_DECLARE_ROW, name) \ - name##LIMIT \ - }; - -#define ENUM_DECLARE_ROW(enumName, rowName, rowDoc) \ - enumName##rowName, - -ENUM_DECLARE(EventKind) - - -/* Event type definitions - * - * Various constants for each event type to describe them, so that they - * can easily be looked up from macros by name. - */ - -/* Note that enum values can be up to fifteen bits long portably. */ -#define EVENT_ENUM(X, name, code, always, kind) \ - Event##name##Code = code, \ - Event##name##Always = always, \ - Event##name##Kind = EventKind##kind, - -enum EventDefinitionsEnum { - EVENT_LIST(EVENT_ENUM, X) - EventEnumWarningSuppressor /* suppress comma-at-end-of-enum warning */ -}; - - -/* Event*Struct -- Event Structures - * - * Declare the structures that are used to encode events in the internal event - * buffers and on the binary telemetry output stream. - */ - -/* Types for common event fields */ -typedef unsigned short EventCode; -typedef unsigned EventKind; -typedef unsigned short EventSize; -#define EventSizeMAX USHRT_MAX - -/* Common prefix for all event structures. The size field allows an event - reader to skip over events whose codes it does not recognise. */ -#define EVENT_ANY_FIELDS \ - EventCode code; /* encoding of the event type */ \ - EventSize size; /* allows reader to skip events of unknown code */ \ - EventClock clock; /* when the event occurred */ -typedef struct EventAnyStruct { - EVENT_ANY_FIELDS -} EventAnyStruct; - -/* Event field types, for indexing by macro on the event parameter sort */ -typedef void *EventFP; /* pointer to C object */ -typedef Addr EventFA; /* address on the heap */ -typedef Word EventFW; /* word */ -typedef unsigned EventFU; /* unsigned integer */ -typedef char EventFS[EventStringLengthMAX + sizeof('\0')]; /* string */ -typedef double EventFD; /* double */ -typedef int EventFB; /* boolean */ - -/* Event packing bitfield specifiers */ -#define EventFP_BITFIELD -#define EventFA_BITFIELD -#define EventFW_BITFIELD -#define EventFU_BITFIELD -#define EventFS_BITFIELD -#define EventFD_BITFIELD -#define EventFB_BITFIELD : 1 - -#define EVENT_STRUCT_FIELD(X, index, sort, ident) \ - EventF##sort f##index EventF##sort##_BITFIELD; - -#define EVENT_STRUCT(X, name, _code, always, kind) \ - typedef struct Event##name##Struct { \ - EVENT_ANY_FIELDS \ - EVENT_##name##_PARAMS(EVENT_STRUCT_FIELD, X) \ - } Event##name##Struct; - -EVENT_LIST(EVENT_STRUCT, X) - - -/* Event -- event union type - * - * Event is the type of a pointer to EventUnion, which is a union of all - * event structures. This can be used as the type of any event, decoded - * by examining event->any.code. - */ - -#define EVENT_UNION_MEMBER(X, name, code, always, kind) \ - Event##name##Struct name; - -typedef union EventUnion { - EventAnyStruct any; - EVENT_LIST(EVENT_UNION_MEMBER, X) -} EventUnion, *Event; - - -#endif /* eventcom_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/eventdef.h b/mps/code/eventdef.h deleted file mode 100644 index df80bb6d1c2..00000000000 --- a/mps/code/eventdef.h +++ /dev/null @@ -1,665 +0,0 @@ -/* -- Event Logging Definitions - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .source: - * - * .desc: This file declares macros that define the types of events and their - * properties. - * - * TRANSGRESSIONS - * - * .kind.abuse: A few events have a kind which is not obvious from the - * type of the objects that the event relates to. They are given the - * kind that that have on the grounds of expected use. The kinds are - * used in controlling the overall volume of telemetry and these events are - * given kinds so that they are grouped under the same control as events - * you are likely to want to see them with. (So for example, lots of - * scanner events have the same kind, Seg, because if you are interested - * in one then you're probably interested in them all and it's a similar - * amount of data). - */ - -#ifndef eventdef_h -#define eventdef_h - - -/* EVENT_VERSION_* -- three part version number - * - * Increment the minor version when adding new events, - * the median version when changing an existing event, - * and the major version when changing the format of the event file. - * - * TODO: These should go into a header that appears at the start of a - * telemetry stream, but they aren't currently used. Keep updating them - * anyway. RB 2012-09-07 - */ - -#define EVENT_VERSION_MAJOR ((unsigned)1) -#define EVENT_VERSION_MEDIAN ((unsigned)0) -#define EVENT_VERSION_MINOR ((unsigned)0) - - -/* EVENT_LIST -- list of event types and general properties - * - * These specify: - * - Type: The name of the event type, without the leading "Event"; - * - Code: The unique 16-bit code associated with this event type; - * - Always: Whether this event type should appear in "hot" varieties, - * - Kind: Category into which this event falls, without the - * leading "EventKind"; - * - * When you retire an event type, don't delete it from the list -- comment - * it out. This serves as documentation for what the event code means - * in older logs, and prevents the codes being re-used. See - * . - * - * TODO: Rather than commenting them out, we should leave them in and mark - * them in some other way, because this header is used by event decoders and - * they still want to decode those events. RB 2012-09-07 - * - * When you add an event type, you must also add an EVENT_*_PARAMS macro - * specify its parameters below. - * - * TODO: Add a doc string to each event type. - * - * See also EVENT_*_PARAMS for definition of event parameters. - */ - -#define EventNameMAX ((size_t)19) -#define EventCodeMAX ((EventCode)0x0073) - -#define EVENT_LIST(EVENT, X) \ - /* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \ - EVENT(X, AMCGenCreate , 0x0001, TRUE, Pool) \ - EVENT(X, AMCGenDestroy , 0x0002, TRUE, Pool) \ - EVENT(X, AMCInit , 0x0003, TRUE, Pool) \ - EVENT(X, AMCFinish , 0x0004, TRUE, Pool) \ - EVENT(X, ArenaCreateVM , 0x0005, TRUE, Arena) \ - EVENT(X, ArenaCreateVMNZ , 0x0006, TRUE, Arena) \ - EVENT(X, ArenaWriteFaults , 0x0007, TRUE, Trace) \ - EVENT(X, MeterInit , 0x0008, TRUE, Pool) \ - EVENT(X, MeterValues , 0x0009, TRUE, Pool) \ - EVENT(X, AMCScanBegin , 0x000a, TRUE, Seg) \ - EVENT(X, AMCScanEnd , 0x000b, TRUE, Seg) \ - EVENT(X, AMCFix , 0x000c, FALSE, Ref) \ - EVENT(X, AMCFixInPlace , 0x000d, FALSE, Ref) \ - EVENT(X, AMCFixForward , 0x000e, FALSE, Ref) \ - EVENT(X, AMCReclaim , 0x000f, TRUE, Seg) \ - /* EVENT(X, AMCTraceEnd , 0x0010, TRUE, Trace) */ \ - EVENT(X, ArenaCreateCL , 0x0011, TRUE, Arena) \ - EVENT(X, ArenaDestroy , 0x0012, TRUE, Arena) \ - EVENT(X, SegAlloc , 0x0013, TRUE, Seg) \ - EVENT(X, SegFree , 0x0014, TRUE, Seg) \ - EVENT(X, PoolInit , 0x0015, TRUE, Pool) \ - EVENT(X, PoolFinish , 0x0016, TRUE, Pool) \ - EVENT(X, PoolAlloc , 0x0017, TRUE, Object) \ - EVENT(X, PoolFree , 0x0018, TRUE, Object) \ - EVENT(X, CBSInit , 0x0019, TRUE, Pool) \ - EVENT(X, Intern , 0x001a, TRUE, User) \ - EVENT(X, Label , 0x001b, TRUE, User) \ - /* EVENT(X, TraceStart , 0x001c, TRUE, Trace) */ \ - /* EVENT(X, TraceCreate , 0x001d, TRUE, Trace) */ \ - EVENT(X, TraceDestroy , 0x001e, TRUE, Trace) \ - EVENT(X, SegSetGrey , 0x001f, TRUE, Seg) \ - EVENT(X, TraceFlipBegin , 0x0020, TRUE, Trace) \ - EVENT(X, TraceFlipEnd , 0x0021, TRUE, Trace) \ - EVENT(X, TraceReclaim , 0x0022, TRUE, Seg) \ - /* EVENT(X, TraceScan , 0x0023, TRUE, Seg) */ \ - EVENT(X, TraceAccess , 0x0024, TRUE, Seg) \ - /* TracePoll's kind isn't really Trace, but then it isn't Seg either */ \ - /* EVENT(X, TracePoll , 0x0025, TRUE, Trace) */ \ - EVENT(X, TraceFix , 0x0026, FALSE, Ref) \ - EVENT(X, TraceFixSeg , 0x0027, FALSE, Ref) \ - EVENT(X, TraceFixWhite , 0x0028, FALSE, Ref) \ - /* TraceScanArea{Tagged} abuses kind, see .kind.abuse */ \ - EVENT(X, TraceScanArea , 0x0029, TRUE, Seg) \ - EVENT(X, TraceScanAreaTagged, 0x002a, TRUE, Seg) \ - EVENT(X, VMCreate , 0x002b, TRUE, Arena) \ - EVENT(X, VMDestroy , 0x002c, TRUE, Arena) \ - EVENT(X, VMMap , 0x002d, TRUE, Seg) \ - EVENT(X, VMUnmap , 0x002e, TRUE, Seg) \ - EVENT(X, ArenaExtend , 0x002f, TRUE, Arena) \ - /* EVENT(X, ArenaRetract , 0x0030, TRUE, Arena) */ \ - /* EVENT(X, TraceSegGreyen , 0x0031, TRUE, Seg) */ \ - /* RootScan abuses kind, see .kind.abuse */ \ - EVENT(X, RootScan , 0x0032, TRUE, Seg) \ - /* TraceStep abuses kind, see .kind.abuse */ \ - /* EVENT(X, TraceStep , 0x0033, TRUE, Seg) */ \ - EVENT(X, BufferReserve , 0x0034, TRUE, Object) \ - EVENT(X, BufferCommit , 0x0035, TRUE, Object) \ - /* BufferInit/Finish abuse kind, see .kind.abuse */ \ - EVENT(X, BufferInit , 0x0036, TRUE, Pool) \ - EVENT(X, BufferFinish , 0x0037, TRUE, Pool) \ - /* EVENT(X, MVTFinish , 0x0038, TRUE, Pool) */ \ - EVENT(X, BufferFill , 0x0039, TRUE, Seg) \ - EVENT(X, BufferEmpty , 0x003A, TRUE, Seg) \ - EVENT(X, SegAllocFail , 0x003B, TRUE, Seg) \ - EVENT(X, TraceScanSeg , 0x003C, TRUE, Seg) \ - /* TraceScanSingleRef abuses kind, see .kind.abuse */ \ - EVENT(X, TraceScanSingleRef , 0x003D, TRUE, Seg) \ - EVENT(X, TraceStatCondemn , 0x003E, TRUE, Trace) \ - EVENT(X, TraceStatScan , 0x003F, TRUE, Trace) \ - EVENT(X, TraceStatFix , 0x0040, TRUE, Trace) \ - EVENT(X, TraceStatReclaim , 0x0041, TRUE, Trace) \ - EVENT(X, PoolInitMVFF , 0x0042, TRUE, Pool) \ - EVENT(X, PoolInitMV , 0x0043, TRUE, Pool) \ - EVENT(X, PoolInitMFS , 0x0044, TRUE, Pool) \ - /* EVENT(X, PoolInitEPVM , 0x0045, TRUE, Pool) */ \ - /* EVENT(X, PoolInitEPDL , 0x0046, TRUE, Pool) */ \ - EVENT(X, PoolInitAMS , 0x0047, TRUE, Pool) \ - EVENT(X, PoolInitAMC , 0x0048, TRUE, Pool) \ - EVENT(X, PoolInitAMCZ , 0x0049, TRUE, Pool) \ - EVENT(X, PoolInitAWL , 0x004A, TRUE, Pool) \ - EVENT(X, PoolInitLO , 0x004B, TRUE, Pool) \ - EVENT(X, PoolInitSNC , 0x004C, TRUE, Pool) \ - EVENT(X, PoolInitMVT , 0x004D, TRUE, Pool) \ - /* EVENT(X, BufferInitEPVM , 0x0050, TRUE, Pool) */ \ - EVENT(X, BufferInitSeg , 0x0051, TRUE, Pool) \ - EVENT(X, BufferInitRank , 0x0052, TRUE, Pool) \ - /* PoolPush/Pop go under Object, because they're user ops. */ \ - /* EVENT(X, PoolPush , 0x0060, TRUE, Object) */ \ - /* EVENT(X, PoolPop , 0x0061, TRUE, Object) */ \ - EVENT(X, ReservoirLimitSet , 0x0062, TRUE, Arena) \ - EVENT(X, CommitLimitSet , 0x0063, TRUE, Arena) \ - EVENT(X, SpareCommitLimitSet, 0x0064, TRUE, Arena) \ - EVENT(X, ArenaAlloc , 0x0065, TRUE, Arena) \ - EVENT(X, ArenaFree , 0x0066, TRUE, Arena) \ - EVENT(X, ArenaAllocFail , 0x0067, TRUE, Arena) \ - EVENT(X, SegMerge , 0x0068, TRUE, Seg) \ - EVENT(X, SegSplit , 0x0069, TRUE, Seg) \ - /* Events converted from RHSK's diagnostics */ \ - EVENT(X, vmArenaExtendStart , 0x006A, TRUE, Arena) \ - EVENT(X, vmArenaExtendFail , 0x006B, TRUE, Arena) \ - EVENT(X, vmArenaExtendDone , 0x006C, TRUE, Arena) \ - EVENT(X, MessagesDropped , 0x006D, TRUE, Arena) \ - EVENT(X, MessagesExist , 0x006E, TRUE, Arena) \ - EVENT(X, ChainCondemnAuto , 0x006F, TRUE, Trace) \ - EVENT(X, TraceFindGrey , 0x0070, TRUE, Trace) \ - EVENT(X, TraceBandAdvance , 0x0071, TRUE, Trace) \ - EVENT(X, AWLDeclineTotal , 0x0072, TRUE, Trace) \ - EVENT(X, AWLDeclineSeg , 0x0073, TRUE, Trace) - - -/* Remember to update EventNameMAX and EventCodeMAX in eventcom.h! - (These are checked in EventInit.) */ - - -/* EVENT_*_PARAMS -- definition of event parameters - * - * For each event type in EVENT_LIST, these macros list the parameters of - * the event. THe columns are: - * - the positional index of the parameter in the list, used to define - * numeric field names using the C preprocessor - * - the parameter sort, similar to writef (Pointer, Addr, Word, Unsigned, - * String, Double, Bool) - * - a parameter identifier for display or use in code - * - * TODO: Add a doc string to each parameter. - */ - -#define EVENT_AMCGenCreate_PARAMS(PARAM, X) \ - PARAM(X, 0, P, amc) \ - PARAM(X, 1, P, gen) - -#define EVENT_AMCGenDestroy_PARAMS(PARAM, X) \ - PARAM(X, 0, P, gen) - -#define EVENT_AMCInit_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, amc) - -#define EVENT_AMCFinish_PARAMS(PARAM, X) \ - PARAM(X, 0, P, amc) - -#define EVENT_AMCFix_PARAMS(PARAM, X) - -#define EVENT_ArenaCreateVM_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, userSize) \ - PARAM(X, 2, W, chunkSize) - -#define EVENT_ArenaCreateVMNZ_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, userSize) \ - PARAM(X, 2, W, chunkSize) - -#define EVENT_ArenaWriteFaults_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, writeBarrierHitCount) - -#define EVENT_MeterInit_PARAMS(PARAM, X) \ - PARAM(X, 0, P, meter) \ - PARAM(X, 1, P, owner) - -#define EVENT_MeterValues_PARAMS(PARAM, X) \ - PARAM(X, 0, P, meter) \ - PARAM(X, 1, D, total) \ - PARAM(X, 2, D, meanSquared) \ - PARAM(X, 3, W, count) \ - PARAM(X, 4, W, max) \ - PARAM(X, 5, W, min) - -#define EVENT_AMCScanBegin_PARAMS(PARAM, X) \ - PARAM(X, 0, P, amc) \ - PARAM(X, 1, P, seg) \ - PARAM(X, 2, P, ss) - -#define EVENT_AMCScanEnd_PARAMS(PARAM, X) \ - PARAM(X, 0, P, amc) \ - PARAM(X, 1, P, seg) \ - PARAM(X, 2, P, ss) - -#define EVENT_AMCFixInPlace_PARAMS(PARAM, X) - -#define EVENT_AMCFixForward_PARAMS(PARAM, X) \ - PARAM(X, 0, A, newRef) - -#define EVENT_AMCReclaim_PARAMS(PARAM, X) \ - PARAM(X, 0, P, gen) \ - PARAM(X, 1, P, trace) \ - PARAM(X, 2, P, seg) - -#define EVENT_ArenaCreateCL_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, size) \ - PARAM(X, 2, A, base) - -#define EVENT_ArenaDestroy_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) - -#define EVENT_SegAlloc_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, P, seg) \ - PARAM(X, 2, A, base) \ - PARAM(X, 3, W, size) \ - PARAM(X, 4, P, pool) - -#define EVENT_SegFree_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, P, seg) - -#define EVENT_PoolInit_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, arena) \ - PARAM(X, 2, P, poolClass) - -#define EVENT_PoolFinish_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) - -#define EVENT_PoolAlloc_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, A, pReturn) \ - PARAM(X, 2, W, size) - -#define EVENT_PoolFree_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, A, old) \ - PARAM(X, 2, W, size) - -#define EVENT_CBSInit_PARAMS(PARAM, X) \ - PARAM(X, 0, P, cbs) \ - PARAM(X, 1, P, owner) - -#define EVENT_Intern_PARAMS(PARAM, X) \ - PARAM(X, 0, W, stringId) \ - PARAM(X, 1, S, string) - -#define EVENT_Label_PARAMS(PARAM, X) \ - PARAM(X, 0, A, address) \ - PARAM(X, 1, W, stringId) - -#define EVENT_TraceDestroy_PARAMS(PARAM, X) \ - PARAM(X, 0, P, trace) - -#define EVENT_SegSetGrey_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, P, seg) \ - PARAM(X, 2, U, grey) - -#define EVENT_TraceFlipBegin_PARAMS(PARAM, X) \ - PARAM(X, 0, P, trace) \ - PARAM(X, 1, P, arena) - -#define EVENT_TraceFlipEnd_PARAMS(PARAM, X) \ - PARAM(X, 0, P, trace) \ - PARAM(X, 1, P, arena) - -#define EVENT_TraceReclaim_PARAMS(PARAM, X) \ - PARAM(X, 0, P, trace) - -#define EVENT_TraceAccess_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, P, seg) \ - PARAM(X, 2, U, mode) - -#define EVENT_TraceFix_PARAMS(PARAM, X) \ - PARAM(X, 0, P, ss) \ - PARAM(X, 1, P, refIO) \ - PARAM(X, 2, A, ref) \ - PARAM(X, 3, U, rank) - -#define EVENT_TraceFixSeg_PARAMS(PARAM, X) \ - PARAM(X, 0, P, seg) - -#define EVENT_TraceFixWhite_PARAMS(PARAM, X) - -#define EVENT_TraceScanArea_PARAMS(PARAM, X) \ - PARAM(X, 0, P, ss) \ - PARAM(X, 1, P, base) \ - PARAM(X, 2, P, limit) - -#define EVENT_TraceScanAreaTagged_PARAMS(PARAM, X) \ - PARAM(X, 0, P, ss) \ - PARAM(X, 1, P, base) \ - PARAM(X, 2, P, limit) - -#define EVENT_VMCreate_PARAMS(PARAM, X) \ - PARAM(X, 0, P, vm) \ - PARAM(X, 1, A, base) \ - PARAM(X, 2, A, limit) - -#define EVENT_VMDestroy_PARAMS(PARAM, X) \ - PARAM(X, 0, P, vm) - -#define EVENT_VMMap_PARAMS(PARAM, X) \ - PARAM(X, 0, P, vm) \ - PARAM(X, 1, A, base) \ - PARAM(X, 2, A, limit) - -#define EVENT_VMUnmap_PARAMS(PARAM, X) \ - PARAM(X, 0, P, vm) \ - PARAM(X, 1, A, base) \ - PARAM(X, 2, A, limit) - -#define EVENT_ArenaExtend_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, A, base) \ - PARAM(X, 2, W, size) - -#define EVENT_RootScan_PARAMS(PARAM, X) \ - PARAM(X, 0, P, root) \ - PARAM(X, 1, W, ts) \ - PARAM(X, 2, W, summary) - -#define EVENT_BufferReserve_PARAMS(PARAM, X) \ - PARAM(X, 0, P, buffer) \ - PARAM(X, 1, A, init) \ - PARAM(X, 2, W, size) - -#define EVENT_BufferCommit_PARAMS(PARAM, X) \ - PARAM(X, 0, P, buffer) \ - PARAM(X, 1, A, p) \ - PARAM(X, 2, W, size) \ - PARAM(X, 3, A, clientClass) - -#define EVENT_BufferInit_PARAMS(PARAM, X) \ - PARAM(X, 0, P, buffer) \ - PARAM(X, 1, P, pool) \ - PARAM(X, 2, B, isMutator) - -#define EVENT_BufferFinish_PARAMS(PARAM, X) \ - PARAM(X, 0, P, buffer) - -#define EVENT_BufferFill_PARAMS(PARAM, X) \ - PARAM(X, 0, P, buffer) \ - PARAM(X, 1, W, size) \ - PARAM(X, 2, A, base) \ - PARAM(X, 3, W, filled) - -#define EVENT_BufferEmpty_PARAMS(PARAM, X) \ - PARAM(X, 0, P, buffer) \ - PARAM(X, 1, W, spare) - -#define EVENT_SegAllocFail_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, size) \ - PARAM(X, 2, P, pool) - -#define EVENT_TraceScanSeg_PARAMS(PARAM, X) \ - PARAM(X, 0, U, ts) \ - PARAM(X, 1, U, rank) \ - PARAM(X, 2, P, arena) \ - PARAM(X, 3, P, seg) - -#define EVENT_TraceScanSingleRef_PARAMS(PARAM, X) \ - PARAM(X, 0, U, ts) \ - PARAM(X, 1, U, rank) \ - PARAM(X, 2, P, arena) \ - PARAM(X, 3, A, refIO) - -#define EVENT_TraceStatCondemn_PARAMS(PARAM, X) \ - PARAM(X, 0, P, trace) \ - PARAM(X, 1, W, condemned) \ - PARAM(X, 2, W, notCondemned) \ - PARAM(X, 3, W, foundation) \ - PARAM(X, 4, W, rate) \ - PARAM(X, 5, D, mortality) \ - PARAM(X, 6, D, finishingTime) - -#define EVENT_TraceStatScan_PARAMS(PARAM, X) \ - PARAM(X, 0, P, trace) \ - PARAM(X, 1, W, rootScanCount) \ - PARAM(X, 2, W, rootScanSize) \ - PARAM(X, 3, W, rootCopiedSize) \ - PARAM(X, 4, W, segScanCount) \ - PARAM(X, 5, W, segScanSize) \ - PARAM(X, 6, W, segCopiedSize) \ - PARAM(X, 7, W, singleScanCount) \ - PARAM(X, 8, W, singleScanSize) \ - PARAM(X, 9, W, singleCopiedSize) \ - PARAM(X, 10, W, readBarrierHitCount) \ - PARAM(X, 11, W, greySegMax) \ - PARAM(X, 12, W, pointlessScanCount) - -#define EVENT_TraceStatFix_PARAMS(PARAM, X) \ - PARAM(X, 0, P, trace) \ - PARAM(X, 1, W, fixRefCount) \ - PARAM(X, 2, W, segRefCount) \ - PARAM(X, 3, W, whiteSegRefCount) \ - PARAM(X, 4, W, nailCount) \ - PARAM(X, 5, W, snapCount) \ - PARAM(X, 6, W, forwardedCount) \ - PARAM(X, 7, W, forwardedSize) \ - PARAM(X, 8, W, preservedInPlaceCount) \ - PARAM(X, 9, W, preservedInPlaceSize) - -#define EVENT_TraceStatReclaim_PARAMS(PARAM, X) \ - PARAM(X, 0, P, trace) \ - PARAM(X, 1, W, reclaimCount) \ - PARAM(X, 2, W, reclaimSize) - -#define EVENT_PoolInitMVFF_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, arena) \ - PARAM(X, 2, W, extendBy) \ - PARAM(X, 3, W, avgSize) \ - PARAM(X, 4, W, align) \ - PARAM(X, 5, B, slotHigh) \ - PARAM(X, 6, B, arenaHigh) \ - PARAM(X, 7, B, firstFit) - -#define EVENT_PoolInitMV_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, arena) \ - PARAM(X, 2, W, extendBy) \ - PARAM(X, 3, W, avgSize) \ - PARAM(X, 4, W, maxSize) - -#define EVENT_PoolInitMFS_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, arena) \ - PARAM(X, 2, W, extendBy) \ - PARAM(X, 3, W, unitSize) - -#define EVENT_PoolInitAMS_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, arena) \ - PARAM(X, 2, P, format) - -#define EVENT_PoolInitAMC_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, format) - -#define EVENT_PoolInitAMCZ_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, format) - -#define EVENT_PoolInitAWL_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, format) - -#define EVENT_PoolInitLO_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, format) - -#define EVENT_PoolInitSNC_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, P, format) - -#define EVENT_PoolInitMVT_PARAMS(PARAM, X) \ - PARAM(X, 0, P, pool) \ - PARAM(X, 1, W, minSize) \ - PARAM(X, 2, W, meanSize) \ - PARAM(X, 3, W, maxSize) \ - PARAM(X, 4, W, reserveDepth) \ - PARAM(X, 5, W, fragLimig) - -#define EVENT_BufferInitSeg_PARAMS(PARAM, X) \ - PARAM(X, 0, P, buffer) \ - PARAM(X, 1, P, pool) \ - PARAM(X, 2, B, isMutator) - -#define EVENT_BufferInitRank_PARAMS(PARAM, X) \ - PARAM(X, 0, P, buffer) \ - PARAM(X, 1, P, pool) \ - PARAM(X, 2, B, isMutator) \ - PARAM(X, 3, U, rank) - -#define EVENT_ReservoirLimitSet_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, size) - -#define EVENT_CommitLimitSet_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, limit) \ - PARAM(X, 2, U, OK) - -#define EVENT_SpareCommitLimitSet_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, limit) - -#define EVENT_ArenaAlloc_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, P, baseTract) \ - PARAM(X, 2, A, base) \ - PARAM(X, 3, W, size) \ - PARAM(X, 4, P, pool) - -#define EVENT_ArenaFree_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, A, base) \ - PARAM(X, 2, W, size) - -#define EVENT_ArenaAllocFail_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, size) \ - PARAM(X, 2, P, pool) - -#define EVENT_SegMerge_PARAMS(PARAM, X) \ - PARAM(X, 0, P, segLo) \ - PARAM(X, 1, P, segHi) \ - PARAM(X, 2, B, withReservoirPermit) - -#define EVENT_SegSplit_PARAMS(PARAM, X) \ - PARAM(X, 0, P, seg) \ - PARAM(X, 1, P, segLo) \ - PARAM(X, 2, P, segHi) \ - PARAM(X, 3, A, at) - -#define EVENT_vmArenaExtendStart_PARAMS(PARAM, X) \ - PARAM(X, 0, W, size) /* size to accommodate */ \ - PARAM(X, 1, W, chunkSize) /* chunkSize to try */ \ - PARAM(X, 2, W, reserved) /* current VMArenaReserved */ - -#define EVENT_vmArenaExtendFail_PARAMS(PARAM, X) \ - PARAM(X, 0, W, chunkMin) /* no remaining address space chunk >= chunkMin */ \ - PARAM(X, 1, W, reserved) /* current VMArenaReserved */ - -#define EVENT_vmArenaExtendDone_PARAMS(PARAM, X) \ - PARAM(X, 0, W, chunkSize) /* request succeeded for chunkSize bytes */ \ - PARAM(X, 1, W, reserved) /* new VMArenaReserved */ - -#define EVENT_MessagesDropped_PARAMS(PARAM, X) \ - PARAM(X, 0, W, count) /* count of messages dropped */ - -#define EVENT_MessagesExist_PARAMS(PARAM, X) - -#define EVENT_ChainCondemnAuto_PARAMS(PARAM, X) \ - PARAM(X, 0, P, chain) /* chain with gens being condemned */ \ - PARAM(X, 1, W, topCondemnedGenSerial) /* condemned gens [0..this] */ \ - PARAM(X, 2, W, genCount) /* total gens in chain */ - -#define EVENT_TraceFindGrey_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, ti) \ - PARAM(X, 2, P, seg) \ - PARAM(X, 3, W, rank) - -#define EVENT_TraceBandAdvance_PARAMS(PARAM, X) \ - PARAM(X, 0, P, arena) \ - PARAM(X, 1, W, ti) \ - PARAM(X, 2, W, rank) - -#define EVENT_AWLDeclineTotal_PARAMS(PARAM, X) \ - PARAM(X, 0, P, seg) /* segment declined single access */ \ - PARAM(X, 1, W, succAccesses) /* total successive accesses */ - -#define EVENT_AWLDeclineSeg_PARAMS(PARAM, X) \ - PARAM(X, 0, P, seg) /* segment declined single access */ \ - PARAM(X, 1, W, singleAccesses) /* single accesses this cycle */ - - -#endif /* eventdef_h */ - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/eventpro.c b/mps/code/eventpro.c deleted file mode 100644 index 1730397fab8..00000000000 --- a/mps/code/eventpro.c +++ /dev/null @@ -1,463 +0,0 @@ -/* eventpro.c: Event processing routines - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * $Id$ - */ - -#include "config.h" -#include "table.h" -#include "eventdef.h" -#include "eventcom.h" -#include "eventpro.h" -#include "misc.h" -#include "mpmtypes.h" -#include "testlib.h" /* for ulongest_t and associated print formats */ - -#include /* assert */ -#include /* size_t */ -#include /* strcmp */ - -struct EventProcStruct { - EventProcReader reader; /* reader fn */ - void *readerP; /* closure pointer for reader fn */ - Table internTable; /* dictionary of intern ids to symbols */ - Table labelTable; /* dictionary of addrs to intern ids */ - void *cachedEvent; -}; - - -/* error -- error signalling - * - * Should integrate with client exceptions, but that'll do for now. - */ - -#define error(fmt, arg) assert(((void)fmt, FALSE)); - - -/* PointerAdd -- add offset to pointer - * - * Copy of the def in mpm.h which we can't include - */ - -#define PointerAdd(p, s) ((void *)((char *)(p) + (s))) - - -/* sizeAlignUp -- align size_t values up */ - -#define sizeAlignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - - -/* EventSizeAlign -- Calculate actual size of event in the output - * - * Calculates the actual size of an event in the output, given the size - * of the structure. This has to agree with the writing (EVENT_END). - */ - -/* TODO: Should read this and other layout information from an event file - header in order to be able to process events from other architectures. */ - -#define EventSizeAlign(size) sizeAlignUp(size, MPS_PF_ALIGN) - - - -/* Event types */ - - -/* eventTypes -- an array containing info about the event types */ - -typedef struct { - char *name; /* Event name e.g. "TraceStart" */ - EventCode code; - size_t size; /* event record size, rounded up from structure */ - Count count; /* Parameter count */ - char *format; /* string format, e.g. "PPW" */ -} eventRecord; - -#define EVENT_COUNT_PARAM(X, index, sort, ident) + 1 - -#define EVENT_FORMAT_PARAM(X, index, sort, ident) #sort - -#define EVENT_INIT(X, name, code, always, kind) \ - {#name, \ - code, \ - EventSizeAlign(sizeof(Event##name##Struct)), \ - 0 EVENT_##name##_PARAMS(EVENT_COUNT_PARAM, X), \ - "" EVENT_##name##_PARAMS(EVENT_FORMAT_PARAM, X)}, - -static eventRecord eventTypes[] = { - {"(unused)", 0, 0, 0, ""}, - EVENT_LIST(EVENT_INIT, X) -}; - -#define eventTypeCount (sizeof(eventTypes) / sizeof(eventRecord)) - - -/* eventcode2Index -- find index in eventTypes for the given code */ - -static size_t eventCode2Index(EventCode code, Bool errorp) -{ - size_t i; - - for(i = 0; i < eventTypeCount; ++i) - if (eventTypes[i].code == code) - return i; - if (errorp) - error("Unknown event code %0"PRIwWORD PRIXLONGEST, (ulongest_t)code); - return 0; -} - - -/* EventName2Code -- find event code for the given event name */ - -EventCode EventName2Code(char *name) -{ - size_t i; - - for(i = 0; i < eventTypeCount; ++i) - if (strcmp(eventTypes[i].name, name) == 0) { - assert(eventTypes[i].code <= EventCodeMAX); - return eventTypes[i].code; - } - error("Unknown event name %s", name); - return 0; -} - - -/* EventCode2Name -- find event name for the given event code */ - -char *EventCode2Name(EventCode code) -{ - return eventTypes[eventCode2Index(code, TRUE)].name; -} - - -/* EventCode2Format -- find format for the given event code */ - -char *EventCode2Format(EventCode code) -{ - return eventTypes[eventCode2Index(code, TRUE)].format; -} - - -Bool EventCodeIsValid(EventCode code) -{ - return (eventCode2Index(code, FALSE) != 0); -} - - -/* EventStrings */ - - -/* eventStringCopy -- copy an event string */ - -static Res stringCopy(char **str_o, char *str) -{ - char *newStr; - size_t len, size; - - len = strlen(str); - size = len + sizeof('\0'); - newStr = (char *)malloc(size); - if (newStr == NULL) return ResMEMORY; - memcpy(newStr, str, size); - *str_o = newStr; - return ResOK; -} - - -static void eventStringDestroy(char *str) -{ - free(str); -} - - -/* Labels */ - - -/* Symbol -- representation of an interned string */ - -typedef struct symbolStruct { - Word id; - char *name; -} symbolStruct; -typedef struct symbolStruct *Symbol; - - -/* Label -- representation of a labelled address */ - -typedef struct labelStruct { - Word id; - EventClock time; - Addr addr; -} labelStruct; -typedef struct labelStruct *Label; - - -/* AddrLabel -- return intern id for given addr (or 0 if none) */ - -Word AddrLabel(EventProc proc, Addr addr) -{ - void *entry; - - if (TableLookup(&entry, proc->labelTable, (Word)addr)) - return ((Label)entry)->id; - else - return (Word)0; -} - - -/* LabelText -- return text for given intern id (or NULL if none) */ - -char *LabelText(EventProc proc, Word id) -{ - void *entry; - - if (TableLookup(&entry, proc->internTable, id)) - return ((Symbol)entry)->name; - else - return NULL; -} - - -/* Processing */ - - -/* EventRead -- read one event from the file and allocate descriptor */ - -#define internStrOffset (offsetof(EventInternStruct, f1.str)) - -Res EventRead(Event *eventReturn, EventProc proc) -{ - Res res; - EventAnyStruct anyStruct; - Event event; - - /* Read the prefix common to all event structures, in order to decode the - event size. */ - res = proc->reader(proc->readerP, &anyStruct, sizeof(anyStruct)); - if (res != ResOK) - return res; - - /* Get memory for the event. */ - if (proc->cachedEvent != NULL) { - event = proc->cachedEvent; - proc->cachedEvent = NULL; - } else { - /* This is too long for most events, but never mind. */ - event = (Event)malloc(sizeof(EventUnion)); - if (event == NULL) - return ResMEMORY; - } - - /* Copy the event prefix and read the rest of the event into the memory. */ - event->any = anyStruct; - res = proc->reader(proc->readerP, - PointerAdd(event, sizeof(anyStruct)), - anyStruct.size - sizeof(anyStruct)); - if (res != ResOK) - return res; - - *eventReturn = event; - return ResOK; -} - - -/* EventRecord -- record event in databases - * - * Currently only labels are tracked, but perhaps there will be other - * stuff in the future. - */ - -Res EventRecord(EventProc proc, Event event, EventClock etime) -{ - Res res; - - switch(event->any.code) { - case EventInternCode: { /* id, label */ - Symbol sym = malloc(sizeof(symbolStruct)); - - if (sym == NULL) return ResMEMORY; - sym->id = event->Intern.f0; - res = stringCopy(&sym->name, event->Intern.f1); - if (res != ResOK) { - free(sym); - return res; - } - res = TableDefine(proc->internTable, sym->id, sym); - } break; - case EventLabelCode: { /* addr, id */ - Label label = malloc(sizeof(labelStruct)); - void *entry; - - if (label == NULL) return ResMEMORY; - label->id = event->Label.f1; - /* If events were in time order we'd be able to assert that - TableLookup(&entry, proc->internTable, label->id) */ - label->time = etime; - label->addr = event->Label.f0; - if (TableLookup(&entry, proc->labelTable, (Word)label->addr)) - res = TableRedefine(proc->labelTable, (Word)label->addr, label); - else - res = TableDefine(proc->labelTable, (Word)label->addr, label); - } break; - default: - res = ResOK; - break; - } - return res; -} - - -/* EventDestroy -- destroy an event */ - -void EventDestroy(EventProc proc, Event event) -{ - if (proc->cachedEvent == NULL) - proc->cachedEvent = event; - else - free(event); -} - - -/* initialization and finishing */ - - -/* Checking macros, copied from check.h */ - -#define COMPATLVALUE(lv1, lv2) \ - ((void)sizeof((lv1) = (lv2)), (void)sizeof((lv2) = (lv1)), TRUE) - -#define COMPATTYPE(t1, t2) \ - (sizeof(t1) == sizeof(t2) && \ - COMPATLVALUE(*((t1 *)0), *((t2 *)0))) - -#define COMPATFIELDAPPROX(s1, f1, s2, f2) \ - (sizeof(((s1 *)0)->f1) == sizeof(((s2 *)0)->f2) && \ - offsetof(s1, f1) == offsetof(s2, f2)) - -#define COMPATFIELD(s1, f1, s2, f2) \ - (COMPATFIELDAPPROX(s1, f1, s2, f2) && \ - COMPATLVALUE(((s1 *)0)->f1, ((s2 *)0)->f2)) - - -/* EventProcCreate -- initialize the module */ - -static void *tableAlloc(void *closure, size_t size) -{ - UNUSED(closure); - return malloc(size); -} - -static void tableFree(void *closure, void *p, size_t size) -{ - UNUSED(closure); - UNUSED(size); - free(p); -} - -Res EventProcCreate(EventProc *procReturn, - EventProcReader reader, - void *readerP) -{ - Res res; - EventProc proc = malloc(sizeof(struct EventProcStruct)); - - if (proc == NULL) return ResMEMORY; - - /* check event struct access */ - assert(COMPATFIELD(EventUnion, any.code, EventInternStruct, code)); - assert(COMPATFIELD(EventUnion, any.clock, EventInternStruct, clock)); - /* check use of labelTable */ - assert(sizeof(Word) >= sizeof(Addr)); - - proc->reader = reader; proc->readerP = readerP; - res = TableCreate(&proc->internTable, - (size_t)1<<4, - tableAlloc, tableFree, NULL, - (Word)-1, (Word)-2); /* because MPS IDs are serials from zero up */ - if (res != ResOK) goto failIntern; - res = TableCreate(&proc->labelTable, (size_t)1<<7, - tableAlloc, tableFree, NULL, - 0, 1); /* no Addrs down here */ - if (res != ResOK) goto failLabel; - proc->cachedEvent = NULL; - *procReturn = proc; - return ResOK; - -failLabel: - TableDestroy(proc->internTable); -failIntern: - free(proc); - return res; -} - - -/* EventProcDestroy -- finish the module */ - -static void deallocItem(void *closure, Word key, void *value) -{ - UNUSED(key); - UNUSED(closure); - free(value); -} - -static void deallocSym(void *closure, Word key, void *value) -{ - UNUSED(key); - UNUSED(closure); - eventStringDestroy(((Symbol)value)->name); - free(value); -} - -void EventProcDestroy(EventProc proc) -{ - TableMap(proc->labelTable, deallocItem, NULL); - TableMap(proc->internTable, deallocSym, NULL); - TableDestroy(proc->labelTable); - TableDestroy(proc->internTable); - if (proc->cachedEvent != NULL) - free(proc->cachedEvent); - free(proc); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/eventpro.h b/mps/code/eventpro.h deleted file mode 100644 index ff671523d46..00000000000 --- a/mps/code/eventpro.h +++ /dev/null @@ -1,81 +0,0 @@ -/* eventpro.h: Interface for event processing routines - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * $Id$ - */ - -#ifndef eventpro_h -#define eventpro_h - -#include "config.h" - -#include "eventcom.h" -#include "mpmtypes.h" - - -typedef struct EventProcStruct *EventProc; -typedef Res (*EventProcReader)(void *, void *, size_t); - - -extern EventCode EventName2Code(char *name); -extern char *EventCode2Name(EventCode code); -extern char *EventCode2Format(EventCode code); -extern Bool EventCodeIsValid(EventCode code); - -extern Word AddrLabel(EventProc proc, Addr addr); -extern char *LabelText(EventProc proc, Word label); - -extern Res EventRead(Event *eventReturn, EventProc proc); -extern void EventDestroy(EventProc proc, Event event); - -extern Res EventRecord(EventProc proc, Event event, EventClock etime); - -extern Res EventProcCreate(EventProc *procReturn, - EventProcReader reader, - void *readerP); -extern void EventProcDestroy(EventProc proc); - - -#endif /* eventpro_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/eventrep.c b/mps/code/eventrep.c deleted file mode 100644 index c2f611f7070..00000000000 --- a/mps/code/eventrep.c +++ /dev/null @@ -1,784 +0,0 @@ -/* eventrep.c: Allocation replayer routines - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * $Id$ - */ - -#include "config.h" -/* override variety setting for EVENT */ -#define EVENT - -#include "eventcom.h" -#include "eventrep.h" -#include "eventpro.h" -#include "mpmtypes.h" - -#include "mps.h" -#include "mpsavm.h" -#include "mpsacl.h" -#include "mpscmv.h" -#include "mpscmvff.h" -#include "mpscepvm.h" -#include "fmtpstst.h" -#include "mpscepdl.h" - -#include "table.h" - -#include /* for size_t */ -#include /* for va_list */ -#include /* for EXIT_FAILURE */ -#include /* for printf */ -#include "mpstd.h" - - -#ifdef MPS_PF_W3I6MV -#define PRIuLONGEST "llu" -#define PRIXPTR "016llX" -typedef unsigned long long ulongest_t; -#else -#define PRIuLONGEST "lu" -#define PRIXPTR "08lX" -typedef unsigned long ulongest_t; -#endif - - -typedef unsigned long ulong; - - -/* Globals */ - -static ulong totalEvents; /* count of events */ -static ulong discardedEvents; /* count of ignored events */ -static ulong unknownEvents; /* count of unknown events */ - -static Word eventTime; - -/* Dictionaries for translating from log to replay values */ -static Table arenaTable; /* dictionary of arenas */ -static Table poolTable; /* dictionary of poolReps */ -static Table apTable; /* dictionary of apReps */ - - -/* poolSupport -- describes pool support for explicit deallocation */ - -enum {supportTruncate = 1, supportFree, supportNothing}; -typedef int poolSupport; - - -/* objectTable -- object address mapping structure - * - * .obj-mapping.truncate: Pools that support truncate need to keep track - * of object end points as well. .obj-mapping.partial-free: Arbitrary - * partial free is not supported. - */ - -typedef struct objectTableStruct { - Table startTable; - Table endTable; -} objectTableStruct; -typedef struct objectTableStruct *objectTable; - - -/* poolRep -- pool tracking structure - * - * .pool.object-addr: Pools that support explicit free (or truncate) - * need to maintain a mapping from the addresses in the log to those in - * the replay. - * - * .bufclass: In order to create APs with the correct arguments, the - * replayer has to pick the right BufferInit event to use, as there's - * one for each superclass. The pool determines the buffer class, so - * we store its subclass level in the pool representation. - */ - -typedef struct poolRepStruct { - mps_pool_t pool; /* the replay pool */ - objectTable objects; - int bufferClassLevel; /* subclass level of the buffer class */ -} poolRepStruct; -typedef struct poolRepStruct *poolRep; - - -/* apRep -- ap tracking structure */ - -typedef struct apRepStruct { - mps_ap_t ap; /* the replay ap */ - objectTable objects; /* object mapping for the pool of this ap */ -} apRepStruct; -typedef struct apRepStruct *apRep; - - -/* PointerAdd -- add offset to pointer */ - -#define PointerAdd(p, s) ((void *)((char *)(p) + (s))) -#define PointerSub(p, s) ((void *)((char *)(p) - (s))) - - -/* error -- error signalling */ - -static void error(const char *format, ...) -{ - va_list args; - - fflush(stdout); /* sync */ - fprintf(stderr, "Failed @%"PRIuLONGEST" ", (ulongest_t)eventTime); - va_start(args, format); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - va_end(args); - exit(EXIT_FAILURE); -} - - -/* verify, verifyMPS -- check return values - * - * We don't use assert for this, because we want it in release as well. - */ - -#define verifyMPS(res) \ - MPS_BEGIN if ((res) != MPS_RES_OK) error("line %d MPS", __LINE__); MPS_END - -#define verify(cond) \ - MPS_BEGIN if (!(cond)) error("line %d " #cond, __LINE__); MPS_END - - -#ifdef MPS_PROD_EPCORE - - -/* ensurePSFormat -- return the PS format, creating it, if necessary */ - -static mps_fmt_t psFormat = NULL; - -static void ensurePSFormat(mps_fmt_t *fmtOut, mps_arena_t arena) -{ - mps_res_t eres; - - if (psFormat == NULL) { - eres = mps_fmt_create_A(&psFormat, arena, ps_fmt_A()); - verifyMPS(eres); - } - *fmtOut = psFormat; -} - - -/* finishPSFormat -- finish the PS format, if necessary */ - -static void finishPSFormat(void) -{ - if (psFormat != NULL) - mps_fmt_destroy(psFormat); -} - - -#endif - - -/* objectTableCreate -- create an objectTable */ - -static objectTable objectTableCreate(poolSupport support) -{ - if (support != supportNothing) { - Res ires; - objectTable table; - - table = malloc(sizeof(objectTableStruct)); - verify(table != NULL); - ires = TableCreate(&table->startTable, (size_t)1<<12); - verify(ires == ResOK); - if (support == supportTruncate) { - ires = TableCreate(&table->endTable, (size_t)1<<12); - verify(ires == ResOK); - } else { - table->endTable = NULL; - } - return table; - } else { - return NULL; - } -} - - -/* objectTableDestroy -- destroy an objectTable */ - -static void objectTableDestroy(objectTable table) -{ - if (table != NULL) { - TableDestroy(table->startTable); - if (table->endTable != NULL) - TableDestroy(table->endTable); - free(table); - } -} - - -/* objDefine -- add a new mapping to an objectTable */ - -static void objDefine(objectTable table, - void *logObj, void *obj, size_t size) -{ - if (table != NULL) { - Res ires; - - ires = TableDefine(table->startTable, (Word)logObj, obj); - verify(ires == ResOK); - if (table->endTable != NULL) { - ires = TableDefine(table->endTable, - (Word)PointerAdd(logObj, size), - PointerAdd(obj, size)); - verify(ires == ResOK); - } - } -} - - -/* objRemove -- look up and remove a mapping in an objectTable */ - -static void objRemove(void **objReturn, objectTable table, - void *logObj, size_t size) -{ - Bool found; - Res ires; - void *obj; - void *end; - void *logEnd; - - found = TableLookup(&obj, table->startTable, (Word)logObj); - if (found) { - ires = TableRemove(table->startTable, (Word)logObj); - verify(ires == ResOK); - if (table->endTable != NULL) { - ires = TableRemove(table->endTable, - (Word)PointerAdd(logObj, size)); - verify(ires == ResOK); - } - *objReturn = obj; - return; - } - /* Must be a truncation. */ - verify(table->endTable != NULL); - logEnd = PointerAdd(logObj, size); - found = TableLookup(&end, table->endTable, (Word)logEnd); - verify(found); - obj = PointerSub(end, size); - /* Remove the old end and insert the new one. */ - ires = TableRemove(table->endTable, (Word)logEnd); - verify(ires == ResOK); - ires = TableDefine(table->endTable, (Word)logObj, obj); - verify(ires == ResOK); - *objReturn = obj; - return; -} - - -/* poolRecreate -- create and record a pool */ - -static void poolRecreate(void *logPool, void *logArena, mps_class_t class, - poolSupport support, int bufferClassLevel, ...) -{ - va_list args; - mps_pool_t pool; - mps_res_t eres; - poolRep rep; - Res ires; - void *entry; - Bool found; - - found = TableLookup(&entry, arenaTable, (Word)logArena); - verify(found); - va_start(args, bufferClassLevel); - eres = mps_pool_create_v(&pool, (mps_arena_t)entry, class, args); - verifyMPS(eres); - va_end(args); - rep = malloc(sizeof(poolRepStruct)); - verify(rep != NULL); - rep->pool = pool; - rep->objects = objectTableCreate(support); - rep->bufferClassLevel = bufferClassLevel; - ires = TableDefine(poolTable, (Word)logPool, (void *)rep); - verify(ires == ResOK); -} - - -/* poolRedestroy -- destroy and derecord a pool */ - -static void poolRedestroy(void *logPool) -{ - Res ires; - void *entry; - Bool found; - poolRep rep; - - found = TableLookup(&entry, poolTable, (Word)logPool); - verify(found); - rep = (poolRep)entry; - mps_pool_destroy(rep->pool); - ires = TableRemove(poolTable, (Word)logPool); - verify(ires == ResOK); - objectTableDestroy(rep->objects); - free(rep); -} - - -/* apRecreate -- create and record an ap */ - -static void apRecreate(void *logAp, void *logPool, ...) -{ - va_list args; - mps_ap_t ap; - poolRep pRep; - apRep aRep; - mps_res_t eres; - Res ires; - void *entry; - Bool found; - - found = TableLookup(&entry, poolTable, (Word)logPool); - verify(found); - pRep = (poolRep)entry; - va_start(args, logPool); - eres = mps_ap_create_v(&ap, pRep->pool, args); - verifyMPS(eres); - va_end(args); - aRep = malloc(sizeof(apRepStruct)); - verify(aRep != NULL); - aRep->ap = ap; - aRep->objects = pRep->objects; - ires = TableDefine(apTable, (Word)logAp, (void *)aRep); - verify(ires == ResOK); -} - - -/* apRedestroy -- destroy and derecord an ap */ - -static void apRedestroy(void *logAp) -{ - Res ires; - void *entry; - Bool found; - apRep rep; - - found = TableLookup(&entry, apTable, (Word)logAp); - verify(found); - rep = (apRep)entry; - mps_ap_destroy(rep->ap); - ires = TableRemove(apTable, (Word)logAp); - verify(ires == ResOK); - free(rep); -} - - -/* EventReplay -- replay event */ - -static arenaJustCreated = FALSE; - -void EventReplay(Event event, Word etime) -{ - mps_res_t eres; - Res ires; - Bool found; - void *entry; - - ++totalEvents; - eventTime = etime; - switch(event->any.code) { - case EventArenaCreateVM: { /* arena, userSize, chunkSize */ - mps_arena_t arena; - - eres = mps_arena_create(&arena, mps_arena_class_vm(), - event->pww.w1); - verifyMPS(eres); - ires = TableDefine(arenaTable, (Word)event->pww.p0, (void *)arena); - verify(ires == ResOK); - arenaJustCreated = TRUE; - } break; - case EventArenaCreateVMNZ: { /* arena, userSize, chunkSize */ - mps_arena_t arena; - - eres = mps_arena_create(&arena, mps_arena_class_vmnz(), - event->pww.w1); - verifyMPS(eres); - ires = TableDefine(arenaTable, (Word)event->pww.p0, (void *)arena); - verify(ires == ResOK); - arenaJustCreated = TRUE; - } break; - case EventArenaCreateCL: { /* arena, size, base */ - mps_arena_t arena; - void *base; - - base = malloc((size_t)event->pwa.w1); - verify(base != NULL); - eres = mps_arena_create(&arena, mps_arena_class_cl(), - (Size)event->pwa.w1, base); - verifyMPS(eres); - ires = TableDefine(arenaTable, (Word)event->pw.p0, (void *)arena); - verify(ires == ResOK); - arenaJustCreated = TRUE; - } break; - case EventArenaDestroy: { /* arena */ - found = TableLookup(&entry, arenaTable, (Word)event->p.p0); - verify(found); -#ifdef MPS_PROD_EPCORE - /* @@@@ assuming there's only one arena at a time */ - finishPSFormat(); -#endif - mps_arena_destroy((mps_arena_t)entry); - ires = TableRemove(arenaTable, (Word)event->pw.p0); - verify(ires == ResOK); - } break; - case EventPoolInitMVFF: { - /* pool, arena, extendBy, avgSize, align, slotHigh, arenaHigh, firstFit */ - poolRecreate(event->ppwwwuuu.p0, event->ppwwwuuu.p1, - mps_class_mvff(), supportFree, 0, - (size_t)event->ppwwwuuu.w2, - (size_t)event->ppwwwuuu.w3, - (size_t)event->ppwwwuuu.w4, - (mps_bool_t)event->ppwwwuuu.u5, - (mps_bool_t)event->ppwwwuuu.u6, - (mps_bool_t)event->ppwwwuuu.u7); - } break; - case EventPoolInitMV: { /* pool, arena, extendBy, avgSize, maxSize */ - /* .pool.control: The control pool will get created just after */ - /* its arena; ignore it. */ - if (!arenaJustCreated) { - poolRecreate(event->ppwww.p0, event->ppwww.p1, - mps_class_mv(), supportFree, 0, (size_t)event->ppwww.w2, - (size_t)event->ppwww.w3, (size_t)event->ppwww.w4); - } else { - arenaJustCreated = FALSE; - } - } break; - case EventPoolInitMFS: { /* pool, arena, extendBy, unitSize */ - /* internal only */ - ++discardedEvents; - } break; - case EventPoolInit: { /* pool, arena, class */ - /* all internal only */ - ++discardedEvents; - } break; -#ifdef MPS_PROD_EPCORE - case EventPoolInitEPVM: { - /* pool, arena, format, maxSaveLevel, saveLevel */ - mps_arena_t arena; - mps_fmt_t format; - - found = TableLookup(&entry, arenaTable, (Word)event->pppuu.p1); - verify(found); - arena = (mps_arena_t)entry; - ensurePSFormat(&format, arena); /* We know what the format is. */ - poolRecreate(event->pppuu.p0, event->pppuu.p1, - mps_class_epvm(), supportNothing, 2, format, - (mps_epvm_save_level_t)event->pppuu.u3, - (mps_epvm_save_level_t)event->pppuu.u4); - } break; - case EventPoolInitEPDL: { - /* pool, arena, isEPDL, extendBy, avgSize, align */ - poolRecreate(event->ppuwww.p0, event->ppuwww.p1, - event->ppuwww.u2 ? mps_class_epdl() : mps_class_epdr(), - event->ppuwww.u2 ? supportTruncate : supportFree, 0, - (size_t)event->ppuwww.w3, (size_t)event->ppuwww.w4, - (size_t)event->ppuwww.w5); - } break; -#endif - case EventPoolFinish: { /* pool */ - found = TableLookup(&entry, poolTable, (Word)event->p.p0); - if (found) { - poolRedestroy(event->p.p0); - } else { - ++discardedEvents; - } - } break; - case EventBufferInit: { /* buffer, pool, isMutator */ - if ((Bool)event->ppu.u2) { - found = TableLookup(&entry, poolTable, (Word)event->ppu.p1); - if (found) { - poolRep rep = (poolRep)entry; - - if(rep->bufferClassLevel == 0) { /* see .bufclass */ - apRecreate(event->ppu.p0, event->ppu.p1); - } else { - ++discardedEvents; - } - } else { - ++discardedEvents; - } - } else { - ++discardedEvents; - } - } break; - case EventBufferInitSeg: { /* buffer, pool, isMutator */ - if ((Bool)event->ppu.u2) { - found = TableLookup(&entry, poolTable, (Word)event->ppu.p1); - if (found) { - poolRep rep = (poolRep)entry; - - if(rep->bufferClassLevel == 1) { /* see .bufclass */ - apRecreate(event->ppu.p0, event->ppu.p1); - } else { - ++discardedEvents; - } - } else { - ++discardedEvents; - } - } else { - ++discardedEvents; - } - } break; - case EventBufferInitRank: { /* buffer, pool, isMutator, rank */ - if ((Bool)event->ppuu.u2) { - found = TableLookup(&entry, poolTable, (Word)event->ppuu.p1); - if (found) { - poolRep rep = (poolRep)entry; - - if(rep->bufferClassLevel == 2) { /* see .bufclass */ - apRecreate(event->ppuu.p0, event->ppuu.p1, event->ppuu.u3); - } else { - ++discardedEvents; - } - } else { - ++discardedEvents; - } - } else { - ++discardedEvents; - } - } break; -#ifdef MPS_PROD_EPCORE - case EventBufferInitEPVM: { /* buffer, pool, isObj */ - found = TableLookup(&entry, poolTable, (Word)event->ppu.p1); - if (found) { - poolRep rep = (poolRep)entry; - - if(rep->bufferClassLevel == 2) { /* see .bufclass */ - apRecreate(event->ppu.p0, event->ppu.p1, (mps_bool_t)event->ppu.u2); - } else { - ++discardedEvents; - } - } else { - ++discardedEvents; - } - } break; -#endif - case EventBufferFinish: { /* buffer */ - found = TableLookup(&entry, apTable, (Word)event->p.p0); - if (found) { - apRedestroy(event->p.p0); - } else { - ++discardedEvents; - } - } break; - case EventBufferReserve: { /* buffer, init, size */ - found = TableLookup(&entry, apTable, (Word)event->paw.p0); - if (found) { - apRep rep = (apRep)entry; - mps_addr_t p; - - eres = mps_reserve(&p, rep->ap, (size_t)event->paw.w2); - verifyMPS(eres); - } else { - ++discardedEvents; - } - } break; - case EventBufferCommit: { /* buffer, p, size, clientClass */ - found = TableLookup(&entry, apTable, (Word)event->pawa.p0); - if (found) { - apRep rep = (apRep)entry; - mps_addr_t obj = rep->ap->init; - mps_bool_t committed; - size_t size = (size_t)event->pawa.w2; - - committed = mps_commit(rep->ap, obj, size); - verifyMPS(committed ? MPS_RES_OK : MPS_RES_FAIL); - objDefine(rep->objects, event->pawa.a1, obj, size); - } else { - ++discardedEvents; - } - } break; - case EventPoolAlloc: { /* pool, obj, size */ - found = TableLookup(&entry, poolTable, (Word)event->paw.p0); - if (found) { - poolRep rep = (poolRep)entry; - void *obj; - size_t size = (size_t)event->paw.w2; - - eres = mps_alloc(&obj, rep->pool, size); - verifyMPS(eres); - objDefine(rep->objects, event->paw.a1, obj, size); - } else { - ++discardedEvents; - } - } break; - case EventPoolFree: { /* pool, obj, size */ - found = TableLookup(&entry, poolTable, (Word)event->paw.p0); - if (found) { - poolRep rep = (poolRep)entry; - void *obj; - size_t size = (size_t)event->paw.w2; - - objRemove(&obj, rep->objects, event->paw.a1, size); - mps_free(rep->pool, obj, size); - } else { - ++discardedEvents; - } - } break; -#ifdef MPS_PROD_EPCORE - case EventPoolPush: { /* pool */ - found = TableLookup(&entry, poolTable, (Word)event->p.p0); - if (found) { - poolRep rep = (poolRep)entry; - - /* It must be EPVM. */ - mps_epvm_save(rep->pool); - } - } break; - case EventPoolPop: { /* pool, level */ - found = TableLookup(&entry, poolTable, (Word)event->pu.p0); - if (found) { - poolRep rep = (poolRep)entry; - - /* It must be EPVM. */ - mps_epvm_restore(rep->pool, (mps_epvm_save_level_t)event->pu.u1); - } - } break; -#endif - case EventCommitLimitSet: { /* arena, limit, succeeded */ - found = TableLookup(&entry, arenaTable, (Word)event->pwu.p0); - verify(found); - eres = mps_arena_commit_limit_set((mps_arena_t)entry, - (size_t)event->pwu.w1); - verifyMPS(((Bool)event->pwu.u2 == (eres == MPS_RES_OK)) - ? MPS_RES_OK : MPS_RES_FAIL); - } break; - case EventSpareCommitLimitSet: { /* arena, limit */ - found = TableLookup(&entry, arenaTable, (Word)event->pw.p0); - verify(found); - (void)mps_arena_spare_commit_limit_set((mps_arena_t)entry, - (size_t)event->pw.w1); - } break; - case EventReservoirLimitSet: { /* arena, limit */ - found = TableLookup(&entry, arenaTable, (Word)event->pw.p0); - verify(found); - mps_reservoir_limit_set((mps_arena_t)entry, (size_t)event->pw.w1); - } break; - case EventVMMap: case EventVMUnmap: - case EventVMCreate: case EventVMDestroy: - case EventArenaWriteFaults: - case EventArenaAlloc: case EventArenaAllocFail: case EventArenaFree: - case EventSegAlloc: case EventSegAllocFail: case EventSegFree: - case EventSegMerge: case EventSegSplit: - case EventBufferFill: case EventBufferEmpty: - case EventCBSInit: case EventMeterInit: case EventMeterValues: - case EventIntern: case EventLabel: { - ++discardedEvents; - } break; - default: { - ++unknownEvents; - if (unknownEvents < 12) /* don't output too much */ - printf("Unknown event @%ld: %s.\n", etime, - EventCode2Name(EventGetCode(event))); - } break; - } -} - - -/* Checking macros, copied from check.h */ - -#define COMPATLVALUE(lv1, lv2) \ - ((void)sizeof((lv1) = (lv2)), (void)sizeof((lv2) = (lv1)), TRUE) - -#define COMPATTYPE(t1, t2) \ - (sizeof(t1) == sizeof(t2) && \ - COMPATLVALUE(*((t1 *)0), *((t2 *)0))) - - -/* CHECKCONV -- check t2 can be cast to t1 without loss */ - -#define CHECKCONV(t1, t2) \ - (sizeof(t1) >= sizeof(t2)) - - -/* EventRepInit -- initialize the module */ - -Res EventRepInit(void) -{ - Res res; - - /* Check using pointers as keys in the tables. */ - verify(CHECKCONV(Word, void *)); - /* Check storage of MPS opaque handles in the tables. */ - verify(COMPATTYPE(mps_arena_t, void *)); - verify(COMPATTYPE(mps_ap_t, void *)); - /* .event-conv: Conversion of event fields into the types required */ - /* by the MPS functions is justified by the reverse conversion */ - /* being acceptable (which is upto the event log generator). */ - - totalEvents = 0; discardedEvents = 0; unknownEvents = 0; - - res = TableCreate(&arenaTable, (size_t)1); - if (res != ResOK) goto failArena; - res = TableCreate(&poolTable, (size_t)1<<4); - if (res != ResOK) goto failPool; - res = TableCreate(&apTable, (size_t)1<<6); - if (res != ResOK) goto failAp; - - return ResOK; - -failAp: - TableDestroy(poolTable); -failPool: - TableDestroy(arenaTable); -failArena: - return res; -} - - -/* EventRepFinish -- finish the module */ - -void EventRepFinish(void) -{ - /* @@@@ add listing of remaining objects? */ - /* No point in cleaning up the tables, since we're quitting. */ - printf("Replayed %lu and discarded %lu events (%lu unknown).\n", - totalEvents - discardedEvents - unknownEvents, - discardedEvents + unknownEvents, unknownEvents); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/eventrep.h b/mps/code/eventrep.h deleted file mode 100644 index 0c66bc3e0fe..00000000000 --- a/mps/code/eventrep.h +++ /dev/null @@ -1,66 +0,0 @@ -/* eventrep.h: Allocation replayer interface - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * $Id$ - */ - -#ifndef eventrep_h -#define eventrep_h - -#include "config.h" -/* override variety setting for EVENT */ -#define EVENT - -#include "eventcom.h" -#include "mpmtypes.h" - - -extern Res EventRepInit(Bool partial); -extern void EventRepFinish(void); - -extern void EventReplay(Event event, Word etime); - - -#endif /* eventrep_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/exposet0.c b/mps/code/exposet0.c deleted file mode 100644 index f5a0b1e9e49..00000000000 --- a/mps/code/exposet0.c +++ /dev/null @@ -1,314 +0,0 @@ -/* exposet0.c: ARENA EXPOSE TEST - * - * $Id$ - * Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * The primary purpose of this test is to test that mps_arena_expose does - * not protect any pages. This is only tested to any real extent on - * Windows where an exception handler in test_stepper is used to catch any - * would-be exceptions (there aren't any if the MPS is operating - * correctly). - * - */ - -#include "fmtdy.h" -#include "fmtdytst.h" -#include "testlib.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include "mps.h" -#include -#include - - -/* These values have been tuned in the hope of getting one dynamic collection. */ -#define testArenaSIZE ((size_t)1000*1024) -#define gen1SIZE ((size_t)150) -#define gen2SIZE ((size_t)170) -#define avLEN 3 -#define exactRootsCOUNT 180 -#define ambigRootsCOUNT 50 -#define genCOUNT 2 -#define collectionsCOUNT 37 -#define rampSIZE 9 -#define initTestFREQ 6000 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { gen1SIZE, 0.85 }, { gen2SIZE, 0.45 } }; - - -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) - - -static mps_pool_t pool_g; -static mps_ap_t ap; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; - - -/* report - report statistics from any terminated GCs */ - -static void report(mps_arena_t arena) -{ - mps_message_t message; - static int nCollections = 0; - - while (mps_message_get(&message, arena, mps_message_type_gc())) { - size_t live, condemned, not_condemned; - - live = mps_message_gc_live_size(arena, message); - condemned = mps_message_gc_condemned_size(arena, message); - not_condemned = mps_message_gc_not_condemned_size(arena, message); - - printf("\nCollection %d finished:\n", ++nCollections); - printf("live %"PRIuLONGEST"\n", (ulongest_t)live); - printf("condemned %"PRIuLONGEST"\n", (ulongest_t)condemned); - printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned); - - mps_message_discard(arena, message); - - if (condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024) - /* When condemned size is larger than could happen in a gen 2 - * collection (discounting ramps, natch), guess that was a dynamic - * collection, and reset the commit limit, so it doesn't run out. */ - die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit"); - } -} - - -/* make -- create one new object */ - -static mps_addr_t make(void) -{ - size_t length = rnd() % (2*avLEN); - size_t size = (length+2) * sizeof(mps_word_t); - mps_addr_t p; - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, p, ap, size); - if (res) - die(res, "MPS_RESERVE_BLOCK"); - res = dylan_init(p, size, exactRoots, exactRootsCOUNT); - if (res) - die(res, "dylan_init"); - } while(!mps_commit(ap, p, size)); - - return p; -} - - -/* test_stepper -- stepping function for walk */ - -static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool, - void *p, size_t s) -{ - testlib_unused(fmt); - testlib_unused(pool); - testlib_unused(s); -#ifdef MPS_OS_W3 - __try { - dylan_mutate(object); - } __except(EXCEPTION_EXECUTE_HANDLER) { - error("Unexpected exception.\n"); - } -#else - dylan_mutate(object); -#endif - - (*(unsigned long *)p)++; -} - - -/* test -- the body of the test */ - -static void *test(void *arg, size_t s) -{ - mps_addr_t busy_init; - mps_ap_t busy_ap; - mps_arena_t arena; - mps_chain_t chain; - mps_fmt_t format; - mps_root_t exactRoot, ambigRoot; - mps_word_t collections; - size_t i; - unsigned long objs; - - arena = (mps_arena_t)arg; - (void)s; /* unused */ - - die(dylan_fmt(&format, arena), "fmt_create"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - - die(mps_pool_create(&pool_g, arena, mps_class_amc(), format, chain), - "pool_create(amc)"); - - die(mps_ap_create(&ap, pool_g, mps_rank_exact()), "BufferCreate"); - die(mps_ap_create(&busy_ap, pool_g, mps_rank_exact()), "BufferCreate 2"); - - for(i = 0; i < exactRootsCOUNT; ++i) { - exactRoots[i] = objNULL; - } - for(i = 0; i < ambigRootsCOUNT; ++i) { - ambigRoots[i] = rnd_addr(); - } - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); - - /* create an ap, and leave it busy */ - die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); - - collections = 0; - objs = 0; - while (collections < collectionsCOUNT) { - unsigned long c; - size_t r; - - c = mps_collections(arena); - - if (collections != c) { - collections = c; - printf("\nCollection %lu started, %lu objects.\n", c, objs); - - report(arena); - for (i = 0; i < exactRootsCOUNT; ++i) { - cdie(exactRoots[i] == objNULL - || (dylan_check(exactRoots[i]) - && mps_arena_has_addr(arena, exactRoots[i])), - "all roots check"); - } - cdie(!mps_arena_has_addr(arena, NULL), - "NULL in arena"); - - { - unsigned long object_count = 0; - mps_arena_expose(arena); - mps_arena_formatted_objects_walk(arena, test_stepper, &object_count, 0); - mps_arena_release(arena); - printf("stepped on %lu objects.\n", object_count); - } - } - - r = (size_t)rnd(); - if (r & 1) { - i = (r >> 1) % exactRootsCOUNT; - if (exactRoots[i] != objNULL) { - cdie(dylan_check(exactRoots[i]), "dying root check"); - } - exactRoots[i] = make(); - if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL) { - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - } - } else { - i = (r >> 1) % ambigRootsCOUNT; - ambigRoots[(ambigRootsCOUNT-1) - i] = make(); - /* Create random interior pointers */ - ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); - } - - if (r % initTestFREQ == 0) { - *(int*)busy_init = -1; /* check that the buffer is still there */ - } - - if (objs % 1024 == 0) { - report(arena); - putchar('.'); - fflush(stdout); - } - - ++objs; - } - - (void)mps_commit(busy_ap, busy_init, 64); - mps_ap_destroy(busy_ap); - mps_ap_destroy(ap); - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); - mps_pool_destroy(pool_g); - mps_chain_destroy(chain); - mps_fmt_destroy(format); - - return NULL; -} - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), 2*testArenaSIZE), - "arena_create"); - mps_message_type_enable(arena, mps_message_type_gc()); - die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - report(arena); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/expt825.c b/mps/code/expt825.c deleted file mode 100644 index 588716f49de..00000000000 --- a/mps/code/expt825.c +++ /dev/null @@ -1,314 +0,0 @@ -/* expt825.c: Test for bug described in job000825 - * - * $Id$ - * Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * DESIGN - * - * Just a copy of finaltest.c with the following modifcations: - * maxtreeDEPTH is 2 rather than 12. This makes the test run and fail - * much more quickly. - * - * After trees have been created and finalized, call - * mps_arena_unsafe_expose_remember_protection / restore. If the bug - * is present then this sequence will fail. - * - * - * DEPENDENCIES - * - * This test uses the dylan object format, but the reliance on this - * particular format is not great and could be removed. - * - * NOTES - * - * This code was created by first copying - * and then further by copying - */ - -#include "testlib.h" -#include "mps.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "fmtdy.h" -#include "fmtdytst.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include - - -#define testArenaSIZE ((size_t)16<<20) -#define rootCOUNT 20 -#define maxtreeDEPTH 2 -#define collectionCOUNT 10 -#define genCOUNT 2 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { 150, 0.85 }, { 170, 0.45 } }; - - -/* global object counter */ - -static mps_word_t object_count = 0; - -static mps_word_t make_numbered_cons(mps_word_t car, mps_word_t cdr, - mps_ap_t ap) -{ - mps_word_t cons; - die(make_dylan_vector(&cons, ap, 3), "make_dylan_vector"); - DYLAN_VECTOR_SLOT(cons, 0) = car; - DYLAN_VECTOR_SLOT(cons, 1) = cdr; - DYLAN_VECTOR_SLOT(cons, 2) = DYLAN_INT(object_count); - ++ object_count; - return cons; -} - -static mps_word_t make_numbered_tree(mps_word_t depth, - mps_ap_t ap) -{ - mps_word_t left, right; - if (depth < 2) { - left = DYLAN_INT(object_count); - right = DYLAN_INT(object_count); - } else { - left = make_numbered_tree(depth-1, ap); - right = make_numbered_tree(depth-1, ap); - } - return make_numbered_cons(left, right, ap); -} - -static void register_numbered_tree(mps_word_t tree, mps_arena_t arena) -{ - /* don't finalize ints */ - if ((tree & 1) == 0) { - mps_finalize(arena, (mps_addr_t *)&tree); - register_numbered_tree(DYLAN_VECTOR_SLOT(tree, 0), arena); - register_numbered_tree(DYLAN_VECTOR_SLOT(tree, 1), arena); - } -} - -static mps_word_t make_indirect_cons(mps_word_t car, mps_word_t cdr, - mps_ap_t ap) -{ - mps_word_t cons, indirect; - die(make_dylan_vector(&indirect, ap, 1), "make_dylan_vector"); - DYLAN_VECTOR_SLOT(indirect, 0) = DYLAN_INT(object_count); - die(make_dylan_vector(&cons, ap, 3), "make_dylan_vector"); - DYLAN_VECTOR_SLOT(cons, 0) = car; - DYLAN_VECTOR_SLOT(cons, 1) = cdr; - DYLAN_VECTOR_SLOT(cons, 2) = indirect; - ++ object_count; - return cons; -} - -static mps_word_t make_indirect_tree(mps_word_t depth, - mps_ap_t ap) -{ - mps_word_t left, right; - if (depth < 2) { - left = DYLAN_INT(object_count); - right = DYLAN_INT(object_count); - } else { - left = make_indirect_tree(depth-1, ap); - right = make_indirect_tree(depth-1, ap); - } - return make_indirect_cons(left, right, ap); -} - -static void register_indirect_tree(mps_word_t tree, mps_arena_t arena) -{ - /* don't finalize ints */ - if ((tree & 1) == 0) { - mps_word_t indirect = DYLAN_VECTOR_SLOT(tree,2); - mps_finalize(arena, (mps_addr_t *)&indirect); - register_indirect_tree(DYLAN_VECTOR_SLOT(tree, 0), arena); - register_indirect_tree(DYLAN_VECTOR_SLOT(tree, 1), arena); - } -} - - -static void *root[rootCOUNT]; - -static void *test(void *arg, size_t s) -{ - mps_ap_t ap; - mps_fmt_t fmt; - mps_chain_t chain; - mps_word_t finals; - mps_pool_t amc; - mps_root_t mps_root; - mps_arena_t arena; - mps_message_t message; - size_t i; - - arena = (mps_arena_t)arg; - (void)s; - - die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain), - "pool_create amc\n"); - die(mps_root_create_table(&mps_root, arena, mps_rank_exact(), (mps_rm_t)0, - root, (size_t)rootCOUNT), - "root_create\n"); - die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_create\n"); - - mps_message_type_enable(arena, mps_message_type_finalization()); - - mps_arena_park(arena); - - object_count = 0; - - printf("Making some finalized trees of objects.\n"); - /* make some trees */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = (void *)make_numbered_tree(maxtreeDEPTH, ap); - register_numbered_tree((mps_word_t)root[i], arena); - } - - mps_arena_unsafe_expose_remember_protection(arena); - mps_arena_unsafe_restore_protection(arena); - - printf("Losing all pointers to the trees.\n"); - /* clean out the roots */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = 0; - } - - finals = 0; - - while ((finals < object_count) && - (mps_collections(arena) < collectionCOUNT)) { - mps_word_t final_this_time = 0; - printf("Collecting..."); - fflush(stdout); - die(mps_arena_collect(arena), "collect"); - printf(" Done.\n"); - while (mps_message_poll(arena)) { - mps_word_t obj; - mps_addr_t objaddr; - cdie(mps_message_get(&message, arena, - mps_message_type_finalization()), - "get"); - mps_message_finalization_ref(&objaddr, arena, message); - obj = (mps_word_t)objaddr; - mps_message_discard(arena, message); - ++ final_this_time; - } - finals += final_this_time; - printf("%lu objects finalized: total %lu of %lu\n", - final_this_time, finals, object_count); - } - - object_count = 0; - - printf("Making some indirectly finalized trees of objects.\n"); - /* make some trees */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = (void *)make_indirect_tree(maxtreeDEPTH, ap); - register_indirect_tree((mps_word_t)root[i], arena); - } - - printf("Losing all pointers to the trees.\n"); - /* clean out the roots */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = 0; - } - - finals = 0; - - while ((finals < object_count) && - (mps_collections(arena) < collectionCOUNT)) { - mps_word_t final_this_time = 0; - printf("Collecting..."); - fflush(stdout); - die(mps_arena_collect(arena), "collect"); - printf(" Done.\n"); - while (mps_message_poll(arena)) { - mps_word_t obj; - mps_addr_t objaddr; - cdie(mps_message_get(&message, arena, - mps_message_type_finalization()), - "get"); - mps_message_finalization_ref(&objaddr, arena, message); - obj = (mps_word_t)objaddr; - mps_message_discard(arena, message); - ++ final_this_time; - } - finals += final_this_time; - printf("%lu objects finalized: total %lu of %lu\n", - final_this_time, finals, object_count); - } - - mps_ap_destroy(ap); - mps_root_destroy(mps_root); - mps_pool_destroy(amc); - mps_chain_destroy(chain); - mps_fmt_destroy(fmt); - - return NULL; -} - - -int main(void) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create\n"); - die(mps_thread_reg(&thread, arena), "thread_reg\n"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/finalcv.c b/mps/code/finalcv.c deleted file mode 100644 index 79a38dbbfb3..00000000000 --- a/mps/code/finalcv.c +++ /dev/null @@ -1,273 +0,0 @@ -/* finalcv.c: FINALIZATION COVERAGE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * DESIGN - * - * See . - * - * DEPENDENCIES - * - * This test uses the dylan object format, but the reliance on this - * particular format is not great and could be removed. - * - * NOTES - * - * This code was created by first copying - */ - -#include "testlib.h" -#include "mps.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "fmtdy.h" -#include "fmtdytst.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include - - -#define testArenaSIZE ((size_t)16<<20) -#define rootCOUNT 20 -#define churnFACTOR 10 -#define finalizationRATE 6 -#define gcINTERVAL ((size_t)150 * 1024) -#define collectionCOUNT 3 - -/* 3 words: wrapper | vector-len | first-slot */ -#define vectorSIZE (3*sizeof(mps_word_t)) -#define vectorSLOT 2 - -#define genCOUNT 2 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { 150, 0.85 }, { 170, 0.45 } }; - - -/* tags an integer according to dylan format */ -static mps_word_t dylan_int(mps_word_t x) -{ - return (x << 2)|1; -} - - -/* converts a dylan format int to an int (untags) */ -static mps_word_t dylan_int_int(mps_word_t x) -{ - return x >> 2; -} - - -/* note: static, so auto-initialised to NULL */ -static void *root[rootCOUNT]; - - -/* churn -- allocate a lot of stuff (unreachable garbage, so it will */ -/* probably only ever cause a minor collection). */ -static void churn(mps_ap_t ap) -{ - int i; - mps_addr_t p; - mps_res_t e; - - for (i = 0; i < churnFACTOR; ++i) { - do { - MPS_RESERVE_BLOCK(e, p, ap, 4096); - die(e, "MPS_RESERVE_BLOCK"); - die(dylan_init(p, 4096, root, 1), "dylan_init"); - } while (!mps_commit(ap, p, 4096)); - } - p = NULL; -} - - -enum { - rootSTATE, - deadSTATE, - finalizableSTATE, - finalizedSTATE -}; - - -static void *test(void *arg, size_t s) -{ - unsigned i; /* index */ - mps_ap_t ap; - mps_fmt_t fmt; - mps_chain_t chain; - mps_pool_t amc; - mps_res_t e; - mps_root_t mps_root[2]; - mps_addr_t nullref = NULL; - int state[rootCOUNT]; - mps_arena_t arena; - void *p = NULL; - mps_message_t message; - - arena = (mps_arena_t)arg; - (void)s; - - die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain), - "pool_create amc\n"); - die(mps_root_create_table(&mps_root[0], arena, mps_rank_exact(), (mps_rm_t)0, - root, (size_t)rootCOUNT), - "root_create\n"); - die(mps_root_create_table(&mps_root[1], arena, mps_rank_exact(), (mps_rm_t)0, - &p, (size_t)1), - "root_create\n"); - die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_create\n"); - - /* Make registered-for-finalization objects. */ - /* */ - for(i = 0; i < rootCOUNT; ++i) { - do { - MPS_RESERVE_BLOCK(e, p, ap, vectorSIZE); - die(e, "MPS_RES_OK"); - die(dylan_init(p, vectorSIZE, &nullref, 1), "dylan_init"); - } while (!mps_commit(ap, p, vectorSIZE)); - - /* store index in vector's slot */ - ((mps_word_t *)p)[vectorSLOT] = dylan_int(i); - - die(mps_finalize(arena, &p), "finalize\n"); - root[i] = p; state[i] = rootSTATE; - } - p = NULL; - - mps_message_type_enable(arena, mps_message_type_finalization()); - - /* */ - while (mps_collections(arena) < collectionCOUNT) { - - /* Perhaps cause (minor) collection */ - churn(ap); - - /* Maybe make some objects ready-to-finalize */ - /* */ - for (i = 0; i < rootCOUNT; ++i) { - if (root[i] != NULL && state[i] == rootSTATE) { - if (rnd() % finalizationRATE == 0) { - /* for this object, either... */ - if (rnd() % 2 == 0) { - /* ...definalize it, or */ - die(mps_definalize(arena, &root[i]), "definalize\n"); - state[i] = deadSTATE; - } else { - /* ...expect it to be finalized soon */ - state[i] = finalizableSTATE; - } - /* Drop the root reference to it; this makes it */ - /* non-E-reachable: so either dead, or ready-to-finalize. */ - root[i] = NULL; - } - } - } - - /* Test any finalized objects, and perhaps resurrect some */ - while (mps_message_poll(arena)) { - mps_word_t *obj; - mps_word_t objind; - mps_addr_t objaddr; - - /* */ - cdie(mps_message_get(&message, arena, mps_message_type_finalization()), - "get"); - cdie(0 == mps_message_clock(arena, message), - "message clock should be 0 (unset) for finalization messages"); - mps_message_finalization_ref(&objaddr, arena, message); - obj = objaddr; - objind = dylan_int_int(obj[vectorSLOT]); - printf("Finalizing: object %lu at %p\n", objind, objaddr); - /* */ - cdie(root[objind] == NULL, "finalized live"); - cdie(state[objind] == finalizableSTATE, "finalized dead"); - state[objind] = finalizedSTATE; - /* sometimes resurrect */ - if (rnd() % 2 == 0) - root[objind] = objaddr; - mps_message_discard(arena, message); - } - } - - /* @@@@ missing */ - - mps_ap_destroy(ap); - mps_root_destroy(mps_root[1]); - mps_root_destroy(mps_root[0]); - mps_pool_destroy(amc); - mps_chain_destroy(chain); - mps_fmt_destroy(fmt); - - return NULL; -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create\n"); - die(mps_thread_reg(&thread, arena), "thread_reg\n"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/finaltest.c b/mps/code/finaltest.c deleted file mode 100644 index 069a737d708..00000000000 --- a/mps/code/finaltest.c +++ /dev/null @@ -1,299 +0,0 @@ -/* finaltest.c: LARGE-SCALE FINALIZATION TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * DESIGN - * - * DEPENDENCIES - * - * This test uses the dylan object format, but the reliance on this - * particular format is not great and could be removed. - * - * NOTES - * - * This code was created by first copying - */ - -#include "testlib.h" -#include "mps.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "fmtdy.h" -#include "fmtdytst.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include - - -#define testArenaSIZE ((size_t)16<<20) -#define rootCOUNT 20 -#define maxtreeDEPTH 12 -#define collectionCOUNT 10 -#define genCOUNT 2 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { 150, 0.85 }, { 170, 0.45 } }; - - -/* global object counter */ - -static mps_word_t object_count = 0; - -static mps_word_t make_numbered_cons(mps_word_t car, mps_word_t cdr, - mps_ap_t ap) -{ - mps_word_t cons; - die(make_dylan_vector(&cons, ap, 3), "make_dylan_vector"); - DYLAN_VECTOR_SLOT(cons, 0) = car; - DYLAN_VECTOR_SLOT(cons, 1) = cdr; - DYLAN_VECTOR_SLOT(cons, 2) = DYLAN_INT(object_count); - ++ object_count; - return cons; -} - -static mps_word_t make_numbered_tree(mps_word_t depth, - mps_ap_t ap) -{ - mps_word_t left, right; - if (depth < 2) { - left = DYLAN_INT(object_count); - right = DYLAN_INT(object_count); - } else { - left = make_numbered_tree(depth-1, ap); - right = make_numbered_tree(depth-1, ap); - } - return make_numbered_cons(left, right, ap); -} - -static void register_numbered_tree(mps_word_t tree, mps_arena_t arena) -{ - /* don't finalize ints */ - if ((tree & 1) == 0) { - mps_addr_t tree_ref = (mps_addr_t)tree; - mps_finalize(arena, &tree_ref); - register_numbered_tree(DYLAN_VECTOR_SLOT(tree, 0), arena); - register_numbered_tree(DYLAN_VECTOR_SLOT(tree, 1), arena); - } -} - -static mps_word_t make_indirect_cons(mps_word_t car, mps_word_t cdr, - mps_ap_t ap) -{ - mps_word_t cons, indirect; - die(make_dylan_vector(&indirect, ap, 1), "make_dylan_vector"); - DYLAN_VECTOR_SLOT(indirect, 0) = DYLAN_INT(object_count); - die(make_dylan_vector(&cons, ap, 3), "make_dylan_vector"); - DYLAN_VECTOR_SLOT(cons, 0) = car; - DYLAN_VECTOR_SLOT(cons, 1) = cdr; - DYLAN_VECTOR_SLOT(cons, 2) = indirect; - ++ object_count; - return cons; -} - -static mps_word_t make_indirect_tree(mps_word_t depth, - mps_ap_t ap) -{ - mps_word_t left, right; - if (depth < 2) { - left = DYLAN_INT(object_count); - right = DYLAN_INT(object_count); - } else { - left = make_indirect_tree(depth-1, ap); - right = make_indirect_tree(depth-1, ap); - } - return make_indirect_cons(left, right, ap); -} - -static void register_indirect_tree(mps_word_t tree, mps_arena_t arena) -{ - /* don't finalize ints */ - if ((tree & 1) == 0) { - mps_word_t indirect = DYLAN_VECTOR_SLOT(tree,2); - mps_addr_t indirect_ref = (mps_addr_t)indirect; - mps_finalize(arena, &indirect_ref); - register_indirect_tree(DYLAN_VECTOR_SLOT(tree, 0), arena); - register_indirect_tree(DYLAN_VECTOR_SLOT(tree, 1), arena); - } -} - - -static void *root[rootCOUNT]; - -static void *test(void *arg, size_t s) -{ - mps_ap_t ap; - mps_fmt_t fmt; - mps_chain_t chain; - mps_word_t finals; - mps_pool_t amc; - mps_root_t mps_root; - mps_arena_t arena; - mps_message_t message; - size_t i; - - arena = (mps_arena_t)arg; - (void)s; - - die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain), - "pool_create amc\n"); - die(mps_root_create_table(&mps_root, arena, mps_rank_exact(), (mps_rm_t)0, - root, (size_t)rootCOUNT), - "root_create\n"); - die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_create\n"); - - mps_message_type_enable(arena, mps_message_type_finalization()); - - mps_arena_park(arena); - - object_count = 0; - - printf("Making some finalized trees of objects.\n"); - /* make some trees */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = (void *)make_numbered_tree(maxtreeDEPTH, ap); - register_numbered_tree((mps_word_t)root[i], arena); - } - - printf("Losing all pointers to the trees.\n"); - /* clean out the roots */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = 0; - } - - finals = 0; - - while ((finals < object_count) && - (mps_collections(arena) < collectionCOUNT)) { - mps_word_t final_this_time = 0; - printf("Collecting..."); - fflush(stdout); - die(mps_arena_collect(arena), "collect"); - printf(" Done.\n"); - while (mps_message_poll(arena)) { - mps_addr_t objaddr; - cdie(mps_message_get(&message, arena, - mps_message_type_finalization()), - "get"); - mps_message_finalization_ref(&objaddr, arena, message); - mps_message_discard(arena, message); - ++ final_this_time; - } - finals += final_this_time; - printf("%lu objects finalized: total %lu of %lu\n", - final_this_time, finals, object_count); - } - - object_count = 0; - - printf("Making some indirectly finalized trees of objects.\n"); - /* make some trees */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = (void *)make_indirect_tree(maxtreeDEPTH, ap); - register_indirect_tree((mps_word_t)root[i], arena); - } - - printf("Losing all pointers to the trees.\n"); - /* clean out the roots */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = 0; - } - - finals = 0; - - while ((finals < object_count) && - (mps_collections(arena) < collectionCOUNT)) { - mps_word_t final_this_time = 0; - printf("Collecting..."); - fflush(stdout); - die(mps_arena_collect(arena), "collect"); - printf(" Done.\n"); - while (mps_message_poll(arena)) { - mps_addr_t objaddr; - cdie(mps_message_get(&message, arena, - mps_message_type_finalization()), - "get"); - mps_message_finalization_ref(&objaddr, arena, message); - mps_message_discard(arena, message); - ++ final_this_time; - } - finals += final_this_time; - printf("%lu objects finalized: total %lu of %lu\n", - final_this_time, finals, object_count); - } - - mps_ap_destroy(ap); - mps_root_destroy(mps_root); - mps_pool_destroy(amc); - mps_chain_destroy(chain); - mps_fmt_destroy(fmt); - - return NULL; -} - - -int main(void) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create\n"); - die(mps_thread_reg(&thread, arena), "thread_reg\n"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fmtdy.c b/mps/code/fmtdy.c deleted file mode 100644 index f622bfe128c..00000000000 --- a/mps/code/fmtdy.c +++ /dev/null @@ -1,884 +0,0 @@ -/* fmtdy.c: DYLAN OBJECT FORMAT IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * .readership: MPS developers, Dylan developers - * - * .layouts: - * - * All objects, B: - * - * B W pointer to wrapper - * B+1 object body - * - * Forwarded (or padding) one-word objects, B: - * - * B N | 0b01 new address | 1 - * - * Forwarded (or padding) multi-word objects, B: - * - * B N | 0b10 new address | 2 - * B+1 L limit of object (addr of end + 1) - * - * Wrappers, W: - * - * W WW pointer to wrapper wrapper - * W+1 class DylanWorks class pointer (traceable) - * W+2 subtype_mask DylanWorks subtype_mask (untraceable) - * W+3 (FL << 2) | FF fixed part length and format - * W+4 (VS << 3) | VF variable part format and element size - * W+5 (WT << 2) | 1 tagged pattern vector length - * W+6 pattern 0 patterns for fixed part fields - * W+6+WT-1 pattern WT-1 - * - * The wrapper wrapper, WW: - * - * WW WW WW is it's own wrapper - * WW+1 class DylanWorks class of wrappers - * WW+2 subtype_mask DylanWorks subtype_mask for WW - * WW+3 (4 << 2) | 2 wrappers have four patterned fields - * WW+4 (0 << 3) | 0 wrappers have a non-traceable vector - * WW+5 (1 << 2) | 1 one pattern word follows - * WW+6 0b001 only field 0 is traceable - * - * .improve.abstract.access: There are severe common subexpression - * problems. In particular, code for accessing subfields in the - * fh and vh words is repeated. It should be abstracted into - * macros (or functions). This is particularly bad for the vh - * word which has 4 subfields (version, vb, es, vf). - */ - - -#include "fmtdy.h" -#include "fmtno.h" -#include "mps.h" -#include -#include -#include -#include - - -#define notreached() assert(0) -#define unused(param) ((void)param) - - -#ifdef _MSC_VER - -/* MPS_END causes "constant conditional" warnings. */ -#pragma warning(disable: 4127) - -/* windows.h causes warnings about "unreferenced inline function */ -/* has been removed". */ -#pragma warning(disable: 4514) - -#endif /* _MSC_VER */ - - -#define ALIGN sizeof(mps_word_t) - -#define FMTDY_WORD_WIDTH (sizeof(mps_word_t) * CHAR_BIT) -#define FMTDY_WORD_SHIFT (FMTDY_WORD_WIDTH == 64 ? 6 : 5) -/* FMTDY_WORD_SHIFT is a bit hacky, but good enough for tests. */ - -#ifdef FMTDY_COUNTING -#define FMTDY_COUNT(x) x -#define FMTDY_FL_LIMIT 16 -static unsigned long dylan_vff_counts[4*8]; -static unsigned long dylan_fl_counts[FMTDY_FL_LIMIT]; -static unsigned long dylan_fl_oversize_count; -static unsigned long dylan_fw_counts[2]; -#else -#define FMTDY_COUNT(x) -#endif /* FMTDY_COUNTING */ - - -int dylan_wrapper_check(mps_word_t *w) -{ - mps_word_t *ww; - mps_word_t vh; - mps_word_t version; - mps_word_t reserved; - mps_word_t class; - mps_word_t fh, fl, ff; - mps_word_t vb, es, vf; - mps_word_t vt, t; - - assert(w != NULL); - assert(((mps_word_t)w & 3) == 0); - - /* The first word of the wrapper is a pointer to a wrapper wrapper, */ - /* which always has the same contents. Check it. */ - - /* .improve.unique.wrapper: When this becomes part of the Dylan - * run-time, it would be possible to know the address of a unique - * wrapper wrapper and check that instead. */ - - assert(w[WW] != 0); - assert((w[WW] & 3) == 0); /* wrapper wrapper is aligned */ - ww = (mps_word_t *)w[WW]; - assert(ww[WW] == w[WW]); /* wrapper wrapper is own wrapper */ - assert(ww[WC] != 0); /* wrapper class exists */ - assert((ww[WC] & 3) == 0); /* wrapper class is aligned */ - assert(ww[WF] == (((WS - 1) << 2) | 2)); /* fields with patterns */ - assert((ww[WV] & 0x00ffffff) == 0);/* non-traceable vector */ - /* Code in this file only works for version 2 */ - assert(((ww[WV] >> (FMTDY_WORD_WIDTH - 8)) & 0xff) == 2); - assert(ww[WS] == ((1 << 2) | 1)); /* one pattern word in wrapper wrapper */ - /* The first field is traceable, the second field can be traced, */ - /* but doesn't need to be. */ - assert((ww[WP] == 1) || (ww[WP] == 3)); - unused(ww); - - /* Unpack the wrapper. */ - - class = w[WC]; /* class */ - unused(class); - fh = w[WF]; /* fixed part header word */ - fl = fh >> 2; /* fixed part length */ - ff = fh & 3; /* fixed part format code */ - vh = w[WV]; /* variable part header */ - version = (vh >> (FMTDY_WORD_WIDTH - 8)) & 0xff; - assert(version == 2); /* Code in this file only works for version 2 */ - unused(version); - reserved = (vh >> 8) & 0xff; - assert(reserved == 0); - unused(reserved); - vb = (vh >> 16) & 0xff; - unused(vb); - es = (vh & 0xff) >> 3;/* element size */ - vf = vh & 7; /* variable part format code */ - vt = w[WS]; /* vector total word (Dylan-tagged) */ - t = vt >> 2; /* vector total length */ - unused(t); - - /* The second word is the class of the wrapped object. */ - /* It would be good to check which pool this is in. */ - - assert(class != 0); /* class exists */ - assert((class & 3) == 0); /* class is aligned */ - - /* The third word contains the fixed part format and length. */ - /* The only illegal format is 3. Anything else is possible, although */ - /* we could do some bound checking on the length if we knew more about */ - /* the surroundings of the object. */ - - /* Fixed part format 3 is reserved. */ - assert(ff != 3); - unused(ff); - - /* Zero length fixed part is only legal in format 0. */ - /* Current Dylan run-time does not honour this so I remove it for now */ - /* We probably want this check as then we can scan without having to */ - /* check for 0 fixed length fields as a special case */ - /* assert(ff == 0 || fl != 0); */ - unused(fl); - /* The fourth word contains the variable part format and element */ - /* size. This assumes that DylanWorks is only going to use byte */ - /* vectors in the non-word case. */ - - /* Variable part format 6 is reserved. */ - assert(vf != 6); - unused(vf); - - /* There should be no shift in word vector formats. */ - assert((vf & 6) == 4 || es == 0); - unused(es); - - /* The fifth word is the number of patterns in the pattern */ - /* vector. This can be calculated from the fixed part length. */ - /* The word is also tagged like a DylanWorks integer. */ - - assert((vt & 3) == 1); - - /* The pattern vector in the wrapper should be of non-zero length */ - /* only if there is a patterned fixed part. */ - assert(ff == 2 || t == 0); - - /* The number of patterns is (fixed fields+31)/32. */ - assert(ff != 2 || t == ((fl + FMTDY_WORD_WIDTH - 1) / FMTDY_WORD_WIDTH)); - - /* The patterns are random bits, so we can't check them. However, */ - /* the left-over bits in the last pattern should be zero. */ - - assert(ff != 2 || (w[WS+t] >> ((fh>>2) & (FMTDY_WORD_WIDTH-1))) == 0); - - return 1; -} - - -/* Scan a contiguous array of references in [base, limit). */ -/* This code has been hand-optimised and examined using Metrowerks */ -/* Codewarrior on a 68K and also Microsoft Visual C on a 486. The */ -/* variables in the loop allocate nicely into registers. Alter with */ -/* care. */ - -static mps_res_t dylan_scan_contig(mps_ss_t mps_ss, - mps_addr_t *base, mps_addr_t *limit) -{ - mps_res_t res; - mps_addr_t *p; /* reference cursor */ - mps_addr_t r; /* reference to be fixed */ - - MPS_SCAN_BEGIN(mps_ss) { - p = base; - loop: if(p >= limit) goto out; - r = *p++; - if(((mps_word_t)r&3) != 0) /* pointers tagged with 0 */ - goto loop; /* not a pointer */ - if(!MPS_FIX1(mps_ss, r)) goto loop; - res = MPS_FIX2(mps_ss, p-1); - if(res == MPS_RES_OK) goto loop; - return res; - out: assert(p == limit); - } MPS_SCAN_END(mps_ss); - - return MPS_RES_OK; -} - -/* dylan_weak_dependent -- returns the linked object, if any. - */ - -extern mps_addr_t dylan_weak_dependent(mps_addr_t parent) -{ - mps_word_t *object; - mps_word_t *wrapper; - mps_word_t fword; - mps_word_t fl; - mps_word_t ff; - - assert(parent != NULL); - object = (mps_word_t *)parent; - wrapper = (mps_word_t *)object[0]; - assert(dylan_wrapper_check(wrapper)); - fword = wrapper[3]; - ff = fword & 3; - /* traceable fixed part */ - assert(ff == 1); - unused(ff); - fl = fword & ~(mps_word_t)3; - /* at least one fixed field */ - assert(fl >= 1); - unused(fl); - return (mps_addr_t) object[1]; -} - - -/* Scan weakly a contiguous array of references in [base, limit). */ -/* Only required to scan vectors for Dylan Weak Tables. */ -/* Depends on the vector length field being scannable (ie a tagged */ -/* integer). */ -/* When a reference that has been fixed to NULL is detected the */ -/* corresponding reference in the associated table (pointed to be the */ -/* assoc variable) will be deleted. */ - -static mps_res_t -dylan_scan_contig_weak(mps_ss_t mps_ss, - mps_addr_t *base, mps_addr_t *limit, - mps_addr_t *objectBase, mps_addr_t *assoc) -{ - mps_addr_t *p; - mps_res_t res; - mps_addr_t r; - - MPS_SCAN_BEGIN(mps_ss) { - p = base; - goto skip_inc; - loop: - ++p; - skip_inc: - if(p >= limit) - goto out; - r = *p; - if(((mps_word_t)r & 3) != 0) /* non-pointer */ - goto loop; - if(!MPS_FIX1(mps_ss, r)) - goto loop; - res = MPS_FIX2(mps_ss, p); - if(res == MPS_RES_OK) { - if(*p == 0 && r != 0) { - if(assoc != NULL) { - assoc[p-objectBase] = 0; /* delete corresponding entry */ - } - } - goto loop; - } - return res; - out: - assert(p == limit); - } MPS_SCAN_END(mps_ss); - - return MPS_RES_OK; -} - - -/* dylan_scan_pat -- scan according to pattern */ - -/* Scan an array of words in [base, limit) using the patterns at pats */ -/* to determine which words can be fixed. */ -/* This code has been hand-optimised and examined using Metrowerks */ -/* Codewarrior on a 68K and also Microsoft Visual C on a 486. The */ -/* variables in the loop allocate nicely into registers. Alter with */ -/* care. */ - -static mps_res_t dylan_scan_pat(mps_ss_t mps_ss, - mps_addr_t *base, mps_addr_t *limit, - mps_word_t *pats, mps_word_t nr_pats) -{ - mps_res_t res; - mps_word_t *pc = pats;/* pattern cursor */ - mps_word_t pat; /* pattern register */ - mps_addr_t *p; /* reference cursor */ - mps_addr_t *pp; /* inner loop cursor */ - int b; /* bit */ - mps_addr_t r; /* reference to be fixed */ - - unused(nr_pats); - - MPS_SCAN_BEGIN(mps_ss) { - p = base; - goto in; - pat: p += FMTDY_WORD_WIDTH; - if(p >= limit) goto out; - in: pp = p; - pat = *pc++; - loop: if(pat == 0) goto pat; - ++pp; - b = (int)(pat & 1); - pat >>= 1; - if(b == 0) goto loop; - r = *(pp-1); - if(((mps_word_t)r&3) != 0) /* pointers tagged with 0 */ - goto loop; /* not a pointer */ - if(!MPS_FIX1(mps_ss, r)) goto loop; - res = MPS_FIX2(mps_ss, pp-1); - if(res == MPS_RES_OK) goto loop; - return res; - out: assert(p < limit + FMTDY_WORD_WIDTH); - assert(pc == pats + nr_pats); - } MPS_SCAN_END(mps_ss); - - return MPS_RES_OK; -} - - -#define NONWORD_LENGTH(_vt, _es) \ - ((_es) < FMTDY_WORD_SHIFT ? \ - ((_vt) + ((mps_word_t)1 << (FMTDY_WORD_SHIFT - (_es))) - 1) >> \ - (FMTDY_WORD_SHIFT - (_es)) : \ - (_vt) << ((_es) - FMTDY_WORD_SHIFT)) - - -extern mps_res_t dylan_scan1(mps_ss_t mps_ss, mps_addr_t *object_io) -{ - mps_addr_t *p; /* cursor in object */ - mps_addr_t *q; /* cursor limit for loops */ - mps_word_t h; /* header word */ - mps_word_t *w; /* pointer to wrapper */ - mps_word_t fh; /* fixed part header word */ - mps_word_t fl; /* fixed part length, in words */ - mps_word_t vh; /* variable part header */ - mps_word_t vf; /* variable part format */ - mps_word_t vl; /* variable part actual length */ - unsigned vb; /* vector bias */ - unsigned es; /* variable part element size (log2 of bits) */ - mps_word_t vt; /* total vector length */ - mps_res_t res; - - assert(object_io != NULL); - - p = (mps_addr_t *)*object_io; - assert(p != NULL); - - h = (mps_word_t)p[0]; /* load the header word */ - - /* If the object is forwarded, simply skip it. */ - if(h & 3) { - mps_addr_t l; - - if((h & 3) == 1) { - /* single-word */ - l = (mps_addr_t)(p + 1); - FMTDY_COUNT(++dylan_fw_counts[0]); - } else { /* multi-word */ - assert((h & 3) == 2); - l = (mps_addr_t)p[1]; - FMTDY_COUNT(++dylan_fw_counts[1]); - } - - *object_io = l; - return MPS_RES_OK; - } - - res = mps_fix(mps_ss, p); /* fix the wrapper */ - if ( res != MPS_RES_OK ) return res; - w = (mps_word_t *)p[0]; /* wrapper is header word */ - assert(dylan_wrapper_check(w)); - - ++p; /* skip header */ - - /* Fixed Part */ - - fh = w[WF]; - fl = fh >> 2; /* get the fixed part length */ - - /* It might be worth inlining common cases here, for example, */ - /* pairs. This can be done by examining fh as a whole. */ - - FMTDY_COUNT(fl < FMTDY_FL_LIMIT ? ++dylan_fl_counts[fl] : - ++dylan_fl_oversize_count); - if(fl > 0) { - q = p + fl; /* set q to end of fixed part */ - switch(fh & 3) { /* switch on the fixed format */ - case 0: /* all non-traceable fields */ - p = q; - break; - - case 1: /* all traceable fields */ - res = dylan_scan_contig(mps_ss, p, q); - if(res) return res; - break; - - case 2: /* patterns */ - res = dylan_scan_pat(mps_ss, p, q, &w[WP], w[WS]>>2); - if(res) return res; - break; - - default: - notreached(); - break; - } - p = q; - } - - /* Variable Part */ - vh = w[WV]; - vf = vh & 7; /* get variable part format */ - FMTDY_COUNT(++dylan_vff_counts[(vf << 2)|(fh&3)]); - if(vf != 7) - { - vt = *(mps_word_t *)p; /* total vector length */ - assert((vt & 3) == 1); /* check Dylan integer tag */ - vt >>= 2; /* untag it */ - ++p; - - switch(vf) - { - case 0: /* non-stretchy non-traceable */ - p += vt; - break; - - case 1: /* stretchy non-traceable */ - notreached(); /* Not used by DylanWorks yet */ - p += vt + 1; - break; - - case 2: /* non-stretchy traceable */ - q = p + vt; - res = dylan_scan_contig(mps_ss, p, q); - if(res) return res; - p = q; - break; - - case 3: /* stretchy traceable */ - notreached(); /* DW doesn't create them yet */ - vl = *(mps_word_t *)p; /* vector length */ - assert((vl & 3) == 1); /* check Dylan integer tag */ - vl >>= 2; /* untag it */ - ++p; - res = dylan_scan_contig(mps_ss, p, p + vl); - if(res) return res; - p += vt; /* skip to end of whole vector */ - break; - - case 4: /* non-word */ - es = (vh & 0xff) >> 3; - vb = (vh >> 16) & 0xff; - vt += vb; - p += NONWORD_LENGTH(vt, es); - break; - - case 5: /* stretchy non-word */ - notreached(); /* DW doesn't create them yet */ - es = (vh & 0xff) >> 3; - vb = (vh >> 16) & 0xff; - vt += vb; - p += NONWORD_LENGTH(vt, es) + 1; - break; - - default: - notreached(); - break; - } - } - - *object_io = (mps_addr_t)p; - return MPS_RES_OK; -} - -static mps_res_t dylan_scan(mps_ss_t mps_ss, - mps_addr_t base, mps_addr_t limit) -{ - mps_res_t res; - - while(base < limit) { - res = dylan_scan1(mps_ss, &base); - if(res) return res; - } - - assert(base == limit); - - return MPS_RES_OK; -} - -/* dylan_class -- return pointer indicating class of object - * - * Return wrapper pointer, except for broken hearts or padding - */ - -static mps_addr_t dylan_class(mps_addr_t obj) -{ - mps_word_t first_word = ((mps_word_t *)obj)[0]; - - if((first_word & 3) != 0) /* broken heart or padding */ - return NULL; - else - return (mps_addr_t)first_word; -} - -extern mps_res_t dylan_scan1_weak(mps_ss_t mps_ss, mps_addr_t *object_io) -{ - mps_addr_t *assoc; - mps_addr_t *base; - mps_addr_t *p, q; - mps_res_t res; - mps_word_t *w; - mps_word_t fword, ff, fl; - mps_word_t h; - mps_word_t vword, vf, vl; - - assert(object_io != NULL); - base = (mps_addr_t *)*object_io; - assert(base != NULL); - p = base; - - h = (mps_word_t)p[0]; - /* object should not be forwarded (as there is no forwarding method) */ - assert((h & 3) == 0); - unused(h); - - res = mps_fix(mps_ss, p); - if ( res != MPS_RES_OK ) return res; - - /* w points to wrapper */ - w = (mps_word_t *)p[0]; - - assert(dylan_wrapper_check(w)); - - ++p; /* skip header */ - - fword = w[WF]; - fl = fword >> 2; - /* weak vectors should have at least one fixed field */ - /* (for assoc field) */ - assert(fl >= 1); - - ff = fword & 3; - - /* weak vectors should have traceable fixed format */ - assert(ff == 1); - unused(ff); - - assoc = (mps_addr_t *)p[0]; - - vword = w[WV]; - vf = vword & 7; - vl = (mps_word_t)p[fl] >> 2; - - /* weak vectors should be non-stretchy traceable */ - assert(vf == 2); - unused(vf); - - /* q is end of the object. There are fl fixed fields, vl variable */ - /* fields and another slot that contains the vector length */ - q = p + fl + vl + 1; - - res = dylan_scan_contig_weak(mps_ss, p, q, base, assoc); - if(res != MPS_RES_OK) { - return res; - } - - *object_io = q; - return MPS_RES_OK; -} - - -static mps_res_t dylan_scan_weak(mps_ss_t mps_ss, - mps_addr_t base, mps_addr_t limit) -{ - mps_res_t res; - - while(base < limit) { - res = dylan_scan1_weak(mps_ss, &base); - if(res) return res; - } - - assert(base == limit); - - return MPS_RES_OK; -} - -static mps_addr_t dylan_skip(mps_addr_t object) -{ - mps_addr_t *p; /* cursor in object */ - mps_word_t *w; /* wrapper cursor */ - mps_word_t h; /* header word */ - mps_word_t vh; /* variable part header */ - mps_word_t vf; /* variable part format */ - mps_word_t vt; /* total vector length */ - unsigned vb; /* vector bias */ - unsigned es; /* variable part element size (log2 of bits) */ - - p = (mps_addr_t *)object; - assert(p != NULL); - - h = (mps_word_t)p[0]; /* load the header word */ - - /* If the object is forwarded, simply skip it. */ - if(h & 3) { - mps_addr_t l; - - if((h & 3) == 1) /* single-word */ - l = (mps_addr_t)(p + 1); - else { /* multi-word */ - assert((h & 3) == 2); - l = (mps_addr_t)p[1]; - } - - return l; - } - - w = (mps_word_t *)h; /* load the fixed wrapper */ - assert(dylan_wrapper_check(w)); - ++p; - - p += w[WF] >> 2; /* skip fixed part fields */ - - vh = w[WV]; - vf = vh & 7; /* get variable part format */ - if(vf != 7) - { - vt = *(mps_word_t *)p; - assert((vt & 3) == 1); /* check Dylan integer tag */ - vt = vt >> 2; /* total length */ - ++p; - - p += vf & 1; /* stretchy vectors have an extra word */ - - if((vf & 6) == 4) /* non-word */ - { - es = (vh & 0xff) >> 3; - vb = (vh >> 16) & 0xff; - vt += vb; - p += NONWORD_LENGTH(vt, es); - } - else - p += vt; - } - - return (mps_addr_t)p; -} - -static void dylan_copy(mps_addr_t old, mps_addr_t new) -{ - char *base = (char *)old; - char *limit = (char *)dylan_skip(old); - size_t length; - assert(base < limit); - length = (size_t)(limit - base); - assert(dylan_wrapper_check(*(mps_word_t **)old)); - /* .improve.memcpy: Can do better here as we know that new and old - will be aligned (to MPS_PF_ALIGN) */ - (void)memcpy(new, old, length); -} - -static mps_addr_t dylan_isfwd(mps_addr_t object) -{ - mps_word_t h, tag; - - h = *(mps_word_t *)object; - tag = h & 3; - if(tag != 0) - return (mps_addr_t)(h - tag); - else - return NULL; -} - -static void dylan_fwd(mps_addr_t old, mps_addr_t new) -{ - mps_word_t *p; - mps_addr_t limit; - - assert(dylan_isfwd(old) == NULL); - assert(((mps_word_t)new & 3) == 0); - - p = (mps_word_t *)old; - limit = dylan_skip(old); - if(limit == &p[1]) /* single-word object? */ - p[0] = (mps_word_t)new | 1; - else { - p[0] = (mps_word_t)new | 2; - p[1] = (mps_word_t)limit; - } -} - -void dylan_pad(mps_addr_t addr, size_t size) -{ - mps_word_t *p; - - p = (mps_word_t *)addr; - if(size == sizeof(mps_word_t)) /* single-word object? */ - p[0] = 1; - else { - p[0] = 2; - p[1] = (mps_word_t)((char *)addr + size); - } -} - - -/* The dylan format structures */ - -static struct mps_fmt_A_s dylan_fmt_A_s = -{ - ALIGN, - dylan_scan, - dylan_skip, - dylan_copy, - dylan_fwd, - dylan_isfwd, - dylan_pad -}; - -static struct mps_fmt_B_s dylan_fmt_B_s = -{ - ALIGN, - dylan_scan, - dylan_skip, - dylan_copy, - dylan_fwd, - dylan_isfwd, - dylan_pad, - dylan_class -}; - -/* Functions returning the dylan format structures */ - -mps_fmt_A_s *dylan_fmt_A(void) -{ - return &dylan_fmt_A_s; -} - -mps_fmt_B_s *dylan_fmt_B(void) -{ - return &dylan_fmt_B_s; -} - -/* Format variety-independent version that picks the right format - * variety and creates it. */ - -mps_res_t dylan_fmt(mps_fmt_t *mps_fmt_o, mps_arena_t arena) -{ - return mps_fmt_create_B(mps_fmt_o, arena, dylan_fmt_B()); -} - -/* The weak format structures */ - -static struct mps_fmt_A_s dylan_fmt_A_weak_s = -{ - ALIGN, - dylan_scan_weak, - dylan_skip, - no_copy, - no_fwd, - no_isfwd, - no_pad -}; - -static struct mps_fmt_B_s dylan_fmt_B_weak_s = -{ - ALIGN, - dylan_scan_weak, - dylan_skip, - no_copy, - no_fwd, - no_isfwd, - no_pad, - dylan_class -}; - -/* Functions returning the weak format structures */ - -mps_fmt_A_s *dylan_fmt_A_weak(void) -{ - return &dylan_fmt_A_weak_s; -} - - -mps_fmt_B_s *dylan_fmt_B_weak(void) -{ - return &dylan_fmt_B_weak_s; -} - - -/* Format variety-independent version that picks the right format - * variety and creates it. */ - -mps_res_t dylan_fmt_weak(mps_fmt_t *mps_fmt_o, mps_arena_t arena) -{ - return mps_fmt_create_B(mps_fmt_o, arena, dylan_fmt_B_weak()); -} - - - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fmtdy.h b/mps/code/fmtdy.h deleted file mode 100644 index b7434abebd7..00000000000 --- a/mps/code/fmtdy.h +++ /dev/null @@ -1,85 +0,0 @@ -/* fmtdy.h: DYLAN OBJECT FORMAT - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef fmtdy_h -#define fmtdy_h - -#include "mps.h" - -/* Low-level routines, exposed here so that the with-header format - * can use common code. */ -extern mps_res_t dylan_scan1(mps_ss_t, mps_addr_t *); -extern mps_res_t dylan_scan1_weak(mps_ss_t, mps_addr_t *); - -/* Format */ -extern mps_fmt_A_s *dylan_fmt_A(void); -extern mps_fmt_A_s *dylan_fmt_A_weak(void); -extern mps_fmt_B_s *dylan_fmt_B(void); -extern mps_fmt_B_s *dylan_fmt_B_weak(void); -extern mps_res_t dylan_fmt(mps_fmt_t *, mps_arena_t); -extern mps_res_t dylan_fmt_weak(mps_fmt_t *, mps_arena_t); - -extern mps_addr_t dylan_weak_dependent(mps_addr_t); - -extern void dylan_pad(mps_addr_t addr, size_t size); -extern int dylan_wrapper_check(mps_word_t *w); - -/* Constants describing wrappers. Used only for debugging / testing */ -#define WW 0 /* offset of Wrapper-Wrapper */ -#define WC 1 /* offset of Class pointer*/ -#define WM 2 /* offset of subtype Mask */ -#define WF 3 /* offset of Fixed part descriptor */ -#define WV 4 /* offset of Vector part descriptor */ -#define WS 5 /* offset of Size field for pattern vector */ -#define WP 6 /* offset of Pattern 0, if present */ - -#define BASIC_WRAPPER_SIZE (WS + 1) /* size of wrapper with no patterns */ - -#define ALIGN sizeof(mps_word_t) /* alignment for Dylan format */ - -#endif /* fmtdy_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fmtdytst.c b/mps/code/fmtdytst.c deleted file mode 100644 index c98fc4b9f73..00000000000 --- a/mps/code/fmtdytst.c +++ /dev/null @@ -1,262 +0,0 @@ -/* fmtdytst.c: DYLAN FORMAT TEST CODE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS developers, Dylan developers. - */ - -#include "fmtdy.h" -#include "fmtdytst.h" -#include "mps.h" -#include "testlib.h" -#include -#include -#include - -#define unused(param) ((void)param) - -#ifdef MPS_BUILD_MV -/* windows.h causes warnings about "unreferenced inline function */ -/* has been removed". */ -#pragma warning(disable: 4514) -#endif /* MPS_BUILD_MV */ - - -static mps_word_t *ww = NULL; -static mps_word_t *tvw; - - -static mps_word_t dylan_make_WV(mps_word_t version, mps_word_t vb, - mps_word_t es, mps_word_t vf) -{ - assert((version & ((1 << 8) - 1)) == version); - assert((vb & ((1 << 8) - 1)) == vb); - assert((es & ((1 << 5) - 1)) == es); - assert((vf & ((1 << 3) - 1)) == vf); - - /* VERSION- ... VB------ reserved ES---VF- */ - return((version << (MPS_WORD_WIDTH - 8)) | - (vb << 16) | - (es << 3) | - vf); -} - -static mps_res_t dylan_make_wrapper_wrapper(void) -{ - if(ww == NULL) { - ww = malloc(sizeof(mps_word_t) * (BASIC_WRAPPER_SIZE + 1)); - if(ww == NULL) return MPS_RES_MEMORY; - tvw = malloc(sizeof(mps_word_t) * BASIC_WRAPPER_SIZE); - if(tvw == NULL) { - free(ww); - return MPS_RES_MEMORY; - } - - /* Build a wrapper wrapper. */ - ww[WW] = (mps_word_t)ww; - ww[WC] = (mps_word_t)ww; /* dummy class */ - ww[WM] = (1 << 2) | 1; /* dummy subtype_mask */ - ww[WF] = ((WS - 1) << 2) | 2; - ww[WV] = dylan_make_WV(2, 0, 0, 0); - ww[WS] = (1 << 2) | 1; - ww[WP] = 1; - - /* Build a wrapper for traceable vectors. */ - tvw[WW] = (mps_word_t)ww; - tvw[WC] = (mps_word_t)ww; /* dummy class */ - tvw[WM] = (1 << 2) | 1; /* dummy subtype_mask */ - tvw[WF] = 0; /* no fixed part */ - tvw[WV] = dylan_make_WV(2, 0, 0, 2); /* traceable variable part */ - tvw[WS] = 1; /* no patterns */ - } - return MPS_RES_OK; -} - - -/* dylan_init -- turn raw memory into initialised dylan-vector (or pad) - * - * If the raw memory is large enough, initialises it to a dylan-vector, - * whose slots are initialised to either dylan-ints, or valid refs, at - * random. - * Caller must supply an array of (at least 1) valid refs to copy, via - * the "refs" and "nr_refs" arguments. - * (Makes a pad if the raw memory is too small to hold a dylan-vector) - */ - -mps_res_t dylan_init(mps_addr_t addr, size_t size, - mps_addr_t *refs, size_t nr_refs) -{ - mps_res_t res; - /* Make sure the size is aligned. */ - assert((size & (ALIGN-1)) == 0); - - res = dylan_make_wrapper_wrapper(); - if (res != MPS_RES_OK) - return res; - - /* If there is enough room, make a vector, otherwise just */ - /* make a padding object. */ - if(size >= sizeof(mps_word_t) * 2) { - mps_word_t *p = (mps_word_t *)addr; - mps_word_t i, t = (size / sizeof(mps_word_t)) - 2; - - p[0] = (mps_word_t)tvw; /* install vector wrapper */ - p[1] = (t << 2) | 1; /* tag the vector length */ - for(i = 0; i < t; ++i) { - mps_word_t r = rnd(); - - if(r & 1) - p[2+i] = ((r & ~(mps_word_t)3) | 1); /* random int */ - else - p[2+i] = (mps_word_t)refs[(r >> 1) % nr_refs]; /* random ptr */ - } - } else { - dylan_pad(addr, size); - } - - return MPS_RES_OK; -} - -mps_res_t make_dylan_vector(mps_word_t *v, mps_ap_t ap, size_t slots) -{ - mps_res_t res; - mps_addr_t addr; - mps_word_t *p; - size_t size; - size_t i; - - res = dylan_make_wrapper_wrapper(); - if (res != MPS_RES_OK) - return res; - - size = (slots + 2) * sizeof(mps_word_t); - - do { - MPS_RESERVE_BLOCK(res, addr, ap, size); - if (res != MPS_RES_OK) - return res; - - p = (mps_word_t *)addr; - p[0] = (mps_word_t)tvw; /* install vector wrapper */ - p[1] = (slots << 2) | 1; /* tag the vector length */ - /* fill all slots with zero ints. */ - for (i=0; i> 2; - - /* If the object is a vector, update a random entry. */ - if(p[0] == (mps_word_t)tvw && t > 0) { - mps_word_t r = rnd(); - size_t i = 2 + (rnd() % t); - - if(r & 1) - p[i] = ((r & ~(mps_word_t)3) | 1); /* random int */ - else - p[i] = (mps_word_t)refs[(r >> 1) % nr_refs]; /* random ptr */ - } -} - -/* Writes to a dylan object. - Currently just swaps two refs if it can. - This is only used in a certain way by certain tests, it doesn't have - to be very general. */ -void dylan_mutate(mps_addr_t addr) -{ - mps_word_t *p = (mps_word_t *)addr; - - if(p[0] == (mps_word_t)tvw) { - mps_word_t t = p[1] >> 2; - - if(t > 0) { - mps_word_t tmp; - size_t i, j; - - i = 2 + (rnd() % t); - j = 2 + (rnd() % t); - - tmp = p[i]; - p[i] = p[j]; - p[j] = tmp; - } - } - return; -} - -mps_addr_t dylan_read(mps_addr_t addr) -{ - mps_word_t *p = (mps_word_t *)addr; - - /* If the object is a vector, return a random entry. */ - if(p[0] == (mps_word_t)tvw) { - mps_word_t t = p[1] >> 2; - if(t > 0) - return (mps_addr_t)p[2 + (rnd() % t)]; - } - - return addr; -} - -mps_bool_t dylan_check(mps_addr_t addr) -{ - assert(addr != 0); - assert(((mps_word_t)addr & (ALIGN-1)) == 0); - assert(dylan_wrapper_check((mps_word_t *)((mps_word_t *)addr)[0])); - /* .assert.unused: Asserts throw away their conditions */ - /* in hot varieties, so UNUSED is needed. */ - unused(addr); - return 1; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fmtdytst.h b/mps/code/fmtdytst.h deleted file mode 100644 index 14f8993383d..00000000000 --- a/mps/code/fmtdytst.h +++ /dev/null @@ -1,81 +0,0 @@ -/* fmtdytst.h: DYLAN OBJECT FORMAT TESTING - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef fmtdytst_h -#define fmtdytst_h - -#include "mps.h" -#include "testlib.h" - -extern mps_res_t dylan_init(mps_addr_t addr, size_t size, - mps_addr_t *refs, size_t nr_refs); -extern void dylan_write(mps_addr_t addr, - mps_addr_t *refs, size_t nr_refs); -extern void dylan_mutate(mps_addr_t addr); -extern mps_addr_t dylan_read(mps_addr_t addr); -extern mps_bool_t dylan_check(mps_addr_t addr); -extern void dylan_pad(mps_addr_t addr, size_t size); -extern int dylan_wrapper_check(mps_word_t *w); - -extern mps_res_t make_dylan_vector(mps_word_t *v, mps_ap_t ap, size_t slots); - -#define DYLAN_VECTOR_SLOT(o,n) (((mps_word_t *) (o))[(n)+2]) - -#define DYLAN_INT(n) (((mps_word_t)(n) << 2) | 1) - -#define INT_DYI(n) ( (n) <= DYLAN_UINT_MAX ? DYLAN_INT(n) : (mps_word_t)fail() ) - - -#define DYLAN_INT_INT(d) ((mps_word_t)(d) >> 2) - -#define DYI_INT(d) ( ((d) & 0x3) == 0x1 ? DYLAN_INT_INT(d) : (mps_word_t)fail() ) - -#define DYLAN_UINT_MAX ((mps_word_t)-1 >> 2) -#define DYLAN_UINT_MASK DYLAN_UINT_MAX - -#endif /* fmtdy_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fmthe.c b/mps/code/fmthe.c deleted file mode 100644 index f5e1528d51e..00000000000 --- a/mps/code/fmthe.c +++ /dev/null @@ -1,241 +0,0 @@ -/* fmthe.c: DYLAN-LIKE OBJECT FORMAT WITH HEADERS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * Uses for the actual Dylan format, and just adds - * a thin layer to handle the object headers themselves. - */ - -#include "fmtdy.h" -#include "fmtno.h" -#include "fmthe.h" -#include "mps.h" - -#include -#include - -#include "testlib.h" - - -#define assert(cond) Insist(cond) -#define notreached() assert(0) - -#define AddHeader(p) ((mps_addr_t)((char*)(p) + headerSIZE)) - -static mps_fmt_A_s *dylan_format; - -static mps_res_t dylan_header_scan(mps_ss_t mps_ss, - mps_addr_t base, mps_addr_t limit) -{ - mps_res_t res; - mps_addr_t p = base; - - while(p < limit) { - mps_word_t header = (mps_word_t)*(int*)((char*)p - headerSIZE); - switch(headerType(header)) { - case realTYPE: - assert(header == realHeader); - break; - case padTYPE: - p = (mps_addr_t)((char*)p + headerPadSize(header)); - continue; - default: - notreached(); - break; - } - res = dylan_scan1(mps_ss, &p); - if(res) return res; - p = AddHeader(p); - } - - assert(p <= AddHeader(limit)); - - return MPS_RES_OK; -} - - -static mps_res_t dylan_header_scan_weak(mps_ss_t mps_ss, - mps_addr_t base, - mps_addr_t limit) -{ - mps_res_t res; - - while(base < limit) { - mps_word_t header; - header = (mps_word_t)*(int*)((char*)base - headerSIZE); - switch(headerType(header)) { - case realTYPE: - assert(header == realHeader); - break; - case padTYPE: - base = (mps_addr_t)((char*)base + headerPadSize(header)); - continue; - default: - notreached(); - break; - } - - res = dylan_scan1_weak(mps_ss, &base); - if(res) return res; - base = AddHeader(base); - } - - assert(base <= AddHeader(limit)); - - return MPS_RES_OK; -} - -static mps_addr_t dylan_header_skip(mps_addr_t object) -{ - mps_addr_t *p; /* cursor in object */ - mps_word_t header; - header = (mps_word_t)*(int*)((char*)object - headerSIZE); - switch(headerType(header)) { - case realTYPE: - assert(header == realHeader); - break; - case padTYPE: - return (mps_addr_t)((char*)object + headerPadSize(header)); - default: - notreached(); - break; - } - - p = dylan_format->skip(object); - p = AddHeader(p); - return p; -} - - -static mps_addr_t dylan_header_isfwd(mps_addr_t object) -{ - mps_word_t header; - - header = (mps_word_t)*(int*)((char*)object - headerSIZE); - if (headerType(header) != realTYPE) - return NULL; - - assert(header == realHeader); - - return dylan_format->isfwd(object); -} - - -static void dylan_header_pad(mps_addr_t addr, size_t fullSize) -{ - *(int*)addr = (int)padHeader(fullSize); -} - - -/* HeaderFormat -- format descriptor for this format */ - -static struct mps_fmt_auto_header_s HeaderFormat = -{ - ALIGN, - dylan_header_scan, - dylan_header_skip, - NULL, /* later overwritten by dylan format forward method */ - dylan_header_isfwd, - dylan_header_pad, - (size_t)headerSIZE -}; - - -/* HeaderWeakFormat -- format descriptor for this format */ - -static struct mps_fmt_auto_header_s HeaderWeakFormat = -{ - ALIGN, - dylan_header_scan_weak, - dylan_header_skip, - no_fwd, - no_isfwd, - no_pad, - (size_t)headerSIZE -}; - - -/* EnsureHeaderFormat -- create a format object for this format */ - -mps_res_t EnsureHeaderFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena) -{ - dylan_format = dylan_fmt_A(); - HeaderFormat.fwd = dylan_format->fwd; - return mps_fmt_create_auto_header(mps_fmt_o, arena, &HeaderFormat); -} - - -/* EnsureHeaderWeakFormat -- create a format object for the weak format */ - -mps_res_t EnsureHeaderWeakFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena) -{ - dylan_format = dylan_fmt_A(); - return mps_fmt_create_auto_header(mps_fmt_o, arena, &HeaderWeakFormat); -} - - -/* HeaderFormatCheck -- check an object in this format */ - -mps_res_t HeaderFormatCheck(mps_addr_t addr) -{ - if (addr != 0 && ((mps_word_t)addr & (ALIGN-1)) == 0 - && dylan_wrapper_check((mps_word_t *)((mps_word_t *)addr)[0])) - return MPS_RES_OK; - else - return MPS_RES_FAIL; -} - -/* HeaderWeakFormatCheck -- check an object in this format */ - -mps_res_t HeaderWeakFormatCheck(mps_addr_t addr) -{ - if (addr != 0 && ((mps_word_t)addr & (ALIGN-1)) == 0 - && dylan_wrapper_check((mps_word_t *)((mps_word_t *)addr)[0])) - return MPS_RES_OK; - else - return MPS_RES_FAIL; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fmthe.h b/mps/code/fmthe.h deleted file mode 100644 index fa4c9897c7e..00000000000 --- a/mps/code/fmthe.h +++ /dev/null @@ -1,70 +0,0 @@ -/* fmthe.h: HEADERS FOR DYLAN-LIKE OBJECT FORMATS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - */ - -#ifndef fmthe_h -#define fmthe_h - -#include "mps.h" - -/* Formats */ -extern mps_res_t EnsureHeaderFormat(mps_fmt_t *, mps_arena_t); -extern mps_res_t EnsureHeaderWeakFormat(mps_fmt_t *, mps_arena_t); -extern mps_res_t HeaderFormatCheck(mps_addr_t addr); -extern mps_res_t HeaderWeakFormatCheck(mps_addr_t addr); - -#define headerSIZE (32) -#define headerTypeBits 8 -#define realTYPE 0x33 -#define realHeader (realTYPE + 0x12345600) -#define padTYPE 0xaa -#define headerType(header) ((header) & (((mps_word_t)1 << headerTypeBits) - 1)) -#define headerPadSize(header) ((header) >> headerTypeBits) -#define padHeader(size) ((size << headerTypeBits) | padTYPE) - -#endif /* fmthe_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fmtno.c b/mps/code/fmtno.c deleted file mode 100644 index 6c632fef06b..00000000000 --- a/mps/code/fmtno.c +++ /dev/null @@ -1,177 +0,0 @@ -/* fmtno.c: NULL OBJECT FORMAT IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS developers - */ - - -#include "fmtno.h" -#include "mps.h" -#include -#include -#include - - -#define notreached() assert(0) -#define unused(param) ((void)param) - -#ifdef MPS_BUILD_MV - -/* MSVC 2.0 generates a warning for unused(). */ -#ifdef _MSC_VER -#if _MSC_VER < 1000 -#pragma warning(disable: 4705) -#endif -#else /* _MSC_VER */ -#error "Expected _MSC_VER to be defined for builder.mv" -#endif /* _MSC_VER */ - -/* windows.h causes warnings about "unreferenced inline function */ -/* has been removed". */ -#pragma warning(disable: 4514) - -#endif /* MPS_BUILD_MV */ - -#define ALIGN sizeof(mps_word_t) - -/* Functions for the null format. */ - -mps_res_t no_scan(mps_ss_t mps_ss, - mps_addr_t base, - mps_addr_t limit) -{ - unused(mps_ss); unused(base); unused(limit); - notreached(); - return 0; -} - -mps_addr_t no_skip(mps_addr_t object) -{ - unused(object); - notreached(); - return 0; -} - -void no_copy(mps_addr_t old, - mps_addr_t new) -{ - unused(old); unused(new); - notreached(); -} - -void no_fwd(mps_addr_t old, - mps_addr_t new) -{ - unused(old); unused(new); - notreached(); -} - -mps_addr_t no_isfwd(mps_addr_t object) -{ - unused(object); - notreached(); - return 0; -} - -void no_pad(mps_addr_t addr, - size_t size) -{ - unused(addr); unused(size); - notreached(); -} - -mps_addr_t no_class(mps_addr_t obj) -{ - unused(obj); - notreached(); - return 0; -} - -/* The null format structures */ - -static struct mps_fmt_A_s no_fmt_A_s = -{ - ALIGN, - no_scan, - no_skip, - no_copy, - no_fwd, - no_isfwd, - no_pad -}; - -static struct mps_fmt_B_s no_fmt_B_s = -{ - ALIGN, - no_scan, - no_skip, - no_copy, - no_fwd, - no_isfwd, - no_pad, - no_class -}; - -/* Functions returning the null format structures. */ - -mps_fmt_A_s *no_fmt_A(void) -{ - return &no_fmt_A_s; -} - -mps_fmt_B_s *no_fmt_B(void) -{ - return &no_fmt_B_s; -} - -/* Format variety-independent version that picks the right format - * variety and creates it. */ - -mps_res_t no_fmt(mps_fmt_t *mps_fmt_o, mps_arena_t arena) -{ - return mps_fmt_create_B(mps_fmt_o, arena, no_fmt_B()); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fmtno.h b/mps/code/fmtno.h deleted file mode 100644 index 884c5389a51..00000000000 --- a/mps/code/fmtno.h +++ /dev/null @@ -1,66 +0,0 @@ -/* fmtdy.h: NULL OBJECT FORMAT - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef fmtno_h -#define fmtno_h - -#include "mps.h" - -extern mps_res_t no_scan(mps_ss_t, mps_addr_t, mps_addr_t); -extern mps_addr_t no_skip(mps_addr_t); -extern void no_copy(mps_addr_t, mps_addr_t); -extern void no_fwd(mps_addr_t, mps_addr_t); -extern mps_addr_t no_isfwd(mps_addr_t); -extern void no_pad(mps_addr_t, size_t); -extern mps_addr_t no_class(mps_addr_t); - -extern mps_fmt_A_s *no_fmt_A(void); -extern mps_fmt_B_s *no_fmt_B(void); -extern mps_res_t no_fmt(mps_fmt_t *, mps_arena_t); - -#endif /* fmtno_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/format.c b/mps/code/format.c deleted file mode 100644 index 9867f562167..00000000000 --- a/mps/code/format.c +++ /dev/null @@ -1,205 +0,0 @@ -/* format.c: OBJECT FORMATS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * DESIGN - * - * See protocol.mps.format. - */ - -#include "mpm.h" - -SRCID(format, "$Id$"); - - -/* FormatCheck -- check a format */ - -Bool FormatCheck(Format format) -{ - CHECKS(Format, format); - CHECKU(Arena, format->arena); - CHECKL(format->serial < format->arena->formatSerial); - CHECKL(format->variety == FormatVarietyA - || format->variety == FormatVarietyB - || format->variety == FormatVarietyAutoHeader); - CHECKL(RingCheck(&format->arenaRing)); - CHECKL(AlignCheck(format->alignment)); - /* @@@@ alignment should be less than maximum allowed */ - CHECKL(FUNCHECK(format->scan)); - CHECKL(format->variety == FormatVarietyFixed - ? format->skip == NULL : FUNCHECK(format->skip)); - CHECKL(FUNCHECK(format->move)); - CHECKL(FUNCHECK(format->isMoved)); - /* Ignore unused copy field. */ - CHECKL(FUNCHECK(format->pad)); - CHECKL(FUNCHECK(format->class)); - - return TRUE; -} - - -static mps_addr_t FormatDefaultClass(mps_addr_t object) -{ - AVER(object != NULL); - - return ((mps_addr_t *)object)[0]; -} - - -/* FormatCreate -- create a format */ - -Res FormatCreate(Format *formatReturn, Arena arena, - Align alignment, - FormatVariety variety, - mps_fmt_scan_t scan, - mps_fmt_skip_t skip, - mps_fmt_fwd_t move, - mps_fmt_isfwd_t isMoved, - mps_fmt_copy_t copy, - mps_fmt_pad_t pad, - mps_fmt_class_t class, - Size headerSize) -{ - Format format; - Res res; - void *p; - - AVER(formatReturn != NULL); - - res = ControlAlloc(&p, arena, sizeof(FormatStruct), - /* withReservoirPermit */ FALSE); - if(res != ResOK) - return res; - format = (Format)p; /* avoid pun */ - - format->arena = arena; - RingInit(&format->arenaRing); - format->alignment = alignment; - format->variety = variety; - format->scan = scan; - format->skip = skip; - format->move = move; - format->isMoved = isMoved; - format->copy = copy; - format->pad = pad; - if (class == NULL) { - format->class = &FormatDefaultClass; - } else { - AVER(variety == FormatVarietyB); - format->class = class; - } - if (headerSize != 0) { - AVER(variety == FormatVarietyAutoHeader); - format->headerSize = headerSize; - } else { - format->headerSize = 0; - } - - format->sig = FormatSig; - format->serial = arena->formatSerial; - ++arena->formatSerial; - - AVERT(Format, format); - - RingAppend(&arena->formatRing, &format->arenaRing); - - *formatReturn = format; - return ResOK; -} - - -/* FormatDestroy -- destroy a format */ - -void FormatDestroy(Format format) -{ - AVERT(Format, format); - - RingRemove(&format->arenaRing); - - format->sig = SigInvalid; - - RingFinish(&format->arenaRing); - - ControlFree(format->arena, format, sizeof(FormatStruct)); -} - - -/* FormatArena -- find the arena of a format - * - * Must be thread-safe. See . */ - -Arena FormatArena(Format format) -{ - /* Can't AVER format as that would not be thread-safe */ - /* AVERT(Format, format); */ - return format->arena; -} - - -/* FormatDescribe -- describe a format */ - -Res FormatDescribe(Format format, mps_lib_FILE *stream) -{ - Res res; - - res = WriteF(stream, - "Format $P ($U) {\n", (WriteFP)format, (WriteFU)format->serial, - " arena $P ($U)\n", - (WriteFP)format->arena, (WriteFU)format->arena->serial, - " alignment $W\n", (WriteFW)format->alignment, - " scan $F\n", (WriteFF)format->scan, - " skip $F\n", (WriteFF)format->skip, - " move $F\n", (WriteFF)format->move, - " isMoved $F\n", (WriteFF)format->isMoved, - " copy $F\n", (WriteFF)format->copy, - " pad $F\n", (WriteFF)format->pad, - "} Format $P ($U)\n", (WriteFP)format, (WriteFU)format->serial, - NULL); - if (res != ResOK) return res; - - return ResOK; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/fri3gc.gmk b/mps/code/fri3gc.gmk deleted file mode 100644 index f2895c00404..00000000000 --- a/mps/code/fri3gc.gmk +++ /dev/null @@ -1,62 +0,0 @@ -# fri3gc.gmk: BUILD FOR FreeBSD/i386/GCC PLATFORM -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - -PFM = fri3gc - -MPMPF = lockix.c thix.c pthrdext.c vmix.c \ - protix.c protsgix.c prmcan.c prmci3fr.c ssixi3.c span.c - -LIBS = -lm -pthread - -include gc.gmk - -# FIXME: We pun types through the MPS interface, setting off this warning. -# Can we avoid this? The puns might indeed be dangerous. -CFLAGSCOMPILER := $(CFLAGSCOMPILER) -Wno-strict-aliasing - -CC = cc - -include comm.gmk - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/fri6gc.gmk b/mps/code/fri6gc.gmk deleted file mode 100644 index 814d0a7e204..00000000000 --- a/mps/code/fri6gc.gmk +++ /dev/null @@ -1,60 +0,0 @@ -# fri6gc.gmk: BUILD FOR FreeBSD/amd64/GCC PLATFORM -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - -PFM = fri6gc - -MPMPF = lockix.c thix.c pthrdext.c vmix.c \ - protix.c protsgix.c prmcan.c prmci6fr.c ssixi6.c span.c - -LIBS = -lm -pthread - -include gc.gmk - -CFLAGSCOMPILER := $(CFLAGSCOMPILER) -Wno-strict-aliasing - -CC = cc - -include comm.gmk - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/gc.gmk b/mps/code/gc.gmk deleted file mode 100644 index 3de47e908b0..00000000000 --- a/mps/code/gc.gmk +++ /dev/null @@ -1,70 +0,0 @@ -# gc.gmk: GNUMAKEFILE FRAGMENT FOR GNU CC -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. -# -# This file is included by platform makefiles that use the GNU CC -# compiler. It defines the compiler-specific variables that the -# common makefile fragment () requires. - -CC = gcc -CFLAGSCOMPILER := \ - -ansi -pedantic -Wall -Werror -Wpointer-arith \ - -Wstrict-prototypes -Wmissing-prototypes \ - -Winline -Waggregate-return -Wnested-externs \ - -Wcast-qual -Wshadow -Wstrict-aliasing=2 -CFLAGSDEBUG = -O -g3 -CFLAGSOPT = -O2 -g3 - -# gcc -MM generates a dependency line of the form: -# thing.o : thing.c ... -# The sed line converts this into: -# //thing.o //thing.d : thing.c ... -# If interrupted, this is liable to leave a zero-length file behind. - -define gendep - $(SHELL) -ec "$(CC) $(CFLAGS) -MM $< | \ - sed '/:/s!$*.o!$(@D)/& $(@D)/$*.d!' > $@" - [ -s $@ ] || rm -f $@ -endef - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/global.c b/mps/code/global.c deleted file mode 100644 index 0f16c5e4475..00000000000 --- a/mps/code/global.c +++ /dev/null @@ -1,1120 +0,0 @@ -/* global.c: ARENA-GLOBAL INTERFACES - * - * $Id$ - * Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .sources: See . design.mps.thread-safety is relevant - * to the functions ArenaEnter and ArenaLeave in this file. - * - * - * TRANSGRESSIONS - * - * .static: Static data is used in ArenaAccess (in order to find the - * appropriate arena) and GlobalsInit. It's checked in GlobalsCheck. - * See . - * - * .non-mod: The Globals structure has many fields which properly belong - * to other modules (see ); GlobalsInit contains code which - * breaks the usual module abstractions. Such instances are documented - * with a tag to the relevant module implementation. Most of the - * functions should be in some other module, they just ended up here by - * confusion over naming. */ - -#include "bt.h" -#include "poolmrg.h" -#include "mps.h" /* finalization */ -#include "poolmv.h" -#include "mpm.h" - -SRCID(global, "$Id$"); - - -/* All static data objects are declared here. See .static */ - -/* */ -static Bool arenaRingInit = FALSE; -static RingStruct arenaRing; /* */ - -/* forward declarations */ -void arenaEnterLock(Arena, int); -void arenaLeaveLock(Arena, int); - - -/* arenaClaimRingLock, arenaReleaseRingLock -- lock/release the arena ring - * - * See . */ - -static void arenaClaimRingLock(void) -{ - LockClaimGlobal(); /* claim the global lock to protect arenaRing */ -} - -static void arenaReleaseRingLock(void) -{ - LockReleaseGlobal(); /* release the global lock protecting arenaRing */ -} - - -/* arenaAnnounce -- add a new arena into the global ring of arenas - * - * On entry, the arena must not be locked (there should be no need, - * because other threads can't know about it). On exit, it will be. */ - -static void arenaAnnounce(Arena arena) -{ - Globals arenaGlobals; - - /* arena checked in ArenaEnter */ - - arenaClaimRingLock(); - ArenaEnter(arena); - arenaGlobals = ArenaGlobals(arena); - AVERT(Globals, arenaGlobals); - RingAppend(&arenaRing, &arenaGlobals->globalRing); - arenaReleaseRingLock(); -} - - -/* arenaDenounce -- remove an arena from the global ring of arenas - * - * After this, no other thread can access the arena through ArenaAccess. - * On entry, the arena should be locked. On exit, it will still be, but - * the lock has been released and reacquired in the meantime, so callers - * should not assume anything about the state of the arena. */ - -static void arenaDenounce(Arena arena) -{ - Globals arenaGlobals; - - AVERT(Arena, arena); - - /* Temporarily give up the arena lock to avoid deadlock, */ - /* see . */ - ArenaLeave(arena); - - /* Detach the arena from the global list. */ - arenaClaimRingLock(); - ArenaEnter(arena); - arenaGlobals = ArenaGlobals(arena); - AVERT(Globals, arenaGlobals); - RingRemove(&arenaGlobals->globalRing); - arenaReleaseRingLock(); -} - - -/* GlobalsCheck -- check the arena globals */ - -Bool GlobalsCheck(Globals arenaGlobals) -{ - Arena arena; - TraceId ti; - Trace trace; - Index i; - Size depth; - RefSet rs; - Rank rank; - - CHECKS(Globals, arenaGlobals); - arena = GlobalsArena(arenaGlobals); - CHECKL(RingCheck(&arenaGlobals->globalRing)); - - CHECKL(MPSVersion() == arenaGlobals->mpsVersionString); - - if (arenaGlobals->lock != NULL) - CHECKD_NOSIG(Lock, arenaGlobals->lock); - - /* no check possible on pollThreshold */ - CHECKL(BoolCheck(arenaGlobals->insidePoll)); - CHECKL(BoolCheck(arenaGlobals->clamped)); - CHECKL(arenaGlobals->fillMutatorSize >= 0.0); - CHECKL(arenaGlobals->emptyMutatorSize >= 0.0); - CHECKL(arenaGlobals->allocMutatorSize >= 0.0); - CHECKL(arenaGlobals->fillMutatorSize - arenaGlobals->emptyMutatorSize - >= arenaGlobals->allocMutatorSize); - CHECKL(arenaGlobals->fillInternalSize >= 0.0); - CHECKL(arenaGlobals->emptyInternalSize >= 0.0); - - CHECKL(BoolCheck(arenaGlobals->bufferLogging)); - CHECKL(RingCheck(&arenaGlobals->poolRing)); - CHECKL(RingCheck(&arenaGlobals->rootRing)); - CHECKL(RingCheck(&arenaGlobals->rememberedSummaryRing)); - CHECKL(arenaGlobals->rememberedSummaryIndex < RememberedSummaryBLOCK); - /* RingIsSingle imples index == 0 */ - CHECKL(!RingIsSingle(&arenaGlobals->rememberedSummaryRing) || - arenaGlobals->rememberedSummaryIndex == 0); - CHECKL(RingCheck(&arena->formatRing)); - CHECKL(RingCheck(&arena->messageRing)); - /* Don't check enabledMessageTypes */ - CHECKL(BoolCheck(arena->isFinalPool)); - if (arena->isFinalPool) { - CHECKD(Pool, arena->finalPool); - } else { - CHECKL(arena->finalPool == NULL); - } - - CHECKL(RingCheck(&arena->threadRing)); - - CHECKL(BoolCheck(arena->insideShield)); - CHECKL(arena->shCacheLimit <= ShieldCacheSIZE); - CHECKL(arena->shCacheI < arena->shCacheLimit); - CHECKL(BoolCheck(arena->suspended)); - - depth = 0; - for (i = 0; i < arena->shCacheLimit; ++i) { - Seg seg = arena->shCache[i]; - if (seg != NULL) { - CHECKD(Seg, seg); - depth += SegDepth(seg); - } - } - CHECKL(depth <= arena->shDepth); - - CHECKL(TraceSetCheck(arena->busyTraces)); - CHECKL(TraceSetCheck(arena->flippedTraces)); - CHECKL(TraceSetSuper(arena->busyTraces, arena->flippedTraces)); - - TRACE_SET_ITER(ti, trace, TraceSetUNIV, arena) - /* */ - if (TraceSetIsMember(arena->busyTraces, trace)) { - CHECKD(Trace, trace); - } else { - /* */ - CHECKL(trace->sig == SigInvalid); - } - /* */ - CHECKL(TraceIdMessagesCheck(arena, ti)); - TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena); - - for(rank = 0; rank < RankLIMIT; ++rank) - CHECKL(RingCheck(&arena->greyRing[rank])); - CHECKL(RingCheck(&arena->chainRing)); - - CHECKL(arena->tracedSize >= 0.0); - CHECKL(arena->tracedTime >= 0.0); - /* no check for arena->lastWorldCollect (Clock) */ - - /* can't write a check for arena->epoch */ - - /* check that each history entry is a subset of the next oldest */ - rs = RefSetEMPTY; - /* note this loop starts from 1; there is no history age 0 */ - for (i=1; i <= LDHistoryLENGTH; ++ i) { - /* check history age 'i'; 'j' is the history index. */ - Index j = (arena->epoch + LDHistoryLENGTH - i) % LDHistoryLENGTH; - CHECKL(RefSetSub(rs, arena->history[j])); - rs = arena->history[j]; - } - /* the oldest history entry must be a subset of the prehistory */ - CHECKL(RefSetSub(rs, arena->prehistory)); - - /* we also check the statics now. */ - CHECKL(BoolCheck(arenaRingInit)); - CHECKL(RingCheck(&arenaRing)); - - CHECKL(BoolCheck(arena->emergency)); - - /* can't check arena->stackAtArenaEnter */ - - return TRUE; -} - - -/* GlobalsInit -- initialize the globals of the arena */ - -Res GlobalsInit(Globals arenaGlobals) -{ - Arena arena; - Index i; - Rank rank; - TraceId ti; - - /* This is one of the first things that happens, */ - /* so check static consistency here. */ - AVER(MPMCheck()); - - arenaClaimRingLock(); - /* Ensure static things are initialized. */ - if (!arenaRingInit) { - /* there isn't an arena ring yet */ - /* */ - arenaRingInit = TRUE; - RingInit(&arenaRing); - ProtSetup(); - } - arenaReleaseRingLock(); - - arena = GlobalsArena(arenaGlobals); - - RingInit(&arenaGlobals->globalRing); - - arenaGlobals->lock = NULL; - - arenaGlobals->pollThreshold = 0.0; - arenaGlobals->insidePoll = FALSE; - arenaGlobals->clamped = FALSE; - arenaGlobals->fillMutatorSize = 0.0; - arenaGlobals->emptyMutatorSize = 0.0; - arenaGlobals->allocMutatorSize = 0.0; - arenaGlobals->fillInternalSize = 0.0; - arenaGlobals->emptyInternalSize = 0.0; - - arenaGlobals->mpsVersionString = MPSVersion(); - arenaGlobals->bufferLogging = FALSE; - RingInit(&arenaGlobals->poolRing); - arenaGlobals->poolSerial = (Serial)0; - RingInit(&arenaGlobals->rootRing); - arenaGlobals->rootSerial = (Serial)0; - RingInit(&arenaGlobals->rememberedSummaryRing); - arenaGlobals->rememberedSummaryIndex = 0; - - RingInit(&arena->threadRing); - arena->threadSerial = (Serial)0; - RingInit(&arena->formatRing); - arena->formatSerial = (Serial)0; - RingInit(&arena->messageRing); - arena->enabledMessageTypes = NULL; - arena->droppedMessages = 0; - arena->isFinalPool = FALSE; - arena->finalPool = NULL; - arena->busyTraces = TraceSetEMPTY; /* */ - arena->flippedTraces = TraceSetEMPTY; /* */ - arena->tracedSize = 0.0; - arena->tracedTime = 0.0; - arena->lastWorldCollect = ClockNow(); - arena->insideShield = FALSE; /* */ - arena->shCacheI = (Size)0; - arena->shCacheLimit = (Size)1; - arena->shDepth = (Size)0; - arena->suspended = FALSE; - for(i = 0; i < ShieldCacheSIZE; i++) - arena->shCache[i] = NULL; - - for (ti = 0; ti < TraceLIMIT; ++ti) { - /* */ - arena->trace[ti].sig = SigInvalid; - /* ti must be valid so that TraceSetIsMember etc. always work */ - arena->trace[ti].ti = ti; - /* */ - arena->tsMessage[ti] = NULL; - arena->tMessage[ti] = NULL; - } - - for(rank = 0; rank < RankLIMIT; ++rank) - RingInit(&arena->greyRing[rank]); - STATISTIC(arena->writeBarrierHitCount = 0); - RingInit(&arena->chainRing); - - arena->epoch = (Epoch)0; /* */ - arena->prehistory = RefSetEMPTY; - for(i = 0; i < LDHistoryLENGTH; ++i) - arena->history[i] = RefSetEMPTY; - - arena->emergency = FALSE; - - arena->stackAtArenaEnter = NULL; - - arenaGlobals->sig = GlobalsSig; - AVERT(Globals, arenaGlobals); - return ResOK; -} - - -/* GlobalsCompleteCreate -- complete creating the globals of the arena - * - * This is like the final initializations in a Create method, except - * there's no separate GlobalsCreate. */ - -Res GlobalsCompleteCreate(Globals arenaGlobals) -{ - Arena arena; - Res res; - void *p; - TraceId ti; - Trace trace; - - AVERT(Globals, arenaGlobals); - arena = GlobalsArena(arenaGlobals); - - /* initialize the message stuff, */ - { - void *v; - - res = ControlAlloc(&v, arena, BTSize(MessageTypeLIMIT), FALSE); - if (res != ResOK) - return res; - arena->enabledMessageTypes = v; - BTResRange(arena->enabledMessageTypes, 0, MessageTypeLIMIT); - } - - TRACE_SET_ITER(ti, trace, TraceSetUNIV, arena) - /* */ - res = TraceIdMessagesCreate(arena, ti); - if(res != ResOK) - return res; - TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena); - - res = ControlAlloc(&p, arena, LockSize(), FALSE); - if (res != ResOK) - return res; - arenaGlobals->lock = (Lock)p; - LockInit(arenaGlobals->lock); - - arenaAnnounce(arena); - - return ResOK; - - /* @@@@ error path */ -} - - -/* GlobalsFinish -- finish the globals of the arena */ - -void GlobalsFinish(Globals arenaGlobals) -{ - Arena arena; - Rank rank; - - AVERT(Globals, arenaGlobals); - arena = GlobalsArena(arenaGlobals); - - STATISTIC_STAT(EVENT2(ArenaWriteFaults, arena, - arena->writeBarrierHitCount)); - - arenaGlobals->sig = SigInvalid; - - RingFinish(&arena->formatRing); - RingFinish(&arena->messageRing); - RingFinish(&arena->threadRing); - for(rank = 0; rank < RankLIMIT; ++rank) - RingFinish(&arena->greyRing[rank]); - RingFinish(&arenaGlobals->rootRing); - RingFinish(&arenaGlobals->poolRing); - RingFinish(&arenaGlobals->globalRing); -} - - -/* GlobalsPrepareToDestroy -- prepare to destroy the globals of the arena - * - * This is like the final initializations in a Destroy method, except - * there's no separate GlobalsDestroy. */ - -void GlobalsPrepareToDestroy(Globals arenaGlobals) -{ - Arena arena; - TraceId ti; - Trace trace; - - AVERT(Globals, arenaGlobals); - - arena = GlobalsArena(arenaGlobals); - arenaDenounce(arena); - - LockReleaseMPM(arenaGlobals->lock); - /* Theoretically, another thread could grab the lock here, but it's */ - /* not worth worrying about, since an attempt after the lock has been */ - /* destroyed would lead to a crash just the same. */ - LockFinish(arenaGlobals->lock); - - TRACE_SET_ITER(ti, trace, TraceSetUNIV, arena) - /* */ - TraceIdMessagesDestroy(arena, ti); - TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena); - - /* report dropped messages (currently in diagnostic varieties only) */ - if(arena->droppedMessages > 0) { - EVENT1(MessagesDropped, arena->droppedMessages); - DIAG_SINGLEF(( "GlobalsPrepareToDestroy_dropped", - "arena->droppedMessages = $U", (WriteFU)arena->droppedMessages, - NULL )); - } - - /* .message.queue.empty: Empty the queue of messages before */ - /* proceeding to finish the arena. It is important that this */ - /* is done before destroying the finalization pool as otherwise */ - /* the message queue would have dangling pointers to messages */ - /* whose memory has been unmapped. */ - if(MessagePoll(arena)) { - EVENT0(MessagesExist); - DIAG_SINGLEF(( "GlobalsPrepareToDestroy_queue", - "Message queue not empty", NULL )); - } - MessageEmpty(arena); - - /* throw away the BT used by messages */ - if (arena->enabledMessageTypes != NULL) { - ControlFree(arena, (void *)arena->enabledMessageTypes, - BTSize(MessageTypeLIMIT)); - arena->enabledMessageTypes = NULL; - } - - /* destroy the final pool (see ) */ - if (arena->isFinalPool) { - /* All this subtlety is because PoolDestroy will call */ - /* ArenaCheck several times. The invariant on finalPool */ - /* and isFinalPool should hold before, after, and during */ - /* the PoolDestroy call */ - Pool pool = arena->finalPool; - - arena->isFinalPool = FALSE; - arena->finalPool = NULL; - PoolDestroy(pool); - } -} - -Ring GlobalsRememberedSummaryRing(Globals global) -{ - AVERT(Globals, global); - - return &global->rememberedSummaryRing; -} - - -/* ArenaEnter -- enter the state where you can look at the arena */ - -/* TODO: The THREAD_SINGLE and PROTECTION_NONE build configs aren't regularly - tested, though they might well be useful for embedded custom targets. - Should test them. RB 2012-09-03 */ - -#if defined(THREAD_SINGLE) && defined(PROTECTION_NONE) -void (ArenaEnter)(Arena arena) -{ - /* Don't need to lock, just check. */ - AVERT(Arena, arena); -} -#else -void ArenaEnter(Arena arena) -{ - arenaEnterLock(arena, 0); -} -#endif - -/* The recursive argument specifies whether to claim the lock - recursively or not. */ -void arenaEnterLock(Arena arena, int recursive) -{ - Lock lock; - - /* This check is safe to do outside the lock. Unless the client - is also calling ArenaDestroy, but that's a protocol violation by - the client if so. */ - AVER(TESTT(Arena, arena)); - - StackProbe(StackProbeDEPTH); - lock = ArenaGlobals(arena)->lock; - if(recursive) { - LockClaimRecursive(lock); - } else { - LockClaim(lock); - } - AVERT(Arena, arena); /* can't AVER it until we've got the lock */ - if(recursive) { - /* already in shield */ - } else { - ShieldEnter(arena); - } - return; -} - -/* Same as ArenaEnter, but for the few functions that need to be - reentrant with respect to some part of the MPS. - For example, mps_arena_has_addr. */ - -void ArenaEnterRecursive(Arena arena) -{ - arenaEnterLock(arena, 1); -} - -/* ArenaLeave -- leave the state where you can look at MPM data structures */ - -#if defined(THREAD_SINGLE) && defined(PROTECTION_NONE) -void (ArenaLeave)(Arena arena) -{ - /* Don't need to lock, just check. */ - AVERT(Arena, arena); -} -#else -void ArenaLeave(Arena arena) -{ - arenaLeaveLock(arena, 0); -} -#endif - -void arenaLeaveLock(Arena arena, int recursive) -{ - Lock lock; - - AVERT(Arena, arena); - - lock = ArenaGlobals(arena)->lock; - - if(recursive) { - /* no need to leave shield */ - } else { - ShieldLeave(arena); - } - ProtSync(arena); /* */ - if(recursive) { - LockReleaseRecursive(lock); - } else { - LockReleaseMPM(lock); - } - return; -} - -void ArenaLeaveRecursive(Arena arena) -{ - arenaLeaveLock(arena, 1); -} - -/* mps_exception_info -- pointer to exception info - * - * This is a hack to make exception info easier to find in a release - * version. The format is platform-specific. We won't necessarily - * publish this. */ - -MutatorFaultContext mps_exception_info = NULL; - - -/* ArenaAccess -- deal with an access fault - * - * This is called when a protected address is accessed. The mode - * corresponds to which mode flags need to be cleared in order for the - * access to continue. */ - -Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context) -{ - Seg seg; - Ring node, nextNode; - Res res; - - arenaClaimRingLock(); /* */ - mps_exception_info = context; - AVER(RingCheck(&arenaRing)); - - RING_FOR(node, &arenaRing, nextNode) { - Globals arenaGlobals = RING_ELT(Globals, globalRing, node); - Arena arena = GlobalsArena(arenaGlobals); - Root root; - - ArenaEnter(arena); /* */ - /* @@@@ The code below assumes that Roots and Segs are disjoint. */ - /* It will fall over (in TraceSegAccess probably) if there is a */ - /* protected root on a segment. */ - /* It is possible to overcome this restriction. */ - if (SegOfAddr(&seg, arena, addr)) { - mps_exception_info = NULL; - arenaReleaseRingLock(); - /* An access in a different thread may have already caused the - * protection to be cleared. This avoids calling TraceAccess on - * protection that has already been cleared on a separate thread. */ - mode &= SegPM(seg); - if (mode != AccessSetEMPTY) { - res = PoolAccess(SegPool(seg), seg, addr, mode, context); - AVER(res == ResOK); /* Mutator can't continue unless this succeeds */ - } - ArenaLeave(arena); - return TRUE; - } else if (RootOfAddr(&root, arena, addr)) { - mps_exception_info = NULL; - arenaReleaseRingLock(); - mode &= RootPM(root); - if (mode != AccessSetEMPTY) - RootAccess(root, mode); - ArenaLeave(arena); - return TRUE; - } - - ArenaLeave(arena); - } - - mps_exception_info = NULL; - arenaReleaseRingLock(); - return FALSE; -} - - -/* ArenaPoll -- trigger periodic actions - * - * Poll all background activities to see if they need to do anything. - * ArenaPoll does nothing if the amount of committed memory is less than - * the arena poll threshold. This means that actions are taken as the - * memory demands increase. - * - * @@@@ This is where time is "stolen" from the mutator in addition - * to doing what it asks and servicing accesses. This is where the - * amount of time should be controlled, perhaps by passing time - * limits to the various other activities. - * - * @@@@ Perhaps this should be based on a process table rather than a - * series of manual steps for looking around. This might be worthwhile - * if we introduce background activities other than tracing. */ - -#ifdef MPS_PROD_EPCORE -void (ArenaPoll)(Globals globals) -{ - /* Don't poll, just check. */ - AVERT(Globals, globals); -} -#else -void ArenaPoll(Globals globals) -{ - Arena arena; - Clock start; - Count quanta; - Size tracedSize; - double nextPollThreshold = 0.0; - - AVERT(Globals, globals); - - if (globals->clamped) - return; - if (globals->insidePoll) - return; - if(globals->fillMutatorSize < globals->pollThreshold) - return; - - globals->insidePoll = TRUE; - - /* fillMutatorSize has advanced; call TracePoll enough to catch up. */ - arena = GlobalsArena(globals); - start = ClockNow(); - quanta = 0; - while(globals->pollThreshold <= globals->fillMutatorSize) { - tracedSize = TracePoll(globals); - - if(tracedSize == 0) { - /* No work to do. Sleep until NOW + a bit. */ - nextPollThreshold = globals->fillMutatorSize + ArenaPollALLOCTIME; - } else { - /* We did one quantum of work; consume one unit of 'time'. */ - quanta += 1; - arena->tracedSize += tracedSize; - nextPollThreshold = globals->pollThreshold + ArenaPollALLOCTIME; - } - - /* Advance pollThreshold; check: enough precision? */ - AVER(nextPollThreshold > globals->pollThreshold); - globals->pollThreshold = nextPollThreshold; - } - - /* Don't count time spent checking for work, if there was no work to do. */ - if(quanta > 0) { - arena->tracedTime += (ClockNow() - start) / (double) ClocksPerSec(); - } - - AVER(globals->fillMutatorSize < globals->pollThreshold); - - globals->insidePoll = FALSE; -} -#endif - -/* Work out whether we have enough time here to collect the world, - * and whether much time has passed since the last time we did that - * opportunistically. */ -static Bool arenaShouldCollectWorld(Arena arena, - double interval, - double multiplier, - Clock now, - Clock clocks_per_sec) -{ - double scanRate; - Size arenaSize; - double arenaScanTime; - double sinceLastWorldCollect; - - /* don't collect the world if we're not given any time */ - if ((interval > 0.0) && (multiplier > 0.0)) { - /* don't collect the world if we're already collecting. */ - if (arena->busyTraces == TraceSetEMPTY) { - /* don't collect the world if it's very small */ - arenaSize = ArenaCommitted(arena) - ArenaSpareCommitted(arena); - if (arenaSize > 1000000) { - /* how long would it take to collect the world? */ - if ((arena->tracedSize > 1000000.0) && - (arena->tracedTime > 1.0)) - scanRate = arena->tracedSize / arena->tracedTime; - else - scanRate = 25000000.0; /* a reasonable default. */ - arenaScanTime = arenaSize / scanRate; - arenaScanTime += 0.1; /* for overheads. */ - - /* how long since we last collected the world? */ - sinceLastWorldCollect = ((now - arena->lastWorldCollect) / - (double) clocks_per_sec); - /* have to be offered enough time, and it has to be a long time - * since we last did it. */ - if ((interval * multiplier > arenaScanTime) && - sinceLastWorldCollect > arenaScanTime * 10.0) { - return TRUE; - } - } - } - } - return FALSE; -} - -Bool ArenaStep(Globals globals, double interval, double multiplier) -{ - Size scanned; - Bool stepped; - Clock start, end, now; - Clock clocks_per_sec; - Arena arena; - - AVERT(Globals, globals); - AVER(interval >= 0.0); - AVER(multiplier >= 0.0); - - arena = GlobalsArena(globals); - clocks_per_sec = ClocksPerSec(); - - start = ClockNow(); - end = start + (Clock)(interval * clocks_per_sec); - AVER(end >= start); - - stepped = FALSE; - - if (arenaShouldCollectWorld(arena, interval, multiplier, - start, clocks_per_sec)) - { - ArenaStartCollect(globals, TraceStartWhyOPPORTUNISM); - arena->lastWorldCollect = start; - stepped = TRUE; - } - - /* loop while there is work to do and time on the clock. */ - do { - scanned = TracePoll(globals); - now = ClockNow(); - if (scanned > 0) { - stepped = TRUE; - arena->tracedSize += scanned; - } - } while ((scanned > 0) && (now < end)); - - if (stepped) { - arena->tracedTime += (now - start) / (double) clocks_per_sec; - } - - return stepped; -} - -/* ArenaFinalize -- registers an object for finalization - * - * See . */ - -Res ArenaFinalize(Arena arena, Ref obj) -{ - Res res; - - AVERT(Arena, arena); - AVER(ArenaHasAddr(arena, (Addr)obj)); - - if (!arena->isFinalPool) { - Pool pool; - - res = PoolCreate(&pool, arena, PoolClassMRG()); - if (res != ResOK) - return res; - arena->finalPool = pool; - arena->isFinalPool = TRUE; - } - - res = MRGRegister(arena->finalPool, obj); - return res; -} - - -/* ArenaDefinalize -- removes one finalization registration of an object - * - * See . */ - -Res ArenaDefinalize(Arena arena, Ref obj) -{ - Res res; - - AVERT(Arena, arena); - AVER(ArenaHasAddr(arena, (Addr)obj)); - - if (!arena->isFinalPool) { - return ResFAIL; - } - res = MRGDeregister(arena->finalPool, obj); - return res; -} - - -/* Peek / Poke */ - -Ref ArenaPeek(Arena arena, Ref *p) -{ - Seg seg; - Ref ref; - - AVERT(Arena, arena); - - if (SegOfAddr(&seg, arena, (Addr)p)) - ref = ArenaPeekSeg(arena, seg, p); - else - ref = *p; - return ref; -} - -Ref ArenaPeekSeg(Arena arena, Seg seg, Ref *p) -{ - Ref ref; - - AVERT(Arena, arena); - AVERT(Seg, seg); - - AVER(SegBase(seg) <= (Addr)p); - AVER((Addr)p < SegLimit(seg)); - /* TODO: Consider checking addr's alignment using seg->pool->alignment */ - - ShieldExpose(arena, seg); - ref = *p; - ShieldCover(arena, seg); - return ref; -} - -void ArenaPoke(Arena arena, Ref *p, Ref ref) -{ - Seg seg; - - AVERT(Arena, arena); - /* Can't check addr as it is arbitrary */ - /* Can't check ref as it is arbitrary */ - - if (SegOfAddr(&seg, arena, (Addr)p)) - ArenaPokeSeg(arena, seg, p, ref); - else - *p = ref; -} - -void ArenaPokeSeg(Arena arena, Seg seg, Ref *p, Ref ref) -{ - RefSet summary; - - AVERT(Arena, arena); - AVERT(Seg, seg); - AVER(SegBase(seg) <= (Addr)p); - AVER((Addr)p < SegLimit(seg)); - /* TODO: Consider checking addr's alignment using seg->pool->alignment */ - /* ref is arbitrary and can't be checked */ - - ShieldExpose(arena, seg); - *p = ref; - summary = SegSummary(seg); - summary = RefSetAdd(arena, summary, (Addr)ref); - SegSetSummary(seg, summary); - ShieldCover(arena, seg); -} - - -/* ArenaRead -- read a single reference, possibly through a barrier - * - * This forms part of a software barrier. It provides fine-grain access - * to single references in segments. - * - * See also PoolSingleAccess and PoolSegAccess. */ - -Ref ArenaRead(Arena arena, Ref *p) -{ - Bool b; - Seg seg = NULL; /* suppress "may be used uninitialized" */ - Rank rank; - - AVERT(Arena, arena); - - b = SegOfAddr(&seg, arena, (Addr)p); - AVER(b == TRUE); - - /* .read.flipped: We AVER that the reference that we are reading */ - /* refers to an object for which all the traces that the object is */ - /* white for are also flipped. This is because we don't have any */ - /* write-barrier (in the sense of write-barrier collectors) */ - /* mechanism in place for reading (strictly speaking, writing */ - /* it somewhere after having read it) references that are white. */ - AVER(TraceSetSub(SegWhite(seg), arena->flippedTraces)); - - /* .read.conservative: Scan according to rank phase-of-trace, */ - /* See */ - /* If the segment isn't grey it doesn't need scanning, and in fact it - would be wrong to even ask what rank to scan it at, since there might - not be any traces running. */ - if (TraceSetInter(SegGrey(seg), arena->flippedTraces) != TraceSetEMPTY) { - rank = TraceRankForAccess(arena, seg); - TraceScanSingleRef(arena->flippedTraces, rank, arena, seg, p); - } - - /* We don't need to update the Seg Summary as in PoolSingleAccess - * because we are not changing it after it has been scanned. */ - - /* get the possibly fixed reference */ - return ArenaPeekSeg(arena, seg, p); -} - - -/* GlobalsDescribe -- describe the arena globals */ - -Res GlobalsDescribe(Globals arenaGlobals, mps_lib_FILE *stream) -{ - Res res; - Arena arena; - Ring node, nextNode; - Index i; - - if (!TESTT(Globals, arenaGlobals)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - arena = GlobalsArena(arenaGlobals); - res = WriteF(stream, - " mpsVersion $S\n", arenaGlobals->mpsVersionString, - " lock $P\n", (WriteFP)arenaGlobals->lock, - " pollThreshold $U kB\n", - (WriteFU)(arenaGlobals->pollThreshold / 1024), - arenaGlobals->insidePoll ? "inside poll\n" : "outside poll\n", - arenaGlobals->clamped ? "clamped\n" : "released\n", - " fillMutatorSize $U kB\n", - (WriteFU)(arenaGlobals->fillMutatorSize / 1024), - " emptyMutatorSize $U kB\n", - (WriteFU)(arenaGlobals->emptyMutatorSize / 1024), - " allocMutatorSize $U kB\n", - (WriteFU)(arenaGlobals->allocMutatorSize / 1024), - " fillInternalSize $U kB\n", - (WriteFU)(arenaGlobals->fillInternalSize / 1024), - " emptyInternalSize $U kB\n", - (WriteFU)(arenaGlobals->emptyInternalSize / 1024), - " poolSerial $U\n", (WriteFU)arenaGlobals->poolSerial, - " rootSerial $U\n", (WriteFU)arenaGlobals->rootSerial, - " formatSerial $U\n", (WriteFU)arena->formatSerial, - " threadSerial $U\n", (WriteFU)arena->threadSerial, - arena->insideShield ? "inside shield\n" : "outside shield\n", - " busyTraces $B\n", (WriteFB)arena->busyTraces, - " flippedTraces $B\n", (WriteFB)arena->flippedTraces, - /* @@@@ no TraceDescribe function */ - " epoch $U\n", (WriteFU)arena->epoch, - NULL); - if (res != ResOK) return res; - - for(i=0; i < LDHistoryLENGTH; ++ i) { - res = WriteF(stream, - " history[$U] = $B\n", i, arena->history[i], - NULL); - if (res != ResOK) return res; - } - - res = WriteF(stream, - " [note: indices are raw, not rotated]\n" - " prehistory = $B\n", (WriteFB)arena->prehistory, - NULL); - if (res != ResOK) return res; - - res = WriteF(stream, - " suspended $S\n", arena->suspended ? "YES" : "NO", - " shDepth $U\n", arena->shDepth, - " shCacheI $U\n", arena->shCacheI, - /* @@@@ should SegDescribe the cached segs? */ - NULL); - if (res != ResOK) return res; - - res = RootsDescribe(arenaGlobals, stream); - if (res != ResOK) return res; - - RING_FOR(node, &arenaGlobals->poolRing, nextNode) { - Pool pool = RING_ELT(Pool, arenaRing, node); - res = PoolDescribe(pool, stream); - if (res != ResOK) return res; - } - - RING_FOR(node, &arena->formatRing, nextNode) { - Format format = RING_ELT(Format, arenaRing, node); - res = FormatDescribe(format, stream); - if (res != ResOK) return res; - } - - RING_FOR(node, &arena->threadRing, nextNode) { - Thread thread = ThreadRingThread(node); - res = ThreadDescribe(thread, stream); - if (res != ResOK) return res; - } - - /* @@@@ What about grey rings? */ - return res; -} - - -/* ArenaSetEmergency -- move the arena into emergency mode - * - * Emergency mode is set when garbage collection cannot make progress because - * it can't allocate memory. - * - * Emergency mode affects the choice of PoolFixMethod in new ScanStates. - * See ScanStateInit. - * - * If the traces aren't normal GC traces, and have their fix method - * set to something other than PoolFix, then this won't affect the choice - * of fix method in ScanStateInit and so won't have any effect. Whatever - * caused the first failure will likely repeat. - */ - -void ArenaSetEmergency(Arena arena, Bool emergency) -{ - AVERT(Arena, arena); - AVERT(Bool, emergency); - - DIAG_SINGLEF(( "ArenaSetEmergency", - "emergency: $U", (WriteFU)emergency, NULL )); - - arena->emergency = emergency; -} - -Bool ArenaEmergency(Arena arena) -{ - AVERT(Arena, arena); - return arena->emergency; -} - - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/gp.gmk b/mps/code/gp.gmk deleted file mode 100644 index 8e16b524c38..00000000000 --- a/mps/code/gp.gmk +++ /dev/null @@ -1,72 +0,0 @@ -# gp.gmk: GNUMAKEFILE FRAGMENT FOR GNU CC/GPROF -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. -# -# This file is included by platform makefiles that use the GNU CC -# compiler with gprof. It defines the compiler specific variables -# that the common makefile fragment () requires. - - -CC = gcc -CFLAGSCOMPILER = \ - -ansi -pedantic -Wall -Werror -Wpointer-arith \ - -Wstrict-prototypes -Wmissing-prototypes \ - -Winline -Waggregate-return -Wnested-externs \ - -Wcast-qual -Wshadow -pg -CFLAGSDEBUG = -g -ggdb3 -CFLAGSOPT = -O -g -ggdb3 - -# gcc -MM generates a dependency line of the form: -# thing.o : thing.c ... -# The sed line converts this into: -# //thing.o //thing.d : thing.c ... -# @@ This sequence is vulnerable to interrupts (for some reason) - -define gendep - $(SHELL) -ec "gcc -c $(CFLAGS) -MM $< | \ - sed '/:/s!$*.o!$(@D)/& $(@D)/$*.d!' > $@" -endef - -include comm.gmk - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/ld.c b/mps/code/ld.c deleted file mode 100644 index 766bfe5d823..00000000000 --- a/mps/code/ld.c +++ /dev/null @@ -1,252 +0,0 @@ -/* ld.c: LOCATION DEPENDENCY IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .def: A location dependency records the fact that the bit-patterns - * of some references will be used directly (most likely for - * hashing), and provides a protocol for finding out whether that - * dependency has become stale because a reference has been changed (by - * a moving memory manager). - * - * .rationale: The client may build hash-tables using pointer hashing. - * The collector may change the values of the pointers transparently, - * by fixing them and moving the objects. The hash function will no - * longer return the same value, and the object can't be found in - * the expected bucket. When the client can't find an object in a - * hashtable it must check to see if any of the references in the table - * have moved, and rehash if they have. Location dependency provides - * a reasonably accurate way of determining whether this has happened. - * - * .impl: A location dependency consists of an epoch (monotonically - * increasing notion of time) and a reference set. The epoch records - * when the location dependency started, and the reference set - * accumulates an approximation to the set of references which are - * depended on. The client can check to see if any of these - * references have moved since the epoch. - * - * .history: The current epoch, and a history of object movement - * are recorded in the arena. Each slot in the history contains a - * summary of all the movement since an earlier epoch (maintained by - * LDAge). To see if a dependency has become stale all that - * is needed is to see whether its reference set intersects with the - * movement since its epoch. - * - * .mod: LDHistoryLENGTH is used as a modulus to calculate the offset - * of an epoch in the history, so it's best if this is a power of two. - * () - * - * .epoch-size: The epoch should probably be a longer integer to avoid - * the possibility of overflow. - * (32 bits only gives 50 days at 1ms frequency) - * - * .ld.access: Accesses (reads and writes) to the ld structure must be - * "wrapped" with an ShieldExpose/Cover pair if and only if the access - * is taking place inside the arena. Currently this is only the case for - * LDReset. - */ - -#include "mpm.h" - -SRCID(ld, "$Id$"); - - -/* LDReset -- reset a dependency to empty - * - * .reset.sync: This does not need to be synchronized with LDAge - * because if the epoch advances after it is read the dependency - * will simply include movement for more time than necessary. - */ -void LDReset(mps_ld_t ld, Arena arena) -{ - Bool b; - Seg seg; - - AVER(ld != NULL); - AVERT(Arena, arena); - - b = SegOfAddr(&seg, arena, (Addr)ld); - if (b) - ShieldExpose(arena, seg); /* .ld.access */ - ld->_epoch = arena->epoch; - ld->_rs = RefSetEMPTY; - if (b) - ShieldCover(arena, seg); -} - - -/* LDAdd -- add a reference to a dependency - * - * .add.lock-free: This function is thread safe with respect to the - * (rest of the) mps. It is unnecessary to claim locks before calling - * this function. - * - * .add.user-serial: - * However, this function is _not_ thread safe with respect to itself. - * Users should ensure that calls to LDAdd operating on the same LD are - * serialized. - * - * .add.sync: Add must take place _before_ the location of the reference - * is depended on. If the reference changes between adding and - * depending it will show up as moved because the movement will have - * occured since the epoch recorded in the dependency. If the location - * were used first only the new location of the reference would end up - * in the set. - */ -void LDAdd(mps_ld_t ld, Arena arena, Addr addr) -{ - AVER(ld->_epoch <= arena->epoch); - /* AVERT(Arena, arena) -- see .add.lock-free */ - - ld->_rs = RefSetAdd(arena, ld->_rs, addr); -} - - -/* LDIsStale -- check whether a dependency is stale - * - * .stale.thread-safe: This function is thread safe. It will return a - * correct (but possibly conservative) answer regardless of the number - * of calls to LDAge anywhere during the function. Update with care. - * - * .stale.current: If the dependency's epoch is the current epoch, - * nothing can have moved since it was initialized. - * - * .stale.recent: If the dependency is recent, see if it intersects - * with everything which has moved since it was initialized. - * - * .stale.recent.conservative: The refset from the history table is - * loaded before we check whether ld->_epoch is "recent" with respect to - * the current epoch. This means that we may (conservatively) decide - * to use the prehistory instead. - * - * .stale.old: Otherwise, if the dependency is older than the length - * of the history, check it against all movement that has ever occured. - */ -Bool LDIsStale(mps_ld_t ld, Arena arena, Addr addr) -{ - RefSet rs; - - UNUSED(addr); - - AVER(ld->_epoch <= arena->epoch); - /* AVERT(Arena, arena) -- .stale.thread-safe */ - - if (arena->epoch == ld->_epoch) /* .stale.current */ - return FALSE; - - /* Load the history refset, _then_ check to see if it's recent. - * This may in fact load an okay refset, which we decide to throw - * away and use the pre-history instead. */ - rs = arena->history[ld->_epoch % LDHistoryLENGTH]; - /* .stale.recent */ - /* .stale.recent.conservative */ - if (arena->epoch - ld->_epoch > LDHistoryLENGTH) { - rs = arena->prehistory; /* .stale.old */ - } - - return RefSetInter(ld->_rs, rs) != RefSetEMPTY; -} - - -/* LDAge -- age the arena by adding a moved set - * - * This stores the fact that a set of references has changed in - * the history in the arena structure, and increments the epoch. - * - * This is only called during a 'flip', because it must be atomic - * w.r.t. the mutator (and therefore w.r.t. LdIsStale). This is - * because it updates the notion of the 'current' and 'oldest' history - * entries. - */ -void LDAge(Arena arena, RefSet rs) -{ - Size i; - - AVERT(Arena, arena); - AVER(rs != RefSetEMPTY); - - /* Replace the entry for epoch - LDHistoryLENGTH by an empty */ - /* set which will become the set which has moved since the */ - /* current epoch. */ - arena->history[arena->epoch % LDHistoryLENGTH] = RefSetEMPTY; - - /* Record the fact that the moved set has moved, by adding it */ - /* to all the sets in the history, including the set for the */ - /* current epoch. */ - for(i = 0; i < LDHistoryLENGTH; ++i) - arena->history[i] = RefSetUnion(arena->history[i], rs); - - /* This is the union of all movement since time zero. */ - arena->prehistory = RefSetUnion(arena->prehistory, rs); - - /* Advance the epoch by one. */ - ++arena->epoch; - AVER(arena->epoch != 0); /* .epoch-size */ -} - - -/* LDMerge -- merge two location dependencies - * - * .merge.lock-free: This function is thread-safe with respect to the - * (rest of the) MPS. It is unnecessary to claim locks before calling - * this function. - */ -void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from) -{ - /* AVERT(Arena, arena); -- .merge.lock-free */ - AVER(ld != NULL); - AVER(ld->_epoch <= arena->epoch); - AVER(from != NULL); - AVER(from->_epoch <= arena->epoch); - - /* If a reference has been added since epoch e1 then I've */ - /* certainly added since epoch e0 where e0 < e1. Therefore */ - /* the epoch of the merged ld is the minimum. */ - if (from->_epoch < ld->_epoch) - ld->_epoch = from->_epoch; - - /* The set of references added is the union of the two. */ - ld->_rs = RefSetUnion(ld->_rs, from->_rs); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/libcbt.c b/mps/code/libcbt.c deleted file mode 100644 index 7e13734ecf8..00000000000 --- a/mps/code/libcbt.c +++ /dev/null @@ -1,111 +0,0 @@ -/* libcbt: MPS LIBRARY CALLBACK TEST - * - * $Header$ - * Copyright (C) 2005 Ravenbrook Limited. See end of file for license. - * - * This is a simple test of the MPS Library Callback interface - * (mpslibcb.h). */ - -#include "mps.h" -#include "mpsavm.h" -#include "mpslib.h" -#include "mpslibcb.h" - -#include "testlib.h" - -#include -#include - -void libcbt_assert_fail(const char *); -mps_clock_t libcbt_clock(void); - -int main(void) -{ - int res; - int defects = 0; - mps_arena_t arena; - - res = mps_lib_callback_register("not a callback", (void(*)(void))0); - if(MPS_RES_OK == res) { - printf("mps_lib_callback_register claims to successfully register\n" - "an interface that does not exist.\n"); - ++ defects; - } - die(mps_lib_callback_register("mps_lib_assert_fail", - (void(*)(void))libcbt_assert_fail), - "register assert_fail"); - /* The following functions are registered in the order that you get by - * providing no functions and then providing functions as they are - * required by assertionn failures. - * Interestingly, for this very simple test, only mps_clock is - * required. */ - die(mps_lib_callback_register("mps_clock", - (mps_lib_function_t)libcbt_clock), - "register clock"); - die(mps_arena_create(&arena, mps_arena_class_vm(), (size_t)1000*1000), - "mps_arena_create"); - if(defects) { - printf("Conclusion: Defects detected.\n"); - } else { - printf("Conclusion: Failed to find any defects.\n"); - } - return 0; -} - -void libcbt_assert_fail(const char *message) -{ - fflush(stdout); - fprintf(stderr, "\nMPS ASSERTION FAILURE (TEST): %s\n", message); - fflush(stderr); - abort(); -} - -mps_clock_t libcbt_clock(void) -{ - static mps_clock_t c = 0; - - ++ c; - return c; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2005 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/lii3gc.gmk b/mps/code/lii3gc.gmk deleted file mode 100644 index 58176c0571f..00000000000 --- a/mps/code/lii3gc.gmk +++ /dev/null @@ -1,61 +0,0 @@ -# lii3gc.gmk: BUILD FOR LINUX/INTEL/GCC PLATFORM -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - -PFM = lii3gc - -THREADSRC = lockli.c thix.c pthrdext.c -THREADLIB = -lpthread - -MPMPF = ${THREADSRC} vmix.c \ - protix.c protli.c proti3.c prmci3li.c ssixi3.c span.c - -LIBS = -lm ${THREADLIB} - -include gc.gmk - -CC = cc - -include comm.gmk - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/lii6gc.gmk b/mps/code/lii6gc.gmk deleted file mode 100644 index 4c48923b082..00000000000 --- a/mps/code/lii6gc.gmk +++ /dev/null @@ -1,61 +0,0 @@ -# lii6gc.gmk: BUILD FOR LINUX/x64/GCC PLATFORM -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - -PFM = lii6gc - -THREADSRC = lockli.c thix.c pthrdext.c -THREADLIB = -lpthread - -MPMPF = ${THREADSRC} vmix.c \ - protix.c protli.c proti6.c prmci6li.c ssixi6.c span.c - -LIBS = -lm ${THREADLIB} - -include gc.gmk - -CC = cc - -include comm.gmk - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/lo.h b/mps/code/lo.h deleted file mode 100644 index 55acbec0a8e..00000000000 --- a/mps/code/lo.h +++ /dev/null @@ -1,83 +0,0 @@ -/* lo.h: LEAF OBJECT POOL CLASS INTERFACE - * - * $Id$ - * - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * The Leaf Object PoolClass is an automatically managed (ie garbage - * collected) pool for managing "leaf" objects. Leaf objects are - * objects that have no references or no references that need tracing - * (ie the objects they refer too are non-moving and are manually - * managed). - * - * This Class has the following features: - * - * Approximately 6% (asymptotically) space overhead on managed objects. - * - * Automatically reclaims memory used by objects no longer reachable - * from the roots. - * - * Non-moving. References to objects in this pool will never change - * due to "fixing". - * - * Buffers will always "commit". When allocating using a buffer, - * commit will never fail. - * - * The following caveat applies: - * - * Space and time performance will degrade when fragmentation - * increases. - */ - -#ifndef lo_h -#define lo_h - -#include "mpm.h" - -typedef struct LOStruct *LO; - -extern PoolClass PoolClassLO(void); - -#endif /* lo_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/locbwcss.c b/mps/code/locbwcss.c deleted file mode 100644 index 766b427ce30..00000000000 --- a/mps/code/locbwcss.c +++ /dev/null @@ -1,247 +0,0 @@ -/* locbwcss.c: LOCUS BACKWARDS COMPATIBILITY STRESS TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpscmvff.h" -#include "mpslib.h" -#include "mpsavm.h" -#include "testlib.h" -#include "mps.h" - -#include -#include - - -/* some constants */ - -#define TRUE 1 -#define FALSE 0 - -#define iterationCount 30 /* number of iterations */ -#define allocsPerIteration 8 /* number of allocs each iteration */ -#define chunkSize ((size_t)65536) /* our allocation chunk size */ - -#define testArenaSIZE \ - ((size_t)(chunkSize * iterationCount * allocsPerIteration * 3)) - - -#define AddressOffset(b, l) \ - ((size_t)((char *)(l) - (char *)(b))) - - -/* PoolStat -- maintain data about contiguous allocations */ - -typedef struct PoolStatStruct *PoolStat; - -typedef struct PoolStatStruct { - mps_pool_t pool; /* the pool being measured */ - size_t objSize; /* size of each allocation */ - mps_addr_t min; /* lowest address lock allocated to the pool */ - mps_addr_t max; /* highest address lock allocated to the pool */ - int ncCount; /* count of non-contiguous allocations */ - int aCount; /* count of allocations */ - int fCount; /* count of frees */ -} PoolStatStruct; - - - -static mps_addr_t allocObject(mps_pool_t pool, size_t size) -{ - mps_addr_t addr; - die(mps_alloc(&addr, pool, size), - "Allocate Object"); - return addr; -} - - -static void recordNewObjectStat(PoolStat stat, mps_addr_t obj) -{ - stat->aCount++; - if (obj < stat->min) { - if (AddressOffset(obj, stat->min) > stat->objSize) { - stat->ncCount++; - } - stat->min = obj; - } else if (obj > stat->max) { - if (AddressOffset(stat->max, obj) > stat->objSize) { - stat->ncCount++; - } - stat->max = obj; - } -} - -static void recordFreedObjectStat(PoolStat stat) -{ - stat->fCount++; -} - - -static void poolStatInit(PoolStat stat, mps_pool_t pool, size_t objSize) -{ - mps_addr_t s1, s2, s3; - - stat->pool = pool; - stat->objSize = objSize; - stat->ncCount = 0; - stat->aCount = 0; - stat->fCount = 0; - - /* allocate 3 half-size sentinel objects, freeing the middle one */ - /* to leave a bit of space for the control pool */ - s1 = allocObject(pool, objSize / 2); - stat->min = s1; - stat->max = s1; - stat->aCount++; - - s2 = allocObject(pool, objSize / 2); - recordNewObjectStat(stat, s2); - s3 = allocObject(pool, objSize / 2); - recordNewObjectStat(stat, s3); - - mps_free(pool, s2, objSize / 2); - recordFreedObjectStat(stat); - -} - - -static void allocMultiple(PoolStat stat) -{ - mps_addr_t objects[allocsPerIteration]; - int i; - - /* allocate a few objects, and record stats for them */ - for (i = 0; i < allocsPerIteration; i++) { - mps_addr_t obj = allocObject(stat->pool, stat->objSize); - recordNewObjectStat(stat, obj); - objects[i] = obj; - } - - /* free one of the objects, to make the test more interesting */ - i = rnd() % allocsPerIteration; - mps_free(stat->pool, objects[i], stat->objSize); - recordFreedObjectStat(stat); - -} - - -/* reportResults - print a report on a PoolStat */ - -static void reportResults(PoolStat stat, char *name) -{ - printf("\nResults for "); - fputs(name, stdout); - printf("\n"); - printf(" Allocated %"PRIuLONGEST" objects\n", (ulongest_t)stat->aCount); - printf(" Freed %"PRIuLONGEST" objects\n", (ulongest_t)stat->fCount); - printf(" There were %lu non-contiguous allocations\n", - (unsigned long)stat->ncCount); - printf(" Address range from %p to %p\n", - (void *)stat->min, (void *)stat->max); - printf("\n"); -} - - -static void testInArena(mps_arena_t arena) -{ - mps_pool_t lopool, hipool; - PoolStatStruct lostruct; /* stats about lopool */ - PoolStatStruct histruct; /* stats about lopool */ - PoolStat lostat = &lostruct; - PoolStat histat = &histruct; - int i; - - die(mps_pool_create(&hipool, arena, mps_class_mvff(), - chunkSize, chunkSize, 1024, - TRUE, TRUE, TRUE), - "Create HI MFFV"); - - die(mps_pool_create(&lopool, arena, mps_class_mvff(), - chunkSize, chunkSize, 1024, - FALSE, FALSE, TRUE), - "Create LO MFFV"); - - poolStatInit(lostat, lopool, chunkSize); - poolStatInit(histat, hipool, chunkSize); - - /* iterate, allocating objects */ - for (i=0; imax > histat->min) { - printf("\nFOUND PROBLEM - low range overlaps high\n"); - } else if (lostat->ncCount != 0 || histat->ncCount != 0) { - printf("\nFOUND POSSIBLE PROBLEM - some non-contiguous allocations\n"); - } else { - printf("\nNo problems detected.\n"); - } - - mps_pool_destroy(hipool); - mps_pool_destroy(lopool); -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vmnz(), testArenaSIZE), - "mps_arena_create"); - - testInArena(arena); - - mps_arena_destroy(arena); - - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/lock.h b/mps/code/lock.h deleted file mode 100644 index 1431bbacd85..00000000000 --- a/mps/code/lock.h +++ /dev/null @@ -1,267 +0,0 @@ -/* lock.h: RECURSIVE LOCKS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .description: [@@@@ Should be combined with ] - * This defines the type Lock, which supports simple recursive - * locking. Locking ensures that only a single thread may be running - * with a lock held. By claiming a lock in some code, this ensures - * that only one thread can be running in that code at a time. This - * in turn can be used to protect different threads from trying to - * read or update data structures which are in a transitional state. - * - * At most one thread may own a lock at a time. A lock is initialised - * without an owner. A lock should not have an owner when it is - * finished. Claiming the lock will wait until the lock is not owned - * by another thread and then cause the current thread to become the - * owner. Releasing the the lock will relinquish ownership if the - * number of releases matches the number of claims. - * - * To use a lock a structure of type LockStruct must be allocated. - * This is defined in . Sources which allocate such a - * structure will need to include "lockst.h". A lock of type Lock is - * a pointer to such an allocated structure. - * - * A lock must be Inited before use and should be Finished after use, - * using LockInit and LockFinish. - * - * LockClaimRecursive & LockReleaseRecursive are for claiming and - * releasing the lock. These may be used recursively. - * - * There is a limit on the number of recursive claims which - * depends on the implementation. See issue.lock-claim-limit. - * - * LockClaim and LockReleaseMPM are the same as the Recursive versions, - * except that LockClaim may only be used by a thread that doesn't - * already own the lock, and LockReleaseMPM may only be used to release - * a lock with one claim. LockClaim and LockReleaseMPM if used, must - * be used symmetrically in pairs. - * - * There are two intended uses. Here is an example: - * #include "lock.h" - * #include "lockst.h" - * static LockStruct lockStruct; - * binaryUse() - * { ;; lock not owned by this thread. - * LockClaim(&lockStruct); - * ;; lock owned by this thread. - * ;; Cannot call binaryUse() at this point. - * ;; only one thread at a time may be at this point. - * LockReleaseMPM(&lockStruct); - * ;; lock not owned by this thread. - * } - * - * recursiveUse() - * { ;; lock may already be owned by this thread. - * LockClaimRecursive(&lockStruct); - * ;; lock held by this thread. - * ;; only one thread at a time may be at this point. - * LockReleaseRecursive(&lockStruct); - * ;; lock owned by this thread if it was before. - * } - * LockInit(&lockStruct) must be called before calling binaryUse() - * or recursiveUse(). - * LockFinish(&lockStruct) should be called when lock is no longer - * needed. - * recursiveUse() may be called by both functions. - * binaryUse() may only be called where lock is known not to be - * already owned by this thread. In particular, it may not be - * called by recursiveUse(). - * - * LockClaimGlobalRecursive & LockReleaseGlobalRecursive are - * similar to LockClaimRecursive & LockReleaseRecursive - * except that they lock an implicit global lock. This may be - * used for locking access to data structures which are global, - * such as class objects. - */ - -#ifndef lock_h -#define lock_h - -#include "mpm.h" - - -#define LockSig ((Sig)0x51970CC9) /* SIGnature LOCK */ - - -#if defined(THREAD_MULTI) - - -/* LockSize -- Return the size of a LockStruct - * - * Supports allocation of locks. - */ - -extern size_t LockSize(void); - - -/* LockInit/Finish - * - * lock points to the allocated lock structure. A lock has no - * owner after initialisation. - */ - -extern void LockInit(Lock lock); -extern void LockFinish(Lock lock); - - -/* LockClaimRecursive - * - * This is called to increase the number of claims on the lock. - * LockClaimRecursive will wait until the lock is not owned by another - * thread and return with the lock owned. - * This can be called recursively. - */ - -extern void LockClaimRecursive(Lock lock); - - -/* LockReleaseRecursive - * - * This is called to reduce the number of claims on the lock. - * If the number of claims drops to zero, ownership is relinquished. - * This must not be called without possession of the lock. - */ - -extern void LockReleaseRecursive(Lock lock); - - -/* LockClaim - * - * This may only be used when the lock is not already owned by - * the calling thread. - * When used it behaves like LockClaimRecursive, but must be - * matched by a call to LockReleaseMPM. - */ - -extern void LockClaim(Lock lock); - - -/* LockReleaseMPM - * - * This must only be used to release a Lock symmetrically - * with LockClaim. It therefore should only be called with - * a single claim. - */ - -extern void LockReleaseMPM(Lock lock); - - -/* LockCheck -- Validation */ - -extern Bool LockCheck(Lock lock); - - -/* == Global locks == */ - - -/* LockClaimGlobalRecursive - * - * This is called to increase the number of claims on the recursive - * global lock. LockClaimRecursive will wait until the lock is not - * owned by another thread and return with the lock owned. - * This can be called recursively. - */ - -extern void LockClaimGlobalRecursive(void); - - -/* LockReleaseGlobalRecursive - * - * This is called to reduce the number of claims on the recursive - * global lock. If the number of claims drops to zero, ownership - * is relinquished. This must not be called without possession of - * the lock. - */ - -extern void LockReleaseGlobalRecursive(void); - - -/* LockClaimGlobal - * - * This is called to claim the binary global lock, and may only be - * used if that lock is not already owned by the calling thread. - * It must be matched by a call to LockReleaseGlobal. - */ - -extern void LockClaimGlobal(void); - - -/* LockReleaseGlobal - * - * This must only be used to release the binary global lock - * symmetrically with LockClaimGlobal. - * It therefore should only be called with a single claim. - */ - -extern void LockReleaseGlobal(void); - - -#elif defined(THREAD_SINGLE) - - -#define LockSize() MPS_PF_ALIGN -#define LockInit(lock) UNUSED(lock) -#define LockFinish(lock) UNUSED(lock) -#define LockClaimRecursive(lock) UNUSED(lock) -#define LockReleaseRecursive(lock) UNUSED(lock) -#define LockClaim(lock) UNUSED(lock) -#define LockReleaseMPM(lock) UNUSED(lock) -#define LockCheck(lock) ((void)lock, TRUE) -#define LockClaimGlobalRecursive() -#define LockReleaseGlobalRecursive() -#define LockClaimGlobal() -#define LockReleaseGlobal() - - -#else - -#error "No threading defined." - -#endif - - -#endif /* lock_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/lockan.c b/mps/code/lockan.c deleted file mode 100644 index f720e22755d..00000000000 --- a/mps/code/lockan.c +++ /dev/null @@ -1,164 +0,0 @@ -/* lockan.c: ANSI RECURSIVE LOCKS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This is a trivial implementation of recursive locks - * that assumes we are not running in a multi-threaded environment. - * This provides stubs for the locking code where locking is not - * applicable. The stubs provide some amount of checking. - * - * .limit: The limit on the number of recursive claims is ULONG_MAX. - */ - -#include "lock.h" -#include "mpmtypes.h" - -SRCID(lockan, "$Id$"); - - -typedef struct LockStruct { /* ANSI fake lock structure */ - Sig sig; /* */ - unsigned long claims; /* # claims held by owner */ -} LockStruct; - - -size_t (LockSize)(void) -{ - return sizeof(LockStruct); -} - -Bool (LockCheck)(Lock lock) -{ - CHECKS(Lock, lock); - return TRUE; -} - - -void (LockInit)(Lock lock) -{ - AVER(lock != NULL); - lock->claims = 0; - lock->sig = LockSig; - AVERT(Lock, lock); -} - -void (LockFinish)(Lock lock) -{ - AVERT(Lock, lock); - AVER(lock->claims == 0); - lock->sig = SigInvalid; -} - - -void (LockClaim)(Lock lock) -{ - AVERT(Lock, lock); - AVER(lock->claims == 0); - lock->claims = 1; -} - -void (LockReleaseMPM)(Lock lock) -{ - AVERT(Lock, lock); - AVER(lock->claims == 1); - lock->claims = 0; -} - -void (LockClaimRecursive)(Lock lock) -{ - AVERT(Lock, lock); - ++lock->claims; - AVER(lock->claims>0); -} - -void (LockReleaseRecursive)(Lock lock) -{ - AVERT(Lock, lock); - AVER(lock->claims > 0); - --lock->claims; -} - - -/* Global locking is performed by normal locks. - * A separate lock structure is used for recursive and - * non-recursive locks so that each may be differently ordered - * with respect to client-allocated locks. - */ - -static LockStruct globalLockStruct = { - LockSig, - 0 -}; - -static LockStruct globalRecursiveLockStruct = { - LockSig, - 0 -}; - -static Lock globalLock = &globalLockStruct; - -static Lock globalRecLock = &globalRecursiveLockStruct; - - -void (LockClaimGlobalRecursive)(void) -{ - LockClaimRecursive(globalRecLock); -} - -void (LockReleaseGlobalRecursive)(void) -{ - LockReleaseRecursive(globalRecLock); -} - -void (LockClaimGlobal)(void) -{ - LockClaim(globalLock); -} - -void (LockReleaseGlobal)(void) -{ - LockReleaseMPM(globalLock); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/lockcov.c b/mps/code/lockcov.c deleted file mode 100644 index 159a93e95ce..00000000000 --- a/mps/code/lockcov.c +++ /dev/null @@ -1,92 +0,0 @@ -/* lockcov.c: LOCK COVERAGE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" -#include "testlib.h" -#include /* for malloc & free */ - - -int main(void) -{ - Lock a = malloc(LockSize()); - Lock b = malloc(LockSize()); - - Insist(a != NULL); - Insist(b != NULL); - - LockInit(a); - LockInit(b); - LockClaimGlobal(); - LockClaim(a); - LockClaimRecursive(b); - LockClaimGlobalRecursive(); - LockReleaseGlobal(); - LockClaimGlobal(); - LockReleaseMPM(a); - LockClaimGlobalRecursive(); - LockReleaseGlobal(); - LockClaimRecursive(b); - LockFinish(a); - LockReleaseRecursive(b); - LockReleaseRecursive(b); - LockFinish(b); - LockInit(a); - LockClaim(a); - LockClaimRecursive(a); - LockReleaseGlobalRecursive(); - LockReleaseRecursive(a); - LockReleaseMPM(a); - LockFinish(a); - LockReleaseGlobalRecursive(); - free(a); - free(b); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/lockix.c b/mps/code/lockix.c deleted file mode 100644 index c32361e8560..00000000000 --- a/mps/code/lockix.c +++ /dev/null @@ -1,285 +0,0 @@ -/* lockix.c: RECURSIVE LOCKS FOR POSIX SYSTEMS - * - * $Id$ - * Copyright (c) 2001,2007 Ravenbrook Limited. See end of file for license. - * - * .posix: The implementation uses a POSIX interface, and should be reusable - * for many Unix-like operating systems. - * - * .freebsd: This implementation supports FreeBSD (platform - * MPS_OS_FR). - * - * .darwin: This implementation supports Darwin (OS X) (platform - * MPS_OS_XC). - * - * .design: These locks are implemented using mutexes. - * - * .recursive: Mutexes support both non-recursive and recursive - * locking, but only at initialization time. This doesn't match the - * API of MPS Lock module, which chooses at locking time, so all locks - * are made (non-recursive) errorchecking. Recursive locks are - * implemented by checking the error code. - * - * .claims: During use the claims field is updated to remember the - * number of claims acquired on a lock. This field must only be - * modified while we hold the mutex. - * - * .from: This version was copied from the FreeBSD version (lockfr.c) - * which was itself a cleaner version of the Linux version (lockli.c). - */ - -#include -#include -#include - -#include "mpmtypes.h" -#include "lock.h" -#include "config.h" - - -#if !defined(MPS_OS_FR) && !defined(MPS_OS_XC) -#error "lockix.c is Unix specific, currently for MPS_OS_FR XC." -#endif - -SRCID(lockix, "$Id$"); - - -/* LockStruct -- the MPS lock structure - * - * .lock.posix: Posix lock structure; uses a mutex. - */ - -typedef struct LockStruct { - Sig sig; /* */ - unsigned long claims; /* # claims held by owner */ - pthread_mutex_t mut; /* the mutex itself */ -} LockStruct; - - -/* LockSize -- size of a LockStruct */ - -size_t LockSize(void) -{ - return sizeof(LockStruct); -} - - -/* LockCheck -- check a lock */ - -Bool LockCheck(Lock lock) -{ - CHECKS(Lock, lock); - /* While claims can't be very large, I don't dare to put a limit on it. */ - /* There's no way to test the mutex, or check if it's held by somebody. */ - return TRUE; -} - - -/* LockInit -- initialize a lock */ - -void LockInit(Lock lock) -{ - pthread_mutexattr_t attr; - int res; - - AVER(lock != NULL); - lock->claims = 0; - res = pthread_mutexattr_init(&attr); - AVER(res == 0); - res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); - AVER(res == 0); - res = pthread_mutex_init(&lock->mut, &attr); - AVER(res == 0); - res = pthread_mutexattr_destroy(&attr); - AVER(res == 0); - lock->sig = LockSig; - AVERT(Lock, lock); -} - - -/* LockFinish -- finish a lock */ - -void LockFinish(Lock lock) -{ - int res; - - AVERT(Lock, lock); - /* Lock should not be finished while held */ - AVER(lock->claims == 0); - res = pthread_mutex_destroy(&lock->mut); - AVER(res == 0); - lock->sig = SigInvalid; -} - - -/* LockClaim -- claim a lock (non-recursive) */ - -void LockClaim(Lock lock) -{ - int res; - - AVERT(Lock, lock); - - res = pthread_mutex_lock(&lock->mut); - /* pthread_mutex_lock will error if we own the lock already. */ - AVER(res == 0); - - /* This should be the first claim. Now we own the mutex */ - /* it is ok to check this. */ - AVER(lock->claims == 0); - lock->claims = 1; -} - - -/* LockReleaseMPM -- release a lock (non-recursive) */ - -void LockReleaseMPM(Lock lock) -{ - int res; - - AVERT(Lock, lock); - AVER(lock->claims == 1); /* The lock should only be held once */ - lock->claims = 0; /* Must set this before releasing the lock */ - res = pthread_mutex_unlock(&lock->mut); - /* pthread_mutex_unlock will error if we didn't own the lock. */ - AVER(res == 0); -} - - -/* LockClaimRecursive -- claim a lock (recursive) */ - -void LockClaimRecursive(Lock lock) -{ - int res; - - AVERT(Lock, lock); - - res = pthread_mutex_lock(&lock->mut); - /* pthread_mutex_lock will return: */ - /* 0 if we have just claimed the lock */ - /* EDEADLK if we own the lock already. */ - AVER((res == 0 && lock->claims == 0) || - (res == EDEADLK && lock->claims > 0)); - - ++lock->claims; - AVER(lock->claims > 0); -} - - -/* LockReleaseRecursive -- release a lock (recursive) */ - -void LockReleaseRecursive(Lock lock) -{ - int res; - - AVERT(Lock, lock); - AVER(lock->claims > 0); - --lock->claims; - if (lock->claims == 0) { - res = pthread_mutex_unlock(&lock->mut); - /* pthread_mutex_unlock will error if we didn't own the lock. */ - AVER(res == 0); - } -} - - -/* Global locks - * - * .global: The two "global" locks are statically allocated normal locks. - */ - -static LockStruct globalLockStruct; -static LockStruct globalRecLockStruct; -static Lock globalLock = &globalLockStruct; -static Lock globalRecLock = &globalRecLockStruct; -static pthread_once_t isGlobalLockInit = PTHREAD_ONCE_INIT; - -static void globalLockInit(void) -{ - LockInit(globalLock); - LockInit(globalRecLock); -} - - -/* LockClaimGlobalRecursive -- claim the global recursive lock */ - -void LockClaimGlobalRecursive(void) -{ - int res; - - /* Ensure the global lock has been initialized */ - res = pthread_once(&isGlobalLockInit, globalLockInit); - AVER(res == 0); - LockClaimRecursive(globalRecLock); -} - - -/* LockReleaseGlobalRecursive -- release the global recursive lock */ - -void LockReleaseGlobalRecursive(void) -{ - LockReleaseRecursive(globalRecLock); -} - - -/* LockClaimGlobal -- claim the global non-recursive lock */ - -void LockClaimGlobal(void) -{ - int res; - - /* Ensure the global lock has been initialized */ - res = pthread_once(&isGlobalLockInit, globalLockInit); - AVER(res == 0); - LockClaim(globalLock); -} - - -/* LockReleaseGlobal -- release the global non-recursive lock */ - -void LockReleaseGlobal(void) -{ - LockReleaseMPM(globalLock); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/lockli.c b/mps/code/lockli.c deleted file mode 100644 index 8bd03649bbf..00000000000 --- a/mps/code/lockli.c +++ /dev/null @@ -1,299 +0,0 @@ -/* lockli.c: RECURSIVE LOCKS FOR POSIX SYSTEMS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .linux: This implementation currently just supports LinuxThreads - * (platform MPS_OS_LI), Single Unix i/f. - * - * .posix: In fact, the implementation should be reusable for most POSIX - * implementations, but may need some customization for each. - * - * .design: These locks are implemented using mutexes. - * - * .recursive: Mutexes support both non-recursive and recursive locking, but - * only at initialization time. This doesn't match the API of MPS Lock module, - * which chooses at locking time, so all locks are made (non-recursive) - * errorchecking. Recursive locks are implemented by checking the error - * code. - * - * .claims: During use the claims field is updated to remember the number of - * claims acquired on a lock. This field must only be modified - * while we hold the mutex. - */ - -#include "mpmtypes.h" -#include "lock.h" -#include "config.h" - -#include -#include -#include - - -#ifndef MPS_OS_LI -#error "lockli.c is specific to LinuxThreads but MPS_OS_LI not defined" -#endif - -SRCID(lockli, "$Id$"); - - -/* LockAttrSetRecursive -- Set mutexattr to permit recursive locking - * - * There's a standard way to do this - but early LinuxThreads doesn't - * quite follow the standard. Some other implementations might not - * either. - */ - -#ifdef OLD_LINUXTHREADS - -#define LockAttrSetRecursive(attrptr) \ - pthread_mutexattr_setkind_np(attrptr, PTHREAD_MUTEX_ERRORCHECK_NP) - -#else - -#define LockAttrSetRecursive(attrptr) \ - pthread_mutexattr_settype(attrptr, PTHREAD_MUTEX_ERRORCHECK) - -#endif - - -/* LockStruct -- the MPS lock structure - * - * .lock.posix: Posix lock structure; uses a mutex. - */ - -typedef struct LockStruct { - Sig sig; /* */ - unsigned long claims; /* # claims held by owner */ - pthread_mutex_t mut; /* the mutex itself */ -} LockStruct; - - -/* LockSize -- size of a LockStruct */ - -size_t LockSize(void) -{ - return sizeof(LockStruct); -} - - -/* LockCheck -- check a lock */ - -Bool LockCheck(Lock lock) -{ - CHECKS(Lock, lock); - /* While claims can't be very large, I don't dare to put a limit on it. */ - /* There's no way to test the mutex, or check if it's held by somebody. */ - return TRUE; -} - - -/* LockInit -- initialize a lock */ - -void LockInit(Lock lock) -{ - pthread_mutexattr_t attr; - int res; - - AVER(lock != NULL); - lock->claims = 0; - res = pthread_mutexattr_init(&attr); - AVER(res == 0); - res = LockAttrSetRecursive(&attr); - AVER(res == 0); - res = pthread_mutex_init(&lock->mut, &attr); - AVER(res == 0); - res = pthread_mutexattr_destroy(&attr); - AVER(res == 0); - lock->sig = LockSig; - AVERT(Lock, lock); -} - - -/* LockFinish -- finish a lock */ - -void LockFinish(Lock lock) -{ - int res; - - AVERT(Lock, lock); - /* Lock should not be finished while held */ - AVER(lock->claims == 0); - res = pthread_mutex_destroy(&lock->mut); - AVER(res == 0); - lock->sig = SigInvalid; -} - - -/* LockClaim -- claim a lock (non-recursive) */ - -void LockClaim(Lock lock) -{ - int res; - - AVERT(Lock, lock); - - res = pthread_mutex_lock(&lock->mut); - /* pthread_mutex_lock will error if we own the lock already. */ - AVER(res == 0); - - /* This should be the first claim. Now we own the mutex */ - /* it is ok to check this. */ - AVER(lock->claims == 0); - lock->claims = 1; -} - - -/* LockReleaseMPM -- release a lock (non-recursive) */ - -void LockReleaseMPM(Lock lock) -{ - int res; - - AVERT(Lock, lock); - AVER(lock->claims == 1); /* The lock should only be held once */ - lock->claims = 0; /* Must set this before releasing the lock */ - res = pthread_mutex_unlock(&lock->mut); - /* pthread_mutex_unlock will error if we didn't own the lock. */ - AVER(res == 0); -} - - -/* LockClaimRecursive -- claim a lock (recursive) */ - -void LockClaimRecursive(Lock lock) -{ - int res; - - AVERT(Lock, lock); - - res = pthread_mutex_lock(&lock->mut); - /* pthread_mutex_lock will return: */ - /* 0 if we have just claimed the lock */ - /* EDEADLK if we own the lock already. */ - AVER((res == 0 && lock->claims == 0) || - (res == EDEADLK && lock->claims > 0)); - - ++lock->claims; - AVER(lock->claims > 0); -} - - -/* LockReleaseRecursive -- release a lock (recursive) */ - -void LockReleaseRecursive(Lock lock) -{ - int res; - - AVERT(Lock, lock); - AVER(lock->claims > 0); - --lock->claims; - if (lock->claims == 0) { - res = pthread_mutex_unlock(&lock->mut); - /* pthread_mutex_unlock will error if we didn't own the lock. */ - AVER(res == 0); - } -} - - -/* Global locks - * - * .global: The two "global" locks are statically allocated normal locks. - */ - -static LockStruct globalLockStruct; -static LockStruct globalRecLockStruct; -static Lock globalLock = &globalLockStruct; -static Lock globalRecLock = &globalRecLockStruct; -static pthread_once_t isGlobalLockInit = PTHREAD_ONCE_INIT; - -static void globalLockInit(void) -{ - LockInit(globalLock); - LockInit(globalRecLock); -} - - -/* LockClaimGlobalRecursive -- claim the global recursive lock */ - -void LockClaimGlobalRecursive(void) -{ - int res; - - /* Ensure the global lock has been initialized */ - res = pthread_once(&isGlobalLockInit, globalLockInit); - AVER(res == 0); - LockClaimRecursive(globalRecLock); -} - - -/* LockReleaseGlobalRecursive -- release the global recursive lock */ - -void LockReleaseGlobalRecursive(void) -{ - LockReleaseRecursive(globalRecLock); -} - - -/* LockClaimGlobal -- claim the global non-recursive lock */ - -void LockClaimGlobal(void) -{ - int res; - - /* Ensure the global lock has been initialized */ - res = pthread_once(&isGlobalLockInit, globalLockInit); - AVER(res == 0); - LockClaim(globalLock); -} - - -/* LockReleaseGlobal -- release the global non-recursive lock */ - -void LockReleaseGlobal(void) -{ - LockReleaseMPM(globalLock); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/lockutw3.c b/mps/code/lockutw3.c deleted file mode 100644 index 2565ec60796..00000000000 --- a/mps/code/lockutw3.c +++ /dev/null @@ -1,135 +0,0 @@ -/* lockutw3.c: LOCK UTILIZATION TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" -#include "testlib.h" - -#include "mpswin.h" - - -#ifndef MPS_OS_W3 -#error "Relies on Win32 threads" -#endif - - -#define nTHREADS 4 - -static Lock lock; -unsigned long shared, tmp; - - -void incR(unsigned long i) -{ - LockClaimRecursive(lock); - if (i < 100) { - while(i--) { - tmp = shared; - shared = tmp + 1; - } - } else { - incR(i >> 1); - incR( (i+1) >> 1); - } - LockReleaseRecursive(lock); -} - - -void inc(unsigned long i) -{ - incR( (i+1) >>1); - i >>= 1; - while (i) { - LockClaim(lock); - if (i > 10000) { - incR(5000); - i -= 5000; - } - tmp = shared; - shared = tmp+1; - i--; - LockReleaseMPM(lock); - } -} - - -#define COUNT 100000l -DWORD WINAPI thread0(void *p) -{ - (void)p; - inc(COUNT); - return 0; -} - - -int main(void) -{ - DWORD id; - HANDLE t[10]; - unsigned i; - - lock = malloc(LockSize()); - Insist(lock != NULL); - - LockInit(lock); - - shared = 0; - - for(i = 0; i < nTHREADS; i++) - t[i] = CreateThread(NULL, 0, thread0, NULL, 0, &id); - - for(i = 0; i < nTHREADS; i++) - WaitForSingleObject(t[i], INFINITE); - - Insist(shared == nTHREADS*COUNT); - - LockFinish(lock); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/lockw3.c b/mps/code/lockw3.c deleted file mode 100644 index 258b31bff44..00000000000 --- a/mps/code/lockw3.c +++ /dev/null @@ -1,198 +0,0 @@ -/* lockw3.c: RECURSIVE LOCKS IN WIN32 - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .design: These are implemented using critical sections. - * See the section titled "Synchronization functions" in the Groups - * chapter of the Microsoft Win32 API Programmer's Reference. - * The "Synchronization" section of the Overview is also relevant. - * - * Critical sections support recursive locking, so the implementation - * could be trivial. This implementation counts the claims to provide - * extra checking. - * - * The limit on the number of recursive claims is the max of - * ULONG_MAX and the limit imposed by critical sections, which - * is believed to be about UCHAR_MAX. - * - * During use the claims field is updated to remember the number of - * claims acquired on a lock. This field must only be modified - * while we are inside the critical section. - */ - -#include "mpm.h" - -#ifndef MPS_OS_W3 -#error "lockw3.c is specific to Win32 but MPS_OS_W3 not defined" -#endif - -#include "mpswin.h" - -SRCID(lockw3, "$Id$"); - - -/* .lock.win32: Win32 lock structure; uses CRITICAL_SECTION */ -typedef struct LockStruct { - Sig sig; /* */ - unsigned long claims; /* # claims held by the owning thread */ - CRITICAL_SECTION cs; /* Win32's recursive lock thing */ -} LockStruct; - - -size_t LockSize(void) -{ - return sizeof(LockStruct); -} - -Bool LockCheck(Lock lock) -{ - CHECKS(Lock, lock); - return TRUE; -} - -void LockInit(Lock lock) -{ - AVER(lock != NULL); - lock->claims = 0; - InitializeCriticalSection(&lock->cs); - lock->sig = LockSig; - AVERT(Lock, lock); -} - -void LockFinish(Lock lock) -{ - AVERT(Lock, lock); - /* Lock should not be finished while held */ - AVER(lock->claims == 0); - DeleteCriticalSection(&lock->cs); - lock->sig = SigInvalid; -} - -void LockClaim(Lock lock) -{ - AVERT(Lock, lock); - EnterCriticalSection(&lock->cs); - /* This should be the first claim. Now we are inside the - * critical section it is ok to check this. */ - AVER(lock->claims == 0); - lock->claims = 1; -} - -void LockReleaseMPM(Lock lock) -{ - AVERT(Lock, lock); - AVER(lock->claims == 1); /* The lock should only be held once */ - lock->claims = 0; /* Must set this before leaving CS */ - LeaveCriticalSection(&lock->cs); -} - -void LockClaimRecursive(Lock lock) -{ - AVERT(Lock, lock); - EnterCriticalSection(&lock->cs); - ++lock->claims; - AVER(lock->claims > 0); -} - -void LockReleaseRecursive(Lock lock) -{ - AVERT(Lock, lock); - AVER(lock->claims > 0); - --lock->claims; - LeaveCriticalSection(&lock->cs); -} - - - -/* Global locking is performed by normal locks. - * A separate lock structure is used for recursive and - * non-recursive locks so that each may be differently ordered - * with respect to client-allocated locks. - */ - -static LockStruct globalLockStruct; -static LockStruct globalRecLockStruct; -static Lock globalLock = &globalLockStruct; -static Lock globalRecLock = &globalRecLockStruct; -static Bool globalLockInit = FALSE; /* TRUE iff initialized */ - - -static void lockEnsureGlobalLock(void) -{ - /* Ensure both global locks have been initialized. */ - /* There is a race condition initializing them. */ - if (!globalLockInit) { - LockInit(globalLock); - LockInit(globalRecLock); - globalLockInit = TRUE; - } -} - -void LockClaimGlobalRecursive(void) -{ - lockEnsureGlobalLock(); - AVER(globalLockInit); - LockClaimRecursive(globalRecLock); -} - -void LockReleaseGlobalRecursive(void) -{ - AVER(globalLockInit); - LockReleaseRecursive(globalRecLock); -} - -void LockClaimGlobal(void) -{ - lockEnsureGlobalLock(); - AVER(globalLockInit); - LockClaim(globalLock); -} - -void LockReleaseGlobal(void) -{ - AVER(globalLockInit); - LockReleaseMPM(globalLock); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/locus.c b/mps/code/locus.c deleted file mode 100644 index 6ea5127ee12..00000000000 --- a/mps/code/locus.c +++ /dev/null @@ -1,528 +0,0 @@ -/* locus.c: LOCUS MANAGER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * DESIGN - * - * See and for basic locus stuff. - * See for chains. - */ - -#include "chain.h" -#include "ring.h" -#include "mpm.h" -#include "mpstd.h" -#include /* for DBL_MAX */ - -SRCID(locus, "$Id$"); - - -/* SegPrefCheck -- check the consistency of a segment preference */ - -Bool SegPrefCheck(SegPref pref) -{ - CHECKS(SegPref, pref); - CHECKL(BoolCheck(pref->high)); - /* zones can't be checked because it's arbitrary. */ - CHECKL(BoolCheck(pref->isGen)); - CHECKL(BoolCheck(pref->isCollected)); - /* gen is an arbitrary serial */ - return TRUE; -} - - -/* SegPrefDefault -- return a segment preference representing the defaults */ - -static SegPrefStruct segPrefDefault = SegPrefDEFAULT; - -SegPref SegPrefDefault(void) -{ - return &segPrefDefault; -} - - -/* SegPrefExpress -- express a segment preference */ - -void SegPrefExpress(SegPref pref, SegPrefKind kind, void *p) -{ - AVERT(SegPref, pref); - AVER(pref != &segPrefDefault); - - switch(kind) { - case SegPrefHigh: - AVER(p == NULL); - pref->high = TRUE; - break; - - case SegPrefLow: - AVER(p == NULL); - pref->high = FALSE; - break; - - case SegPrefZoneSet: - AVER(p != NULL); - pref->zones = *(ZoneSet *)p; - break; - - case SegPrefCollected: - AVER(p == NULL); - pref->isCollected = TRUE; - break; - - case SegPrefGen: - AVER(p != NULL); - pref->isGen = TRUE; - pref->gen = *(Serial *)p; - break; - - default: - /* Unknown kinds are ignored for binary compatibility. */ - /* See design.mps.pref. */ - break; - } -} - - -/* GenDescCheck -- check a GenDesc */ - -static Bool GenDescCheck(GenDesc gen) -{ - CHECKS(GenDesc, gen); - /* nothing to check for zones */ - /* nothing to check for capacity */ - CHECKL(gen->mortality >= 0.0); - CHECKL(gen->mortality <= 1.0); - CHECKL(gen->proflow >= 0.0); - CHECKL(gen->proflow <= 1.0); - CHECKL(RingCheck(&gen->locusRing)); - return TRUE; -} - - -/* GenDescNewSize -- return effective size of generation */ - -static Size GenDescNewSize(GenDesc gen) -{ - Size size = 0; - Ring node, nextNode; - - RING_FOR(node, &gen->locusRing, nextNode) { - PoolGen pgen = RING_ELT(PoolGen, genRing, node); - AVERT(PoolGen, pgen); - size += pgen->newSize; - } - return size; -} - - -/* GenDescTotalSize -- return total size of generation */ - -static Size GenDescTotalSize(GenDesc gen) -{ - Size size = 0; - Ring node, nextNode; - - RING_FOR(node, &gen->locusRing, nextNode) { - PoolGen pgen = RING_ELT(PoolGen, genRing, node); - AVERT(PoolGen, pgen); - size += pgen->totalSize; - } - return size; -} - - -/* ChainCreate -- create a generation chain */ - -Res ChainCreate(Chain *chainReturn, Arena arena, size_t genCount, - GenParamStruct *params) -{ - size_t i; - Chain chain; - GenDescStruct *gens; - Res res; - void *p; - - AVER(chainReturn != NULL); - AVERT(Arena, arena); - AVER(genCount > 0); - AVER(params != NULL); - for (i = 0; i < genCount; ++i) { - AVER(params[i].capacity > 0); - AVER(params[i].mortality > 0.0); - AVER(params[i].mortality < 1.0); - } - - res = ControlAlloc(&p, arena, genCount * sizeof(GenDescStruct), FALSE); - if (res != ResOK) - return res; - gens = (GenDescStruct *)p; - - for (i = 0; i < genCount; ++i) { - gens[i].zones = ZoneSetEMPTY; - gens[i].capacity = params[i].capacity; - gens[i].mortality = params[i].mortality; - gens[i].proflow = 1.0; /* @@@@ temporary */ - RingInit(&gens[i].locusRing); - gens[i].sig = GenDescSig; - } - - res = ControlAlloc(&p, arena, sizeof(ChainStruct), FALSE); - if (res != ResOK) - goto failChainAlloc; - chain = (Chain)p; - - chain->arena = arena; - RingInit(&chain->chainRing); - chain->activeTraces = TraceSetEMPTY; - chain->genCount = genCount; - chain->gens = gens; - chain->sig = ChainSig; - - RingAppend(&arena->chainRing, &chain->chainRing); - AVERT(Chain, chain); - *chainReturn = chain; - return ResOK; - -failChainAlloc: - ControlFree(arena, gens, genCount * sizeof(GenDescStruct)); - return res; -} - - -/* ChainCheck -- check a chain */ - -Bool ChainCheck(Chain chain) -{ - size_t i; - - CHECKS(Chain, chain); - CHECKU(Arena, chain->arena); - CHECKL(RingCheck(&chain->chainRing)); - CHECKL(TraceSetCheck(chain->activeTraces)); - CHECKL(chain->genCount > 0); - for (i = 0; i < chain->genCount; ++i) { - CHECKD(GenDesc, &chain->gens[i]); - } - return TRUE; -} - - -/* ChainDestroy -- destroy a chain */ - -void ChainDestroy(Chain chain) -{ - Arena arena; - size_t genCount; - size_t i; - - AVERT(Chain, chain); - - arena = chain->arena; genCount = chain->genCount; - RingRemove(&chain->chainRing); - chain->sig = SigInvalid; - for (i = 0; i < genCount; ++i) { - RingFinish(&chain->gens[i].locusRing); - chain->gens[i].sig = SigInvalid; - } - RingFinish(&chain->chainRing); - ControlFree(arena, chain->gens, genCount * sizeof(GenDescStruct)); - ControlFree(arena, chain, sizeof(ChainStruct)); -} - - -/* ChainGens -- return the number of generation in chain */ - -size_t ChainGens(Chain chain) -{ - AVERT(Chain, chain); - return chain->genCount; -} - - -/* ChainDeferral -- time until next ephemeral GC for this chain */ - -double ChainDeferral(Chain chain) -{ - AVERT(Chain, chain); - - if (chain->activeTraces != TraceSetEMPTY) - return DBL_MAX; - else - return chain->gens[0].capacity * 1024.0 - - (double)GenDescNewSize(&chain->gens[0]); -} - - -/* ChainCondemnAuto -- condemn approriate parts of this chain - * - * This is only called if ChainDeferral returned a value sufficiently - * low that the tracer decided to start the collection. (Usually - * such values are less than zero; see ) - */ -Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace) -{ - Res res; - Serial topCondemnedGenSerial, currGenSerial; - GenDesc gen; - ZoneSet condemnedSet = ZoneSetEMPTY; - Size condemnedSize = 0, survivorSize = 0, genNewSize, genTotalSize; - - AVERT(Chain, chain); - AVERT(Trace, trace); - - /* Find lowest gen within its capacity, set topCondemnedGenSerial to the */ - /* preceeding one. */ - currGenSerial = 0; - gen = &chain->gens[0]; - AVERT(GenDesc, gen); - genNewSize = GenDescNewSize(gen); - do { /* At this point, we've decided to collect currGenSerial. */ - topCondemnedGenSerial = currGenSerial; - condemnedSet = ZoneSetUnion(condemnedSet, gen->zones); - genTotalSize = GenDescTotalSize(gen); - condemnedSize += genTotalSize; - survivorSize += (Size)(genNewSize * (1.0 - gen->mortality)) - /* predict survivors will survive again */ - + (genTotalSize - genNewSize); - - /* is there another one to consider? */ - currGenSerial += 1; - if (currGenSerial >= chain->genCount) - break; /* reached the top */ - gen = &chain->gens[currGenSerial]; - AVERT(GenDesc, gen); - genNewSize = GenDescNewSize(gen); - } while (genNewSize >= gen->capacity * (Size)1024); - - EVENT3(ChainCondemnAuto, chain, topCondemnedGenSerial, chain->genCount); - DIAG_SINGLEF(( "ChainCondemnAuto", - "condemn gens [0..$U]", (WriteFU)topCondemnedGenSerial, - " (of $U)", (WriteFU)chain->genCount, - " of this chain $P.", (WriteFP)chain, - NULL )); - UNUSED(topCondemnedGenSerial); /* only used for DIAG */ - - /* Condemn everything in these zones. */ - if (condemnedSet != ZoneSetEMPTY) { - res = TraceCondemnZones(trace, condemnedSet); - if (res != ResOK) - return res; - } - - *mortalityReturn = 1.0 - (double)survivorSize / condemnedSize; - return ResOK; -} - - -/* ChainCondemnAll -- condemn everything in the chain */ - -Res ChainCondemnAll(Chain chain, Trace trace) -{ - Ring node, nextNode; - Bool haveWhiteSegs = FALSE; - Res res; - - /* Condemn every segment in every pool using this chain. */ - /* Finds the pools by iterating over the PoolGens in gen 0. */ - RING_FOR(node, &chain->gens[0].locusRing, nextNode) { - PoolGen nursery = RING_ELT(PoolGen, genRing, node); - Pool pool = nursery->pool; - Ring segNode, nextSegNode; - - AVERT(Pool, pool); - AVER((pool->class->attr & AttrGC) != 0); - RING_FOR(segNode, PoolSegRing(pool), nextSegNode) { - Seg seg = SegOfPoolRing(segNode); - - res = TraceAddWhite(trace, seg); - if (res != ResOK) - goto failBegin; - haveWhiteSegs = TRUE; - } - } - - return ResOK; - -failBegin: - AVER(!haveWhiteSegs); /* Would leave white sets inconsistent. */ - return res; -} - - -/* ChainStartGC -- called to notify start of GC for this chain */ - -void ChainStartGC(Chain chain, Trace trace) -{ - AVERT(Chain, chain); - AVERT(Trace, trace); - - chain->activeTraces = TraceSetAdd(chain->activeTraces, trace); -} - - -/* ChainEndGC -- called to notify end of GC for this chain */ - -void ChainEndGC(Chain chain, Trace trace) -{ - AVERT(Chain, chain); - AVERT(Trace, trace); - - chain->activeTraces = TraceSetDel(chain->activeTraces, trace); -} - - -/* PoolGenInit -- initialize a PoolGen */ - -Res PoolGenInit(PoolGen gen, Chain chain, Serial nr, Pool pool) -{ - /* Can't check gen, because it's not been initialized. */ - AVERT(Chain, chain); - AVER(nr <= chain->genCount); - AVERT(Pool, pool); - - gen->nr = nr; - gen->pool = pool; - gen->chain = chain; - RingInit(&gen->genRing); - gen->totalSize = (Size)0; - gen->newSize = (Size)0; - gen->sig = PoolGenSig; - - if(nr != chain->genCount) { - RingAppend(&chain->gens[nr].locusRing, &gen->genRing); - } else { - /* Dynamic generation is linked to the arena, not the chain. */ - RingAppend(&chain->arena->topGen.locusRing, &gen->genRing); - } - AVERT(PoolGen, gen); - return ResOK; -} - - -/* PoolGenFinish -- finish a PoolGen */ - -void PoolGenFinish(PoolGen gen) -{ - AVERT(PoolGen, gen); - - gen->sig = SigInvalid; - RingRemove(&gen->genRing); -} - - -/* PoolGenCheck -- check a PoolGen */ - -Bool PoolGenCheck(PoolGen gen) -{ - CHECKS(PoolGen, gen); - /* nothing to check about serial */ - CHECKU(Pool, gen->pool); - CHECKU(Chain, gen->chain); - CHECKL(RingCheck(&gen->genRing)); - CHECKL(gen->newSize <= gen->totalSize); - return TRUE; -} - - -/* PoolGenUpdateZones -- update the zone of the generation - * - * This is a temporary i/f: eventually the locus manager will update - * these directly. - */ -void PoolGenUpdateZones(PoolGen gen, Seg seg) -{ - Chain chain; - - AVERT(PoolGen, gen); - AVERT(Seg, seg); - - chain = gen->chain; - AVERT(Chain, chain); - if (gen->nr != chain->genCount) - chain->gens[gen->nr].zones = - ZoneSetUnion(chain->gens[gen->nr].zones, ZoneSetOfSeg(chain->arena, seg)); - /* No need to keep track of dynamic gen zoneset. */ -} - - -/* LocusInit -- initialize the locus module */ - -void LocusInit(Arena arena) -{ - GenDesc gen = &arena->topGen; - - /* Can't check arena, because it's not been inited. */ - - gen->zones = ZoneSetEMPTY; - gen->capacity = 0; /* unused */ - gen->mortality = TraceTopGenMortality; /* @@@@ unused ATM */ - gen->proflow = 0.0; - RingInit(&gen->locusRing); - gen->sig = GenDescSig; -} - - -/* LocusFinish -- finish the locus module */ - -void LocusFinish(Arena arena) -{ - GenDesc gen = &arena->topGen; - - /* Can't check arena, because it's being finished. */ - - gen->sig = SigInvalid; - RingFinish(&gen->locusRing); -} - - -/* LocusCheck -- check the locus module */ - -Bool LocusCheck(Arena arena) -{ - /* Can't check arena, because this is part of ArenaCheck. */ - CHECKL(GenDescCheck(&arena->topGen)); - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/locusss.c b/mps/code/locusss.c deleted file mode 100644 index f3828404c0b..00000000000 --- a/mps/code/locusss.c +++ /dev/null @@ -1,289 +0,0 @@ -/* locusss.c: LOCUS STRESS TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpscmvff.h" -#include "mpscmv.h" -#include "mpslib.h" -#include "mpsavm.h" -#include "testlib.h" -#include "mps.h" - -#include -#include - - -/* some constants */ - -#define TRUE 1 -#define FALSE 0 - -#define iterationCount 30 /* number of iterations */ -#define contigAllocs 8 /* number of allocs each iteration */ -#define chunkSize ((size_t)65536) /* our allocation chunk size */ - -#define smallArenaSize \ - ((size_t)(chunkSize * iterationCount * contigAllocs * 2)) - - -#define AddressOffset(b, l) \ - ((size_t)((char *)(l) - (char *)(b))) - - -/* PoolStat -- maintain data about contiguous allocations */ - -typedef struct PoolStatStruct *PoolStat; - -typedef struct PoolStatStruct { - mps_pool_t pool; /* the pool being measured */ - size_t objSize; /* size of each allocation */ - mps_addr_t min; /* lowest address lock allocated to the pool */ - mps_addr_t max; /* highest address lock allocated to the pool */ - int ncCount; /* count of non-contiguous allocations */ - int aCount; /* count of allocations */ - int fCount; /* count of frees */ -} PoolStatStruct; - - - -static mps_addr_t allocObject(mps_pool_t pool, size_t size) -{ - mps_addr_t addr; - die(mps_alloc(&addr, pool, size), - "Allocate Object"); - return addr; -} - -static void recordNewObjectStat(PoolStat stat, mps_addr_t obj) -{ - stat->aCount++; - if (obj < stat->min) { - if (AddressOffset(obj, stat->min) > stat->objSize) { - stat->ncCount++; - } - stat->min = obj; - } else if (obj > stat->max) { - if (AddressOffset(stat->max, obj) > stat->objSize) { - stat->ncCount++; - } - stat->max = obj; - } -} - -static void recordFreedObjectStat(PoolStat stat) -{ - stat->fCount++; -} - - -static void poolStatInit(PoolStat stat, mps_pool_t pool, size_t objSize) -{ - mps_addr_t s1, s2, s3; - - stat->pool = pool; - stat->objSize = objSize; - stat->ncCount = 0; - stat->aCount = 0; - stat->fCount = 0; - - /* allocate 3 half-size sentinel objects, freeing the middle one */ - /* to leave a bit of space for the control pool */ - s1 = allocObject(pool, objSize / 2); - stat->min = s1; - stat->max = s1; - stat->aCount++; - - s2 = allocObject(pool, objSize / 2); - recordNewObjectStat(stat, s2); - s3 = allocObject(pool, objSize / 2); - recordNewObjectStat(stat, s3); - - mps_free(pool, s2, objSize / 2); - recordFreedObjectStat(stat); - -} - - -static mps_res_t allocMultiple(PoolStat stat) -{ - mps_addr_t objects[contigAllocs]; - int i; - - /* allocate a few objects, and record stats for them */ - for (i = 0; i < contigAllocs; i++) { - mps_addr_t obj; - mps_res_t res = mps_alloc(&obj, stat->pool, stat->objSize); - if (res != MPS_RES_OK) - return res; - recordNewObjectStat(stat, obj); - objects[i] = obj; - } - - /* free one of the objects, to make the test more interesting */ - i = rnd() % contigAllocs; - mps_free(stat->pool, objects[i], stat->objSize); - recordFreedObjectStat(stat); - - return MPS_RES_OK; -} - - -/* reportResults - print a report on a PoolStat */ - -static void reportResults(PoolStat stat, char *name) -{ - printf("\nResults for "); - printf("%s", name); - printf("\n"); - printf(" Allocated %"PRIuLONGEST" objects\n", (ulongest_t)stat->aCount); - printf(" Freed %"PRIuLONGEST" objects\n", (ulongest_t)stat->fCount); - printf(" There were %lu non-contiguous allocations\n", - (unsigned long)stat->ncCount); - printf(" Address range from %p to %p\n", stat->min, stat->max); - printf("\n"); -} - - -static void testInArena(mps_arena_t arena, - mps_bool_t failcase, - mps_bool_t usefulFailcase) -{ - mps_pool_t lopool, hipool, temppool; - PoolStatStruct lostruct; /* stats about lopool */ - PoolStatStruct histruct; /* stats about lopool */ - PoolStatStruct tempstruct; /* stats about temppool */ - PoolStat lostat = &lostruct; - PoolStat histat = &histruct; - PoolStat tempstat = &tempstruct; - int i; - - die(mps_pool_create(&hipool, arena, mps_class_mvff(), - chunkSize, chunkSize, (size_t)1024, - TRUE, TRUE, TRUE), - "Create HI MFFV"); - - die(mps_pool_create(&lopool, arena, mps_class_mvff(), - chunkSize, chunkSize, (size_t)1024, - FALSE, FALSE, TRUE), - "Create LO MFFV"); - - die(mps_pool_create(&temppool, arena, mps_class_mv(), - chunkSize, chunkSize, chunkSize), - "Create TEMP"); - - if(failcase) { - if(usefulFailcase) { - /* describe a useful failure case */ - } else { - /* describe a misleading failure case */ - } - } - - poolStatInit(lostat, lopool, chunkSize); - poolStatInit(histat, hipool, chunkSize); - poolStatInit(tempstat, temppool, chunkSize); - - /* iterate, allocating objects */ - for (i=0; i. - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/locv.c b/mps/code/locv.c deleted file mode 100644 index 76260ed526b..00000000000 --- a/mps/code/locv.c +++ /dev/null @@ -1,208 +0,0 @@ -/* locv.c: LEAF OBJECT POOL CLASS COVERAGE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This is (not much of) a coverage test for the Leaf Object - * pool (PoolClassLO). - */ - -#include "testlib.h" -#include "mps.h" -#include "mpsclo.h" -#include "mpsavm.h" - - -#define testArenaSIZE ((size_t)16<<20) - -static mps_res_t scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit); -static mps_addr_t skip(mps_addr_t object); -static void move(mps_addr_t object, mps_addr_t to); -static mps_addr_t isMoved(mps_addr_t object); -static void copy(mps_addr_t old, mps_addr_t new); -static void pad(mps_addr_t base, size_t size); - -static void stepper(mps_addr_t addr, mps_fmt_t fmt, mps_pool_t pool, - void *p, size_t s); - -static mps_fmt_A_s locv_fmt = - { - (mps_align_t)0, /* .fmt.align.delayed: to be filled in */ - scan, - skip, - copy, - move, - isMoved, - pad - }; - -static mps_addr_t roots[4]; - - -int main(void) -{ - mps_arena_t arena; - mps_pool_t pool; - mps_fmt_t format; - mps_ap_t ap; - mps_addr_t p; - mps_root_t root; - - locv_fmt.align = sizeof(void *); /* .fmt.align.delayed */ - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "mps_arena_create"); - die(mps_root_create_table(&root, arena, mps_rank_exact(), - (mps_rm_t)0, - roots, (sizeof(roots)/sizeof(*roots))), - "RootCreate"); - - die(mps_fmt_create_A(&format, arena, &locv_fmt), "FormatCreate"); - - die(mps_pool_create(&pool, arena, mps_class_lo(), format), "LOCreate"); - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "APCreate"); - - die(mps_reserve(&p, ap, sizeof(void *)), "mps_reserve min"); - *(mps_word_t *)p = sizeof(void *); - cdie(mps_commit(ap, p, sizeof(void *)), "commit min"); - - die(mps_reserve(&roots[1], ap, 2*sizeof(void *)), "mps_reserve 2*min"); - p = roots[1]; - *(mps_word_t *)p = 2*sizeof(void *); - cdie(mps_commit(ap, p, 2*sizeof(void *)), "commit 2*min"); - - die(mps_reserve(&p, ap, (size_t)4096), "mps_reserve 4096"); - *(mps_word_t *)p = 4096; - cdie(mps_commit(ap, p, (size_t)4096), "commit 4096"); - - die(mps_reserve(&p, ap, sizeof(void *)), "mps_reserve last"); - *(mps_word_t *)p = sizeof(void *); - cdie(mps_commit(ap, p, sizeof(void *)), "commit last"); - - { - size_t count = 0; - mps_arena_formatted_objects_walk(arena, stepper, &count, 0); - cdie(count == 4, "walk 4 objects"); - } - - mps_ap_destroy(ap); - mps_pool_destroy(pool); - mps_fmt_destroy(format); - mps_root_destroy(root); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -static mps_res_t scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit) -{ - testlib_unused(ss); - testlib_unused(base); - testlib_unused(limit); - die(MPS_RES_FAIL, "Error in Test, scan called unexpectedly"); - return MPS_RES_FAIL; -} - - -static mps_addr_t skip(mps_addr_t object) -{ - size_t bytes; - - bytes = (size_t)(*(mps_word_t *)object); - - return (mps_addr_t)((char *)object + bytes); -} - - -static void move(mps_addr_t object, mps_addr_t to) -{ - testlib_unused(object); - testlib_unused(to); - cdie(0, "move"); -} - - -static mps_addr_t isMoved(mps_addr_t object) -{ - testlib_unused(object); - cdie(0, "isMoved"); - return (mps_addr_t)NULL; -} - - -static void copy(mps_addr_t old, mps_addr_t new) -{ - testlib_unused(old); - testlib_unused(new); - cdie(0, "copy"); -} - - -static void pad(mps_addr_t base, size_t size) -{ - testlib_unused(base); - testlib_unused(size); - cdie(0, "pad"); -} - -static void stepper(mps_addr_t addr, mps_fmt_t fmt, mps_pool_t pool, - void *p, size_t s) -{ - size_t *pcount; - - testlib_unused(addr); - testlib_unused(fmt); - testlib_unused(pool); - testlib_unused(s); - - pcount = p; - *pcount += 1; - return; -} - - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/message.c b/mps/code/message.c deleted file mode 100644 index 75b01d328d8..00000000000 --- a/mps/code/message.c +++ /dev/null @@ -1,467 +0,0 @@ -/* message.c: MPS/CLIENT MESSAGES - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * DESIGN - * - * .design: See (it really exists). - * - * PURPOSE - * - * .purpose: Provide the generic part of the MPS / Client message - * interface. Messages are instances of Message Classes; much of the - * "real work" goes on in the modules that provide the actual messages. - */ - -#include "bt.h" -#include "mpm.h" - -SRCID(message, "$Id$"); - - -/* Maps from a Ring pointer to the message */ -#define MessageNodeMessage(node) \ - PARENT(MessageStruct, queueRing, node) - - -/* forward declarations */ -static Bool MessageTypeEnabled(Arena arena, MessageType type); -static void MessageDelete(Message message); - - -/* Internal (MPM) Interface -- functions for message originator - * - */ - - -Bool MessageTypeCheck(MessageType type) -{ - CHECKL(type < MessageTypeLIMIT); - UNUSED(type); /* */ - - return TRUE; -} - -/* See .message.clocked. Currently finalization messages are the */ -/* only ones that can be numerous. */ -#define MessageIsClocked(message) ((message)->class->type \ - != MessageTypeFINALIZATION) - -Bool MessageCheck(Message message) -{ - CHECKS(Message, message); - CHECKU(Arena, message->arena); - CHECKD(MessageClass, message->class); - CHECKL(RingCheck(&message->queueRing)); - /* postedClock is uncheckable for clocked message types, */ - /* but must be 0 for unclocked message types: */ - CHECKL(MessageIsClocked(message) || (message->postedClock == 0)); - - return TRUE; -} - -Bool MessageClassCheck(MessageClass class) -{ - CHECKS(MessageClass, class); - CHECKL(class->name != NULL); - CHECKL(MessageTypeCheck(class->type)); - CHECKL(FUNCHECK(class->delete)); - CHECKL(FUNCHECK(class->finalizationRef)); - CHECKL(FUNCHECK(class->gcLiveSize)); - CHECKL(FUNCHECK(class->gcCondemnedSize)); - CHECKL(FUNCHECK(class->gcNotCondemnedSize)); - CHECKL(FUNCHECK(class->gcStartWhy)); - CHECKL(class->endSig == MessageClassSig); - - return TRUE; -} - -void MessageInit(Arena arena, Message message, MessageClass class, - MessageType type) -{ - AVERT(Arena, arena); - AVER(message != NULL); - AVERT(MessageClass, class); - AVERT(MessageType, type); - - message->arena = arena; - message->class = class; - RingInit(&message->queueRing); - message->postedClock = 0; - message->sig = MessageSig; - - AVERT(Message, message); - AVER(MessageGetType(message) == type); -} - -void MessageFinish(Message message) -{ - AVERT(Message, message); - AVER(RingIsSingle(&message->queueRing)); - - message->sig = SigInvalid; - RingFinish(&message->queueRing); -} - -Arena MessageArena(Message message) -{ - AVERT(Message, message); - - return message->arena; -} - -Bool MessageOnQueue(Message message) -{ - AVERT(Message, message); - - /* message is on queue if and only if its ring is not a singleton. */ - return !RingIsSingle(&message->queueRing); -} - -/* Post a message to the arena's queue of pending messages */ -void MessagePost(Arena arena, Message message) -{ - AVERT(Arena, arena); - AVERT(Message, message); - - /* queueRing field must be a singleton, see */ - /* */ - AVER(!MessageOnQueue(message)); - if(MessageTypeEnabled(arena, MessageGetType(message))) { - /* .message.clocked: Reading the clock with ClockNow() */ - /* involves an mpslib call, so we avoid it for message */ - /* types that may be numerous. */ - if(MessageIsClocked(message)) { - message->postedClock = ClockNow(); - } - RingAppend(&arena->messageRing, &message->queueRing); - } else { - /* discard message immediately if client hasn't enabled that type */ - MessageDiscard(arena, message); - } -} - -/* Return the message at the head of the arena's queue */ -static Message MessageHead(Arena arena) -{ - AVERT(Arena, arena); - AVER(!RingIsSingle(&arena->messageRing)); - - return MessageNodeMessage(RingNext(&arena->messageRing)); -} - -/* Delete the message at the head of the queue (helper function). */ -static void MessageDeleteHead(Arena arena) -{ - Message message; - - AVERT(Arena, arena); - AVER(!RingIsSingle(&arena->messageRing)); - - message = MessageHead(arena); - AVERT(Message, message); - RingRemove(&message->queueRing); - MessageDelete(message); -} - -/* Empty the queue by discarding all messages */ -void MessageEmpty(Arena arena) -{ - AVERT(Arena, arena); - - while(!RingIsSingle(&arena->messageRing)) { - MessageDeleteHead(arena); - } -} - - -/* Delivery (Client) Interface -- functions for recipient - * - * Most of these functions are exposed through the external MPS - * interface. - */ - - -static Bool MessageTypeEnabled(Arena arena, MessageType type) -{ - AVERT(Arena, arena); - AVER(MessageTypeCheck(type)); - - return BTGet(arena->enabledMessageTypes, type); -} - -void MessageTypeEnable(Arena arena, MessageType type) -{ - AVERT(Arena, arena); - AVER(MessageTypeCheck(type)); - - BTSet(arena->enabledMessageTypes, type); -} - -void MessageTypeDisable(Arena arena, MessageType type) -{ - Message message; - - AVERT(Arena, arena); - AVER(MessageTypeCheck(type)); - - /* Flush existing messages of this type */ - while(MessageGet(&message, arena, type)) { - MessageDelete(message); - } - - BTRes(arena->enabledMessageTypes, type); -} - -/* Any messages on the queue? */ -Bool MessagePoll(Arena arena) -{ - AVERT(Arena, arena); - - if(RingIsSingle(&arena->messageRing)) { - return FALSE; - } else { - return TRUE; - } -} - -/* Return the type of the message at the head of the queue, if any */ -Bool MessageQueueType(MessageType *typeReturn, Arena arena) -{ - Message message; - MessageType type; - - AVER(typeReturn != NULL); - AVERT(Arena, arena); - - if(!MessagePoll(arena)) { - return FALSE; - } - message = MessageHead(arena); - type = MessageGetType(message); - *typeReturn = type; - - return TRUE; -} - -/* Get next message of specified type, removing it from the queue */ -Bool MessageGet(Message *messageReturn, Arena arena, MessageType type) -{ - Ring node, next; - - AVER(messageReturn != NULL); - AVERT(Arena, arena); - AVER(MessageTypeCheck(type)); - - RING_FOR(node, &arena->messageRing, next) { - Message message = RING_ELT(Message, queueRing, node); - if(MessageGetType(message) == type) { - RingRemove(&message->queueRing); - *messageReturn = message; - return TRUE; - } - } - return FALSE; -} - -/* Discard a message (recipient has finished using it). */ -void MessageDiscard(Arena arena, Message message) -{ - AVERT(Arena, arena); - AVERT(Message, message); - - AVER(!MessageOnQueue(message)); - - MessageDelete(message); -} - - -/* Message Methods, Generic - * - * (Some of these dispatch on message->class). - */ - - -/* Return the type of a message */ -MessageType MessageGetType(Message message) -{ - MessageClass class; - AVERT(Message, message); - - class = message->class; - AVERT(MessageClass, class); - - return class->type; -} - -/* Return the class of a message */ -MessageClass MessageGetClass(Message message) -{ - AVERT(Message, message); - - return message->class; -} - -Clock MessageGetClock(Message message) -{ - AVERT(Message, message); - - return message->postedClock; -} - -static void MessageDelete(Message message) -{ - AVERT(Message, message); - - (*message->class->delete)(message); -} - - -/* Message Method Dispatchers, Type-specific - * - */ - - -void MessageFinalizationRef(Ref *refReturn, Arena arena, - Message message) -{ - AVER(refReturn != NULL); - AVERT(Arena, arena); - AVERT(Message, message); - AVER(MessageGetType(message) == MessageTypeFINALIZATION); - - (*message->class->finalizationRef)(refReturn, arena, message); - - return; -} - -Size MessageGCLiveSize(Message message) -{ - AVERT(Message, message); - AVER(MessageGetType(message) == MessageTypeGC); - - return (*message->class->gcLiveSize)(message); -} - -Size MessageGCCondemnedSize(Message message) -{ - AVERT(Message, message); - AVER(MessageGetType(message) == MessageTypeGC); - - return (*message->class->gcCondemnedSize)(message); -} - -Size MessageGCNotCondemnedSize(Message message) -{ - AVERT(Message, message); - AVER(MessageGetType(message) == MessageTypeGC); - - return (*message->class->gcNotCondemnedSize)(message); -} - -const char *MessageGCStartWhy(Message message) -{ - AVERT(Message, message); - AVER(MessageGetType(message) == MessageTypeGCSTART); - - return (*message->class->gcStartWhy)(message); -} - - -/* Message Method Stubs, Type-specific - * - */ - - -void MessageNoFinalizationRef(Ref *refReturn, Arena arena, - Message message) -{ - AVER(refReturn != NULL); - AVERT(Arena, arena); - AVERT(Message, message); - - NOTREACHED; -} - -Size MessageNoGCLiveSize(Message message) -{ - AVERT(Message, message); - UNUSED(message); - - NOTREACHED; - - return (Size)0; -} - -Size MessageNoGCCondemnedSize(Message message) -{ - AVERT(Message, message); - UNUSED(message); - - NOTREACHED; - - return (Size)0; -} - -Size MessageNoGCNotCondemnedSize(Message message) -{ - AVERT(Message, message); - UNUSED(message); - - NOTREACHED; - - return (Size)0; -} - -const char *MessageNoGCStartWhy(Message message) -{ - AVERT(Message, message); - UNUSED(message); - - NOTREACHED; - - return NULL; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/messtest.c b/mps/code/messtest.c deleted file mode 100644 index 2bb608481e0..00000000000 --- a/mps/code/messtest.c +++ /dev/null @@ -1,315 +0,0 @@ -/* messtest.c: MESSAGE TEST - * - * $Id$ - * Copyright (c) 2001-2003 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" -#include "mpsavm.h" -#include "mps.h" -#include "testlib.h" - -#include -#include - -SRCID(messtest, "$Id$"); - - -/* Basic infrastructure for creating dummy messages */ - -static void dfMessageDelete(Message message) -{ - Arena arena; - arena = MessageArena(message); - ControlFree(arena, (void *)message, sizeof(MessageStruct)); -} - - -/* DFMessageClassStruct -- dummy finalization message class */ - -static MessageClassStruct DFMessageClassStruct = { - MessageClassSig, /* sig */ - "DummyFinal", /* name */ - MessageTypeFINALIZATION, /* Message Type */ - dfMessageDelete, /* Delete */ - MessageNoFinalizationRef, /* FinalizationRef */ - MessageNoGCLiveSize, /* GCLiveSize */ - MessageNoGCCondemnedSize, /* GCCondemnedSize */ - MessageNoGCNotCondemnedSize, /* GCNotCondemnedSize */ - MessageNoGCStartWhy, /* GCStartWhy */ - MessageClassSig /* */ -}; - - -/* DGCMessageClassStruct -- dummy GC message class */ - -static MessageClassStruct DGCMessageClassStruct = { - MessageClassSig, /* sig */ - "DummyGC", /* name */ - MessageTypeGC, /* Message Type */ - dfMessageDelete, /* Delete */ - MessageNoFinalizationRef, /* FinalizationRef */ - MessageNoGCLiveSize, /* GCLiveSize */ - MessageNoGCCondemnedSize, /* GCCondemnedSize */ - MessageNoGCNotCondemnedSize, /* GCNoteCondemnedSize */ - MessageNoGCStartWhy, /* GCStartWhy */ - MessageClassSig /* */ -}; - - -static void checkNoMessages(Arena arena) -{ - cdie(!MessagePoll(arena), "Queue not empty"); -} - - -static void topMessageType(MessageType *typeReturn, Arena arena) -{ - cdie(MessageQueueType(typeReturn, arena), "Queue empty"); -} - - -/* postDummyMessage -- post a dummy message */ - -static void postDummyMessage(Arena arena, MessageClass class, - MessageType type) -{ - void *p; - Message message; - - die((mps_res_t)ControlAlloc(&p, arena, sizeof(MessageStruct), FALSE), - "AllocMessage"); - message = (Message)p; - MessageInit(arena, message, class, type); - MessagePost(arena, message); - return; -} - - -/* postFinalizationMessage -- post dummy finalization message */ - -static void postFinalizationMessage(Arena arena) -{ - postDummyMessage(arena, &DFMessageClassStruct, MessageTypeFINALIZATION); -} - -/* postGCMessage -- post dummy GC message */ - -static void postGCMessage(Arena arena) -{ - postDummyMessage(arena, &DGCMessageClassStruct, MessageTypeGC); -} - - -/* postInterleavedMessages -- post a couple of each message type */ - -static void postInterleavedMessages(Arena arena) -{ - postFinalizationMessage(arena); - postGCMessage(arena); - postFinalizationMessage(arena); - postGCMessage(arena); -} - - -/* eatMessageOfType -- get a message of a specified type - * - * There must be at least 1 message of that type on the queue. - */ - -static void eatMessageOfType(Arena arena, MessageType type) -{ - Message message; - cdie(MessageGet(&message, arena, type), "No message"); - MessageDiscard(arena, message); -} - - -/* eatHiddenMessage -- get a message which isn't at top of queue - * - * Assumes there is at least 1 message of each of Finalization - * and GC types. - */ - -static void eatHiddenMessage(Arena arena) -{ - MessageType type, eatType; - - topMessageType(&type, arena); - if (type != MessageTypeGC) { - eatType = MessageTypeGC; - } else { - eatType = MessageTypeFINALIZATION; - } - eatMessageOfType(arena, eatType); -} - - -/* eatTopMessageOfType -- get a message which is at top of queue - * - * The message must be of the specified type. - * Assumes there is at least 1 message on the queue. - */ - -static void eatTopMessageOfType(Arena arena, MessageType type) -{ - MessageType topType; - - topMessageType(&topType, arena); - cdie((topType == type), "Unexpected type"); - eatMessageOfType(arena, type); -} - - -/* eatTopMessage -- get a message which is at top of queue - * - * Assumes there is at least 1 message on the queue. - */ - -static void eatTopMessage(Arena arena) -{ - MessageType type; - - topMessageType(&type, arena); - eatMessageOfType(arena, type); -} - - - -/* testInterleaving -- test interleaving messages of different types - * - * See request.dylan.160204 - * must be able to retrieve a message even if a message of - * another type is at the head of the queue. - */ - -static void testInterleaving(Arena arena) -{ - MessageEmpty(arena); - - /* enable both types of message */ - MessageTypeEnable(arena, MessageTypeGC); - MessageTypeEnable(arena, MessageTypeFINALIZATION); - - /* post a couple of interleaved messages of each type */ - postInterleavedMessages(arena); - - /* check that we can pull out 2 messages not at the head */ - eatHiddenMessage(arena); - eatHiddenMessage(arena); - - /* check that we can pull out 2 messages which are at the head */ - eatTopMessage(arena); - eatTopMessage(arena); -} - - -/* testDisabling -- test message types can be disabled - * - * See request.dylan.160204 - */ - -static void testDisabling(Arena arena) -{ - MessageEmpty(arena); - - /* enable both types of message */ - MessageTypeEnable(arena, MessageTypeGC); - MessageTypeEnable(arena, MessageTypeFINALIZATION); - - /* post a couple of interleaved messages of each type */ - postInterleavedMessages(arena); - - /* Disable one of the types */ - MessageTypeDisable(arena, MessageTypeFINALIZATION); - - /* check that we can pull out 2 messages of the other type */ - eatTopMessageOfType(arena, MessageTypeGC); - eatTopMessageOfType(arena, MessageTypeGC); - - /* check that the queue is empty */ - checkNoMessages(arena); - - /* Post a disabled message */ - postFinalizationMessage(arena); - - /* check that the queue is still empty */ - checkNoMessages(arena); -} - - -/* testGetEmpty -- test we don't AVER when getting a non-existent message */ - -static void testGetEmpty(Arena arena) -{ - Message message; - - MessageEmpty(arena); - checkNoMessages(arena); - cdie(!MessageGet(&message, arena, MessageTypeGC), "Got non-existent message"); -} - - -#define testArenaSIZE (((size_t)64)<<20) - -extern int main(int argc, char *argv[]) -{ - mps_arena_t mpsArena; - Arena arena; - - testlib_unused(argc); - testlib_unused(argv); - - die(mps_arena_create(&mpsArena, mps_arena_class_vm(), testArenaSIZE), - "mps_arena_create"); - arena = (Arena)mpsArena; - - testGetEmpty(arena); - testInterleaving(arena); - testDisabling(arena); - - printf("\nNo problems detected.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/meter.c b/mps/code/meter.c deleted file mode 100644 index 04f684c07f3..00000000000 --- a/mps/code/meter.c +++ /dev/null @@ -1,144 +0,0 @@ -/* meter.c: METERS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * TRANSGRESSIONS - * - * .trans.label: We label meters with EventLabelAddr, but of course that's - * meant for labelling Addr's. We get away with it as long as the type - * Meter is compatible with Addr. - */ - -#include "meter.h" -#include "mpm.h" - -SRCID(meter, "$Id$"); - - -/* MeterInit -- initialize a meter */ - -void MeterInit(Meter meter, char *name, void *owner) -{ - Word sym; - - meter->name = name; - meter->count = 0; - meter->total = 0.0; - meter->meanSquared = 0.0; - meter->max = 0; - meter->min = (Size)-1; - - sym = EventInternString(name); - EventLabelAddr((Addr)meter, sym); /* see .trans.label */ - EVENT2(MeterInit, meter, owner); -} - - -/* MeterAccumulate -- accumulate another data point in the meter */ - -void MeterAccumulate(Meter meter, Size amount) -{ - Count count = meter->count + 1; - double total = meter->total; - double meanSquared = meter->meanSquared; - double dcount = (double)count; - - /* .limitation.variance: This computation accumulates a running - * mean^2, minimizing overflow, but sacrificing numerical stablity - * for small variances. For more accuracy, the data set should be - * emitted using a telemetry stream and analyzed off-line. - .stddev: stddev = sqrt(meanSquared - mean^2). - */ - meter->count = count; - meter->total = total + amount; - meter->meanSquared = - meanSquared / dcount * (dcount - 1.0) - + amount / dcount * amount; - if (amount > meter->max) - meter->max = amount; - if (amount < meter->min) - meter->min = amount; -} - - -/* MeterWrite -- describe method for meters */ - -Res MeterWrite(Meter meter, mps_lib_FILE *stream) -{ - Res res = ResOK; - - res = WriteF(stream, - "meter $S {", meter->name, - "count: $U", meter->count, - NULL); - if (res != ResOK) - return res; - if (meter->count > 0) { - double mean = meter->total / (double)meter->count; - - res = WriteF(stream, - ", total: $D", meter->total, - ", max: $U", meter->max, - ", min: $U", meter->min, - ", mean: $D", mean, - ", mean^2: $D", meter->meanSquared, - NULL); - if (res != ResOK) - return res; - } - res = WriteF(stream, "}\n", NULL); - - return res; -} - - -/* MeterEmit -- emit an evnet with the current data from the meter */ - -void MeterEmit(Meter meter) -{ - EVENT6(MeterValues, meter, meter->total, meter->meanSquared, - meter->count, meter->max, meter->min); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/meter.h b/mps/code/meter.h deleted file mode 100644 index 6912ca7afc0..00000000000 --- a/mps/code/meter.h +++ /dev/null @@ -1,99 +0,0 @@ -/* meter.h: METER INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .sources: mps.design.metrics. - * - * .purpose: Defines an interface for creating "meters" that accumulate - * the number, total and mean^2 of a set of data points. These - * accumulators can be used to report on the number, total, average, and - * variance of the data set. - */ - -#ifndef meter_h -#define meter_h - -#include "mpmtypes.h" -#include "config.h" -#include "misc.h" -#include "mpslib.h" - - -typedef struct MeterStruct *Meter; - -typedef struct MeterStruct -{ - char *name; - Count count; - double total; - double meanSquared; - Size min; - Size max; -} MeterStruct; - - -extern void MeterInit(Meter meter, char* name, void *owner); -extern void MeterAccumulate(Meter meter, Size amount); -extern Res MeterWrite(Meter meter, mps_lib_FILE *stream); -extern void MeterEmit(Meter meter); - -#define METER_DECL(meter) STATISTIC_DECL(struct MeterStruct meter) -#define METER_INIT(meter, init, owner) \ - BEGIN STATISTIC(MeterInit(&(meter), init, owner)); UNUSED(owner); END -/* Hack: owner is typically only used for MeterInit */ -#define METER_ACC(meter, delta) \ - STATISTIC(MeterAccumulate(&(meter), delta)) -#if defined(STATISTICS) -#define METER_WRITE(meter, stream) MeterWrite(&(meter), stream) -#elif defined(STATISTICS_NONE) -#define METER_WRITE(meter, stream) (ResOK) -#else -#error "No statistics configured." -#endif -#define METER_EMIT(meter) STATISTIC(MeterEmit(meter)) - - -#endif /* meter_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/misc.h b/mps/code/misc.h deleted file mode 100644 index 0557c9af6fc..00000000000 --- a/mps/code/misc.h +++ /dev/null @@ -1,230 +0,0 @@ -/* misc.h: MISCELLANEOUS DEFINITIONS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2001 Global Graphics Software. - * - * Small general things which are useful for C but aren't part of the - * memory manager itself. The only reason that this file exists is - * that these things are too small and trivial to be put in their own - * headers. If they ever become non-trivial they should be moved out. - */ - -#ifndef misc_h -#define misc_h - -#include - - -typedef int Bool; /* */ -enum BoolEnum { - FALSE = 0, - TRUE = 1 -}; - - -/* SrcId -- source identification - * - * Every C source file should start with a SRCID declaration to - * create a local static source identification structure. This - * is used by other macros (particularly assertions) and can be - * used to reverse engineer binary deliverables. - */ - -typedef const struct SrcIdStruct *SrcId; -typedef const struct SrcIdStruct { - const char *file; - const char *scmid; - const char *build_date; - const char *build_time; -} SrcIdStruct; - -#define SRCID(id, scmid) \ - static SrcIdStruct id ## FileSrcIdStruct = \ - {__FILE__, (scmid), __DATE__, __TIME__}; \ - SrcId id ## SrcId = &id ## FileSrcIdStruct - - -/* BEGIN and END -- statement brackets - * - * BEGIN and END can be used to bracket multi-statement blocks which - * will be followed by a semicolon, such as multi-statement macros. - * BEGIN and END should be used to bracket ALL multi-statement macros. - * The block, with its semicolon, still counts as a single statement. - * This ensures that such macros can be used in all statement contexts, - * including in the first branch of an if() statement which has an else - * clause. - */ - -#define BEGIN do { -#define END } while(0) - - - -/* RVALUE -- for method-style macros - * - * RVALUE is used to enclose the expansion of a macro that must not be - * used as an lvalue, e.g. a getter method. - */ - -#define RVALUE(expr) ((void)0, (expr)) - -/* NOOP -- null statement - * - * Do not be tempted to use NULL, or just semicolon as the null - * statement. These items are dangerously ambigous and could cause - * subtle bugs if misplaced. NOOP is a macro which is guaranteed to - * cause an error if it is not used in a statement context. - */ - -#define NOOP do {} while(0) - - -/* STR -- expands into a string of the expansion of the argument - * - * E.g., if we have: - * #define a b - * STR(a) will expand into "b". - */ - -#define STR_(x) #x -#define STR(x) STR_(x) - -/* NELEMS -- counts number of elements in an array - * - * NELEMS(a) expands into an expression that is the number - * of elements in the array a. - * - * WARNING: expands a more than once (you'd have to write obviously - * perverse code for this to matter though). - */ - -#define NELEMS(a) (sizeof(a)/sizeof((a)[0])) - - -/* DISCARD -- discards an expression, but checks syntax - * - * The argument is an expression; the expansion followed by a semicolon - * is syntactically a statement (to avoid it being used in computation). - * - * .discard: DISCARD uses sizeof so that the expression is not evaluated - * and yet the compiler will check that it is a valid expression. The - * conditional is compared with zero so it can designate a bitfield object. - */ - -#define DISCARD(expr) \ - BEGIN \ - (void)sizeof((expr)!=0); \ - END - - -/* DISCARD_STAT -- discards a statement, but checks syntax - * - * The argument is a statement; the expansion followed by a semicolon - * is syntactically a statement. - */ - -#define DISCARD_STAT(stat) \ - BEGIN \ - if (0) stat; \ - END - - -/* UNUSED -- declare parameter unused - * - * This macro supresses warnings about unused parameters. It should be - * applied to the parameter at the beginning of the body of the - * procedure. - * - * The cast to void appears to work for GCC, MSVC, and CodeWarrior. - * It's a shame there's no way to ensure that the parameter won't be - * used. We could scramble it, but that's undesirable in release - * versions. - */ - -#define UNUSED(param) ((void)param) - - -/* PARENT -- parent structure - * - * Given a pointer to a field of a structure this returns a pointer to - * the main structure. PARENT(foo_t, x, &(foo->x)) == foo. - * - * This macro is thread-safe, see design.mps.misc.parent.thread-safe. - * - * That intermediate (void *) is required to stop some compilers complaining - * about alignment of 'type *' being greater than that of 'char *'. Which - * is true, but not a bug, since the result really is a pointer to a 'type' - * struct. - */ - -#define PARENT(type, field, p) \ - ((type *)(void *)((char *)(p) - offsetof(type, field))) - - -/* Bit Sets -- sets of integers in [0,N-1]. - * - * Can be used on any unsigned integral type, ty. These definitions - * are _syntactic_, hence macroid, hence upper case - * (guide.c.naming.macro.special). - */ - -#define BS_EMPTY(ty) ((ty)0) -#define BS_COMP(s) (~(s)) -#define BS_UNIV(ty) BS_COMP(BS_EMPTY(ty)) -#define BS_SINGLE(ty, i) ((ty)1 << (i)) -#define BS_IS_MEMBER(s, i) (((s) >> (i)) & 1) -#define BS_UNION(s1, s2) ((s1) | (s2)) -#define BS_ADD(ty, s, i) BS_UNION((s), BS_SINGLE(ty, (i))) -#define BS_INTER(s1, s2) ((s1) & (s2)) -#define BS_DIFF(s1, s2) BS_INTER((s1), BS_COMP(s2)) -#define BS_DEL(ty, s, i) BS_DIFF((s), BS_SINGLE(ty, (i))) -#define BS_SUPER(s1, s2) (BS_INTER((s1), (s2)) == (s2)) -#define BS_SUB(s1, s2) BS_SUPER((s2), (s1)) -#define BS_IS_SINGLE(s) ( ((s) != 0) && (((s) & ((s)-1)) == 0) ) -#define BS_SYM_DIFF(s1, s2) ((s1) ^ (s2)) - - -#endif /* misc_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpm.c b/mps/code/mpm.c deleted file mode 100644 index 4623ca7fad6..00000000000 --- a/mps/code/mpm.c +++ /dev/null @@ -1,642 +0,0 @@ -/* mpm.c: GENERAL MPM SUPPORT - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: Miscellaneous support for the implementation of the MPM - * and pool classes. - * - * .sources: */ - -#include "check.h" -#include "mpm.h" -#include -/* Get some floating constants for WriteDouble */ -#include -#include - -SRCID(mpm, "$Id$"); - - -#if defined(AVER_AND_CHECK) - - -/* CheckLevel -- Control check level - * - * This controls the behaviour of Check methods (see check.h). - */ - -#ifdef CHECKLEVEL_DYNAMIC -unsigned CheckLevel = CHECKLEVEL_DYNAMIC; -#endif - - -/* MPMCheck -- test MPM assumptions */ - -Bool MPMCheck(void) -{ - CHECKL(sizeof(Word) * CHAR_BIT == MPS_WORD_WIDTH); - CHECKL((Word)1 << MPS_WORD_SHIFT == MPS_WORD_WIDTH); - CHECKL(AlignCheck(MPS_PF_ALIGN)); - /* Check that trace ids will fit in the TraceId type. */ - CHECKL(TraceLIMIT <= UINT_MAX); - /* Check that there are enough bits in */ - /* a TraceSet to store all possible trace ids. */ - CHECKL(sizeof(TraceSet) * CHAR_BIT >= TraceLIMIT); - - CHECKL((SizeAlignUp(0, 2048) == 0)); - CHECKL(!SizeIsAligned(64, (unsigned) -1)); - CHECKL(SizeIsAligned(0, 32)); - CHECKL((SizeAlignUp(1024, 16) == 1024)); - /* .prime: 31051 is prime */ - CHECKL(SizeIsAligned(SizeAlignUp(31051, 256), 256)); - CHECKL(SizeIsAligned(SizeAlignUp(31051, 512), 512)); - CHECKL(!SizeIsAligned(31051, 1024)); - CHECKL(!SizeIsP2(0)); - CHECKL(SizeIsP2(128)); - CHECKL(SizeLog2((Size)1) == 0); - CHECKL(SizeLog2((Size)256) == 8); - CHECKL(SizeLog2((Size)65536) == 16); - CHECKL(SizeLog2((Size)131072) == 17); - - /* .check.writef: We check that various types will fit in a Word; */ - /* See .writef.check. Don't need to check WriteFS or WriteFF as they */ - /* should not be cast to Word. */ - CHECKL(sizeof(WriteFA) <= sizeof(Word)); - CHECKL(sizeof(WriteFP) <= sizeof(Word)); - CHECKL(sizeof(WriteFW) <= sizeof(Word)); /* Should be trivial*/ - CHECKL(sizeof(WriteFU) <= sizeof(Word)); - CHECKL(sizeof(WriteFB) <= sizeof(Word)); - CHECKL(sizeof(WriteFC) <= sizeof(Word)); - /* .check.write.double: See .write.double.check */ - { - int e, DBL_EXP_DIG = 1; - for (e = DBL_MAX_10_EXP; e > 0; e /= 10) - DBL_EXP_DIG++; - CHECKL(DBL_EXP_DIG < DBL_DIG); - CHECKL(-(DBL_MIN_10_EXP) <= DBL_MAX_10_EXP); - } - - return TRUE; -} - - -/* FunCheck -- check that a function pointer is valid */ - -Bool FunCheck(Fun f) -{ - CHECKL(f != NULL); - /* Could assert various platform-specific things here. */ - UNUSED(f); /* see .check.unused */ - return TRUE; -} - - -/* ShiftCheck -- check that a shift is valid */ - -Bool ShiftCheck(Shift shift) -{ - CHECKL(shift < MPS_WORD_WIDTH); /* standard.ansic 6.3.7 */ - UNUSED(shift); /* see .check.unused */ - return TRUE; -} - - -/* AttrCheck -- check that a set of pool attributes are valid */ - -Bool AttrCheck(Attr attr) -{ - CHECKL((attr & ~AttrMASK) == 0); - /* Could check for legal combinations of attributes. */ - UNUSED(attr); /* see .check.unused */ - return TRUE; -} - - -/* AlignCheck -- check that an alignment is valid */ - -Bool AlignCheck(Align align) -{ - CHECKL(align > 0 && (align & (align - 1)) == 0); - /* .check.unused: Check methods for signatureless types don't use */ - /* their argument in hot varieties, so UNUSED is needed. */ - UNUSED(align); - return TRUE; -} - - -#endif /* defined(AVER_AND_CHECK) */ - - -/* WordIsAligned -- test whether a word is aligned */ - -Bool (WordIsAligned)(Word word, Align align) -{ - AVER(AlignCheck(align)); - return WordIsAligned(word, align); -} - - -/* WordAlignUp -- round a word up to the nearest aligned value */ - -Word (WordAlignUp)(Word word, Align align) -{ - AVER(AlignCheck(align)); - return WordAlignUp(word, align); -} - -/* WordRoundUp -- round word up to round. - * - * .wordroundup.arg.word: The word arg is quantity to be rounded. - * .wordroundup.arg.round: The modulus argument is not necessarily an - * alignment (i.e., not a power of two). - * - * .wordroundup.result: Let m be congruent to 0 mod r (m == 0(r)), and - * let m be the least m >= w. If w+r-1 (!) is representable in Word - * then result is m. Otherwise result is 0. Wittily. (NB. Result may - * be 0 even if m is representable.) */ - -Word (WordRoundUp)(Word word, Size modulus) -{ - AVER(modulus > 0); - return WordRoundUp(word, modulus); -} - - -/* WordAlignUp -- round a word down to the nearest aligned value */ - -Word (WordAlignDown)(Word word, Align alignment) -{ - AVER(AlignCheck(alignment)); - return WordAlignDown(word, alignment); -} - - -/* SizeIsP2 -- test whether a size is a power of two */ - -Bool SizeIsP2(Size size) -{ - return WordIsP2((Word)size); -} - -/* WordIsP2 -- tests whether a word is a power of two */ - -Bool WordIsP2(Word word) -{ - return word > 0 && (word & (word - 1)) == 0; -} - - -/* Logarithms */ - -Shift SizeFloorLog2(Size size) -{ - Shift l = 0; - - AVER(size != 0); - while(size > 1) { - ++l; - size >>= 1; - } - return l; -} - -Shift SizeLog2(Size size) -{ - AVER(SizeIsP2(size)); - return SizeFloorLog2(size); -} - - -/* AddrAlignDown -- round a word down to the nearest aligned value */ - -Addr (AddrAlignDown)(Addr addr, Align alignment) -{ - AVER(AlignCheck(alignment)); - return AddrAlignDown(addr, alignment); -} - - -/* ResIsAllocFailure - * - * Test whether a result code is in the set of allocation failure codes. */ - -Bool ResIsAllocFailure(Res res) -{ - return (res == ResMEMORY || res == ResRESOURCE || res == ResCOMMIT_LIMIT); -} - - -/* WriteULongest -- output a textual representation of an integer to a stream - * - * Output as an unsigned value in the given base (2-16), padded to the - * given width. */ - -static Res WriteULongest(mps_lib_FILE *stream, ULongest w, unsigned base, - unsigned width) -{ - static const char digit[16 + 1] = "0123456789ABCDEF"; - /* + 1 for terminator: unused, but prevents compiler warning */ - static const char pad = '0'; /* padding character */ - char buf[MPS_WORD_WIDTH + 1]; /* enough for binary, */ - /* plus one for terminator */ - unsigned i; - int r; - - AVER(stream != NULL); - AVER(2 <= base); - AVER(base <= 16); - AVER(width <= MPS_WORD_WIDTH); - - /* Add digits to the buffer starting at the right-hand end, so that */ - /* the buffer forms a string representing the number. A do...while */ - /* loop is used to ensure that at least one digit (zero) is written */ - /* when the number is zero. */ - i = MPS_WORD_WIDTH; - buf[i] = '\0'; - do { - --i; - buf[i] = digit[w % base]; - w /= base; - } while(w > 0); - - /* If the number is not as wide as the requested field, pad out the */ - /* buffer with zeros. */ - while(i > MPS_WORD_WIDTH - width) { - --i; - buf[i] = pad; - } - - r = Stream_fputs(&buf[i], stream); - if (r == mps_lib_EOF) - return ResIO; - - return ResOK; -} - - -/* WriteDouble -- write a double float to a stream - * - * Cf.: Guy L. Steele, Jr. and Jon L. White, "How to print - * floating-point numbers accurately", ACM SIGPLAN Notices, Vol. 25, - * No. 6 (Jun. 1990), Pages 112-126 - * - * .write.double.limitation: Only the "simple" printer is implemented - * here. - * - * .write.double.check: There being no DBL_EXP_DIG, we assume that it is - * less than DBL_DIG. */ - -static Res WriteDouble(mps_lib_FILE *stream, double d) -{ - double F = d; - int E = 0, i, x = 0; - /* Largest exponent that will print in %f style. Larger will use %e */ - /* style. DBL_DIG is chosen for use of doubles as extra-large integers. */ - int expmax = DBL_DIG; - /* Smallest exponent that will print in %f style. Smaller will use */ - /* %e style. -4 is chosen because it is the %g default. */ - int expmin = -4; - /* Epsilon defines how many digits will be printed. Using DBL_EPSILON */ - /* prints all the significant digits. To print fewer digits, set */ - /* epsilon to 10 ^ - N, where N is the desired number of digits. */ - double epsilon = DBL_EPSILON / 2; - char digits[] = "0123456789"; - /* sign, DBL_DIG, '0.', 'e', '+/-', log10(DBL_MAX_10_EXP), */ - /* terminator. See .write.double.check. */ - char buf[1+DBL_DIG+2+1+1+DBL_DIG+1]; - int j = 0; - - if (F == 0.0) { - if (Stream_fputs("0", stream) == mps_lib_EOF) - return ResIO; - return ResOK; - } - - if (F < 0) { - buf[j] = '-'; - j++; - F = - F; - } - - /* This scaling operation could introduce rounding errors. */ - for ( ; F >= 1.0 ; F /= 10.0) { - E++; - if (E > DBL_MAX_10_EXP) { - if (Stream_fputs("Infinity", stream) == mps_lib_EOF) - return ResIO; - return ResOK; - } - } - for ( ; F < 0.1; F *= 10) - E--; - - /* See if %e notation is required */ - if (E > expmax || E <= expmin) { - x = E - 1; - E = 1; - } - - /* Insert leading 0's */ - if (E <= 0) { - buf[j] = '0'; - j++; - } - if (E < 0) { - buf[j] = '.'; - j++; - } - for (i = -E; i > 0; i--) { - buf[j] = '0'; - j++; - } - - /* Convert the fraction to base 10, inserting a decimal according to */ - /* the exponent. This is Steele and White's FP3 algorithm. */ - do { - int U; - - if (E == 0) { - buf[j] = '.'; - j++; - } - F *= 10.0; - U = (int)F; - F = F - U; - epsilon *= 10.0; - E--; - if (F < epsilon || F > 1.0 - epsilon) { - if (F < 0.5) - buf[j] = digits[U]; - else - buf[j] = digits[U + 1]; - j++; - break; - } - buf[j] = digits[U]; - j++; - } while (1); - - /* Insert trailing 0's */ - for (i = E; i > 0; i--) { - buf[j] = '0'; - j++; - } - - /* If %e notation is selected, append the exponent indicator and sign. */ - if (x != 0) { - buf[j] = 'e'; - j++; - if (x < 0) { - buf[j] = '-'; - j++; - x = - x; - } - else { - buf[j] = '+'; - j++; - } - - /* Format the exponent to at least two digits. */ - for (i = 100; i <= x; ) - i *= 10; - i /= 10; - do { - buf[j] = digits[x / i]; - j++; - x %= i; - i /= 10; - } while (i > 0); - } - buf[j] = '\0'; /* arnold */ - - if (Stream_fputs(buf, stream) == mps_lib_EOF) - return ResIO; - return ResOK; -} - - -/* WriteF -- write formatted output - * - * .writef.des: See , also - * - * .writef.p: There is an assumption that void * fits in Word in - * the case of $P, and ULongest for $U and $B. This is checked in - * MPMCheck. - * - * .writef.div: Although MPS_WORD_WIDTH/4 appears three times, there - * are effectively three separate decisions to format at this width. - * - * .writef.check: See .check.writef. - */ - -Res WriteF(mps_lib_FILE *stream, ...) -{ - Res res; - va_list args; - - va_start(args, stream); - res = WriteF_v(stream, args); - va_end(args); - return res; -} - -Res WriteF_v(mps_lib_FILE *stream, va_list args) -{ - const char *firstformat; - Res res; - - firstformat = va_arg(args, const char *); - res = WriteF_firstformat_v(stream, firstformat, args); - return res; -} - -Res WriteF_firstformat_v(mps_lib_FILE *stream, - const char *firstformat, va_list args) -{ - const char *format; - int r; - size_t i; - Res res; - - AVER(stream != NULL); - - format = firstformat; - - for(;;) { - if (format == NULL) - break; - - while(*format != '\0') { - if (*format != '$') { - r = Stream_fputc(*format, stream); /* Could be more efficient */ - if (r == mps_lib_EOF) return ResIO; - } else { - ++format; - AVER(*format != '\0'); - - switch(*format) { - case 'A': { /* address */ - WriteFA addr = va_arg(args, WriteFA); - res = WriteULongest(stream, (ULongest)addr, 16, - (sizeof(WriteFA) * CHAR_BIT + 3) / 4); - if (res != ResOK) return res; - } break; - - case 'P': { /* pointer, see .writef.p */ - WriteFP p = va_arg(args, WriteFP); - res = WriteULongest(stream, (ULongest)p, 16, - (sizeof(WriteFP) * CHAR_BIT + 3)/ 4); - if (res != ResOK) return res; - } break; - - case 'F': { /* function */ - WriteFF f = va_arg(args, WriteFF); - Byte *b = (Byte *)&f; - /* TODO: Why do we always write these little-endian? */ - for(i=0; i < sizeof(WriteFF); i++) { - res = WriteULongest(stream, (ULongest)(b[i]), 16, - (CHAR_BIT + 3) / 4); - if (res != ResOK) return res; - } - } break; - - case 'S': { /* string */ - WriteFS s = va_arg(args, WriteFS); - r = Stream_fputs((const char *)s, stream); - if (r == mps_lib_EOF) return ResIO; - } break; - - case 'C': { /* character */ - WriteFC c = va_arg(args, WriteFC); /* promoted */ - r = Stream_fputc((int)c, stream); - if (r == mps_lib_EOF) return ResIO; - } break; - - case 'W': { /* word */ - WriteFW w = va_arg(args, WriteFW); - res = WriteULongest(stream, (ULongest)w, 16, - (sizeof(WriteFW) * CHAR_BIT + 3) / 4); - if (res != ResOK) return res; - } break; - - case 'U': { /* decimal, see .writef.p */ - WriteFU u = va_arg(args, WriteFU); - res = WriteULongest(stream, (ULongest)u, 10, 0); - if (res != ResOK) return res; - } break; - - case '3': { /* decimal for thousandths */ - WriteFU u = va_arg(args, WriteFU); - res = WriteULongest(stream, (ULongest)u, 10, 3); - if (res != ResOK) return res; - } break; - - case 'B': { /* binary, see .writef.p */ - WriteFB b = va_arg(args, WriteFB); - res = WriteULongest(stream, (ULongest)b, 2, sizeof(WriteFB) * CHAR_BIT); - if (res != ResOK) return res; - } break; - - case '$': { /* dollar char */ - r = Stream_fputc('$', stream); - if (r == mps_lib_EOF) return ResIO; - } break; - - case 'D': { /* double */ - WriteFD d = va_arg(args, WriteFD); - res = WriteDouble(stream, d); - if (res != ResOK) return res; - } break; - - default: - NOTREACHED; - } - } - - ++format; - } - - format = va_arg(args, const char *); - } - - return ResOK; -} - - -/* StringLength -- slow substitute for strlen */ - -size_t StringLength(const char *s) -{ - size_t i; - - AVER(s != NULL); - - for(i = 0; s[i] != '\0'; i++) - NOOP; - return(i); -} - - -/* StringEqual -- slow substitute for (strcmp == 0) */ - -Bool StringEqual(const char *s1, const char *s2) -{ - Index i; - - AVER(s1); - AVER(s2); - - for(i = 0; ; i++) { - if(s1[i] != s2[i]) - return FALSE; - if(s1[i] == '\0') { - AVER(s2[i] == '\0'); - break; - } - } - return TRUE; -} - - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpm.h b/mps/code/mpm.h deleted file mode 100644 index 049cbf65343..00000000000 --- a/mps/code/mpm.h +++ /dev/null @@ -1,1151 +0,0 @@ -/* mpm.h: MEMORY POOL MANAGER DEFINITIONS - * - * $Id$ - * Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .trans.bufferinit: The Buffer data structure has an Init field and - * an Init method, there's a name clash. We resolve this by calling the - * accessor BufferGetInit. */ - -#ifndef mpm_h -#define mpm_h - -#include "config.h" -#include "misc.h" -#include "check.h" - -#include "event.h" -#include "lock.h" -#include "th.h" -#include "ss.h" -#include "mpslib.h" -#include "ring.h" -#include "tract.h" /* only for certain Seg macros */ -#include "mpmtypes.h" -#include "mpmst.h" - - -/* MPMCheck -- check MPM assumptions */ - -extern Bool MPMCheck(void); - - -/* Miscellaneous Checks -- see */ - -/* */ -#define BoolCheck(b) ((unsigned)(b) <= 1) - -extern Bool FunCheck(Fun f); -#define FUNCHECK(f) (FunCheck((Fun)f)) - -extern Bool ShiftCheck(Shift shift); -extern Bool AttrCheck(Attr attr); -extern Bool RootVarCheck(RootVar rootVar); - - -/* Address/Size Interface -- see */ - -extern Bool AlignCheck(Align align); - -extern Bool (WordIsAligned)(Word word, Align align); -#define WordIsAligned(w, a) (((w) & ((a) - 1)) == 0) - -extern Word (WordAlignUp)(Word word, Align align); -#define WordAlignUp(w, a) (((w) + (a) - 1) & ~((Word)(a) - 1)) - -/* Rounds w up to a multiple of r, see for exact behaviour */ -extern Word (WordRoundUp)(Word word, Size round); -#define WordRoundUp(w, r) (((w)+(r)-1) - ((w)+(r)-1)%(r)) - -extern Word (WordAlignDown)(Word word, Align align); -#define WordAlignDown(w, a) ((w) & ~((Word)(a) - 1)) - -#define size_tAlignUp(s, a) ((size_t)WordAlignUp((Word)(s), a)) - -#define PointerAdd(p, s) ((void *)((char *)(p) + (s))) -#define PointerSub(p, s) ((void *)((char *)(p) - (s))) - -#define PointerOffset(base, limit) \ - ((size_t)((char *)(limit) - (char *)(base))) - -#define PointerAlignUp(p, s) \ - ((void *)WordAlignUp((Word)(p), (Align)(s))) - -#define AddrAdd(p, s) ((Addr)PointerAdd((void *)(p), s)) -#define AddrSub(p, s) ((Addr)PointerSub((void *)(p), s)) - -#define AddrOffset(b, l) \ - ((Size)(PointerOffset((void *)(b), (void *)(l)))) - -extern Addr (AddrAlignDown)(Addr addr, Align align); -#define AddrAlignDown(p, a) ((Addr)WordAlignDown((Word)(p), a)) - -#define AlignWord(s) ((Word)(s)) - -#define AddrIsAligned(p, a) WordIsAligned((Word)(p), a) -#define AddrAlignUp(p, a) ((Addr)WordAlignUp((Word)(p), a)) - -#define SizeIsAligned(s, a) WordIsAligned((Word)(s), a) -#define SizeAlignUp(s, a) ((Size)WordAlignUp((Word)(s), a)) -#define SizeAlignDown(s, a) ((Size)WordAlignDown((Word)(s), a)) -/* r not required to be a power of 2 */ -#define SizeRoundUp(s, r) ((Size)WordRoundUp((Word)(s), (Size)(r))) - -#define IndexIsAligned(s, a) WordIsAligned((Word)(s), a) -#define IndexAlignUp(s, a) ((Index)WordAlignUp((Word)(s), a)) -#define IndexAlignDown(s, a) ((Index)WordAlignDown((Word)(s), a)) - -#define AlignIsAligned(a1, a2) WordIsAligned((Word)(a1), a2) - - -extern Addr (AddrSet)(Addr target, Byte value, Size size); -/* This is one of the places that implements Addr, so it's allowed to */ -/* convert to void *, see . */ -#define AddrSet(target, value, size) \ - mps_lib_memset(target, (int)(value), size) - -extern Addr (AddrCopy)(Addr target, Addr source, Size size); -#define AddrCopy(target, source, size) \ - mps_lib_memcpy(target, source, size) - -extern int (AddrComp)(Addr a, Addr b, Size size); -#define AddrComp(a, b, size) \ - mps_lib_memcmp(a, b, size) - - -/* ADDR_PTR -- turns an Addr into a pointer to the given type */ - -#define ADDR_PTR(type, addr) ((type *)(addr)) - - -/* Clock */ - -#define ClockNow() ((Clock)mps_clock()) -#define ClocksPerSec() ((Clock)mps_clocks_per_sec()) - - -/* Result codes */ - -extern Bool ResIsAllocFailure(Res res); - - -/* Logs and Powers - * - * SizeIsP2 returns TRUE if and only if size is a non-negative integer - * power of 2, and FALSE otherwise. - * - * SizeLog2 returns the logarithm in base 2 of size. size must be a - * power of 2. - * - * SizeFloorLog2 returns the floor of the logarithm in base 2 of size. - * size can be any positive non-zero value. */ - -extern Bool SizeIsP2(Size size); -extern Shift SizeLog2(Size size); -extern Shift SizeFloorLog2(Size size); - -extern Bool WordIsP2(Word word); - -/* Formatted Output -- see , */ - -extern Res WriteF(mps_lib_FILE *stream, ...); -extern Res WriteF_v(mps_lib_FILE *stream, va_list args); -extern Res WriteF_firstformat_v(mps_lib_FILE *stream, - const char *firstformat, va_list args); - -#if defined(DIAG_WITH_STREAM_AND_WRITEF) -extern int Stream_fputc(int c, mps_lib_FILE *stream); -extern int Stream_fputs(const char *s, mps_lib_FILE *stream); -#else -#define Stream_fputc mps_lib_fputc -#define Stream_fputs mps_lib_fputs -#endif - - -/* Miscellaneous support -- see */ - -extern size_t StringLength(const char *s); -extern Bool StringEqual(const char *s1, const char *s2); - - -/* Version Determination - * - * See . */ - -extern char *MPSVersion(void); - - -/* Pool Interface -- see impl.c.pool */ - -extern Res PoolInit(Pool pool, Arena arena, PoolClass class, ...); -extern Res PoolInitV(Pool pool, Arena arena, PoolClass class, va_list args); -extern void PoolFinish(Pool pool); -extern Bool PoolClassCheck(PoolClass class); -extern Bool PoolCheck(Pool pool); -extern Res PoolDescribe(Pool pool, mps_lib_FILE *stream); - -#define PoolArena(pool) ((pool)->arena) -#define PoolAlignment(pool) ((pool)->alignment) -#define PoolSegRing(pool) (&(pool)->segRing) - -extern Bool PoolFormat(Format *formatReturn, Pool pool); - -extern double PoolMutatorAllocSize(Pool pool); - -extern Bool PoolOfAddr(Pool *poolReturn, Arena arena, Addr addr); -extern Bool PoolHasAddr(Pool pool, Addr addr); - -extern Res PoolCreate(Pool *poolReturn, Arena arena, PoolClass class, ...); -extern Res PoolCreateV(Pool *poolReturn, Arena arena, PoolClass class, - va_list arg); -extern void PoolDestroy(Pool pool); -extern BufferClass PoolDefaultBufferClass(Pool pool); -extern Res PoolAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit); -extern void PoolFree(Pool pool, Addr old, Size size); -extern Res PoolTraceBegin(Pool pool, Trace trace); -extern Res PoolAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context); -extern Res PoolWhiten(Pool pool, Trace trace, Seg seg); -extern void PoolGrey(Pool pool, Trace trace, Seg seg); -extern void PoolBlacken(Pool pool, TraceSet traceSet, Seg seg); -extern Res PoolScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg); -extern Res (PoolFix)(Pool pool, ScanState ss, Seg seg, Addr *refIO); -#define PoolFix(pool, ss, seg, refIO) \ - ((*(pool)->fix)(pool, ss, seg, refIO)) -extern Res PoolFixEmergency(Pool pool, ScanState ss, Seg seg, Addr *refIO); -extern void PoolReclaim(Pool pool, Trace trace, Seg seg); -extern void PoolTraceEnd(Pool pool, Trace trace); -extern void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, - void *v, size_t s); -extern void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p); -extern Res PoolTrivInit(Pool pool, va_list arg); -extern void PoolTrivFinish(Pool pool); -extern Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit); -extern Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit); -extern void PoolNoFree(Pool pool, Addr old, Size size); -extern void PoolTrivFree(Pool pool, Addr old, Size size); -extern Res PoolNoBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit); -extern Res PoolTrivBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit); -extern void PoolNoBufferEmpty(Pool pool, Buffer buffer, - Addr init, Addr limit); -extern void PoolTrivBufferEmpty(Pool pool, Buffer buffer, - Addr init, Addr limit); -extern Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream); -extern Res PoolNoTraceBegin(Pool pool, Trace trace); -extern Res PoolTrivTraceBegin(Pool pool, Trace trace); -extern Res PoolNoAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context); -extern Res PoolSegAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context); -extern Res PoolSingleAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context); -extern Res PoolNoWhiten(Pool pool, Trace trace, Seg seg); -extern Res PoolTrivWhiten(Pool pool, Trace trace, Seg seg); -extern void PoolNoGrey(Pool pool, Trace trace, Seg seg); -extern void PoolTrivGrey(Pool pool, Trace trace, Seg seg); -extern void PoolNoBlacken(Pool pool, TraceSet traceSet, Seg seg); -extern void PoolTrivBlacken(Pool pool, TraceSet traceSet, Seg seg); -extern Res PoolNoScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg); -extern Res PoolNoFix(Pool pool, ScanState ss, Seg seg, Ref *refIO); -extern void PoolNoReclaim(Pool pool, Trace trace, Seg seg); -extern void PoolTrivTraceEnd(Pool pool, Trace trace); -extern void PoolNoRampBegin(Pool pool, Buffer buf, Bool collectAll); -extern void PoolTrivRampBegin(Pool pool, Buffer buf, Bool collectAll); -extern void PoolNoRampEnd(Pool pool, Buffer buf); -extern void PoolTrivRampEnd(Pool pool, Buffer buf); -extern Res PoolNoFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf); -extern Res PoolTrivFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf); -extern Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame); -extern Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame); -extern void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame); -extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsStepMethod step, - void *p, size_t s); -extern void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p); -extern PoolDebugMixin PoolNoDebugMixin(Pool pool); -extern BufferClass PoolNoBufferClass(void); - -#define ClassOfPool(pool) ((pool)->class) -#define SuperclassOfPool(pool) \ - ((PoolClass)ProtocolClassSuperclassPoly((pool)->class)) - - -/* Abstract Pool Classes Interface -- see */ -extern void PoolClassMixInAllocFree(PoolClass class); -extern void PoolClassMixInBuffer(PoolClass class); -extern void PoolClassMixInScan(PoolClass class); -extern void PoolClassMixInFormat(PoolClass class); -extern void PoolClassMixInCollect(PoolClass class); -extern AbstractPoolClass AbstractPoolClassGet(void); -extern AbstractAllocFreePoolClass AbstractAllocFreePoolClassGet(void); -extern AbstractBufferPoolClass AbstractBufferPoolClassGet(void); -extern AbstractBufferPoolClass AbstractSegBufPoolClassGet(void); -extern AbstractScanPoolClass AbstractScanPoolClassGet(void); -extern AbstractCollectPoolClass AbstractCollectPoolClassGet(void); - -/* DEFINE_POOL_CLASS - * - * Convenience macro -- see . */ - -#define DEFINE_POOL_CLASS(className, var) \ - DEFINE_ALIAS_CLASS(className, PoolClass, var) - -#define POOL_SUPERCLASS(className) \ - ((PoolClass)SUPERCLASS(className)) - - -/* Message Interface -- see */ -/* -- Internal (MPM) Interface -- functions for message originator */ -extern Bool MessageCheck(Message message); -extern Bool MessageClassCheck(MessageClass class); -extern Bool MessageTypeCheck(MessageType type); -extern void MessageInit(Arena arena, Message message, - MessageClass class, MessageType type); -extern void MessageFinish(Message message); -extern Arena MessageArena(Message message); -extern Bool MessageOnQueue(Message message); -extern void MessagePost(Arena arena, Message message); -extern void MessageEmpty(Arena arena); -/* -- Delivery (Client) Interface -- functions for recipient */ -extern void MessageTypeEnable(Arena arena, MessageType type); -extern void MessageTypeDisable(Arena arena, MessageType type); -extern Bool MessagePoll(Arena arena); -extern Bool MessageQueueType(MessageType *typeReturn, Arena arena); -extern Bool MessageGet(Message *messageReturn, Arena arena, - MessageType type); -extern void MessageDiscard(Arena arena, Message message); -/* -- Message Methods, Generic */ -extern MessageType MessageGetType(Message message); -extern MessageClass MessageGetClass(Message message); -extern Clock MessageGetClock(Message message); -/* -- Message Method Dispatchers, Type-specific */ -extern void MessageFinalizationRef(Ref *refReturn, - Arena arena, Message message); -extern Size MessageGCLiveSize(Message message); -extern Size MessageGCCondemnedSize(Message message); -extern Size MessageGCNotCondemnedSize(Message message); -extern const char *MessageGCStartWhy(Message message); -/* -- Message Method Stubs, Type-specific */ -extern void MessageNoFinalizationRef(Ref *refReturn, - Arena arena, Message message); -extern Size MessageNoGCLiveSize(Message message); -extern Size MessageNoGCCondemnedSize(Message message); -extern Size MessageNoGCNotCondemnedSize(Message message); -extern const char *MessageNoGCStartWhy(Message message); - - -/* Trace Interface -- see */ - -#define TraceSetSingle(trace) BS_SINGLE(TraceSet, (trace)->ti) -#define TraceSetIsSingle(ts) BS_IS_SINGLE(ts) -#define TraceSetIsMember(ts, trace) BS_IS_MEMBER(ts, (trace)->ti) -#define TraceSetAdd(ts, trace) BS_ADD(TraceSet, ts, (trace)->ti) -#define TraceSetDel(ts, trace) BS_DEL(TraceSet, ts, (trace)->ti) -#define TraceSetUnion(ts1, ts2) BS_UNION(ts1, ts2) -#define TraceSetInter(ts1, ts2) BS_INTER(ts1, ts2) -#define TraceSetDiff(ts1, ts2) BS_DIFF(ts1, ts2) -#define TraceSetSuper(ts1, ts2) BS_SUPER(ts1, ts2) -#define TraceSetSub(ts1, ts2) BS_SUB(ts1, ts2) -#define TraceSetComp(ts) BS_COMP(ts) - -#define TRACE_SET_ITER(ti, trace, ts, arena) \ - for(ti = 0, trace = ArenaTrace(arena, ti); ti < TraceLIMIT; \ - ++ti, trace = ArenaTrace(arena, ti)) BEGIN \ - if (TraceSetIsMember(ts, trace)) { - -#define TRACE_SET_ITER_END(ti, trace, ts, arena) } END - - -extern void ScanStateInit(ScanState ss, TraceSet ts, Arena arena, - Rank rank, ZoneSet white); -extern void ScanStateFinish(ScanState ss); -extern Bool ScanStateCheck(ScanState ss); -extern void ScanStateSetSummary(ScanState ss, RefSet summary); -extern RefSet ScanStateSummary(ScanState ss); - -/* See impl.h.mpmst.ss */ -#define ScanStateZoneShift(ss) ((Shift)(ss)->ss_s._zs) -#define ScanStateWhite(ss) ((ZoneSet)(ss)->ss_s._w) -#define ScanStateUnfixedSummary(ss) ((RefSet)(ss)->ss_s._ufs) -#define ScanStateSetZoneShift(ss, shift) ((void)((ss)->ss_s._zs = (shift))) -#define ScanStateSetWhite(ss, zs) ((void)((ss)->ss_s._w = (zs))) -#define ScanStateSetUnfixedSummary(ss, rs) ((void)((ss)->ss_s._ufs = (rs))) - -extern Bool TraceIdCheck(TraceId id); -extern Bool TraceSetCheck(TraceSet ts); -extern Bool TraceCheck(Trace trace); -extern Res TraceCreate(Trace *traceReturn, Arena arena, int why); -extern void TraceDestroy(Trace trace); - -extern Res TraceAddWhite(Trace trace, Seg seg); -extern Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet); -extern Res TraceStart(Trace trace, double mortality, double finishingTime); -extern Size TracePoll(Globals globals); - -extern Rank TraceRankForAccess(Arena arena, Seg seg); -extern void TraceSegAccess(Arena arena, Seg seg, AccessSet mode); - -extern void TraceQuantum(Trace trace); -extern Res TraceStartCollectAll(Trace *traceReturn, Arena arena, int why); - -/* traceanc.c -- Trace Ancillary */ - -extern Bool TraceStartMessageCheck(TraceStartMessage message); -extern const char *TraceStartWhyToString(int why); -extern void TracePostStartMessage(Trace trace); -extern Bool TraceMessageCheck(TraceMessage message); /* trace end */ -extern void TracePostMessage(Trace trace); /* trace end */ -extern Bool TraceIdMessagesCheck(Arena arena, TraceId ti); -extern Res TraceIdMessagesCreate(Arena arena, TraceId ti); -extern void TraceIdMessagesDestroy(Arena arena, TraceId ti); - -/* Collection control parameters */ - -extern double TraceTopGenMortality; -extern double TraceWorkFactor; - - -/* Equivalent to MPS_SCAN_BEGIN */ - -#define TRACE_SCAN_BEGIN(ss) \ - BEGIN \ - /* Check range on zoneShift before casting to Shift. */ \ - AVER(ScanStateZoneShift(ss) < MPS_WORD_WIDTH); \ - { \ - Shift SCANzoneShift = ScanStateZoneShift(ss); \ - ZoneSet SCANwhite = ScanStateWhite(ss); \ - RefSet SCANsummary = ScanStateUnfixedSummary(ss); \ - Word SCANt; \ - mps_addr_t SCANref; \ - Res SCANres; \ - { - -/* Equivalent to MPS_FIX1 */ - -#define TRACE_FIX1(ss, ref) \ - (SCANt = (Word)1 << ((Word)(ref) >> SCANzoneShift & (MPS_WORD_WIDTH-1)), \ - SCANsummary |= SCANt, \ - (SCANwhite & SCANt) != 0) - -/* Equivalent to MPS_FIX2 */ - -/* TODO: The ref is copied to avoid breaking strict aliasing rules that could - well affect optimised scan loops. This code could be improved by - returning the fixed ref as a result and using longjmp to signal errors, - and that might well improve all scan loops too. The problem is whether - some embedded client platforms support longjmp. RB 2012-09-07 */ - -#define TRACE_FIX2(ss, refIO) \ - (SCANref = (mps_addr_t)*(refIO), \ - SCANres = _mps_fix2(&(ss)->ss_s, &SCANref), \ - *(refIO) = SCANref, \ - SCANres) - -/* Equivalent to MPS_FIX */ - -#define TRACE_FIX(ss, refIO) \ - (TRACE_FIX1(ss, *(refIO)) ? TRACE_FIX2(ss, refIO) : ResOK) - -/* Equivalent to MPS_SCAN_END */ - -#define TRACE_SCAN_END(ss) \ - } \ - ScanStateSetUnfixedSummary(ss, SCANsummary); \ - } \ - END - -extern Res TraceScanArea(ScanState ss, Addr *base, Addr *limit); -extern Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit); -extern Res TraceScanAreaMasked(ScanState ss, - Addr *base, Addr *limit, Word mask); -extern void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena, - Seg seg, Ref *refIO); - - -/* Arena Interface -- see */ - -/* DEFINE_ARENA_CLASS - * - * Convenience macro -- see . */ - -#define DEFINE_ARENA_CLASS(className, var) \ - DEFINE_ALIAS_CLASS(className, ArenaClass, var) - -#define ARENA_SUPERCLASS(className) \ - ((ArenaClass)SUPERCLASS(className)) - -extern AbstractArenaClass AbstractArenaClassGet(void); -extern Bool ArenaClassCheck(ArenaClass class); - -extern Bool ArenaCheck(Arena arena); -extern Res ArenaCreateV(Arena *arenaReturn, ArenaClass class, va_list args); -extern void ArenaDestroy(Arena arena); -extern Res ArenaInit(Arena arena, ArenaClass class); -extern void ArenaFinish(Arena arena); -extern Res ArenaDescribe(Arena arena, mps_lib_FILE *stream); -extern Res ArenaDescribeTracts(Arena arena, mps_lib_FILE *stream); -extern Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context); - -extern Bool GlobalsCheck(Globals arena); -extern Res GlobalsInit(Globals arena); -extern void GlobalsFinish(Globals arena); -extern Res GlobalsCompleteCreate(Globals arenaGlobals); -extern void GlobalsPrepareToDestroy(Globals arenaGlobals); -extern Res GlobalsDescribe(Globals arena, mps_lib_FILE *stream); -extern Ring GlobalsRememberedSummaryRing(Globals); - -#define ArenaGlobals(arena) (&(arena)->globals) -#define GlobalsArena(glob) PARENT(ArenaStruct, globals, glob) - -#define ArenaRootRing(arena) (&(arena)->rootRing) -#define ArenaTraceRing(arena) (&(arena)->traceRing) -#define ArenaThreadRing(arena) (&(arena)->threadRing) -#define ArenaEpoch(arena) ((arena)->epoch) /* .epoch.ts */ -#define ArenaTrace(arena, ti) (&(arena)->trace[ti]) -#define ArenaZoneShift(arena) ((arena)->zoneShift) -#define ArenaAlign(arena) ((arena)->alignment) -#define ArenaGreyRing(arena, rank) (&(arena)->greyRing[rank]) - - -extern void (ArenaEnter)(Arena arena); -extern void (ArenaLeave)(Arena arena); - -#if defined(THREAD_SINGLE) && defined(PROTECTION_NONE) -#define ArenaEnter(arena) UNUSED(arena) -#define ArenaLeave(arena) UNUSED(arena) -#endif - -extern void ArenaEnterRecursive(Arena arena); -extern void ArenaLeaveRecursive(Arena arena); - -extern void (ArenaPoll)(Globals globals); -#ifdef MPS_PROD_EPCORE -#define ArenaPoll(globals) UNUSED(globals) -#endif -/* .nogc.why: ScriptWorks doesn't use MM-provided incremental GC, so */ -/* doesn't need to poll when allocating. */ - -extern Bool (ArenaStep)(Globals globals, double interval, double multiplier); -extern void ArenaClamp(Globals globals); -extern void ArenaRelease(Globals globals); -extern void ArenaPark(Globals globals); -extern void ArenaExposeRemember(Globals globals, int remember); -extern void ArenaRestoreProtection(Globals globals); -extern Res ArenaStartCollect(Globals globals, int why); -extern Res ArenaCollect(Globals globals, int why); -extern Bool ArenaHasAddr(Arena arena, Addr addr); - -extern void ArenaSetEmergency(Arena arena, Bool emergency); -extern Bool ArenaEmergency(Arena arean); - -extern Res ControlInit(Arena arena); -extern void ControlFinish(Arena arena); -extern Res ControlAlloc(void **baseReturn, Arena arena, size_t size, - Bool withReservoirPermit); -extern void ControlFree(Arena arena, void *base, size_t size); -extern Res ControlDescribe(Arena arena, mps_lib_FILE *stream); - - -/* Peek/Poke - * - * These are provided so that modules in the MPS can make occasional - * access to client data. They perform the appropriate shield and - * summary manipulations that are necessary. - * - * Note that Peek and Poke can be called with address that may or - * may not be in arena managed memory. */ - -/* Peek reads a value */ -extern Ref ArenaPeek(Arena arena, Ref *p); -/* Same, but p must be in seg */ -extern Ref ArenaPeekSeg(Arena arena, Seg seg, Ref *p); -/* Poke stores a value */ -extern void ArenaPoke(Arena arena, Ref *p, Ref ref); -/* Same, but p must be in seg */ -extern void ArenaPokeSeg(Arena arena, Seg seg, Ref *p, Ref ref); - - -/* Read/Write - * - * These simulate mutator reads and writes to locations. - * They are effectively a software barrier, and maintain the tricolor - * invariant (hence performing any scanning or color manipulation - * necessary). - * - * Only Read provided right now. */ - -Ref ArenaRead(Arena arena, Ref *p); - - -extern Size ArenaReserved(Arena arena); -extern Size ArenaCommitted(Arena arena); -extern Size ArenaSpareCommitted(Arena arena); - -extern Size ArenaCommitLimit(Arena arena); -extern Res ArenaSetCommitLimit(Arena arena, Size limit); -extern Size ArenaSpareCommitLimit(Arena arena); -extern void ArenaSetSpareCommitLimit(Arena arena, Size limit); -extern void ArenaNoSpareCommitExceeded(Arena arena); - -extern double ArenaMutatorAllocSize(Arena arena); -extern Size ArenaAvail(Arena arena); - -extern Res ArenaExtend(Arena, Addr base, Size size); - -extern void ArenaCompact(Arena arena, Trace trace); - -extern Res ArenaFinalize(Arena arena, Ref obj); -extern Res ArenaDefinalize(Arena arena, Ref obj); - -extern Bool ArenaIsReservedAddr(Arena arena, Addr addr); - -#define ArenaReservoir(arena) (&(arena)->reservoirStruct) - -extern Bool ReservoirCheck(Reservoir reservoir); -extern Res ReservoirInit(Reservoir reservoir, Arena arena); -extern void ReservoirFinish (Reservoir reservoir); -extern Size ReservoirLimit(Reservoir reservoir); -extern void ReservoirSetLimit(Reservoir reservoir, Size size); -extern Size ReservoirAvailable(Reservoir reservoir); -extern Res ReservoirEnsureFull(Reservoir reservoir); -extern void ReservoirDeposit(Reservoir reservoir, Addr base, Size size); -extern Res ReservoirWithdraw(Addr *baseReturn, Tract *baseTractReturn, - Reservoir reservoir, Size size, Pool pool); - -extern Res ArenaAlloc(Addr *baseReturn, SegPref pref, - Size size, Pool pool, Bool withReservoirPermit); -extern void ArenaFree(Addr base, Size size, Pool pool); - -extern Res ArenaNoExtend(Arena arena, Addr base, Size size); - - -/* Locus interface */ - -extern Bool SegPrefCheck(SegPref pref); -extern SegPref SegPrefDefault(void); -extern void SegPrefExpress(SegPref pref, SegPrefKind kind, void *p); - -extern void LocusInit(Arena arena); -extern void LocusFinish(Arena arena); -extern Bool LocusCheck(Arena arena); - - -/* Segment interface */ - -extern Res SegAlloc(Seg *segReturn, SegClass class, SegPref pref, - Size size, Pool pool, Bool withReservoirPermit, ...); -extern void SegFree(Seg seg); -extern Bool SegOfAddr(Seg *segReturn, Arena arena, Addr addr); -extern Bool SegFirst(Seg *segReturn, Arena arena); -extern Bool SegNext(Seg *segReturn, Arena arena, Addr addr); -extern void SegSetWhite(Seg seg, TraceSet white); -extern void SegSetGrey(Seg seg, TraceSet grey); -extern void SegSetRankSet(Seg seg, RankSet rankSet); -extern void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary); -extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi, - Bool withReservoirPermit, ...); -extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at, - Bool withReservoirPermit, ...); -extern Res SegDescribe(Seg seg, mps_lib_FILE *stream); -extern void SegSetSummary(Seg seg, RefSet summary); -extern Buffer SegBuffer(Seg seg); -extern void SegSetBuffer(Seg seg, Buffer buffer); -extern Bool SegCheck(Seg seg); -extern Bool GCSegCheck(GCSeg gcseg); -extern Bool SegClassCheck(SegClass class); -extern SegClass SegClassGet(void); -extern SegClass GCSegClassGet(void); -extern void SegClassMixInNoSplitMerge(SegClass class); - - -/* DEFINE_SEG_CLASS -- define a segment class */ - -#define DEFINE_SEG_CLASS(className, var) \ - DEFINE_ALIAS_CLASS(className, SegClass, var) - - -#define SEG_SUPERCLASS(className) \ - ((SegClass)SUPERCLASS(className)) - -#define ClassOfSeg(seg) ((seg)->class) - -extern Size SegSize(Seg seg); -extern Addr (SegBase)(Seg seg); -extern Addr (SegLimit)(Seg seg); -#define SegBase(seg) (TractBase((seg)->firstTract)) -#define SegLimit(seg) ((seg)->limit) -#define SegPool(seg) (TractPool((seg)->firstTract)) -/* .bitfield.promote: The bit field accesses need to be cast to the */ -/* right type, otherwise they'll be promoted to signed int, see */ -/* standard.ansic.6.2.1.1. */ -#define SegRankSet(seg) ((RankSet)(seg)->rankSet) -#define SegPM(seg) ((AccessSet)(seg)->pm) -#define SegSM(seg) ((AccessSet)(seg)->sm) -#define SegDepth(seg) ((unsigned)(seg)->depth) -#define SegGrey(seg) ((TraceSet)(seg)->grey) -#define SegWhite(seg) ((TraceSet)(seg)->white) -#define SegNailed(seg) ((TraceSet)(seg)->nailed) -#define SegOfPoolRing(node) (RING_ELT(Seg, poolRing, (node))) -#define SegOfGreyRing(node) (&(RING_ELT(GCSeg, greyRing, (node)) \ - ->segStruct)) - -#define SegSummary(seg) (((GCSeg)(seg))->summary) - -#define SegSetPM(seg, mode) ((void)((seg)->pm = (mode))) -#define SegSetSM(seg, mode) ((void)((seg)->sm = (mode))) -#define SegSetDepth(seg, d) ((void)((seg)->depth = (d))) -#define SegSetNailed(seg, ts) ((void)((seg)->nailed = (ts))) - - -/* Buffer Interface -- see */ - -extern Res BufferCreate(Buffer *bufferReturn, BufferClass class, - Pool pool, Bool isMutator, ...); -extern Res BufferCreateV(Buffer *bufferReturn, BufferClass class, - Pool pool, Bool isMutator, va_list args); -extern void BufferDestroy(Buffer buffer); -extern Bool BufferCheck(Buffer buffer); -extern Bool SegBufCheck(SegBuf segbuf); -extern Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream); -extern Res BufferReserve(Addr *pReturn, Buffer buffer, Size size, - Bool withReservoirPermit); -/* macro equivalent for BufferReserve, keep in sync with */ -/* TODO: Perhaps this isn't really necessary now that we build the MPS with - more global optimisation and inlining. RB 2012-09-07 */ -#define BUFFER_RESERVE(pReturn, buffer, size, withReservoirPermit) \ - (AddrAdd(BufferAlloc(buffer), size) > BufferAlloc(buffer) && \ - AddrAdd(BufferAlloc(buffer), size) <= (Addr)BufferAP(buffer)->limit ? \ - (*(pReturn) = BufferAlloc(buffer), \ - BufferAP(buffer)->alloc = AddrAdd(BufferAlloc(buffer), size), \ - ResOK) : \ - BufferFill(pReturn, buffer, size, withReservoirPermit)) - -extern Res BufferFill(Addr *pReturn, Buffer buffer, Size size, - Bool withReservoirPermit); - -extern Bool BufferCommit(Buffer buffer, Addr p, Size size); -/* macro equivalent for BufferCommit, keep in sync with */ -/* TODO: Perhaps this isn't really necessary now that we build the MPS with - more global optimisation and inlining. RB 2012-09-07 */ -#define BUFFER_COMMIT(buffer, p, size) \ - (BufferAP(buffer)->init = BufferAlloc(buffer), \ - BufferAP(buffer)->limit != 0 || BufferTrip(buffer, p, size)) - -extern Bool BufferTrip(Buffer buffer, Addr p, Size size); -extern void BufferFinish(Buffer buffer); -extern Bool BufferIsReset(Buffer buffer); -extern Bool BufferIsReady(Buffer buffer); -extern Bool BufferIsMutator(Buffer buffer); -extern void BufferSetAllocAddr(Buffer buffer, Addr addr); -extern void BufferAttach(Buffer buffer, - Addr base, Addr limit, Addr init, Size size); -extern void BufferDetach(Buffer buffer, Pool pool); -extern void BufferFlip(Buffer buffer); - -extern mps_ap_t (BufferAP)(Buffer buffer); -#define BufferAP(buffer) (&(buffer)->ap_s) -extern Buffer BufferOfAP(mps_ap_t ap); -#define BufferOfAP(ap) PARENT(BufferStruct, ap_s, ap) - -#define BufferArena(buffer) ((buffer)->arena) -#define BufferPool(buffer) ((buffer)->pool) - -extern Seg BufferSeg(Buffer buffer); - -extern RankSet BufferRankSet(Buffer buffer); -extern void BufferSetRankSet(Buffer buffer, RankSet rankset); - -#define BufferBase(buffer) ((buffer)->base) -#define BufferGetInit(buffer) /* see .trans.bufferinit */ \ - ((Addr)(BufferAP(buffer)->init)) -#define BufferAlloc(buffer) ((Addr)(BufferAP(buffer)->alloc)) -#define BufferLimit(buffer) ((buffer)->poolLimit) -extern Addr BufferScanLimit(Buffer buffer); - -extern void BufferReassignSeg(Buffer buffer, Seg seg); - -extern Bool BufferIsTrapped(Buffer buffer); -extern Bool BufferIsTrappedByMutator(Buffer buffer); - -extern void BufferRampBegin(Buffer buffer, AllocPattern pattern); -extern Res BufferRampEnd(Buffer buffer); -extern void BufferRampReset(Buffer buffer); - -extern Res BufferFramePush(AllocFrame *frameReturn, Buffer buffer); -extern Res BufferFramePop(Buffer buffer, AllocFrame frame); -extern FrameState BufferFrameState(Buffer buffer); -extern void BufferFrameSetState(Buffer buffer, FrameState state); - - -/* DEFINE_BUFFER_CLASS -- define a buffer class */ - -#define DEFINE_BUFFER_CLASS(className, var) \ - DEFINE_ALIAS_CLASS(className, BufferClass, var) - -#define BUFFER_SUPERCLASS(className) \ - ((BufferClass)SUPERCLASS(className)) - -extern Bool BufferClassCheck(BufferClass class); -extern BufferClass BufferClassGet(void); -extern BufferClass SegBufClassGet(void); -extern BufferClass RankBufClassGet(void); - -extern AllocPattern AllocPatternRamp(void); -extern AllocPattern AllocPatternRampCollectAll(void); - - -/* Format Interface -- see */ - -extern Bool FormatCheck(Format format); -extern Res FormatCreate(Format *formatReturn, Arena arena, - Align alignment, - FormatVariety variety, - mps_fmt_scan_t scan, - mps_fmt_skip_t skip, - mps_fmt_fwd_t move, - mps_fmt_isfwd_t isMoved, - mps_fmt_copy_t copy, - mps_fmt_pad_t pad, - mps_fmt_class_t class, - Size headerSize); -extern void FormatDestroy(Format format); -extern Arena FormatArena(Format format); -extern Res FormatDescribe(Format format, mps_lib_FILE *stream); - - -/* Reference Interface -- see */ - -extern Bool RankCheck(Rank rank); -extern Bool RankSetCheck(RankSet rankSet); - -#define RankSetIsMember(rs, r) BS_IS_MEMBER((rs), (r)) -#define RankSetSingle(r) BS_SINGLE(RankSet, (r)) -#define RankSetIsSingle(r) BS_IS_SINGLE(r) -#define RankSetUnion(rs1, rs2) BS_UNION((rs1), (rs2)) -#define RankSetDel(rs, r) BS_DEL(RankSet, (rs), (r)) - -#define AddrZone(arena, addr) \ - (((Word)(addr) >> (arena)->zoneShift) & (MPS_WORD_WIDTH - 1)) - -#define RefSetUnion(rs1, rs2) BS_UNION((rs1), (rs2)) -#define RefSetInter(rs1, rs2) BS_INTER((rs1), (rs2)) -#define RefSetDiff(rs1, rs2) BS_DIFF((rs1), (rs2)) -#define RefSetAdd(arena, rs, addr) \ - BS_ADD(RefSet, rs, AddrZone(arena, addr)) -#define RefSetIsMember(arena, rs, addr) \ - BS_IS_MEMBER(rs, AddrZone(arena, addr)) -#define RefSetSuper(rs1, rs2) BS_SUPER((rs1), (rs2)) -#define RefSetSub(rs1, rs2) BS_SUB((rs1), (rs2)) - - -/* Zone sets -- see design.mps.refset */ - -#define ZoneSetUnion(zs1, zs2) BS_UNION(zs1, zs2) -#define ZoneSetInter(zs1, zs2) BS_INTER(zs1, zs2) -#define ZoneSetDiff(zs1, zs2) BS_DIFF(zs1, zs2) -#define ZoneSetAdd(arena, zs, addr) \ - BS_ADD(ZoneSet, zs, AddrZone(arena, addr)) -#define ZoneSetIsMember(arena, zs, addr) \ - BS_IS_MEMBER(zs, AddrZone(arena, addr)) -#define ZoneSetSub(zs1, zs2) BS_SUB(zs1, zs2) -#define ZoneSetSuper(zs1, zs2) BS_SUPER(zs1, zs2) -#define ZoneSetComp(zs) BS_COMP(zs) - -extern ZoneSet ZoneSetOfRange(Arena arena, Addr base, Addr limit); -extern ZoneSet ZoneSetOfSeg(Arena arena, Seg seg); - - -/* Shield Interface -- see */ - -extern void (ShieldRaise)(Arena arena, Seg seg, AccessSet mode); -extern void (ShieldLower)(Arena arena, Seg seg, AccessSet mode); -extern void (ShieldEnter)(Arena arena); -extern void (ShieldLeave)(Arena arena); -extern void (ShieldExpose)(Arena arena, Seg seg); -extern void (ShieldCover)(Arena arena, Seg seg); -extern void (ShieldSuspend)(Arena arena); -extern void (ShieldResume)(Arena arena); -extern void (ShieldFlush)(Arena arena); - -#if defined(THREAD_SINGLE) && defined(PROTECTION_NONE) -#define ShieldRaise(arena, seg, mode) \ - BEGIN UNUSED(arena); UNUSED(seg); UNUSED(mode); END -#define ShieldLower(arena, seg, mode) \ - BEGIN UNUSED(arena); UNUSED(seg); UNUSED(mode); END -#define ShieldEnter(arena) BEGIN UNUSED(arena); END -#define ShieldLeave(arena) BEGIN UNUSED(arena); END -#define ShieldExpose(arena, seg) \ - BEGIN UNUSED(arena); UNUSED(seg); END -#define ShieldCover(arena, seg) \ - BEGIN UNUSED(arena); UNUSED(seg); END -#define ShieldSuspend(arena) BEGIN UNUSED(arena); END -#define ShieldResume(arena) BEGIN UNUSED(arena); END -#define ShieldFlush(arena) BEGIN UNUSED(arena); END -#endif - - -/* Protection Interface - * - * See for the design of the generic interface including - * the contracts for these functions. - * - * This interface has several different implementations, typically one - * per platform, see * for the various implementations, and - * * for the corresponding designs. */ - -extern void ProtSetup(void); - -extern void ProtSet(Addr base, Addr limit, AccessSet mode); -extern void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), - void *p, size_t s); -extern void ProtSync(Arena arena); -extern Bool ProtCanStepInstruction(MutatorFaultContext context); -extern Res ProtStepInstruction(MutatorFaultContext context); - - -/* Mutator Fault Context */ - -extern Addr MutatorFaultContextSP(MutatorFaultContext mfc); -extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc); - - -/* Location Dependency -- see */ - -extern void LDReset(mps_ld_t ld, Arena arena); -extern void LDAdd(mps_ld_t ld, Arena arena, Addr addr); -extern Bool LDIsStale(mps_ld_t ld, Arena arena, Addr addr); -extern void LDAge(Arena arena, RefSet moved); -extern void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from); - - -/* Root Interface -- see */ - -extern Res RootCreateTable(Root *rootReturn, Arena arena, - Rank rank, RootMode mode, - Addr *base, Addr *limit); -extern Res RootCreateTableMasked(Root *rootReturn, Arena arena, - Rank rank, RootMode mode, - Addr *base, Addr *limit, - Word mask); -extern Res RootCreateReg(Root *rootReturn, Arena arena, - Rank rank, Thread thread, - mps_reg_scan_t scan, - void *p, size_t s); -extern Res RootCreateFmt(Root *rootReturn, Arena arena, - Rank rank, RootMode mode, - mps_fmt_scan_t scan, - Addr base, Addr limit); -extern Res RootCreateFun(Root *rootReturn, Arena arena, - Rank rank, mps_root_scan_t scan, - void *p, size_t s); -extern void RootDestroy(Root root); -extern Bool RootModeCheck(RootMode mode); -extern Bool RootCheck(Root root); -extern Res RootDescribe(Root root, mps_lib_FILE *stream); -extern Res RootsDescribe(Globals arenaGlobals, mps_lib_FILE *stream); -extern Rank RootRank(Root root); -extern AccessSet RootPM(Root root); -extern RefSet RootSummary(Root root); -extern void RootGrey(Root root, Trace trace); -extern Res RootScan(ScanState ss, Root root); -extern Arena RootArena(Root root); -extern Bool RootOfAddr(Root *root, Arena arena, Addr addr); -extern void RootAccess(Root root, AccessSet mode); -typedef Res (*RootIterateFn)(Root root, void *p); -extern Res RootsIterate(Globals arena, RootIterateFn f, void *p); - - -/* VM Interface -- see * */ - -extern Align VMAlign(VM vm); -extern Bool VMCheck(VM vm); -extern Res VMCreate(VM *VMReturn, Size size); -extern void VMDestroy(VM vm); -extern Addr VMBase(VM vm); -extern Addr VMLimit(VM vm); -extern Res VMMap(VM vm, Addr base, Addr limit); -extern void VMUnmap(VM vm, Addr base, Addr limit); -extern Size VMReserved(VM vm); -extern Size VMMapped(VM vm); - - -/* Stack Probe */ - -extern void StackProbe(Size depth); - - -/* STATISTIC -- gather statistics (in some varieties) - * - * The argument of STATISTIC is an expression; the expansion followed by - * a semicolon is syntactically a statement. - * - * The argument of STATISTIC_STAT is a statement; the expansion followed by - * a semicolon is syntactically a statement. - * - * STATISTIC_WRITE is inserted in WriteF arguments to output the values - * of statistic fields. - * - * .statistic.whitehot: The implementation of STATISTIC for - * non-statistical varieties passes the parameter to DISCARD to ensure - * the parameter is syntactically an expression. The parameter is - * passed as part of a comma-expression so that its type is not - * important. This permits an expression of type void. */ - -#if defined(STATISTICS) - -#define STATISTIC(gather) BEGIN (gather); END -#define STATISTIC_STAT(gather) BEGIN gather; END -#define STATISTIC_WRITE(format, arg) (format), (arg), - -#elif defined(STATISTICS_NONE) - -#define STATISTIC(gather) DISCARD(((gather), 0)) -#define STATISTIC_STAT DISCARD_STAT -#define STATISTIC_WRITE(format, arg) - -#else - -#error "No statistics configured." - -#endif - - -/* ------------ DIAG_WITH_STREAM_AND_WRITEF --------------- */ - -Bool DiagIsOn(void); -mps_lib_FILE *DiagStream(void); - - -/* Diag*F functions -- formatted diagnostic output - * - * Note: do not call these directly; use the DIAG_*F macros below. - */ - -extern void DiagSingleF(const char *tag, ...); -extern void DiagFirstF(const char *tag, ...); -extern void DiagMoreF(const char *format, ...); -extern void DiagEnd(const char *tag); - - -#if defined(DIAG_WITH_STREAM_AND_WRITEF) - -/* Diagnostic Calculation and Output */ -#define DIAG_DECL(decl) decl -#define DIAG_STREAM (DiagStream()) -#define DIAG(s) BEGIN \ - s \ - END - - -/* DIAG_*F macros -- formatted diagnostic output - * - * Note: when invoking these macros, the value passed as macro - * argument "args" might contain commas; it must therefore be - * enclosed in parentheses. That makes these macros unclean in - * all sorts of ways. - */ - -#define DIAG_WRITEF(args) DIAG( \ - if(DiagIsOn()) { \ - WriteF args; \ - } \ -) -#define DIAG_SINGLEF(args) DIAG( \ - DiagSingleF args; \ -) -#define DIAG_FIRSTF(args) DIAG( \ - DiagFirstF args; \ -) -#define DIAG_MOREF(args) DIAG( \ - DiagMoreF args; \ -) - -/* Note: extra parens *not* required when invoking DIAG_END */ -#define DIAG_END(tag) DIAG( \ - DiagEnd(tag); \ -) - - -#else - -/* Diagnostic Calculation and Output */ -#define DIAG_DECL(decl) -#define DIAG(s) BEGIN END -#define DIAG_WRITEF(args) BEGIN END - -/* DIAG_*F macros */ -#define DIAG_SINGLEF(args) BEGIN END -#define DIAG_FIRSTF(args) BEGIN END -#define DIAG_MOREF(args) BEGIN END -#define DIAG_END(tag) BEGIN END - -#endif - -/* ------------ DIAG_WITH_PRINTF --------------- */ - -#if defined(DIAG_WITH_PRINTF) - -#include - -#define DIAG_PRINTF(args) BEGIN\ - printf args ; \ - END - -#else - -#define DIAG_PRINTF(args) BEGIN\ - END - -#endif - - -#endif /* mpm_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpmss.c b/mps/code/mpmss.c deleted file mode 100644 index 5c98b1da9ac..00000000000 --- a/mps/code/mpmss.c +++ /dev/null @@ -1,245 +0,0 @@ -/* mpmss.c: MPM STRESS TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - */ - -#include "mpscmv.h" -#include "mpscmvff.h" -#include "mpslib.h" -#include "mpsavm.h" -#include "testlib.h" -#include "mps.h" -#include -#include - - -/* @@@@ Hack due to missing mpscmfs.h */ -extern mps_class_t PoolClassMFS(void); - - -#define testArenaSIZE ((((size_t)64)<<20) - 4) -#define smallArenaSIZE ((((size_t)1)<<20) - 4) -#define testSetSIZE 200 -#define testLOOPS 10 - - -/* stress -- create a pool of the requested type and allocate in it */ - -static mps_res_t stress(mps_class_t class, size_t (*size)(int i), - mps_arena_t arena, ...) -{ - mps_res_t res; - mps_pool_t pool; - va_list arg; - int i, k; - int *ps[testSetSIZE]; - size_t ss[testSetSIZE]; - - va_start(arg, arena); - res = mps_pool_create_v(&pool, arena, class, arg); - va_end(arg); - if (res != MPS_RES_OK) - return res; - - /* allocate a load of objects */ - for (i=0; i= sizeof(ps[i])) - *ps[i] = 1; /* Write something, so it gets swap. */ - } - - mps_pool_check_fenceposts(pool); - - for (k=0; k (b)) ? (a) : (b)) - -#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - - -/* randomSize -- produce sizes both latge and small */ - -static size_t randomSize(int i) -{ - /* Make the range large enough to span three pages in the segment table: */ - /* 160 segments/page, page size max 0x2000. */ - size_t maxSize = 2 * 160 * 0x2000; - /* Reduce by a factor of 2 every 10 cycles. Total allocation about 40 MB. */ - return rnd() % max((maxSize >> (i / 10)), 2) + 1; -} - - -/* randomSize8 -- produce sizes both latge and small, 8-byte aligned */ - -static size_t randomSize8(int i) -{ - size_t maxSize = 2 * 160 * 0x2000; - /* Reduce by a factor of 2 every 10 cycles. Total allocation about 40 MB. */ - return alignUp(rnd() % max((maxSize >> (i / 10)), 2) + 1, 8); -} - - -/* fixedSize -- produce always the same size */ - -static size_t fixedSizeSize = 0; - -static size_t fixedSize(int i) -{ - testlib_unused(i); - return fixedSizeSize; -} - - -static mps_pool_debug_option_s bothOptions8 = { - /* .fence_template = */ (void *)"postpost", - /* .fence_size = */ 8, - /* .free_template = */ (void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_pool_debug_option_s bothOptions16 = { - /* .fence_template = */ (void *)"postpostpostpost", - /* .fence_size = */ 16, - /* .free_template = */ (void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_pool_debug_option_s fenceOptions = { - /* .fence_template = */ (void *)"\0XXX ''\"\"'' XXX\0", - /* .fence_size = */ 16, - /* .free_template = */ NULL, - /* .free_size = */ 0 -}; - -/* testInArena -- test all the pool classes in the given arena */ - -static int testInArena(mps_arena_t arena, mps_pool_debug_option_s *options) -{ - /* IWBN to test MVFFDebug, but the MPS doesn't support debugging */ - /* cross-segment allocation (possibly MVFF ought not to). */ - printf("MVFF\n"); - die(stress(mps_class_mvff(), randomSize8, arena, - (size_t)65536, (size_t)32, sizeof(void *), TRUE, TRUE, TRUE), - "stress MVFF"); - printf("MV debug\n"); - die(stress(mps_class_mv_debug(), randomSize, arena, - options, (size_t)65536, (size_t)32, (size_t)65536), - "stress MV debug"); - - printf("MFS\n"); - fixedSizeSize = 13; - die(stress(PoolClassMFS(), - fixedSize, arena, (size_t)100000, fixedSizeSize), - "stress MFS"); - - printf("MV\n"); - die(stress(mps_class_mv(), randomSize, arena, - (size_t)65536, (size_t)32, (size_t)65536), - "stress MV"); - - return 0; -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_pool_debug_option_s *bothOptions; - - bothOptions = MPS_PF_ALIGN == 8 ? &bothOptions8 : &bothOptions16; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "mps_arena_create"); - testInArena(arena, bothOptions); - mps_arena_destroy(arena); - - die(mps_arena_create(&arena, mps_arena_class_vm(), smallArenaSIZE), - "mps_arena_create"); - testInArena(arena, &fenceOptions); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h deleted file mode 100644 index 332d32084e1..00000000000 --- a/mps/code/mpmst.h +++ /dev/null @@ -1,746 +0,0 @@ -/* mpmst.h: MEMORY POOL MANAGER DATA STRUCTURES - * - * $Id$ - * Copyright (c) 2001-2003, 2006 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2001 Global Graphics Software. - * - * .design: This header file crosses module boundaries. The relevant - * design a module's structures should be found in that module's design - * document. - * - * .structure: Most structures have already been declared as incomplete - * types in . Most of the structures are the underlying - * aggregate types for an abstract data type. See - * guide.impl.c.naming.type.adt-aggregate.relate. - * - * .rationale.sig: Object signatures (PoolSig, etc.) are defined here, - * along with the structures, so that any code which can see a structure - * can also check its signature before using any of its fields. See - * to check that signatures are unique. */ - -#ifndef mpmst_h -#define mpmst_h - -#include "config.h" -#include "mpmtypes.h" - -#include "protocol.h" -#include "ring.h" -#include "chain.h" - - -/* PoolClassStruct -- pool class structure - * - * See . - * - * .class: The pool class structure is defined by each pool class - * implementation in order to provide an interface between the MPM - * and the class (see ) via generic - * functions (see ). A class XXX defines a function - * PoolClassXXX() returning a PoolClass pointing to a PoolClassStruct - * of methods which implement the memory management policy. - * - * .class.end-sig: The class structure has a signature at the end. This - * causes the compiler to complain if the class structure is extended - * without modifying static initializers. */ - -#define PoolClassSig ((Sig)0x519C7A55) /* SIGnature pool CLASS */ - -typedef struct mps_class_s { - ProtocolClassStruct protocol; - const char *name; /* class name string */ - size_t size; /* size of outer structure */ - size_t offset; /* offset of generic struct in outer struct */ - Attr attr; /* attributes */ - PoolInitMethod init; /* initialize the pool descriptor */ - PoolFinishMethod finish; /* finish the pool descriptor */ - PoolAllocMethod alloc; /* allocate memory from pool */ - PoolFreeMethod free; /* free memory to pool */ - PoolBufferFillMethod bufferFill; /* out-of-line reserve */ - PoolBufferEmptyMethod bufferEmpty; /* out-of-line commit */ - PoolAccessMethod access; /* handles read/write accesses */ - PoolWhitenMethod whiten; /* whiten objects in a segment */ - PoolGreyMethod grey; /* grey non-white objects */ - PoolBlackenMethod blacken; /* blacken grey objects without scanning */ - PoolScanMethod scan; /* find references during tracing */ - PoolFixMethod fix; /* referent reachable during tracing */ - PoolFixEmergencyMethod fixEmergency; /* as fix, no failure allowed */ - PoolReclaimMethod reclaim; /* reclaim dead objects after tracing */ - PoolTraceEndMethod traceEnd; /* do something after all reclaims */ - PoolRampBeginMethod rampBegin;/* begin a ramp pattern */ - PoolRampEndMethod rampEnd; /* end a ramp pattern */ - PoolFramePushMethod framePush; /* push an allocation frame */ - PoolFramePopMethod framePop; /* pop an allocation frame */ - PoolFramePopPendingMethod framePopPending; /* notify pending pop */ - PoolWalkMethod walk; /* walk over a segment */ - PoolFreeWalkMethod freewalk; /* walk over free blocks */ - PoolBufferClassMethod bufferClass; /* default BufferClass of pool */ - PoolDescribeMethod describe; /* describe the contents of the pool */ - PoolDebugMixinMethod debugMixin; /* find the debug mixin, if any */ - Bool labelled; /* whether it has been EventLabelled */ - Sig sig; /* .class.end-sig */ -} PoolClassStruct; - - -/* PoolStruct -- generic structure - * - * .pool: A generic structure is created when a pool is created and - * holds the generic part of the pool's state. Each pool class defines - * a "subclass" of the pool structure (the "outer structure") which - * contains PoolStruct as a a field. The outer structure holds the - * class-specific part of the pool's state. See , - * . */ - -#define PoolSig ((Sig)0x519B0019) /* SIGnature POOL */ - -typedef struct mps_pool_s { /* generic structure */ - Sig sig; /* */ - Serial serial; /* from arena->poolSerial */ - PoolClass class; /* pool class structure */ - Arena arena; /* owning arena */ - RingStruct arenaRing; /* link in list of pools in arena */ - RingStruct bufferRing; /* allocation buffers are attached to pool */ - Serial bufferSerial; /* serial of next buffer */ - RingStruct segRing; /* segs are attached to pool */ - Align alignment; /* alignment for units */ - Format format; /* format only if class->attr&AttrFMT */ - PoolFixMethod fix; /* fix method */ - double fillMutatorSize; /* bytes filled, mutator buffers */ - double emptyMutatorSize; /* bytes emptied, mutator buffers */ - double fillInternalSize; /* bytes filled, internal buffers */ - double emptyInternalSize; /* bytes emptied, internal buffers */ -} PoolStruct; - - -/* MFSStruct -- MFS (Manual Fixed Small) pool outer structure - * - * .mfs: See , . - * - * The MFS outer structure is declared here because it is inlined - * in the control pool structure which is inlined in the arena. Normally, - * pool outer structures are declared with the pools. - * - * The signature is placed at the end, see - * . */ - -#define MFSSig ((Sig)0x5193F599) /* SIGnature MFS */ - -typedef struct MFSStruct { /* MFS outer structure */ - PoolStruct poolStruct; /* generic structure */ - Size unroundedUnitSize; /* the unit size requested */ - Size extendBy; /* arena alloc size rounded using unitSize */ - Size unitSize; /* rounded for management purposes */ - Word unitsPerExtent; /* number of units per arena alloc */ - struct MFSHeaderStruct *freeList; /* head of the free list */ - Tract tractList; /* the first tract */ - Sig sig; /* */ -} MFSStruct; - - -/* MVStruct -- MV (Manual Variable) pool outer structure - * - * .mv: See , . - * - * The MV pool outer structure is declared here because it is the - * control pool structure which is inlined in the arena. Normally, - * pool outer structures are declared with the pools. */ - -#define MVSig ((Sig)0x5193B999) /* SIGnature MV */ - -typedef struct MVStruct { /* MV pool outer structure */ - PoolStruct poolStruct; /* generic structure */ - MFSStruct blockPoolStruct; /* for managing block descriptors */ - MFSStruct spanPoolStruct; /* for managing span descriptors */ - Size extendBy; /* segment size to extend pool by */ - Size avgSize; /* client estimate of allocation size */ - Size maxSize; /* client estimate of maximum size */ - Size space; /* total free space in pool */ - Size lost; /* */ - RingStruct spans; /* span chain */ - Sig sig; /* */ -} MVStruct; - - -/* ReservoirStruct -- Reservoir structure - * - * .reservoir: See , . - * - * The Reservoir structure is declared here because it is in-lined in - * the arena for storing segments for the low-memory reservoir. It is - * implemented as a pool - but doesn't follow the normal pool naming - * conventions because it's not intended for general use and the use of - * a pool is an incidental detail. */ - -#define ReservoirSig ((Sig)0x5196e599) /* SIGnature REServoir */ - -typedef struct ReservoirStruct { /* Reservoir structure */ - PoolStruct poolStruct; /* generic pool structure */ - Tract reserve; /* linked list of reserve tracts */ - Size reservoirLimit; /* desired reservoir size */ - Size reservoirSize; /* actual reservoir size */ - Sig sig; /* */ -} ReservoirStruct; - - -/* MessageClassStruct -- Message Class structure - * - * See (and , - * and ). */ - -#define MessageClassSig ((Sig)0x519359c1) /* SIGnature MeSsaGe CLass */ - -typedef struct MessageClassStruct { - Sig sig; /* */ - const char *name; /* Human readable Class name */ - - MessageType type; /* Message Type */ - - /* generic methods */ - MessageDeleteMethod delete; /* terminates a message */ - - /* methods specific to MessageTypeFinalization */ - MessageFinalizationRefMethod finalizationRef; - - /* methods specific to MessageTypeGC */ - MessageGCLiveSizeMethod gcLiveSize; - MessageGCCondemnedSizeMethod gcCondemnedSize; - MessageGCNotCondemnedSizeMethod gcNotCondemnedSize; - - /* methods specific to MessageTypeGCStart */ - MessageGCStartWhyMethod gcStartWhy; - - Sig endSig; /* */ -} MessageClassStruct; - -#define MessageSig ((Sig)0x5193e559) /* SIG MESSaGe */ - -/* MessageStruct -- Message structure - * - * See . */ - -typedef struct mps_message_s { - Sig sig; /* */ - Arena arena; /* owning arena */ - MessageClass class; /* Message Class Structure */ - Clock postedClock; /* mps_clock() at post time, or 0 */ - RingStruct queueRing; /* Message queue ring */ -} MessageStruct; - - -/* SegClassStruct -- segment class structure - * - * See & . - * - * .seg.class: The segment class structure is defined by each segment - * class implementation in order to provide a generic interface to - * segments. */ - -#define SegClassSig ((Sig)0x5195E9C7) /* SIGnature SEG CLass */ - -typedef struct SegClassStruct { - ProtocolClassStruct protocol; - const char *name; /* class name string */ - size_t size; /* size of outer structure */ - SegInitMethod init; /* initialize the segment */ - SegFinishMethod finish; /* finish the segment */ - SegSetSummaryMethod setSummary; /* set the segment summary */ - SegBufferMethod buffer; /* get the segment buffer */ - SegSetBufferMethod setBuffer; /* set the segment buffer */ - SegSetGreyMethod setGrey; /* change greyness of segment */ - SegSetWhiteMethod setWhite; /* change whiteness of segment */ - SegSetRankSetMethod setRankSet; /* change rank set of segment */ - SegSetRankSummaryMethod setRankSummary; /* change rank set & summary */ - SegDescribeMethod describe; /* describe the contents of the seg */ - SegMergeMethod merge; /* merge two adjacent segments */ - SegSplitMethod split; /* split a segment into two */ - Sig sig; /* .class.end-sig */ -} SegClassStruct; - - -/* SegStruct -- segment structure - * - * .seg: Segments are the basic units of protection and tracer activity - * for allocated memory. See . */ - -#define SegSig ((Sig)0x5195E999) /* SIGnature SEG */ - -typedef struct SegStruct { /* segment structure */ - Sig sig; /* */ - SegClass class; /* segment class structure */ - Tract firstTract; /* first tract of segment */ - RingStruct poolRing; /* link in list of segs in pool */ - Addr limit; /* limit of segment */ - unsigned depth : ShieldDepthWIDTH; /* see */ - AccessSet pm : AccessSetWIDTH; /* protection mode, */ - AccessSet sm : AccessSetWIDTH; /* shield mode, */ - TraceSet grey : TraceLIMIT; /* traces for which seg is grey */ - TraceSet white : TraceLIMIT; /* traces for which seg is white */ - TraceSet nailed : TraceLIMIT; /* traces for which seg has nailed objects */ - RankSet rankSet : RankLIMIT; /* ranks of references in this seg */ -} SegStruct; - - -/* GCSegStruct -- GCable segment structure - * - * .seggc: GCSeg is a subclass of Seg with support for buffered - * allocation and GC. See . */ - -#define GCSegSig ((Sig)0x5199C5E9) /* SIGnature GC SEG */ - -typedef struct GCSegStruct { /* GC segment structure */ - SegStruct segStruct; /* superclass fields must come first */ - RingStruct greyRing; /* link in list of grey segs */ - RefSet summary; /* summary of references out of seg */ - Buffer buffer; /* non-NULL if seg is buffered */ - Sig sig; /* */ -} GCSegStruct; - - -/* SegPrefStruct -- segment preference structure - * - * .seg-pref: arena memory users (pool class code) need a way of - * expressing preferences about the segments they allocate. - * - * .seg-pref.misleading: The name is historical and misleading. SegPref - * objects need have nothing to do with segments. @@@@ */ - -#define SegPrefSig ((Sig)0x5195E9B6) /* SIGnature SEG PRef */ - -typedef struct SegPrefStruct { /* segment placement preferences */ - Sig sig; /* */ - Bool high; /* high or low */ - ZoneSet zones; /* preferred zones */ - Bool isCollected; /* whether segment will be collected */ - Bool isGen; /* whether gen is set */ - Serial gen; /* associated geneation */ -} SegPrefStruct; - - -/* BufferClassStruct -- buffer class structure - * - * See & . - * - * .buffer.class: The buffer class structure is defined by each buffer - * class implementation in order to provide a generic interface to - * buffers. */ - -#define BufferClassSig ((Sig)0x519B0FC7) /* SIGnature BUFfer CLass */ - -typedef struct BufferClassStruct { - ProtocolClassStruct protocol; - const char *name; /* class name string */ - size_t size; /* size of outer structure */ - BufferInitMethod init; /* initialize the buffer */ - BufferFinishMethod finish; /* finish the buffer */ - BufferAttachMethod attach; /* attach the buffer */ - BufferDetachMethod detach; /* detach the buffer */ - BufferDescribeMethod describe;/* describe the contents of the buffer */ - BufferSegMethod seg; /* seg of buffer */ - BufferRankSetMethod rankSet; /* rank set of buffer */ - BufferSetRankSetMethod setRankSet; /* change rank set of buffer */ - BufferReassignSegMethod reassignSeg; /* change seg of attached buffer */ - Sig sig; /* .class.end-sig */ -} BufferClassStruct; - - -/* BufferStruct -- allocation buffer structure - * - * See , . - * - * The buffer contains an AP which may be exported to the client. - * AP are part of the design of buffers see . - * The allocation point is exported to the client code so that it can - * do in-line buffered allocation. - */ - -#define BufferSig ((Sig)0x519B0FFE) /* SIGnature BUFFEr */ - -typedef struct BufferStruct { - Sig sig; /* */ - BufferClass class; /* buffer class structure */ - Serial serial; /* from pool->bufferSerial */ - Arena arena; /* owning arena */ - Pool pool; /* owning pool */ - RingStruct poolRing; /* buffers are attached to pools */ - Bool isMutator; /* TRUE iff buffer used by mutator */ - BufferMode mode; /* Attached/Logged/Flipped/etc */ - double fillSize; /* bytes filled in this buffer */ - double emptySize; /* bytes emptied from this buffer */ - Addr base; /* base address of allocation buffer */ - Addr initAtFlip; /* limit of initialized data at flip */ - mps_ap_s ap_s; /* the allocation point */ - Addr poolLimit; /* the pool's idea of the limit */ - Align alignment; /* allocation alignment */ - unsigned rampCount; /* see */ -} BufferStruct; - - -/* SegBufStruct -- Buffer structure associated with segments - * - * .segbuf: SegBuf is a subclass of Buffer with support for attachment - * to segments. */ - -#define SegBufSig ((Sig)0x51959B0F) /* SIGnature SeG BUFfer */ - -typedef struct SegBufStruct { - BufferStruct bufferStruct; /* superclass fields must come first */ - RankSet rankSet; /* ranks of references being created */ - Seg seg; /* segment being buffered */ - Sig sig; /* */ -} SegBufStruct; - - -/* FormatStruct -- object format structure - * - * See design.mps.format-interface, . - * - * .single: In future, when more variants are added, FormatStruct should - * really be replaced by a collection of format classes. */ - -#define FormatSig ((Sig)0x519F63A2) /* Signature FoRMAT */ - -typedef struct mps_fmt_s { - Sig sig; - Serial serial; /* from arena->formatSerial */ - FormatVariety variety; /* format variety (e.g. A) */ - Arena arena; /* owning arena */ - RingStruct arenaRing; /* formats are attached to the arena */ - Align alignment; /* alignment of formatted objects */ - mps_fmt_scan_t scan; - mps_fmt_skip_t skip; - mps_fmt_fwd_t move; - mps_fmt_isfwd_t isMoved; - mps_fmt_copy_t copy; - mps_fmt_pad_t pad; - mps_fmt_class_t class; /* pointer indicating class */ - Size headerSize; /* size of header */ -} FormatStruct; - - -/* ScanState - * - * .ss: See . - * - * .ss: The mps_ss field of the scan state structure is exported - * through the MPS interface to optimise the critical path scan loop. - * See ["The critical path through the MPS"](../design/critical-path.txt). - * - * .ss.zone: For binary compatibility, the zone shift is exported as - * a word rather than a shift, so that the external mps_ss_s is a uniform - * three-word structure. See and . - * - * zs Shift zoneShift copy of arena->zoneShift. See .ss.zone - * w ZoneSet white white set, for inline fix test - * ufs RefSet unfixedSummary accumulated summary of scanned references - * - * NOTE: The mps_ss structure used to be obfuscated to preserve Harlequin's - * trade secrets in the MPS technology. These days they just seek to - * emphasize the abstraction, and could maybe be given better names and - * types. RB 2012-09-07 - */ - -#define ScanStateSig ((Sig)0x5195CA45) /* SIGnature SCAN State */ - -typedef struct ScanStateStruct { - Sig sig; /* */ - struct mps_ss_s ss_s; /* .ss */ - Arena arena; /* owning arena */ - PoolFixMethod fix; /* third stage fix function */ - void *fixClosure; /* closure data for fix */ - TraceSet traces; /* traces to scan for */ - Rank rank; /* reference rank of scanning */ - Bool wasMarked; /* design.mps.fix.protocol.was-ready */ - RefSet fixedSummary; /* accumulated summary of fixed references */ - STATISTIC_DECL(Count fixRefCount); /* refs which pass zone check */ - STATISTIC_DECL(Count segRefCount); /* refs which refer to segs */ - STATISTIC_DECL(Count whiteSegRefCount); /* refs which refer to white segs */ - STATISTIC_DECL(Count nailCount); /* segments nailed by ambig refs */ - STATISTIC_DECL(Count snapCount); /* refs snapped to forwarded objs */ - STATISTIC_DECL(Count forwardedCount); /* objects preserved by moving */ - Size forwardedSize; /* bytes preserved by moving */ - STATISTIC_DECL(Count preservedInPlaceCount); /* objects preserved in place */ - Size preservedInPlaceSize; /* bytes preserved in place */ - STATISTIC_DECL(Size copiedSize); /* bytes copied */ - STATISTIC_DECL(Size scannedSize); /* bytes scanned */ -} ScanStateStruct; - - -/* TraceStruct -- tracer state structure */ - -#define TraceSig ((Sig)0x51924ACE) /* SIGnature TRACE */ - -typedef struct TraceStruct { - Sig sig; /* */ - TraceId ti; /* index into TraceSets */ - Arena arena; /* owning arena */ - int why; /* why the trace began */ - ZoneSet white; /* zones in the white set */ - ZoneSet mayMove; /* zones containing possibly moving objs */ - TraceState state; /* current state of trace */ - Rank band; /* current band */ - Bool firstStretch; /* in first stretch of band (see accessor) */ - PoolFixMethod fix; /* fix method to apply to references */ - void *fixClosure; /* closure information for fix method */ - Chain chain; /* chain being incrementally collected */ - STATISTIC_DECL(Size preTraceArenaReserved); /* ArenaReserved before this trace */ - Size condemned; /* condemned bytes */ - Size notCondemned; /* collectable but not condemned */ - Size foundation; /* initial grey set size */ - Size rate; /* segs to scan per increment */ - STATISTIC_DECL(Count greySegCount); /* number of grey segs */ - STATISTIC_DECL(Count greySegMax); /* max number of grey segs */ - STATISTIC_DECL(Count rootScanCount); /* number of roots scanned */ - Count rootScanSize; /* total size of scanned roots */ - Size rootCopiedSize; /* bytes copied by scanning roots */ - STATISTIC_DECL(Count segScanCount); /* number of segs scanned */ - Count segScanSize; /* total size of scanned segments */ - Size segCopiedSize; /* bytes copied by scanning segments */ - STATISTIC_DECL(Count singleScanCount); /* number of single refs scanned */ - STATISTIC_DECL(Count singleScanSize); /* total size of single refs scanned */ - STATISTIC_DECL(Size singleCopiedSize); /* bytes copied by scanning single refs */ - STATISTIC_DECL(Count fixRefCount); /* refs which pass zone check */ - STATISTIC_DECL(Count segRefCount); /* refs which refer to segs */ - STATISTIC_DECL(Count whiteSegRefCount); /* refs which refer to white segs */ - STATISTIC_DECL(Count nailCount); /* segments nailed by ambig refs */ - STATISTIC_DECL(Count snapCount); /* refs snapped to forwarded objs */ - STATISTIC_DECL(Count readBarrierHitCount); /* read barrier faults */ - STATISTIC_DECL(Count pointlessScanCount); /* pointless seg scans */ - STATISTIC_DECL(Count forwardedCount); /* objects preserved by moving */ - Size forwardedSize; /* bytes preserved by moving */ - STATISTIC_DECL(Count preservedInPlaceCount); /* objects preserved in place */ - Size preservedInPlaceSize; /* bytes preserved in place */ - STATISTIC_DECL(Count reclaimCount); /* segments reclaimed */ - STATISTIC_DECL(Count reclaimSize); /* bytes reclaimed */ -} TraceStruct; - - -/* ChunkCacheEntryStruct -- cache entry in the chunk cache */ - -#define ChunkCacheEntrySig ((Sig)0x519C80CE) /* SIGnature CHUnk Cache Entry */ - -typedef struct ChunkCacheEntryStruct { - Sig sig; - Chunk chunk; - Addr base; - Addr limit; -} ChunkCacheEntryStruct; - - -/* ArenaClassStruct -- generic arena class interface */ - -#define ArenaClassSig ((Sig)0x519A6C1A) /* SIGnature ARena CLAss */ - -typedef struct mps_arena_class_s { - ProtocolClassStruct protocol; - char *name; /* class name string */ - size_t size; /* size of outer structure */ - size_t offset; /* offset of generic struct in outer struct */ - ArenaInitMethod init; - ArenaFinishMethod finish; - ArenaReservedMethod reserved; - ArenaSpareCommitExceededMethod spareCommitExceeded; - ArenaExtendMethod extend; - ArenaAllocMethod alloc; - ArenaFreeMethod free; - ArenaChunkInitMethod chunkInit; - ArenaChunkFinishMethod chunkFinish; - ArenaCompactMethod compact; - ArenaDescribeMethod describe; - Sig sig; -} ArenaClassStruct; - - -/* GlobalsStruct -- the global state associated with an arena - * - * .space: The arena structure holds the entire state of the MPS, and as - * such contains a lot of fields which are considered "global". These - * fields belong to different modules. The module which owns each group - * of fields is commented. */ - -#define GlobalsSig ((Sig)0x519970BA) /* SIGnature GLOBAls */ - -typedef struct GlobalsStruct { - Sig sig; - - /* general fields () */ - RingStruct globalRing; /* node in global ring of arenas */ - Lock lock; /* arena's lock */ - - /* polling fields () */ - double pollThreshold; /* */ - Bool insidePoll; - Bool clamped; /* prevent background activity */ - double fillMutatorSize; /* total bytes filled, mutator buffers */ - double emptyMutatorSize; /* total bytes emptied, mutator buffers */ - double allocMutatorSize; /* fill-empty, only asymptotically accurate */ - double fillInternalSize; /* total bytes filled, internal buffers */ - double emptyInternalSize; /* total bytes emptied, internal buffers */ - - /* version field () */ - const char *mpsVersionString; /* MPSVersion() */ - - /* buffer fields () */ - Bool bufferLogging; /* */ - - /* pool fields () */ - RingStruct poolRing; /* ring of pools in arena */ - Serial poolSerial; /* serial of next created pool */ - - /* root fields () */ - RingStruct rootRing; /* ring of roots attached to arena */ - Serial rootSerial; /* serial of next root */ - - /* remember summary () */ - RingStruct rememberedSummaryRing; - /* index into next free slot in block. 0 means that a new - block should be allocated and appended. */ - Index rememberedSummaryIndex; -} GlobalsStruct; - - -/* ArenaStruct -- generic arena - * - * See . */ - -#define ArenaSig ((Sig)0x519A6E4A) /* SIGnature ARENA */ - -typedef struct mps_arena_s { - GlobalsStruct globals; /* must be first, see */ - Serial serial; - - ArenaClass class; /* arena class structure */ - - Bool poolReady; /* */ - MVStruct controlPoolStruct; /* */ - - ReservoirStruct reservoirStruct; /* */ - - Size committed; /* amount of committed RAM */ - Size commitLimit; /* client-configurable commit limit */ - - Size spareCommitted; /* Amount of memory in hysteresis fund */ - Size spareCommitLimit; /* Limit on spareCommitted */ - - Shift zoneShift; /* see also */ - Align alignment; /* minimum alignment of tracts */ - - Tract lastTract; /* most recently allocated tract */ - Addr lastTractBase; /* base address of lastTract */ - - Chunk primary; /* the primary chunk */ - RingStruct chunkRing; /* all the chunks */ - Serial chunkSerial; /* next chunk number */ - ChunkCacheEntryStruct chunkCache; /* just one entry */ - - /* locus fields () */ - GenDescStruct topGen; /* generation descriptor for dynamic gen */ - - /* format fields () */ - RingStruct formatRing; /* ring of formats attached to arena */ - Serial formatSerial; /* serial of next format */ - - /* message fields (, ) */ - RingStruct messageRing; /* ring of pending messages */ - BT enabledMessageTypes; /* map of which types are enabled */ - Count droppedMessages; /* */ - - /* finalization fields (), */ - Bool isFinalPool; /* indicator for finalPool */ - Pool finalPool; /* either NULL or an MRG pool */ - - /* alert fields */ - mps_alert_collection_fn_t alertCollection; /* client alert fn or 0 */ - - /* thread fields () */ - RingStruct threadRing; /* ring of attached threads */ - Serial threadSerial; /* serial of next thread */ - - /* shield fields () */ - Bool insideShield; /* TRUE if and only if inside shield */ - Seg shCache[ShieldCacheSIZE]; /* Cache of unsynced segs */ - Size shCacheI; /* index into cache */ - Size shCacheLimit; /* High water mark for cache usage */ - Size shDepth; /* sum of depths of all segs */ - Bool suspended; /* TRUE iff mutator suspended */ - - /* trace fields () */ - TraceSet busyTraces; /* set of running traces */ - TraceSet flippedTraces; /* set of running and flipped traces */ - TraceStruct trace[TraceLIMIT]; /* trace structures. See - */ - - /* trace ancillary fields () */ - TraceStartMessage tsMessage[TraceLIMIT]; /* */ - TraceMessage tMessage[TraceLIMIT]; /* */ - - /* policy fields */ - double tracedSize; - double tracedTime; - Clock lastWorldCollect; - - RingStruct greyRing[RankLIMIT]; /* ring of grey segments at each rank */ - STATISTIC_DECL(Count writeBarrierHitCount); /* write barrier hits */ - RingStruct chainRing; /* ring of chains */ - - /* location dependency fields () */ - Epoch epoch; /* */ - RefSet prehistory; /* */ - RefSet history[LDHistoryLENGTH]; /* */ - - Bool emergency; /* garbage collect in emergency mode? */ - - Addr *stackAtArenaEnter; /* NULL or top of client stack, in the thread */ - /* that then entered the MPS. */ - - Sig sig; -} ArenaStruct; - - -typedef struct AllocPatternStruct { - char dummy; -} AllocPatternStruct; - - -#endif /* mpmst_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003, 2006, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h deleted file mode 100644 index 984790baf56..00000000000 --- a/mps/code/mpmtypes.h +++ /dev/null @@ -1,492 +0,0 @@ -/* mpmtypes.h: MEMORY POOL MANAGER TYPES - * - * $Id$ - * Copyright (c) 2001-2002, 2006 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2001 Global Graphics Software. - * - * .design: - * - * .rationale: Types and type constants are almost all defined - * in this header, in advance of any declarations of prototypes - * or structures. This avoids difficulties in defining recursive - * data structures. - */ - -#ifndef mpmtypes_h -#define mpmtypes_h - -#include "config.h" /* this must come first: it defines target options */ -#include "misc.h" /* miscellaneous non-specific bits and bobs */ -#include "mpslib.h" -#include "mpstd.h" /* for MPS_T_ULONGEST */ - -#include -#include - - -/* TYPES */ - -typedef unsigned long Sig; /* */ -typedef int Res; /* */ - -typedef void (*Fun)(void); /* */ -typedef MPS_T_WORD Word; /* */ -typedef unsigned char Byte; /* */ -typedef struct AddrStruct *Addr; /* */ -typedef Word Size; /* */ -typedef Word Count; /* */ -typedef Word Index; /* */ -typedef Word Align; /* */ -typedef unsigned Shift; /* */ -typedef unsigned Serial; /* */ -typedef Addr Ref; /* */ -typedef void *Pointer; /* */ -typedef unsigned long Clock; /* processor time */ -typedef MPS_T_ULONGEST ULongest; /* */ - -typedef Word RefSet; /* design.mps.refset */ -typedef Word ZoneSet; /* design.mps.refset */ -typedef unsigned Rank; -typedef unsigned RankSet; -typedef unsigned RootMode; -typedef Size Epoch; /* design.mps.ld */ -typedef unsigned TraceId; /* */ -typedef unsigned TraceSet; /* */ -typedef unsigned TraceState; /* */ -typedef unsigned AccessSet; /* */ -typedef unsigned Attr; /* */ -typedef unsigned FormatVariety; -typedef int RootVar; /* */ - -typedef Word *BT; /* */ -typedef struct BootBlockStruct *BootBlock; /* */ -typedef struct BufferStruct *Buffer; /* */ -typedef struct SegBufStruct *SegBuf; /* */ -typedef struct BufferClassStruct *BufferClass; /* */ -typedef BufferClass SegBufClass; /* */ -typedef BufferClass RankBufClass; /* */ -typedef unsigned BufferMode; /* */ -typedef unsigned FrameState; /* */ -typedef struct mps_fmt_s *Format; /* design.mps.format */ -typedef struct LockStruct *Lock; /* * */ -typedef struct mps_pool_s *Pool; /* */ -typedef struct mps_class_s *PoolClass; /* */ -typedef PoolClass AbstractPoolClass; /* */ -typedef PoolClass AbstractAllocFreePoolClass; /* */ -typedef PoolClass AbstractBufferPoolClass; /* */ -typedef PoolClass AbstractSegBufPoolClass; /* */ -typedef PoolClass AbstractScanPoolClass; /* */ -typedef PoolClass AbstractCollectPoolClass; /* */ -typedef struct TraceStruct *Trace; /* */ -typedef struct ScanStateStruct *ScanState; /* */ -typedef struct mps_chain_s *Chain; /* */ -typedef struct TractStruct *Tract; /* */ -typedef struct ChunkStruct *Chunk; /* */ -typedef struct ChunkCacheEntryStruct *ChunkCacheEntry; /* */ -typedef struct PageStruct *Page; /* */ -typedef struct SegStruct *Seg; /* */ -typedef struct GCSegStruct *GCSeg; /* */ -typedef struct SegClassStruct *SegClass; /* */ -typedef SegClass GCSegClass; /* */ -typedef struct SegPrefStruct *SegPref; /* design.mps.pref, */ -typedef int SegPrefKind; /* design.mps.pref, */ -typedef struct mps_arena_class_s *ArenaClass; /* */ -typedef ArenaClass AbstractArenaClass; /* */ -typedef struct mps_arena_s *Arena; /* */ -typedef struct GlobalsStruct *Globals; /* */ -typedef struct VMStruct *VM; /* * */ -typedef struct RootStruct *Root; /* */ -typedef struct mps_thr_s *Thread; /* * */ -typedef struct MutatorFaultContextStruct - *MutatorFaultContext; /* */ -typedef struct PoolDebugMixinStruct *PoolDebugMixin; -typedef struct AllocPatternStruct *AllocPattern; -typedef struct AllocFrameStruct *AllocFrame; /* */ -typedef struct ReservoirStruct *Reservoir; /* */ -typedef struct StackContextStruct *StackContext; - - -/* Arena*Method -- see */ - -typedef Res (*ArenaInitMethod)(Arena *arenaReturn, - ArenaClass class, va_list args); -typedef void (*ArenaFinishMethod)(Arena arena); -typedef Size (*ArenaReservedMethod)(Arena arena); -typedef void (*ArenaSpareCommitExceededMethod)(Arena arena); -typedef Res (*ArenaExtendMethod)(Arena arena, Addr base, Size size); -typedef Res (*ArenaAllocMethod)(Addr *baseReturn, Tract *baseTractReturn, - SegPref pref, Size size, Pool pool); -typedef void (*ArenaFreeMethod)(Addr base, Size size, Pool pool); -typedef Res (*ArenaChunkInitMethod)(Chunk chunk, BootBlock boot); -typedef void (*ArenaChunkFinishMethod)(Chunk chunk); -typedef void (*ArenaCompactMethod)(Arena arena, Trace trace); -typedef Res (*ArenaDescribeMethod)(Arena arena, mps_lib_FILE *stream); - - -/* TraceFixMethod */ - -typedef Res (*TraceFixMethod)(ScanState ss, Ref *refIO); - - -/* Heap Walker */ - -/* This type is used by the PoolClass method Walk */ -typedef void (*FormattedObjectsStepMethod)(Addr obj, Format fmt, Pool pool, - void *v, size_t s); - -/* This type is used by the PoolClass method Walk */ -typedef void (*FreeBlockStepMethod)(Addr base, Addr limit, Pool pool, void *p); - - -/* Seg*Method -- see */ - -typedef Res (*SegInitMethod)(Seg seg, Pool pool, Addr base, Size size, - Bool withReservoirPermit, va_list args); -typedef void (*SegFinishMethod)(Seg seg); -typedef void (*SegSetGreyMethod)(Seg seg, TraceSet grey); -typedef void (*SegSetWhiteMethod)(Seg seg, TraceSet white); -typedef void (*SegSetRankSetMethod)(Seg seg, RankSet rankSet); -typedef void (*SegSetRankSummaryMethod)(Seg seg, RankSet rankSet, - RefSet summary); -typedef void (*SegSetSummaryMethod)(Seg seg, RefSet summary); -typedef Buffer (*SegBufferMethod)(Seg seg); -typedef void (*SegSetBufferMethod)(Seg seg, Buffer buffer); -typedef Res (*SegDescribeMethod)(Seg seg, mps_lib_FILE *stream); -typedef Res (*SegMergeMethod)(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args); -typedef Res (*SegSplitMethod)(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args); - -/* Buffer*Method -- see */ - -typedef Res (*BufferInitMethod)(Buffer buffer, Pool pool, va_list args); -typedef void (*BufferFinishMethod)(Buffer buffer); -typedef void (*BufferAttachMethod)(Buffer buffer, Addr base, Addr limit, - Addr init, Size size); -typedef void (*BufferDetachMethod)(Buffer buffer); -typedef Seg (*BufferSegMethod)(Buffer buffer); -typedef RankSet (*BufferRankSetMethod)(Buffer buffer); -typedef void (*BufferSetRankSetMethod)(Buffer buffer, RankSet rankSet); -typedef void (*BufferReassignSegMethod)(Buffer buffer, Seg seg); -typedef Res (*BufferDescribeMethod)(Buffer buffer, mps_lib_FILE *stream); - - -/* Pool*Method -- see */ - -/* Order of types corresponds to PoolClassStruct in */ - -typedef Res (*PoolInitMethod)(Pool pool, va_list args); -typedef void (*PoolFinishMethod)(Pool pool); -typedef Res (*PoolAllocMethod)(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit); -typedef void (*PoolFreeMethod)(Pool pool, Addr old, Size size); -typedef Res (*PoolBufferFillMethod)(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit); -typedef void (*PoolBufferEmptyMethod)(Pool pool, Buffer buffer, - Addr init, Addr limit); -typedef Res (*PoolTraceBeginMethod)(Pool pool, Trace trace); -typedef Res (*PoolAccessMethod)(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context); -typedef Res (*PoolWhitenMethod)(Pool pool, Trace trace, Seg seg); -typedef void (*PoolGreyMethod)(Pool pool, Trace trace, Seg seg); -typedef void (*PoolBlackenMethod)(Pool pool, TraceSet traceSet, Seg seg); -typedef Res (*PoolScanMethod)(Bool *totalReturn, ScanState ss, - Pool pool, Seg seg); -typedef Res (*PoolFixMethod)(Pool pool, ScanState ss, Seg seg, - Ref *refIO); -typedef Res (*PoolFixEmergencyMethod)(Pool pool, ScanState ss, - Seg seg, Ref *refIO); -typedef void (*PoolReclaimMethod)(Pool pool, Trace trace, Seg seg); -typedef void (*PoolTraceEndMethod)(Pool pool, Trace trace); -typedef void (*PoolRampBeginMethod)(Pool pool, Buffer buf, Bool collectAll); -typedef void (*PoolRampEndMethod)(Pool pool, Buffer buf); -typedef Res (*PoolFramePushMethod)(AllocFrame *frameReturn, - Pool pool, Buffer buf); -typedef Res (*PoolFramePopMethod)(Pool pool, Buffer buf, - AllocFrame frame); -typedef void (*PoolFramePopPendingMethod)(Pool pool, Buffer buf, - AllocFrame frame); -typedef void (*PoolWalkMethod)(Pool pool, Seg seg, - FormattedObjectsStepMethod f, - void *v, size_t s); -typedef void (*PoolFreeWalkMethod)(Pool pool, FreeBlockStepMethod f, void *p); -typedef BufferClass (*PoolBufferClassMethod)(void); -typedef Res (*PoolDescribeMethod)(Pool pool, mps_lib_FILE *stream); -typedef PoolDebugMixin (*PoolDebugMixinMethod)(Pool pool); - - -/* Messages - * - * See - */ - -typedef unsigned MessageType; -typedef struct mps_message_s *Message; -typedef struct MessageClassStruct *MessageClass; - -/* Message*Method -- */ - -typedef void (*MessageDeleteMethod)(Message message); -typedef void (*MessageFinalizationRefMethod) - (Ref *refReturn, Arena arena, Message message); -typedef Size (*MessageGCLiveSizeMethod)(Message message); -typedef Size (*MessageGCCondemnedSizeMethod)(Message message); -typedef Size (*MessageGCNotCondemnedSizeMethod)(Message message); -typedef const char * (*MessageGCStartWhyMethod)(Message message); - -/* Message Types -- and elsewhere */ - -typedef struct TraceStartMessageStruct *TraceStartMessage; -typedef struct TraceMessageStruct *TraceMessage; /* trace end */ - - -/* CONSTANTS */ - - -/* SIGnature IS BAD */ -#define SigInvalid ((Sig)0x51915BAD) - -#define SizeMAX ((Size)-1) -#define AccessSetEMPTY ((AccessSet)0) /* */ -#define AccessREAD ((AccessSet)(1<<0)) -#define AccessWRITE ((AccessSet)(1<<1)) -#define AccessSetWIDTH (2) -#define RefSetEMPTY BS_EMPTY(RefSet) -#define RefSetUNIV BS_UNIV(RefSet) -#define ZoneSetEMPTY BS_EMPTY(ZoneSet) -#define ZoneSetUNIV BS_UNIV(ZoneSet) -#define TraceSetEMPTY BS_EMPTY(TraceSet) -#define TraceSetUNIV ((TraceSet)((1u << TraceLIMIT) - 1)) -#define RankSetEMPTY BS_EMPTY(RankSet) -#define RankSetUNIV ((RankSet)((1u << RankLIMIT) - 1)) -#define AttrFMT ((Attr)(1<<0)) /* */ -#define AttrSCAN ((Attr)(1<<1)) -#define AttrPM_NO_READ ((Attr)(1<<2)) -#define AttrPM_NO_WRITE ((Attr)(1<<3)) -#define AttrALLOC ((Attr)(1<<4)) -#define AttrFREE ((Attr)(1<<5)) -#define AttrBUF ((Attr)(1<<6)) -#define AttrBUF_RESERVE ((Attr)(1<<7)) -#define AttrBUF_ALLOC ((Attr)(1<<8)) -#define AttrGC ((Attr)(1<<9)) -#define AttrINCR_RB ((Attr)(1<<10)) -#define AttrINCR_WB ((Attr)(1<<11)) -#define AttrMOVINGGC ((Attr)(1<<12)) -#define AttrMASK (AttrFMT | AttrSCAN | AttrPM_NO_READ | \ - AttrPM_NO_WRITE | AttrALLOC | AttrFREE | \ - AttrBUF | AttrBUF_RESERVE | AttrBUF_ALLOC | \ - AttrGC | AttrINCR_RB | AttrINCR_WB | AttrMOVINGGC) - - -/* Format varieties */ -enum { - FormatVarietyA = 1, - FormatVarietyB, - FormatVarietyAutoHeader, - FormatVarietyFixed, - FormatVarietyLIMIT -}; - - -/* Segment preferences */ -enum { - SegPrefHigh = 1, - SegPrefLow, - SegPrefZoneSet, - SegPrefGen, - SegPrefCollected, - SegPrefLIMIT -}; - - -/* Buffer modes */ -#define BufferModeATTACHED ((BufferMode)(1<<0)) -#define BufferModeFLIPPED ((BufferMode)(1<<1)) -#define BufferModeLOGGED ((BufferMode)(1<<2)) -#define BufferModeTRANSITION ((BufferMode)(1<<3)) - - -/* Buffer frame states. See */ -enum { - BufferFrameVALID = 1, - BufferFramePOP_PENDING, - BufferFrameDISABLED -}; - - -/* Rank constants -- see */ -/* These definitions must match . */ -/* This is checked by . */ - -enum { - RankAMBIG = 0, - RankEXACT = 1, - RankFINAL = 2, - RankWEAK = 3, - RankLIMIT -}; - - -/* Root Modes -- not implemented */ -/* .rm: Synchronize with . */ -/* This comment exists as a placeholder for when root modes are */ -/* implemented. */ - -#define RootModeCONSTANT ((RootMode)1<<0) -#define RootModePROTECTABLE ((RootMode)1<<1) -#define RootModePROTECTABLE_INNER ((RootMode)1<<2) - - -/* Root Variants -- see - * - * .rootvar: Synchonize with - */ - -enum { - RootFUN, - RootTABLE, - RootTABLE_MASKED, - RootREG, - RootFMT, - RootLIMIT -}; - - -/* .result-codes: Result Codes -- see */ -/* These definitions must match . */ -/* This is checked by . */ -/* Changing this list entails changing the list in */ -/* and the check in */ - -enum { - ResOK = 0, /* MPS_RES_OK */ - ResFAIL, /* MPS_RES_FAIL */ - ResRESOURCE, /* MPS_RES_RESOURCE */ - ResMEMORY, /* MPS_RES_MEMORY */ - ResLIMIT, /* MPS_RES_LIMIT */ - /* note "LIMIT" does _not_ have usual end-of-enum meaning -rhsk */ - ResUNIMPL, /* MPS_RES_UNIMPL */ - ResIO, /* MPS_RES_IO */ - ResCOMMIT_LIMIT, /* MPS_RES_COMMIT_LIMIT */ - ResPARAM /* MPS_RES_PARAM */ -}; - - -/* TraceStates -- see */ - -enum { - TraceINIT = 1, - TraceUNFLIPPED, - TraceFLIPPED, - TraceRECLAIM, - TraceFINISHED -}; - - -/* TraceStart reasons: the trigger that caused a trace to start. */ -/* Make these specific trigger names, not broad categories; */ -/* and if a new trigger is added, add a new reason. */ -/* TODO: A better way for MPS extensions to extend the list of reasons - instead of the catch-all TraceStartWhyEXTENSION. */ - -enum { - TraceStartWhyBASE = 1, /* not a reason, the base of the enum. */ - TraceStartWhyCHAIN_GEN0CAP = TraceStartWhyBASE, /* start minor */ - TraceStartWhyDYNAMICCRITERION, /* start full */ - TraceStartWhyOPPORTUNISM, /* start full */ - TraceStartWhyCLIENTFULL_INCREMENTAL, /* start full */ - TraceStartWhyCLIENTFULL_BLOCK, /* do full */ - TraceStartWhyWALK, /* walking references -- see walk.c */ - TraceStartWhyEXTENSION, /* MPS extension using traces */ - TraceStartWhyLIMIT /* not a reason, the limit of the enum. */ -}; - - -/* MessageTypes -- see */ -/* .message.types: Keep in sync with */ - -enum { - MessageTypeFINALIZATION, /* MPS_MESSAGE_TYPE_FINALIZATION */ - MessageTypeGC, /* MPS_MESSAGE_TYPE_GC = trace end */ - MessageTypeGCSTART, /* MPS_MESSAGE_TYPE_GC_START */ - MessageTypeLIMIT /* not a message type, the limit of the enum. */ -}; - - -/* Types for WriteF formats */ -/* These should be used with calls to WriteF. */ -/* These must be unpromotable types. */ - -typedef Addr WriteFA; -typedef Pointer WriteFP; -typedef const char *WriteFS; -typedef Word WriteFW; -typedef ULongest WriteFU; -typedef ULongest WriteFB; -typedef void *(*WriteFF)(void); -typedef int WriteFC; /* Promoted */ -typedef double WriteFD; - - -/* STATISTIC_DECL -- declare a field to accumulate statistics in - * - * The argument is a field declaration (a struct-declaration minus the - * semicolon) for a single field (no commas). Currently, we always - * leave them in, see design.mps.metrics. - */ - -#if defined(STATISTICS) -#define STATISTIC_DECL(field) field -#elif defined(STATISTICS_NONE) -#define STATISTIC_DECL(field) field -#else -#error "No statistics configured." -#endif - - -#endif /* mpmtypes_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2006 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mps.c b/mps/code/mps.c deleted file mode 100644 index 1d1d93100d0..00000000000 --- a/mps/code/mps.c +++ /dev/null @@ -1,256 +0,0 @@ -/* mps.c: MEMORY POOL SYSTEM ALL-IN-ONE TRANSLATION UNIT - * - * $Id$ - * Copyright (C) 2012 Ravenbrook Limited. See end of file for license. - * - * .purpose: This file can be compiled to create the complete MPS library in - * a single compilation, allowing the compiler to apply global optimizations - * and inlining effectively. On most modern compilers this is also faster - * than compiling each file separately. - * - * .purpose.universal: This file also allows simple building of a Mac OS X - * "universal" (multiple architecture) binary when the set of source files - * differs by architecture. It may work for other platforms in a similar - * manner. - * - * .rule.simple: This file should never be more than a simple list of - * includes of other source code, with ifdefs for platform configuration, - * which closely mirror those in the makefiles. - */ - - -/* Platform interface - * - * This must be included first as it defines symbols which affect system - * headers, such as _POSIX_C_SOURCE _REENTRANT etc. - */ - -#include "mpstd.h" - - -/* MPM Core */ - -#include "mpsi.c" -#include "mpm.c" -#include "arenavm.c" -#include "arenacl.c" -#include "arena.c" -#include "global.c" -#include "locus.c" -#include "tract.c" -#include "walk.c" -#include "reserv.c" -#include "protocol.c" -#include "pool.c" -#include "poolabs.c" -#include "trace.c" -#include "traceanc.c" -#include "root.c" -#include "seg.c" -#include "format.c" -#include "buffer.c" -#include "ref.c" -#include "bt.c" -#include "ring.c" -#include "shield.c" -#include "ld.c" -#include "event.c" -#include "sac.c" -#include "message.c" -#include "poolmrg.c" -#include "poolmfs.c" -#include "poolmv.c" -#include "dbgpool.c" -#include "dbgpooli.c" -#include "boot.c" -#include "meter.c" -#include "splay.c" -#include "cbs.c" -#include "diag.c" -#include "ss.c" -#include "version.c" -#include "table.c" - -/* Additional pool classes */ - -#include "poolamc.c" -#include "poolams.c" -#include "poolamsi.c" -#include "poolawl.c" -#include "poollo.c" -#include "poolsnc.c" -#include "pooln.c" -#include "poolmvff.c" - -/* ANSI Plinth */ - -#if !defined(PLINTH_NONE) /* see CONFIG_PLINTH_NONE in config.h */ -#include "mpsliban.c" -#include "mpsioan.c" -#endif - -/* Mac OS X on 32-bit Intel built with Clang or GCC */ - -#if defined(MPS_PF_XCI3LL) || defined(MPS_PF_XCI3GC) - -#include "lockix.c" /* Posix locks */ -#include "than.c" /* generic single threading */ -#include "vmix.c" /* Posix virtual memory */ -#include "protix.c" /* Posix protection */ -#include "protsgix.c" /* Posix signal handling */ -#include "prmcan.c" /* generic mutator context */ -#include "span.c" /* generic stack probe */ -#include "ssixi3.c" /* Posix on 32-bit Intel stack scan */ - -/* Mac OS X on 64-bit Intel build with Clang or GCC */ - -#elif defined(MPS_PF_XCI6LL) || defined(MPS_PF_XCI6GC) - -#include "lockix.c" /* Posix locks */ -#include "than.c" /* generic single threading */ -#include "vmix.c" /* Posix virtual memory */ -#include "protix.c" /* Posix protection */ -#include "protsgix.c" /* Posix signal handling */ -#include "prmcan.c" /* generic mutator context */ -#include "span.c" /* generic stack probe */ -#include "ssixi6.c" /* Posix on 64-bit Intel stack scan */ - -/* FreeBSD on 32-bit Intel built with GCC */ - -#elif defined(MPS_PF_FRI3GC) - -#include "lockix.c" /* Posix locks */ -#include "thix.c" /* Posix threading */ -#include "pthrdext.c" /* Posix thread extensions */ -#include "vmix.c" /* Posix virtual memory */ -#include "protix.c" /* Posix protection */ -#include "protsgix.c" /* Posix signal handling */ -#include "prmcan.c" /* generic mutator context */ -#include "prmci3fr.c" /* 32-bit Intel for FreeBSD mutator context */ -#include "span.c" /* generic stack probe */ -#include "ssixi3.c" /* Posix on 32-bit Intel stack scan */ - -/* FreeBSD on 64-bit Intel built with GCC */ - -#elif defined(MPS_PF_FRI6GC) - -#include "lockix.c" /* Posix locks */ -#include "thix.c" /* Posix threading */ -#include "pthrdext.c" /* Posix thread extensions */ -#include "vmix.c" /* Posix virtual memory */ -#include "protix.c" /* Posix protection */ -#include "protsgix.c" /* Posix signal handling */ -#include "prmcan.c" /* generic mutator context */ -#include "prmci6fr.c" /* 64-bit Intel for FreeBSD mutator context */ -#include "span.c" /* generic stack probe */ -#include "ssixi6.c" /* Posix on 64-bit Intel stack scan */ - -/* Linux on 32-bit Intel with GCC */ - -#elif defined(MPS_PF_LII3GC) - -#include "lockli.c" /* Linux locks */ -#include "thix.c" /* Posix threading */ -#include "pthrdext.c" /* Posix thread extensions */ -#include "vmix.c" /* Posix virtual memory */ -#include "protix.c" /* Posix protection */ -#include "protli.c" /* Linux protection */ -#include "proti3.c" /* 32-bit Intel mutator context */ -#include "prmci3li.c" /* 32-bit Intel for Linux mutator context */ -#include "span.c" /* generic stack probe */ -#include "ssixi3.c" /* Posix on 32-bit Intel stack scan */ - -/* Linux on 64-bit Intel with GCC */ - -#elif defined(MPS_PF_LII6GC) - -#include "lockli.c" /* Linux locks */ -#include "thix.c" /* Posix threading */ -#include "pthrdext.c" /* Posix thread extensions */ -#include "vmix.c" /* Posix virtual memory */ -#include "protix.c" /* Posix protection */ -#include "protli.c" /* Linux protection */ -#include "proti6.c" /* 64-bit Intel mutator context */ -#include "prmci6li.c" /* 64-bit Intel for Linux mutator context */ -#include "span.c" /* generic stack probe */ -#include "ssixi6.c" /* Posix on 64-bit Intel stack scan */ - -/* Windows on 32-bit Intel with Microsoft Visual Studio */ - -#elif defined(MPS_PF_W3I3MV) - -#include "lockw3.c" /* Windows locks */ -#include "thw3.c" /* Windows threading */ -#include "thw3i3.c" /* Windows on 32-bit Intel thread stack scan */ -#include "vmw3.c" /* Windows virtual memory */ -#include "protw3.c" /* Windows protection */ -#include "proti3.c" /* 32-bit Intel mutator context decoding */ -#include "prmci3w3.c" /* Windows on 32-bit Intel mutator context */ -#include "ssw3i3mv.c" /* Windows on 32-bit stack scan for Microsoft C */ -#include "spi3.c" /* Intel stack probe */ -#include "mpsiw3.c" /* Windows interface layer extras */ - -/* Windows on 64-bit Intel with Microsoft Visual Studio */ -/* ssw3i6.asm is also required, but can't be included here */ - -#elif defined(MPS_PF_W3I6MV) - -#include "lockw3.c" /* Windows locks */ -#include "thw3.c" /* Windows threading */ -#include "thw3i6.c" /* Windows on 64-bit Intel thread stack scan */ -#include "vmw3.c" /* Windows virtual memory */ -#include "protw3.c" /* Windows protection */ -#include "proti6.c" /* 64-bit Intel mutator context decoding */ -#include "prmci6w3.c" /* Windows on 64-bit Intel mutator context */ -#include "ssw3i6mv.c" /* Windows on 64-bit stack scan for Microsoft C */ -#include "span.c" /* generic stack probe FIXME: Is this correct? */ -#include "mpsiw3.c" /* Windows interface layer extras */ - -#else - -#error "Unknown platform -- can't determine platform specific parts." - -#endif - - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2012 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mps.h b/mps/code/mps.h deleted file mode 100644 index 6d0edbb75d2..00000000000 --- a/mps/code/mps.h +++ /dev/null @@ -1,708 +0,0 @@ -/* mps.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE - * - * $Id$ - * Copyright (c) 2001-2012 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * THIS HEADER IS NOT DOCUMENTATION. - * Please refer to the [MPS Manual](../manual/). - * - * But if you are a human reading this, please note: - * - * .naming: The MPS interface only uses identifiers beginning `mps_`, - * `MPS_` or `_mps_` and may use any identifiers with these prefixes in - * future. - * - * .naming.internal: Any idenfitier beginning with underscore is for - * internal use within the interface and may change or be withdrawn without - * warning. - * - * .readership: compilers, MPS developers. - * - * .sources: [The design of the MPS Interface to C](../design/interface-c). - */ - -#ifndef mps_h -#define mps_h - -#include -#include -#include - - -/* Platform Dependencies - * - * We went for over ten years without any platform ifdefs in this header. - * Then Microsoft made unsigned long shorter than a pointer on Win64. Ugh. - */ - -#ifndef MPS_T_WORD -#if defined(_MSC_VER) && defined(_WIN32) && defined(_WIN64) && defined(_M_X64) -#define MPS_T_WORD unsigned __int64 -#else -#define MPS_T_WORD unsigned long /* won't be true on W3I6MV */ -#endif -#endif /* MPS_T_WORD */ - - -/* Abstract Types */ - -typedef struct mps_arena_s *mps_arena_t; /* arena */ -typedef struct mps_arena_class_s *mps_arena_class_t; /* arena class */ -typedef struct mps_pool_s *mps_pool_t; /* pool */ -typedef struct mps_chain_s *mps_chain_t; /* chain */ -typedef struct mps_fmt_s *mps_fmt_t; /* object format */ -typedef struct mps_root_s *mps_root_t; /* root */ -typedef struct mps_class_s *mps_class_t; /* pool class */ -typedef struct mps_thr_s *mps_thr_t; /* thread registration */ -typedef struct mps_ap_s *mps_ap_t; /* allocation point */ -typedef struct mps_ld_s *mps_ld_t; /* location dependency */ -typedef struct mps_ss_s *mps_ss_t; /* scan state */ -typedef struct mps_message_s - *mps_message_t; /* message */ -typedef struct mps_alloc_pattern_s - *mps_alloc_pattern_t; /* allocation patterns */ -typedef struct mps_frame_s - *mps_frame_t; /* allocation frames */ - -/* Concrete Types */ - -typedef MPS_T_WORD mps_word_t; /* pointer-sized word */ -typedef int mps_bool_t; /* boolean (int) */ -typedef int mps_res_t; /* result code (int) */ -typedef unsigned mps_shift_t; /* shift amount (unsigned int) */ -typedef void *mps_addr_t; /* managed address (void *) */ -typedef size_t mps_align_t; /* alignment (size_t) */ -typedef unsigned mps_rm_t; /* root mode (unsigned) */ -typedef unsigned mps_rank_t; /* ranks (unsigned) */ -typedef unsigned mps_message_type_t; /* message type (unsigned) */ -typedef unsigned long mps_clock_t; /* processor time */ - -/* Result Codes */ -/* .result-codes: Keep in sync with */ -/* and the check in */ - -enum { - MPS_RES_OK = 0, /* success (always zero) */ - MPS_RES_FAIL, /* unspecified failure */ - MPS_RES_RESOURCE, /* unable to obtain resources */ - MPS_RES_MEMORY, /* unable to obtain memory */ - MPS_RES_LIMIT, /* limitation reached */ - MPS_RES_UNIMPL, /* unimplemented facility */ - MPS_RES_IO, /* system I/O error */ - MPS_RES_COMMIT_LIMIT, /* arena commit limit exceeded */ - MPS_RES_PARAM /* illegal user parameter value */ -}; - -/* Keep in sync with - * */ -/* Not meant to be used by clients, they should use the macros below. */ -enum { - _mps_MESSAGE_TYPE_FINALIZATION, - _mps_MESSAGE_TYPE_GC, - _mps_MESSAGE_TYPE_GC_START -}; - -/* Message Types - * This is what clients should use. */ -#define mps_message_type_finalization() _mps_MESSAGE_TYPE_FINALIZATION -#define mps_message_type_gc() _mps_MESSAGE_TYPE_GC -#define mps_message_type_gc_start() _mps_MESSAGE_TYPE_GC_START - - -/* Reference Ranks - * - * See protocol.mps.reference. */ - -extern mps_rank_t mps_rank_ambig(void); -extern mps_rank_t mps_rank_exact(void); -extern mps_rank_t mps_rank_weak(void); - - -/* Root Modes */ -/* .rm: Keep in sync with */ - -#define MPS_RM_CONST (((mps_rm_t)1<<0)) -#define MPS_RM_PROT (((mps_rm_t)1<<1)) - - -/* Allocation Point */ -/* .ap: Keep in sync with . */ - -typedef struct mps_ap_s { /* allocation point descriptor */ - mps_addr_t init; /* limit of initialized memory */ - mps_addr_t alloc; /* limit of allocated memory */ - mps_addr_t limit; /* limit of available memory */ - mps_addr_t _frameptr; /* lightweight frame pointer */ - mps_bool_t _enabled; /* lightweight frame status */ - mps_bool_t _lwpoppending; /* lightweight pop pending? */ -} mps_ap_s; - - -/* Segregated-fit Allocation Caches */ -/* .sac: Keep in sync with . */ - -typedef struct mps_sac_s *mps_sac_t; - -#define MPS_SAC_CLASS_LIMIT ((size_t)8) - -typedef struct mps_sac_freelist_block_s { - size_t _size; - size_t _count; - size_t _count_max; - mps_addr_t _blocks; -} mps_sac_freelist_block_s; - -typedef struct mps_sac_s { - size_t _middle; - mps_bool_t _trapped; - mps_sac_freelist_block_s _freelists[2 * MPS_SAC_CLASS_LIMIT]; -} mps_sac_s; - -/* .sacc: Keep in sync with . */ -typedef struct mps_sac_class_s { - size_t _block_size; - size_t _cached_count; - unsigned _frequency; -} mps_sac_class_s; - -#define mps_sac_classes_s mps_sac_class_s - - -/* Location Dependency */ -/* .ld: Keep in sync with . */ - -typedef struct mps_ld_s { /* location dependency descriptor */ - mps_word_t _epoch, _rs; -} mps_ld_s; - - -/* Format and Root Method Types */ -/* see design.mps.root-interface */ -/* see design.mps.format-interface */ - -typedef mps_res_t (*mps_root_scan_t)(mps_ss_t, void *, size_t); -typedef mps_res_t (*mps_fmt_scan_t)(mps_ss_t, mps_addr_t, mps_addr_t); -typedef mps_res_t (*mps_reg_scan_t)(mps_ss_t, mps_thr_t, - void *, size_t); -typedef mps_addr_t (*mps_fmt_skip_t)(mps_addr_t); -typedef void (*mps_fmt_copy_t)(mps_addr_t, mps_addr_t); -typedef void (*mps_fmt_fwd_t)(mps_addr_t, mps_addr_t); -typedef mps_addr_t (*mps_fmt_isfwd_t)(mps_addr_t); -typedef void (*mps_fmt_pad_t)(mps_addr_t, size_t); -typedef mps_addr_t (*mps_fmt_class_t)(mps_addr_t); - - -/* Scan State */ -/* .ss: See also . */ - -typedef struct mps_ss_s { - mps_word_t _zs, _w, _ufs; -} mps_ss_s; - - -/* Format Variants */ - -typedef struct mps_fmt_A_s { - mps_align_t align; - mps_fmt_scan_t scan; - mps_fmt_skip_t skip; - mps_fmt_copy_t copy; - mps_fmt_fwd_t fwd; - mps_fmt_isfwd_t isfwd; - mps_fmt_pad_t pad; -} mps_fmt_A_s; -typedef struct mps_fmt_A_s *mps_fmt_A_t; -/* type-name mps_fmt_A_t is deprecated: use mps_fmt_A_s* instead */ - -typedef struct mps_fmt_B_s { - mps_align_t align; - mps_fmt_scan_t scan; - mps_fmt_skip_t skip; - mps_fmt_copy_t copy; - mps_fmt_fwd_t fwd; - mps_fmt_isfwd_t isfwd; - mps_fmt_pad_t pad; - mps_fmt_class_t mps_class; -} mps_fmt_B_s; -typedef struct mps_fmt_B_s *mps_fmt_B_t; -/* type-name mps_fmt_B_t is deprecated: use mps_fmt_B_s* instead */ - - -typedef struct mps_fmt_auto_header_s { - mps_align_t align; - mps_fmt_scan_t scan; - mps_fmt_skip_t skip; - mps_fmt_fwd_t fwd; - mps_fmt_isfwd_t isfwd; - mps_fmt_pad_t pad; - size_t mps_headerSize; -} mps_fmt_auto_header_s; - - -typedef struct mps_fmt_fixed_s { - mps_align_t align; - mps_fmt_scan_t scan; - mps_fmt_fwd_t fwd; - mps_fmt_isfwd_t isfwd; - mps_fmt_pad_t pad; -} mps_fmt_fixed_s; - - -/* Internal Definitions */ - -#define MPS_BEGIN do { -#define MPS_END } while(0) -/* MPS_END might cause compiler warnings about constant conditionals. - * This could be avoided with some loss of efficiency by replacing 0 - * with a variable always guaranteed to be 0. In Visual C, the - * warning can be turned off using: - * #pragma warning(disable: 4127) - */ - - -/* arenas */ - -extern void mps_arena_clamp(mps_arena_t); -extern void mps_arena_release(mps_arena_t); -extern void mps_arena_park(mps_arena_t); -extern void mps_arena_expose(mps_arena_t); -extern void mps_arena_unsafe_expose_remember_protection(mps_arena_t); -extern void mps_arena_unsafe_restore_protection(mps_arena_t); -extern mps_res_t mps_arena_start_collect(mps_arena_t); -extern mps_res_t mps_arena_collect(mps_arena_t); -extern mps_bool_t mps_arena_step(mps_arena_t, double, double); - -extern mps_res_t mps_arena_create(mps_arena_t *, mps_arena_class_t, ...); -extern mps_res_t mps_arena_create_v(mps_arena_t *, mps_arena_class_t, va_list); -extern void mps_arena_destroy(mps_arena_t); - -extern size_t mps_arena_reserved(mps_arena_t); -extern size_t mps_arena_committed(mps_arena_t); -extern size_t mps_arena_spare_committed(mps_arena_t); - -extern size_t mps_arena_commit_limit(mps_arena_t); -extern mps_res_t mps_arena_commit_limit_set(mps_arena_t, size_t); -extern void mps_arena_spare_commit_limit_set(mps_arena_t, size_t); -extern size_t mps_arena_spare_commit_limit(mps_arena_t); - -extern mps_bool_t mps_arena_has_addr(mps_arena_t, mps_addr_t); -extern mps_bool_t mps_addr_pool(mps_pool_t *, mps_arena_t, mps_addr_t); -extern mps_bool_t mps_addr_fmt(mps_fmt_t *, mps_arena_t, mps_addr_t); - -/* Client memory arenas */ -extern mps_res_t mps_arena_extend(mps_arena_t, mps_addr_t, size_t); -#if 0 -/* There's no implementation for this function. */ -extern mps_res_t mps_arena_retract(mps_arena_t, mps_addr_t, size_t); -#endif - - -/* Object Formats */ - -extern mps_res_t mps_fmt_create_A(mps_fmt_t *, mps_arena_t, - mps_fmt_A_s *); -extern mps_res_t mps_fmt_create_B(mps_fmt_t *, mps_arena_t, - mps_fmt_B_s *); -extern mps_res_t mps_fmt_create_auto_header(mps_fmt_t *, mps_arena_t, - mps_fmt_auto_header_s *); -extern mps_res_t mps_fmt_create_fixed(mps_fmt_t *, mps_arena_t, - mps_fmt_fixed_s *); -extern void mps_fmt_destroy(mps_fmt_t); - - -/* Pools */ - -extern mps_res_t mps_pool_create(mps_pool_t *, mps_arena_t, - mps_class_t, ...); -extern mps_res_t mps_pool_create_v(mps_pool_t *, mps_arena_t, - mps_class_t, va_list); -extern void mps_pool_destroy(mps_pool_t); - -/* .gen-param: This structure must match . */ -typedef struct mps_gen_param_s { - size_t mps_capacity; - double mps_mortality; -} mps_gen_param_s; - -extern mps_res_t mps_chain_create(mps_chain_t *, mps_arena_t, - size_t, mps_gen_param_s *); -extern void mps_chain_destroy(mps_chain_t); - -extern mps_res_t mps_alloc(mps_addr_t *, mps_pool_t, size_t, ...); -extern mps_res_t mps_alloc_v(mps_addr_t *, mps_pool_t, size_t, va_list); -extern void mps_free(mps_pool_t, mps_addr_t, size_t); - - -/* Allocation Points */ - -extern mps_res_t mps_ap_create(mps_ap_t *, mps_pool_t, ...); -extern mps_res_t mps_ap_create_v(mps_ap_t *, mps_pool_t, va_list); -extern void mps_ap_destroy(mps_ap_t); - -extern mps_res_t (mps_reserve)(mps_addr_t *, mps_ap_t, size_t); -extern mps_bool_t (mps_commit)(mps_ap_t, mps_addr_t, size_t); - -extern mps_res_t mps_ap_fill(mps_addr_t *, mps_ap_t, size_t); -extern mps_res_t mps_ap_fill_with_reservoir_permit(mps_addr_t *, - mps_ap_t, - size_t); - -extern mps_res_t (mps_ap_frame_push)(mps_frame_t *, mps_ap_t); -extern mps_res_t (mps_ap_frame_pop)(mps_ap_t, mps_frame_t); - -extern mps_bool_t mps_ap_trip(mps_ap_t, mps_addr_t, size_t); - -extern mps_alloc_pattern_t mps_alloc_pattern_ramp(void); -extern mps_alloc_pattern_t mps_alloc_pattern_ramp_collect_all(void); -extern mps_res_t mps_ap_alloc_pattern_begin(mps_ap_t, mps_alloc_pattern_t); -extern mps_res_t mps_ap_alloc_pattern_end(mps_ap_t, mps_alloc_pattern_t); -extern mps_res_t mps_ap_alloc_pattern_reset(mps_ap_t); - - -/* Segregated-fit Allocation Caches */ - -extern mps_res_t mps_sac_create(mps_sac_t *, mps_pool_t, size_t, - mps_sac_classes_s *); -extern void mps_sac_destroy(mps_sac_t); -extern mps_res_t mps_sac_alloc(mps_addr_t *, mps_sac_t, size_t, mps_bool_t); -extern void mps_sac_free(mps_sac_t, mps_addr_t, size_t); -extern void mps_sac_flush(mps_sac_t); - -/* Direct access to mps_sac_fill and mps_sac_empty is not supported. */ -extern mps_res_t mps_sac_fill(mps_addr_t *, mps_sac_t, size_t, mps_bool_t); -extern void mps_sac_empty(mps_sac_t, mps_addr_t, size_t); - -#define MPS_SAC_ALLOC_FAST(res_o, p_o, sac, size, has_reservoir_permit) \ - MPS_BEGIN \ - size_t _mps_i, _mps_s; \ - \ - _mps_s = (size); \ - if (_mps_s > (sac)->_middle) { \ - _mps_i = 0; \ - while (_mps_s > (sac)->_freelists[_mps_i]._size) \ - _mps_i += 2; \ - } else { \ - _mps_i = 1; \ - while (_mps_s <= (sac)->_freelists[_mps_i]._size) \ - _mps_i += 2; \ - } \ - if ((sac)->_freelists[_mps_i]._count != 0) { \ - (p_o) = (sac)->_freelists[_mps_i]._blocks; \ - (sac)->_freelists[_mps_i]._blocks = *(mps_addr_t *)(p_o); \ - --(sac)->_freelists[_mps_i]._count; \ - (res_o) = MPS_RES_OK; \ - } else \ - (res_o) = mps_sac_fill(&(p_o), sac, _mps_s, \ - has_reservoir_permit); \ - MPS_END - -#define MPS_SAC_FREE_FAST(sac, p, size) \ - MPS_BEGIN \ - size_t _mps_i, _mps_s; \ - \ - _mps_s = (size); \ - if (_mps_s > (sac)->_middle) { \ - _mps_i = 0; \ - while (_mps_s > (sac)->_freelists[_mps_i]._size) \ - _mps_i += 2; \ - } else { \ - _mps_i = 1; \ - while (_mps_s <= (sac)->_freelists[_mps_i]._size) \ - _mps_i += 2; \ - } \ - if ((sac)->_freelists[_mps_i]._count \ - < (sac)->_freelists[_mps_i]._count_max) { \ - *(mps_addr_t *)(p) = (sac)->_freelists[_mps_i]._blocks; \ - (sac)->_freelists[_mps_i]._blocks = (p); \ - ++(sac)->_freelists[_mps_i]._count; \ - } else \ - mps_sac_empty(sac, p, _mps_s); \ - MPS_END - -/* backward compatibility */ -#define MPS_SAC_ALLOC(res_o, p_o, sac, size, has_reservoir_permit) \ - MPS_SAC_ALLOC_FAST(res_o, p_o, sac, size, has_reservoir_permit) -#define MPS_SAC_FREE(sac, p, size) MPS_SAC_FREE_FAST(sac, p, size) - - -/* Low memory reservoir */ - -extern void mps_reservoir_limit_set(mps_arena_t, size_t); -extern size_t mps_reservoir_limit(mps_arena_t); -extern size_t mps_reservoir_available(mps_arena_t); -extern mps_res_t mps_reserve_with_reservoir_permit(mps_addr_t *, - mps_ap_t, - size_t); - - -/* Reserve Macros */ -/* .reserve: Keep in sync with . */ - -#define mps_reserve(_p_o, _mps_ap, _size) \ - ((char *)(_mps_ap)->alloc + (_size) > (char *)(_mps_ap)->alloc && \ - (char *)(_mps_ap)->alloc + (_size) <= (char *)(_mps_ap)->limit ? \ - ((_mps_ap)->alloc = \ - (mps_addr_t)((char *)(_mps_ap)->alloc + (_size)), \ - *(_p_o) = (_mps_ap)->init, \ - MPS_RES_OK) : \ - mps_ap_fill(_p_o, _mps_ap, _size)) - - -#define MPS_RESERVE_BLOCK(_res_v, _p_v, _mps_ap, _size) \ - MPS_BEGIN \ - char *_alloc = (char *)(_mps_ap)->alloc; \ - char *_next = _alloc + (_size); \ - if(_next > _alloc && _next <= (char *)(_mps_ap)->limit) { \ - (_mps_ap)->alloc = (mps_addr_t)_next; \ - (_p_v) = (_mps_ap)->init; \ - (_res_v) = MPS_RES_OK; \ - } else \ - (_res_v) = mps_ap_fill(&(_p_v), _mps_ap, _size); \ - MPS_END - - -#define MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK(_res_v, _p_v, _mps_ap, _size) \ - MPS_BEGIN \ - char *_alloc = (char *)(_mps_ap)->alloc; \ - char *_next = _alloc + (_size); \ - if(_next > _alloc && _next <= (char *)(_mps_ap)->limit) { \ - (_mps_ap)->alloc = (mps_addr_t)_next; \ - (_p_v) = (_mps_ap)->init; \ - (_res_v) = MPS_RES_OK; \ - } else \ - (_res_v) = mps_ap_fill_with_reservoir_permit(&(_p_v), _mps_ap, _size); \ - MPS_END - - -/* Commit Macros */ -/* .commit: Keep in sync with . */ - -#define mps_commit(_mps_ap, _p, _size) \ - ((_mps_ap)->init = (_mps_ap)->alloc, \ - (_mps_ap)->limit != 0 || mps_ap_trip(_mps_ap, _p, _size)) - - -/* Root Creation and Destruction */ - -extern mps_res_t mps_root_create(mps_root_t *, mps_arena_t, mps_rank_t, - mps_rm_t, mps_root_scan_t, - void *, size_t); -extern mps_res_t mps_root_create_table(mps_root_t *, mps_arena_t, - mps_rank_t, mps_rm_t, - mps_addr_t *, size_t); -extern mps_res_t mps_root_create_table_masked(mps_root_t *, mps_arena_t, - mps_rank_t, mps_rm_t, - mps_addr_t *, size_t, - mps_word_t); -extern mps_res_t mps_root_create_fmt(mps_root_t *, mps_arena_t, - mps_rank_t, mps_rm_t, - mps_fmt_scan_t, mps_addr_t, - mps_addr_t); -extern mps_res_t mps_root_create_reg(mps_root_t *, mps_arena_t, - mps_rank_t, mps_rm_t, mps_thr_t, - mps_reg_scan_t, void *, size_t); -extern void mps_root_destroy(mps_root_t); - -extern mps_res_t mps_stack_scan_ambig(mps_ss_t, mps_thr_t, - void *, size_t); - - -/* Protection Trampoline and Thread Registration */ - -typedef void *(*mps_tramp_t)(void *, size_t); -extern void (mps_tramp)(void **, mps_tramp_t, void *, size_t); - -extern mps_res_t mps_thread_reg(mps_thr_t *, mps_arena_t); -extern void mps_thread_dereg(mps_thr_t); - - -/* Location Dependency */ - -extern void mps_ld_reset(mps_ld_t, mps_arena_t); -extern void mps_ld_add(mps_ld_t, mps_arena_t, mps_addr_t); -extern void mps_ld_merge(mps_ld_t, mps_arena_t, mps_ld_t); -extern mps_bool_t mps_ld_isstale(mps_ld_t, mps_arena_t, mps_addr_t); - -extern mps_word_t mps_collections(mps_arena_t); - - -/* Messages */ - -extern void mps_message_type_enable(mps_arena_t, mps_message_type_t); -extern void mps_message_type_disable(mps_arena_t, mps_message_type_t); -extern mps_bool_t mps_message_poll(mps_arena_t); -extern mps_bool_t mps_message_queue_type(mps_message_type_t *, mps_arena_t); -extern mps_bool_t mps_message_get(mps_message_t *, - mps_arena_t, mps_message_type_t); -extern void mps_message_discard(mps_arena_t, mps_message_t); - -/* Message Methods */ - -/* -- All Message Types */ -extern mps_message_type_t mps_message_type(mps_arena_t, mps_message_t); -extern mps_clock_t mps_message_clock(mps_arena_t, mps_message_t); - -/* -- mps_message_type_finalization */ -extern void mps_message_finalization_ref(mps_addr_t *, - mps_arena_t, mps_message_t); - -/* -- mps_message_type_gc */ -extern size_t mps_message_gc_live_size(mps_arena_t, mps_message_t); -extern size_t mps_message_gc_condemned_size(mps_arena_t, mps_message_t); -extern size_t mps_message_gc_not_condemned_size(mps_arena_t, - mps_message_t); - -/* -- mps_message_type_gc_start */ -extern const char *mps_message_gc_start_why(mps_arena_t, mps_message_t); - - -/* Finalization */ - -extern mps_res_t mps_finalize(mps_arena_t, mps_addr_t *); -extern mps_res_t mps_definalize(mps_arena_t, mps_addr_t *); - - -/* Alert */ - -/* Alert codes. */ -enum { - MPS_ALERT_COLLECTION_BEGIN, - MPS_ALERT_COLLECTION_END -}; -typedef void (*mps_alert_collection_fn_t)(int, int); -extern mps_res_t mps_alert_collection_set(mps_arena_t, - mps_alert_collection_fn_t); -/* The following _START and _STOP identifiers are obsolete and - * deprecated: use _BEGIN and _END instead. */ -enum { - MPS_ALERT_COLLECTION_START = MPS_ALERT_COLLECTION_BEGIN, - MPS_ALERT_COLLECTION_STOP = MPS_ALERT_COLLECTION_END -}; - - -/* Telemetry */ - -extern mps_word_t mps_telemetry_control(mps_word_t, mps_word_t); -extern mps_word_t mps_telemetry_intern(const char *); -extern void mps_telemetry_label(mps_addr_t, mps_word_t); -extern void mps_telemetry_flush(void); - - -/* Heap Walking */ - -typedef void (*mps_formatted_objects_stepper_t)(mps_addr_t, mps_fmt_t, - mps_pool_t, - void *, size_t); -extern void mps_arena_formatted_objects_walk(mps_arena_t, - mps_formatted_objects_stepper_t, - void *, size_t); - - -/* Root Walking */ - -typedef void (*mps_roots_stepper_t)(mps_addr_t *, - mps_root_t, - void *, size_t); -extern void mps_arena_roots_walk(mps_arena_t, - mps_roots_stepper_t, - void *, size_t); - - -/* Allocation debug options */ - - -typedef struct mps_pool_debug_option_s { - void* fence_template; - size_t fence_size; - void* free_template; - size_t free_size; -} mps_pool_debug_option_s; - -extern void mps_pool_check_fenceposts(mps_pool_t); -extern void mps_pool_check_free_space(mps_pool_t); - - -/* Scanner Support */ - -extern mps_res_t mps_fix(mps_ss_t, mps_addr_t *); - -#define MPS_SCAN_BEGIN(ss) \ - MPS_BEGIN \ - mps_ss_t _ss = (ss); \ - mps_word_t _mps_zs = (_ss)->_zs; \ - mps_word_t _mps_w = (_ss)->_w; \ - mps_word_t _mps_ufs = (_ss)->_ufs; \ - mps_word_t _mps_wt; \ - { - -#define MPS_FIX1(ss, ref) \ - (_mps_wt = (mps_word_t)1 << ((mps_word_t)(ref) >> _mps_zs \ - & (sizeof(mps_word_t) * CHAR_BIT - 1)), \ - _mps_ufs |= _mps_wt, \ - (_mps_w & _mps_wt) != 0) - -extern mps_res_t _mps_fix2(mps_ss_t, mps_addr_t *); -#define MPS_FIX2(ss, ref_io) _mps_fix2(ss, ref_io) - -#define MPS_FIX12(ss, ref_io) \ - (MPS_FIX1(ss, *(ref_io)) ? \ - MPS_FIX2(ss, ref_io) : MPS_RES_OK) - -/* MPS_FIX is deprecated */ -#define MPS_FIX(ss, ref_io) MPS_FIX12(ss, ref_io) - -#define MPS_FIX_CALL(ss, call) \ - MPS_BEGIN \ - (call); _mps_ufs |= (ss)->_ufs; \ - MPS_END - -#define MPS_SCAN_END(ss) \ - } \ - (ss)->_ufs = _mps_ufs; \ - MPS_END - - -#endif /* mps_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj deleted file mode 100644 index 207e50660e4..00000000000 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ /dev/null @@ -1,3952 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - 3104AFF1156D37A0000A585A /* all */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 3104AFF2156D37A0000A585A /* Build configuration list for PBXAggregateTarget "all" */; - buildPhases = ( - ); - dependencies = ( - 3104AFF6156D37BC000A585A /* PBXTargetDependency */, - 3114A6D5156E9839001E0AA3 /* PBXTargetDependency */, - 3114A6B9156E9763001E0AA3 /* PBXTargetDependency */, - 3114A6A7156E9739001E0AA3 /* PBXTargetDependency */, - 3114A68D156E9686001E0AA3 /* PBXTargetDependency */, - 3114A677156E961C001E0AA3 /* PBXTargetDependency */, - 3114A65B156E95B4001E0AA3 /* PBXTargetDependency */, - 3114A644156E94FB001E0AA3 /* PBXTargetDependency */, - 3114A62E156E94AA001E0AA3 /* PBXTargetDependency */, - 3114A612156E943B001E0AA3 /* PBXTargetDependency */, - 3114A600156E940A001E0AA3 /* PBXTargetDependency */, - 3114A5EA156E93C4001E0AA3 /* PBXTargetDependency */, - 3114A5CC156E932C001E0AA3 /* PBXTargetDependency */, - 3114A5B6156E92DC001E0AA3 /* PBXTargetDependency */, - 3114A5A0156E915A001E0AA3 /* PBXTargetDependency */, - 31D6009D156D404B00337B26 /* PBXTargetDependency */, - 31D60087156D3FE600337B26 /* PBXTargetDependency */, - 31D60063156D3F5C00337B26 /* PBXTargetDependency */, - 31D6004F156D3EF700337B26 /* PBXTargetDependency */, - 3104B04A156D3AE4000A585A /* PBXTargetDependency */, - 3104B02D156D39DF000A585A /* PBXTargetDependency */, - 3104B01D156D398B000A585A /* PBXTargetDependency */, - 3104B004156D37CD000A585A /* PBXTargetDependency */, - 3104B002156D37CB000A585A /* PBXTargetDependency */, - 3104B000156D37C8000A585A /* PBXTargetDependency */, - 3104AFFE156D37C6000A585A /* PBXTargetDependency */, - 3104AFFC156D37C3000A585A /* PBXTargetDependency */, - 3104AFFA156D37C1000A585A /* PBXTargetDependency */, - 3104AFF8156D37BE000A585A /* PBXTargetDependency */, - 31D60022156D3CF200337B26 /* PBXTargetDependency */, - 31D60034156D3D5A00337B26 /* PBXTargetDependency */, - ); - name = all; - productName = all; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 3104AFBF156D3591000A585A /* apss.c in Sources */ = {isa = PBXBuildFile; fileRef = 3104AFBE156D3591000A585A /* apss.c */; }; - 3104AFC2156D35B2000A585A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3104AFC3156D35C3000A585A /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3104AFD4156D35F7000A585A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3104AFD5156D35FB000A585A /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3104AFD8156D3607000A585A /* sacss.c in Sources */ = {isa = PBXBuildFile; fileRef = 3104AFD6156D3602000A585A /* sacss.c */; }; - 3104AFE9156D3690000A585A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3104AFEA156D3697000A585A /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3104AFEC156D36A5000A585A /* amcsshe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3104AFEB156D36A5000A585A /* amcsshe.c */; }; - 3104AFED156D374A000A585A /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; }; - 3104AFEE156D374D000A585A /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3104AFEF156D3753000A585A /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3104AFF0156D3756000A585A /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3104B016156D390B000A585A /* amsss.c in Sources */ = {isa = PBXBuildFile; fileRef = 3104B015156D390B000A585A /* amsss.c */; }; - 3104B017156D3915000A585A /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3104B018156D3953000A585A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3104B019156D3960000A585A /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3104B01A156D396E000A585A /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3104B01B156D3973000A585A /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3104B02E156D39E2000A585A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3104B031156D39FD000A585A /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; }; - 3104B032156D3A00000A585A /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3104B033156D3A05000A585A /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3104B034156D3A2C000A585A /* amssshe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3104B02F156D39F2000A585A /* amssshe.c */; }; - 3104B035156D3A39000A585A /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3104B036156D3A49000A585A /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3104B04E156D3AFE000A585A /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3104B04F156D3B09000A585A /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3104B050156D3B09000A585A /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3104B051156D3B09000A585A /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3114A59B156E914B001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A59C156E914F001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A5A2156E9168001E0AA3 /* locv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A5A1156E9168001E0AA3 /* locv.c */; }; - 3114A5B1156E92C8001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A5B2156E92CB001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A5B8156E92F1001E0AA3 /* qs.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A5B7156E92F0001E0AA3 /* qs.c */; }; - 3114A5C7156E9322001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A5C8156E9322001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A5CE156E9369001E0AA3 /* finalcv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A5CD156E9369001E0AA3 /* finalcv.c */; }; - 3114A5CF156E9381001E0AA3 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3114A5D0156E9381001E0AA3 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3114A5D1156E9381001E0AA3 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3114A5E0156E93AE001E0AA3 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3114A5E1156E93AE001E0AA3 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3114A5E2156E93AE001E0AA3 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3114A5E3156E93AE001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A5E4156E93AE001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A5E6156E93B9001E0AA3 /* finaltest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A5E5156E93B9001E0AA3 /* finaltest.c */; }; - 3114A5F9156E93F3001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A5FA156E93F3001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A5FC156E93FC001E0AA3 /* arenacv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A5FB156E93FC001E0AA3 /* arenacv.c */; }; - 3114A615156E944E001E0AA3 /* bttest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A613156E944A001E0AA3 /* bttest.c */; }; - 3114A616156E9455001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A617156E946B001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A626156E948C001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A627156E9490001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A62A156E949E001E0AA3 /* teletest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A628156E949A001E0AA3 /* teletest.c */; }; - 3114A63E156E94EA001E0AA3 /* abqtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A63D156E94EA001E0AA3 /* abqtest.c */; }; - 3114A63F156E94F0001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A640156E94F0001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A646156E9525001E0AA3 /* abq.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A645156E9525001E0AA3 /* abq.c */; }; - 3114A657156E95A6001E0AA3 /* cbstest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A656156E95A6001E0AA3 /* cbstest.c */; }; - 3114A66E156E95F2001E0AA3 /* btcv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A66C156E95EB001E0AA3 /* btcv.c */; }; - 3114A66F156E95F2001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A670156E95F2001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A672156E95F6001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A673156E95F6001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A687156E9674001E0AA3 /* mv2test.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A686156E9674001E0AA3 /* mv2test.c */; }; - 3114A688156E967C001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A68F156E96B6001E0AA3 /* poolmv2.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A68E156E96B6001E0AA3 /* poolmv2.c */; }; - 3114A690156E96CE001E0AA3 /* abq.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A645156E9525001E0AA3 /* abq.c */; }; - 3114A6A1156E9729001E0AA3 /* messtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A69F156E9725001E0AA3 /* messtest.c */; }; - 3114A6A2156E972D001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A6A3156E972D001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A6BC156E976C001E0AA3 /* walkt0.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A6BA156E9768001E0AA3 /* walkt0.c */; }; - 3114A6BD156E9771001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3114A6BE156E9771001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A6BF156E97B8001E0AA3 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3114A6C0156E97B8001E0AA3 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3114A6C1156E97B8001E0AA3 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3114A6D1156E9829001E0AA3 /* eventcnv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A6D0156E9829001E0AA3 /* eventcnv.c */; }; - 3114A6D7156E9923001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3114A6DA156E9950001E0AA3 /* eventpro.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A6D9156E9950001E0AA3 /* eventpro.c */; }; - 3114A6DD156E9A0F001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3124CAC3156BE40100753214 /* awlut.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC2156BE40100753214 /* awlut.c */; }; - 3124CAC4156BE40D00753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3124CAC5156BE41700753214 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3124CAC8156BE48D00753214 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3124CAC9156BE48D00753214 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3124CACD156BE4C200753214 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3124CADF156BE65900753214 /* mpsicv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CADE156BE65900753214 /* mpsicv.c */; }; - 3124CAE0156BE66B00753214 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3124CAE1156BE67000753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3124CAE2156BE68E00753214 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3124CAE3156BE69B00753214 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3124CAE5156BE6D500753214 /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; }; - 3124CAE6156BE6F700753214 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3124CAF6156BE81100753214 /* amcss.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAF5156BE81100753214 /* amcss.c */; }; - 3124CAF7156BE82000753214 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 3124CAF8156BE82000753214 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 3124CAF9156BE82000753214 /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; }; - 3124CAFA156BE82000753214 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 3124CAFB156BE82000753214 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 3124CAFC156BE82900753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 3150AE53156ABA2500A6E22A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 31A47BA4156C1E130039B1C2 /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; }; - 31D60007156D3C6200337B26 /* segsmss.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D60006156D3C5F00337B26 /* segsmss.c */; }; - 31D60008156D3C7400337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 31D60018156D3CC300337B26 /* awluthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D60017156D3CC300337B26 /* awluthe.c */; }; - 31D60019156D3CCC00337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 31D6001A156D3CDC00337B26 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 31D6001B156D3CDC00337B26 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 31D6001C156D3CDC00337B26 /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; }; - 31D6001D156D3CDC00337B26 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 31D6001E156D3CDF00337B26 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 31D60035156D3DF300337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 31D60038156D3E3000337B26 /* lockcov.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D60036156D3E0200337B26 /* lockcov.c */; }; - 31D60039156D3E3E00337B26 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 31D60048156D3ECF00337B26 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 31D60049156D3ED200337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 31D6004B156D3EE600337B26 /* poolncv.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D6004A156D3EE600337B26 /* poolncv.c */; }; - 31D6005F156D3F4A00337B26 /* zcoll.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D6005E156D3F4A00337B26 /* zcoll.c */; }; - 31D60060156D3F5000337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 31D60069156D3F7200337B26 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 31D6006A156D3F7200337B26 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 31D6006B156D3F7200337B26 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 31D6006C156D3F7200337B26 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 31D6007D156D3FCF00337B26 /* zmess.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D6007B156D3FCC00337B26 /* zmess.c */; }; - 31D6007E156D3FD700337B26 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 31D6007F156D3FD700337B26 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 31D60080156D3FD700337B26 /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; }; - 31D60081156D3FD700337B26 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 31D60082156D3FD700337B26 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 31D60083156D3FDB00337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 31D6009A156D404000337B26 /* steptest.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D60098156D403C00337B26 /* steptest.c */; }; - 31D6009B156D404400337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; }; - 31D6009E156D406400337B26 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; }; - 31D6009F156D406400337B26 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; }; - 31D600A0156D406400337B26 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; }; - 31D600A1156D406400337B26 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; - 31EEAC75156AB58E00714D05 /* mpmss.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC74156AB58E00714D05 /* mpmss.c */; }; - 31EEAC9F156AB73400714D05 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 3104AFC0156D35AE000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3104AFD2156D35F2000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3104AFE7156D368D000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3104AFF5156D37BC000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3104AFF7156D37BE000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3124CAEA156BE7F300753214; - remoteInfo = amcss; - }; - 3104AFF9156D37C1000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3104AFB2156D357B000A585A; - remoteInfo = apss; - }; - 3104AFFB156D37C3000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3124CAB7156BE3EC00753214; - remoteInfo = awlut; - }; - 3104AFFD156D37C6000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEAC64156AB52600714D05; - remoteInfo = mpmss; - }; - 3104AFFF156D37C8000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3124CAD3156BE64A00753214; - remoteInfo = mpsicv; - }; - 3104B001156D37CB000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3104AFC7156D35E2000A585A; - remoteInfo = sacss; - }; - 3104B003156D37CD000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3104AFDC156D3681000A585A; - remoteInfo = amcsshe; - }; - 3104B013156D38FA000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3104B01C156D398B000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3104B008156D38F3000A585A; - remoteInfo = amsss; - }; - 3104B02C156D39DF000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3104B021156D39D4000A585A; - remoteInfo = amssshe; - }; - 3104B037156D3A56000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3104B047156D3ADE000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3104B049156D3AE4000A585A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3104B03C156D3AD7000A585A; - remoteInfo = segsmss; - }; - 3114A59D156E9156001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A59F156E915A001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A58F156E913C001E0AA3; - remoteInfo = locv; - }; - 3114A5B3156E92D8001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A5B5156E92DC001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A5A6156E92C0001E0AA3; - remoteInfo = qs; - }; - 3114A5C9156E9328001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A5CB156E932C001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A5BC156E9315001E0AA3; - remoteInfo = finalcv; - }; - 3114A5E7156E93BF001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A5E9156E93C4001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A5D5156E93A0001E0AA3; - remoteInfo = finaltest; - }; - 3114A5FD156E9406001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A5FF156E940A001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A5EE156E93E7001E0AA3; - remoteInfo = arenacv; - }; - 3114A60F156E9438001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A611156E943B001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A604156E9430001E0AA3; - remoteInfo = bttest; - }; - 3114A62B156E94A6001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A62D156E94AA001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A61B156E9485001E0AA3; - remoteInfo = teletest; - }; - 3114A641156E94F8001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A643156E94FB001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A632156E94DB001E0AA3; - remoteInfo = abqtest; - }; - 3114A658156E95B1001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A65A156E95B4001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A64B156E9596001E0AA3; - remoteInfo = cbstest; - }; - 3114A674156E9619001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A676156E961C001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A661156E95D9001E0AA3; - remoteInfo = btcv; - }; - 3114A68A156E9682001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A68C156E9686001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A67B156E9668001E0AA3; - remoteInfo = mv2test; - }; - 3114A6A4156E9735001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A6A6156E9739001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A694156E971B001E0AA3; - remoteInfo = messtest; - }; - 3114A6B6156E975E001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A6B8156E9763001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A6AB156E9759001E0AA3; - remoteInfo = walkt0; - }; - 3114A6D2156E9834001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 3114A6D4156E9839001E0AA3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3114A6C5156E9815001E0AA3; - remoteInfo = eventcnv; - }; - 31A47BA9156C210D0039B1C2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31A47BAB156C21120039B1C2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31A47BAD156C21170039B1C2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31A47BAF156C211B0039B1C2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31D6001F156D3CEC00337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31D60021156D3CF200337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31D6000C156D3CB200337B26; - remoteInfo = awluthe; - }; - 31D60031156D3D5300337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31D60033156D3D5A00337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31D60026156D3D3E00337B26; - remoteInfo = lockcov; - }; - 31D6004C156D3EF000337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31D6004E156D3EF700337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31D6003D156D3EC700337B26; - remoteInfo = poolncv; - }; - 31D60062156D3F5C00337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31D60053156D3F3500337B26; - remoteInfo = zcoll; - }; - 31D60064156D3F5F00337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31D60084156D3FE100337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31D60086156D3FE600337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31D60070156D3FBC00337B26; - remoteInfo = zmess; - }; - 31D60096156D403500337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31EEABFA156AAF9D00714D05; - remoteInfo = mps; - }; - 31D6009C156D404B00337B26 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 31D6008B156D402900337B26; - remoteInfo = steptest; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 3104AFB1156D357B000A585A /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3104AFC6156D35E2000A585A /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3104AFDB156D3681000A585A /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3104B007156D38F3000A585A /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3104B020156D39D4000A585A /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3104B03B156D3AD7000A585A /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A58E156E913C001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A5A5156E92C0001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A5BB156E9315001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A5D4156E93A0001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A5ED156E93E7001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A603156E9430001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A61A156E9485001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A631156E94DB001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A64A156E9596001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A660156E95D9001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A67A156E9668001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A693156E971B001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A6AA156E9759001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3114A6C4156E9815001E0AA3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3124CAB6156BE3EC00753214 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3124CAD2156BE64A00753214 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 3124CAE9156BE7F300753214 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 31D6000B156D3CB200337B26 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 31D60025156D3D3E00337B26 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 31D6003C156D3EC700337B26 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 31D60052156D3F3500337B26 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 31D6006F156D3FBC00337B26 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 31D6008A156D402900337B26 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 31EEAC63156AB52600714D05 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 3104AFA5156D27E7000A585A /* ssixi6.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ssixi6.c; sourceTree = ""; }; - 3104AFB3156D357B000A585A /* apss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = apss; sourceTree = BUILT_PRODUCTS_DIR; }; - 3104AFBE156D3591000A585A /* apss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = apss.c; sourceTree = ""; }; - 3104AFC8156D35E2000A585A /* sacss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sacss; sourceTree = BUILT_PRODUCTS_DIR; }; - 3104AFD6156D3602000A585A /* sacss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sacss.c; sourceTree = ""; }; - 3104AFDD156D3681000A585A /* amcsshe */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amcsshe; sourceTree = BUILT_PRODUCTS_DIR; }; - 3104AFEB156D36A5000A585A /* amcsshe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcsshe.c; sourceTree = ""; }; - 3104B009156D38F3000A585A /* amsss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amsss; sourceTree = BUILT_PRODUCTS_DIR; }; - 3104B015156D390B000A585A /* amsss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amsss.c; sourceTree = ""; }; - 3104B022156D39D4000A585A /* amssshe */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amssshe; sourceTree = BUILT_PRODUCTS_DIR; }; - 3104B02F156D39F2000A585A /* amssshe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amssshe.c; sourceTree = ""; }; - 3104B03D156D3AD7000A585A /* segsmss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = segsmss; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A590156E913C001E0AA3 /* locv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = locv; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A5A1156E9168001E0AA3 /* locv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locv.c; sourceTree = ""; }; - 3114A5A7156E92C0001E0AA3 /* qs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = qs; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A5B7156E92F0001E0AA3 /* qs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = qs.c; sourceTree = ""; }; - 3114A5BD156E9315001E0AA3 /* finalcv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = finalcv; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A5CD156E9369001E0AA3 /* finalcv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = finalcv.c; sourceTree = ""; }; - 3114A5D6156E93A0001E0AA3 /* finaltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = finaltest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A5E5156E93B9001E0AA3 /* finaltest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = finaltest.c; sourceTree = ""; }; - 3114A5EF156E93E7001E0AA3 /* arenacv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = arenacv; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A5FB156E93FC001E0AA3 /* arenacv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arenacv.c; sourceTree = ""; }; - 3114A605156E9430001E0AA3 /* bttest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bttest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A613156E944A001E0AA3 /* bttest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bttest.c; sourceTree = ""; }; - 3114A61C156E9485001E0AA3 /* teletest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = teletest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A628156E949A001E0AA3 /* teletest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = teletest.c; sourceTree = ""; }; - 3114A633156E94DB001E0AA3 /* abqtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = abqtest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A63D156E94EA001E0AA3 /* abqtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abqtest.c; sourceTree = ""; }; - 3114A645156E9525001E0AA3 /* abq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abq.c; sourceTree = ""; }; - 3114A64C156E9596001E0AA3 /* cbstest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cbstest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A656156E95A6001E0AA3 /* cbstest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cbstest.c; sourceTree = ""; }; - 3114A662156E95D9001E0AA3 /* btcv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = btcv; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A66C156E95EB001E0AA3 /* btcv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = btcv.c; sourceTree = ""; }; - 3114A67C156E9668001E0AA3 /* mv2test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mv2test; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A686156E9674001E0AA3 /* mv2test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mv2test.c; sourceTree = ""; }; - 3114A68E156E96B6001E0AA3 /* poolmv2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolmv2.c; sourceTree = ""; }; - 3114A695156E971B001E0AA3 /* messtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = messtest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A69F156E9725001E0AA3 /* messtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = messtest.c; sourceTree = ""; }; - 3114A6AC156E9759001E0AA3 /* walkt0 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = walkt0; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A6BA156E9768001E0AA3 /* walkt0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = walkt0.c; sourceTree = ""; }; - 3114A6C6156E9815001E0AA3 /* eventcnv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = eventcnv; sourceTree = BUILT_PRODUCTS_DIR; }; - 3114A6D0156E9829001E0AA3 /* eventcnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventcnv.c; sourceTree = ""; }; - 3114A6D9156E9950001E0AA3 /* eventpro.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventpro.c; sourceTree = ""; }; - 3124CAB8156BE3EC00753214 /* awlut */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = awlut; sourceTree = BUILT_PRODUCTS_DIR; }; - 3124CAC2156BE40100753214 /* awlut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awlut.c; sourceTree = ""; }; - 3124CAC6156BE48D00753214 /* fmtdy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmtdy.c; sourceTree = ""; }; - 3124CAC7156BE48D00753214 /* fmtdytst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmtdytst.c; sourceTree = ""; }; - 3124CACA156BE4A300753214 /* poollo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poollo.c; sourceTree = ""; }; - 3124CACC156BE4C200753214 /* fmtno.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmtno.c; sourceTree = ""; }; - 3124CACE156BE4CF00753214 /* poolawl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolawl.c; sourceTree = ""; }; - 3124CAD4156BE64A00753214 /* mpsicv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mpsicv; sourceTree = BUILT_PRODUCTS_DIR; }; - 3124CADE156BE65900753214 /* mpsicv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpsicv.c; sourceTree = ""; }; - 3124CAE4156BE6D500753214 /* fmthe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmthe.c; sourceTree = ""; }; - 3124CAEB156BE7F300753214 /* amcss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amcss; sourceTree = BUILT_PRODUCTS_DIR; }; - 3124CAF5156BE81100753214 /* amcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcss.c; sourceTree = ""; }; - 31A47BA3156C1E130039B1C2 /* mps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mps.c; sourceTree = ""; }; - 31A47BA5156C1E5E0039B1C2 /* ssixi3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ssixi3.c; sourceTree = ""; }; - 31D60006156D3C5F00337B26 /* segsmss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = segsmss.c; sourceTree = ""; }; - 31D6000D156D3CB200337B26 /* awluthe */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = awluthe; sourceTree = BUILT_PRODUCTS_DIR; }; - 31D60017156D3CC300337B26 /* awluthe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awluthe.c; sourceTree = ""; }; - 31D60027156D3D3E00337B26 /* lockcov */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lockcov; sourceTree = BUILT_PRODUCTS_DIR; }; - 31D60036156D3E0200337B26 /* lockcov.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lockcov.c; sourceTree = ""; }; - 31D6003E156D3EC700337B26 /* poolncv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = poolncv; sourceTree = BUILT_PRODUCTS_DIR; }; - 31D6004A156D3EE600337B26 /* poolncv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolncv.c; sourceTree = ""; }; - 31D60054156D3F3500337B26 /* zcoll */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = zcoll; sourceTree = BUILT_PRODUCTS_DIR; }; - 31D6005E156D3F4A00337B26 /* zcoll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zcoll.c; sourceTree = ""; }; - 31D60071156D3FBC00337B26 /* zmess */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = zmess; sourceTree = BUILT_PRODUCTS_DIR; }; - 31D6007B156D3FCC00337B26 /* zmess.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zmess.c; sourceTree = ""; }; - 31D6008C156D402900337B26 /* steptest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = steptest; sourceTree = BUILT_PRODUCTS_DIR; }; - 31D60098156D403C00337B26 /* steptest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = steptest.c; sourceTree = ""; }; - 31EEABF5156AAF7C00714D05 /* mpsi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpsi.c; sourceTree = ""; }; - 31EEABFB156AAF9D00714D05 /* libmps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmps.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 31EEAC01156AB21B00714D05 /* mpm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpm.c; sourceTree = ""; }; - 31EEAC03156AB23A00714D05 /* arenavm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arenavm.c; sourceTree = ""; }; - 31EEAC05156AB27B00714D05 /* arena.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arena.c; sourceTree = ""; }; - 31EEAC06156AB27B00714D05 /* arenacl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arenacl.c; sourceTree = ""; }; - 31EEAC07156AB27B00714D05 /* global.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = global.c; sourceTree = ""; }; - 31EEAC08156AB27B00714D05 /* locus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locus.c; sourceTree = ""; }; - 31EEAC09156AB27B00714D05 /* pool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pool.c; sourceTree = ""; }; - 31EEAC0A156AB27B00714D05 /* poolabs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolabs.c; sourceTree = ""; }; - 31EEAC0B156AB27B00714D05 /* protocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = protocol.c; sourceTree = ""; }; - 31EEAC0C156AB27B00714D05 /* reserv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reserv.c; sourceTree = ""; }; - 31EEAC0D156AB27B00714D05 /* tract.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tract.c; sourceTree = ""; }; - 31EEAC0E156AB27B00714D05 /* walk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = walk.c; sourceTree = ""; }; - 31EEAC19156AB2B200714D05 /* buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = buffer.c; sourceTree = ""; }; - 31EEAC1A156AB2B200714D05 /* format.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = format.c; sourceTree = ""; }; - 31EEAC1B156AB2B200714D05 /* ref.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ref.c; sourceTree = ""; }; - 31EEAC1C156AB2B200714D05 /* root.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = root.c; sourceTree = ""; }; - 31EEAC1D156AB2B200714D05 /* seg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = seg.c; sourceTree = ""; }; - 31EEAC1E156AB2B200714D05 /* trace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = trace.c; sourceTree = ""; }; - 31EEAC1F156AB2B200714D05 /* traceanc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = traceanc.c; sourceTree = ""; }; - 31EEAC27156AB2F200714D05 /* bt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bt.c; sourceTree = ""; }; - 31EEAC28156AB2F200714D05 /* dbgpool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dbgpool.c; sourceTree = ""; }; - 31EEAC29156AB2F200714D05 /* dbgpooli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dbgpooli.c; sourceTree = ""; }; - 31EEAC2A156AB2F200714D05 /* event.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = event.c; sourceTree = ""; }; - 31EEAC2B156AB2F200714D05 /* ld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ld.c; sourceTree = ""; }; - 31EEAC2C156AB2F200714D05 /* message.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = message.c; sourceTree = ""; }; - 31EEAC2D156AB2F200714D05 /* poolmfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolmfs.c; sourceTree = ""; }; - 31EEAC2E156AB2F200714D05 /* poolmrg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolmrg.c; sourceTree = ""; }; - 31EEAC2F156AB2F200714D05 /* poolmv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolmv.c; sourceTree = ""; }; - 31EEAC30156AB2F200714D05 /* ring.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ring.c; sourceTree = ""; }; - 31EEAC31156AB2F200714D05 /* sac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sac.c; sourceTree = ""; }; - 31EEAC32156AB2F200714D05 /* shield.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = shield.c; sourceTree = ""; }; - 31EEAC3F156AB32500714D05 /* boot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = boot.c; sourceTree = ""; }; - 31EEAC40156AB32500714D05 /* cbs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cbs.c; sourceTree = ""; }; - 31EEAC41156AB32500714D05 /* diag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = diag.c; sourceTree = ""; }; - 31EEAC42156AB32500714D05 /* meter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = meter.c; sourceTree = ""; }; - 31EEAC43156AB32500714D05 /* splay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = splay.c; sourceTree = ""; }; - 31EEAC44156AB32500714D05 /* version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = version.c; sourceTree = ""; }; - 31EEAC4C156AB3B000714D05 /* lockix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lockix.c; sourceTree = ""; }; - 31EEAC4E156AB3E300714D05 /* prmcan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prmcan.c; sourceTree = ""; }; - 31EEAC4F156AB3E300714D05 /* protix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = protix.c; sourceTree = ""; }; - 31EEAC50156AB3E300714D05 /* protsgix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = protsgix.c; sourceTree = ""; }; - 31EEAC52156AB3E300714D05 /* than.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = than.c; sourceTree = ""; }; - 31EEAC53156AB3E300714D05 /* vmix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vmix.c; sourceTree = ""; }; - 31EEAC5B156AB41900714D05 /* poolamc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolamc.c; sourceTree = ""; }; - 31EEAC5D156AB43F00714D05 /* poolsnc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolsnc.c; sourceTree = ""; }; - 31EEAC5F156AB44D00714D05 /* poolmvff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolmvff.c; sourceTree = ""; }; - 31EEAC65156AB52600714D05 /* mpmss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mpmss; sourceTree = BUILT_PRODUCTS_DIR; }; - 31EEAC70156AB56000714D05 /* mpsioan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpsioan.c; sourceTree = ""; }; - 31EEAC71156AB56000714D05 /* mpsliban.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpsliban.c; sourceTree = ""; }; - 31EEAC74156AB58E00714D05 /* mpmss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpmss.c; sourceTree = SOURCE_ROOT; }; - 31EEAC9E156AB73400714D05 /* testlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testlib.c; sourceTree = ""; }; - 31EEACA7156AB79800714D05 /* span.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = span.c; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 3104AFB0156D357B000A585A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104AFC2156D35B2000A585A /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104AFC5156D35E2000A585A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104AFD4156D35F7000A585A /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104AFDA156D3681000A585A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104AFE9156D3690000A585A /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104B006156D38F3000A585A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104B018156D3953000A585A /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104B01F156D39D4000A585A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104B02E156D39E2000A585A /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104B03A156D3AD7000A585A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60008156D3C7400337B26 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A58D156E913C001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A59B156E914B001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A5A4156E92C0001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A5B1156E92C8001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A5BA156E9315001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A5C8156E9322001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A5D3156E93A0001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A5E4156E93AE001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A5EC156E93E7001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A5FA156E93F3001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A602156E9430001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A617156E946B001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A619156E9485001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A626156E948C001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A630156E94DB001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A640156E94F0001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A649156E9596001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A673156E95F6001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A65F156E95D9001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A670156E95F2001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A679156E9668001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A6DD156E9A0F001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A692156E971B001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A6A3156E972D001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A6A9156E9759001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A6BE156E9771001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A6C3156E9815001E0AA3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A6D7156E9923001E0AA3 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3124CAB5156BE3EC00753214 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3124CAC4156BE40D00753214 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3124CAD1156BE64A00753214 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3124CAE1156BE67000753214 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3124CAE8156BE7F300753214 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3124CAFC156BE82900753214 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D6000A156D3CB200337B26 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60019156D3CCC00337B26 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D60024156D3D3E00337B26 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60035156D3DF300337B26 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D6003B156D3EC700337B26 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60049156D3ED200337B26 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D60051156D3F3500337B26 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60060156D3F5000337B26 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D6006E156D3FBC00337B26 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60083156D3FDB00337B26 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D60089156D402900337B26 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D6009B156D404400337B26 /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31EEABF8156AAF9D00714D05 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31EEAC62156AB52600714D05 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3150AE53156ABA2500A6E22A /* libmps.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 3114A647156E956C001E0AA3 /* Mysterious */ = { - isa = PBXGroup; - children = ( - 3114A68E156E96B6001E0AA3 /* poolmv2.c */, - 3114A645156E9525001E0AA3 /* abq.c */, - ); - name = Mysterious; - sourceTree = ""; - }; - 3114A6D6156E9846001E0AA3 /* Tools */ = { - isa = PBXGroup; - children = ( - 3114A6D8156E9942001E0AA3 /* eventcnv */, - ); - name = Tools; - sourceTree = ""; - }; - 3114A6D8156E9942001E0AA3 /* eventcnv */ = { - isa = PBXGroup; - children = ( - 3114A6D9156E9950001E0AA3 /* eventpro.c */, - 3114A6D0156E9829001E0AA3 /* eventcnv.c */, - ); - name = eventcnv; - sourceTree = ""; - }; - 3124CAB3156BE1B700753214 /* Tests */ = { - isa = PBXGroup; - children = ( - 3114A63D156E94EA001E0AA3 /* abqtest.c */, - 3124CAF5156BE81100753214 /* amcss.c */, - 3104AFEB156D36A5000A585A /* amcsshe.c */, - 3104B015156D390B000A585A /* amsss.c */, - 3104B02F156D39F2000A585A /* amssshe.c */, - 3104AFBE156D3591000A585A /* apss.c */, - 3114A5FB156E93FC001E0AA3 /* arenacv.c */, - 3124CAC2156BE40100753214 /* awlut.c */, - 31D60017156D3CC300337B26 /* awluthe.c */, - 3114A66C156E95EB001E0AA3 /* btcv.c */, - 3114A613156E944A001E0AA3 /* bttest.c */, - 3114A656156E95A6001E0AA3 /* cbstest.c */, - 3114A5CD156E9369001E0AA3 /* finalcv.c */, - 3114A5E5156E93B9001E0AA3 /* finaltest.c */, - 3124CAC6156BE48D00753214 /* fmtdy.c */, - 3124CAC7156BE48D00753214 /* fmtdytst.c */, - 3124CAE4156BE6D500753214 /* fmthe.c */, - 3124CACC156BE4C200753214 /* fmtno.c */, - 31D60036156D3E0200337B26 /* lockcov.c */, - 3114A5A1156E9168001E0AA3 /* locv.c */, - 3114A69F156E9725001E0AA3 /* messtest.c */, - 31EEAC74156AB58E00714D05 /* mpmss.c */, - 3124CADE156BE65900753214 /* mpsicv.c */, - 3114A686156E9674001E0AA3 /* mv2test.c */, - 31D6004A156D3EE600337B26 /* poolncv.c */, - 3114A5B7156E92F0001E0AA3 /* qs.c */, - 3104AFD6156D3602000A585A /* sacss.c */, - 31D60006156D3C5F00337B26 /* segsmss.c */, - 31D60098156D403C00337B26 /* steptest.c */, - 3114A628156E949A001E0AA3 /* teletest.c */, - 31EEAC9E156AB73400714D05 /* testlib.c */, - 3114A6BA156E9768001E0AA3 /* walkt0.c */, - 31D6005E156D3F4A00337B26 /* zcoll.c */, - 31D6007B156D3FCC00337B26 /* zmess.c */, - ); - name = Tests; - sourceTree = ""; - }; - 31A47BA6156C1E620039B1C2 /* I3 */ = { - isa = PBXGroup; - children = ( - 31A47BA5156C1E5E0039B1C2 /* ssixi3.c */, - ); - name = I3; - sourceTree = ""; - }; - 31A47BA7156C1E6E0039B1C2 /* I6 */ = { - isa = PBXGroup; - children = ( - 3104AFA5156D27E7000A585A /* ssixi6.c */, - ); - name = I6; - sourceTree = ""; - }; - 31A47BA8156C1E930039B1C2 /* MPS */ = { - isa = PBXGroup; - children = ( - 31A47BA3156C1E130039B1C2 /* mps.c */, - 31EEABF4156AAF6500714D05 /* MPM Core */, - 31EEAC5A156AB40800714D05 /* Extra pools */, - 31EEAC4B156AB39C00714D05 /* Platform */, - 31EEAC6F156AB54300714D05 /* ANSI Plinth */, - ); - name = MPS; - sourceTree = ""; - }; - 31EEABD8156AAE9E00714D05 = { - isa = PBXGroup; - children = ( - 3114A6D6156E9846001E0AA3 /* Tools */, - 3114A647156E956C001E0AA3 /* Mysterious */, - 31A47BA8156C1E930039B1C2 /* MPS */, - 3124CAB3156BE1B700753214 /* Tests */, - 31EEABEF156AAF5C00714D05 /* Products */, - ); - sourceTree = ""; - }; - 31EEABEF156AAF5C00714D05 /* Products */ = { - isa = PBXGroup; - children = ( - 31EEABFB156AAF9D00714D05 /* libmps.a */, - 31EEAC65156AB52600714D05 /* mpmss */, - 3124CAB8156BE3EC00753214 /* awlut */, - 3124CAD4156BE64A00753214 /* mpsicv */, - 3124CAEB156BE7F300753214 /* amcss */, - 3104AFB3156D357B000A585A /* apss */, - 3104AFC8156D35E2000A585A /* sacss */, - 3104AFDD156D3681000A585A /* amcsshe */, - 3104B009156D38F3000A585A /* amsss */, - 3104B022156D39D4000A585A /* amssshe */, - 3104B03D156D3AD7000A585A /* segsmss */, - 31D6000D156D3CB200337B26 /* awluthe */, - 31D60027156D3D3E00337B26 /* lockcov */, - 31D6003E156D3EC700337B26 /* poolncv */, - 31D60054156D3F3500337B26 /* zcoll */, - 31D60071156D3FBC00337B26 /* zmess */, - 31D6008C156D402900337B26 /* steptest */, - 3114A590156E913C001E0AA3 /* locv */, - 3114A5A7156E92C0001E0AA3 /* qs */, - 3114A5BD156E9315001E0AA3 /* finalcv */, - 3114A5D6156E93A0001E0AA3 /* finaltest */, - 3114A5EF156E93E7001E0AA3 /* arenacv */, - 3114A605156E9430001E0AA3 /* bttest */, - 3114A61C156E9485001E0AA3 /* teletest */, - 3114A633156E94DB001E0AA3 /* abqtest */, - 3114A64C156E9596001E0AA3 /* cbstest */, - 3114A662156E95D9001E0AA3 /* btcv */, - 3114A67C156E9668001E0AA3 /* mv2test */, - 3114A695156E971B001E0AA3 /* messtest */, - 3114A6AC156E9759001E0AA3 /* walkt0 */, - 3114A6C6156E9815001E0AA3 /* eventcnv */, - ); - name = Products; - sourceTree = ""; - }; - 31EEABF4156AAF6500714D05 /* MPM Core */ = { - isa = PBXGroup; - children = ( - 31EEAC05156AB27B00714D05 /* arena.c */, - 31EEAC06156AB27B00714D05 /* arenacl.c */, - 31EEAC03156AB23A00714D05 /* arenavm.c */, - 31EEAC3F156AB32500714D05 /* boot.c */, - 31EEAC27156AB2F200714D05 /* bt.c */, - 31EEAC19156AB2B200714D05 /* buffer.c */, - 31EEAC40156AB32500714D05 /* cbs.c */, - 31EEAC28156AB2F200714D05 /* dbgpool.c */, - 31EEAC29156AB2F200714D05 /* dbgpooli.c */, - 31EEAC41156AB32500714D05 /* diag.c */, - 31EEAC2A156AB2F200714D05 /* event.c */, - 31EEAC1A156AB2B200714D05 /* format.c */, - 31EEAC07156AB27B00714D05 /* global.c */, - 31EEAC2B156AB2F200714D05 /* ld.c */, - 31EEAC08156AB27B00714D05 /* locus.c */, - 31EEAC2C156AB2F200714D05 /* message.c */, - 31EEAC42156AB32500714D05 /* meter.c */, - 31EEAC01156AB21B00714D05 /* mpm.c */, - 31EEABF5156AAF7C00714D05 /* mpsi.c */, - 31EEAC09156AB27B00714D05 /* pool.c */, - 31EEAC0A156AB27B00714D05 /* poolabs.c */, - 31EEAC2D156AB2F200714D05 /* poolmfs.c */, - 31EEAC2E156AB2F200714D05 /* poolmrg.c */, - 31EEAC2F156AB2F200714D05 /* poolmv.c */, - 31EEAC0B156AB27B00714D05 /* protocol.c */, - 31EEAC1B156AB2B200714D05 /* ref.c */, - 31EEAC0C156AB27B00714D05 /* reserv.c */, - 31EEAC30156AB2F200714D05 /* ring.c */, - 31EEAC1C156AB2B200714D05 /* root.c */, - 31EEAC31156AB2F200714D05 /* sac.c */, - 31EEAC1D156AB2B200714D05 /* seg.c */, - 31EEAC32156AB2F200714D05 /* shield.c */, - 31EEAC43156AB32500714D05 /* splay.c */, - 31EEAC1E156AB2B200714D05 /* trace.c */, - 31EEAC1F156AB2B200714D05 /* traceanc.c */, - 31EEAC0D156AB27B00714D05 /* tract.c */, - 31EEAC44156AB32500714D05 /* version.c */, - 31EEAC0E156AB27B00714D05 /* walk.c */, - ); - name = "MPM Core"; - sourceTree = ""; - }; - 31EEAC4B156AB39C00714D05 /* Platform */ = { - isa = PBXGroup; - children = ( - 31A47BA7156C1E6E0039B1C2 /* I6 */, - 31A47BA6156C1E620039B1C2 /* I3 */, - 31EEAC4C156AB3B000714D05 /* lockix.c */, - 31EEAC4E156AB3E300714D05 /* prmcan.c */, - 31EEAC4F156AB3E300714D05 /* protix.c */, - 31EEAC50156AB3E300714D05 /* protsgix.c */, - 31EEACA7156AB79800714D05 /* span.c */, - 31EEAC52156AB3E300714D05 /* than.c */, - 31EEAC53156AB3E300714D05 /* vmix.c */, - ); - name = Platform; - sourceTree = ""; - }; - 31EEAC5A156AB40800714D05 /* Extra pools */ = { - isa = PBXGroup; - children = ( - 31EEAC5B156AB41900714D05 /* poolamc.c */, - 3124CACE156BE4CF00753214 /* poolawl.c */, - 3124CACA156BE4A300753214 /* poollo.c */, - 31EEAC5F156AB44D00714D05 /* poolmvff.c */, - 31EEAC5D156AB43F00714D05 /* poolsnc.c */, - ); - name = "Extra pools"; - sourceTree = ""; - }; - 31EEAC6F156AB54300714D05 /* ANSI Plinth */ = { - isa = PBXGroup; - children = ( - 31EEAC70156AB56000714D05 /* mpsioan.c */, - 31EEAC71156AB56000714D05 /* mpsliban.c */, - ); - name = "ANSI Plinth"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 31EEABF9156AAF9D00714D05 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 3104AFB2156D357B000A585A /* apss */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3104AFBC156D357B000A585A /* Build configuration list for PBXNativeTarget "apss" */; - buildPhases = ( - 3104AFAF156D357B000A585A /* Sources */, - 3104AFB0156D357B000A585A /* Frameworks */, - 3104AFB1156D357B000A585A /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3104AFC1156D35AE000A585A /* PBXTargetDependency */, - ); - name = apss; - productName = apss; - productReference = 3104AFB3156D357B000A585A /* apss */; - productType = "com.apple.product-type.tool"; - }; - 3104AFC7156D35E2000A585A /* sacss */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3104AFCF156D35E2000A585A /* Build configuration list for PBXNativeTarget "sacss" */; - buildPhases = ( - 3104AFC4156D35E2000A585A /* Sources */, - 3104AFC5156D35E2000A585A /* Frameworks */, - 3104AFC6156D35E2000A585A /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3104AFD3156D35F2000A585A /* PBXTargetDependency */, - ); - name = sacss; - productName = sacss; - productReference = 3104AFC8156D35E2000A585A /* sacss */; - productType = "com.apple.product-type.tool"; - }; - 3104AFDC156D3681000A585A /* amcsshe */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3104AFE4156D3682000A585A /* Build configuration list for PBXNativeTarget "amcsshe" */; - buildPhases = ( - 3104AFD9156D3681000A585A /* Sources */, - 3104AFDA156D3681000A585A /* Frameworks */, - 3104AFDB156D3681000A585A /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3104AFE8156D368D000A585A /* PBXTargetDependency */, - ); - name = amcsshe; - productName = amcsshe; - productReference = 3104AFDD156D3681000A585A /* amcsshe */; - productType = "com.apple.product-type.tool"; - }; - 3104B008156D38F3000A585A /* amsss */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3104B010156D38F3000A585A /* Build configuration list for PBXNativeTarget "amsss" */; - buildPhases = ( - 3104B005156D38F3000A585A /* Sources */, - 3104B006156D38F3000A585A /* Frameworks */, - 3104B007156D38F3000A585A /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3104B014156D38FA000A585A /* PBXTargetDependency */, - ); - name = amsss; - productName = amsss; - productReference = 3104B009156D38F3000A585A /* amsss */; - productType = "com.apple.product-type.tool"; - }; - 3104B021156D39D4000A585A /* amssshe */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3104B029156D39D4000A585A /* Build configuration list for PBXNativeTarget "amssshe" */; - buildPhases = ( - 3104B01E156D39D4000A585A /* Sources */, - 3104B01F156D39D4000A585A /* Frameworks */, - 3104B020156D39D4000A585A /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3104B038156D3A56000A585A /* PBXTargetDependency */, - ); - name = amssshe; - productName = amssshe; - productReference = 3104B022156D39D4000A585A /* amssshe */; - productType = "com.apple.product-type.tool"; - }; - 3104B03C156D3AD7000A585A /* segsmss */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3104B044156D3AD8000A585A /* Build configuration list for PBXNativeTarget "segsmss" */; - buildPhases = ( - 3104B039156D3AD7000A585A /* Sources */, - 3104B03A156D3AD7000A585A /* Frameworks */, - 3104B03B156D3AD7000A585A /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3104B048156D3ADE000A585A /* PBXTargetDependency */, - ); - name = segsmss; - productName = segsmss; - productReference = 3104B03D156D3AD7000A585A /* segsmss */; - productType = "com.apple.product-type.tool"; - }; - 3114A58F156E913C001E0AA3 /* locv */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A599156E913C001E0AA3 /* Build configuration list for PBXNativeTarget "locv" */; - buildPhases = ( - 3114A58C156E913C001E0AA3 /* Sources */, - 3114A58D156E913C001E0AA3 /* Frameworks */, - 3114A58E156E913C001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A59E156E9156001E0AA3 /* PBXTargetDependency */, - ); - name = locv; - productName = locv; - productReference = 3114A590156E913C001E0AA3 /* locv */; - productType = "com.apple.product-type.tool"; - }; - 3114A5A6156E92C0001E0AA3 /* qs */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A5AE156E92C0001E0AA3 /* Build configuration list for PBXNativeTarget "qs" */; - buildPhases = ( - 3114A5A3156E92C0001E0AA3 /* Sources */, - 3114A5A4156E92C0001E0AA3 /* Frameworks */, - 3114A5A5156E92C0001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A5B4156E92D8001E0AA3 /* PBXTargetDependency */, - ); - name = qs; - productName = qs; - productReference = 3114A5A7156E92C0001E0AA3 /* qs */; - productType = "com.apple.product-type.tool"; - }; - 3114A5BC156E9315001E0AA3 /* finalcv */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A5C4156E9315001E0AA3 /* Build configuration list for PBXNativeTarget "finalcv" */; - buildPhases = ( - 3114A5B9156E9315001E0AA3 /* Sources */, - 3114A5BA156E9315001E0AA3 /* Frameworks */, - 3114A5BB156E9315001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A5CA156E9328001E0AA3 /* PBXTargetDependency */, - ); - name = finalcv; - productName = finalcv; - productReference = 3114A5BD156E9315001E0AA3 /* finalcv */; - productType = "com.apple.product-type.tool"; - }; - 3114A5D5156E93A0001E0AA3 /* finaltest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A5DD156E93A0001E0AA3 /* Build configuration list for PBXNativeTarget "finaltest" */; - buildPhases = ( - 3114A5D2156E93A0001E0AA3 /* Sources */, - 3114A5D3156E93A0001E0AA3 /* Frameworks */, - 3114A5D4156E93A0001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A5E8156E93BF001E0AA3 /* PBXTargetDependency */, - ); - name = finaltest; - productName = finaltest; - productReference = 3114A5D6156E93A0001E0AA3 /* finaltest */; - productType = "com.apple.product-type.tool"; - }; - 3114A5EE156E93E7001E0AA3 /* arenacv */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A5F6156E93E7001E0AA3 /* Build configuration list for PBXNativeTarget "arenacv" */; - buildPhases = ( - 3114A5EB156E93E7001E0AA3 /* Sources */, - 3114A5EC156E93E7001E0AA3 /* Frameworks */, - 3114A5ED156E93E7001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A5FE156E9406001E0AA3 /* PBXTargetDependency */, - ); - name = arenacv; - productName = arenacv; - productReference = 3114A5EF156E93E7001E0AA3 /* arenacv */; - productType = "com.apple.product-type.tool"; - }; - 3114A604156E9430001E0AA3 /* bttest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A60C156E9430001E0AA3 /* Build configuration list for PBXNativeTarget "bttest" */; - buildPhases = ( - 3114A601156E9430001E0AA3 /* Sources */, - 3114A602156E9430001E0AA3 /* Frameworks */, - 3114A603156E9430001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A610156E9438001E0AA3 /* PBXTargetDependency */, - ); - name = bttest; - productName = bttest; - productReference = 3114A605156E9430001E0AA3 /* bttest */; - productType = "com.apple.product-type.tool"; - }; - 3114A61B156E9485001E0AA3 /* teletest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A623156E9485001E0AA3 /* Build configuration list for PBXNativeTarget "teletest" */; - buildPhases = ( - 3114A618156E9485001E0AA3 /* Sources */, - 3114A619156E9485001E0AA3 /* Frameworks */, - 3114A61A156E9485001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A62C156E94A6001E0AA3 /* PBXTargetDependency */, - ); - name = teletest; - productName = teletest; - productReference = 3114A61C156E9485001E0AA3 /* teletest */; - productType = "com.apple.product-type.tool"; - }; - 3114A632156E94DB001E0AA3 /* abqtest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A63A156E94DB001E0AA3 /* Build configuration list for PBXNativeTarget "abqtest" */; - buildPhases = ( - 3114A62F156E94DB001E0AA3 /* Sources */, - 3114A630156E94DB001E0AA3 /* Frameworks */, - 3114A631156E94DB001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A642156E94F8001E0AA3 /* PBXTargetDependency */, - ); - name = abqtest; - productName = abqtest; - productReference = 3114A633156E94DB001E0AA3 /* abqtest */; - productType = "com.apple.product-type.tool"; - }; - 3114A64B156E9596001E0AA3 /* cbstest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A653156E9596001E0AA3 /* Build configuration list for PBXNativeTarget "cbstest" */; - buildPhases = ( - 3114A648156E9596001E0AA3 /* Sources */, - 3114A649156E9596001E0AA3 /* Frameworks */, - 3114A64A156E9596001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A659156E95B1001E0AA3 /* PBXTargetDependency */, - ); - name = cbstest; - productName = cbstest; - productReference = 3114A64C156E9596001E0AA3 /* cbstest */; - productType = "com.apple.product-type.tool"; - }; - 3114A661156E95D9001E0AA3 /* btcv */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A669156E95D9001E0AA3 /* Build configuration list for PBXNativeTarget "btcv" */; - buildPhases = ( - 3114A65E156E95D9001E0AA3 /* Sources */, - 3114A65F156E95D9001E0AA3 /* Frameworks */, - 3114A660156E95D9001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A675156E9619001E0AA3 /* PBXTargetDependency */, - ); - name = btcv; - productName = btcv; - productReference = 3114A662156E95D9001E0AA3 /* btcv */; - productType = "com.apple.product-type.tool"; - }; - 3114A67B156E9668001E0AA3 /* mv2test */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A683156E9669001E0AA3 /* Build configuration list for PBXNativeTarget "mv2test" */; - buildPhases = ( - 3114A678156E9668001E0AA3 /* Sources */, - 3114A679156E9668001E0AA3 /* Frameworks */, - 3114A67A156E9668001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A68B156E9682001E0AA3 /* PBXTargetDependency */, - ); - name = mv2test; - productName = mv2test; - productReference = 3114A67C156E9668001E0AA3 /* mv2test */; - productType = "com.apple.product-type.tool"; - }; - 3114A694156E971B001E0AA3 /* messtest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A69C156E971B001E0AA3 /* Build configuration list for PBXNativeTarget "messtest" */; - buildPhases = ( - 3114A691156E971B001E0AA3 /* Sources */, - 3114A692156E971B001E0AA3 /* Frameworks */, - 3114A693156E971B001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A6A5156E9735001E0AA3 /* PBXTargetDependency */, - ); - name = messtest; - productName = messtest; - productReference = 3114A695156E971B001E0AA3 /* messtest */; - productType = "com.apple.product-type.tool"; - }; - 3114A6AB156E9759001E0AA3 /* walkt0 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A6B3156E9759001E0AA3 /* Build configuration list for PBXNativeTarget "walkt0" */; - buildPhases = ( - 3114A6A8156E9759001E0AA3 /* Sources */, - 3114A6A9156E9759001E0AA3 /* Frameworks */, - 3114A6AA156E9759001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A6B7156E975E001E0AA3 /* PBXTargetDependency */, - ); - name = walkt0; - productName = walkt0; - productReference = 3114A6AC156E9759001E0AA3 /* walkt0 */; - productType = "com.apple.product-type.tool"; - }; - 3114A6C5156E9815001E0AA3 /* eventcnv */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3114A6CD156E9815001E0AA3 /* Build configuration list for PBXNativeTarget "eventcnv" */; - buildPhases = ( - 3114A6C2156E9815001E0AA3 /* Sources */, - 3114A6C3156E9815001E0AA3 /* Frameworks */, - 3114A6C4156E9815001E0AA3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 3114A6D3156E9834001E0AA3 /* PBXTargetDependency */, - ); - name = eventcnv; - productName = eventcnv; - productReference = 3114A6C6156E9815001E0AA3 /* eventcnv */; - productType = "com.apple.product-type.tool"; - }; - 3124CAB7156BE3EC00753214 /* awlut */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3124CABF156BE3EC00753214 /* Build configuration list for PBXNativeTarget "awlut" */; - buildPhases = ( - 3124CAB4156BE3EC00753214 /* Sources */, - 3124CAB5156BE3EC00753214 /* Frameworks */, - 3124CAB6156BE3EC00753214 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31A47BAC156C21120039B1C2 /* PBXTargetDependency */, - ); - name = awlut; - productName = awlut; - productReference = 3124CAB8156BE3EC00753214 /* awlut */; - productType = "com.apple.product-type.tool"; - }; - 3124CAD3156BE64A00753214 /* mpsicv */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3124CADB156BE64A00753214 /* Build configuration list for PBXNativeTarget "mpsicv" */; - buildPhases = ( - 3124CAD0156BE64A00753214 /* Sources */, - 3124CAD1156BE64A00753214 /* Frameworks */, - 3124CAD2156BE64A00753214 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31A47BAE156C21170039B1C2 /* PBXTargetDependency */, - ); - name = mpsicv; - productName = mpsicv; - productReference = 3124CAD4156BE64A00753214 /* mpsicv */; - productType = "com.apple.product-type.tool"; - }; - 3124CAEA156BE7F300753214 /* amcss */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3124CAF2156BE7F300753214 /* Build configuration list for PBXNativeTarget "amcss" */; - buildPhases = ( - 3124CAE7156BE7F300753214 /* Sources */, - 3124CAE8156BE7F300753214 /* Frameworks */, - 3124CAE9156BE7F300753214 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31A47BB0156C211B0039B1C2 /* PBXTargetDependency */, - ); - name = amcss; - productName = amcss; - productReference = 3124CAEB156BE7F300753214 /* amcss */; - productType = "com.apple.product-type.tool"; - }; - 31D6000C156D3CB200337B26 /* awluthe */ = { - isa = PBXNativeTarget; - buildConfigurationList = 31D60014156D3CB200337B26 /* Build configuration list for PBXNativeTarget "awluthe" */; - buildPhases = ( - 31D60009156D3CB200337B26 /* Sources */, - 31D6000A156D3CB200337B26 /* Frameworks */, - 31D6000B156D3CB200337B26 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31D60020156D3CEC00337B26 /* PBXTargetDependency */, - ); - name = awluthe; - productName = awluthe; - productReference = 31D6000D156D3CB200337B26 /* awluthe */; - productType = "com.apple.product-type.tool"; - }; - 31D60026156D3D3E00337B26 /* lockcov */ = { - isa = PBXNativeTarget; - buildConfigurationList = 31D6002E156D3D3F00337B26 /* Build configuration list for PBXNativeTarget "lockcov" */; - buildPhases = ( - 31D60023156D3D3E00337B26 /* Sources */, - 31D60024156D3D3E00337B26 /* Frameworks */, - 31D60025156D3D3E00337B26 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31D60032156D3D5300337B26 /* PBXTargetDependency */, - ); - name = lockcov; - productName = lockcov; - productReference = 31D60027156D3D3E00337B26 /* lockcov */; - productType = "com.apple.product-type.tool"; - }; - 31D6003D156D3EC700337B26 /* poolncv */ = { - isa = PBXNativeTarget; - buildConfigurationList = 31D60045156D3EC700337B26 /* Build configuration list for PBXNativeTarget "poolncv" */; - buildPhases = ( - 31D6003A156D3EC700337B26 /* Sources */, - 31D6003B156D3EC700337B26 /* Frameworks */, - 31D6003C156D3EC700337B26 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31D6004D156D3EF000337B26 /* PBXTargetDependency */, - ); - name = poolncv; - productName = poolncv; - productReference = 31D6003E156D3EC700337B26 /* poolncv */; - productType = "com.apple.product-type.tool"; - }; - 31D60053156D3F3500337B26 /* zcoll */ = { - isa = PBXNativeTarget; - buildConfigurationList = 31D6005B156D3F3500337B26 /* Build configuration list for PBXNativeTarget "zcoll" */; - buildPhases = ( - 31D60050156D3F3500337B26 /* Sources */, - 31D60051156D3F3500337B26 /* Frameworks */, - 31D60052156D3F3500337B26 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31D60065156D3F5F00337B26 /* PBXTargetDependency */, - ); - name = zcoll; - productName = zcoll; - productReference = 31D60054156D3F3500337B26 /* zcoll */; - productType = "com.apple.product-type.tool"; - }; - 31D60070156D3FBC00337B26 /* zmess */ = { - isa = PBXNativeTarget; - buildConfigurationList = 31D60078156D3FBC00337B26 /* Build configuration list for PBXNativeTarget "zmess" */; - buildPhases = ( - 31D6006D156D3FBC00337B26 /* Sources */, - 31D6006E156D3FBC00337B26 /* Frameworks */, - 31D6006F156D3FBC00337B26 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31D60085156D3FE100337B26 /* PBXTargetDependency */, - ); - name = zmess; - productName = zmess; - productReference = 31D60071156D3FBC00337B26 /* zmess */; - productType = "com.apple.product-type.tool"; - }; - 31D6008B156D402900337B26 /* steptest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 31D60093156D402900337B26 /* Build configuration list for PBXNativeTarget "steptest" */; - buildPhases = ( - 31D60088156D402900337B26 /* Sources */, - 31D60089156D402900337B26 /* Frameworks */, - 31D6008A156D402900337B26 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31D60097156D403500337B26 /* PBXTargetDependency */, - ); - name = steptest; - productName = steptest; - productReference = 31D6008C156D402900337B26 /* steptest */; - productType = "com.apple.product-type.tool"; - }; - 31EEABFA156AAF9D00714D05 /* mps */ = { - isa = PBXNativeTarget; - buildConfigurationList = 31EEABFC156AAF9D00714D05 /* Build configuration list for PBXNativeTarget "mps" */; - buildPhases = ( - 31EEABF7156AAF9D00714D05 /* Sources */, - 31EEABF8156AAF9D00714D05 /* Frameworks */, - 31EEABF9156AAF9D00714D05 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = mps; - productName = mps; - productReference = 31EEABFB156AAF9D00714D05 /* libmps.a */; - productType = "com.apple.product-type.library.static"; - }; - 31EEAC64156AB52600714D05 /* mpmss */ = { - isa = PBXNativeTarget; - buildConfigurationList = 31EEAC6C156AB52600714D05 /* Build configuration list for PBXNativeTarget "mpmss" */; - buildPhases = ( - 31EEAC61156AB52600714D05 /* Sources */, - 31EEAC62156AB52600714D05 /* Frameworks */, - 31EEAC63156AB52600714D05 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 31A47BAA156C210D0039B1C2 /* PBXTargetDependency */, - ); - name = mpmss; - productName = mpmss; - productReference = 31EEAC65156AB52600714D05 /* mpmss */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 31EEABDA156AAE9E00714D05 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0440; - }; - buildConfigurationList = 31EEABDD156AAE9E00714D05 /* Build configuration list for PBXProject "mps" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 31EEABD8156AAE9E00714D05; - productRefGroup = 31EEABEF156AAF5C00714D05 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 3104AFF1156D37A0000A585A /* all */, - 31EEABFA156AAF9D00714D05 /* mps */, - 3124CAEA156BE7F300753214 /* amcss */, - 3104AFB2156D357B000A585A /* apss */, - 3124CAB7156BE3EC00753214 /* awlut */, - 31EEAC64156AB52600714D05 /* mpmss */, - 3124CAD3156BE64A00753214 /* mpsicv */, - 3104AFC7156D35E2000A585A /* sacss */, - 3104AFDC156D3681000A585A /* amcsshe */, - 3104B008156D38F3000A585A /* amsss */, - 3104B021156D39D4000A585A /* amssshe */, - 3104B03C156D3AD7000A585A /* segsmss */, - 31D6000C156D3CB200337B26 /* awluthe */, - 31D60026156D3D3E00337B26 /* lockcov */, - 31D6003D156D3EC700337B26 /* poolncv */, - 31D60053156D3F3500337B26 /* zcoll */, - 31D60070156D3FBC00337B26 /* zmess */, - 31D6008B156D402900337B26 /* steptest */, - 3114A58F156E913C001E0AA3 /* locv */, - 3114A5A6156E92C0001E0AA3 /* qs */, - 3114A5BC156E9315001E0AA3 /* finalcv */, - 3114A5D5156E93A0001E0AA3 /* finaltest */, - 3114A5EE156E93E7001E0AA3 /* arenacv */, - 3114A604156E9430001E0AA3 /* bttest */, - 3114A61B156E9485001E0AA3 /* teletest */, - 3114A632156E94DB001E0AA3 /* abqtest */, - 3114A64B156E9596001E0AA3 /* cbstest */, - 3114A661156E95D9001E0AA3 /* btcv */, - 3114A67B156E9668001E0AA3 /* mv2test */, - 3114A694156E971B001E0AA3 /* messtest */, - 3114A6AB156E9759001E0AA3 /* walkt0 */, - 3114A6C5156E9815001E0AA3 /* eventcnv */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 3104AFAF156D357B000A585A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104AFBF156D3591000A585A /* apss.c in Sources */, - 3104AFC3156D35C3000A585A /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104AFC4156D35E2000A585A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104AFD5156D35FB000A585A /* testlib.c in Sources */, - 3104AFD8156D3607000A585A /* sacss.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104AFD9156D3681000A585A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104AFEA156D3697000A585A /* testlib.c in Sources */, - 3104AFEC156D36A5000A585A /* amcsshe.c in Sources */, - 3104AFED156D374A000A585A /* fmthe.c in Sources */, - 3104AFEE156D374D000A585A /* fmtno.c in Sources */, - 3104AFEF156D3753000A585A /* fmtdy.c in Sources */, - 3104AFF0156D3756000A585A /* fmtdytst.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104B005156D38F3000A585A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104B016156D390B000A585A /* amsss.c in Sources */, - 3104B017156D3915000A585A /* testlib.c in Sources */, - 3104B019156D3960000A585A /* fmtdy.c in Sources */, - 3104B01A156D396E000A585A /* fmtdytst.c in Sources */, - 3104B01B156D3973000A585A /* fmtno.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104B01E156D39D4000A585A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104B031156D39FD000A585A /* fmthe.c in Sources */, - 3104B032156D3A00000A585A /* fmtdytst.c in Sources */, - 3104B033156D3A05000A585A /* testlib.c in Sources */, - 3104B034156D3A2C000A585A /* amssshe.c in Sources */, - 3104B035156D3A39000A585A /* fmtdy.c in Sources */, - 3104B036156D3A49000A585A /* fmtno.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3104B039156D3AD7000A585A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3104B04E156D3AFE000A585A /* testlib.c in Sources */, - 3104B04F156D3B09000A585A /* fmtdy.c in Sources */, - 3104B050156D3B09000A585A /* fmtdytst.c in Sources */, - 3104B051156D3B09000A585A /* fmtno.c in Sources */, - 31D60007156D3C6200337B26 /* segsmss.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A58C156E913C001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A59C156E914F001E0AA3 /* testlib.c in Sources */, - 3114A5A2156E9168001E0AA3 /* locv.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A5A3156E92C0001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A5B2156E92CB001E0AA3 /* testlib.c in Sources */, - 3114A5B8156E92F1001E0AA3 /* qs.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A5B9156E9315001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A5C7156E9322001E0AA3 /* testlib.c in Sources */, - 3114A5CE156E9369001E0AA3 /* finalcv.c in Sources */, - 3114A5CF156E9381001E0AA3 /* fmtdy.c in Sources */, - 3114A5D0156E9381001E0AA3 /* fmtdytst.c in Sources */, - 3114A5D1156E9381001E0AA3 /* fmtno.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A5D2156E93A0001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A5E0156E93AE001E0AA3 /* fmtdy.c in Sources */, - 3114A5E1156E93AE001E0AA3 /* fmtdytst.c in Sources */, - 3114A5E2156E93AE001E0AA3 /* fmtno.c in Sources */, - 3114A5E3156E93AE001E0AA3 /* testlib.c in Sources */, - 3114A5E6156E93B9001E0AA3 /* finaltest.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A5EB156E93E7001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A5F9156E93F3001E0AA3 /* testlib.c in Sources */, - 3114A5FC156E93FC001E0AA3 /* arenacv.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A601156E9430001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A615156E944E001E0AA3 /* bttest.c in Sources */, - 3114A616156E9455001E0AA3 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A618156E9485001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A627156E9490001E0AA3 /* testlib.c in Sources */, - 3114A62A156E949E001E0AA3 /* teletest.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A62F156E94DB001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A63E156E94EA001E0AA3 /* abqtest.c in Sources */, - 3114A63F156E94F0001E0AA3 /* testlib.c in Sources */, - 3114A646156E9525001E0AA3 /* abq.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A648156E9596001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A657156E95A6001E0AA3 /* cbstest.c in Sources */, - 3114A672156E95F6001E0AA3 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A65E156E95D9001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A66E156E95F2001E0AA3 /* btcv.c in Sources */, - 3114A66F156E95F2001E0AA3 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A678156E9668001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A687156E9674001E0AA3 /* mv2test.c in Sources */, - 3114A688156E967C001E0AA3 /* testlib.c in Sources */, - 3114A68F156E96B6001E0AA3 /* poolmv2.c in Sources */, - 3114A690156E96CE001E0AA3 /* abq.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A691156E971B001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A6A1156E9729001E0AA3 /* messtest.c in Sources */, - 3114A6A2156E972D001E0AA3 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A6A8156E9759001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A6BC156E976C001E0AA3 /* walkt0.c in Sources */, - 3114A6BD156E9771001E0AA3 /* testlib.c in Sources */, - 3114A6BF156E97B8001E0AA3 /* fmtdy.c in Sources */, - 3114A6C0156E97B8001E0AA3 /* fmtdytst.c in Sources */, - 3114A6C1156E97B8001E0AA3 /* fmtno.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3114A6C2156E9815001E0AA3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3114A6D1156E9829001E0AA3 /* eventcnv.c in Sources */, - 3114A6DA156E9950001E0AA3 /* eventpro.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3124CAB4156BE3EC00753214 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3124CAC3156BE40100753214 /* awlut.c in Sources */, - 3124CAC5156BE41700753214 /* testlib.c in Sources */, - 3124CAC8156BE48D00753214 /* fmtdy.c in Sources */, - 3124CAC9156BE48D00753214 /* fmtdytst.c in Sources */, - 3124CACD156BE4C200753214 /* fmtno.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3124CAD0156BE64A00753214 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3124CADF156BE65900753214 /* mpsicv.c in Sources */, - 3124CAE0156BE66B00753214 /* testlib.c in Sources */, - 3124CAE2156BE68E00753214 /* fmtdy.c in Sources */, - 3124CAE3156BE69B00753214 /* fmtno.c in Sources */, - 3124CAE5156BE6D500753214 /* fmthe.c in Sources */, - 3124CAE6156BE6F700753214 /* fmtdytst.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3124CAE7156BE7F300753214 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3124CAF6156BE81100753214 /* amcss.c in Sources */, - 3124CAF7156BE82000753214 /* fmtdy.c in Sources */, - 3124CAF8156BE82000753214 /* fmtdytst.c in Sources */, - 3124CAF9156BE82000753214 /* fmthe.c in Sources */, - 3124CAFA156BE82000753214 /* fmtno.c in Sources */, - 3124CAFB156BE82000753214 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D60009156D3CB200337B26 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60018156D3CC300337B26 /* awluthe.c in Sources */, - 31D6001A156D3CDC00337B26 /* fmtdy.c in Sources */, - 31D6001B156D3CDC00337B26 /* fmtdytst.c in Sources */, - 31D6001C156D3CDC00337B26 /* fmthe.c in Sources */, - 31D6001D156D3CDC00337B26 /* fmtno.c in Sources */, - 31D6001E156D3CDF00337B26 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D60023156D3D3E00337B26 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60038156D3E3000337B26 /* lockcov.c in Sources */, - 31D60039156D3E3E00337B26 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D6003A156D3EC700337B26 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D60048156D3ECF00337B26 /* testlib.c in Sources */, - 31D6004B156D3EE600337B26 /* poolncv.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D60050156D3F3500337B26 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D6005F156D3F4A00337B26 /* zcoll.c in Sources */, - 31D60069156D3F7200337B26 /* fmtdy.c in Sources */, - 31D6006A156D3F7200337B26 /* fmtdytst.c in Sources */, - 31D6006B156D3F7200337B26 /* fmtno.c in Sources */, - 31D6006C156D3F7200337B26 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D6006D156D3FBC00337B26 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D6007D156D3FCF00337B26 /* zmess.c in Sources */, - 31D6007E156D3FD700337B26 /* fmtdy.c in Sources */, - 31D6007F156D3FD700337B26 /* fmtdytst.c in Sources */, - 31D60080156D3FD700337B26 /* fmthe.c in Sources */, - 31D60081156D3FD700337B26 /* fmtno.c in Sources */, - 31D60082156D3FD700337B26 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31D60088156D402900337B26 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 31D6009A156D404000337B26 /* steptest.c in Sources */, - 31D6009E156D406400337B26 /* fmtdy.c in Sources */, - 31D6009F156D406400337B26 /* fmtdytst.c in Sources */, - 31D600A0156D406400337B26 /* fmtno.c in Sources */, - 31D600A1156D406400337B26 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31EEABF7156AAF9D00714D05 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 31A47BA4156C1E130039B1C2 /* mps.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 31EEAC61156AB52600714D05 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 31EEAC75156AB58E00714D05 /* mpmss.c in Sources */, - 31EEAC9F156AB73400714D05 /* testlib.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 3104AFC1156D35AE000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3104AFC0156D35AE000A585A /* PBXContainerItemProxy */; - }; - 3104AFD3156D35F2000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3104AFD2156D35F2000A585A /* PBXContainerItemProxy */; - }; - 3104AFE8156D368D000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3104AFE7156D368D000A585A /* PBXContainerItemProxy */; - }; - 3104AFF6156D37BC000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3104AFF5156D37BC000A585A /* PBXContainerItemProxy */; - }; - 3104AFF8156D37BE000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3124CAEA156BE7F300753214 /* amcss */; - targetProxy = 3104AFF7156D37BE000A585A /* PBXContainerItemProxy */; - }; - 3104AFFA156D37C1000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3104AFB2156D357B000A585A /* apss */; - targetProxy = 3104AFF9156D37C1000A585A /* PBXContainerItemProxy */; - }; - 3104AFFC156D37C3000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3124CAB7156BE3EC00753214 /* awlut */; - targetProxy = 3104AFFB156D37C3000A585A /* PBXContainerItemProxy */; - }; - 3104AFFE156D37C6000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEAC64156AB52600714D05 /* mpmss */; - targetProxy = 3104AFFD156D37C6000A585A /* PBXContainerItemProxy */; - }; - 3104B000156D37C8000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3124CAD3156BE64A00753214 /* mpsicv */; - targetProxy = 3104AFFF156D37C8000A585A /* PBXContainerItemProxy */; - }; - 3104B002156D37CB000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3104AFC7156D35E2000A585A /* sacss */; - targetProxy = 3104B001156D37CB000A585A /* PBXContainerItemProxy */; - }; - 3104B004156D37CD000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3104AFDC156D3681000A585A /* amcsshe */; - targetProxy = 3104B003156D37CD000A585A /* PBXContainerItemProxy */; - }; - 3104B014156D38FA000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3104B013156D38FA000A585A /* PBXContainerItemProxy */; - }; - 3104B01D156D398B000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3104B008156D38F3000A585A /* amsss */; - targetProxy = 3104B01C156D398B000A585A /* PBXContainerItemProxy */; - }; - 3104B02D156D39DF000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3104B021156D39D4000A585A /* amssshe */; - targetProxy = 3104B02C156D39DF000A585A /* PBXContainerItemProxy */; - }; - 3104B038156D3A56000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3104B037156D3A56000A585A /* PBXContainerItemProxy */; - }; - 3104B048156D3ADE000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3104B047156D3ADE000A585A /* PBXContainerItemProxy */; - }; - 3104B04A156D3AE4000A585A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3104B03C156D3AD7000A585A /* segsmss */; - targetProxy = 3104B049156D3AE4000A585A /* PBXContainerItemProxy */; - }; - 3114A59E156E9156001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A59D156E9156001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A5A0156E915A001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A58F156E913C001E0AA3 /* locv */; - targetProxy = 3114A59F156E915A001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A5B4156E92D8001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A5B3156E92D8001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A5B6156E92DC001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A5A6156E92C0001E0AA3 /* qs */; - targetProxy = 3114A5B5156E92DC001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A5CA156E9328001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A5C9156E9328001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A5CC156E932C001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A5BC156E9315001E0AA3 /* finalcv */; - targetProxy = 3114A5CB156E932C001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A5E8156E93BF001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A5E7156E93BF001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A5EA156E93C4001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A5D5156E93A0001E0AA3 /* finaltest */; - targetProxy = 3114A5E9156E93C4001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A5FE156E9406001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A5FD156E9406001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A600156E940A001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A5EE156E93E7001E0AA3 /* arenacv */; - targetProxy = 3114A5FF156E940A001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A610156E9438001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A60F156E9438001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A612156E943B001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A604156E9430001E0AA3 /* bttest */; - targetProxy = 3114A611156E943B001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A62C156E94A6001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A62B156E94A6001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A62E156E94AA001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A61B156E9485001E0AA3 /* teletest */; - targetProxy = 3114A62D156E94AA001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A642156E94F8001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A641156E94F8001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A644156E94FB001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A632156E94DB001E0AA3 /* abqtest */; - targetProxy = 3114A643156E94FB001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A659156E95B1001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A658156E95B1001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A65B156E95B4001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A64B156E9596001E0AA3 /* cbstest */; - targetProxy = 3114A65A156E95B4001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A675156E9619001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A674156E9619001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A677156E961C001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A661156E95D9001E0AA3 /* btcv */; - targetProxy = 3114A676156E961C001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A68B156E9682001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A68A156E9682001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A68D156E9686001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A67B156E9668001E0AA3 /* mv2test */; - targetProxy = 3114A68C156E9686001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A6A5156E9735001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A6A4156E9735001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A6A7156E9739001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A694156E971B001E0AA3 /* messtest */; - targetProxy = 3114A6A6156E9739001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A6B7156E975E001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A6B6156E975E001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A6B9156E9763001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A6AB156E9759001E0AA3 /* walkt0 */; - targetProxy = 3114A6B8156E9763001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A6D3156E9834001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 3114A6D2156E9834001E0AA3 /* PBXContainerItemProxy */; - }; - 3114A6D5156E9839001E0AA3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3114A6C5156E9815001E0AA3 /* eventcnv */; - targetProxy = 3114A6D4156E9839001E0AA3 /* PBXContainerItemProxy */; - }; - 31A47BAA156C210D0039B1C2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31A47BA9156C210D0039B1C2 /* PBXContainerItemProxy */; - }; - 31A47BAC156C21120039B1C2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31A47BAB156C21120039B1C2 /* PBXContainerItemProxy */; - }; - 31A47BAE156C21170039B1C2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31A47BAD156C21170039B1C2 /* PBXContainerItemProxy */; - }; - 31A47BB0156C211B0039B1C2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31A47BAF156C211B0039B1C2 /* PBXContainerItemProxy */; - }; - 31D60020156D3CEC00337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31D6001F156D3CEC00337B26 /* PBXContainerItemProxy */; - }; - 31D60022156D3CF200337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31D6000C156D3CB200337B26 /* awluthe */; - targetProxy = 31D60021156D3CF200337B26 /* PBXContainerItemProxy */; - }; - 31D60032156D3D5300337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31D60031156D3D5300337B26 /* PBXContainerItemProxy */; - }; - 31D60034156D3D5A00337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31D60026156D3D3E00337B26 /* lockcov */; - targetProxy = 31D60033156D3D5A00337B26 /* PBXContainerItemProxy */; - }; - 31D6004D156D3EF000337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31D6004C156D3EF000337B26 /* PBXContainerItemProxy */; - }; - 31D6004F156D3EF700337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31D6003D156D3EC700337B26 /* poolncv */; - targetProxy = 31D6004E156D3EF700337B26 /* PBXContainerItemProxy */; - }; - 31D60063156D3F5C00337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31D60053156D3F3500337B26 /* zcoll */; - targetProxy = 31D60062156D3F5C00337B26 /* PBXContainerItemProxy */; - }; - 31D60065156D3F5F00337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31D60064156D3F5F00337B26 /* PBXContainerItemProxy */; - }; - 31D60085156D3FE100337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31D60084156D3FE100337B26 /* PBXContainerItemProxy */; - }; - 31D60087156D3FE600337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31D60070156D3FBC00337B26 /* zmess */; - targetProxy = 31D60086156D3FE600337B26 /* PBXContainerItemProxy */; - }; - 31D60097156D403500337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31EEABFA156AAF9D00714D05 /* mps */; - targetProxy = 31D60096156D403500337B26 /* PBXContainerItemProxy */; - }; - 31D6009D156D404B00337B26 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 31D6008B156D402900337B26 /* steptest */; - targetProxy = 31D6009C156D404B00337B26 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 3104AFBA156D357B000A585A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3104AFBB156D357B000A585A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3104AFD0156D35E2000A585A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3104AFD1156D35E2000A585A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3104AFE5156D3682000A585A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3104AFE6156D3682000A585A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3104AFF3156D37A0000A585A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3104AFF4156D37A0000A585A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3104B011156D38F3000A585A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3104B012156D38F3000A585A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3104B02A156D39D4000A585A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3104B02B156D39D4000A585A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3104B045156D3AD8000A585A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3104B046156D3AD8000A585A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A597156E913C001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A598156E913C001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A5AF156E92C0001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A5B0156E92C0001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A5C5156E9315001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A5C6156E9315001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A5DE156E93A0001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A5DF156E93A0001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A5F7156E93E7001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A5F8156E93E7001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A60D156E9430001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A60E156E9430001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A624156E9485001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A625156E9485001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A63B156E94DB001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A63C156E94DB001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A654156E9596001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A655156E9596001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A66A156E95D9001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A66B156E95D9001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A684156E9669001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A685156E9669001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A69D156E971B001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A69E156E971B001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A6B4156E9759001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A6B5156E9759001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3114A6CE156E9815001E0AA3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3114A6CF156E9815001E0AA3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3124CAC0156BE3EC00753214 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3124CAC1156BE3EC00753214 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3124CADC156BE64A00753214 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3124CADD156BE64A00753214 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 3124CAF3156BE7F300753214 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 3124CAF4156BE7F300753214 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 318387EB15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = ansi; - GCC_OPTIMIZATION_LEVEL = 2; - GCC_PREPROCESSOR_DEFINITIONS = CONFIG_VAR_WE; - GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_PEDANTIC = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_PARAMETER = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.4; - OTHER_CFLAGS = ( - "-pedantic", - "-Wall", - "-Wno-extended-offsetof", - ); - SDKROOT = macosx; - SYMROOT = xc; - WARNING_CFLAGS = ( - "-pedantic", - "-Wpointer-arith", - "-Wstrict-prototypes", - "-Wmissing-prototypes", - "-Winline", - "-Waggregate-return", - "-Wnested-externs", - "-Wcast-qual", - "-Wshadow", - "-Wall", - "-Wno-extended-offsetof", - ); - }; - name = WE; - }; - 318387EC15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387ED15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COMBINE_HIDPI_IMAGES = YES; - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387EE15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387EF15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F015DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F115DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F215DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F315DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F415DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F515DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F615DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F715DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F815DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387F915DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387FA15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387FB15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387FC15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387FD15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387FE15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 318387FF15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880015DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880115DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880215DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880315DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880415DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880515DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880615DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880715DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880815DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880915DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880A15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 3183880B15DC30CC008E4EA0 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = WE; - }; - 31D60015156D3CB200337B26 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 31D60016156D3CB200337B26 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 31D6002F156D3D3F00337B26 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 31D60030156D3D3F00337B26 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 31D60046156D3EC700337B26 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 31D60047156D3EC700337B26 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 31D6005C156D3F3500337B26 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 31D6005D156D3F3500337B26 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 31D60079156D3FBC00337B26 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 31D6007A156D3FBC00337B26 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 31D60094156D402900337B26 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 31D60095156D402900337B26 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 31EEABDF156AAE9E00714D05 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = ansi; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = CONFIG_VAR_COOL; - GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_PEDANTIC = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_PARAMETER = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.4; - ONLY_ACTIVE_ARCH = YES; - OTHER_CFLAGS = ( - "-pedantic", - "-Wall", - "-Wno-extended-offsetof", - ); - SDKROOT = macosx; - SYMROOT = xc; - WARNING_CFLAGS = ( - "-pedantic", - "-Wpointer-arith", - "-Wstrict-prototypes", - "-Wmissing-prototypes", - "-Winline", - "-Waggregate-return", - "-Wnested-externs", - "-Wcast-qual", - "-Wshadow", - "-Wall", - "-Wno-extended-offsetof", - ); - }; - name = Debug; - }; - 31EEABE0156AAE9E00714D05 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = ansi; - GCC_OPTIMIZATION_LEVEL = 2; - GCC_PREPROCESSOR_DEFINITIONS = CONFIG_VAR_HOT; - GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_PEDANTIC = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_PARAMETER = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.4; - OTHER_CFLAGS = ( - "-pedantic", - "-Wall", - "-Wno-extended-offsetof", - ); - SDKROOT = macosx; - SYMROOT = xc; - WARNING_CFLAGS = ( - "-pedantic", - "-Wpointer-arith", - "-Wstrict-prototypes", - "-Wmissing-prototypes", - "-Winline", - "-Waggregate-return", - "-Wnested-externs", - "-Wcast-qual", - "-Wshadow", - "-Wall", - "-Wno-extended-offsetof", - ); - }; - name = Release; - }; - 31EEABFD156AAF9D00714D05 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COMBINE_HIDPI_IMAGES = YES; - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 31EEABFE156AAF9D00714D05 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COMBINE_HIDPI_IMAGES = YES; - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 31EEAC6D156AB52600714D05 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 31EEAC6E156AB52600714D05 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 3104AFBC156D357B000A585A /* Build configuration list for PBXNativeTarget "apss" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3104AFBA156D357B000A585A /* Debug */, - 3104AFBB156D357B000A585A /* Release */, - 318387EF15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3104AFCF156D35E2000A585A /* Build configuration list for PBXNativeTarget "sacss" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3104AFD0156D35E2000A585A /* Debug */, - 3104AFD1156D35E2000A585A /* Release */, - 318387F315DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3104AFE4156D3682000A585A /* Build configuration list for PBXNativeTarget "amcsshe" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3104AFE5156D3682000A585A /* Debug */, - 3104AFE6156D3682000A585A /* Release */, - 318387F415DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3104AFF2156D37A0000A585A /* Build configuration list for PBXAggregateTarget "all" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3104AFF3156D37A0000A585A /* Debug */, - 3104AFF4156D37A0000A585A /* Release */, - 318387EC15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3104B010156D38F3000A585A /* Build configuration list for PBXNativeTarget "amsss" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3104B011156D38F3000A585A /* Debug */, - 3104B012156D38F3000A585A /* Release */, - 318387F515DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3104B029156D39D4000A585A /* Build configuration list for PBXNativeTarget "amssshe" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3104B02A156D39D4000A585A /* Debug */, - 3104B02B156D39D4000A585A /* Release */, - 318387F615DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3104B044156D3AD8000A585A /* Build configuration list for PBXNativeTarget "segsmss" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3104B045156D3AD8000A585A /* Debug */, - 3104B046156D3AD8000A585A /* Release */, - 318387F715DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A599156E913C001E0AA3 /* Build configuration list for PBXNativeTarget "locv" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A597156E913C001E0AA3 /* Debug */, - 3114A598156E913C001E0AA3 /* Release */, - 318387FE15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A5AE156E92C0001E0AA3 /* Build configuration list for PBXNativeTarget "qs" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A5AF156E92C0001E0AA3 /* Debug */, - 3114A5B0156E92C0001E0AA3 /* Release */, - 318387FF15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A5C4156E9315001E0AA3 /* Build configuration list for PBXNativeTarget "finalcv" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A5C5156E9315001E0AA3 /* Debug */, - 3114A5C6156E9315001E0AA3 /* Release */, - 3183880015DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A5DD156E93A0001E0AA3 /* Build configuration list for PBXNativeTarget "finaltest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A5DE156E93A0001E0AA3 /* Debug */, - 3114A5DF156E93A0001E0AA3 /* Release */, - 3183880115DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A5F6156E93E7001E0AA3 /* Build configuration list for PBXNativeTarget "arenacv" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A5F7156E93E7001E0AA3 /* Debug */, - 3114A5F8156E93E7001E0AA3 /* Release */, - 3183880215DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A60C156E9430001E0AA3 /* Build configuration list for PBXNativeTarget "bttest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A60D156E9430001E0AA3 /* Debug */, - 3114A60E156E9430001E0AA3 /* Release */, - 3183880315DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A623156E9485001E0AA3 /* Build configuration list for PBXNativeTarget "teletest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A624156E9485001E0AA3 /* Debug */, - 3114A625156E9485001E0AA3 /* Release */, - 3183880415DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A63A156E94DB001E0AA3 /* Build configuration list for PBXNativeTarget "abqtest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A63B156E94DB001E0AA3 /* Debug */, - 3114A63C156E94DB001E0AA3 /* Release */, - 3183880515DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A653156E9596001E0AA3 /* Build configuration list for PBXNativeTarget "cbstest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A654156E9596001E0AA3 /* Debug */, - 3114A655156E9596001E0AA3 /* Release */, - 3183880615DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A669156E95D9001E0AA3 /* Build configuration list for PBXNativeTarget "btcv" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A66A156E95D9001E0AA3 /* Debug */, - 3114A66B156E95D9001E0AA3 /* Release */, - 3183880715DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A683156E9669001E0AA3 /* Build configuration list for PBXNativeTarget "mv2test" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A684156E9669001E0AA3 /* Debug */, - 3114A685156E9669001E0AA3 /* Release */, - 3183880815DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A69C156E971B001E0AA3 /* Build configuration list for PBXNativeTarget "messtest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A69D156E971B001E0AA3 /* Debug */, - 3114A69E156E971B001E0AA3 /* Release */, - 3183880915DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A6B3156E9759001E0AA3 /* Build configuration list for PBXNativeTarget "walkt0" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A6B4156E9759001E0AA3 /* Debug */, - 3114A6B5156E9759001E0AA3 /* Release */, - 3183880A15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3114A6CD156E9815001E0AA3 /* Build configuration list for PBXNativeTarget "eventcnv" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3114A6CE156E9815001E0AA3 /* Debug */, - 3114A6CF156E9815001E0AA3 /* Release */, - 3183880B15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3124CABF156BE3EC00753214 /* Build configuration list for PBXNativeTarget "awlut" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3124CAC0156BE3EC00753214 /* Debug */, - 3124CAC1156BE3EC00753214 /* Release */, - 318387F015DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3124CADB156BE64A00753214 /* Build configuration list for PBXNativeTarget "mpsicv" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3124CADC156BE64A00753214 /* Debug */, - 3124CADD156BE64A00753214 /* Release */, - 318387F215DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3124CAF2156BE7F300753214 /* Build configuration list for PBXNativeTarget "amcss" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3124CAF3156BE7F300753214 /* Debug */, - 3124CAF4156BE7F300753214 /* Release */, - 318387EE15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31D60014156D3CB200337B26 /* Build configuration list for PBXNativeTarget "awluthe" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31D60015156D3CB200337B26 /* Debug */, - 31D60016156D3CB200337B26 /* Release */, - 318387F815DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31D6002E156D3D3F00337B26 /* Build configuration list for PBXNativeTarget "lockcov" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31D6002F156D3D3F00337B26 /* Debug */, - 31D60030156D3D3F00337B26 /* Release */, - 318387F915DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31D60045156D3EC700337B26 /* Build configuration list for PBXNativeTarget "poolncv" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31D60046156D3EC700337B26 /* Debug */, - 31D60047156D3EC700337B26 /* Release */, - 318387FA15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31D6005B156D3F3500337B26 /* Build configuration list for PBXNativeTarget "zcoll" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31D6005C156D3F3500337B26 /* Debug */, - 31D6005D156D3F3500337B26 /* Release */, - 318387FB15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31D60078156D3FBC00337B26 /* Build configuration list for PBXNativeTarget "zmess" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31D60079156D3FBC00337B26 /* Debug */, - 31D6007A156D3FBC00337B26 /* Release */, - 318387FC15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31D60093156D402900337B26 /* Build configuration list for PBXNativeTarget "steptest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31D60094156D402900337B26 /* Debug */, - 31D60095156D402900337B26 /* Release */, - 318387FD15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31EEABDD156AAE9E00714D05 /* Build configuration list for PBXProject "mps" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31EEABDF156AAE9E00714D05 /* Debug */, - 31EEABE0156AAE9E00714D05 /* Release */, - 318387EB15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31EEABFC156AAF9D00714D05 /* Build configuration list for PBXNativeTarget "mps" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31EEABFD156AAF9D00714D05 /* Debug */, - 31EEABFE156AAF9D00714D05 /* Release */, - 318387ED15DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 31EEAC6C156AB52600714D05 /* Build configuration list for PBXNativeTarget "mpmss" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 31EEAC6D156AB52600714D05 /* Debug */, - 31EEAC6E156AB52600714D05 /* Release */, - 318387F115DC30CC008E4EA0 /* WE */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 31EEABDA156AAE9E00714D05 /* Project object */; -} diff --git a/mps/code/mpsacl.h b/mps/code/mpsacl.h deleted file mode 100644 index 62a8952ba83..00000000000 --- a/mps/code/mpsacl.h +++ /dev/null @@ -1,58 +0,0 @@ -/* mpsacl.h: MEMORY POOL SYSTEM ARENA CLASS "CL" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpsacl_h -#define mpsacl_h - -#include "mps.h" - - -extern mps_arena_class_t mps_arena_class_cl(void); - - -#endif /* mpsacl_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsavm.h b/mps/code/mpsavm.h deleted file mode 100644 index 5eae2ef201b..00000000000 --- a/mps/code/mpsavm.h +++ /dev/null @@ -1,63 +0,0 @@ -/* mpsavm.h: MEMORY POOL SYSTEM ARENA CLASS "VM" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpsavm_h -#define mpsavm_h - -#include "mps.h" - - -extern mps_arena_class_t mps_arena_class_vm(void); -extern mps_arena_class_t mps_arena_class_vmnz(void); - - -/* The vm arena class supports extensions to the arena protocol: */ -extern mps_res_t mps_arena_vm_growth(mps_arena_t, size_t, size_t); - - -#endif /* mpsavm_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002,2007 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpscamc.h b/mps/code/mpscamc.h deleted file mode 100644 index 8d33ee4bb6a..00000000000 --- a/mps/code/mpscamc.h +++ /dev/null @@ -1,61 +0,0 @@ -/* mpscamc.h: MEMORY POOL SYSTEM CLASS "AMC" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpscamc_h -#define mpscamc_h - -#include "mps.h" - -extern mps_class_t mps_class_amc(void); -extern mps_class_t mps_class_amcz(void); - -extern void mps_amc_apply(mps_pool_t, - void (*)(mps_addr_t, void *, size_t), - void *, size_t); - -#endif /* mpscamc_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpscams.h b/mps/code/mpscams.h deleted file mode 100644 index 22fc9185157..00000000000 --- a/mps/code/mpscams.h +++ /dev/null @@ -1,58 +0,0 @@ -/* mpscams.h: MEMORY POOL SYSTEM CLASS "AMS" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - */ - -#ifndef mpscams_h -#define mpscams_h - -#include "mps.h" - -extern mps_class_t mps_class_ams(void); -extern mps_class_t mps_class_ams_debug(void); - -#endif /* mpscams_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpscawl.h b/mps/code/mpscawl.h deleted file mode 100644 index 0b5bc790acf..00000000000 --- a/mps/code/mpscawl.h +++ /dev/null @@ -1,56 +0,0 @@ -/* mpscaawl.h: MEMORY POOL SYSTEM CLASS "AWL" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpscawl_h -#define mpscawl_h - -#include "mps.h" - -extern mps_class_t mps_class_awl(void); - -#endif /* mpscawl_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsclo.h b/mps/code/mpsclo.h deleted file mode 100644 index 15813bbfdef..00000000000 --- a/mps/code/mpsclo.h +++ /dev/null @@ -1,57 +0,0 @@ -/* mpsclo.h: MEMORY POOL SYSTEM CLASS "LO" - * - * $Id$ - * - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpsclo_h -#define mpsclo_h - -#include "mps.h" - -extern mps_class_t mps_class_lo(void); - -#endif /* mpsclo_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpscmv.h b/mps/code/mpscmv.h deleted file mode 100644 index 805db19b8af..00000000000 --- a/mps/code/mpscmv.h +++ /dev/null @@ -1,59 +0,0 @@ -/* mpscmv.h: MEMORY POOL SYSTEM CLASS "MV" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpscmv_h -#define mpscmv_h - -#include "mps.h" - -extern size_t mps_mv_free_size(mps_pool_t mps_pool); -extern size_t mps_mv_size(mps_pool_t mps_pool); -extern mps_class_t mps_class_mv(void); -extern mps_class_t mps_class_mv_debug(void); - -#endif /* mpscmv_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpscmv2.h b/mps/code/mpscmv2.h deleted file mode 100644 index 8490b8f311a..00000000000 --- a/mps/code/mpscmv2.h +++ /dev/null @@ -1,77 +0,0 @@ -/* mpscmv2.h: MEMORY POOL SYSTEM CLASS "MVT" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpscmv2_h -#define mpscmv2_h - -#include "mps.h" - -/* The mvt pool class has five extra parameters to mps_pool_create: - * mps_res_t mps_pool_create(mps_pool_t * pool, mps_arena_t arena, - * mps_class_t mvt_class, - * size_t minimum_size, - * size_t mean_size, - * size_t maximum_size, - * mps_count_t reserve_depth - * mps_count_t fragmentation_limit); - * minimum_, mean_, and maximum_size are the mimimum, mean, and - * maximum (typical) size of objects expected to be allocated in the - * pool. reserve_depth is a measure of the expected hysteresis of the - * object population. fragmentation_limit is a percentage (between 0 - * and 100): if the free space managed by the pool exceeds the - * specified percentage, the pool will resort to a "first fit" - * allocation policy. - */ -extern mps_class_t mps_class_mvt(void); - -/* The mvt pool class supports two extensions to the pool protocol: - size and free_size. */ -extern size_t mps_mvt_free_size(mps_pool_t mps_pool); -extern size_t mps_mvt_size(mps_pool_t mps_pool); - -#endif /* mpscmv2_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpscmvff.h b/mps/code/mpscmvff.h deleted file mode 100644 index f80815a7ca6..00000000000 --- a/mps/code/mpscmvff.h +++ /dev/null @@ -1,59 +0,0 @@ -/* mpscmvff.h: MEMORY POOL SYSTEM CLASS "MVFF" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpscmvff_h -#define mpscmvff_h - -#include "mps.h" - -extern size_t mps_mvff_free_size(mps_pool_t mps_pool); -extern size_t mps_mvff_size(mps_pool_t mps_pool); -extern mps_class_t mps_class_mvff(void); -extern mps_class_t mps_class_mvff_debug(void); - -#endif /* mpscmvff_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpscsnc.h b/mps/code/mpscsnc.h deleted file mode 100644 index 8a87d7b5d69..00000000000 --- a/mps/code/mpscsnc.h +++ /dev/null @@ -1,56 +0,0 @@ -/* mpscsnc.h: MEMORY POOL SYSTEM CLASS "SNC" - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef mpscsnc_h -#define mpscsnc_h - -#include "mps.h" - -extern mps_class_t mps_class_snc(void); - -#endif /* mpscsnc_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c deleted file mode 100644 index 15bc692ee00..00000000000 --- a/mps/code/mpsi.c +++ /dev/null @@ -1,1918 +0,0 @@ -/* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER - * - * $Id$ - * Copyright (c) 2001-2003, 2006 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * .purpose: This code bridges between the MPS interface to C, - * , and the internal MPM interfaces, as defined by - * . .purpose.check: It performs checking of the C client's - * usage of the MPS Interface. .purpose.thread: It excludes multiple - * threads from the MPM by locking the Arena (see .thread-safety). - * - * .design: - * - * - * NOTES - * - * .note.break-out: Take care not to return when "inside" the Arena - * (between ArenaEnter and ArenaLeave) as this will leave the Arena in - * an unsuitable state for re-entry. - * - * - * TRANSGRESSIONS (rule.impl.trans) - * - * .check.protocol: (rule.impl.req) More could be done in this code to - * check that protocols are obeyed by the client. It probably doesn't - * meet checking requirements. - * - * .varargs: (rule.universal.complete) The varargs passed to - * mps_alloc(_v) are ignored at the moment. None of the pool - * implementations use them. - * - * .poll: (rule.universal.complete) Various allocation methods call - * ArenaPoll to allow the MPM to "steal" CPU time and get on with - * background tasks such as incremental GC. - * - * .root-mode: (rule.universal.complete) The root "mode", which - * specifies things like the protectability of roots, is ignored at - * present. This is because the MPM doesn't ever try to protect them. - * In future, it will. - * - * .reg-scan: (rule.universal.complete) At present, we only support - * register scanning using our own ambiguous register and stack scanning - * method, mps_stack_scan_ambig. This may never change, but the way the - * interface is designed allows for the possibility of change. - * - * .naming: (rule.impl.guide) The exported identifiers do not follow the - * normal MPS naming conventions. See . */ - -#include "mpm.h" -#include "mps.h" -#include "mpsavm.h" /* only for mps_space_create */ -#include "sac.h" -#include "chain.h" - -SRCID(mpsi, "$Id$"); - - -/* mpsi_check -- check consistency of interface mappings - * - * .check.purpose: The mpsi_check function attempts to check whether - * the defintions in match the equivalent definition in - * the MPM. It is checking the assumptions made in the other functions - * in this implementation. - * - * .check.empty: Note that mpsi_check compiles away to almost nothing. - * - * .check.enum.cast: enum comparisons have to be cast to avoid a warning - * from the SunPro C compiler. See builder.sc.warn.enum. */ - -static Bool mpsi_check(void) -{ - /* .check.rc: Check that external and internal result codes match. */ - /* See and . */ - /* Also see .check.enum.cast. */ - CHECKL(COMPATTYPE(mps_res_t, Res)); - CHECKL((int)MPS_RES_OK == (int)ResOK); - CHECKL((int)MPS_RES_FAIL == (int)ResFAIL); - CHECKL((int)MPS_RES_RESOURCE == (int)ResRESOURCE); - CHECKL((int)MPS_RES_MEMORY == (int)ResMEMORY); - CHECKL((int)MPS_RES_LIMIT == (int)ResLIMIT); - CHECKL((int)MPS_RES_UNIMPL == (int)ResUNIMPL); - CHECKL((int)MPS_RES_IO == (int)ResIO); - CHECKL((int)MPS_RES_COMMIT_LIMIT == (int)ResCOMMIT_LIMIT); - - /* Check that external and internal message types match. */ - /* See and */ - /* . */ - /* Also see .check.enum.cast. */ - CHECKL(COMPATTYPE(mps_message_type_t, MessageType)); - CHECKL((int)MessageTypeFINALIZATION - == (int)_mps_MESSAGE_TYPE_FINALIZATION); - CHECKL((int)MessageTypeGC - == (int)_mps_MESSAGE_TYPE_GC); - CHECKL((int)MessageTypeGCSTART - == (int)_mps_MESSAGE_TYPE_GC_START); - - /* The external idea of a word width and the internal one */ - /* had better match. See . */ - CHECKL(sizeof(mps_word_t) == sizeof(void *)); - CHECKL(COMPATTYPE(mps_word_t, Word)); - - /* The external idea of an address and the internal one */ - /* had better match. */ - CHECKL(COMPATTYPE(mps_addr_t, Addr)); - - /* The external idea of size and the internal one had */ - /* better match. See */ - /* and . */ - CHECKL(COMPATTYPE(size_t, Size)); - - /* Clock values are passed from external to internal and back */ - /* out to external. */ - CHECKL(COMPATTYPE(mps_clock_t, Clock)); - - return TRUE; -} - - -/* Ranks - * - * Here a rank returning function is defined for all client visible - * ranks. - * - * .rank.final.not: RankFINAL does not have a corresponding function as - * it is only used internally. */ - -mps_rank_t mps_rank_ambig(void) -{ - return RankAMBIG; -} - -mps_rank_t mps_rank_exact(void) -{ - return RankEXACT; -} - -mps_rank_t mps_rank_weak(void) -{ - return RankWEAK; -} - - -mps_res_t mps_arena_extend(mps_arena_t arena, - mps_addr_t base, size_t size) -{ - Res res; - - ArenaEnter(arena); - AVER(size > 0); - res = ArenaExtend(arena, (Addr)base, (Size)size); - ArenaLeave(arena); - - return (mps_res_t)res; -} - -size_t mps_arena_reserved(mps_arena_t arena) -{ - Size size; - - ArenaEnter(arena); - size = ArenaReserved(arena); - ArenaLeave(arena); - - return (size_t)size; -} - -size_t mps_arena_committed(mps_arena_t arena) -{ - Size size; - - ArenaEnter(arena); - size = ArenaCommitted(arena); - ArenaLeave(arena); - - return (size_t)size; -} - -size_t mps_arena_spare_committed(mps_arena_t arena) -{ - Size size; - - ArenaEnter(arena); - size = ArenaSpareCommitted(arena); - ArenaLeave(arena); - - return (size_t)size; -} - -size_t mps_arena_commit_limit(mps_arena_t arena) -{ - Size size; - - ArenaEnter(arena); - size = ArenaCommitLimit(arena); - ArenaLeave(arena); - - return size; -} - -mps_res_t mps_arena_commit_limit_set(mps_arena_t arena, size_t limit) -{ - Res res; - - ArenaEnter(arena); - res = ArenaSetCommitLimit(arena, limit); - ArenaLeave(arena); - - return res; -} - -void mps_arena_spare_commit_limit_set(mps_arena_t arena, size_t limit) -{ - ArenaEnter(arena); - ArenaSetSpareCommitLimit(arena, limit); - ArenaLeave(arena); - - return; -} - -size_t mps_arena_spare_commit_limit(mps_arena_t arena) -{ - size_t limit; - - ArenaEnter(arena); - limit = ArenaSpareCommitLimit(arena); - ArenaLeave(arena); - - return limit; -} - -void mps_arena_clamp(mps_arena_t arena) -{ - ArenaEnter(arena); - ArenaClamp(ArenaGlobals(arena)); - ArenaLeave(arena); -} - - -void mps_arena_release(mps_arena_t arena) -{ - ArenaEnter(arena); - ArenaRelease(ArenaGlobals(arena)); - ArenaLeave(arena); -} - - -void mps_arena_park(mps_arena_t arena) -{ - ArenaEnter(arena); - ArenaPark(ArenaGlobals(arena)); - ArenaLeave(arena); -} - - -void mps_arena_expose(mps_arena_t arena) -{ - ArenaEnter(arena); - ArenaExposeRemember(ArenaGlobals(arena), 0); - ArenaLeave(arena); -} - -/* Null implementations of remember and restore */ -void mps_arena_unsafe_expose_remember_protection(mps_arena_t arena) -{ - ArenaEnter(arena); - ArenaExposeRemember(ArenaGlobals(arena), 1); - ArenaLeave(arena); -} - -void mps_arena_unsafe_restore_protection(mps_arena_t arena) -{ - ArenaEnter(arena); - ArenaRestoreProtection(ArenaGlobals(arena)); - ArenaLeave(arena); -} - - -mps_res_t mps_arena_start_collect(mps_arena_t arena) -{ - Res res; - ArenaEnter(arena); - res = ArenaStartCollect(ArenaGlobals(arena), TraceStartWhyCLIENTFULL_INCREMENTAL); - ArenaLeave(arena); - return res; -} - -mps_res_t mps_arena_collect(mps_arena_t arena) -{ - Res res; - ArenaEnter(arena); - res = ArenaCollect(ArenaGlobals(arena), TraceStartWhyCLIENTFULL_BLOCK); - ArenaLeave(arena); - return res; -} - -mps_bool_t mps_arena_step(mps_arena_t arena, - double interval, - double multiplier) -{ - Bool b; - ArenaEnter(arena); - b = ArenaStep(ArenaGlobals(arena), interval, multiplier); - ArenaLeave(arena); - return b; -} - - -/* mps_arena_create -- create an arena object */ - -mps_res_t mps_arena_create(mps_arena_t *mps_arena_o, - mps_arena_class_t mps_arena_class, ...) -{ - mps_res_t res; - va_list args; - - va_start(args, mps_arena_class); - res = mps_arena_create_v(mps_arena_o, mps_arena_class, args); - va_end(args); - return res; -} - - -/* mps_arena_create_v -- create an arena object */ - -mps_res_t mps_arena_create_v(mps_arena_t *mps_arena_o, - mps_arena_class_t arena_class, va_list args) -{ - Arena arena; - Res res; - - /* This is the first real call that the client will have to make, */ - /* so check static consistency here. */ - AVER(mpsi_check()); - - AVER(mps_arena_o != NULL); - - res = ArenaCreateV(&arena, arena_class, args); - if (res != ResOK) - return res; - - ArenaLeave(arena); - *mps_arena_o = (mps_arena_t)arena; - return MPS_RES_OK; -} - -/* mps_arena_destroy -- destroy an arena object */ - -void mps_arena_destroy(mps_arena_t arena) -{ - ArenaEnter(arena); - ArenaDestroy(arena); -} - - -/* mps_arena_has_addr -- is this address managed by this arena? */ - -mps_bool_t mps_arena_has_addr(mps_arena_t arena, mps_addr_t p) -{ - Bool b; - - /* One of the few functions that can be called - during the call to an MPS function. IE this function - can be called when walking the heap. */ - ArenaEnterRecursive(arena); - AVERT(Arena, arena); - b = ArenaHasAddr(arena, (Addr)p); - ArenaLeaveRecursive(arena); - return b; -} - - -/* mps_addr_pool -- return the pool containing the given address - * - * Wrapper for PoolOfAddr. Note: may return an MPS-internal pool. - */ - -mps_bool_t mps_addr_pool(mps_pool_t *mps_pool_o, - mps_arena_t arena, - mps_addr_t p) -{ - Bool b; - Pool pool; - - AVER(mps_pool_o != NULL); - /* mps_arena -- will be checked by ArenaEnterRecursive */ - /* p -- cannot be checked */ - - /* One of the few functions that can be called - during the call to an MPS function. IE this function - can be called when walking the heap. */ - ArenaEnterRecursive(arena); - b = PoolOfAddr(&pool, arena, (Addr)p); - ArenaLeaveRecursive(arena); - - if(b) - *mps_pool_o = (mps_pool_t)pool; - - return b; -} - - -/* mps_addr_fmt -- what format might this address have? - * - * .per-pool: There's no reason why all objects in a pool should have - * the same format. But currently, MPS internals support at most one - * format per pool. - * - * If the address is in a pool and has a format, returns TRUE and - * updates *mps_fmt_o to be that format. Otherwise, returns FALSE - * and does not update *mps_fmt_o. - * - * Note: may return an MPS-internal format. - */ -mps_bool_t mps_addr_fmt(mps_fmt_t *mps_fmt_o, - mps_arena_t arena, - mps_addr_t p) -{ - Bool b; - Pool pool; - Format format = 0; - - AVER(mps_fmt_o != NULL); - /* mps_arena -- will be checked by ArenaEnterRecursive */ - /* p -- cannot be checked */ - - /* One of the few functions that can be called - during the call to an MPS function. IE this function - can be called when walking the heap. */ - ArenaEnterRecursive(arena); - /* .per-pool */ - b = PoolOfAddr(&pool, arena, (Addr)p); - if(b) - b = PoolFormat(&format, pool); - ArenaLeaveRecursive(arena); - - if(b) - *mps_fmt_o = (mps_fmt_t)format; - - return b; -} - - -/* mps_fmt_create_A -- create an object format of variant A - * - * .fmt.create.A.purpose: This function converts an object format spec - * of variant "A" into an MPM Format object. See - * for justification of the way that - * the format structure is declared as "mps_fmt_A". */ - -mps_res_t mps_fmt_create_A(mps_fmt_t *mps_fmt_o, - mps_arena_t arena, - mps_fmt_A_s *mps_fmt_A) -{ - Format format; - Res res; - - ArenaEnter(arena); - - AVER(mps_fmt_A != NULL); - - res = FormatCreate(&format, - arena, - (Align)mps_fmt_A->align, - FormatVarietyA, - mps_fmt_A->scan, - mps_fmt_A->skip, - mps_fmt_A->fwd, - mps_fmt_A->isfwd, - mps_fmt_A->copy, - mps_fmt_A->pad, - NULL, - (Size)0); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_fmt_o = (mps_fmt_t)format; - return MPS_RES_OK; -} - - -/* mps_fmt_create_B -- create an object format of variant B */ - -mps_res_t mps_fmt_create_B(mps_fmt_t *mps_fmt_o, - mps_arena_t arena, - mps_fmt_B_s *mps_fmt_B) -{ - Format format; - Res res; - - ArenaEnter(arena); - - AVER(mps_fmt_B != NULL); - - res = FormatCreate(&format, - arena, - (Align)mps_fmt_B->align, - FormatVarietyB, - mps_fmt_B->scan, - mps_fmt_B->skip, - mps_fmt_B->fwd, - mps_fmt_B->isfwd, - mps_fmt_B->copy, - mps_fmt_B->pad, - mps_fmt_B->mps_class, - (Size)0); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_fmt_o = (mps_fmt_t)format; - return MPS_RES_OK; -} - - -/* mps_fmt_create_auto_header -- create a format of variant auto_header */ - -mps_res_t mps_fmt_create_auto_header(mps_fmt_t *mps_fmt_o, - mps_arena_t arena, - mps_fmt_auto_header_s *mps_fmt) -{ - Format format; - Res res; - - ArenaEnter(arena); - - AVER(mps_fmt != NULL); - - res = FormatCreate(&format, - arena, - (Align)mps_fmt->align, - FormatVarietyAutoHeader, - mps_fmt->scan, - mps_fmt->skip, - mps_fmt->fwd, - mps_fmt->isfwd, - NULL, - mps_fmt->pad, - NULL, - (Size)mps_fmt->mps_headerSize); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_fmt_o = (mps_fmt_t)format; - return MPS_RES_OK; -} - - -/* mps_fmt_create_fixed -- create an object format of variant fixed */ - -mps_res_t mps_fmt_create_fixed(mps_fmt_t *mps_fmt_o, - mps_arena_t arena, - mps_fmt_fixed_s *mps_fmt_fixed) -{ - Format format; - Res res; - - ArenaEnter(arena); - - AVER(mps_fmt_fixed != NULL); - - res = FormatCreate(&format, - arena, - (Align)mps_fmt_fixed->align, - FormatVarietyFixed, - mps_fmt_fixed->scan, - NULL, - mps_fmt_fixed->fwd, - mps_fmt_fixed->isfwd, - NULL, - mps_fmt_fixed->pad, - NULL, - (Size)0); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_fmt_o = (mps_fmt_t)format; - return MPS_RES_OK; -} - - -/* mps_fmt_destroy -- destroy a format object */ - -void mps_fmt_destroy(mps_fmt_t format) -{ - Arena arena; - - AVER(TESTT(Format, format)); - arena = FormatArena(format); - - ArenaEnter(arena); - - FormatDestroy(format); - - ArenaLeave(arena); -} - - -mps_res_t mps_pool_create(mps_pool_t *mps_pool_o, mps_arena_t arena, - mps_class_t mps_class, ...) -{ - mps_res_t res; - va_list args; - va_start(args, mps_class); - res = mps_pool_create_v(mps_pool_o, arena, mps_class, args); - va_end(args); - return res; -} - -mps_res_t mps_pool_create_v(mps_pool_t *mps_pool_o, mps_arena_t arena, - mps_class_t class, va_list args) -{ - Pool pool; - Res res; - - ArenaEnter(arena); - - AVER(mps_pool_o != NULL); - AVERT(Arena, arena); - AVERT(PoolClass, class); - - res = PoolCreateV(&pool, arena, class, args); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_pool_o = (mps_pool_t)pool; - return res; -} - -void mps_pool_destroy(mps_pool_t pool) -{ - Arena arena; - - AVER(TESTT(Pool, pool)); - arena = PoolArena(pool); - - ArenaEnter(arena); - - PoolDestroy(pool); - - ArenaLeave(arena); -} - - -mps_res_t mps_alloc(mps_addr_t *p_o, mps_pool_t pool, size_t size, ...) -{ - Arena arena; - Addr p; - Res res; - - AVER(TESTT(Pool, pool)); - arena = PoolArena(pool); - - ArenaEnter(arena); - - ArenaPoll(ArenaGlobals(arena)); /* .poll */ - - AVER(p_o != NULL); - AVERT(Pool, pool); - AVER(size > 0); - /* Note: class may allow unaligned size, see */ - /* . */ - /* Rest ignored, see .varargs. */ - - /* @@@@ There is currently no requirement for reservoirs to work */ - /* with unbuffered allocation. */ - res = PoolAlloc(&p, pool, size, FALSE); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *p_o = (mps_addr_t)p; - return MPS_RES_OK; -} - - -mps_res_t mps_alloc_v(mps_addr_t *p_o, mps_pool_t mps_pool, size_t size, - va_list args) -{ - mps_res_t res; - - UNUSED(args); /* See .varargs. */ - res = mps_alloc(p_o, mps_pool, size); - return res; -} - - -void mps_free(mps_pool_t pool, mps_addr_t p, size_t size) -{ - Arena arena; - - AVER(TESTT(Pool, pool)); - arena = PoolArena(pool); - - ArenaEnter(arena); - - AVERT(Pool, pool); - AVER(PoolHasAddr(pool, p)); - AVER(size > 0); - /* Note: class may allow unaligned size, see */ - /* . */ - - PoolFree(pool, (Addr)p, size); - ArenaLeave(arena); -} - - -/* mps_ap_create -- create an allocation point */ - -mps_res_t mps_ap_create(mps_ap_t *mps_ap_o, mps_pool_t pool, ...) -{ - Arena arena; - Buffer buf; - BufferClass bufclass; - Res res; - va_list args; - - AVER(mps_ap_o != NULL); - AVER(TESTT(Pool, pool)); - arena = PoolArena(pool); - - ArenaEnter(arena); - - AVERT(Pool, pool); - - va_start(args, pool); - bufclass = PoolDefaultBufferClass(pool); - res = BufferCreateV(&buf, bufclass, pool, TRUE, args); - va_end(args); - - ArenaLeave(arena); - - if (res != ResOK) - return res; - *mps_ap_o = BufferAP(buf); - return MPS_RES_OK; -} - - -/* mps_ap_create_v -- create an allocation point, with varargs */ - -mps_res_t mps_ap_create_v(mps_ap_t *mps_ap_o, mps_pool_t pool, - va_list args) -{ - Arena arena; - Buffer buf; - BufferClass bufclass; - Res res; - - AVER(mps_ap_o != NULL); - AVER(TESTT(Pool, pool)); - arena = PoolArena(pool); - - ArenaEnter(arena); - - AVERT(Pool, pool); - - bufclass = PoolDefaultBufferClass(pool); - res = BufferCreateV(&buf, bufclass, pool, TRUE, args); - - ArenaLeave(arena); - - if (res != ResOK) - return res; - *mps_ap_o = BufferAP(buf); - return MPS_RES_OK; -} - -void mps_ap_destroy(mps_ap_t mps_ap) -{ - Buffer buf = BufferOfAP(mps_ap); - Arena arena; - - AVER(mps_ap != NULL); - AVER(TESTT(Buffer, buf)); - arena = BufferArena(buf); - - ArenaEnter(arena); - - BufferDestroy(buf); - - ArenaLeave(arena); -} - - -/* mps_reserve -- allocate store in preparation for initialization - * - * .reserve.call: mps_reserve does not call BufferReserve, but instead - * uses the in-line macro from . This is so that it calls - * mps_ap_fill and thence ArenaPoll (.poll). The consistency checks are - * those which can be done outside the MPM. See also .commit.call. */ - -mps_res_t (mps_reserve)(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size) -{ - mps_res_t res; - - AVER(p_o != NULL); - AVER(mps_ap != NULL); - AVER(TESTT(Buffer, BufferOfAP(mps_ap))); - AVER(mps_ap->init == mps_ap->alloc); - AVER(size > 0); - - MPS_RESERVE_BLOCK(res, *p_o, mps_ap, size); - - return res; -} - - - -mps_res_t mps_reserve_with_reservoir_permit(mps_addr_t *p_o, - mps_ap_t mps_ap, size_t size) -{ - mps_res_t res; - - AVER(p_o != NULL); - AVER(size > 0); - AVER(mps_ap != NULL); - AVER(TESTT(Buffer, BufferOfAP(mps_ap))); - AVER(mps_ap->init == mps_ap->alloc); - - MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK(res, *p_o, mps_ap, size); - - return res; -} - - - -/* mps_commit -- commit initialized object, finishing allocation - * - * .commit.call: mps_commit does not call BufferCommit, but instead uses - * the in-line commit macro from . This is so that it calls - * mps_ap_trip and thence ArenaPoll in future (.poll). The consistency - * checks here are the ones which can be done outside the MPM. See also - * .reserve.call. */ - -mps_bool_t (mps_commit)(mps_ap_t mps_ap, mps_addr_t p, size_t size) -{ - AVER(mps_ap != NULL); - AVER(TESTT(Buffer, BufferOfAP(mps_ap))); - AVER(p != NULL); - AVER(size > 0); - AVER(p == mps_ap->init); - AVER((void *)((char *)mps_ap->init + size) == mps_ap->alloc); - - return mps_commit(mps_ap, p, size); -} - - -/* Allocation frame support - * - * These are candidates for being inlineable as macros. - * These functions are easier to maintain, so we'll avoid - * macros for now. */ - - -/* mps_ap_frame_push -- push a new allocation frame - * - * See . */ - -mps_res_t (mps_ap_frame_push)(mps_frame_t *frame_o, mps_ap_t mps_ap) -{ - AVER(frame_o != NULL); - AVER(mps_ap != NULL); - - /* Fail if between reserve & commit */ - if ((char *)mps_ap->alloc != (char *)mps_ap->init) { - return MPS_RES_FAIL; - } - - if (!mps_ap->_lwpoppending) { - /* Valid state for a lightweight push */ - *frame_o = (mps_frame_t)mps_ap->init; - return MPS_RES_OK; - } else { - /* Need a heavyweight push */ - Buffer buf = BufferOfAP(mps_ap); - Arena arena; - AllocFrame frame; - Res res; - - AVER(TESTT(Buffer, buf)); - arena = BufferArena(buf); - - ArenaEnter(arena); - AVERT(Buffer, buf); - - res = BufferFramePush(&frame, buf); - - if (res == ResOK) { - *frame_o = (mps_frame_t)frame; - } - ArenaLeave(arena); - return (mps_res_t)res; - } -} - -/* mps_ap_frame_pop -- push a new allocation frame - * - * See . */ - -mps_res_t (mps_ap_frame_pop)(mps_ap_t mps_ap, mps_frame_t frame) -{ - AVER(mps_ap != NULL); - /* Can't check frame because it's an arbitrary value */ - - /* Fail if between reserve & commit */ - if ((char *)mps_ap->alloc != (char *)mps_ap->init) { - return MPS_RES_FAIL; - } - - if (mps_ap->_enabled) { - /* Valid state for a lightweight pop */ - mps_ap->_frameptr = (mps_addr_t)frame; /* record pending pop */ - mps_ap->_lwpoppending = TRUE; - mps_ap->limit = (mps_addr_t)0; /* trap the buffer */ - return MPS_RES_OK; - - } else { - /* Need a heavyweight pop */ - Buffer buf = BufferOfAP(mps_ap); - Arena arena; - Res res; - - AVER(TESTT(Buffer, buf)); - arena = BufferArena(buf); - - ArenaEnter(arena); - AVERT(Buffer, buf); - - res = BufferFramePop(buf, (AllocFrame)frame); - - ArenaLeave(arena); - return (mps_res_t)res; - } -} - - -/* mps_ap_fill -- called by mps_reserve when an AP hasn't enough arena - * - * .ap.fill.internal: Note that mps_ap_fill should never be "called" - * directly by the client code. It is invoked by the mps_reserve macro. */ - -mps_res_t mps_ap_fill(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size) -{ - Buffer buf = BufferOfAP(mps_ap); - Arena arena; - Addr p; - Res res; - - AVER(mps_ap != NULL); - AVER(TESTT(Buffer, buf)); - arena = BufferArena(buf); - - ArenaEnter(arena); - - ArenaPoll(ArenaGlobals(arena)); /* .poll */ - - AVER(p_o != NULL); - AVERT(Buffer, buf); - AVER(size > 0); - AVER(SizeIsAligned(size, BufferPool(buf)->alignment)); - - res = BufferFill(&p, buf, size, FALSE); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *p_o = (mps_addr_t)p; - return MPS_RES_OK; -} - - -mps_res_t mps_ap_fill_with_reservoir_permit(mps_addr_t *p_o, mps_ap_t mps_ap, - size_t size) -{ - Buffer buf = BufferOfAP(mps_ap); - Arena arena; - Addr p; - Res res; - - AVER(mps_ap != NULL); - AVER(TESTT(Buffer, buf)); - arena = BufferArena(buf); - - ArenaEnter(arena); - - ArenaPoll(ArenaGlobals(arena)); /* .poll */ - - AVER(p_o != NULL); - AVERT(Buffer, buf); - AVER(size > 0); - AVER(SizeIsAligned(size, BufferPool(buf)->alignment)); - - res = BufferFill(&p, buf, size, TRUE); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *p_o = (mps_addr_t)p; - return MPS_RES_OK; -} - - -/* mps_ap_trip -- called by mps_commit when an AP is tripped - * - * .ap.trip.internal: Note that mps_ap_trip should never be "called" - * directly by the client code. It is invoked by the mps_commit macro. */ - -mps_bool_t mps_ap_trip(mps_ap_t mps_ap, mps_addr_t p, size_t size) -{ - Buffer buf = BufferOfAP(mps_ap); - Arena arena; - Bool b; - - AVER(mps_ap != NULL); - AVER(TESTT(Buffer, buf)); - arena = BufferArena(buf); - - ArenaEnter(arena); - - AVERT(Buffer, buf); - AVER(size > 0); - AVER(SizeIsAligned(size, BufferPool(buf)->alignment)); - - b = BufferTrip(buf, (Addr)p, size); - - ArenaLeave(arena); - - return b; -} - - -/* mps_sac_create -- create an SAC object */ - -mps_res_t mps_sac_create(mps_sac_t *mps_sac_o, mps_pool_t pool, - size_t classes_count, mps_sac_classes_s *classes) -{ - Arena arena; - SAC sac; - Res res; - - AVER(mps_sac_o != NULL); - AVER(TESTT(Pool, pool)); - arena = PoolArena(pool); - - ArenaEnter(arena); - - res = SACCreate(&sac, pool, (Count)classes_count, classes); - - ArenaLeave(arena); - - if (res != ResOK) return (mps_res_t)res; - *mps_sac_o = ExternalSACOfSAC(sac); - return (mps_res_t)res; -} - - -/* mps_sac_destroy -- destroy an SAC object */ - -void mps_sac_destroy(mps_sac_t mps_sac) -{ - SAC sac = SACOfExternalSAC(mps_sac); - Arena arena; - - AVER(TESTT(SAC, sac)); - arena = SACArena(sac); - - ArenaEnter(arena); - - SACDestroy(sac); - - ArenaLeave(arena); -} - - -/* mps_sac_flush -- flush an SAC, releasing all memory held in it */ - -void mps_sac_flush(mps_sac_t mps_sac) -{ - SAC sac = SACOfExternalSAC(mps_sac); - Arena arena; - - AVER(TESTT(SAC, sac)); - arena = SACArena(sac); - - ArenaEnter(arena); - - SACFlush(sac); - - ArenaLeave(arena); -} - - -/* mps_sac_fill -- alloc an object, and perhaps fill the cache */ - -mps_res_t mps_sac_fill(mps_addr_t *p_o, mps_sac_t mps_sac, size_t size, - mps_bool_t has_reservoir_permit) -{ - SAC sac = SACOfExternalSAC(mps_sac); - Arena arena; - Addr p = NULL; /* suppress "may be used uninitialized" */ - Res res; - - AVER(p_o != NULL); - AVER(TESTT(SAC, sac)); - arena = SACArena(sac); - - ArenaEnter(arena); - - res = SACFill(&p, sac, size, (has_reservoir_permit != 0)); - - ArenaLeave(arena); - - if (res != ResOK) return (mps_res_t)res; - *p_o = (mps_addr_t)p; - return (mps_res_t)res; -} - - -/* mps_sac_empty -- free an object, and perhaps empty the cache */ - -void mps_sac_empty(mps_sac_t mps_sac, mps_addr_t p, size_t size) -{ - SAC sac = SACOfExternalSAC(mps_sac); - Arena arena; - - AVER(TESTT(SAC, sac)); - arena = SACArena(sac); - - ArenaEnter(arena); - - SACEmpty(sac, (Addr)p, (Size)size); - - ArenaLeave(arena); -} - - -/* mps_sac_alloc -- alloc an object, using cached space if possible */ - -mps_res_t mps_sac_alloc(mps_addr_t *p_o, mps_sac_t mps_sac, size_t size, - mps_bool_t has_reservoir_permit) -{ - Res res; - - AVER(p_o != NULL); - AVER(TESTT(SAC, SACOfExternalSAC(mps_sac))); - AVER(size > 0); - - MPS_SAC_ALLOC_FAST(res, *p_o, mps_sac, size, (has_reservoir_permit != 0)); - return res; -} - - -/* mps_sac_free -- free an object, to the cache if possible */ - -void mps_sac_free(mps_sac_t mps_sac, mps_addr_t p, size_t size) -{ - AVER(TESTT(SAC, SACOfExternalSAC(mps_sac))); - /* Can't check p outside arena lock */ - AVER(size > 0); - - MPS_SAC_FREE_FAST(mps_sac, p, size); -} - - -/* Roots */ - - -mps_res_t mps_root_create(mps_root_t *mps_root_o, mps_arena_t arena, - mps_rank_t mps_rank, mps_rm_t mps_rm, - mps_root_scan_t mps_root_scan, void *p, size_t s) -{ - Rank rank = (Rank)mps_rank; - Root root; - Res res; - - ArenaEnter(arena); - - AVER(mps_root_o != NULL); - AVER(mps_rm == (mps_rm_t)0); - - /* See .root-mode. */ - res = RootCreateFun(&root, arena, rank, mps_root_scan, p, s); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_root_o = (mps_root_t)root; - return MPS_RES_OK; -} - -mps_res_t mps_root_create_table(mps_root_t *mps_root_o, mps_arena_t arena, - mps_rank_t mps_rank, mps_rm_t mps_rm, - mps_addr_t *base, size_t size) -{ - Rank rank = (Rank)mps_rank; - Root root; - RootMode mode = (RootMode)mps_rm; - Res res; - - ArenaEnter(arena); - - AVER(mps_root_o != NULL); - AVER(base != NULL); - AVER(size > 0); - - /* .root.table-size: size is the length of the array at base, not */ - /* the size in bytes. However, RootCreateTable expects base and */ - /* limit pointers. Be careful. */ - - res = RootCreateTable(&root, arena, rank, mode, - (Addr *)base, (Addr *)base + size); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_root_o = (mps_root_t)root; - return MPS_RES_OK; -} - -mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o, - mps_arena_t arena, - mps_rank_t mps_rank, mps_rm_t mps_rm, - mps_addr_t *base, size_t size, - mps_word_t mask) -{ - Rank rank = (Rank)mps_rank; - Root root; - RootMode mode = (RootMode)mps_rm; - Res res; - - ArenaEnter(arena); - - AVER(mps_root_o != NULL); - AVER(base != NULL); - AVER(size > 0); - /* Can't check anything about mask */ - - /* See .root.table-size. */ - - res = RootCreateTableMasked(&root, arena, rank, mode, - (Addr *)base, (Addr *)base + size, - mask); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_root_o = (mps_root_t)root; - return MPS_RES_OK; -} - -mps_res_t mps_root_create_fmt(mps_root_t *mps_root_o, mps_arena_t arena, - mps_rank_t mps_rank, mps_rm_t mps_rm, - mps_fmt_scan_t scan, - mps_addr_t base, mps_addr_t limit) -{ - Rank rank = (Rank)mps_rank; - Root root; - RootMode mode = (RootMode)mps_rm; - Res res; - - ArenaEnter(arena); - - AVER(mps_root_o != NULL); - - res = RootCreateFmt(&root, arena, rank, mode, scan, (Addr)base, (Addr)limit); - - ArenaLeave(arena); - if (res != ResOK) return res; - *mps_root_o = (mps_root_t)root; - return MPS_RES_OK; -} - -mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena, - mps_rank_t mps_rank, mps_rm_t mps_rm, - mps_thr_t thread, mps_reg_scan_t mps_reg_scan, - void *reg_scan_p, size_t mps_size) -{ - Rank rank = (Rank)mps_rank; - Root root; - Res res; - - ArenaEnter(arena); - - AVER(mps_root_o != NULL); - AVER(mps_reg_scan != NULL); - AVER(mps_reg_scan == mps_stack_scan_ambig); /* .reg.scan */ - AVER(reg_scan_p != NULL); /* stackBot */ - AVER(rank == mps_rank_ambig()); - AVER(mps_rm == (mps_rm_t)0); - - /* See .root-mode. */ - res = RootCreateReg(&root, arena, rank, thread, - mps_reg_scan, reg_scan_p, mps_size); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_root_o = (mps_root_t)root; - return MPS_RES_OK; -} - - -/* mps_stack_scan_ambig -- scan the thread state ambiguously - * - * See .reg-scan. */ - -mps_res_t mps_stack_scan_ambig(mps_ss_t mps_ss, - mps_thr_t thread, void *p, size_t s) -{ - ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss); - UNUSED(s); - return ThreadScan(ss, thread, p); -} - - -void mps_root_destroy(mps_root_t mps_root) -{ - Root root = (Root)mps_root; - Arena arena; - - arena = RootArena(root); - - ArenaEnter(arena); - - RootDestroy(root); - - ArenaLeave(arena); -} - - -void (mps_tramp)(void **r_o, - void *(*f)(void *p, size_t s), - void *p, size_t s) -{ - AVER(r_o != NULL); - AVER(FUNCHECK(f)); - /* Can't check p and s as they are interpreted by the client */ - - ProtTramp(r_o, f, p, s); -} - - -mps_res_t mps_thread_reg(mps_thr_t *mps_thr_o, mps_arena_t arena) -{ - Thread thread; - Res res; - - ArenaEnter(arena); - - AVER(mps_thr_o != NULL); - AVERT(Arena, arena); - - res = ThreadRegister(&thread, arena); - - ArenaLeave(arena); - - if (res != ResOK) return res; - *mps_thr_o = (mps_thr_t)thread; - return MPS_RES_OK; -} - -void mps_thread_dereg(mps_thr_t thread) -{ - Arena arena; - - AVER(ThreadCheckSimple(thread)); - arena = ThreadArena(thread); - - ArenaEnter(arena); - - ThreadDeregister(thread, arena); - - ArenaLeave(arena); -} - -void mps_ld_reset(mps_ld_t ld, mps_arena_t arena) -{ - ArenaEnter(arena); - LDReset(ld, arena); - ArenaLeave(arena); -} - - -/* mps_ld_add -- add a reference to a location dependency - * - * See . */ - -void mps_ld_add(mps_ld_t ld, mps_arena_t arena, mps_addr_t addr) -{ - LDAdd(ld, arena, (Addr)addr); -} - - -/* mps_ld_merge -- merge two location dependencies - * - * See . */ - -void mps_ld_merge(mps_ld_t ld, mps_arena_t arena, - mps_ld_t from) -{ - LDMerge(ld, arena, from); -} - - -/* mps_ld_isstale -- check whether a location dependency is "stale" - * - * See . */ - -mps_bool_t mps_ld_isstale(mps_ld_t ld, mps_arena_t arena, - mps_addr_t addr) -{ - Bool b; - - b = LDIsStale(ld, arena, (Addr)addr); - - return (mps_bool_t)b; -} - -mps_res_t mps_fix(mps_ss_t mps_ss, mps_addr_t *ref_io) -{ - mps_res_t res; - - MPS_SCAN_BEGIN(mps_ss) { - res = MPS_FIX(mps_ss, ref_io); - } MPS_SCAN_END(mps_ss); - - return res; -} - -mps_word_t mps_collections(mps_arena_t arena) -{ - return ArenaEpoch(arena); /* thread safe: see */ -} - - -/* mps_finalize -- register for finalization */ - -mps_res_t mps_finalize(mps_arena_t arena, mps_addr_t *refref) -{ - Res res; - Addr object; - - ArenaEnter(arena); - - object = (Addr)ArenaPeek(arena, (Ref *)refref); - res = ArenaFinalize(arena, object); - - ArenaLeave(arena); - return res; -} - - -/* mps_definalize -- deregister for finalization */ - -mps_res_t mps_definalize(mps_arena_t arena, mps_addr_t *refref) -{ - Res res; - Addr object; - - ArenaEnter(arena); - - object = (Addr)ArenaPeek(arena, (Ref *)refref); - res = ArenaDefinalize(arena, object); - - ArenaLeave(arena); - return res; -} - - -/* Messages */ - - -void mps_message_type_enable(mps_arena_t arena, - mps_message_type_t mps_type) -{ - MessageType type = (MessageType)mps_type; - - ArenaEnter(arena); - - MessageTypeEnable(arena, type); - - ArenaLeave(arena); -} - -void mps_message_type_disable(mps_arena_t arena, - mps_message_type_t mps_type) -{ - MessageType type = (MessageType)mps_type; - - ArenaEnter(arena); - - MessageTypeDisable(arena, type); - - ArenaLeave(arena); -} - -mps_bool_t mps_message_poll(mps_arena_t arena) -{ - Bool b; - - ArenaEnter(arena); - - b = MessagePoll(arena); - - ArenaLeave(arena); - return b; -} - -mps_bool_t mps_message_queue_type(mps_message_type_t *mps_message_type_return, - mps_arena_t arena) -{ - MessageType type; - Bool b; - - ArenaEnter(arena); - - b = MessageQueueType(&type, arena); - - ArenaLeave(arena); - if (b) { - *mps_message_type_return = (mps_message_type_t)type; - } - return b; -} - -mps_bool_t mps_message_get(mps_message_t *mps_message_return, - mps_arena_t arena, - mps_message_type_t mps_type) -{ - Bool b; - MessageType type = (MessageType)mps_type; - Message message; - - ArenaEnter(arena); - - b = MessageGet(&message, arena, type); - - ArenaLeave(arena); - if (b) { - *mps_message_return = (mps_message_t)message; - } - return b; -} - -void mps_message_discard(mps_arena_t arena, - mps_message_t message) -{ - ArenaEnter(arena); - - MessageDiscard(arena, message); - - ArenaLeave(arena); -} - - -/* Message Methods */ - -/* -- All Message Types */ - -mps_message_type_t mps_message_type(mps_arena_t arena, - mps_message_t message) -{ - MessageType type; - - ArenaEnter(arena); - - type = MessageGetType(message); - - ArenaLeave(arena); - - return (mps_message_type_t)type; -} - -mps_clock_t mps_message_clock(mps_arena_t arena, - mps_message_t message) -{ - Clock postedClock; - - ArenaEnter(arena); - - postedClock = MessageGetClock(message); - - ArenaLeave(arena); - - return (mps_clock_t)postedClock; -} - - -/* -- mps_message_type_finalization */ - -void mps_message_finalization_ref(mps_addr_t *mps_addr_return, - mps_arena_t arena, - mps_message_t message) -{ - Ref ref; - - AVER(mps_addr_return != NULL); - - ArenaEnter(arena); - - AVERT(Arena, arena); - MessageFinalizationRef(&ref, arena, message); - ArenaPoke(arena, (Ref *)mps_addr_return, ref); - - ArenaLeave(arena); -} - -/* -- mps_message_type_gc */ - -size_t mps_message_gc_live_size(mps_arena_t arena, - mps_message_t message) -{ - Size size; - - ArenaEnter(arena); - - AVERT(Arena, arena); - size = MessageGCLiveSize(message); - - ArenaLeave(arena); - return (size_t)size; -} - -size_t mps_message_gc_condemned_size(mps_arena_t arena, - mps_message_t message) -{ - Size size; - - ArenaEnter(arena); - - AVERT(Arena, arena); - size = MessageGCCondemnedSize(message); - - ArenaLeave(arena); - return (size_t)size; -} - -size_t mps_message_gc_not_condemned_size(mps_arena_t arena, - mps_message_t message) -{ - Size size; - - ArenaEnter(arena); - - AVERT(Arena, arena); - size = MessageGCNotCondemnedSize(message); - - ArenaLeave(arena); - return (size_t)size; -} - -/* -- mps_message_type_gc_start */ - -const char *mps_message_gc_start_why(mps_arena_t arena, - mps_message_t message) -{ - const char *s; - - ArenaEnter(arena); - - AVERT(Arena, arena); - - s = MessageGCStartWhy(message); - - ArenaLeave(arena); - - return s; -} - - -/* Alert */ - -mps_res_t mps_alert_collection_set(mps_arena_t arena, - mps_alert_collection_fn_t fn) -{ - ArenaEnter(arena); - arena->alertCollection = fn; - ArenaLeave(arena); - return MPS_RES_OK; -} - - -/* Telemetry */ - -mps_word_t mps_telemetry_control(mps_word_t resetMask, mps_word_t flipMask) -{ - /* Doesn't require locking and isn't arena-specific. */ - return EventControl((Word)resetMask, (Word)flipMask); -} - -mps_word_t mps_telemetry_intern(const char *label) -{ - AVER(label != NULL); - return (mps_word_t)EventInternString(label); -} - -void mps_telemetry_label(mps_addr_t addr, mps_word_t intern_id) -{ - EventLabelAddr((Addr)addr, (Word)intern_id); -} - -void mps_telemetry_flush(void) -{ - /* Telemetry does its own concurrency control, so none here. */ - EventSync(); -} - - -/* Allocation Patterns */ - - -mps_alloc_pattern_t mps_alloc_pattern_ramp(void) -{ - return (mps_alloc_pattern_t)AllocPatternRamp(); -} - -mps_alloc_pattern_t mps_alloc_pattern_ramp_collect_all(void) -{ - return (mps_alloc_pattern_t)AllocPatternRampCollectAll(); -} - - -/* mps_ap_alloc_pattern_begin -- signal start of an allocation pattern - * - * .ramp.hack: There are only two allocation patterns, both ramps. So - * we assume it's a ramp, and call BufferRampBegin/End directly, without - * dispatching. No point in creating a mechanism for that. */ - -mps_res_t mps_ap_alloc_pattern_begin(mps_ap_t mps_ap, - mps_alloc_pattern_t alloc_pattern) -{ - Buffer buf; - Arena arena; - - AVER(mps_ap != NULL); - buf = BufferOfAP(mps_ap); - AVER(TESTT(Buffer, buf)); - - arena = BufferArena(buf); - ArenaEnter(arena); - - BufferRampBegin(buf, (AllocPattern)alloc_pattern); - - ArenaLeave(arena); - return MPS_RES_OK; -} - - -mps_res_t mps_ap_alloc_pattern_end(mps_ap_t mps_ap, - mps_alloc_pattern_t alloc_pattern) -{ - Buffer buf; - Arena arena; - Res res; - - AVER(mps_ap != NULL); - buf = BufferOfAP(mps_ap); - AVER(TESTT(Buffer, buf)); - UNUSED(alloc_pattern); /* .ramp.hack */ - - arena = BufferArena(buf); - ArenaEnter(arena); - - res = BufferRampEnd(buf); - ArenaPoll(ArenaGlobals(arena)); /* .poll */ - - ArenaLeave(arena); - return res; -} - - -mps_res_t mps_ap_alloc_pattern_reset(mps_ap_t mps_ap) -{ - Buffer buf; - Arena arena; - - AVER(mps_ap != NULL); - buf = BufferOfAP(mps_ap); - AVER(TESTT(Buffer, buf)); - - arena = BufferArena(buf); - ArenaEnter(arena); - - BufferRampReset(buf); - ArenaPoll(ArenaGlobals(arena)); /* .poll */ - - ArenaLeave(arena); - return MPS_RES_OK; -} - - -/* Low memory reservoir */ - - -/* mps_reservoir_limit_set -- set the reservoir size */ - -void mps_reservoir_limit_set(mps_arena_t arena, size_t size) -{ - ArenaEnter(arena); - ReservoirSetLimit(ArenaReservoir(arena), size); - ArenaLeave(arena); -} - - -/* mps_reservoir_limit -- return the reservoir size */ - -size_t mps_reservoir_limit(mps_arena_t arena) -{ - Size size; - - ArenaEnter(arena); - - size = ReservoirLimit(ArenaReservoir(arena)); - - ArenaLeave(arena); - return size; -} - - -/* mps_reservoir_available -- return memory available in the reservoir */ - -size_t mps_reservoir_available(mps_arena_t arena) -{ - Size size; - - ArenaEnter(arena); - - size = ReservoirAvailable(ArenaReservoir(arena)); - - ArenaLeave(arena); - return size; -} - - -/* Chains */ - - -/* mps_chain_create -- create a chain */ - -mps_res_t mps_chain_create(mps_chain_t *chain_o, mps_arena_t arena, - size_t gen_count, mps_gen_param_s *params) -{ - Chain chain; - Res res; - - ArenaEnter(arena); - - AVER(gen_count > 0); - res = ChainCreate(&chain, arena, gen_count, (GenParamStruct *)params); - - ArenaLeave(arena); - if (res != ResOK) - return res; - *chain_o = (mps_chain_t)chain; - return MPS_RES_OK; -} - - -/* mps_chain_destroy -- destroy a chain */ - -void mps_chain_destroy(mps_chain_t chain) -{ - Arena arena; - - AVER(TESTT(Chain, chain)); - arena = chain->arena; - - ArenaEnter(arena); - ChainDestroy(chain); - ArenaLeave(arena); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003, 2006, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsicv.c b/mps/code/mpsicv.c deleted file mode 100644 index 0c003442aff..00000000000 --- a/mps/code/mpsicv.c +++ /dev/null @@ -1,646 +0,0 @@ -/* mpsicv.c: MPSI COVERAGE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - */ - -#include "testlib.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "mpscmv.h" -#include "fmthe.h" -#include "fmtdy.h" -#include "fmtdytst.h" -#include "mps.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -# include "mpsw3.h" -#endif -#include -#include -#include -#include - - -#define exactRootsCOUNT 49 -#define ambigRootsCOUNT 49 -#define OBJECTS 200000 -#define patternFREQ 100 - -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) -#define FILLER_OBJECT_SIZE 1023 - -#define genCOUNT 2 -static mps_gen_param_s testChain[genCOUNT] = { - { 150, 0.85 }, { 170, 0.45 } }; - - -static mps_pool_t amcpool; -static mps_ap_t ap; -static size_t ap_headerSIZE = 0; -/* For this ap.... */ -/* Auto_header format - * - * [ auto_header ][===object===] - * ^pMps ^pCli - * <-----------sizeMps---------> - * <---sizeCli--> - * - * Note: pMps < pCli; sizeMps > sizeCli. - */ -#define PtrMps2Cli(n) ((char*)n + ap_headerSIZE) -#define PtrCli2Mps(n) ((char*)n - ap_headerSIZE) -#define SizeMps2Cli(n) (n - ap_headerSIZE) -#define SizeCli2Mps(n) (n + ap_headerSIZE) -#define HeaderInit(pMps) do { \ - if(ap_headerSIZE != 0) { \ - mps_addr_t pMps_MACROCOPY = (pMps); /* macro hygiene */ \ - ((int*)pMps_MACROCOPY)[0] = realHeader; \ - ((int*)pMps_MACROCOPY)[1] = 0xED0ED; \ - } \ - } while(0) - -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; - - -/* Types for alignment tests */ - -#define hasLONG_LONG 1 - -#ifdef _MSC_VER -#define long_long_t __int64 -#else -#define long_long_t long long -#endif - -struct tdouble { - double d; -}; - -struct tlong { - long d; -}; - -#ifdef HAS_LONG_LONG -struct tlonglong { - long_long_t d; -}; -#endif - - -/* alignmentTest -- test default alignment is acceptable */ - -#define max(a, b) (((a) > (b)) ? (a) : (b)) - -static void alignmentTest(mps_arena_t arena) -{ - mps_pool_t pool; - void *p; - int dummy = 0; - size_t j, size; - - die(mps_pool_create(&pool, arena, mps_class_mv(), - (size_t)0x1000, (size_t)1024, (size_t)16384), - "alignment pool create"); - size = max(sizeof(double), sizeof(long)); -#ifdef HAS_LONG_LONG - size = max(size, sizeof(long_long_t)); -#endif - for(j = 0; j <= size + (size_t)1; ++j) { - die(mps_alloc(&p, pool, size + 1), "alignment alloc"); - -#define access(type, p) *(type*)(p) = (type)dummy; dummy += (int)*(type*)(p); - - access(double, p); - access(long, p); -#ifdef HAS_LONG_LONG - access(long_long_t, p); -#endif - } - mps_pool_destroy(pool); -} - - -/* make -- allocate an object */ - -static mps_addr_t make(void) -{ - size_t length = rnd() % 20; - size_t sizeCli = (length+2)*sizeof(mps_word_t); - size_t sizeMps = SizeCli2Mps(sizeCli); - mps_addr_t pMps, pCli; - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, pMps, ap, sizeMps); - if (res != MPS_RES_OK) die(res, "MPS_RESERVE_BLOCK"); - HeaderInit(pMps); - pCli = PtrMps2Cli(pMps); - res = dylan_init(pCli, sizeCli, exactRoots, exactRootsCOUNT); - if (res != MPS_RES_OK) die(res, "dylan_init"); - } while(!mps_commit(ap, pMps, sizeMps)); - - return pCli; -} - - -/* make_with_permit -- allocate an object, with reservoir permit */ - -static mps_addr_t make_with_permit(void) -{ - size_t length = rnd() % 20; - size_t sizeCli = (length+2)*sizeof(mps_word_t); - size_t sizeMps = SizeCli2Mps(sizeCli); - mps_addr_t pMps, pCli; - mps_res_t res; - - do { - MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK(res, pMps, ap, sizeMps); - if (res != MPS_RES_OK) die(res, "MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK"); - HeaderInit(pMps); - pCli = PtrMps2Cli(pMps); - res = dylan_init(pCli, sizeCli, exactRoots, exactRootsCOUNT); - if (res != MPS_RES_OK) die(res, "dylan_init"); - } while(!mps_commit(ap, pMps, sizeMps)); - - return pCli; -} - - -/* make_no_inline -- allocate an object, using non-inlined interface */ - -static mps_addr_t make_no_inline(void) -{ - size_t length = rnd() % 20; - size_t sizeCli = (length+2)*sizeof(mps_word_t); - size_t sizeMps = SizeCli2Mps(sizeCli); - mps_addr_t pMps, pCli; - mps_res_t res; - - do { - res = (mps_reserve)(&pMps, ap, sizeMps); - if (res != MPS_RES_OK) die(res, "(mps_reserve)"); - HeaderInit(pMps); - pCli = PtrMps2Cli(pMps); - res = dylan_init(pCli, sizeCli, exactRoots, exactRootsCOUNT); - if (res != MPS_RES_OK) die(res, "dylan_init"); - } while(!(mps_commit)(ap, pMps, sizeMps)); - - return pCli; -} - - -/* alloc_v_test -- test mps_alloc_v */ - -static void alloc_v_test(mps_pool_t pool, ...) -{ - void *p; - size_t size = 32; - va_list args; - - va_start(args, pool); - die(mps_alloc_v(&p, pool, size, args), "alloc_v"); - va_end(args); - mps_free(pool, p, size); -} - - -static void pool_create_v_test(mps_arena_t arena, ...) -{ - va_list args; - - va_start(args, arena); - die(mps_pool_create_v(&amcpool, arena, mps_class_amc(), args), - "pool_create_v(amc)"); - va_end(args); -} - -static void ap_create_v_test(mps_pool_t pool, ...) -{ - mps_ap_t apt; - va_list args; - - va_start(args, pool); - die(mps_ap_create_v(&apt, pool, args), "ap_create_v"); - va_end(args); - mps_ap_destroy(apt); -} - - -/* addr_pool_test - * - * intended to test: - * mps_addr_pool - * mps_addr_fmt - */ - -static void addr_pool_test(mps_arena_t arena, - mps_addr_t obj1, /* unformatted */ - mps_pool_t pool1, - mps_addr_t obj2, /* formatted */ - mps_pool_t pool2, - mps_fmt_t fmt2) -{ - /* Things we might test. An addr might be: - * 0- a valid reference to an MPS-managed object; - * 1- interior pointer to an MPS-managed object; - * 2- pointer into some other part of a Seg owned by a Pool; - * ^^^(mps_addr_pool returns TRUE for these) - * 3- pointer to some MPS memory that's not a Seg; - * 4- pointer to unmapped memory; - * 5- pointer to memory not in any Chunk. - * ^^^(mps_addr_pool returns FALSE for these) - * - * We actually test case 0 (for both unformatted and formatted - * objects), and case 5. - */ - - mps_bool_t b; - mps_addr_t addr; - /* DISTInguished values are to observe overwrites. */ - mps_pool_t poolDistinguished = (mps_pool_t)MPS_WORD_CONST(0x000d1521); - mps_pool_t pool = poolDistinguished; - mps_fmt_t fmtDistinguished = (mps_fmt_t)MPS_WORD_CONST(0x000d1521); - mps_fmt_t fmt = fmtDistinguished; - - /* 0a -- obj1 in pool1 (unformatted) */ - addr = obj1; - pool = poolDistinguished; - fmt = fmtDistinguished; - b = mps_addr_pool(&pool, arena, addr); - /* printf("b %d; pool %p; sig %lx\n", b, (void *)pool, - b ? ((mps_word_t*)pool)[0] : (mps_word_t)0); */ - cdie(b == TRUE && pool == pool1, "mps_addr_pool 0a"); - b = mps_addr_fmt(&fmt, arena, addr); - /* printf("b %d; fmt %p; sig %lx\n", b, (void *)fmt, - b ? ((mps_word_t*)fmt)[0] : (mps_word_t)0); */ - cdie(b == FALSE && fmt == fmtDistinguished, "mps_addr_fmt 0a"); - - /* 0b -- obj2 in pool2, with fmt2 */ - addr = obj2; - pool = poolDistinguished; - fmt = fmtDistinguished; - b = mps_addr_pool(&pool, arena, addr); - /* printf("b %d; pool %p; sig %lx\n", b, (void *)pool, - b ? ((mps_word_t*)pool)[0] : (mps_word_t)0); */ - cdie(b == TRUE && pool == pool2, "mps_addr_pool 0b"); - b = mps_addr_fmt(&fmt, arena, addr); - /* printf("b %d; fmt %p; sig %lx\n", b, (void *)fmt, - b ? ((mps_word_t*)fmt)[0] : (mps_word_t)0); */ - cdie(b == TRUE && fmt == fmt2, "mps_addr_fmt 0b"); - - /* 5 */ - addr = &pool; /* point at stack, not in any chunk */ - pool = poolDistinguished; - fmt = fmtDistinguished; - b = mps_addr_pool(&pool, arena, addr); - cdie(b == FALSE && pool == poolDistinguished, "mps_addr_pool 5"); - b = mps_addr_fmt(&fmt, arena, addr); - cdie(b == FALSE && fmt == fmtDistinguished, "mps_addr_fmt 5"); -} - - -static mps_res_t root_single(mps_ss_t ss, void *p, size_t s) -{ - testlib_unused(s); - return mps_fix(ss, (mps_addr_t *)p); -} - - -/* arena_commit_test - * - * intended to test: - * MPS_RES_COMMIT_LIMIT - * mps_arena_commit_limit - * mps_arena_commit_limit_set - * mps_arena_committed - * mps_arena_reserved - * incidentally tests: - * mps_alloc - * mps_class_mv - * mps_pool_create - * mps_pool_destroy - */ - -static void arena_commit_test(mps_arena_t arena) -{ - mps_pool_t pool; - size_t committed; - size_t reserved; - size_t limit; - void *p; - mps_res_t res; - - committed = mps_arena_committed(arena); - reserved = mps_arena_reserved(arena); - cdie(reserved >= committed, "reserved < committed"); - die(mps_pool_create(&pool, arena, mps_class_mv(), - (size_t)0x1000, (size_t)1024, (size_t)16384), - "commit pool create"); - limit = mps_arena_commit_limit(arena); - die(mps_arena_commit_limit_set(arena, committed), "commit_limit_set before"); - do { - res = mps_alloc(&p, pool, FILLER_OBJECT_SIZE); - } while (res == MPS_RES_OK); - die_expect(res, MPS_RES_COMMIT_LIMIT, "Commit limit allocation"); - die(mps_arena_commit_limit_set(arena, limit), "commit_limit_set after"); - res = mps_alloc(&p, pool, FILLER_OBJECT_SIZE); - die_expect(res, MPS_RES_OK, "Allocation failed after raising commit_limit"); - mps_pool_destroy(pool); -} - - -/* reservoir_test -- Test the reservoir interface - * - * This has not been tuned to actually dip into the reservoir. See - * QA test 132 for that. - */ - -#define reservoirSIZE ((size_t)128 * 1024) - -static void reservoir_test(mps_arena_t arena) -{ - (void)make_with_permit(); - cdie(mps_reservoir_available(arena) == 0, "empty reservoir"); - cdie(mps_reservoir_limit(arena) == 0, "no reservoir"); - mps_reservoir_limit_set(arena, reservoirSIZE); - cdie(mps_reservoir_limit(arena) >= reservoirSIZE, "reservoir limit set"); - cdie(mps_reservoir_available(arena) >= reservoirSIZE, "got reservoir"); - (void)make_with_permit(); - mps_reservoir_limit_set(arena, 0); - cdie(mps_reservoir_available(arena) == 0, "empty reservoir"); - cdie(mps_reservoir_limit(arena) == 0, "no reservoir"); - (void)make_with_permit(); -} - - -static void *test(void *arg, size_t s) -{ - mps_arena_t arena; - mps_fmt_t format; - mps_chain_t chain; - mps_root_t exactRoot, ambigRoot, singleRoot, fmtRoot; - unsigned long i; - /* Leave arena clamped until we have allocated this many objects. - is 0 when arena has not been clamped. */ - unsigned long clamp_until = 0; - size_t j; - mps_word_t collections; - mps_pool_t mv; - mps_addr_t alloced_obj; - size_t asize = 32; /* size of alloced obj */ - mps_addr_t obj; - mps_ld_s ld; - mps_alloc_pattern_t ramp = mps_alloc_pattern_ramp(); - size_t rampCount = 0; - mps_res_t res; - - arena = (mps_arena_t)arg; - testlib_unused(s); - - if (rnd() & 1) { - printf("Using auto_header format.\n"); - EnsureHeaderFormat(&format, arena); - ap_headerSIZE = headerSIZE; /* from fmthe.h */ - } else { - printf("Using normal format (no implicit object header: client pointers point at start of storage).\n"); - die(dylan_fmt(&format, arena), "fmt_create"); - ap_headerSIZE = 0; - } - - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - - die(mps_pool_create(&mv, arena, mps_class_mv(), - (size_t)0x10000, (size_t)32, (size_t)0x10000), - "pool_create(mv)"); - - pool_create_v_test(arena, format, chain); /* creates amc pool */ - - ap_create_v_test(amcpool); - - die(mps_ap_create(&ap, amcpool), "ap_create"); - - for(j = 0; j < exactRootsCOUNT; ++j) { - exactRoots[j] = objNULL; - } - for(j = 0; j < ambigRootsCOUNT; ++j) { - ambigRoots[j] = rnd_addr(); - } - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - MPS_WORD_CONST(1)), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); - - obj = objNULL; - - die(mps_root_create(&singleRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &root_single, &obj, 0), - "root_create(single)"); - - /* test non-inlined reserve/commit */ - obj = make_no_inline(); - - die(mps_alloc(&alloced_obj, mv, asize), "mps_alloc"); - die(dylan_init(alloced_obj, asize, exactRoots, exactRootsCOUNT), - "dylan_init(alloced_obj)"); - - addr_pool_test(arena, alloced_obj, mv, make(), amcpool, format); - - die(mps_root_create_fmt(&fmtRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - dylan_fmt_A()->scan, - alloced_obj, - (mps_addr_t)(((char*)alloced_obj)+asize)), - "root_create_fmt"); - - mps_ld_reset(&ld, arena); - mps_ld_add(&ld, arena, obj); - - if (mps_ld_isstale(&ld, arena, obj)) { - mps_ld_reset(&ld, arena); - mps_ld_add(&ld, arena, obj); - } - - collections = mps_collections(arena); - - for(i = 0; i < OBJECTS; ++i) { - mps_word_t c; - size_t r; - - c = mps_collections(arena); - - if(collections != c) { - collections = c; - printf("\nCollection %"PRIuLONGEST", %lu objects.\n", (ulongest_t)c, i); - for(r = 0; r < exactRootsCOUNT; ++r) { - cdie(exactRoots[r] == objNULL || dylan_check(exactRoots[r]), - "all roots check"); - } - if(collections == 1) { - mps_arena_clamp(arena); - clamp_until = i + 10000; - } - if(collections % 6 == 0) { - mps_arena_expose(arena); - mps_arena_release(arena); - } - if(collections % 6 == 3) { - mps_arena_unsafe_expose_remember_protection(arena); - mps_arena_unsafe_restore_protection(arena); - mps_arena_release(arena); - } - if(collections % 6 == 4) { - mps_arena_unsafe_expose_remember_protection(arena); - mps_arena_release(arena); - } - if(collections % 3 == 2) { - mps_arena_park(arena); - mps_arena_release(arena); - } - } - - if(clamp_until && i >= clamp_until) { - mps_arena_release(arena); - clamp_until = 0; - } - - if (rnd() % patternFREQ == 0) { - switch(rnd() % 4) { - case 0: case 1: - die(mps_ap_alloc_pattern_begin(ap, ramp), "alloc_pattern_begin"); - ++rampCount; - break; - case 2: - res = mps_ap_alloc_pattern_end(ap, ramp); - cdie(rampCount > 0 ? res == MPS_RES_OK : res == MPS_RES_FAIL, - "alloc_pattern_end"); - if (rampCount > 0) { - --rampCount; - } - break; - case 3: - die(mps_ap_alloc_pattern_reset(ap), "alloc_pattern_reset"); - rampCount = 0; - break; - } - } - - if (rnd() & 1) { - exactRoots[rnd() % exactRootsCOUNT] = make(); - } else { - ambigRoots[rnd() % ambigRootsCOUNT] = make(); - } - - r = rnd() % exactRootsCOUNT; - if (exactRoots[r] != objNULL) { - cdie(dylan_check(exactRoots[r]), "random root check"); - } - } - - arena_commit_test(arena); - reservoir_test(arena); - alignmentTest(arena); - - die(mps_arena_collect(arena), "collect"); - - mps_free(mv, alloced_obj, 32); - alloc_v_test(mv); - mps_pool_destroy(mv); - mps_ap_destroy(ap); - mps_root_destroy(fmtRoot); - mps_root_destroy(singleRoot); - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); - mps_pool_destroy(amcpool); - mps_chain_destroy(chain); - mps_fmt_destroy(format); - - return NULL; -} - - -#define TEST_ARENA_SIZE ((size_t)16<<20) - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_thr_t thread; - mps_root_t reg_root; - void *r; - void *marker = ▮ - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), TEST_ARENA_SIZE), - "arena_create"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - - die(mps_root_create_reg(®_root, arena, - mps_rank_ambig(), (mps_rm_t)0, - thread, &mps_stack_scan_ambig, - marker, (size_t)0), - "root_create_reg"); - - (mps_tramp)(&r, test, arena, 0); /* non-inlined trampoline */ - mps_tramp(&r, test, arena, 0); - mps_root_destroy(reg_root); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsio.h b/mps/code/mpsio.h deleted file mode 100644 index 77f44c46a38..00000000000 --- a/mps/code/mpsio.h +++ /dev/null @@ -1,67 +0,0 @@ -/* mpsio.h: RAVENBROOK MEMORY POOL SYSTEM I/O INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: For MPS client application developers, MPS developers. - * .sources: - */ - -#ifndef mpsio_h -#define mpsio_h - -#include "mps.h" /* for mps_res_t */ - - -typedef struct mps_io_s *mps_io_t; - -extern mps_res_t mps_io_create(mps_io_t *); -extern void mps_io_destroy(mps_io_t); - -extern mps_res_t mps_io_write(mps_io_t, void *, size_t); -extern mps_res_t mps_io_flush(mps_io_t); - - -#endif /* mpsio_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsioan.c b/mps/code/mpsioan.c deleted file mode 100644 index 966847575fb..00000000000 --- a/mps/code/mpsioan.c +++ /dev/null @@ -1,126 +0,0 @@ -/* mpsioan.c: RAVENBROOK MEMORY POOL SYSTEM I/O IMPLEMENTATION (ANSI) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: For MPS client application developers and MPS developers. - * .sources: - */ - -#include "mpsio.h" - -#include "mpstd.h" - -#ifdef MPS_OS_XC -#include "osxc.h" -#endif - -#include -#include -#include "config.h" /* to get platform configurations */ - - -static FILE *ioFile = NULL; - -#ifdef MPS_BUILD_MV -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: fopen. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - -mps_res_t mps_io_create(mps_io_t *mps_io_r) -{ - FILE *f; - char *filename; - - if(ioFile != NULL) /* See */ - return MPS_RES_LIMIT; /* Cannot currently open more than one log */ - - filename = getenv("MPS_TELEMETRY_FILENAME"); - if(filename == NULL) - filename = "mpsio.log"; - - f = fopen(filename, "wb"); - if(f == NULL) - return MPS_RES_IO; - - *mps_io_r = (mps_io_t)f; - ioFile = f; - return MPS_RES_OK; -} - - -void mps_io_destroy(mps_io_t mps_io) -{ - FILE *f = (FILE *)mps_io; - ioFile = NULL; /* Should check f == ioFile */ - (void)fclose(f); -} - - -mps_res_t mps_io_write(mps_io_t mps_io, void *buf, size_t size) -{ - FILE *f = (FILE *)mps_io; /* Should check f == ioFile */ - size_t n; - - n = fwrite(buf, size, 1, f); - if(n != 1) - return MPS_RES_IO; - - return MPS_RES_OK; -} - - -mps_res_t mps_io_flush(mps_io_t mps_io) -{ - FILE *f = (FILE *)mps_io; /* Should check f == ioFile */ - int e; - - e = fflush(f); - if(e == EOF) - return MPS_RES_IO; - - return MPS_RES_OK; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsiw3.c b/mps/code/mpsiw3.c deleted file mode 100644 index c3cffe8c4c5..00000000000 --- a/mps/code/mpsiw3.c +++ /dev/null @@ -1,73 +0,0 @@ -/* mpsint.c: WIN32 MEMORY POOL SYSTEM INTERFACE LAYER EXTRAS - * - * $Id$ - * - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" -#include "mps.h" - -#include "mpswin.h" - -SRCID(mpsiw3, "$Id$"); - - -/* This is defined in protw3.c */ -extern LONG ProtSEHfilter(LPEXCEPTION_POINTERS info); - -LONG mps_SEH_filter(LPEXCEPTION_POINTERS info, - void **hp_o, size_t *hs_o) -{ - UNUSED(hp_o); - UNUSED(hs_o); - return ProtSEHfilter(info); -} - -void mps_SEH_handler(void *p, size_t s) -{ - UNUSED(p); UNUSED(s); - NOTREACHED; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpslib.h b/mps/code/mpslib.h deleted file mode 100644 index f74bd986fa6..00000000000 --- a/mps/code/mpslib.h +++ /dev/null @@ -1,88 +0,0 @@ -/* mpslib.h: RAVENBROOK MEMORY POOL SYSTEM LIBRARY INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS client application developers, MPS developers. - * .sources: - * - * .purpose: The purpose of this file is to declare the functions and types - * required for the MPS library interface. - */ - -#ifndef mpslib_h -#define mpslib_h - -#include -#include "mps.h" /* mps_clock_t */ - -extern int mps_lib_get_EOF(void); -#define mps_lib_EOF (mps_lib_get_EOF()) - -typedef struct mps_lib_stream_s mps_lib_FILE; - -extern mps_lib_FILE *mps_lib_get_stderr(void); -extern mps_lib_FILE *mps_lib_get_stdout(void); -#define mps_lib_stderr (mps_lib_get_stderr()) -#define mps_lib_stdout (mps_lib_get_stdout()) - -extern int mps_lib_fputc(int, mps_lib_FILE *); -extern int mps_lib_fputs(const char *, mps_lib_FILE *); - -extern void mps_lib_assert_fail(const char *); - -extern void *(mps_lib_memset)(void *, int, size_t); -extern void *(mps_lib_memcpy)(void *, const void *, size_t); -extern int (mps_lib_memcmp)(const void *, const void *, size_t); - - -extern mps_clock_t mps_clock(void); -extern mps_clock_t mps_clocks_per_sec(void); - - -extern unsigned long mps_lib_telemetry_control(void); - - -#endif /* mpslib_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsliban.c b/mps/code/mpsliban.c deleted file mode 100644 index 8abab586319..00000000000 --- a/mps/code/mpsliban.c +++ /dev/null @@ -1,187 +0,0 @@ -/* mpsliban.c: RAVENBROOK MEMORY POOL SYSTEM LIBRARY INTERFACE (ANSI) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * .purpose: The purpose of this code is - * 1. to connect the MPS Library Interface to the ANSI C libraries, - * where they exist, and - * 2. to provide an example of how to implement the MPS Library - * Interface. - * - * .readership: For MPS client application developers and MPS developers. - * .sources: - * - * - * TRANSGRESSIONS (rule.impl.trans) - * - * .trans.file: The ANSI standard says (in section 7.9.1) that FILE is an - * object type, and hence the casts between FILE and mps_lib_FILE (an - * incomplete type) are not necessarily valid. We assume that this trick - * works, however, in all current environments. - */ - -#include "mpslib.h" - -#include "mpstd.h" -#include "event.h" - -#ifdef MPS_OS_XC -#include "osxc.h" -#endif - -#include - -#include -#include -#include - - -int mps_lib_get_EOF(void) -{ - return EOF; -} - -mps_lib_FILE *mps_lib_get_stderr(void) -{ - return (mps_lib_FILE *)stderr; /* see .trans.file */ -} - -mps_lib_FILE *mps_lib_get_stdout(void) -{ - return (mps_lib_FILE *)stdout; /* see .trans.file */ -} - -int mps_lib_fputc(int c, mps_lib_FILE *stream) -{ - return fputc(c, (FILE *)stream); /* see .trans.file */ -} - -int mps_lib_fputs(const char *s, mps_lib_FILE *stream) -{ - return fputs(s, (FILE *)stream); /* see .trans.file */ -} - - -void mps_lib_assert_fail(const char *message) -{ - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nMPS ASSERTION FAILURE: %s\n\nRECENT EVENTS:\n", message); - EventDump((mps_lib_FILE *)stderr); - fflush(stderr); /* make sure the message is output */ - abort(); -} - - -void *(mps_lib_memset)(void *s, int c, size_t n) -{ - return memset(s, c, n); -} - -void *(mps_lib_memcpy)(void *s1, const void *s2, size_t n) -{ - return memcpy(s1, s2, n); -} - -int (mps_lib_memcmp)(const void *s1, const void *s2, size_t n) -{ - return memcmp(s1, s2, n); -} - - -/* @@@@ Platform specific conversion? */ -/* See http://devworld.apple.com/dev/techsupport/insidemac/OSUtilities/OSUtilities-94.html#MARKER-9-32 */ -mps_clock_t mps_clock(void) -{ - return (unsigned long)clock(); -} - - -mps_clock_t mps_clocks_per_sec(void) -{ - return (unsigned long)CLOCKS_PER_SEC; -} - - -/* mps_lib_telemetry_control -- get and interpret MPS_TELEMETRY_CONTROL */ - -#ifdef MPS_BUILD_MV -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: getenv. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - -unsigned long mps_lib_telemetry_control(void) -{ - char *s; - char **null = NULL; - unsigned long mask; - char buf[256]; - char *word; - char *sep = " "; - - s = getenv("MPS_TELEMETRY_CONTROL"); - if (s == NULL) - return 0; - - /* If the value can be read as a number, use it. */ - mask = strtoul(s, null, 0); - if (mask != 0) - return mask; - - /* Split the value at spaces and try to patch the words against the names - of event kinds, enabling them if there's a match. */ - strncpy(buf, s, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; - for (word = strtok(buf, sep); word != NULL; word = strtok(NULL, sep)) { -#define TELEMATCH(X, rowName, rowDoc) \ - if (strcmp(word, #rowName) == 0) \ - mask |= (1ul << EventKind##rowName); - EventKindENUM(TELEMATCH, X) - } - - return mask; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpstd.h b/mps/code/mpstd.h deleted file mode 100644 index 0345810b723..00000000000 --- a/mps/code/mpstd.h +++ /dev/null @@ -1,301 +0,0 @@ -/* mpstd.h: RAVENBROOK MEMORY POOL SYSTEM TARGET DETECTION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2001 Global Graphics Software. - * - * Detect the target platform using predefined preprocessor symbols - * defined by the build environment. The symbols are derived from the - * documentation, or, in the case of GCC, from the compiler itself. - * References to the documentation appear above each detection line. - * - * .macos.ppc.align: MacOS / PowerPC requires 8 bytes alignment (in - * general). See "Mac OS Runtime Architecture", table 4-2. - */ - -#ifndef mpstd_h -#define mpstd_h - -/* DESIGN NOTES - * ------------ - * [These should be moved to a proper buildsys design doc. RHSK] - * - * mpstd.h does two main things: - * 1. platform detection by looking at preprocessor symbols; - * 2. setting variables (eg. MPS_PF_STRING, MPS_WORD_WIDTH). - * - * Sometimes the platform is *already* known by the buildsystem: - * - the Global Graphics buildsystem always sets CONFIG_PF_*. - * - the Ravenbrook buildsystem knows the platform and may (but - * typically does not) set CONFIG_PF_*. - * - * Regardless of this, mpstd.h still attempts to detect the platform. - * (This is intentional). However if both CONFIG_PF_* and - * CONFIG_PF_STRING are set, then mpstd.h performs a third function: - * 3. checking that the detected platform corresponds to that - * specified by CONFIG_PF_*. - * - * Sometimes no MPS buildsystem is in use, so the platform *must* - * be detected. For example, when client software #includes mps.h, - * we want it to just work out of the box with whatever compiler is - * being used. In other words we do not require the client to define - * CONFIG_PF_*. - * (This is the case that justifes mpstd.h doing platform detection - * by looking at preprocessor symbols; otherwise we'd simply use - * CONFIG_PF_*). - * - * mpstd.h fails if it cannot detect the platform (even if CONFIG_PF_* - * is specified). This is intentional. mpstd.h does *not* allow - * CONFIG_PF_* to override the platform as detected from preprocessor - * symbols. This is intentional. - * - * References: - * GG buildsys use of CONFIG_PF_*: - * - */ - - -/* Visual C++ 2.0, Books Online, C/C++ Book, Preprocessor Reference, - * Chapter 1: The Preprocessor, Macros, Predefined Macros. - * Alignment of 4 would work, but the MS library uses 8 bytes for - * doubles and __int64, so we choose that. The actual granularity of - * VC malloc is 16! - */ - -#if defined(_MSC_VER) && defined(_WIN32) && defined(_M_IX86) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_W3I3MV) -#error "specified CONFIG_PF_... inconsistent with detected w3i3mv" -#endif -#define MPS_PF_W3I3MV -#define MPS_PF_STRING "w3i3mv" -#define MPS_OS_W3 -#define MPS_ARCH_I3 -#define MPS_BUILD_MV -#define MPS_T_WORD unsigned long -#define MPS_T_ULONGEST unsigned long -#define MPS_WORD_WIDTH 32 -#define MPS_WORD_SHIFT 5 -#define MPS_PF_ALIGN 8 - - -/* "Predefined Macros" from "Visual Studio 2010" on MSDN - * . - * Note that Win32 includes 64-bit Windows! - * We use the same alignment as MS malloc: 16, which is used for XMM - * operations. - * See MSDN -> x64 Software Conventions -> Overview of x64 Calling Conventions - * - */ - -#elif defined(_MSC_VER) && defined(_WIN32) && defined(_WIN64) && defined(_M_X64) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_W3I6MV) -#error "specified CONFIG_PF_... inconsistent with detected w3i6mv" -#endif -#define MPS_PF_W3I6MV -#define MPS_PF_STRING "w3i6mv" -#define MPS_OS_W3 -#define MPS_ARCH_I6 -#define MPS_BUILD_MV -#define MPS_T_WORD unsigned __int64 -#define MPS_T_LONGEST __int64 -#define MPS_T_ULONGEST unsigned __int64 -#define MPS_WORD_WIDTH 64 -#define MPS_WORD_SHIFT 6 -#define MPS_PF_ALIGN 16 - - -/* GCC 4.0.1 (As supplied by Apple on Mac OS X 10.4.8 on an Intel Mac), - * gcc -E -dM - * And above for xcppgc. - * Note that Clang also defines __GNUC__ since it's generally GCC compatible, - * but that doesn't fit our system so we exclude Clang here. - */ - -#elif defined(__APPLE__) && defined(__i386__) && defined(__MACH__) \ - && defined(__GNUC__) && !defined(__clang__) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_XCI3GC) -#error "specified CONFIG_PF_... inconsistent with detected xci3gc" -#endif -#define MPS_PF_XCI3GC -#define MPS_PF_STRING "xci3gc" -#define MPS_OS_XC -#define MPS_ARCH_I3 -#define MPS_BUILD_GC -#define MPS_T_WORD unsigned long -#define MPS_T_ULONGEST unsigned long -#define MPS_WORD_WIDTH 32 -#define MPS_WORD_SHIFT 5 -#define MPS_PF_ALIGN 4 /* I'm just guessing. */ - - -/* Apple clang version 3.1, clang -E -dM */ - -#elif defined(__APPLE__) && defined(__i386__) && defined(__MACH__) \ - && defined(__clang__) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_XCI3LL) -#error "specified CONFIG_PF_... inconsistent with detected xci3ll" -#endif -#define MPS_PF_XCI3LL -#define MPS_PF_STRING "xci3ll" -#define MPS_OS_XC -#define MPS_ARCH_I3 -#define MPS_BUILD_LL -#define MPS_T_WORD unsigned long -#define MPS_T_ULONGEST unsigned long -#define MPS_WORD_WIDTH 32 -#define MPS_WORD_SHIFT 5 -#define MPS_PF_ALIGN 4 /* I'm just guessing. */ - - -/* Apple clang version 3.1, clang -E -dM */ - -#elif defined(__APPLE__) && defined(__x86_64__) && defined(__MACH__) \ - && defined(__clang__) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_XCI6LL) -#error "specified CONFIG_PF_... inconsistent with detected xci6ll" -#endif -#define MPS_PF_XCI6LL -#define MPS_PF_STRING "xci6ll" -#define MPS_OS_XC -#define MPS_ARCH_I6 -#define MPS_BUILD_LL -#define MPS_T_WORD unsigned long -#define MPS_T_ULONGEST unsigned long -#define MPS_WORD_WIDTH 64 -#define MPS_WORD_SHIFT 6 -#define MPS_PF_ALIGN 8 - - -/* GCC 2.6.3, gcc -E -dM - * The actual granularity of GNU malloc is 8, but field alignments are - * all 4. - */ - -#elif defined(__linux__) && defined(__i386__) && defined(__GNUC__) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_LII3GC) -#error "specified CONFIG_PF_... inconsistent with detected lii3gc" -#endif -#define MPS_PF_LII3GC -#define MPS_PF_STRING "lii3gc" -#define MPS_OS_LI -#define MPS_ARCH_I3 -#define MPS_BUILD_GC -#define MPS_T_WORD unsigned long -#define MPS_T_ULONGEST unsigned long -#define MPS_WORD_WIDTH 32 -#define MPS_WORD_SHIFT 5 -#define MPS_PF_ALIGN 4 - -#ifndef _REENTRANT /* it's also defined by cc -pthread */ -#define _REENTRANT /* defines, e.g., pthread_mutexattr_settype */ -#endif -#define _XOPEN_SOURCE 500 /* to get POSIX signal handling */ -#define _GNU_SOURCE /* to get register numbers for prmci3li.c */ - - -/* GCC 4.6.3, gcc -E -dM */ - -#elif defined(__linux__) && defined(__x86_64) && defined(__GNUC__) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_LII6GC) -#error "specified CONFIG_PF_... inconsistent with detected lii6gc" -#endif -#define MPS_PF_LII6GC -#define MPS_PF_STRING "lii6gc" -#define MPS_OS_LI -#define MPS_ARCH_I6 -#define MPS_BUILD_GC -#define MPS_T_WORD unsigned long -#define MPS_T_ULONGEST unsigned long -#define MPS_WORD_WIDTH 64 -#define MPS_WORD_SHIFT 6 -#define MPS_PF_ALIGN 8 - -#ifndef _REENTRANT /* it's also defined by cc -pthread */ -#define _REENTRANT /* defines, e.g., pthread_mutexattr_settype */ -#endif -#define _XOPEN_SOURCE 500 /* to get POSIX signal handling */ -#define _GNU_SOURCE /* to get register numbers for prmci3li.c */ - - -/* GCC 2.95.3, gcc -E -dM */ - -#elif defined(__FreeBSD__) && defined (__i386__) && defined (__GNUC__) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI3GC) -#error "specified CONFIG_PF_... inconsistent with detected fri3gc" -#endif -#define MPS_PF_FRI3GC -#define MPS_PF_STRING "fri3gc" -#define MPS_OS_FR -#define MPS_ARCH_I3 -#define MPS_BUILD_GC -#define MPS_T_WORD unsigned long -#define MPS_T_ULONGEST unsigned long -#define MPS_WORD_WIDTH 32 -#define MPS_WORD_SHIFT 5 -#define MPS_PF_ALIGN 4 - - -#elif defined(__FreeBSD__) && defined (__x86_64__) && defined (__GNUC__) -#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI6GC) -#error "specified CONFIG_PF_... inconsistent with detected fri6gc" -#endif -#define MPS_PF_FRI6GC -#define MPS_PF_STRING "fri6gc" -#define MPS_OS_FR -#define MPS_ARCH_I6 -#define MPS_BUILD_GC -#define MPS_T_WORD unsigned long -#define MPS_T_ULONGEST unsigned long -#define MPS_WORD_WIDTH 64 -#define MPS_WORD_SHIFT 6 -#define MPS_PF_ALIGN 8 - - -#else -#error "The MPS Kit does not have a configuration for this platform out of the box; see manual/build.txt" -#endif - - -#endif /* mpstd_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002,2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpsw3.h b/mps/code/mpsw3.h deleted file mode 100644 index 2f543ddc0f8..00000000000 --- a/mps/code/mpsw3.h +++ /dev/null @@ -1,79 +0,0 @@ -/* mpsw3.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE, WINDOWS PART - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: customers, MPS developers. - * .sources: . - */ - -#ifndef mpsw3_h -#define mpsw3_h - -#include "mps.h" /* needed for mps_tramp_t */ -#include /* needed for SEH filter */ - - -extern LONG mps_SEH_filter(LPEXCEPTION_POINTERS, void **, size_t *); -extern void mps_SEH_handler(void *, size_t); - - -#define mps_tramp(r_o, f, p, s) \ - MPS_BEGIN \ - void **_r_o = (r_o); \ - mps_tramp_t _f = (f); \ - void *_p = (p); \ - size_t _s = (s); \ - void *_hp = NULL; size_t _hs = 0; \ - __try { \ - *_r_o = (*_f)(_p, _s); \ - } __except(mps_SEH_filter(GetExceptionInformation(), \ - &_hp, &_hs)) { \ - mps_SEH_handler(_hp, _hs); \ - } \ - MPS_END - - -#endif /* mpsw3_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mpswin.h b/mps/code/mpswin.h deleted file mode 100644 index 99317fb790a..00000000000 --- a/mps/code/mpswin.h +++ /dev/null @@ -1,73 +0,0 @@ -/* mpswin.h: RAVENBROOK MEMORY POOL SYSTEM WINDOWS.H INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: For MPS client application developers, MPS developers. - * - * .purpose: Shared file for the incantations needed to include windows.h. - */ - -#ifndef mpswin_h -#define mpswin_h - -/* Suppress Visual C warnings from windows.h at warning level 4. */ -#ifdef MPS_BUILD_MV -#pragma warning(disable: 4115 4201 4209 4214) -#endif - -#include - -#ifdef MPS_BUILD_MV -#pragma warning(default: 4115 4201 4209 4214) -/* windows.h might also cause warnings about "unreferenced inline - * function has been removed". In Visual C, these can be turned off: - * #pragma warning(disable: 4514) - * But they are generated at the end of the compilation, so you have - * to turn them off permanently. - */ -#endif - -#endif /* mpswin_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/mv2test.c b/mps/code/mv2test.c deleted file mode 100644 index d8c80ba0d6a..00000000000 --- a/mps/code/mv2test.c +++ /dev/null @@ -1,366 +0,0 @@ -/* mv2test.c: POOLMVT STRESS TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include -#include -#include -#include "mpstd.h" -#include - -#include "mpscmv2.h" -#include "mps.h" - -typedef MPS_T_WORD mps_count_t; /* machine word (target dep.) */ - -#include "mpslib.h" -#include "mpsavm.h" -#include "testlib.h" - -/* --- to get to describe */ -#include "mpm.h" - -#include - - -/* - * From - * - * "Minimal" random number generator of Park and Miller with - * Bays-Durham shuffle and added safeguards. Returns a uniform random - * deviate between 0.0 and 1.0 (exclusive of the endpoint - * values). Call with idum a negative integer to initialize; - * thereafter, do not alter idum between successive deviates in a - * sequence. RNMX should approximate the largest floating value that - * is less than 1. - */ -#define IA 16807 -#define IM 2147483647 -#define AM (1.0F/IM) -#define IQ 127773 -#define IR 2836 -#define NTAB 32 -#define NDIV (1+(IM-1)/NTAB) -#define EPS 1.2e-7F -#define RNMX (1.0F-EPS) - -static float ran1(long *idum) -{ - int j; - long k; - static long iy=0; - static long iv[NTAB]; - float temp; - if (*idum <= 0 || !iy) { /* Initialize. */ - if (-(*idum) < 1) /* Be sure to prevent idum = 0. */ - *idum=1; - else - *idum = -(*idum); - for (j=NTAB+7;j>=0;j--) { /* Load the shuffle table (after 8 - warm-ups). */ - k=(*idum)/IQ; - *idum=IA*(*idum-k*IQ)-IR*k; - if (*idum < 0) - *idum += IM; - if (j < NTAB) - iv[j] = *idum; - } - iy=iv[0]; - } - k=(*idum)/IQ; /* Start here when not initializing. */ - *idum=IA*(*idum-k*IQ)-IR*k; /* Compute idum=(IA*idum) % IM without - overflows by Schrage's method. */ - if (*idum < 0) *idum += IM; - j=(int)(iy/NDIV); /* Will be in the range 0..NTAB-1. */ - iy=iv[j]; /* Output previously stored value and - refill the shuffle table. */ - iv[j] = *idum; - if ((temp=AM*(float)iy) > RNMX) /* Because users don't expect endpoint - values. */ - return RNMX; - else - return temp; -} - - -/* - * From - * - * Returns an exponentially distributed, positive, random deviate of - * unit mean, using ran1(idum) as the source of uniform deviates. - */ - -static float expdev(long *idum) -{ - float dum; - do - dum=ran1(idum); - while (dum == 0.0); - return (float)-log(dum); -} - - -#ifdef ndef -/* - From: Leva, Joseph L., A fast normal random number generator, ACM Transactions on - Mathematical Software Vol. 18, No. 4 (Dec. 1992), Pages 449-453 -*/ - -static double nrnd(void) -{ - double m = (double)((unsigned)-1); - double u; - double v; - double twor = 1.7156; /* 2 * sqrt(2.0 / exp(1.0)) */ - double s = 0.449871; - double t = -0.386595; - double a = 0.19600; - double b = 0.25472; - double r1 = 0.27597; - double r2 = 0.27846; - double x, y, Q; - -reject: - u = (double)rnd()/m; - v = (double)rnd()/m; - v = twor * (v - 0.5); - x = u - s; - y = fabs(v) - t; - Q = x * x + y * (a * y - b * x); - - if (Q < r1) - goto accept; - if (Q > r2) - goto reject; - if (v * v > -4 * u * u * log(u)) - goto reject; -accept: - return v / u; -} -#endif /* ndef */ - - -#define max(a, b) (((a) > (b)) ? (a) : (b)) - -static size_t min; -static size_t mean; -static size_t max; -static int verbose = 0; -static mps_pool_t pool; - - -extern void DescribeIt(void); - -void DescribeIt(void) -{ - PoolDescribe((Pool)pool, (mps_lib_FILE *)stderr); -} - - -static size_t randomSize(int i) -{ - /* Distribution centered on mean. Verify that allocations - below min and above max are handled correctly */ - static long seed = 7472366; - size_t s = (max - mean)/4; - size_t m = mean; - double r; - double x; - - testlib_unused(i); - - /* per SGR */ - do { - r = expdev(&seed); - x = (double)s * sqrt(2 * r); - x += (double)m; - } while (x <= 1.0); - - return (size_t)x; - -} - - -#define testArenaSIZE ((size_t)64<<20) -#define TEST_SET_SIZE 1234 -#define TEST_LOOPS 27 - -#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - -static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size) -{ - mps_res_t res; - - size = alignUp(size, MPS_PF_ALIGN); - - do { - MPS_RESERVE_BLOCK(res, *p, ap, size); - if(res != MPS_RES_OK) - return res; - } while(!mps_commit(ap, *p, size)); - - return MPS_RES_OK; -} - - -static mps_res_t stress(mps_class_t class, mps_arena_t arena, - size_t (*size)(int i), ...) -{ - mps_res_t res; - mps_ap_t ap; - va_list arg; - int i, k; - int *ps[TEST_SET_SIZE]; - size_t ss[TEST_SET_SIZE]; - - va_start(arg, size); - res = mps_pool_create_v(&pool, arena, class, arg); - va_end(arg); - if(res != MPS_RES_OK) return res; - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - - /* allocate a load of objects */ - for(i=0; i 0) { - mps_free(pool, (mps_addr_t)ps[i], ss[i]); - ss[i] = 0; - } - } - /* allocate some new objects */ - for(i=x; i. - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ntbuild.cmd b/mps/code/ntbuild.cmd deleted file mode 100644 index 3654a479f04..00000000000 --- a/mps/code/ntbuild.cmd +++ /dev/null @@ -1,122 +0,0 @@ -@ECHO OFF -REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -REM $Id$ -REM $Change$ $DateTime$ $Author$ -REM -REM Build the MPS and construct a kit. -REM Copyright (C) 2011 Ravenbrook Limited. All rights reserved. -REM -REM P1 is the name of the release, which should match the name -REM in the version.c source file. -REM The current directory is assumed to be the code directory. -REM -REM -------------------------------------------------------------------- - -SETLOCAL - -SET mpsreleasename=%1 -IF NOT DEFINED mpsreleasename GOTO :error - -REM -REM The make file is designed to construct the target files under -REM a w3i3mv subdirectory of the current directory. We remove this -REM if it already exists, so that the target is guaranteed to be clean. -REM - -IF EXIST w3i3mv\NUL RMDIR /Q/S w3i3mv - -REM Make four varieties of target file. If there are build errors, -REM abort as soon as possible. Any non zero return code from nmake -REM indicates a problem. -REM See http://msdn.microsoft.com/en-us/library/afyyse50(v=VS.71).aspx - -ECHO * Building four varieties into the w3i3mv subdirectory... - -NMAKE /F w3i3mv.nmk VARIETY=we mps.lib mpsplan.lib mpsplcb.lib mpsdy.dll -IF %ERRORLEVEL% GTR 0 GOTO :build_error -NMAKE /F w3i3mv.nmk VARIETY=hi mps.lib mpsplan.lib mpsplcb.lib mpsdy.dll -IF %ERRORLEVEL% GTR 0 GOTO :build_error -NMAKE /F w3i3mv.nmk VARIETY=di mps.lib mpsplan.lib mpsplcb.lib mpsdy.dll -IF %ERRORLEVEL% GTR 0 GOTO :build_error -NMAKE /F w3i3mv.nmk VARIETY=ci mps.lib mpsplan.lib mpsplcb.lib mpsdy.dll -IF %ERRORLEVEL% GTR 0 GOTO :build_error - -REM Now purge and construct the kit release subdirectory. - -ECHO Populating the %mpsreleasename% subdirectory... - -IF EXIST %mpsreleasename%\NUL RMDIR /Q/S %mpsreleasename% -MKDIR %mpsreleasename%\include - -COPY mps.h %mpsreleasename%\include -COPY mpsavm.h %mpsreleasename%\include -COPY mpsacl.h %mpsreleasename%\include -COPY mpscamc.h %mpsreleasename%\include -COPY mpscams.h %mpsreleasename%\include -COPY mpscawl.h %mpsreleasename%\include -COPY mpsclo.h %mpsreleasename%\include -COPY mpscmv.h %mpsreleasename%\include -COPY mpscmvff.h %mpsreleasename%\include -COPY mpscsnc.h %mpsreleasename%\include -COPY mpsio.h %mpsreleasename%\include -COPY mpslib.h %mpsreleasename%\include -COPY mpslibcb.h %mpsreleasename%\include -COPY mpstd.h %mpsreleasename%\include -COPY mpsw3.h %mpsreleasename%\include -COPY mpswin.h %mpsreleasename%\include - -MKDIR %mpsreleasename%\lib -COPY w3gen.def %mpsreleasename%\lib\mps-fns.def - -MKDIR %mpsreleasename%\lib\W3I3MV - -MKDIR %mpsreleasename%\lib\W3I3MV\we -ECHO we-%mpsreleasename% > %mpsreleasename%\lib\W3I3MV\we\we-%mpsreleasename%.txt -COPY w3i3mv\we\mps.lib %mpsreleasename%\lib\W3I3MV\we -COPY w3i3mv\we\mpsplan.lib %mpsreleasename%\lib\W3I3MV\we -COPY w3i3mv\we\mpsplcb.lib %mpsreleasename%\lib\W3I3MV\we -COPY w3i3mv\we\mpsdy.dll %mpsreleasename%\lib\W3I3MV\we -COPY w3i3mv\we\mpsdy.lib %mpsreleasename%\lib\W3I3MV\we - -MKDIR %mpsreleasename%\lib\W3I3MV\hi -ECHO hi-%mpsreleasename% > %mpsreleasename%\lib\W3I3MV\hi\hi-%mpsreleasename%.txt -COPY w3i3mv\hi\mps.lib %mpsreleasename%\lib\W3I3MV\hi -COPY w3i3mv\hi\mpsplan.lib %mpsreleasename%\lib\W3I3MV\hi -COPY w3i3mv\hi\mpsplcb.lib %mpsreleasename%\lib\W3I3MV\hi -COPY w3i3mv\hi\mpsdy.dll %mpsreleasename%\lib\W3I3MV\hi -COPY w3i3mv\hi\mpsdy.lib %mpsreleasename%\lib\W3I3MV\hi - -MKDIR %mpsreleasename%\lib\W3I3MV\di -ECHO di-%mpsreleasename% > %mpsreleasename%\lib\W3I3MV\di\di-%mpsreleasename%.txt -COPY w3i3mv\di\mps.lib %mpsreleasename%\lib\W3I3MV\di -COPY w3i3mv\di\mpsplan.lib %mpsreleasename%\lib\W3I3MV\di -COPY w3i3mv\di\mpsplcb.lib %mpsreleasename%\lib\W3I3MV\di -COPY w3i3mv\di\mpsdy.dll %mpsreleasename%\lib\W3I3MV\di -COPY w3i3mv\di\mpsdy.lib %mpsreleasename%\lib\W3I3MV\di - -MKDIR %mpsreleasename%\lib\W3I3MV\ci -ECHO ci-%mpsreleasename% > %mpsreleasename%\lib\W3I3MV\ci\ci-%mpsreleasename%.txt -COPY w3i3mv\ci\mps.lib %mpsreleasename%\lib\W3I3MV\ci -COPY w3i3mv\ci\mpsplan.lib %mpsreleasename%\lib\W3I3MV\ci -COPY w3i3mv\ci\mpsplcb.lib %mpsreleasename%\lib\W3I3MV\ci -COPY w3i3mv\ci\mpsdy.dll %mpsreleasename%\lib\W3I3MV\ci -COPY w3i3mv\ci\mpsdy.lib %mpsreleasename%\lib\W3I3MV\ci - -MKDIR %mpsreleasename%\src -COPY mpsliban.c %mpsreleasename%\src -COPY mpsioan.c %mpsreleasename%\src - -ECHO * NT build complete -GOTO :end - -:ERROR -ECHO * Error: You must provide a release name as the first parameter. -GOTO :end - -:BUILD_ERROR -ECHO * An error occurred during the build process. -GOTO :end - - -:END -ENDLOCAL diff --git a/mps/code/osxc.h b/mps/code/osxc.h deleted file mode 100644 index 14ae6ae98a2..00000000000 --- a/mps/code/osxc.h +++ /dev/null @@ -1,59 +0,0 @@ -/* osxc.h: MacOS X (Carbon-compatible) system header hacks - * - * $Id$ - * Copyright (c) 2005 Ravenbrook Limited. See end of file for license. - * - * .purpose: This header fixes bugs in the system headers. - */ - - -#ifndef osxc_h -#define osxc_h - - -/* There's nothing to fix. */ - - -#endif /* osxc_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2005 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/pool.c b/mps/code/pool.c deleted file mode 100644 index a88cf48e97c..00000000000 --- a/mps/code/pool.c +++ /dev/null @@ -1,662 +0,0 @@ -/* pool.c: POOL IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2001 Global Graphics Software. - * - * DESIGN - * - * .design: See and . - * - * PURPOSE - * - * .purpose: This is the implementation of the generic pool interface. - * There are three sorts of functions provided: - * .purpose.support: Support functions for manipulating and accessing - * Pool and PoolClass objects (create, destroy, check, various - * accessors, and other miscellaneous functions). - * .purpose.dispatch: Dispatch functions that implement the generic - * function dispatch mechanism for Pool Classes (PoolAlloc, PoolFix, - * etc.). - * .purpose.core: A selection of default, trivial, or useful methods - * that Pool Classes can use as the implementations for some of their - * methods (such as PoolTrivWhiten, PoolNoFix, etc.). - * - * SOURCES - * - * .source: See .design also. PoolStruct and PoolClassStruct, the - * central types for this module, are defined in , the - * corresponding abstract types in . Declarations and - * prototypes are in . Several functions have macro versions - * defined in . - */ - -#include "mpm.h" - -SRCID(pool, "$Id$"); - - -/* PoolClassCheck -- check a pool class */ - -Bool PoolClassCheck(PoolClass class) -{ - CHECKL(ProtocolClassCheck(&class->protocol)); - CHECKL(class->name != NULL); /* Should be <=6 char C identifier */ - CHECKL(class->size >= sizeof(PoolStruct)); - /* Offset of generic Pool within class-specific instance cannot be */ - /* greater than the size of the class-specific portion of the instance */ - CHECKL(class->offset <= (size_t)(class->size - sizeof(PoolStruct))); - CHECKL(AttrCheck(class->attr)); - CHECKL(FUNCHECK(class->init)); - CHECKL(FUNCHECK(class->finish)); - CHECKL(FUNCHECK(class->alloc)); - CHECKL(FUNCHECK(class->free)); - CHECKL(FUNCHECK(class->bufferFill)); - CHECKL(FUNCHECK(class->bufferEmpty)); - CHECKL(FUNCHECK(class->access)); - CHECKL(FUNCHECK(class->whiten)); - CHECKL(FUNCHECK(class->grey)); - CHECKL(FUNCHECK(class->blacken)); - CHECKL(FUNCHECK(class->scan)); - CHECKL(FUNCHECK(class->fix)); - CHECKL(FUNCHECK(class->fixEmergency)); - CHECKL(FUNCHECK(class->reclaim)); - CHECKL(FUNCHECK(class->traceEnd)); - CHECKL(FUNCHECK(class->rampBegin)); - CHECKL(FUNCHECK(class->rampEnd)); - CHECKL(FUNCHECK(class->framePush)); - CHECKL(FUNCHECK(class->framePop)); - CHECKL(FUNCHECK(class->framePopPending)); - CHECKL(FUNCHECK(class->walk)); - CHECKL(FUNCHECK(class->freewalk)); - CHECKL(FUNCHECK(class->bufferClass)); - CHECKL(FUNCHECK(class->describe)); - CHECKL(FUNCHECK(class->debugMixin)); - CHECKS(PoolClass, class); - return TRUE; -} - - -/* PoolCheck -- check the generic part of a pool */ - -Bool PoolCheck(Pool pool) -{ - /* Checks ordered as per struct decl in */ - CHECKS(Pool, pool); - /* Break modularity for checking efficiency */ - CHECKL(pool->serial < ArenaGlobals(pool->arena)->poolSerial); - CHECKD(PoolClass, pool->class); - CHECKU(Arena, pool->arena); - CHECKL(RingCheck(&pool->arenaRing)); - CHECKL(RingCheck(&pool->bufferRing)); - /* Cannot check pool->bufferSerial */ - CHECKL(RingCheck(&pool->segRing)); - CHECKL(AlignCheck(pool->alignment)); - /* normally pool->format iff pool->class->attr&AttrFMT, but not */ - /* during pool initialization */ - if (pool->format != NULL) { - CHECKL((pool->class->attr & AttrFMT) != 0); - } - CHECKL(pool->fillMutatorSize >= 0.0); - CHECKL(pool->emptyMutatorSize >= 0.0); - CHECKL(pool->fillInternalSize >= 0.0); - CHECKL(pool->emptyInternalSize >= 0.0); - return TRUE; -} - - -/* PoolInit, PoolInitV -- initialize a pool - * - * Initialize the generic fields of the pool and calls class-specific - * init. See . */ - -Res PoolInit(Pool pool, Arena arena, PoolClass class, ...) -{ - Res res; - va_list args; - va_start(args, class); - res = PoolInitV(pool, arena, class, args); - va_end(args); - return res; -} - -Res PoolInitV(Pool pool, Arena arena, PoolClass class, va_list args) -{ - Res res; - Word classId; - Globals globals; - - AVER(pool != NULL); - AVERT(Arena, arena); - AVERT(PoolClass, class); - globals = ArenaGlobals(arena); - - pool->class = class; - /* label the pool class with its name */ - if (!class->labelled) { - /* We could still get multiple labelling if multiple instances of */ - /* the pool class get created simultaneously, but it's not worth */ - /* putting another lock in the code. */ - class->labelled = TRUE; - classId = EventInternString(class->name); - /* @@@@ this breaks */ - EventLabelAddr((Addr)class, classId); - } - - pool->arena = arena; - RingInit(&pool->arenaRing); - RingInit(&pool->bufferRing); - RingInit(&pool->segRing); - pool->bufferSerial = (Serial)0; - pool->alignment = MPS_PF_ALIGN; - pool->format = NULL; - pool->fix = class->fix; - pool->fillMutatorSize = 0.0; - pool->emptyMutatorSize = 0.0; - pool->fillInternalSize = 0.0; - pool->emptyInternalSize = 0.0; - - /* Initialise signature last; see */ - pool->sig = PoolSig; - pool->serial = globals->poolSerial; - ++(globals->poolSerial); - - AVERT(Pool, pool); - - /* Do class-specific initialization. */ - res = (*class->init)(pool, args); - if (res != ResOK) - goto failInit; - - /* Add initialized pool to list of pools in arena. */ - RingAppend(&globals->poolRing, &pool->arenaRing); - - return ResOK; - -failInit: - pool->sig = SigInvalid; /* Leave arena->poolSerial incremented */ - RingFinish(&pool->segRing); - RingFinish(&pool->bufferRing); - RingFinish(&pool->arenaRing); - return res; -} - - -/* PoolCreate, PoolCreateV: Allocate and initialise pool */ - -Res PoolCreate(Pool *poolReturn, Arena arena, - PoolClass class, ...) -{ - Res res; - va_list args; - va_start(args, class); - res = PoolCreateV(poolReturn, arena, class, args); - va_end(args); - return res; -} - -Res PoolCreateV(Pool *poolReturn, Arena arena, - PoolClass class, va_list args) -{ - Res res; - Pool pool; - void *base; - - AVER(poolReturn != NULL); - AVERT(Arena, arena); - AVERT(PoolClass, class); - - /* .space.alloc: Allocate the pool instance structure with the size */ - /* requested in the pool class. See .space.free */ - res = ControlAlloc(&base, arena, class->size, - /* withReservoirPermit */ FALSE); - if (res != ResOK) - goto failControlAlloc; - - /* base is the address of the class-specific pool structure. */ - /* We calculate the address of the generic pool structure within the */ - /* instance by using the offset information from the class. */ - pool = (Pool)PointerAdd(base, class->offset); - - /* Initialize the pool. */ - res = PoolInitV(pool, arena, class, args); - if (res != ResOK) - goto failPoolInit; - - *poolReturn = pool; - return ResOK; - -failPoolInit: - ControlFree(arena, base, class->size); -failControlAlloc: - return res; -} - - -/* PoolFinish -- Finish pool including class-specific and generic fields. */ - -void PoolFinish(Pool pool) -{ - AVERT(Pool, pool); - - /* Do any class-specific finishing. */ - (*pool->class->finish)(pool); - - /* Detach the pool from the arena, and unsig it. */ - RingRemove(&pool->arenaRing); - pool->sig = SigInvalid; - - RingFinish(&pool->segRing); - RingFinish(&pool->bufferRing); - RingFinish(&pool->arenaRing); - - EVENT1(PoolFinish, pool); -} - - -/* PoolDestroy -- Finish and free pool. */ - -void PoolDestroy(Pool pool) -{ - PoolClass class; - Arena arena; - Addr base; - - AVERT(Pool, pool); - - class = pool->class; /* } In case PoolFinish changes these */ - arena = pool->arena; /* } */ - - /* Finish the pool instance structure. */ - PoolFinish(pool); - - /* .space.free: Free the pool instance structure. See .space.alloc */ - base = AddrSub((Addr)pool, (Size)(class->offset)); - ControlFree(arena, base, (Size)(class->size)); -} - - -/* PoolDefaultBufferClass -- return the buffer class used by the pool */ - -BufferClass PoolDefaultBufferClass(Pool pool) -{ - AVERT(Pool, pool); - return (*pool->class->bufferClass)(); -} - - -/* PoolAlloc -- allocate a block of memory from a pool */ - -Res PoolAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit) -{ - Res res; - - AVER(pReturn != NULL); - AVERT(Pool, pool); - AVER((pool->class->attr & AttrALLOC) != 0); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - - res = (*pool->class->alloc)(pReturn, pool, size, withReservoirPermit); - if (res != ResOK) - return res; - /* Make sure that the allocated address was in the pool's memory. */ - /* .hasaddr.critical: The PoolHasAddr check is expensive, and in */ - /* allocation-bound programs this is on the critical path. */ - AVER_CRITICAL(PoolHasAddr(pool, *pReturn)); - /* All allocations should be aligned to the pool's alignment */ - AVER_CRITICAL(AddrIsAligned(*pReturn, pool->alignment)); - - /* All PoolAllocs should advance the allocation clock, so we count */ - /* it all in the fillMutatorSize field. */ - pool->fillMutatorSize += size; - ArenaGlobals(PoolArena(pool))->fillMutatorSize += size; - - EVENT3(PoolAlloc, pool, *pReturn, size); - - return ResOK; -} - - -/* PoolFree -- deallocate a block of memory allocated from the pool */ - -void PoolFree(Pool pool, Addr old, Size size) -{ - AVERT(Pool, pool); - AVER((pool->class->attr & AttrFREE) != 0); - AVER(old != NULL); - /* The pool methods should check that old is in pool. */ - AVER(size > 0); - (*pool->class->free)(pool, old, size); - - EVENT3(PoolFree, pool, old, size); -} - - -Res PoolAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context) -{ - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(SegBase(seg) <= addr); - AVER(addr < SegLimit(seg)); - /* Can't check mode as there is no check method */ - /* Can't check MutatorFaultContext as there is no check method */ - - return (*pool->class->access)(pool, seg, addr, mode, context); -} - - -/* PoolWhiten, PoolGrey, PoolBlacken -- change color of a segment in the pool */ - -Res PoolWhiten(Pool pool, Trace trace, Seg seg) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - AVER(PoolArena(pool) == trace->arena); - AVER(SegPool(seg) == pool); - return (*pool->class->whiten)(pool, trace, seg); -} - -void PoolGrey(Pool pool, Trace trace, Seg seg) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - AVER(pool->arena == trace->arena); - AVER(SegPool(seg) == pool); - (*pool->class->grey)(pool, trace, seg); -} - -void PoolBlacken(Pool pool, TraceSet traceSet, Seg seg) -{ - AVERT(Pool, pool); - AVERT(TraceSet, traceSet); - AVERT(Seg, seg); - AVER(SegPool(seg) == pool); - (*pool->class->blacken)(pool, traceSet, seg); -} - - -/* PoolScan -- scan a segment in the pool */ - -Res PoolScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) -{ - AVER(totalReturn != NULL); - AVERT(ScanState, ss); - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(ss->arena == pool->arena); - - /* The segment must belong to the pool. */ - AVER(pool == SegPool(seg)); - - /* We check that either ss->rank is in the segment's - * ranks, or that ss->rank is exact. The check is more complicated if - * we actually have multiple ranks in a seg. - * See */ - AVER(ss->rank == RankEXACT || RankSetIsMember(SegRankSet(seg), ss->rank)); - - /* Should only scan segments which contain grey objects. */ - AVER(TraceSetInter(SegGrey(seg), ss->traces) != TraceSetEMPTY); - - return (*pool->class->scan)(totalReturn, ss, pool, seg); -} - - -/* PoolFix* -- fix a reference to an object in this pool - * - * See for macro version; see . - */ - -Res (PoolFix)(Pool pool, ScanState ss, Seg seg, Addr *refIO) -{ - AVERT(Pool, pool); - AVERT(ScanState, ss); - AVERT(Seg, seg); - AVER(pool == SegPool(seg)); - AVER(refIO != NULL); - - /* Should only be fixing references to white segments. */ - AVER(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY); - - return PoolFix(pool, ss, seg, refIO); -} - -Res PoolFixEmergency(Pool pool, ScanState ss, Seg seg, Addr *refIO) -{ - Res res; - - AVERT(Pool, pool); - AVERT(ScanState, ss); - AVERT(Seg, seg); - AVER(pool == SegPool(seg)); - AVER(refIO != NULL); - - /* Should only be fixing references to white segments. */ - AVER(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY); - - res = (pool->class->fixEmergency)(pool, ss, seg, refIO); - AVER(res == ResOK); - return res; -} - - -/* PoolReclaim -- reclaim a segment in the pool */ - -void PoolReclaim(Pool pool, Trace trace, Seg seg) -{ - AVERT_CRITICAL(Pool, pool); - AVERT_CRITICAL(Trace, trace); - AVERT_CRITICAL(Seg, seg); - AVER_CRITICAL(pool->arena == trace->arena); - AVER_CRITICAL(SegPool(seg) == pool); - - /* There shouldn't be any grey things left for this trace. */ - AVER_CRITICAL(!TraceSetIsMember(SegGrey(seg), trace)); - /* Should only be reclaiming segments which are still white. */ - AVER_CRITICAL(TraceSetIsMember(SegWhite(seg), trace)); - - (*pool->class->reclaim)(pool, trace, seg); -} - - -/* PoolTraceEnd -- do end-of-trace work - * - * This method is for a pool class to do final end-of-trace work, - * after all reclaiming is complete. For example, emitting - * diagnostics about what happened during the trace. - */ - -void PoolTraceEnd(Pool pool, Trace trace) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVER(pool->arena == trace->arena); - - (*pool->class->traceEnd)(pool, trace); -} - - -/* PoolWalk -- walk objects in this segment */ - -void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, - void *p, size_t s) -{ - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(FUNCHECK(f)); - /* p and s are arbitrary values, hence can't be checked. */ - - (*pool->class->walk)(pool, seg, f, p, s); -} - - -/* PoolFreeWalk -- walk free blocks in this pool - * - * PoolFreeWalk is not required to find all free blocks. - */ - -void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p) -{ - AVERT(Pool, pool); - AVER(FUNCHECK(f)); - /* p is arbitrary, hence can't be checked. */ - - (*pool->class->freewalk)(pool, f, p); -} - - -/* PoolDescribe -- describe a pool */ - -Res PoolDescribe(Pool pool, mps_lib_FILE *stream) -{ - Res res; - Ring node, nextNode; - - if (!TESTT(Pool, pool)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, - "Pool $P ($U) {\n", (WriteFP)pool, (WriteFU)pool->serial, - " class $P (\"$S\")\n", - (WriteFP)pool->class, pool->class->name, - " arena $P ($U)\n", - (WriteFP)pool->arena, (WriteFU)pool->arena->serial, - " alignment $W\n", (WriteFW)pool->alignment, - NULL); - if (res != ResOK) return res; - if (NULL != pool->format) { - res = FormatDescribe(pool->format, stream); - if (res != ResOK) return res; - } - res = WriteF(stream, - " fillMutatorSize $UKb\n", - (WriteFU)(pool->fillMutatorSize / 1024), - " emptyMutatorSize $UKb\n", - (WriteFU)(pool->emptyMutatorSize / 1024), - " fillInternalSize $UKb\n", - (WriteFU)(pool->fillInternalSize / 1024), - " emptyInternalSize $UKb\n", - (WriteFU)(pool->emptyInternalSize / 1024), - NULL); - if (res != ResOK) return res; - - res = (*pool->class->describe)(pool, stream); - if (res != ResOK) return res; - - RING_FOR(node, &pool->bufferRing, nextNode) { - Buffer buffer = RING_ELT(Buffer, poolRing, node); - res = BufferDescribe(buffer, stream); - if (res != ResOK) return res; - } - - res = WriteF(stream, - "} Pool $P ($U)\n", (WriteFP)pool, (WriteFU)pool->serial, - NULL); - if (res != ResOK) return res; - - return ResOK; -} - - -/* PoolFormat - * - * Returns the format of the pool (the format of objects in the pool). - * If the pool is unformatted or doesn't declare a format then this - * function returns FALSE and does not update *formatReturn. Otherwise - * this function returns TRUE and *formatReturn is updated to be the - * pool's format. */ - -Bool PoolFormat(Format *formatReturn, Pool pool) -{ - AVER(formatReturn != NULL); - AVERT(Pool, pool); - - if (pool->format) { - *formatReturn = pool->format; - return TRUE; - } - return FALSE; -} - - -/* PoolOfAddr -- return the pool containing the given address - * - * If the address points to a page assigned to a pool, this returns TRUE - * and sets *poolReturn to that pool. Otherwise, it returns FALSE, and - * *poolReturn is unchanged. - */ - -Bool PoolOfAddr(Pool *poolReturn, Arena arena, Addr addr) -{ - Tract tract; - - AVER(poolReturn != NULL); - AVERT(Arena, arena); - - if (TractOfAddr(&tract, arena, addr)) { - *poolReturn = TractPool(tract); - return TRUE; - } - - return FALSE; -} - - -Bool PoolHasAddr(Pool pool, Addr addr) -{ - Pool addrPool; - Arena arena; - Bool managed; - - AVERT(Pool, pool); - - arena = PoolArena(pool); - managed = PoolOfAddr(&addrPool, arena, addr); - return (managed && addrPool == pool); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolabs.c b/mps/code/poolabs.c deleted file mode 100644 index e3e45b7480c..00000000000 --- a/mps/code/poolabs.c +++ /dev/null @@ -1,704 +0,0 @@ -/* poolabs.c: ABSTRACT POOL CLASSES - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * PURPOSE - * - * .purpose: This defines the abstract pool classes, giving - * a single-inheritance framework which concrete classes - * may utilize. The purpose is to reduce the fragility of class - * definitions for pool implementations when small changes are - * made to the pool protocol. For now, the class hierarchy for - * the abstract classes is intended to be useful, but not to - * represent any particular design for pool inheritance. - * - * HIERARCHY - * - * .hierarchy: define the following hierarchy of abstract pool classes: - * AbstractPoolClass - implements init, finish, describe - * AbstractAllocFreePoolClass - implements alloc & free - * AbstractBufferPoolClass - implements the buffer protocol - * AbstractSegBufPoolClass - uses SegBuf buffer class - * AbstractScanPoolClass - implements basic scanning - * AbstractCollectPoolClass - implements basic GC - */ - -#include "mpm.h" - -SRCID(poolabs, "$Id$"); - - -typedef PoolClassStruct AbstractPoolClassStruct; -typedef PoolClassStruct AbstractAllocFreePoolClassStruct; -typedef PoolClassStruct AbstractBufferPoolClassStruct; -typedef PoolClassStruct AbstractSegBufPoolClassStruct; -typedef PoolClassStruct AbstractScanPoolClassStruct; -typedef PoolClassStruct AbstractCollectPoolClassStruct; - - -/* Mixins: - * - * For now (at least) we're avoiding multiple inheritance. - * However, there is a significant use of multiple inheritance - * in practice amongst the pool classes, as there are several - * orthogonal sub-protocols included in the pool protocol. - * The following mixin functions help to provide the inheritance - * via a simpler means than real multiple inheritance. - */ - - -/* PoolClassMixInAllocFree -- mix in the protocol for Alloc / Free */ - -void PoolClassMixInAllocFree(PoolClass class) -{ - /* Can't check class because it's not initialized yet */ - class->attr |= (AttrALLOC | AttrFREE); - class->alloc = PoolTrivAlloc; - class->free = PoolTrivFree; -} - - -/* PoolClassMixInBuffer -- mix in the protocol for buffer reserve / commit */ - -void PoolClassMixInBuffer(PoolClass class) -{ - /* Can't check class because it's not initialized yet */ - class->attr |= (AttrBUF | AttrBUF_RESERVE); - class->bufferFill = PoolTrivBufferFill; - class->bufferEmpty = PoolTrivBufferEmpty; - /* By default, buffered pools treat frame operations as NOOPs */ - class->framePush = PoolTrivFramePush; - class->framePop = PoolTrivFramePop; - class->bufferClass = BufferClassGet; -} - - -/* PoolClassMixInScan -- mix in the protocol for scanning */ - -void PoolClassMixInScan(PoolClass class) -{ - /* Can't check class because it's not initialized yet */ - class->attr |= AttrSCAN; - class->access = PoolSegAccess; - class->blacken = PoolTrivBlacken; - class->grey = PoolTrivGrey; - /* Scan is part of the scanning protocol - but there is */ - /* no useful default method */ -} - - -/* PoolClassMixInFormat -- mix in the protocol for formatted pools */ - -void PoolClassMixInFormat(PoolClass class) -{ - /* Can't check class because it's not initialized yet */ - class->attr |= AttrFMT; -} - - -/* PoolClassMixInCollect -- mix in the protocol for GC */ - -void PoolClassMixInCollect(PoolClass class) -{ - /* Can't check class because it's not initialized yet */ - class->attr |= (AttrGC | AttrINCR_RB); - class->whiten = PoolTrivWhiten; - /* Fix & reclaim are part of the collection protocol - but there */ - /* are no useful default methods for them. */ - class->rampBegin = PoolTrivRampBegin; - class->rampEnd = PoolTrivRampEnd; -} - - -/* Classes */ - - -DEFINE_CLASS(AbstractPoolClass, class) -{ - INHERIT_CLASS(&class->protocol, ProtocolClass); - class->name = "ABSTRACT"; - class->size = 0; - class->offset = 0; - class->attr = 0; - class->init = PoolTrivInit; - class->finish = PoolTrivFinish; - class->alloc = PoolNoAlloc; - class->free = PoolNoFree; - class->bufferFill = PoolNoBufferFill; - class->bufferEmpty = PoolNoBufferEmpty; - class->access = PoolNoAccess; - class->whiten = PoolNoWhiten; - class->grey = PoolNoGrey; - class->blacken = PoolNoBlacken; - class->scan = PoolNoScan; - class->fix = PoolNoFix; - class->fixEmergency = PoolNoFix; - class->reclaim = PoolNoReclaim; - class->traceEnd = PoolTrivTraceEnd; - class->rampBegin = PoolNoRampBegin; - class->rampEnd = PoolNoRampEnd; - class->framePush = PoolNoFramePush; - class->framePop = PoolNoFramePop; - class->framePopPending = PoolNoFramePopPending; - class->walk = PoolNoWalk; - class->freewalk = PoolNoFreeWalk; - class->bufferClass = PoolNoBufferClass; - class->describe = PoolTrivDescribe; - class->debugMixin = PoolNoDebugMixin; - class->labelled = FALSE; - class->sig = PoolClassSig; -} - -DEFINE_CLASS(AbstractAllocFreePoolClass, class) -{ - INHERIT_CLASS(class, AbstractPoolClass); - PoolClassMixInAllocFree(class); -} - -DEFINE_CLASS(AbstractBufferPoolClass, class) -{ - INHERIT_CLASS(class, AbstractPoolClass); - PoolClassMixInBuffer(class); -} - -DEFINE_CLASS(AbstractSegBufPoolClass, class) -{ - INHERIT_CLASS(class, AbstractBufferPoolClass); - class->bufferClass = SegBufClassGet; -} - -DEFINE_CLASS(AbstractScanPoolClass, class) -{ - INHERIT_CLASS(class, AbstractSegBufPoolClass); - PoolClassMixInScan(class); -} - -DEFINE_CLASS(AbstractCollectPoolClass, class) -{ - INHERIT_CLASS(class, AbstractScanPoolClass); - PoolClassMixInCollect(class); -} - - -/* PoolNo*, PoolTriv* -- Trivial and non-methods for Pool Classes - * - * See and - */ - - -void PoolTrivFinish(Pool pool) -{ - AVERT(Pool, pool); - NOOP; -} - -Res PoolTrivInit(Pool pool, va_list args) -{ - AVERT(Pool, pool); - UNUSED(args); - return ResOK; -} - -Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit) -{ - AVER(pReturn != NULL); - AVERT(Pool, pool); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - NOTREACHED; - return ResUNIMPL; -} - -Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit) -{ - AVER(pReturn != NULL); - AVERT(Pool, pool); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - return ResLIMIT; -} - -void PoolNoFree(Pool pool, Addr old, Size size) -{ - AVERT(Pool, pool); - AVER(old != NULL); - AVER(size > 0); - NOTREACHED; -} - -void PoolTrivFree(Pool pool, Addr old, Size size) -{ - AVERT(Pool, pool); - AVER(old != NULL); - AVER(size > 0); - NOOP; /* trivial free has no effect */ -} - - -Res PoolNoBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Pool, pool); - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - NOTREACHED; - return ResUNIMPL; -} - -Res PoolTrivBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - Res res; - Addr p; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Pool, pool); - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - - res = PoolAlloc(&p, pool, size, withReservoirPermit); - if(res != ResOK) return res; - - *baseReturn = p; - *limitReturn = AddrAdd(p, size); - return ResOK; -} - - -void PoolNoBufferEmpty(Pool pool, Buffer buffer, - Addr init, Addr limit) -{ - AVERT(Pool, pool); - AVERT(Buffer, buffer); - AVER(BufferIsReady(buffer)); - AVER(init <= limit); - NOTREACHED; -} - -void PoolTrivBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) -{ - AVERT(Pool, pool); - AVERT(Buffer, buffer); - AVER(BufferIsReady(buffer)); - AVER(init <= limit); - if (limit > init) - PoolFree(pool, init, AddrOffset(init, limit)); -} - - -Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream) -{ - AVERT(Pool, pool); - AVER(stream != NULL); - return WriteF(stream, " No class-specific description available.\n", NULL); -} - - -Res PoolNoTraceBegin(Pool pool, Trace trace) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVER(PoolArena(pool) == trace->arena); - NOTREACHED; - return ResUNIMPL; -} - -Res PoolTrivTraceBegin(Pool pool, Trace trace) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVER(PoolArena(pool) == trace->arena); - return ResOK; -} - -/* NoAccess - * - * Should be used (for the access method) by Pool Classes which do - * not expect to ever have pages which the mutator will fault on. - * That is, no protected pages, or only pages which are inaccessible - * by the mutator are protected. - */ -Res PoolNoAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context) -{ - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(SegBase(seg) <= addr); - AVER(addr < SegLimit(seg)); - /* can't check AccessSet as there is no Check method */ - /* can't check context as there is no Check method */ - UNUSED(mode); - UNUSED(context); - - NOTREACHED; - return ResUNIMPL; -} - - -/* SegAccess - * - * See also PoolSingleAccess - * - * Should be used (for the access method) by Pool Classes which intend - * to handle page faults by scanning the entire segment and lowering - * the barrier. - */ -Res PoolSegAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context) -{ - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(SegBase(seg) <= addr); - AVER(addr < SegLimit(seg)); - AVER(SegPool(seg) == pool); - /* can't check AccessSet as there is no Check method */ - /* can't check context as there is no Check method */ - - UNUSED(addr); - UNUSED(context); - TraceSegAccess(PoolArena(pool), seg, mode); - return ResOK; -} - - -/* SingleAccess - * - * See also ArenaRead, and PoolSegAccess. - * - * Handles page faults by attempting emulation. If the faulting - * instruction cannot be emulated then this function returns ResFAIL. - * - * Due to the assumptions made below, pool classes should only use - * this function if all words in an object are tagged or traceable. - * - * .single-access.assume.ref: It currently assumes that the address - * being faulted on contains a plain reference or a tagged non-reference. - * .single-access.improve.format: Later this will be abstracted - * through the cleint object format interface, so that - * no such assumption is necessary. - */ -Res PoolSingleAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context) -{ - Arena arena; - - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(SegBase(seg) <= addr); - AVER(addr < SegLimit(seg)); - AVER(SegPool(seg) == pool); - /* can't check AccessSet as there is no Check method */ - /* can't check context as there is no Check method */ - - arena = PoolArena(pool); - - if(ProtCanStepInstruction(context)) { - Ref ref; - Res res; - - ShieldExpose(arena, seg); - - if(mode & SegSM(seg) & AccessREAD) { - /* Read access. */ - /* .single-access.assume.ref */ - /* .single-access.improve.format */ - ref = *(Ref *)addr; - /* .tagging: Check that the reference is aligned to a word boundary */ - /* (we assume it is not a reference otherwise). */ - if(WordIsAligned((Word)ref, sizeof(Word))) { - Rank rank; - /* See the note in TraceRankForAccess */ - /* (). */ - - rank = TraceRankForAccess(arena, seg); - TraceScanSingleRef(arena->flippedTraces, rank, arena, - seg, (Ref *)addr); - } - } - res = ProtStepInstruction(context); - AVER(res == ResOK); - - /* Update SegSummary according to the possibly changed reference. */ - ref = *(Ref *)addr; - /* .tagging: ought to check the reference for a tag. But - * this is conservative. */ - SegSetSummary(seg, RefSetAdd(arena, SegSummary(seg), ref)); - - ShieldCover(arena, seg); - - return ResOK; - } else { - /* couldn't single-step instruction */ - return ResFAIL; - } -} - - -Res PoolTrivWhiten(Pool pool, Trace trace, Seg seg) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - - SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace)); - - return ResOK; -} - -Res PoolNoWhiten(Pool pool, Trace trace, Seg seg) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - NOTREACHED; - return ResUNIMPL; -} - - -void PoolNoGrey(Pool pool, Trace trace, Seg seg) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - NOTREACHED; -} - -void PoolTrivGrey(Pool pool, Trace trace, Seg seg) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - - /* If we had a (partially) white seg, then other parts of the */ - /* same seg might need to get greyed. In fact, all current pools */ - /* only ever Whiten a whole seg, so we never need to Greyen any */ - /* part of an already Whitened seg. So we hereby exclude white */ - /* segs. */ - /* @@@@ This should not really be called 'trivial'! */ - if(!TraceSetIsMember(SegWhite(seg), trace)) - SegSetGrey(seg, TraceSetSingle(trace)); -} - - -void PoolNoBlacken(Pool pool, TraceSet traceSet, Seg seg) -{ - AVERT(Pool, pool); - AVERT(TraceSet, traceSet); - AVERT(Seg, seg); - NOTREACHED; -} - -void PoolTrivBlacken(Pool pool, TraceSet traceSet, Seg seg) -{ - AVERT(Pool, pool); - AVERT(TraceSet, traceSet); - AVERT(Seg, seg); - - /* The trivial blacken method does nothing; for pool classes which do */ - /* not keep additional colour information. */ - NOOP; -} - - -Res PoolNoScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) -{ - AVER(totalReturn != NULL); - AVERT(ScanState, ss); - AVERT(Pool, pool); - AVERT(Seg, seg); - NOTREACHED; - return ResUNIMPL; -} - -Res PoolNoFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) -{ - AVERT(Pool, pool); - AVERT(ScanState, ss); - AVERT(Seg, seg); - AVER(refIO != NULL); - NOTREACHED; - return ResUNIMPL; -} - -void PoolNoReclaim(Pool pool, Trace trace, Seg seg) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - NOTREACHED; -} - -void PoolTrivTraceEnd(Pool pool, Trace trace) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - NOOP; -} - - -void PoolNoRampBegin(Pool pool, Buffer buf, Bool collectAll) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - AVERT(Bool, collectAll); - NOTREACHED; -} - - -void PoolNoRampEnd(Pool pool, Buffer buf) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - NOTREACHED; -} - - -void PoolTrivRampBegin(Pool pool, Buffer buf, Bool collectAll) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - AVERT(Bool, collectAll); -} - - -void PoolTrivRampEnd(Pool pool, Buffer buf) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); -} - - -Res PoolNoFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf) -{ - AVER(frameReturn != NULL); - AVERT(Pool, pool); - AVERT(Buffer, buf); - NOTREACHED; - return ResUNIMPL; -} - - -Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - /* frame is of a abstract type & can't be checked */ - UNUSED(frame); - NOTREACHED; - return ResUNIMPL; -} - - -void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - /* frame is of a abstract type & can't be checked */ - UNUSED(frame); - NOTREACHED; -} - - -Res PoolTrivFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf) -{ - AVER(frameReturn != NULL); - AVERT(Pool, pool); - AVERT(Buffer, buf); - return ResOK; -} - - -Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - /* frame is of a abstract type & can't be checked */ - UNUSED(frame); - return ResOK; -} - - -void PoolNoWalk(Pool pool, Seg seg, - FormattedObjectsStepMethod f, void *p, size_t s) -{ - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(FUNCHECK(f)); - /* p and s are arbitrary, hence can't be checked */ - UNUSED(p); - UNUSED(s); - - NOTREACHED; -} - - -void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p) -{ - AVERT(Pool, pool); - AVER(FUNCHECK(f)); - /* p is arbitrary, hence can't be checked */ - UNUSED(p); - - /* FreeWalk doesn't have be perfect, so just pretend you didn't find any. */ - NOOP; -} - - -BufferClass PoolNoBufferClass(void) -{ - NOTREACHED; - return NULL; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c deleted file mode 100644 index 5901c098512..00000000000 --- a/mps/code/poolamc.c +++ /dev/null @@ -1,2539 +0,0 @@ -/* poolamc.c: AUTOMATIC MOSTLY-COPYING MEMORY POOL CLASS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .sources: . - */ - -#include "mpscamc.h" -#include "chain.h" -#include "bt.h" -#include "mpm.h" - -SRCID(poolamc, "$Id$"); - -/* PType enumeration -- distinguishes AMCGen and AMCNailboard */ -enum {AMCPTypeGen = 1, AMCPTypeNailboard}; - -/* AMC typedef */ -typedef struct AMCStruct *AMC; - -/* amcGen typedef */ -typedef struct amcGenStruct *amcGen; - -/* forward declarations */ - -static Bool amcSegHasNailboard(Seg seg); -static Bool AMCCheck(AMC amc); -static Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO); -static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO); -static PoolClass AMCPoolClassGet(void); -static BufferClass amcBufClassGet(void); -static SegClass amcSegClassGet(void); - - -/* amcGenStruct -- pool AMC generation descriptor */ - -#define amcGenSig ((Sig)0x519A3C9E) /* SIGnature AMC GEn */ - -typedef struct amcGenStruct { - PoolGenStruct pgen; - int type; /* AMCPTypeGen for a gen */ - RingStruct amcRing; /* link in list of gens in pool */ - Buffer forward; /* forwarding buffer */ - Count segs; /* number of segs in gen */ - Sig sig; /* */ -} amcGenStruct; - -#define amcGenAMC(amcgen) Pool2AMC((amcgen)->pgen.pool) -#define amcGenPool(amcgen) ((amcgen)->pgen.pool) - -#define amcGenNr(amcgen) ((amcgen)->pgen.nr) - - -#define RAMP_RELATION(X) \ - X(RampOUTSIDE, "outside ramp") \ - X(RampBEGIN, "begin ramp") \ - X(RampRAMPING, "ramping") \ - X(RampFINISH, "finish ramp") \ - X(RampCOLLECTING, "collecting ramp") - -#define RAMP_ENUM(e, s) e, -enum { - RAMP_RELATION(RAMP_ENUM) - RampLIMIT -}; -#undef RAMP_ENUM - - -/* amcNailboard -- the nailboard */ - -typedef struct amcNailboardStruct *amcNailboard; -typedef struct amcNailboardStruct { - Sig sig; - int type; /* AMCPTypeNailboard for a nailboard */ - amcGen gen; /* generation of this segment */ - Count nails; /* no. of ambigFixes, not necessarily distinct */ - Count distinctNails; /* number of distinct ambigFixes */ - Bool newMarks; /* set to TRUE if a new mark bit is added */ - Shift markShift; /* to convert offset into bit index for mark */ - BT mark; /* mark table used to record ambiguous fixes */ -} amcNailboardStruct; - -#define amcNailboardSig ((Sig)0x519A3C4B) /* SIGnature AMC Nailboard */ - - -/* amcSegStruct -- AMC-specific fields appended to GCSegStruct - * - * .segtype: logically, AMC segs should have pointers to: - * - the generation (amcGenStruct); - * - the nailboard (or NULL if not present). - * But in fact (apparently to save space in the amcSegStruct?) these - * pointers are encoded, so as to use only a single-word "segTypeP" - * field in amcSegStruct, as follows: - * The "segTypeP" field is a pointer to (the type field of) either - * a nailboard or a generation. The value stored in the type field - * indicates whether its enclosing struct is a generation or a - * nailboard. The segTypeP field is initialised by passing an - * additional parameter (the address of the segment's generation) to - * SegAlloc. See . - * - * .seg-ramp-new: "new" (if true) means this segment was allocated by - * AMCBufferFill while amc->rampMode == RampRAMPING, and therefore - * (I think) the contribution it *should* make to gen->pgen.newSize - * is being deferred until the ramping is over. "new" is set to FALSE - * in all other (ie. normal) circumstances. (The original comment for - * this struct member was "allocated since last GC"). RHSK 2009-04-15. - */ - -typedef struct amcSegStruct *amcSeg; - -#define amcSegSig ((Sig)0x519A3C59) /* SIGnature AMC SeG */ - -typedef struct amcSegStruct { - GCSegStruct gcSegStruct; /* superclass fields must come first */ - int *segTypeP; /* .segtype */ - Bool new; /* .seg-ramp-new */ - Sig sig; /* */ -} amcSegStruct; - -#define Seg2amcSeg(seg) ((amcSeg)(seg)) -#define amcSeg2Seg(amcseg) ((Seg)(amcseg)) - -#define amcSegTypeP(seg) (Seg2amcSeg(seg)->segTypeP) -#define amcSegSetTypeP(seg, type) (Seg2amcSeg(seg)->segTypeP = (type)) - - -static Bool amcSegCheck(amcSeg amcseg) -{ - CHECKS(amcSeg, amcseg); - CHECKD(GCSeg, &amcseg->gcSegStruct); - CHECKL(*amcseg->segTypeP == AMCPTypeNailboard - || *amcseg->segTypeP == AMCPTypeGen); - if(*amcseg->segTypeP == AMCPTypeNailboard) { - CHECKL(SegNailed(amcSeg2Seg(amcseg)) != TraceSetEMPTY); - } - CHECKL(BoolCheck(amcseg->new)); - return TRUE; -} - - -/* AMCSegInit -- initialise an AMC segment */ - -static Res AMCSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - int *segtype = va_arg(args, int*); /* .segtype */ - SegClass super; - amcSeg amcseg; - Res res; - - AVERT(Seg, seg); - amcseg = Seg2amcSeg(seg); - /* no useful checks for base and size */ - AVERT(Bool, reservoirPermit); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(amcSegClass); - res = super->init(seg, pool, base, size, reservoirPermit, args); - if(res != ResOK) - return res; - - amcseg->segTypeP = segtype; /* .segtype */ - amcseg->new = TRUE; - amcseg->sig = amcSegSig; - AVERT(amcSeg, amcseg); - - return ResOK; -} - - -/* AMCSegSketch -- summarise the segment state for a human reader - * - * Write a short human-readable text representation of the segment - * state into storage indicated by pbSketch+cbSketch. - * - * A typical sketch is "bGW_", meaning the seg has a nailboard, has - * some Grey and some White objects, and has no buffer attached. - */ - -static void AMCSegSketch(Seg seg, char *pbSketch, size_t cbSketch) -{ - amcSeg amcseg; - Buffer buffer; - - AVER(pbSketch); - AVER(cbSketch >= 5); - AVERT(Seg, seg); - amcseg = Seg2amcSeg(seg); - AVERT(amcSeg, amcseg); - - if(SegNailed(seg) == TraceSetEMPTY) { - pbSketch[0] = 'm'; /* mobile */ - } else if (amcSegHasNailboard(seg)) { - pbSketch[0] = 'b'; /* boarded */ - } else { - pbSketch[0] = 's'; /* stuck */ - } - - if(SegGrey(seg) == TraceSetEMPTY) { - pbSketch[1] = '_'; - } else { - pbSketch[1] = 'G'; /* Grey */ - } - - if(SegWhite(seg) == TraceSetEMPTY) { - pbSketch[2] = '_'; - } else { - pbSketch[2] = 'W'; /* White */ - } - - buffer = SegBuffer(seg); - if(buffer == NULL) { - pbSketch[3] = '_'; - } else { - Bool mut = BufferIsMutator(buffer); - Bool flipped = ((buffer->mode & BufferModeFLIPPED) != 0); - Bool trapped = BufferIsTrapped(buffer); - Bool limitzeroed = (buffer->ap_s.limit == 0); - - pbSketch[3] = 'X'; /* I don't know what's going on! */ - - if((flipped == trapped) && (trapped == limitzeroed)) { - if(mut) { - if(flipped) { - pbSketch[3] = 's'; /* stalo */ - } else { - pbSketch[3] = 'n'; /* neo */ - } - } else { - if(!flipped) { - pbSketch[3] = 'f'; /* forwarding */ - } - } - } else { - /* I don't know what's going on! */ - } - } - - pbSketch[4] = '\0'; - AVER(4 < cbSketch); -} - - -/* AMCSegDescribe -- describe the contents of a segment - * - * See . - */ -static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream) -{ - Res res; - Pool pool; - amcSeg amcseg; - SegClass super; - Addr i, p, base, limit, init; - Align step; - Size row; - char abzSketch[5]; - - if(!TESTT(Seg, seg)) - return ResFAIL; - if(stream == NULL) - return ResFAIL; - amcseg = Seg2amcSeg(seg); - if(!TESTT(amcSeg, amcseg)) - return ResFAIL; - - /* Describe the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(amcSegClass); - res = super->describe(seg, stream); - if(res != ResOK) - return res; - - pool = SegPool(seg); - step = PoolAlignment(pool); - row = step * 64; - - base = SegBase(seg); - p = AddrAdd(base, pool->format->headerSize); - limit = SegLimit(seg); - - res = WriteF(stream, - "AMC seg $P [$A,$A){\n", - (WriteFP)seg, (WriteFA)base, (WriteFA)limit, - NULL); - if(res != ResOK) - return res; - - if(amcSegHasNailboard(seg)) { - res = WriteF(stream, " Boarded\n", NULL); - /* @@@@ should have AMCNailboardDescribe() */ - } else { - if(SegNailed(seg) == TraceSetEMPTY) { - res = WriteF(stream, " Mobile\n", NULL); - } else { - res = WriteF(stream, " Stuck\n", NULL); - } - } - if(res != ResOK) - return res; - - res = WriteF(stream, " Map: *===:object bbbb:buffer\n", NULL); - if(res != ResOK) - return res; - - if(SegBuffer(seg) != NULL) - init = BufferGetInit(SegBuffer(seg)); - else - init = limit; - - for(i = base; i < limit; i = AddrAdd(i, row)) { - Addr j; - char c; - - res = WriteF(stream, " $A ", i, NULL); - if(res != ResOK) - return res; - - /* @@@@ This needs to describe nailboards as well */ - /* @@@@ This misses a header-sized pad at the end. */ - for(j = i; j < AddrAdd(i, row); j = AddrAdd(j, step)) { - if(j >= limit) - c = ' '; /* if seg is not a whole number of print rows */ - else if(j >= init) - c = 'b'; - else if(j == p) { - c = '*'; - p = (pool->format->skip)(p); - } else { - c = '='; - } - res = WriteF(stream, "$C", c, NULL); - if(res != ResOK) - return res; - } - - res = WriteF(stream, "\n", NULL); - if(res != ResOK) - return res; - } - - AMCSegSketch(seg, abzSketch, NELEMS(abzSketch)); - res = WriteF(stream, " Sketch: $S\n", (WriteFS)abzSketch, NULL); - if(res != ResOK) - return res; - - res = WriteF(stream, "} AMC Seg $P\n", (WriteFP)seg, NULL); - if(res != ResOK) - return res; - - return ResOK; -} - - -/* amcSegClass -- Class definition for AMC segments */ - -DEFINE_SEG_CLASS(amcSegClass, class) -{ - INHERIT_CLASS(class, GCSegClass); - SegClassMixInNoSplitMerge(class); /* no support for this (yet) */ - class->name = "AMCSEG"; - class->size = sizeof(amcSegStruct); - class->init = AMCSegInit; - class->describe = AMCSegDescribe; -} - - - -/* amcSegHasNailboard -- test whether the segment has a nailboard - * - * See . - */ -static Bool amcSegHasNailboard(Seg seg) -{ - int type; - - type = *amcSegTypeP(seg); - AVER(type == AMCPTypeNailboard || type == AMCPTypeGen); - return type == AMCPTypeNailboard; -} - - -/* amcSegNailboard -- get the nailboard for this segment */ - -static amcNailboard amcSegNailboard(Seg seg) -{ - int *p; - - p = amcSegTypeP(seg); - AVER(amcSegHasNailboard(seg)); - return PARENT(amcNailboardStruct, type, p); -} - - -/* amcSegGen -- get the generation structure for this segment */ - -static amcGen amcSegGen(Seg seg) -{ - if(amcSegHasNailboard(seg)) { - amcNailboard Nailboard = amcSegNailboard(seg); - return Nailboard->gen; - } else { - int *p; - p = amcSegTypeP(seg); - return PARENT(amcGenStruct, type, p); - } -} - - -/* AMCStruct -- pool AMC descriptor - * - * See . - */ - -#define AMCSig ((Sig)0x519A3C99) /* SIGnature AMC */ - -typedef struct PageRetStruct { - Count pCond; /* pages Condemned */ - Count pRet; /* pages Retained (in place) */ - /* Small */ - Count pCS; /* pages Condemned in Small segments */ - Count pRS; /* pages Retained in Small segments */ - /* Medium */ - Count sCM; /* segments Condemned: Medium */ - /* ...= upper bound of how many extra pages it */ - /* would have cost, had we chosen to LSP-pad */ - /* all these segments. */ - Count pCM; /* pages Condemned in Medium segments */ - Count sRM; /* segments Retained: Medium */ - Count pRM; /* pages Retained in Medium segments: */ - Count pRM1; /* ...because obj 1 was preserved in place */ - /* ...because a rest obj was pip, causing: */ - Count pRMrr; /* ...retained rest pages (page where rest obj is) */ - Count pRMr1; /* ...retained obj 1 pages (purely NMR pad) */ - /* Large */ - Count sCL; /* segments Condemned: Large */ - /* ...= upper bound of how many extra pages it */ - /* has cost to LSP-pad all these segments. */ - Count pCL; /* pages Condemned in Large segments */ - Count sRL; /* segments Retained: Large */ - Count pRL; /* pages Retained in Large segments */ - Count pRLr; /* ...because a rest obj (actually LSP) was pip */ - - /* The interesting things about this report are: - * - How many pages are actually being retained? (pRet) - * - Percentage? (pRet/pCond) - * - Is the major contribution from Small, Medium, or Large segs? - * - * Generally, pages retained because obj 1 needed to be preserved in - * place are ok (because no alternative placement could have retained - * fewer pages), but pages retained by a rest obj are unfortunate - * (better placement, putting the small rest objs in their own seg, - * would have retained fewer pages). In particular: - * - * The LSP threshold is a payoff between the wasted space from - * LSP-padding, versus the risk of increased page-retention (due to - * rest objs) from not LSP-padding. - * - * For Medium segs, where we do not do LSP-padding: - * - LSP would have required at most sCM extra pages; - * - the extra retention incurred by not LSP-padding is pRMr1. - * A high pRMr1 => lots of Medium segs getting retained by the rest - * objs tacked on after obj 1. Consider lowering LSP-threshold. - * - * For Large segs we do LSP padding. This has a cost; upper bound is - * sCL extra pages. But the benefit should be greatly reduced ambig - * refs to rest objs. With LSP, the only rest obj is the LSP pad - * itself. We expect that ambig refs to this are rare, so currently - * we do not implement .large.lsp-no-retain. But we do record the - * occurrence of pages retained by a ref to an LSP pad: pPLr. A high - * pRLr => perhaps .large.lsp-no-retain should be implemented? - * - * If the mutator is causing a lot of page retention, then sRM/pRM - * and sRL/pRL should give some picture of the number of retained - * objects and their average size. - */ -} PageRetStruct; - -/* static => init'd to zero */ -static struct PageRetStruct pageretstruct_Zero; - -typedef struct AMCStruct { /* */ - PoolStruct poolStruct; /* generic pool structure */ - RankSet rankSet; /* rankSet for entire pool */ - RingStruct genRing; /* ring of generations */ - Bool gensBooted; /* used during boot (init) */ - Chain chain; /* chain used by this pool */ - size_t gens; /* number of generations */ - amcGen *gen; /* (pointer to) array of generations */ - amcGen nursery; /* the default mutator generation */ - amcGen rampGen; /* the ramp generation */ - amcGen afterRampGen; /* the generation after rampGen */ - unsigned rampCount; /* */ - int rampMode; /* */ - - /* page retention in an in-progress trace */ - STATISTIC_DECL(PageRetStruct pageretstruct[TraceLIMIT]); - - Sig sig; /* */ -} AMCStruct; - -#define Pool2AMC(pool) PARENT(AMCStruct, poolStruct, (pool)) -#define AMC2Pool(amc) (&(amc)->poolStruct) - - -/* amcGenCheck -- check consistency of a generation structure */ - -static Bool amcGenCheck(amcGen gen) -{ - Arena arena; - AMC amc; - - CHECKS(amcGen, gen); - CHECKD(PoolGen, &gen->pgen); - amc = amcGenAMC(gen); - CHECKU(AMC, amc); - CHECKL(gen->type == AMCPTypeGen); - CHECKD(Buffer, gen->forward); - CHECKL(RingCheck(&gen->amcRing)); - CHECKL((gen->pgen.totalSize == 0) == (gen->segs == 0)); - arena = amc->poolStruct.arena; - CHECKL(gen->pgen.totalSize >= gen->segs * ArenaAlign(arena)); - return TRUE; -} - - -/* amcNailboardCheck -- check the nailboard */ - -static Bool amcNailboardCheck(amcNailboard board) -{ - CHECKS(amcNailboard, board); - CHECKL(board->type == AMCPTypeNailboard); - CHECKD(amcGen, board->gen); - /* nails is >= number of set bits in mark, but we can't check this */ - /* We know that shift corresponds to pool->align. */ - CHECKL(BoolCheck(board->newMarks)); - CHECKL(board->distinctNails <= board->nails); - CHECKL((Align)1 << board->markShift - == PoolAlignment(amcGenPool(board->gen))); - /* weak check for BTs @@@@ */ - CHECKL(board->mark != NULL); - return TRUE; -} - - -/* amcBufStruct -- AMC Buffer subclass - * - * This subclass of SegBuf records a link to a generation. - */ - -#define amcBufSig ((Sig)0x519A3CBF) /* SIGnature AMC BuFfer */ - -typedef struct amcBufStruct *amcBuf; - -typedef struct amcBufStruct { - SegBufStruct segbufStruct; /* superclass fields must come first */ - amcGen gen; /* The AMC generation */ - Sig sig; /* */ -} amcBufStruct; - - -/* Buffer2amcBuf -- convert generic Buffer to an amcBuf */ - -#define Buffer2amcBuf(buffer) ((amcBuf)(buffer)) - - - -/* amcBufCheck -- check consistency of an amcBuf */ - -static Bool amcBufCheck(amcBuf amcbuf) -{ - SegBuf segbuf; - - CHECKS(amcBuf, amcbuf); - segbuf = &amcbuf->segbufStruct; - CHECKL(SegBufCheck(segbuf)); - if(amcbuf->gen != NULL) - CHECKD(amcGen, amcbuf->gen); - return TRUE; -} - - -/* amcBufGen -- Return the AMC generation of an amcBuf */ - -static amcGen amcBufGen(Buffer buffer) -{ - return Buffer2amcBuf(buffer)->gen; -} - - -/* amcBufSetGen -- Set the AMC generation of an amcBuf */ - -static void amcBufSetGen(Buffer buffer, amcGen gen) -{ - amcBuf amcbuf; - - if(gen != NULL) - AVERT(amcGen, gen); - amcbuf = Buffer2amcBuf(buffer); - amcbuf->gen = gen; -} - - -/* AMCBufInit -- Initialize an amcBuf */ - -static Res AMCBufInit(Buffer buffer, Pool pool, va_list args) -{ - AMC amc; - amcBuf amcbuf; - BufferClass superclass; - Res res; - - AVERT(Buffer, buffer); - AVERT(Pool, pool); - amc = Pool2AMC(pool); - AVERT(AMC, amc); - - /* call next method */ - superclass = BUFFER_SUPERCLASS(amcBufClass); - res = (*superclass->init)(buffer, pool, args); - if(res != ResOK) - return res; - - amcbuf = Buffer2amcBuf(buffer); - if(BufferIsMutator(buffer)) { - /* Set up the buffer to be allocating in the nursery. */ - amcbuf->gen = amc->nursery; - } else { - /* No gen yet -- see . */ - amcbuf->gen = NULL; - } - amcbuf->sig = amcBufSig; - AVERT(amcBuf, amcbuf); - - BufferSetRankSet(buffer, amc->rankSet); - - return ResOK; -} - - -/* AMCBufFinish -- Finish an amcBuf */ - -static void AMCBufFinish(Buffer buffer) -{ - BufferClass super; - amcBuf amcbuf; - - AVERT(Buffer, buffer); - amcbuf = Buffer2amcBuf(buffer); - AVERT(amcBuf, amcbuf); - - amcbuf->sig = SigInvalid; - - /* Finish the superclass fields last. */ - super = BUFFER_SUPERCLASS(amcBufClass); - super->finish(buffer); -} - - -/* amcBufClass -- The class definition */ - -DEFINE_BUFFER_CLASS(amcBufClass, class) -{ - INHERIT_CLASS(class, SegBufClass); - class->name = "AMCBUF"; - class->size = sizeof(amcBufStruct); - class->init = AMCBufInit; - class->finish = AMCBufFinish; -} - - -/* amcGenCreate -- create a generation */ - -static Res amcGenCreate(amcGen *genReturn, AMC amc, Serial genNr) -{ - Arena arena; - Buffer buffer; - Pool pool; - amcGen gen; - Res res; - void *p; - - pool = AMC2Pool(amc); - arena = pool->arena; - - res = ControlAlloc(&p, arena, sizeof(amcGenStruct), FALSE); - if(res != ResOK) - goto failControlAlloc; - gen = (amcGen)p; - - res = BufferCreate(&buffer, EnsureamcBufClass(), pool, FALSE); - if(res != ResOK) - goto failBufferCreate; - - res = PoolGenInit(&gen->pgen, amc->chain, genNr, pool); - if(res != ResOK) - goto failGenInit; - gen->type = AMCPTypeGen; - RingInit(&gen->amcRing); - gen->segs = 0; - gen->forward = buffer; - gen->sig = amcGenSig; - - AVERT(amcGen, gen); - - RingAppend(&amc->genRing, &gen->amcRing); - EVENT2(AMCGenCreate, amc, gen); - *genReturn = gen; - return ResOK; - -failGenInit: - BufferDestroy(buffer); -failBufferCreate: - ControlFree(arena, p, sizeof(amcGenStruct)); -failControlAlloc: - return res; -} - - -/* amcGenDestroy -- destroy a generation */ - -static void amcGenDestroy(amcGen gen) -{ - Arena arena; - - AVERT(amcGen, gen); - AVER(gen->segs == 0); - AVER(gen->pgen.totalSize == 0); - - EVENT1(AMCGenDestroy, gen); - arena = PoolArena(amcGenPool(gen)); - gen->sig = SigInvalid; - RingRemove(&gen->amcRing); - RingFinish(&gen->amcRing); - PoolGenFinish(&gen->pgen); - BufferDestroy(gen->forward); - ControlFree(arena, gen, sizeof(amcGenStruct)); -} - - -/* amcGenDescribe -- describe an AMC generation */ - -static Res amcGenDescribe(amcGen gen, mps_lib_FILE *stream) -{ - Res res; - - if(!TESTT(amcGen, gen)) - return ResFAIL; - - res = WriteF(stream, - " amcGen $P ($U) {\n", - (WriteFP)gen, (WriteFU)amcGenNr(gen), - " buffer $P\n", gen->forward, - " segs $U, totalSize $U, newSize $U\n", - (WriteFU)gen->segs, - (WriteFU)gen->pgen.totalSize, - (WriteFU)gen->pgen.newSize, - " } amcGen\n", NULL); - return res; -} - - -/* amcSegCreateNailboard -- create nailboard for segment */ - -static Res amcSegCreateNailboard(Seg seg, Pool pool) -{ - amcNailboard board; - Arena arena; - Count bits; - Res res; - void *p; - - AVER(!amcSegHasNailboard(seg)); - - arena = PoolArena(pool); - - res = ControlAlloc(&p, arena, sizeof(amcNailboardStruct), FALSE); - if(res != ResOK) - goto failAllocNailboard; - board = p; - board->type = AMCPTypeNailboard; - board->gen = amcSegGen(seg); - board->nails = (Count)0; - board->distinctNails = (Count)0; - board->newMarks = FALSE; - board->markShift = SizeLog2((Size)pool->alignment); - /* [I wonder what this comment is referring to? 2007-07-11 DRJ] */ - /* See d.m.p.Nailboard.size. */ - bits = (SegSize(seg) + pool->format->headerSize) >> board->markShift; - res = ControlAlloc(&p, arena, BTSize(bits), FALSE); - if(res != ResOK) - goto failMarkTable; - board->mark = p; - BTResRange(board->mark, 0, bits); - board->sig = amcNailboardSig; - AVERT(amcNailboard, board); - amcSegSetTypeP(seg, &board->type); /* .segtype */ - return ResOK; - -failMarkTable: - ControlFree(arena, board, sizeof(amcNailboardStruct)); -failAllocNailboard: - return res; -} - - -/* amcSegDestroyNailboard -- destroy the nailboard of a segment */ - -static void amcSegDestroyNailboard(Seg seg, Pool pool) -{ - amcNailboard board; - amcGen gen; - Arena arena; - Count bits; - - gen = amcSegGen(seg); - board = amcSegNailboard(seg); - AVERT(amcNailboard, board); - - arena = PoolArena(pool); - /* See d.m.p.Nailboard.size. */ - bits = (SegSize(seg) + pool->format->headerSize) >> board->markShift; - ControlFree(arena, board->mark, BTSize(bits)); - board->sig = SigInvalid; - ControlFree(arena, board, sizeof(amcNailboardStruct)); - amcSegSetTypeP(seg, &gen->type); /* .segtype */ -} - - -/* amcNailGetMark -- get the mark bit for ref from the nailboard */ - -static Bool amcNailGetMark(Seg seg, Ref ref) -{ - amcNailboard board; - Index i; - - board = amcSegNailboard(seg); - AVERT(amcNailboard, board); - - i = AddrOffset(SegBase(seg), ref) >> board->markShift; - return BTGet(board->mark, i); -} - - -/* amcNailGetAndSetMark -- set the mark bit for ref in the nailboard - * - * Returns the old value. - */ -static Bool amcNailGetAndSetMark(Seg seg, Ref ref) -{ - amcNailboard board; - Index i; - - board = amcSegNailboard(seg); - AVERT(amcNailboard, board); - - ++board->nails; - i = AddrOffset(SegBase(seg), ref) >> board->markShift; - if(!BTGet(board->mark, i)) { - BTSet(board->mark, i); - board->newMarks = TRUE; - ++board->distinctNails; - return FALSE; - } - return TRUE; -} - - -/* amcNailMarkRange -- nail a range in the board - * - * We nail the objects laying between base and limit, i.e., mark the - * bits that correspond to client pointers for them. We may assume - * that the range is unmarked. - */ -static void amcNailMarkRange(Seg seg, Addr base, Addr limit) -{ - amcNailboard board; - Index ibase, ilimit; - Size headerSize; - - AVER(SegBase(seg) <= base); - AVER(base < SegLimit(seg)); - AVER(SegBase(seg) <= limit); - AVER(limit <= SegLimit(seg)); - AVER(base < limit); - - board = amcSegNailboard(seg); - AVERT(amcNailboard, board); - headerSize = SegPool(seg)->format->headerSize; - ibase = (AddrOffset(SegBase(seg), base) + headerSize) - >> board->markShift; - ilimit = (AddrOffset(SegBase(seg), limit) + headerSize) - >> board->markShift; - AVER(BTIsResRange(board->mark, ibase, ilimit)); - - BTSetRange(board->mark, ibase, ilimit); - board->nails += ilimit - ibase; - board->distinctNails += ilimit - ibase; -} - - -/* amcNailRangeIsMarked -- check that a range in the board is marked - * - * Like amcNailMarkRange, we take the arguments as referring to base - * pointers and look at the bits of the corresponding client pointers. - */ -static Bool amcNailRangeIsMarked(Seg seg, Addr base, Addr limit) -{ - amcNailboard board; - Index ibase, ilimit; - Size headerSize; - - AVER(SegBase(seg) <= base); - AVER(base < SegLimit(seg)); - AVER(SegBase(seg) <= limit); - AVER(limit <= SegLimit(seg)); - AVER(base < limit); - - board = amcSegNailboard(seg); - AVERT(amcNailboard, board); - headerSize = SegPool(seg)->format->headerSize; - ibase = (AddrOffset(SegBase(seg), base) + headerSize) - >> board->markShift; - ilimit = (AddrOffset(SegBase(seg), limit) + headerSize) - >> board->markShift; - return BTIsSetRange(board->mark, ibase, ilimit); -} - - -/* amcInitComm -- initialize AMC/Z pool - * - * See . - * Shared by AMCInit and AMCZinit. - */ -static Res amcInitComm(Pool pool, RankSet rankSet, va_list arg) -{ - AMC amc; - Res res; - Arena arena; - TraceId ti; - Trace trace; - Index i; - size_t genArraySize; - size_t genCount; - - /* Suppress a warning about this structure not being used when there - are no statistics. Note that simply making the declaration conditional - does not work, because we carefully reference expressions inside - STATISTICS to prevent such warnings on parameters and local variables. - It's just that clang 4.0 on Mac OS X does some sort of extra check - that produces a special warnings about static variables. */ -#if !defined(STATISTICS) - UNUSED(pageretstruct_Zero); -#endif - - AVER(pool != NULL); - - amc = Pool2AMC(pool); - arena = PoolArena(pool); - - pool->format = va_arg(arg, Format); - AVERT(Format, pool->format); - pool->alignment = pool->format->alignment; - amc->chain = va_arg(arg, Chain); - AVERT(Chain, amc->chain); - amc->rankSet = rankSet; - - RingInit(&amc->genRing); - /* amc gets checked before the generations get created, but they */ - /* do get created later in this function. */ - amc->gen = NULL; - amc->nursery = NULL; - amc->rampGen = NULL; - amc->afterRampGen = NULL; - amc->gensBooted = FALSE; - - amc->rampCount = 0; - amc->rampMode = RampOUTSIDE; - - TRACE_SET_ITER(ti, trace, TraceSetUNIV, arena) - STATISTIC(amc->pageretstruct[ti] = pageretstruct_Zero); - TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena); - - if(pool->format->headerSize == 0) { - pool->fix = AMCFix; - } else { - pool->fix = AMCHeaderFix; - } - - amc->sig = AMCSig; - AVERT(AMC, amc); - - /* Init generations. */ - genCount = ChainGens(amc->chain); - { - void *p; - - /* One gen for each one in the chain plus dynamic gen. */ - genArraySize = sizeof(amcGen) * (genCount + 1); - res = ControlAlloc(&p, arena, genArraySize, FALSE); - if(res != ResOK) - goto failGensAlloc; - amc->gen = p; - for(i = 0; i < genCount + 1; ++i) { - res = amcGenCreate(&amc->gen[i], amc, (Serial)i); - if(res != ResOK) { - goto failGenAlloc; - } - } - /* Set up forwarding buffers. */ - for(i = 0; i < genCount; ++i) { - amcBufSetGen(amc->gen[i]->forward, amc->gen[i+1]); - } - /* Dynamic gen forwards to itself. */ - amcBufSetGen(amc->gen[genCount]->forward, amc->gen[genCount]); - } - amc->nursery = amc->gen[0]; - amc->rampGen = amc->gen[genCount-1]; /* last ephemeral gen */ - amc->afterRampGen = amc->gen[genCount]; - amc->gensBooted = TRUE; - - AVERT(AMC, amc); - EVENT2(AMCInit, pool, amc); - if(rankSet == RankSetEMPTY) - EVENT2(PoolInitAMCZ, pool, pool->format); - else - EVENT2(PoolInitAMC, pool, pool->format); - return ResOK; - -failGenAlloc: - while(i > 0) { - --i; - amcGenDestroy(amc->gen[i]); - } - ControlFree(arena, amc->gen, genArraySize); -failGensAlloc: - return res; -} - -static Res AMCInit(Pool pool, va_list arg) -{ - return amcInitComm(pool, RankSetSingle(RankEXACT), arg); -} - -static Res AMCZInit(Pool pool, va_list arg) -{ - return amcInitComm(pool, RankSetEMPTY, arg); -} - - -/* AMCFinish -- finish AMC pool - * - * See . - */ -static void AMCFinish(Pool pool) -{ - AMC amc; - Ring ring; - Ring node, nextNode; - - AVERT(Pool, pool); - amc = Pool2AMC(pool); - AVERT(AMC, amc); - - EVENT1(AMCFinish, amc); - - /* @@@@ Make sure that segments aren't buffered by forwarding */ - /* buffers. This is a hack which allows the pool to be destroyed */ - /* while it is collecting. Note that there aren't any mutator */ - /* buffers by this time. */ - RING_FOR(node, &amc->genRing, nextNode) { - amcGen gen = RING_ELT(amcGen, amcRing, node); - BufferDetach(gen->forward, pool); - /* Maintain invariant < totalSize. */ - gen->pgen.newSize = (Size)0; - } - - ring = PoolSegRing(pool); - RING_FOR(node, ring, nextNode) { - Seg seg = SegOfPoolRing(node); - Size size; - amcGen gen = amcSegGen(seg); - - --gen->segs; - size = SegSize(seg); - gen->pgen.totalSize -= size; - - SegFree(seg); - } - - /* Disassociate forwarding buffers from gens before they are */ - /* destroyed. */ - ring = &amc->genRing; - RING_FOR(node, ring, nextNode) { - amcGen gen = RING_ELT(amcGen, amcRing, node); - amcBufSetGen(gen->forward, NULL); - } - RING_FOR(node, ring, nextNode) { - amcGen gen = RING_ELT(amcGen, amcRing, node); - amcGenDestroy(gen); - } - - amc->sig = SigInvalid; -} - - -/* AMCBufferFill -- refill an allocation buffer - * - * See . - */ -static Res AMCBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - Seg seg; - AMC amc; - Res res; - Addr base, limit; - Arena arena; - Size alignedSize; - amcGen gen; - Serial genNr; - SegPrefStruct segPrefStruct; - - AVERT(Pool, pool); - amc = Pool2AMC(pool); - AVERT(AMC, amc); - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Buffer, buffer); - AVER(BufferIsReset(buffer)); - AVER(size > 0); - AVER(SizeIsAligned(size, PoolAlignment(pool))); - AVERT(Bool, withReservoirPermit); - - gen = amcBufGen(buffer); - AVERT(amcGen, gen); - - /* Create and attach segment. The location of this segment is */ - /* expressed as a generation number. We rely on the arena to */ - /* organize locations appropriately. */ - arena = PoolArena(pool); - alignedSize = SizeAlignUp(size, ArenaAlign(arena)); - segPrefStruct = *SegPrefDefault(); - SegPrefExpress(&segPrefStruct, SegPrefCollected, NULL); - genNr = PoolGenNr(&gen->pgen); - SegPrefExpress(&segPrefStruct, SegPrefGen, &genNr); - res = SegAlloc(&seg, amcSegClassGet(), &segPrefStruct, - alignedSize, pool, withReservoirPermit, - &gen->type); /* .segtype */ - if(res != ResOK) - return res; - AVER(alignedSize == SegSize(seg)); - - /* */ - if(BufferRankSet(buffer) == RankSetEMPTY) - SegSetRankAndSummary(seg, BufferRankSet(buffer), RefSetEMPTY); - else - SegSetRankAndSummary(seg, BufferRankSet(buffer), RefSetUNIV); - - /* Put the segment in the generation indicated by the buffer. */ - ++gen->segs; - gen->pgen.totalSize += alignedSize; - /* If ramping, don't count survivors in newSize. */ - if(amc->rampMode != RampRAMPING - || buffer != amc->rampGen->forward - || gen != amc->rampGen) - { - gen->pgen.newSize += alignedSize; - } else { - Seg2amcSeg(seg)->new = FALSE; - } - PoolGenUpdateZones(&gen->pgen, seg); - - base = SegBase(seg); - *baseReturn = base; - if(alignedSize < AMCLargeSegPAGES * ArenaAlign(arena)) { - /* Small or Medium segment: give the buffer the entire seg. */ - limit = AddrAdd(base, alignedSize); - AVER(limit == SegLimit(seg)); - } else { - /* Large segment: ONLY give the buffer the size requested, and */ - /* pad the remainder of the segment: see job001811. */ - Size padSize; - - limit = AddrAdd(base, size); - AVER(limit <= SegLimit(seg)); - - padSize = alignedSize - size; - AVER(SizeIsAligned(padSize, PoolAlignment(pool))); - AVER(AddrAdd(limit, padSize) == SegLimit(seg)); - if(padSize > 0) { - ShieldExpose(arena, seg); - (*pool->format->pad)(limit, padSize); - ShieldCover(arena, seg); - } - } - *limitReturn = limit; - return ResOK; -} - - -/* amcBufferEmpty -- detach a buffer from a segment - * - * See . - */ -static void AMCBufferEmpty(Pool pool, Buffer buffer, - Addr init, Addr limit) -{ - AMC amc; - Size size; - Arena arena; - Seg seg; - - AVERT(Pool, pool); - amc = Pool2AMC(pool); - AVERT(AMC, amc); - AVERT(Buffer, buffer); - AVER(BufferIsReady(buffer)); - seg = BufferSeg(buffer); - AVERT(Seg, seg); - AVER(init <= limit); - - arena = BufferArena(buffer); - if(SegSize(seg) < AMCLargeSegPAGES * ArenaAlign(arena)) { - /* Small or Medium segment: buffer had the entire seg. */ - AVER(limit == SegLimit(seg)); - } else { - /* Large segment: buffer had only the size requested; job001811. */ - AVER(limit <= SegLimit(seg)); - } - - /* */ - size = AddrOffset(init, limit); - if(size > 0) { - ShieldExpose(arena, seg); - (*pool->format->pad)(init, size); - ShieldCover(arena, seg); - } -} - - -/* AMCRampBegin -- note an entry into a ramp pattern */ - -static void AMCRampBegin(Pool pool, Buffer buf, Bool collectAll) -{ - AMC amc; - - AVERT(Pool, pool); - amc = Pool2AMC(pool); - AVERT(AMC, amc); - AVERT(Buffer, buf); - AVERT(Bool, collectAll); - UNUSED(collectAll); /* obsolete */ - - AVER(amc->rampCount < UINT_MAX); - ++amc->rampCount; - if(amc->rampCount == 1) { - if(amc->rampMode != RampFINISH) - amc->rampMode = RampBEGIN; - } -} - - -/* AMCRampEnd -- note an exit from a ramp pattern */ - -static void AMCRampEnd(Pool pool, Buffer buf) -{ - AMC amc; - - AVERT(Pool, pool); - amc = Pool2AMC(pool); - AVERT(AMC, amc); - AVERT(Buffer, buf); - - AVER(amc->rampCount > 0); - --amc->rampCount; - if(amc->rampCount == 0) { - PoolGen pgen = &amc->rampGen->pgen; - Ring node, nextNode; - - if(amc->rampMode == RampRAMPING) { - /* We were ramping, so clean up. */ - amc->rampMode = RampFINISH; - } else { - amc->rampMode = RampOUTSIDE; - } - - /* Adjust amc->rampGen->pgen.newSize: Now count all the segments */ - /* in the ramp generation as new (except if they're white). */ - RING_FOR(node, PoolSegRing(pool), nextNode) { - Seg seg = SegOfPoolRing(node); - - if(amcSegGen(seg) == amc->rampGen && !Seg2amcSeg(seg)->new - && SegWhite(seg) == TraceSetEMPTY) - { - pgen->newSize += SegSize(seg); - Seg2amcSeg(seg)->new = TRUE; - } - } - } -} - - -/* AMCWhiten -- condemn the segment for the trace - * - * If the segment has a mutator buffer on it, we nail the buffer, - * because we can't scan or reclaim uncommitted buffers. - */ -static Res AMCWhiten(Pool pool, Trace trace, Seg seg) -{ - amcGen gen; - AMC amc; - Buffer buffer; - Res res; - - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - - buffer = SegBuffer(seg); - if(buffer != NULL) { - AVERT(Buffer, buffer); - - if(!BufferIsMutator(buffer)) { /* forwarding buffer */ - AVER(BufferIsReady(buffer)); - BufferDetach(buffer, pool); - } else { /* mutator buffer */ - if(BufferScanLimit(buffer) == SegBase(seg)) { - /* There's nothing but the buffer, don't condemn. */ - return ResOK; - } - /* [The following else-if section is just a comment added in */ - /* 1998-10-08. It has never worked. RHSK 2007-01-16] */ - /* else if (BufferScanLimit(buffer) == BufferLimit(buffer)) { */ - /* The buffer is full, so it won't be used by the mutator. */ - /* @@@@ We should detach it, but can't for technical */ - /* reasons. */ - /* BufferDetach(buffer, pool); */ - /* } */ - else { - /* There is an active buffer, make sure it's nailed. */ - if(!amcSegHasNailboard(seg)) { - if(SegNailed(seg) == TraceSetEMPTY) { - res = amcSegCreateNailboard(seg, pool); - if(res != ResOK) { - /* Can't create nailboard, don't condemn. */ - return ResOK; - } - if(BufferScanLimit(buffer) != BufferLimit(buffer)) { - amcNailMarkRange(seg, BufferScanLimit(buffer), - BufferLimit(buffer)); - } - ++trace->nailCount; - SegSetNailed(seg, TraceSetSingle(trace)); - } else { - /* Segment is nailed already, cannot create a nailboard */ - /* (see .nail.new), just give up condemning. */ - return ResOK; - } - } else { - /* We have a nailboard, the buffer must be nailed already. */ - AVER((BufferScanLimit(buffer) == BufferLimit(buffer)) - || amcNailRangeIsMarked(seg, BufferScanLimit(buffer), - BufferLimit(buffer))); - /* Nail it for this trace as well. */ - SegSetNailed(seg, TraceSetAdd(SegNailed(seg), trace)); - } - /* We didn't condemn the buffer, subtract it from the count. */ - /* @@@@ We could subtract all the nailed grains. */ - /* Relies on unsigned arithmetic wrapping round */ - /* on under- and overflow (which it does). */ - trace->condemned -= AddrOffset(BufferScanLimit(buffer), - BufferLimit(buffer)); - } - } - } - - SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace)); - trace->condemned += SegSize(seg); - - amc = Pool2AMC(pool); - AVERT(AMC, amc); - - STATISTIC_STAT( { - Count pages; - AVER(SizeIsAligned(SegSize(seg), ArenaAlign(pool->arena))); - pages = SegSize(seg) / ArenaAlign(pool->arena); - AVER(pages != 0); - amc->pageretstruct[trace->ti].pCond += pages; - if(pages == 1) { - amc->pageretstruct[trace->ti].pCS += pages; - } else if(pages < AMCLargeSegPAGES) { - amc->pageretstruct[trace->ti].sCM += 1; - amc->pageretstruct[trace->ti].pCM += pages; - } else { - amc->pageretstruct[trace->ti].sCL += 1; - amc->pageretstruct[trace->ti].pCL += pages; - } - } ); - - gen = amcSegGen(seg); - AVERT(amcGen, gen); - if(Seg2amcSeg(seg)->new) { - gen->pgen.newSize -= SegSize(seg); - Seg2amcSeg(seg)->new = FALSE; - } - - /* Ensure we are forwarding into the right generation. */ - - /* see */ - /* This switching needs to be more complex for multiple traces. */ - AVER(TraceSetIsSingle(PoolArena(pool)->busyTraces)); - if(amc->rampMode == RampBEGIN && gen == amc->rampGen) { - BufferDetach(gen->forward, pool); - amcBufSetGen(gen->forward, gen); - amc->rampMode = RampRAMPING; - } else if(amc->rampMode == RampFINISH && gen == amc->rampGen) { - BufferDetach(gen->forward, pool); - amcBufSetGen(gen->forward, amc->afterRampGen); - amc->rampMode = RampCOLLECTING; - } - - return ResOK; -} - - -/* amcScanNailedOnce -- make one scanning pass over a nailed segment - * - * *totalReturn set to TRUE iff all objects in segment scanned. - * *moreReturn set to FALSE only if there are no more objects - * on the segment that need scanning (which is normally the case). - * It is set to TRUE if scanning had to be abandoned early on, and - * also if during emergency fixing any new marks got added to the - * nailboard. - */ -static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, - ScanState ss, Pool pool, Seg seg, AMC amc) -{ - Addr p, limit; - Format format; - Res res; - Bool total = TRUE; - Size bytesScanned = 0; - - UNUSED(amc); /* Actually only unused when telemetry is off. @@@@ */ - - EVENT3(AMCScanBegin, amc, seg, ss); /* @@@@ use own event */ - - format = pool->format; - amcSegNailboard(seg)->newMarks = FALSE; - - p = AddrAdd(SegBase(seg), format->headerSize); - while(SegBuffer(seg) != NULL) { - limit = AddrAdd(BufferScanLimit(SegBuffer(seg)), - format->headerSize); - if(p >= limit) { - AVER(p == limit); - goto returnGood; - } - while(p < limit) { - Addr q; - q = (*format->skip)(p); - if(amcNailGetMark(seg, p)) { - res = (*format->scan)(&ss->ss_s, p, q); - if(res != ResOK) { - *totalReturn = FALSE; - *moreReturn = TRUE; - return res; - } - bytesScanned += AddrOffset(p, q); - } else { - total = FALSE; - } - p = q; - } - AVER(p == limit); - } - - /* Should have a ScanMarkedRange or something like that @@@@ */ - /* to abstract common code. */ - limit = AddrAdd(SegLimit(seg), format->headerSize); - /* @@@@ Shouldn't p be set to BufferLimit here?! */ - while(p < limit) { - Addr q; - q = (*format->skip)(p); - if(amcNailGetMark(seg, p)) { - res = (*format->scan)(&ss->ss_s, p, q); - if(res != ResOK) { - *totalReturn = FALSE; - *moreReturn = TRUE; - return res; - } - bytesScanned += AddrOffset(p, q); - } else { - total = FALSE; - } - p = q; - } - AVER(p == limit); - -returnGood: - EVENT3(AMCScanEnd, amc, seg, ss); /* @@@@ use own event */ - - AVER(bytesScanned <= SegSize(seg)); - ss->scannedSize += bytesScanned; - *totalReturn = total; - *moreReturn = amcSegNailboard(seg)->newMarks; - return ResOK; -} - - -/* amcScanNailed -- scan a nailed segment */ - -static Res amcScanNailed(Bool *totalReturn, ScanState ss, Pool pool, - Seg seg, AMC amc) -{ - Bool total, moreScanning; - size_t loops = 0; - - do { - Res res; - res = amcScanNailedOnce(&total, &moreScanning, ss, pool, seg, amc); - if(res != ResOK) { - *totalReturn = FALSE; - return res; - } - loops += 1; - } while(moreScanning); - - if(loops > 1) { - RefSet refset; - - AVER(ArenaEmergency(PoolArena(pool))); - - /* Looped: fixed refs (from 1st pass) were seen by MPS_FIX1 - * (in later passes), so the "ss.unfixedSummary" is _not_ - * purely unfixed. In this one case, unfixedSummary is not - * accurate, and cannot be used to verify the SegSummary (see - * impl/trace/#verify.segsummary). Use ScanStateSetSummary to - * store ScanStateSummary in ss.fixedSummary and reset - * ss.unfixedSummary. See job001548. - */ - - refset = ScanStateSummary(ss); - -#if 1 - /* A rare event, which might prompt a rare defect to appear. */ - DIAG_SINGLEF(( "amcScanNailed_loop", - "scan completed, but had to loop $U times:\n", (WriteFU)loops, - " SegSummary: $B\n", (WriteFB)SegSummary(seg), - " ss.white: $B\n", (WriteFB)ScanStateWhite(ss), - " ss.unfixedSummary: $B", (WriteFB)ScanStateUnfixedSummary(ss), - "$S\n", (WriteFS)( - (RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg))) - ? "" - : " <=== This would have failed .verify.segsummary!" - ), - " ss.fixedSummary: $B\n", (WriteFB)ss->fixedSummary, - "ScanStateSummary: $B\n", (WriteFB)refset, - "MOVING ScanStateSummary TO fixedSummary, " - "RESETTING unfixedSummary.\n", NULL - )); -#endif - - ScanStateSetSummary(ss, refset); - } - - *totalReturn = total; - return ResOK; -} - - -/* AMCScan -- scan a single seg, turning it black - * - * See . - */ -static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) -{ - Addr base, limit; - Format format; - AMC amc; - Res res; - - AVER(totalReturn != NULL); - AVERT(ScanState, ss); - AVERT(Seg, seg); - AVERT(Pool, pool); - amc = Pool2AMC(pool); - AVERT(AMC, amc); - - - format = pool->format; - - if(amcSegHasNailboard(seg)) { - return amcScanNailed(totalReturn, ss, pool, seg, amc); - } - - EVENT3(AMCScanBegin, amc, seg, ss); - - base = AddrAdd(SegBase(seg), format->headerSize); - /* */ - while(SegBuffer(seg) != NULL) { - limit = AddrAdd(BufferScanLimit(SegBuffer(seg)), - format->headerSize); - if(base >= limit) { - /* @@@@ Are we sure we don't need scan the rest of the */ - /* segment? */ - AVER(base == limit); - *totalReturn = TRUE; - return ResOK; - } - res = (*format->scan)(&ss->ss_s, base, limit); - if(res != ResOK) { - *totalReturn = FALSE; - return res; - } - ss->scannedSize += AddrOffset(base, limit); - base = limit; - } - - /* @@@@ base? */ - limit = AddrAdd(SegLimit(seg), format->headerSize); - AVER(SegBase(seg) <= base); - AVER(base <= AddrAdd(SegLimit(seg), format->headerSize)); - if(base < limit) { - res = (*format->scan)(&ss->ss_s, base, limit); - if(res != ResOK) { - *totalReturn = FALSE; - return res; - } - } - - ss->scannedSize += AddrOffset(base, limit); - EVENT3(AMCScanEnd, amc, seg, ss); - - *totalReturn = TRUE; - return ResOK; -} - - -/* amcFixInPlace -- fix an reference without moving the object - * - * Usually this function is used for ambiguous references, but during - * emergency tracing may be used for references of any rank. - * - * If the segment has a nailboard then we use that to record the fix. - * Otherwise we simply grey and nail the entire segment. - */ -static void amcFixInPlace(Pool pool, Seg seg, ScanState ss, Ref *refIO) -{ - Addr ref; - - UNUSED(pool); - - ref = (Addr)*refIO; - /* An ambiguous reference can point before the header. */ - AVER(SegBase(seg) <= ref); - /* .ref-limit: A reference passed to Fix can't be beyond the */ - /* segment, because then TraceFix would not have picked this */ - /* segment. */ - AVER(ref < SegLimit(seg)); - - EVENT0(AMCFixInPlace); - if(amcSegHasNailboard(seg)) { - Bool wasMarked = amcNailGetAndSetMark(seg, ref); - /* If there are no new marks (i.e., no new traces for which we */ - /* are marking, and no new mark bits set) then we can return */ - /* immediately, without changing colour. */ - if(TraceSetSub(ss->traces, SegNailed(seg)) && wasMarked) - return; - } else if(TraceSetSub(ss->traces, SegNailed(seg))) { - return; - } - SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); - SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); -} - - -/* AMCFixEmergency -- fix a reference, without allocating - * - * See . - */ -static Res AMCFixEmergency(Pool pool, ScanState ss, Seg seg, - Ref *refIO) -{ - Arena arena; - AMC amc; - Addr newRef; - - AVERT(Pool, pool); - AVERT(ScanState, ss); - AVERT(Seg, seg); - AVER(refIO != NULL); - - arena = PoolArena(pool); - AVERT(Arena, arena); - amc = Pool2AMC(pool); - AVERT(AMC, amc); - - ss->wasMarked = TRUE; - - if(ss->rank == RankAMBIG) - goto fixInPlace; - - ShieldExpose(arena, seg); - newRef = (*pool->format->isMoved)(*refIO); - ShieldCover(arena, seg); - if(newRef != (Addr)0) { - /* Object has been forwarded already, so snap-out pointer. */ - /* Useful weak pointer semantics not implemented. @@@@ */ - *refIO = newRef; - return ResOK; - } - -fixInPlace: /* see .Nailboard.emergency */ - amcFixInPlace(pool, seg, ss, refIO); - return ResOK; -} - - -/* AMCFix -- fix a reference to the pool - * - * See . - */ -Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) -{ - Arena arena; - AMC amc; - Res res; - Format format; /* cache of pool->format */ - Ref ref; /* reference to be fixed */ - Ref newRef; /* new location, if moved */ - Size length; /* length of object to be relocated */ - Buffer buffer; /* buffer to allocate new copy into */ - amcGen gen; /* generation of old copy of object */ - TraceSet grey; /* greyness of object being relocated */ - Seg toSeg; /* segment to which object is being relocated */ - - /* */ - AVERT_CRITICAL(Pool, pool); - AVERT_CRITICAL(ScanState, ss); - AVERT_CRITICAL(Seg, seg); - AVER_CRITICAL(refIO != NULL); - EVENT0(AMCFix); - - /* For the moment, assume that the object was already marked. */ - /* (See .) */ - ss->wasMarked = TRUE; - - /* If the reference is ambiguous, set up the datastructures for */ - /* managing a nailed segment. This involves marking the segment */ - /* as nailed, and setting up a per-word mark table */ - if(ss->rank == RankAMBIG) { - /* .nail.new: Check to see whether we need a Nailboard for */ - /* this seg. We use "SegNailed(seg) == TraceSetEMPTY" */ - /* rather than "!amcSegHasNailboard(seg)" because this avoids */ - /* setting up a new nailboard when the segment was nailed, but */ - /* had no nailboard. This must be avoided because otherwise */ - /* assumptions in AMCFixEmergency will be wrong (essentially */ - /* we will lose some pointer fixes because we introduced a */ - /* nailboard). */ - if(SegNailed(seg) == TraceSetEMPTY) { - res = amcSegCreateNailboard(seg, pool); - if(res != ResOK) - return res; - ++ss->nailCount; - SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); - } - amcFixInPlace(pool, seg, ss, refIO); - return ResOK; - } - - amc = Pool2AMC(pool); - AVERT_CRITICAL(AMC, amc); - format = pool->format; - ref = *refIO; - AVER_CRITICAL(SegBase(seg) <= ref); - AVER_CRITICAL(ref < SegLimit(seg)); - arena = pool->arena; - - /* .exposed.seg: Statements tagged ".exposed.seg" below require */ - /* that "seg" (that is: the 'from' seg) has been ShieldExposed. */ - ShieldExpose(arena, seg); - newRef = (*format->isMoved)(ref); /* .exposed.seg */ - - if(newRef == (Addr)0) { - /* If object is nailed already then we mustn't copy it: */ - if(SegNailed(seg) != TraceSetEMPTY - && (!amcSegHasNailboard(seg) || amcNailGetMark(seg, ref))) { - /* Segment only needs greying if there are new traces for */ - /* which we are nailing. */ - if(!TraceSetSub(ss->traces, SegNailed(seg))) { - SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); - SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); - } - res = ResOK; - goto returnRes; - } else if(ss->rank == RankWEAK) { - /* Object is not preserved (neither moved, nor nailed) */ - /* hence, reference should be splatted. */ - goto updateReference; - } - /* Object is not preserved yet (neither moved, nor nailed) */ - /* so should be preserved by forwarding. */ - EVENT1(AMCFixForward, newRef); - /* */ - ss->wasMarked = FALSE; - - /* Get the forwarding buffer from the object's generation. */ - gen = amcSegGen(seg); - buffer = gen->forward; - AVER_CRITICAL(buffer != NULL); - - length = AddrOffset(ref, (*format->skip)(ref)); /* .exposed.seg */ - STATISTIC_STAT(++ss->forwardedCount); - ss->forwardedSize += length; - do { - res = BUFFER_RESERVE(&newRef, buffer, length, FALSE); - if(res != ResOK) - goto returnRes; - - toSeg = BufferSeg(buffer); - ShieldExpose(arena, toSeg); - - /* Since we're moving an object from one segment to another, */ - /* union the greyness and the summaries together. */ - grey = TraceSetUnion(ss->traces, SegGrey(seg)); - SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey)); - SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg))); - - /* */ - (void)AddrCopy(newRef, ref, length); /* .exposed.seg */ - - ShieldCover(arena, toSeg); - } while(!BUFFER_COMMIT(buffer, newRef, length)); - ss->copiedSize += length; - - (*format->move)(ref, newRef); /* .exposed.seg */ - } else { - /* reference to broken heart (which should be snapped out -- */ - /* consider adding to (non-existant) snap-out cache here) */ - STATISTIC_STAT(++ss->snapCount); - } - - /* .fix.update: update the reference to whatever the above code */ - /* decided it should be */ -updateReference: - *refIO = newRef; - res = ResOK; - -returnRes: - ShieldCover(arena, seg); /* .exposed.seg */ - return res; -} - - -/* AMCHeaderFix -- fix a reference to the pool, with headers - * - * See . - */ -static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) -{ - Arena arena; - AMC amc; - Res res; - Format format; /* cache of pool->format */ - Ref ref; /* reference to be fixed */ - Ref newRef; /* new location, if moved */ - Addr newBase; /* base address of new copy */ - Size length; /* length of object to be relocated */ - Buffer buffer; /* buffer to allocate new copy into */ - amcGen gen; /* generation of old copy of object */ - TraceSet grey; /* greyness of object being relocated */ - Seg toSeg; /* segment to which object is being relocated */ - - /* */ - AVERT_CRITICAL(Pool, pool); - AVERT_CRITICAL(ScanState, ss); - AVERT_CRITICAL(Seg, seg); - AVER_CRITICAL(refIO != NULL); - EVENT0(AMCFix); - - /* For the moment, assume that the object was already marked. */ - /* (See .) */ - ss->wasMarked = TRUE; - - /* If the reference is ambiguous, set up the datastructures for */ - /* managing a nailed segment. This involves marking the segment */ - /* as nailed, and setting up a per-word mark table */ - if(ss->rank == RankAMBIG) { - /* .nail.new: Check to see whether we need a Nailboard for */ - /* this seg. We use "SegNailed(seg) == TraceSetEMPTY" */ - /* rather than "!amcSegHasNailboard(seg)" because this avoids */ - /* setting up a new nailboard when the segment was nailed, but */ - /* had no nailboard. This must be avoided because otherwise */ - /* assumptions in AMCFixEmergency will be wrong (essentially */ - /* we will lose some pointer fixes because we introduced a */ - /* nailboard). */ - if(SegNailed(seg) == TraceSetEMPTY) { - res = amcSegCreateNailboard(seg, pool); - if(res != ResOK) - return res; - ++ss->nailCount; - SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); - } - amcFixInPlace(pool, seg, ss, refIO); - return ResOK; - } - - amc = Pool2AMC(pool); - AVERT_CRITICAL(AMC, amc); - format = pool->format; - ref = *refIO; - AVER_CRITICAL(AddrAdd(SegBase(seg), pool->format->headerSize) - <= ref); - AVER_CRITICAL(ref < SegLimit(seg)); /* see .ref-limit */ - arena = pool->arena; - - /* .exposed.seg: Statements tagged ".exposed.seg" below require */ - /* that "seg" (that is: the 'from' seg) has been ShieldExposed. */ - ShieldExpose(arena, seg); - newRef = (*format->isMoved)(ref); /* .exposed.seg */ - - if(newRef == (Addr)0) { - /* If object is nailed already then we mustn't copy it: */ - if(SegNailed(seg) != TraceSetEMPTY - && (!amcSegHasNailboard(seg) || amcNailGetMark(seg, ref))) { - /* Segment only needs greying if there are new traces for */ - /* which we are nailing. */ - if(!TraceSetSub(ss->traces, SegNailed(seg))) { - SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); - SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces)); - } - res = ResOK; - goto returnRes; - } else if(ss->rank == RankWEAK) { - /* object is not preserved (neither moved, nor nailed) */ - /* hence, reference should be splatted */ - goto updateReference; - } - /* object is not preserved yet (neither moved, nor nailed) */ - /* so should be preserved by forwarding */ - EVENT1(AMCFixForward, newRef); - /* */ - ss->wasMarked = FALSE; - - /* Get the forwarding buffer from the object's generation. */ - gen = amcSegGen(seg); - buffer = gen->forward; - AVER_CRITICAL(buffer != NULL); - - length = AddrOffset(ref, (*format->skip)(ref)); /* .exposed.seg */ - STATISTIC_STAT(++ss->forwardedCount); - ss->forwardedSize += length; - do { - Size headerSize = format->headerSize; - - res = BUFFER_RESERVE(&newBase, buffer, length, FALSE); - if (res != ResOK) - goto returnRes; - newRef = AddrAdd(newBase, headerSize); - - toSeg = BufferSeg(buffer); - ShieldExpose(arena, toSeg); - - /* Since we're moving an object from one segment to another, */ - /* union the greyness and the summaries together. */ - grey = TraceSetUnion(ss->traces, SegGrey(seg)); - SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey)); - SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg))); - - /* */ - (void)AddrCopy(newBase, AddrSub(ref, headerSize), length); /* .exposed.seg */ - - ShieldCover(arena, toSeg); - } while (!BUFFER_COMMIT(buffer, newBase, length)); - ss->copiedSize += length; - - (*format->move)(ref, newRef); /* .exposed.seg */ - } else { - /* reference to broken heart (which should be snapped out -- */ - /* consider adding to (non-existent) snap-out cache here) */ - STATISTIC_STAT(++ss->snapCount); - } - - /* .fix.update: update the reference to whatever the above code */ - /* decided it should be */ -updateReference: - *refIO = newRef; - res = ResOK; - -returnRes: - ShieldCover(arena, seg); /* .exposed.seg */ - return res; -} - - -/* amcReclaimNailed -- reclaim what you can from a nailed segment */ - -static void amcReclaimNailed(Pool pool, Trace trace, Seg seg) -{ - Addr p, limit; - Arena arena; - Format format; - Size bytesReclaimed = (Size)0; - Count preservedInPlaceCount = (Count)0; - Size preservedInPlaceSize = (Size)0; - AMC amc; - Size headerSize; - Addr p1; /* first obj in seg */ - Bool obj1pip = FALSE; /* first obj was preserved in place */ - - /* All arguments AVERed by AMCReclaim */ - - amc = Pool2AMC(pool); - AVERT(AMC, amc); - format = pool->format; - - arena = PoolArena(pool); - AVERT(Arena, arena); - - /* see for improvements */ - headerSize = format->headerSize; - ShieldExpose(arena, seg); - p = AddrAdd(SegBase(seg), headerSize); - if(SegBuffer(seg) != NULL) { - limit = BufferScanLimit(SegBuffer(seg)); - } else { - limit = SegLimit(seg); - } - limit = AddrAdd(limit, headerSize); - p1 = p; - while(p < limit) { - Addr q; - Size length; - q = (*format->skip)(p); - length = AddrOffset(p, q); - if(amcSegHasNailboard(seg) - ? !amcNailGetMark(seg, p) - /* If there's no mark table, retain all that hasn't been */ - /* forwarded. In this case, preservedInPlace* become */ - /* somewhat overstated. */ - : (*format->isMoved)(p) != NULL) - { - /* Replace forwarding pointer / unreachable object with pad */ - (*format->pad)(AddrSub(p, headerSize), length); - bytesReclaimed += length; - } else { - ++preservedInPlaceCount; - preservedInPlaceSize += length; - if(p == p1) - obj1pip = TRUE; - } - - AVER(p < q); - p = q; - } - AVER(p == limit); - ShieldCover(arena, seg); - - SegSetNailed(seg, TraceSetDel(SegNailed(seg), trace)); - SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace)); - if(SegNailed(seg) == TraceSetEMPTY && amcSegHasNailboard(seg)) { - amcSegDestroyNailboard(seg, pool); - } - - AVER(bytesReclaimed <= SegSize(seg)); - trace->reclaimSize += bytesReclaimed; - trace->preservedInPlaceCount += preservedInPlaceCount; - trace->preservedInPlaceSize += preservedInPlaceSize; - - /* Free the seg if we can; fixes .nailboard.limitations.middle. */ - if(preservedInPlaceCount == 0 - && (SegBuffer(seg) == NULL) - && (SegNailed(seg) == TraceSetEMPTY)) { - - amcGen gen = amcSegGen(seg); - - /* We may not free a buffered seg. */ - AVER(SegBuffer(seg) == NULL); - - --gen->segs; - gen->pgen.totalSize -= SegSize(seg); - SegFree(seg); - } else { - /* Seg retained */ - STATISTIC_STAT( { - Count pages; - AVER(SizeIsAligned(SegSize(seg), ArenaAlign(pool->arena))); - pages = SegSize(seg) / ArenaAlign(pool->arena); - AVER(pages != 0); - amc->pageretstruct[trace->ti].pRet += pages; - if(pages == 1) { - amc->pageretstruct[trace->ti].pRS += pages; - } else if(pages < AMCLargeSegPAGES) { - amc->pageretstruct[trace->ti].sRM += 1; - amc->pageretstruct[trace->ti].pRM += pages; - if(obj1pip) { - amc->pageretstruct[trace->ti].pRM1 += pages; - } else { - /* Seg retained by a rest obj. Cost: one rest page, */ - /* plus pages-1 pages of pure padding. */ - amc->pageretstruct[trace->ti].pRMrr += 1; - amc->pageretstruct[trace->ti].pRMr1 += pages - 1; - } - } else { - amc->pageretstruct[trace->ti].sRL += 1; - amc->pageretstruct[trace->ti].pRL += pages; - if(!obj1pip) { - /* Seg retained by a rest obj */ - amc->pageretstruct[trace->ti].pRLr += pages; - } - } - } ); - - } -} - - -/* AMCReclaim -- recycle a segment if it is still white - * - * See . - */ -static void AMCReclaim(Pool pool, Trace trace, Seg seg) -{ - AMC amc; - amcGen gen; - Size size; - - AVERT_CRITICAL(Pool, pool); - amc = Pool2AMC(pool); - AVERT_CRITICAL(AMC, amc); - AVERT_CRITICAL(Trace, trace); - AVERT_CRITICAL(Seg, seg); - - gen = amcSegGen(seg); - AVERT_CRITICAL(amcGen, gen); - - EVENT3(AMCReclaim, gen, trace, seg); - - /* This switching needs to be more complex for multiple traces. */ - AVER_CRITICAL(TraceSetIsSingle(PoolArena(pool)->busyTraces)); - if(amc->rampMode == RampCOLLECTING) { - if(amc->rampCount > 0) { - /* Entered ramp mode before previous one was cleaned up */ - amc->rampMode = RampBEGIN; - } else { - amc->rampMode = RampOUTSIDE; - } - } - - if(SegNailed(seg) != TraceSetEMPTY) { - amcReclaimNailed(pool, trace, seg); - return; - } - - /* We may not free a buffered seg. (But all buffered + condemned */ - /* segs should have been nailed anyway). */ - AVER(SegBuffer(seg) == NULL); - - --gen->segs; - size = SegSize(seg); - gen->pgen.totalSize -= size; - - trace->reclaimSize += size; - - SegFree(seg); -} - - -/* AMCTraceEnd -- emit end-of-trace diagnostics - * - */ -static void AMCTraceEnd(Pool pool, Trace trace) -{ - AMC amc; - TraceId ti; - Count pRetMin = 100; - - AVERT(Pool, pool); - AVERT(Trace, trace); - - amc = Pool2AMC(pool); - AVERT(AMC, amc); - ti = trace->ti; - AVER(TraceIdCheck(ti)); - - if(amc->pageretstruct[ti].pRet >= pRetMin) { - DIAG_SINGLEF(( "AMCTraceEnd_pageret", - " $U", (WriteFU)ArenaEpoch(pool->arena), - " $U", (WriteFU)trace->why, - " $U", (WriteFU)amc->pageretstruct[ti].pCond, - " $U", (WriteFU)amc->pageretstruct[ti].pRet, ",", - " $U", (WriteFU)amc->pageretstruct[ti].pCS, - " $U", (WriteFU)amc->pageretstruct[ti].pRS, ",", - " $U", (WriteFU)amc->pageretstruct[ti].sCM, - " $U", (WriteFU)amc->pageretstruct[ti].pCM, - " $U", (WriteFU)amc->pageretstruct[ti].sRM, - " $U", (WriteFU)amc->pageretstruct[ti].pRM, - " $U", (WriteFU)amc->pageretstruct[ti].pRM1, - " $U", (WriteFU)amc->pageretstruct[ti].pRMrr, - " $U", (WriteFU)amc->pageretstruct[ti].pRMr1, ",", - " $U", (WriteFU)amc->pageretstruct[ti].sCL, - " $U", (WriteFU)amc->pageretstruct[ti].pCL, - " $U", (WriteFU)amc->pageretstruct[ti].sRL, - " $U", (WriteFU)amc->pageretstruct[ti].pRL, - " $U", (WriteFU)amc->pageretstruct[ti].pRLr, - " (page = $Ub,", (WriteFU)ArenaAlign(pool->arena), - " Large >= $Up,", (WriteFU)AMCLargeSegPAGES, - " pRetMin $U)", (WriteFU)pRetMin, - NULL )); - } - - STATISTIC(amc->pageretstruct[ti] = pageretstruct_Zero); -} - - -/* AMCWalk -- Apply function to (black) objects in segment */ - -static void AMCWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, - void *p, size_t s) -{ - Addr object, nextObject, limit; - AMC amc; - Format format; - - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(FUNCHECK(f)); - /* p and s are arbitrary closures so can't be checked */ - - /* Avoid applying the function to grey or white objects. */ - /* White objects might not be alive, and grey objects */ - /* may have pointers to old-space. */ - - /* NB, segments containing a mix of colours (i.e., nailed segs) */ - /* are not handled properly: No objects are walked. See */ - /* job001682. */ - if(SegWhite(seg) == TraceSetEMPTY && SegGrey(seg) == TraceSetEMPTY - && SegNailed(seg) == TraceSetEMPTY) - { - amc = Pool2AMC(pool); - AVERT(AMC, amc); - format = pool->format; - - /* If the segment is buffered, only walk as far as the end */ - /* of the initialized objects. cf. AMCScan */ - if(SegBuffer(seg) != NULL) - limit = BufferScanLimit(SegBuffer(seg)); - else - limit = SegLimit(seg); - limit = AddrAdd(limit, format->headerSize); - - object = AddrAdd(SegBase(seg), format->headerSize); - while(object < limit) { - /* Check not a broken heart. */ - AVER((*format->isMoved)(object) == NULL); - (*f)(object, pool->format, pool, p, s); - nextObject = (*pool->format->skip)(object); - AVER(nextObject > object); - object = nextObject; - } - AVER(object == limit); - } -} - - -/* amcWalkAll -- Apply a function to all (black) objects in a pool */ - -static void amcWalkAll(Pool pool, FormattedObjectsStepMethod f, - void *p, size_t s) -{ - Arena arena; - Ring ring, next, node; - - AVER(IsSubclassPoly(pool->class, AMCPoolClassGet())); - - arena = PoolArena(pool); - ring = PoolSegRing(pool); - node = RingNext(ring); - RING_FOR(node, ring, next) { - Seg seg = SegOfPoolRing(node); - - ShieldExpose(arena, seg); - AMCWalk(pool, seg, f, p, s); - ShieldCover(arena, seg); - } -} - - -/* AMCDescribe -- describe the contents of the AMC pool - * - * See . - */ -static Res AMCDescribe(Pool pool, mps_lib_FILE *stream) -{ - Res res; - AMC amc; - Ring node, nextNode; - char *rampmode; - - if(!TESTT(Pool, pool)) - return ResFAIL; - amc = Pool2AMC(pool); - if(!TESTT(AMC, amc)) - return ResFAIL; - if(stream == NULL) - return ResFAIL; - - res = WriteF(stream, - (amc->rankSet == RankSetEMPTY) ? "AMCZ" : "AMC", - " $P {\n", (WriteFP)amc, " pool $P ($U)\n", - (WriteFP)AMC2Pool(amc), (WriteFU)AMC2Pool(amc)->serial, - NULL); - if(res != ResOK) - return res; - - switch(amc->rampMode) { - -#define RAMP_DESCRIBE(e, s) \ - case e: \ - rampmode = s; \ - break; - - RAMP_RELATION(RAMP_DESCRIBE) -#undef RAMP_DESCRIBE - - default: - rampmode = "unknown ramp mode"; - break; - - } - res = WriteF(stream, - " ", rampmode, " ($U)\n", (WriteFU)amc->rampCount, - NULL); - if(res != ResOK) - return res; - - RING_FOR(node, &amc->genRing, nextNode) { - amcGen gen = RING_ELT(amcGen, amcRing, node); - res = amcGenDescribe(gen, stream); - if(res != ResOK) - return res; - } - - if(0) { - /* SegDescribes */ - RING_FOR(node, &AMC2Pool(amc)->segRing, nextNode) { - Seg seg = RING_ELT(Seg, poolRing, node); - res = AMCSegDescribe(seg, stream); - if(res != ResOK) - return res; - } - } - - res = WriteF(stream, "} AMC $P\n", (WriteFP)amc, NULL); - if(res != ResOK) - return res; - - return ResOK; -} - - -/* AMCPoolClass -- the class definition */ - -DEFINE_POOL_CLASS(AMCPoolClass, this) -{ - INHERIT_CLASS(this, AbstractCollectPoolClass); - PoolClassMixInFormat(this); - this->name = "AMC"; - this->size = sizeof(AMCStruct); - this->offset = offsetof(AMCStruct, poolStruct); - this->attr |= AttrMOVINGGC; - this->init = AMCInit; - this->finish = AMCFinish; - this->bufferFill = AMCBufferFill; - this->bufferEmpty = AMCBufferEmpty; - this->whiten = AMCWhiten; - this->scan = AMCScan; - this->fix = AMCFix; - this->fixEmergency = AMCFixEmergency; - this->reclaim = AMCReclaim; - this->traceEnd = AMCTraceEnd; - this->rampBegin = AMCRampBegin; - this->rampEnd = AMCRampEnd; - this->walk = AMCWalk; - this->bufferClass = amcBufClassGet; - this->describe = AMCDescribe; -} - - -/* AMCZPoolClass -- the class definition */ - -DEFINE_POOL_CLASS(AMCZPoolClass, this) -{ - INHERIT_CLASS(this, AMCPoolClass); - this->name = "AMCZ"; - this->attr &= ~(AttrSCAN | AttrINCR_RB); - this->init = AMCZInit; - this->grey = PoolNoGrey; - this->scan = PoolNoScan; -} - - -/* mps_class_amc -- return the pool class descriptor to the client */ - -mps_class_t mps_class_amc(void) -{ - return (mps_class_t)AMCPoolClassGet(); -} - -/* mps_class_amcz -- return the pool class descriptor to the client */ - -mps_class_t mps_class_amcz(void) -{ - return (mps_class_t)AMCZPoolClassGet(); -} - - -/* mps_amc_apply -- apply function to all objects in pool - * - * The iterator that is passed by the client is stored in a closure - * structure which is passed to a local iterator in order to ensure - * that any type conversion necessary between Addr and mps_addr_t - * happen. They are almost certainly the same on all platforms, but - * this is the correct way to do it. -*/ - -typedef struct mps_amc_apply_closure_s { - void (*f)(mps_addr_t object, void *p, size_t s); - void *p; - size_t s; -} mps_amc_apply_closure_s; - -static void mps_amc_apply_iter(Addr addr, Format format, Pool pool, - void *p, size_t s) -{ - mps_amc_apply_closure_s *closure = p; - /* Can't check addr */ - AVERT(Format, format); - AVERT(Pool, pool); - /* We could check that s is the sizeof *p, but it would be slow */ - UNUSED(format); - UNUSED(pool); - UNUSED(s); - (*closure->f)(addr, closure->p, closure->s); -} - -void mps_amc_apply(mps_pool_t mps_pool, - void (*f)(mps_addr_t object, void *p, size_t s), - void *p, size_t s) -{ - Pool pool = (Pool)mps_pool; - mps_amc_apply_closure_s closure_s; - Arena arena; - - AVER(TESTT(Pool, pool)); - arena = PoolArena(pool); - ArenaEnter(arena); - AVERT(Pool, pool); - - closure_s.f = f; - closure_s.p = p; - closure_s.s = s; - amcWalkAll(pool, mps_amc_apply_iter, &closure_s, sizeof(closure_s)); - - ArenaLeave(arena); -} - - -/* AMCCheck -- check consistency of the AMC pool - * - * See . - */ -static Bool AMCCheck(AMC amc) -{ - CHECKS(AMC, amc); - CHECKD(Pool, &amc->poolStruct); - CHECKL(IsSubclassPoly(amc->poolStruct.class, EnsureAMCPoolClass())); - CHECKL(RankSetCheck(amc->rankSet)); - CHECKL(RingCheck(&amc->genRing)); - CHECKL(BoolCheck(amc->gensBooted)); - if(amc->gensBooted) { - CHECKD(amcGen, amc->nursery); - CHECKL(amc->gen != NULL); - CHECKD(amcGen, amc->rampGen); - CHECKD(amcGen, amc->afterRampGen); - } - /* nothing to check for rampCount */ - CHECKL(amc->rampMode >= RampOUTSIDE); - CHECKL(amc->rampMode <= RampCOLLECTING); - /* pageretstruct[ti] is statistics only, currently unchecked */ - - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolams.c b/mps/code/poolams.c deleted file mode 100644 index 34e07fceccc..00000000000 --- a/mps/code/poolams.c +++ /dev/null @@ -1,1748 +0,0 @@ -/* poolams.c: AUTOMATIC MARK & SWEEP POOL CLASS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * - * .design: See . - * - * - * TRANSGRESSSIONS - * - * .no-check.local: We have decided to omit checks in local functions of - * structure arguments that are simply passed down through the caller - * (as opposed to being constructed by the caller). - */ - -#include "poolams.h" -#include "dbgpool.h" -#include "mpm.h" -#include - -SRCID(poolams, "$Id$"); - - -#define AMSSig ((Sig)0x519A3599) /* SIGnature AMS */ -#define AMSSegSig ((Sig)0x519A3559) /* SIGnature AMS SeG */ - - -/* AMSDebugStruct -- structure for a debug subclass */ - -typedef struct AMSDebugStruct { - AMSStruct amsStruct; /* AMS structure */ - PoolDebugMixinStruct debug; /* debug mixin */ -} AMSDebugStruct; - -typedef struct AMSDebugStruct *AMSDebug; - - -#define AMS2AMSDebug(ams) PARENT(AMSDebugStruct, amsStruct, ams) -#define AMSDebug2AMS(amsd) (&((amsd)->amsStruct)) - - - -/* AMSSegCheck -- check an AMS segment */ - -Bool AMSSegCheck(AMSSeg amsseg) -{ - Seg seg = AMSSeg2Seg(amsseg); - CHECKS(AMSSeg, amsseg); - CHECKL(GCSegCheck(&amsseg->gcSegStruct)); - CHECKU(AMS, amsseg->ams); - CHECKL(AMS2Pool(amsseg->ams) == SegPool(seg)); - CHECKD_NOSIG(Ring, &amsseg->segRing); - - CHECKL(amsseg->grains == AMSGrains(amsseg->ams, SegSize(seg))); - CHECKL(amsseg->grains > 0); - CHECKL(amsseg->grains >= amsseg->free + amsseg->newAlloc); - - CHECKL(BoolCheck(amsseg->allocTableInUse)); - if (!amsseg->allocTableInUse) - CHECKL(amsseg->firstFree <= amsseg->grains); - CHECKL(amsseg->allocTable != NULL); - - if (SegWhite(seg) != TraceSetEMPTY) { - /* */ - CHECKL(TraceSetIsSingle(SegWhite(seg))); - CHECKL(amsseg->colourTablesInUse); - } - - CHECKL(BoolCheck(amsseg->marksChanged)); - CHECKL(BoolCheck(amsseg->ambiguousFixes)); - CHECKL(BoolCheck(amsseg->colourTablesInUse)); - CHECKL(amsseg->nongreyTable != NULL); - CHECKL(amsseg->nonwhiteTable != NULL); - - return TRUE; -} - - -/* AMSSegFreeWalk -- walk the free space in a segment */ - -void AMSSegFreeWalk(AMSSeg amsseg, FreeBlockStepMethod f, void *p) -{ - Pool pool; - Seg seg; - - AVERT(AMSSeg, amsseg); - pool = SegPool(AMSSeg2Seg(amsseg)); - seg = AMSSeg2Seg(amsseg); - - if (amsseg->free == 0) - return; - if (amsseg->allocTableInUse) { - Index base, limit, next; - - next = 0; - while (next < amsseg->grains) { - Bool found = BTFindLongResRange(&base, &limit, amsseg->allocTable, - next, amsseg->grains, 1); - if (!found) break; - (*f)(AMS_INDEX_ADDR(seg, base), AMS_INDEX_ADDR(seg, limit), pool, p); - next = limit + 1; - } - } else { - if ( amsseg->firstFree < amsseg->grains ) - (*f)(AMS_INDEX_ADDR(seg, amsseg->firstFree), SegLimit(seg), pool, p); - } -} - - -/* AMSSegFreeCheck -- check the free space in a segment */ - -static void amsFreeBlockCheckStep(Addr base, Addr limit, Pool pool, void *p) -{ - UNUSED(p); - DebugPoolFreeCheck(pool, base, limit); -} - -void AMSSegFreeCheck(AMSSeg amsseg) -{ - Pool pool; - PoolDebugMixin debug; - - AVERT(AMSSeg, amsseg); - - if (amsseg->free == 0) - return; - - /* If it's not a debug class, don't bother walking. */ - pool = SegPool(AMSSeg2Seg(amsseg)); - AVERT(Pool, pool); - debug = ((pool)->class->debugMixin)(pool); - if (debug == NULL) - return; - - AMSSegFreeWalk(amsseg, amsFreeBlockCheckStep, NULL); -} - - -/* amsCreateTables -- create the tables for an AMS seg */ - -static Res amsCreateTables(AMS ams, BT *allocReturn, - BT *nongreyReturn, BT *nonwhiteReturn, - Arena arena, Count length) -{ - Res res; - BT allocTable, nongreyTable, nonwhiteTable; - - AVER(allocReturn != NULL); - AVER(nongreyReturn != NULL); - AVER(nonwhiteReturn != NULL); - AVERT(Arena, arena); - AVER(length > 0); - - res = BTCreate(&allocTable, arena, length); - if (res != ResOK) - goto failAlloc; - res = BTCreate(&nongreyTable, arena, length); - if (res != ResOK) - goto failGrey; - if (ams->shareAllocTable) - nonwhiteTable = allocTable; - else { - res = BTCreate(&nonwhiteTable, arena, length); - if (res != ResOK) - goto failWhite; - } - - *allocReturn = allocTable; - *nongreyReturn = nongreyTable; - *nonwhiteReturn = nonwhiteTable; - return ResOK; - -failWhite: - BTDestroy(nongreyTable, arena, length); -failGrey: - BTDestroy(allocTable, arena, length); -failAlloc: - return res; -} - - -/* amsDestroyTables -- destroy the tables for an AMS seg */ - -static void amsDestroyTables(AMS ams, BT allocTable, - BT nongreyTable, BT nonwhiteTable, - Arena arena, Count length) -{ - AVER(allocTable != NULL); - AVER(nongreyTable != NULL); - AVER(nonwhiteTable != NULL); - AVERT(Arena, arena); - AVER(length > 0); - - if (!ams->shareAllocTable) - BTDestroy(nonwhiteTable, arena, length); - BTDestroy(nongreyTable, arena, length); - BTDestroy(allocTable, arena, length); -} - - -/* AMSSegInit -- Init method for AMS segments */ - -static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - SegClass super; - AMSSeg amsseg; - Res res; - Arena arena; - AMS ams; - - AVERT(Seg, seg); - amsseg = Seg2AMSSeg(seg); - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - arena = PoolArena(pool); - /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(AMSSegClass); - res = super->init(seg, pool, base, size, reservoirPermit, args); - if (res != ResOK) - goto failNextMethod; - - amsseg->grains = size >> ams->grainShift; - amsseg->free = amsseg->grains; - amsseg->newAlloc = (Count)0; - amsseg->marksChanged = FALSE; /* */ - amsseg->ambiguousFixes = FALSE; - - res = amsCreateTables(ams, &amsseg->allocTable, - &amsseg->nongreyTable, &amsseg->nonwhiteTable, - arena, amsseg->grains); - if (res != ResOK) - goto failCreateTables; - - /* start off using firstFree, see */ - amsseg->allocTableInUse = FALSE; - amsseg->firstFree = 0; - amsseg->colourTablesInUse = FALSE; - - amsseg->ams = ams; - RingInit(&amsseg->segRing); - RingAppend((ams->allocRing)(ams, SegRankSet(seg), size), - &amsseg->segRing); - - amsseg->sig = AMSSegSig; - ams->size += size; - AVERT(AMSSeg, amsseg); - - return ResOK; - -failCreateTables: - super->finish(seg); -failNextMethod: - return res; -} - - -/* AMSSegFinish -- Finish method for AMS segments */ - -static void AMSSegFinish(Seg seg) -{ - SegClass super; - AMSSeg amsseg; - AMS ams; - Arena arena; - - AVERT(Seg, seg); - amsseg = Seg2AMSSeg(seg); - AVERT(AMSSeg, amsseg); - ams = amsseg->ams; - AVERT(AMS, ams); - arena = PoolArena(AMS2Pool(ams)); - AVER(SegBuffer(seg) == NULL); - - /* keep the destructions in step with AMSSegInit failure cases */ - amsDestroyTables(ams, amsseg->allocTable, amsseg->nongreyTable, - amsseg->nonwhiteTable, arena, amsseg->grains); - - RingRemove(&amsseg->segRing); - RingFinish(&amsseg->segRing); - - AVER(ams->size >= SegSize(seg)); - ams->size -= SegSize(seg); - amsseg->sig = SigInvalid; - - /* finish the superclass fields last */ - super = SEG_SUPERCLASS(AMSSegClass); - super->finish(seg); -} - - -/* AMSSegMerge & AMSSegSplit -- AMSSeg split & merge methods - * - * .empty: segment merging and splitting is limited to simple cases - * where the high segment is empty. - * See . - * - * .grain-align: segment merging and splitting is limited to cases - * where the join is aligned with the grain alignment - * See . - * - * .alloc-early: Allocations are performed before calling the - * next method to simplify the fail cases. See - * - * - * .table-names: The names of local variables holding the new - * allocation and colour tables are chosen to have names which - * are derivable from the field names for tables in AMSSegStruct. - * (I.e. allocTable, nongreyTable, nonwhiteTable). This simplifies - * processing of all such tables by a macro. - */ - -static Res AMSSegMerge(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - SegClass super; - Count loGrains, hiGrains, allGrains; - AMSSeg amsseg, amssegHi; - Arena arena; - AMS ams; - BT allocTable, nongreyTable, nonwhiteTable; /* .table-names */ - Res res; - - AVERT(Seg, seg); - AVERT(Seg, segHi); - amsseg = Seg2AMSSeg(seg); - amssegHi = Seg2AMSSeg(segHi); - AVERT(AMSSeg, amsseg); - AVERT(AMSSeg, amssegHi); - /* other parameters are checked by next-method */ - arena = PoolArena(SegPool(seg)); - ams = Pool2AMS(SegPool(seg)); - - loGrains = amsseg->grains; - hiGrains = amssegHi->grains; - allGrains = loGrains + hiGrains; - - /* checks for .grain-align */ - AVER(allGrains == AddrOffset(base, limit) >> ams->grainShift); - /* checks for .empty */ - AVER(amssegHi->free == hiGrains); - AVER(!amssegHi->marksChanged); - - /* .alloc-early */ - res = amsCreateTables(ams, &allocTable, &nongreyTable, &nonwhiteTable, - arena, allGrains); - if (res != ResOK) - goto failCreateTables; - - /* Merge the superclass fields via next-method call */ - super = SEG_SUPERCLASS(AMSSegClass); - res = super->merge(seg, segHi, base, mid, limit, - withReservoirPermit, args); - if (res != ResOK) - goto failSuper; - - /* Update fields of seg. Finish segHi. */ - -#define MERGE_TABLES(table, setHighRangeFn) \ - /* Implementation depends on .table-names */ \ - BEGIN \ - BTCopyRange(amsseg->table, (table), 0, loGrains); \ - setHighRangeFn((table), loGrains, allGrains); \ - BTDestroy(amsseg->table, arena, loGrains); \ - BTDestroy(amssegHi->table, arena, hiGrains); \ - amsseg->table = (table); \ - END - - MERGE_TABLES(allocTable, BTResRange); - MERGE_TABLES(nongreyTable, BTSetRange); - if (!ams->shareAllocTable) - MERGE_TABLES(nonwhiteTable, BTSetRange); - - amsseg->grains = allGrains; - amsseg->free = amsseg->free + amssegHi->free; - amsseg->newAlloc = amsseg->newAlloc + amssegHi->newAlloc; - /* other fields in amsseg are unaffected */ - - RingRemove(&amssegHi->segRing); - RingFinish(&amssegHi->segRing); - amssegHi->sig = SigInvalid; - - AVERT(AMSSeg, amsseg); - return ResOK; - -failSuper: - amsDestroyTables(ams, allocTable, nongreyTable, nonwhiteTable, - arena, allGrains); -failCreateTables: - AVERT(AMSSeg, amsseg); - AVERT(AMSSeg, amssegHi); - return res; -} - - -static Res AMSSegSplit(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - SegClass super; - Count loGrains, hiGrains, allGrains; - AMSSeg amsseg, amssegHi; - Arena arena; - AMS ams; - BT allocTableLo, nongreyTableLo, nonwhiteTableLo; /* .table-names */ - BT allocTableHi, nongreyTableHi, nonwhiteTableHi; /* .table-names */ - Res res; - - AVERT(Seg, seg); - AVER(segHi != NULL); /* can't check fully, it's not initialized */ - amsseg = Seg2AMSSeg(seg); - amssegHi = Seg2AMSSeg(segHi); - AVERT(AMSSeg, amsseg); - /* other parameters are checked by next-method */ - arena = PoolArena(SegPool(seg)); - ams = Pool2AMS(SegPool(seg)); - - loGrains = AMSGrains(ams, AddrOffset(base, mid)); - hiGrains = AMSGrains(ams, AddrOffset(mid, limit)); - allGrains = loGrains + hiGrains; - - /* checks for .grain-align */ - AVER(allGrains == amsseg->grains); - /* checks for .empty */ - AVER(amsseg->free >= hiGrains); - if (amsseg->allocTableInUse) { - AVER(BTIsResRange(amsseg->allocTable, loGrains, allGrains)); - } else { - AVER(amsseg->firstFree <= loGrains); - } - - /* .alloc-early */ - res = amsCreateTables(ams, &allocTableLo, &nongreyTableLo, &nonwhiteTableLo, - arena, loGrains); - if (res != ResOK) - goto failCreateTablesLo; - res = amsCreateTables(ams, &allocTableHi, &nongreyTableHi, &nonwhiteTableHi, - arena, hiGrains); - if (res != ResOK) - goto failCreateTablesHi; - - - /* Split the superclass fields via next-method call */ - super = SEG_SUPERCLASS(AMSSegClass); - res = super->split(seg, segHi, base, mid, limit, withReservoirPermit, args); - if (res != ResOK) - goto failSuper; - - /* Update seg. Full initialization for segHi. */ - -#define SPLIT_TABLES(table, setHighRangeFn) \ - /* Implementation depends on .table-names */ \ - BEGIN \ - BTCopyRange(amsseg->table, table ## Lo, 0, loGrains); \ - setHighRangeFn(table ## Hi, 0, hiGrains); \ - BTDestroy(amsseg->table, arena, allGrains); \ - amsseg->table = table ## Lo; \ - amssegHi->table = table ## Hi; \ - END - - SPLIT_TABLES(nonwhiteTable, BTSetRange); - SPLIT_TABLES(nongreyTable, BTSetRange); - SPLIT_TABLES(allocTable, BTResRange); - - amsseg->grains = loGrains; - amssegHi->grains = hiGrains; - amsseg->free -= hiGrains; - amssegHi->free = hiGrains; - amssegHi->newAlloc = (Count)0; - amssegHi->marksChanged = FALSE; /* */ - amssegHi->ambiguousFixes = FALSE; - - /* start off using firstFree, see */ - amssegHi->allocTableInUse = FALSE; - amssegHi->firstFree = 0; - /* use colour tables if the segment is white */ - amssegHi->colourTablesInUse = (SegWhite(segHi) != TraceSetEMPTY); - - amssegHi->ams = ams; - RingInit(&amssegHi->segRing); - RingAppend((ams->allocRing)(ams, SegRankSet(segHi), SegSize(segHi)), - &amssegHi->segRing); - - amssegHi->sig = AMSSegSig; - AVERT(AMSSeg, amsseg); - AVERT(AMSSeg, amssegHi); - return ResOK; - -failSuper: - amsDestroyTables(ams, allocTableHi, nongreyTableHi, nonwhiteTableHi, - arena, hiGrains); -failCreateTablesHi: - amsDestroyTables(ams, allocTableLo, nongreyTableLo, nonwhiteTableLo, - arena, loGrains); -failCreateTablesLo: - AVERT(AMSSeg, amsseg); - return res; -} - - -/* AMSSegDescribe -- describe an AMS segment */ - -#define WRITE_BUFFER_LIMIT(stream, seg, i, buffer, accessor, char) \ - BEGIN \ - if ((buffer) != NULL \ - && (i) == AMS_ADDR_INDEX(seg, accessor(buffer))) { \ - Res _res = WriteF(stream, char, NULL); \ - if (_res != ResOK) return _res; \ - } \ - END - -static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream) -{ - Res res; - AMSSeg amsseg; - SegClass super; - Buffer buffer; /* the segment's buffer, if it has one */ - Index i; - - if (!TESTT(Seg, seg)) return ResFAIL; - if (stream == NULL) return ResFAIL; - amsseg = Seg2AMSSeg(seg); - if (!TESTT(AMSSeg, amsseg)) return ResFAIL; - - /* Describe the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(AMSSegClass); - res = super->describe(seg, stream); - if (res != ResOK) return res; - - buffer = SegBuffer(seg); - - res = WriteF(stream, - " AMS $P\n", (WriteFP)amsseg->ams, - " grains $W\n", (WriteFW)amsseg->grains, - NULL); - if (res != ResOK) return res; - if (amsseg->allocTableInUse) - res = WriteF(stream, - " alloctable $P\n", (WriteFP)amsseg->allocTable, - NULL); - else - res = WriteF(stream, - " firstFree $W\n", (WriteFW)amsseg->firstFree, - NULL); - if (res != ResOK) return res; - res = WriteF(stream, - " tables: nongrey $P, nonwhite $P\n", - (WriteFP)amsseg->nongreyTable, - (WriteFP)amsseg->nonwhiteTable, - " map: \n", - NULL); - if (res != ResOK) return res; - - for (i=0; i < amsseg->grains; ++i) { - char c = 0; - - if (i % 64 == 0) { - res = WriteF(stream, "\n ", NULL); - if (res != ResOK) return res; - } - - WRITE_BUFFER_LIMIT(stream, seg, i, buffer, BufferBase, "["); - WRITE_BUFFER_LIMIT(stream, seg, i, buffer, BufferGetInit, "|"); - WRITE_BUFFER_LIMIT(stream, seg, i, buffer, BufferAlloc, ">"); - - if (AMS_ALLOCED(seg, i)) { - if (amsseg->colourTablesInUse) { - if (AMS_IS_INVALID_COLOUR(seg, i)) - c = '!'; - else if (AMS_IS_WHITE(seg, i)) - c = '-'; - else if (AMS_IS_GREY(seg, i)) - c = '+'; - else /* must be black */ - c = '*'; - } else - c = '.'; - } else - c = ' '; - res = WriteF(stream, "$C", c, NULL); - if (res != ResOK) - return res; - - WRITE_BUFFER_LIMIT(stream, seg, i+1, buffer, BufferScanLimit, "<"); - WRITE_BUFFER_LIMIT(stream, seg, i+1, buffer, BufferLimit, "]"); - } - - res = WriteF(stream, "\n", NULL); - return res; -} - - -/* AMSSegClass -- Class definition for AMS segments */ - -DEFINE_CLASS(AMSSegClass, class) -{ - INHERIT_CLASS(class, GCSegClass); - class->name = "AMSSEG"; - class->size = sizeof(AMSSegStruct); - class->init = AMSSegInit; - class->finish = AMSSegFinish; - class->merge = AMSSegMerge; - class->split = AMSSegSplit; - class->describe = AMSSegDescribe; -} - - - - -/* AMSPoolRing -- the ring of segments in the pool */ - -static Ring AMSPoolRing(AMS ams, RankSet rankSet, Size size) -{ - /* arguments checked in the caller */ - UNUSED(rankSet); UNUSED(size); - return &ams->segRing; -} - - -/* AMSSegSizePolicy - * - * Picks a segment size. This policy simply rounds the size - * up to the arena alignment. - */ -static Res AMSSegSizePolicy(Size *sizeReturn, - Pool pool, Size size, RankSet rankSet) -{ - Arena arena; - - AVER(sizeReturn != NULL); - AVERT(Pool, pool); - AVER(size > 0); - AVER(RankSetCheck(rankSet)); - - arena = PoolArena(pool); - - size = SizeAlignUp(size, ArenaAlign(arena)); - if (size == 0) { - /* overflow */ - return ResMEMORY; - } - *sizeReturn = size; - return ResOK; -} - - -/* AMSSegCreate -- create a single AMSSeg */ - -static Res AMSSegCreate(Seg *segReturn, Pool pool, Size size, - SegPref segPref, RankSet rankSet, - Bool withReservoirPermit) -{ - Seg seg; - AMS ams; - Res res; - Arena arena; - Size prefSize; - - AVER(segReturn != NULL); - AVERT(Pool, pool); - AVER(size > 0); - AVERT(RankSet, rankSet); - AVERT(SegPref, segPref); - AVER(BoolCheck(withReservoirPermit)); - - ams = Pool2AMS(pool); - AVERT(AMS,ams); - arena = PoolArena(pool); - - res = ams->segSize(&prefSize, pool, size, rankSet); - if (res != ResOK) - goto failSize; - - res = SegAlloc(&seg, (*ams->segClass)(), segPref, prefSize, - pool, withReservoirPermit); - if (res != ResOK) { /* try to allocate one that's just large enough */ - Size minSize = SizeAlignUp(size, ArenaAlign(arena)); - - if (minSize == prefSize) - goto failSeg; - res = SegAlloc(&seg, (*ams->segClass)(), segPref, minSize, - pool, withReservoirPermit); - if (res != ResOK) - goto failSeg; - } - - PoolGenUpdateZones(&ams->pgen, seg); - - /* see */ - if (rankSet != RankSetEMPTY) { - SegSetRankAndSummary(seg, rankSet, RefSetUNIV); - } else { - SegSetRankAndSummary(seg, rankSet, RefSetEMPTY); - } - DebugPoolFreeSplat(pool, SegBase(seg), SegLimit(seg)); - - AVERT(AMSSeg, Seg2AMSSeg(seg)); - - *segReturn = seg; - return ResOK; - -failSeg: -failSize: - return res; -} - - -/* AMSSegsDestroy -- destroy all the segments */ - -static void AMSSegsDestroy(AMS ams) -{ - Ring ring, node, next; /* for iterating over the segments */ - - ring = PoolSegRing(AMS2Pool(ams)); - RING_FOR(node, ring, next) { - Seg seg = SegOfPoolRing(node); - AVER(Seg2AMSSeg(seg)->ams == ams); - AMSSegFreeCheck(Seg2AMSSeg(seg)); - SegFree(seg); - } -} - - -/* AMSInit -- the pool class initialization method - * - * Takes one additional argument: the format of the objects - * allocated in the pool. See . - */ -static Res AMSInit(Pool pool, va_list args) -{ - Res res; - Format format; - Chain chain; - Bool supportAmbiguous; - - AVERT(Pool, pool); - - format = va_arg(args, Format); - chain = va_arg(args, Chain); - supportAmbiguous = va_arg(args, Bool); - /* .ambiguous.noshare: If the pool is required to support ambiguous */ - /* references, the alloc and white tables cannot be shared. */ - res = AMSInitInternal(Pool2AMS(pool), format, chain, !supportAmbiguous); - if (res == ResOK) { - EVENT3(PoolInitAMS, pool, PoolArena(pool), format); - } - return res; -} - - -/* AMSInitInternal -- initialize an AMS pool, given the format and the chain */ - -Res AMSInitInternal(AMS ams, Format format, Chain chain, Bool shareAllocTable) -{ - Pool pool; - Res res; - - /* Can't check ams, it's not initialized. */ - AVERT(Format, format); - AVERT(Chain, chain); - - pool = AMS2Pool(ams); - AVERT(Pool, pool); - pool->format = format; - pool->alignment = pool->format->alignment; - ams->grainShift = SizeLog2(PoolAlignment(pool)); - - if (ChainGens(chain) != 1) - return ResPARAM; - ams->chain = chain; - res = PoolGenInit(&ams->pgen, ams->chain, 0, pool); - if (res != ResOK) - return res; - - ams->shareAllocTable = shareAllocTable; - - RingInit(&ams->segRing); - - /* The next four might be overridden by a subclass. */ - ams->segSize = AMSSegSizePolicy; - ams->allocRing = AMSPoolRing; - ams->segsDestroy = AMSSegsDestroy; - ams->segClass = AMSSegClassGet; - - ams->size = 0; - - ams->sig = AMSSig; - AVERT(AMS, ams); - return ResOK; -} - - -/* AMSFinish -- the pool class finishing method - * - * Destroys all the segs in the pool. Can't invalidate the AMS until - * we've destroyed all the segments, as it may be checked. - */ -void AMSFinish(Pool pool) -{ - AMS ams; - - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - - (ams->segsDestroy)(ams); - /* can't invalidate the AMS until we've destroyed all the segs */ - ams->sig = SigInvalid; - RingFinish(&ams->segRing); - PoolGenFinish(&ams->pgen); -} - - -/* amsSegAlloc -- try to allocate an area in the given segment - * - * Tries to find an area of at least the given size. If successful, - * returns its base and limit grain indices. - */ -static Bool amsSegAlloc(Index *baseReturn, Index *limitReturn, - Seg seg, Size size) -{ - AMS ams; - AMSSeg amsseg; - Size grains; - Bool canAlloc; /* can we allocate in this segment? */ - Index base, limit; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - /* seg has already been checked, in AMSBufferFill. */ - amsseg = Seg2AMSSeg(seg); - - ams = amsseg->ams; - AVERT(AMS, ams); - - AVER(size > 0); - AVER(SizeIsAligned(size, PoolAlignment(AMS2Pool(ams)))); - - grains = AMSGrains(ams, size); - AVER(grains > 0); - if (grains > amsseg->grains) - return FALSE; - - if (amsseg->allocTableInUse) { - canAlloc = BTFindLongResRange(&base, &limit, amsseg->allocTable, - 0, amsseg->grains, grains); - if (!canAlloc) - return FALSE; - BTSetRange(amsseg->allocTable, base, limit); - } else { - if (amsseg->firstFree > amsseg->grains - grains) - return FALSE; - base = amsseg->firstFree; limit = amsseg->grains; - amsseg->firstFree = limit; - } - - /* We don't place buffers on white segments, so no need to adjust colour. */ - AVER(!amsseg->colourTablesInUse); - - amsseg->free -= limit - base; - amsseg->newAlloc += limit - base; - *baseReturn = base; - *limitReturn = limit; - return TRUE; -} - - -/* AMSBufferFill -- the pool class buffer fill method - * - * Iterates over the segments looking for space. See - * . - */ -static Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - Res res; - AMS ams; - Seg seg; - Ring node, ring, nextNode; /* for iterating over the segments */ - Index base = 0, limit = 0; /* suppress "may be used uninitialized" */ - Addr baseAddr, limitAddr; - RankSet rankSet; - Bool b; /* the return value of amsSegAlloc */ - SegPrefStruct segPrefStruct; - Size allocatedSize; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(SizeIsAligned(size, PoolAlignment(pool))); - AVER(BoolCheck(withReservoirPermit)); - - /* Check that we're not in the grey mutator phase (see */ - /* ). */ - AVER(PoolArena(pool)->busyTraces == PoolArena(pool)->flippedTraces); - - rankSet = BufferRankSet(buffer); - ring = (ams->allocRing)(ams, rankSet, size); - /* */ - RING_FOR(node, ring, nextNode) { - AMSSeg amsseg = RING_ELT(AMSSeg, segRing, node); - AVERT_CRITICAL(AMSSeg, amsseg); - if (amsseg->free >= AMSGrains(ams, size)) { - seg = AMSSeg2Seg(amsseg); - - if (SegRankSet(seg) == rankSet && SegBuffer(seg) == NULL - /* Can't use a white or grey segment, see d.m.p.fill.colour. */ - && SegWhite(seg) == TraceSetEMPTY && SegGrey(seg) == TraceSetEMPTY) { - b = amsSegAlloc(&base, &limit, seg, size); - if (b) - goto found; - } - } - } - - /* No suitable segment found; make a new one. */ - segPrefStruct = *SegPrefDefault(); - SegPrefExpress(&segPrefStruct, SegPrefCollected, NULL); - res = AMSSegCreate(&seg, pool, size, &segPrefStruct, rankSet, - withReservoirPermit); - if (res != ResOK) - return res; - b = amsSegAlloc(&base, &limit, seg, size); - -found: - AVER(b); - baseAddr = AMS_INDEX_ADDR(seg, base); limitAddr = AMS_INDEX_ADDR(seg, limit); - DebugPoolFreeCheck(pool, baseAddr, limitAddr); - allocatedSize = AddrOffset(baseAddr, limitAddr); - ams->pgen.totalSize += allocatedSize; - ams->pgen.newSize += allocatedSize; - - *baseReturn = baseAddr; *limitReturn = limitAddr; - return ResOK; -} - - -/* AMSBufferEmpty -- the pool class buffer empty method - * - * Frees the unused part of the buffer. The colour of the area doesn't - * need to be changed. See . - */ -static void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) -{ - AMS ams; - Index initIndex, limitIndex; - Seg seg; - AMSSeg amsseg; - Size size; - - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - AVERT(Buffer,buffer); - AVER(BufferIsReady(buffer)); - seg = BufferSeg(buffer); - AVER(SegCheck(seg)); - AVER(init <= limit); - AVER(AddrIsAligned(init, PoolAlignment(pool))); - AVER(AddrIsAligned(limit, PoolAlignment(pool))); - - amsseg = Seg2AMSSeg(seg); - AVERT(AMSSeg, amsseg); - - if (init == limit) - return; - - /* Tripped allocations might have scribbled on it, need to splat again. */ - DebugPoolFreeSplat(pool, init, limit); - - initIndex = AMS_ADDR_INDEX(seg, init); - limitIndex = AMS_ADDR_INDEX(seg, limit); - - if (amsseg->allocTableInUse) { - /* check that it's allocated */ - AVER(BTIsSetRange(amsseg->allocTable, initIndex, limitIndex)); - BTResRange(amsseg->allocTable, initIndex, limitIndex); - } else { - /* check that it's allocated */ - AVER(limitIndex <= amsseg->firstFree); - if (limitIndex == amsseg->firstFree) /* is it at the end? */ { - amsseg->firstFree = initIndex; - } else { /* start using allocTable */ - amsseg->allocTableInUse = TRUE; - BTSetRange(amsseg->allocTable, 0, amsseg->firstFree); - if (amsseg->firstFree < amsseg->grains) - BTResRange(amsseg->allocTable, amsseg->firstFree, amsseg->grains); - BTResRange(amsseg->allocTable, initIndex, limitIndex); - } - } - - if (amsseg->colourTablesInUse) - AMS_RANGE_WHITEN(seg, initIndex, limitIndex); - - amsseg->free += limitIndex - initIndex; - /* The unused portion of the buffer must be new, since it's not condemned. */ - AVER(amsseg->newAlloc >= limitIndex - initIndex); - amsseg->newAlloc -= limitIndex - initIndex; - size = AddrOffset(init, limit); - ams->pgen.totalSize -= size; - ams->pgen.newSize -= size; -} - - -/* amsRangeCondemn -- Condemn a part of an AMS segment - * Allow calling it with base = limit, to simplify the callers. - */ -static void amsRangeCondemn(Seg seg, Index base, Index limit) -{ - if (base != limit) { - AMSSeg amsseg = Seg2AMSSeg(seg); - - AVER(base < limit); - AVER(limit <= amsseg->grains); - - AMS_RANGE_WHITEN(seg, base, limit); - } -} - - -/* AMSCondemn -- the pool class segment condemning method */ - -static Res AMSCondemn(Pool pool, Trace trace, Seg seg) -{ - AMS ams; - AMSSeg amsseg; - Buffer buffer; /* the seg's buffer, if it has one */ - Count uncondemned; - - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - - AVERT(Trace, trace); - AVER(SegCheck(seg)); - - amsseg = Seg2AMSSeg(seg); - AVERT(AMSSeg, amsseg); - - /* */ - AVER(SegWhite(seg) == TraceSetEMPTY); - AVER(!amsseg->colourTablesInUse); - - amsseg->colourTablesInUse = TRUE; - - /* Init allocTable, if necessary. */ - if (!amsseg->allocTableInUse) { - if (0 < amsseg->firstFree) - BTSetRange(amsseg->allocTable, 0, amsseg->firstFree); - if (amsseg->firstFree < amsseg->grains) - BTResRange(amsseg->allocTable, amsseg->firstFree, amsseg->grains); - } - - /* Start using allocTable as the white table, if so configured. */ - if (ams->shareAllocTable) { - if (amsseg->allocTableInUse) { - /* During the collection, it can't use allocTable for AMS_ALLOCED, so */ - /* make it use firstFree. */ - amsseg->allocTableInUse = FALSE; - /* Could find a better value for firstFree, but probably not worth it. */ - amsseg->firstFree = amsseg->grains; - } - } else { /* Otherwise, use it as alloc table. */ - amsseg->allocTableInUse = TRUE; - } - - buffer = SegBuffer(seg); - if (buffer != NULL) { /* */ - Index scanLimitIndex, limitIndex; - scanLimitIndex = AMS_ADDR_INDEX(seg, BufferScanLimit(buffer)); - limitIndex = AMS_ADDR_INDEX(seg, BufferLimit(buffer)); - - amsRangeCondemn(seg, 0, scanLimitIndex); - if (scanLimitIndex < limitIndex) - AMS_RANGE_BLACKEN(seg, scanLimitIndex, limitIndex); - amsRangeCondemn(seg, limitIndex, amsseg->grains); - /* We didn't condemn the buffer, subtract it from the count. */ - uncondemned = limitIndex - scanLimitIndex; - } else { /* condemn whole seg */ - amsRangeCondemn(seg, 0, amsseg->grains); - uncondemned = (Count)0; - } - - trace->condemned += SegSize(seg) - AMSGrainsSize(ams, uncondemned); - /* The unused part of the buffer is new allocation by definition. */ - ams->pgen.newSize -= AMSGrainsSize(ams, amsseg->newAlloc - uncondemned); - amsseg->newAlloc = uncondemned; - amsseg->marksChanged = FALSE; /* */ - amsseg->ambiguousFixes = FALSE; - - SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace)); - - return ResOK; -} - - -/* AMSObjectFunction is the type of the method that an */ -/* amsIterate applies to each object in a segment. */ -typedef Res (*AMSObjectFunction)( - /* the segment */ Seg seg, - /* the object grain index */ Index i, - /* the address of the object */Addr p, - /* " " after the object */Addr next, - /* the iteration closure */ void *closure); - -#define AMSObjectFunctionCheck(f) \ - ((f) != NULL) /* that's the best we can do */ - - -/* amsIterate -- applies a function to each object in a segment - * - * amsIterate(seg, f, closure) applies f to all the objects in the - * segment. It skips the buffer, if any (from BufferScanLimit to - * BufferLimit). */ - -static Res amsIterate(Seg seg, AMSObjectFunction f, void *closure) -{ - Res res; - AMS ams; - AMSSeg amsseg; - Format format; - Align alignment; - Index i; - Addr p, next, limit; - Buffer buffer; - - AVERT(Seg, seg); - AVERT(AMSObjectFunction, f); - /* Can't check closure */ - - amsseg = Seg2AMSSeg(seg); - AVERT(AMSSeg, amsseg); - ams = amsseg->ams; - AVERT(AMS, ams); - format = AMS2Pool(ams)->format; - AVERT(Format, format); - alignment = PoolAlignment(AMS2Pool(ams)); - - /* If we're using the alloc table as a white table, we can't use it to */ - /* determine where there are objects. */ - AVER(!(ams->shareAllocTable && amsseg->colourTablesInUse)); - - p = SegBase(seg); - limit = SegLimit(seg); - buffer = SegBuffer(seg); - - while (p < limit) { /* loop over the objects in the segment */ - if (buffer != NULL - && p == BufferScanLimit(buffer) && p != BufferLimit(buffer)) { - /* skip buffer */ - next = BufferLimit(buffer); - AVER(AddrIsAligned(next, alignment)); - } else { - AVER((buffer == NULL) - || (p < BufferScanLimit(buffer)) - || (p >= BufferLimit(buffer))); /* not in the buffer */ - - i = AMS_ADDR_INDEX(seg, p); - if (!AMS_ALLOCED(seg, i)) { /* no object here */ - if (amsseg->allocTableInUse) { - Index dummy, nextIndex; - Bool more; - - /* Find out how large the free block is. */ - more = BTFindLongResRange(&dummy, &nextIndex, amsseg->allocTable, - i, amsseg->grains, 1); - AVER(more); - AVER(dummy == i); - next = AMS_INDEX_ADDR(seg, nextIndex); - } else { - /* If there's no allocTable, this is the free block at the end. */ - next = limit; - } - } else { /* there is an object here */ - if (format->skip != NULL) { - next = (*format->skip)(AddrAdd(p, format->headerSize)); - next = AddrSub(next, format->headerSize); - } else { - next = AddrAdd(p, alignment); - } - AVER(AddrIsAligned(next, alignment)); - res = (*f)(seg, i, p, next, closure); - if (res != ResOK) - return res; - } - } - AVER(next > p); /* make sure we make progress */ - p = next; - } - AVER(p == limit); - return ResOK; -} - - -/* amsScanObject -- scan a single object - * - * This is the object function passed to amsIterate by AMSScan. */ - -struct amsScanClosureStruct { - ScanState ss; - Bool scanAllObjects; -}; - -typedef struct amsScanClosureStruct *amsScanClosure; - -static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos) -{ - amsScanClosure closure; - AMSSeg amsseg; - Format format; - Res res; - - amsseg = Seg2AMSSeg(seg); - /* seg & amsseg have already been checked, in amsIterate. */ - AVER(i < amsseg->grains); - AVER(p != 0); - AVER(p < next); - AVER(clos != NULL); - closure = (amsScanClosure)clos; - AVERT(ScanState, closure->ss); - AVER(BoolCheck(closure->scanAllObjects)); - - format = AMS2Pool(amsseg->ams)->format; - AVERT(Format, format); - - /* @@@@ This isn't quite right for multiple traces. */ - if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) { - res = (*format->scan)(&closure->ss->ss_s, - AddrAdd(p, format->headerSize), - AddrAdd(next, format->headerSize)); - if (res != ResOK) - return res; - closure->ss->scannedSize += AddrOffset(p, next); - if (!closure->scanAllObjects) { - Index j = AMS_ADDR_INDEX(seg, next); - AVER(!AMS_IS_INVALID_COLOUR(seg, i)); - AMS_GREY_BLACKEN(seg, i); - if (i+1 < j) - AMS_RANGE_WHITE_BLACKEN(seg, i+1, j); - } - } - - return ResOK; -} - - -/* AMSScan -- the pool class segment scanning method - * - * See - */ -Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) -{ - Res res; - AMS ams; - Arena arena; - AMSSeg amsseg; - struct amsScanClosureStruct closureStruct; - Format format; - Align alignment; - - AVER(totalReturn != NULL); - AVERT(ScanState, ss); - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - arena = PoolArena(pool); - AVER(SegCheck(seg)); - amsseg = Seg2AMSSeg(seg); - AVERT(AMSSeg, amsseg); - - /* Check that we're not in the grey mutator phase (see */ - /* ). */ - AVER(TraceSetSub(ss->traces, arena->flippedTraces)); - - closureStruct.scanAllObjects = - (TraceSetDiff(ss->traces, SegWhite(seg)) != TraceSetEMPTY); - closureStruct.ss = ss; - /* @@@@ This isn't quite right for multiple traces. */ - if (closureStruct.scanAllObjects) { - /* The whole seg (except the buffer) is grey for some trace. */ - res = amsIterate(seg, amsScanObject, &closureStruct); - if (res != ResOK) { - *totalReturn = FALSE; - return res; - } - *totalReturn = TRUE; - } else { - AVER(amsseg->marksChanged); /* something must have changed */ - AVER(amsseg->colourTablesInUse); - format = pool->format; - AVERT(Format, format); - alignment = PoolAlignment(AMS2Pool(ams)); - do { /* */ - amsseg->marksChanged = FALSE; /* */ - /* */ - if (amsseg->ambiguousFixes) { - res = amsIterate(seg, amsScanObject, &closureStruct); - if (res != ResOK) { - /* */ - amsseg->marksChanged = TRUE; - *totalReturn = FALSE; - return res; - } - } else { - Index i, j = 0; - Addr p, next; - - while(j < amsseg->grains - && AMSFindGrey(&i, &j, seg, j, amsseg->grains)) { - Addr clientP, clientNext; - AVER(!AMS_IS_INVALID_COLOUR(seg, i)); - p = AMS_INDEX_ADDR(seg, i); - clientP = AddrAdd(p, format->headerSize); - if (format->skip != NULL) { - clientNext = (*format->skip)(clientP); - next = AddrSub(clientNext, format->headerSize); - } else { - clientNext = AddrAdd(clientP, alignment); - next = AddrAdd(p, alignment); - } - j = AMS_ADDR_INDEX(seg, next); - res = (*format->scan)(&ss->ss_s, clientP, clientNext); - if (res != ResOK) { - /* */ - amsseg->marksChanged = TRUE; - *totalReturn = FALSE; - return res; - } - /* Check that there haven't been any ambiguous fixes during the */ - /* scan, because AMSFindGrey won't work otherwise. */ - AVER_CRITICAL(!amsseg->ambiguousFixes); - ss->scannedSize += AddrOffset(p, next); - AMS_GREY_BLACKEN(seg, i); - if (i+1 < j) - AMS_RANGE_WHITE_BLACKEN(seg, i+1, j); - } - } - } while(amsseg->marksChanged); - *totalReturn = FALSE; - } - - return ResOK; -} - - -/* AMSFix -- the pool class fixing method */ - -static Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) -{ - AMSSeg amsseg; - Index i; /* the index of the fixed grain */ - Addr base; - Ref clientRef; - Format format; - - AVERT_CRITICAL(Pool, pool); - AVER_CRITICAL(TESTT(AMS, Pool2AMS(pool))); - AVERT_CRITICAL(ScanState, ss); - AVERT_CRITICAL(Seg, seg); - AVER_CRITICAL(refIO != NULL); - - format = pool->format; - AVERT(Format, format); - - amsseg = Seg2AMSSeg(seg); - AVERT_CRITICAL(AMSSeg, amsseg); - /* It's a white seg, so it must have colour tables. */ - AVER_CRITICAL(amsseg->colourTablesInUse); - - /* @@@@ We should check that we're not in the grey mutator phase */ - /* (see ), but there's no way of */ - /* doing that here (this can be called from RootScan, during flip). */ - - clientRef = *refIO; - base = AddrSub((Addr)clientRef, format->headerSize); - /* can get an ambiguous reference too close to the base of the - * segment, so when we subtract the header we are not in the - * segment any longer. This isn't a real reference, - * so we can just skip it. */ - if (base < SegBase(seg)) { - return ResOK; - } - - i = AMS_ADDR_INDEX(seg, base); - AVER_CRITICAL(!AMS_IS_INVALID_COLOUR(seg, i)); - - ss->wasMarked = TRUE; - - switch (ss->rank) { - case RankAMBIG: - if (Pool2AMS(pool)->shareAllocTable) - /* In this state, the pool doesn't support ambiguous references (see */ - /* .ambiguous.noshare), so this is not a reference. */ - break; - /* not a real pointer if not aligned or not allocated */ - if (!AddrIsAligned(base, PoolAlignment(pool)) - || !AMS_ALLOCED(seg, i)) { - break; - } - amsseg->ambiguousFixes = TRUE; - /* falls through */ - case RankEXACT: - case RankFINAL: - case RankWEAK: - AVER_CRITICAL(AddrIsAligned(base, PoolAlignment(pool))); - AVER_CRITICAL(AMS_ALLOCED(seg, i)); - if (AMS_IS_WHITE(seg, i)) { - ss->wasMarked = FALSE; - if (ss->rank == RankWEAK) { /* then splat the reference */ - *refIO = (Ref)0; - } else { - ++ss->preservedInPlaceCount; /* Size updated on reclaim */ - if (SegRankSet(seg) == RankSetEMPTY && ss->rank != RankAMBIG) { - /* */ - Addr clientNext, next; - - ShieldExpose(PoolArena(pool), seg); - clientNext = (*pool->format->skip)(clientRef); - ShieldCover(PoolArena(pool), seg); - next = AddrSub(clientNext, format->headerSize); - /* Part of the object might be grey, because of ambiguous */ - /* fixes, but that's OK, because scan will ignore that. */ - AMS_RANGE_WHITE_BLACKEN(seg, i, AMS_ADDR_INDEX(seg, next)); - } else { /* turn it grey */ - AMS_WHITE_GREYEN(seg, i); - SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); - /* mark it for scanning - */ - amsseg->marksChanged = TRUE; - } - } - } - break; - default: - NOTREACHED; - } - - return ResOK; -} - - -/* AMSBlacken -- the pool class blackening method - * - * Turn all grey objects black. */ - - -static Res amsBlackenObject(Seg seg, Index i, Addr p, Addr next, void *clos) -{ - UNUSED(p); - AVER(clos == NULL); - /* Do what amsScanObject does, minus the scanning. */ - if (AMS_IS_GREY(seg, i)) { - Index j = AMS_ADDR_INDEX(seg, next); - AVER(!AMS_IS_INVALID_COLOUR(seg, i)); - AMS_GREY_BLACKEN(seg, i); - if (i+1 < j) - AMS_RANGE_BLACKEN(seg, i+1, j); - } - return ResOK; -} - - -static void AMSBlacken(Pool pool, TraceSet traceSet, Seg seg) -{ - AMS ams; - Res res; - - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - AVERT(TraceSet, traceSet); - AVERT(Seg, seg); - - /* If it's white for any of these traces, turn grey to black without scanning. */ - if (TraceSetInter(traceSet, SegWhite(seg)) != TraceSetEMPTY) { - AMSSeg amsseg = Seg2AMSSeg(seg); - AVERT(AMSSeg, amsseg); - AVER(amsseg->marksChanged); /* there must be something grey */ - amsseg->marksChanged = FALSE; - res = amsIterate(seg, amsBlackenObject, NULL); - AVER(res == ResOK); - } -} - - -/* AMSReclaim -- the pool class reclamation method */ - -static void AMSReclaim(Pool pool, Trace trace, Seg seg) -{ - AMS ams; - AMSSeg amsseg; - Count nowFree, grains; - Size reclaimedSize; - PoolDebugMixin debug; - - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - AVERT(Trace, trace); - AVERT(Seg, seg); - - amsseg = Seg2AMSSeg(seg); - /* It's a white seg, so it must have colour tables. */ - AVER(amsseg->colourTablesInUse); - AVER(!amsseg->marksChanged); /* there must be nothing grey */ - grains = amsseg->grains; - - /* Loop over all white blocks and splat them, if it's a debug class. */ - debug = ((pool)->class->debugMixin)(pool); - if (debug != NULL) { - Index i, j = 0; - - while(j < grains && AMS_FIND_WHITE_RANGE(&i, &j, seg, j, grains)) { - AVER(!AMS_IS_INVALID_COLOUR(seg, i)); - DebugPoolFreeSplat(pool, AMS_INDEX_ADDR(seg, i), AMS_INDEX_ADDR(seg, j)); - ++j; /* we know next grain is not white */ - } - } - - nowFree = BTCountResRange(amsseg->nonwhiteTable, 0, grains); - - /* If the free space is all after firstFree, keep on using firstFree. */ - /* It could have a more complicated condition, but not worth the trouble. */ - if (!amsseg->allocTableInUse && amsseg->firstFree + nowFree == grains) { - AVER(amsseg->firstFree == grains - || BTIsResRange(amsseg->nonwhiteTable, - amsseg->firstFree, grains)); - } else { - if (ams->shareAllocTable) { - /* Stop using allocTable as the white table. */ - amsseg->allocTableInUse = TRUE; - } else { - AVER(amsseg->allocTableInUse); - BTCopyRange(amsseg->nonwhiteTable, amsseg->allocTable, 0, grains); - } - } - - reclaimedSize = (nowFree - amsseg->free) << ams->grainShift; - amsseg->free = nowFree; - trace->reclaimSize += reclaimedSize; - ams->pgen.totalSize -= reclaimedSize; - /* preservedInPlaceCount is updated on fix */ - trace->preservedInPlaceSize += (grains - amsseg->free) << ams->grainShift; - - if (amsseg->free == grains && SegBuffer(seg) == NULL) { - /* No survivors */ - SegFree(seg); - } else { - amsseg->colourTablesInUse = FALSE; - SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace)); - } -} - - -/* AMSFreeWalk -- free block walking method of the pool class */ - -static void AMSFreeWalk(Pool pool, FreeBlockStepMethod f, void *p) -{ - AMS ams; - Ring node, ring, nextNode; /* for iterating over the segments */ - - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - - ring = &ams->segRing; - RING_FOR(node, ring, nextNode) { - AMSSegFreeWalk(RING_ELT(AMSSeg, segRing, node), f, p); - } -} - - -/* AMSDescribe -- the pool class description method - * - * Iterates over the segments, describing all of them. - */ -static Res AMSDescribe(Pool pool, mps_lib_FILE *stream) -{ - AMS ams; - Ring node, nextNode; - Res res; - - if (!TESTT(Pool, pool)) return ResFAIL; - ams = Pool2AMS(pool); - if (!TESTT(AMS, ams)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, - "AMS $P {\n", (WriteFP)ams, - " pool $P ($U)\n", - (WriteFP)pool, (WriteFU)pool->serial, - " size $W\n", - (WriteFW)ams->size, - " grain shift $U\n", (WriteFU)ams->grainShift, - " chain $P\n", - (WriteFP)ams->chain, - NULL); - if (res != ResOK) return res; - - res = WriteF(stream, - " segments\n" - " * = black, + = grey, - = white, . = alloc, ! = bad\n" - " buffers: [ = base, < = scan limit, | = init,\n" - " > = alloc, ] = limit\n", - NULL); - if (res != ResOK) return res; - - RING_FOR(node, &ams->segRing, nextNode) { - AMSSeg amsseg = RING_ELT(AMSSeg, segRing, node); - res = SegDescribe(AMSSeg2Seg(amsseg), stream); - if (res != ResOK) return res; - } - - res = WriteF(stream, "} AMS $P\n",(WriteFP)ams, NULL); - if (res != ResOK) - return res; - - return ResOK; -} - - -/* AMSPoolClass -- the class definition */ - -/* contains the type definition. Hence the use */ -/* of DEFINE_CLASS rather than DEFINE_POOL_CLASS */ - -DEFINE_CLASS(AMSPoolClass, this) -{ - INHERIT_CLASS(this, AbstractCollectPoolClass); - PoolClassMixInFormat(this); - this->name = "AMS"; - this->size = sizeof(AMSStruct); - this->offset = offsetof(AMSStruct, poolStruct); - this->init = AMSInit; - this->finish = AMSFinish; - this->bufferClass = RankBufClassGet; - this->bufferFill = AMSBufferFill; - this->bufferEmpty = AMSBufferEmpty; - this->whiten = AMSCondemn; - this->blacken = AMSBlacken; - this->scan = AMSScan; - this->fix = AMSFix; - this->fixEmergency = AMSFix; - this->reclaim = AMSReclaim; - this->freewalk = AMSFreeWalk; - this->describe = AMSDescribe; -} - - -/* AMSDebugMixin - find debug mixin in class AMSDebug */ - -static PoolDebugMixin AMSDebugMixin(Pool pool) -{ - AMS ams; - - AVERT(Pool, pool); - ams = Pool2AMS(pool); - AVERT(AMS, ams); - /* Can't check AMSDebug, because this is called during init */ - return &(AMS2AMSDebug(ams)->debug); -} - - -/* AMSDebugPoolClass -- the class definition for the debug version */ - -DEFINE_POOL_CLASS(AMSDebugPoolClass, this) -{ - INHERIT_CLASS(this, AMSPoolClass); - PoolClassMixInDebug(this); - this->name = "AMSDBG"; - this->size = sizeof(AMSDebugStruct); - this->debugMixin = AMSDebugMixin; -} - - -/* AMSCheck -- the check method for an AMS */ - -Bool AMSCheck(AMS ams) -{ - CHECKS(AMS, ams); - CHECKL(PoolCheck(AMS2Pool(ams))); - CHECKL(IsSubclassPoly(AMS2Pool(ams)->class, AMSPoolClassGet())); - CHECKL(PoolAlignment(AMS2Pool(ams)) == ((Size)1 << ams->grainShift)); - CHECKL(PoolAlignment(AMS2Pool(ams)) == AMS2Pool(ams)->format->alignment); - CHECKD(Chain, ams->chain); - CHECKD(PoolGen, &ams->pgen); - CHECKL(SizeIsAligned(ams->size, ArenaAlign(PoolArena(AMS2Pool(ams))))); - CHECKL(FUNCHECK(ams->segSize)); - CHECKL(RingCheck(&ams->segRing)); - CHECKL(FUNCHECK(ams->allocRing)); - CHECKL(FUNCHECK(ams->segsDestroy)); - CHECKL(FUNCHECK(ams->segClass)); - - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolams.h b/mps/code/poolams.h deleted file mode 100644 index 292085fbf10..00000000000 --- a/mps/code/poolams.h +++ /dev/null @@ -1,237 +0,0 @@ -/* poolams.h: AUTOMATIC MARK & SWEEP POOL CLASS INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .purpose: Internal interface to AMS functionality. */ - -#ifndef poolams_h -#define poolams_h - -#include "mpmtypes.h" -#include "mpmst.h" -#include "ring.h" -#include "bt.h" -#include - - -typedef struct AMSStruct *AMS; -typedef struct AMSSegStruct *AMSSeg; - - -/* AMSRingFunction is the type of the method to find the ring that */ -/* the AMS pool is allocating on. */ -typedef Ring (*AMSRingFunction)(AMS ams, RankSet rankSet, Size size); -/* AMSSegClassFunction is the type of the method to indicate */ -/* the segment class of an AMS pool. Returns a subclass of AMSSegClass. */ -/* The type is congruent with SegClassGet functions. */ -typedef SegClass (*AMSSegClassFunction)(void); -/* AMSSegsDestroyFunction is the type of the method to destroy all */ -/* segs of an AMS pool. */ -typedef void (*AMSSegsDestroyFunction)(AMS ams); -/* AMSSegSizePolicyFunction is the type of the method which picks */ -/* a segment size given an object size. */ -typedef Res (*AMSSegSizePolicyFunction)(Size *sizeReturn, - Pool pool, Size size, - RankSet rankSet); - - -typedef struct AMSStruct { - PoolStruct poolStruct; /* generic pool structure */ - Shift grainShift; /* log2 of grain size */ - Chain chain; /* chain used by this pool */ - PoolGenStruct pgen; /* generation representing the pool */ - Size size; /* total segment size of the pool */ - AMSSegSizePolicyFunction segSize; /* SegSize policy */ - RingStruct segRing; /* ring of segments in the pool */ - AMSRingFunction allocRing; /* fn to get the ring to allocate from */ - AMSSegsDestroyFunction segsDestroy; - AMSSegClassFunction segClass;/* fn to get the class for segments */ - Bool shareAllocTable; /* the alloc table is also used as white table */ - Sig sig; /* */ -} AMSStruct; - - -typedef struct AMSSegStruct { - GCSegStruct gcSegStruct; /* superclass fields must come first */ - AMS ams; /* owning ams */ - RingStruct segRing; /* ring that this seg belongs to */ - Count grains; /* number of grains */ - Count free; /* number of free grains */ - Count newAlloc; /* number of grains allocated since last GC */ - Bool allocTableInUse; /* allocTable is used */ - Index firstFree; /* 1st free grain, if allocTable is not used */ - BT allocTable; /* set if grain is allocated */ - /* */ - Bool marksChanged; /* seg has been marked since last scan */ - Bool ambiguousFixes; /* seg has been ambiguously marked since last scan */ - Bool colourTablesInUse;/* the colour tables are in use */ - BT nonwhiteTable; /* set if grain not white */ - BT nongreyTable; /* set if not first grain of grey object */ - Sig sig; -} AMSSegStruct; - - -/* macros to get between child and parent structures */ - -#define Seg2AMSSeg(seg) ((AMSSeg)(seg)) -#define AMSSeg2Seg(amsseg) ((Seg)(amsseg)) - -#define Pool2AMS(pool) PARENT(AMSStruct, poolStruct, pool) -#define AMS2Pool(ams) (&(ams)->poolStruct) - - -/* macros for abstracting index/address computations */ -/* */ - -/* only use when size is a multiple of the grain size */ -#define AMSGrains(ams, size) ((size) >> (ams)->grainShift) - -#define AMSGrainsSize(ams, grains) ((grains) << (ams)->grainShift) - -#define AMSSegShift(seg) (Seg2AMSSeg(seg)->ams->grainShift) - -#define AMS_ADDR_INDEX(seg, addr) \ - ((Index)(AddrOffset(SegBase(seg), addr) >> AMSSegShift(seg))) -#define AMS_INDEX_ADDR(seg, index) \ - AddrAdd(SegBase(seg), (Size)(index) << AMSSegShift(seg)) - - -/* colour ops */ - -#define AMS_IS_WHITE(seg, index) \ - (!BTGet(Seg2AMSSeg(seg)->nonwhiteTable, index)) - -#define AMS_IS_GREY(seg, index) \ - (!BTGet(Seg2AMSSeg(seg)->nongreyTable, index)) - -#define AMS_IS_BLACK(seg, index) \ - (!AMS_IS_GREY(seg, index) && !AMS_IS_WHITE(seg, index)) - -#define AMS_IS_INVALID_COLOUR(seg, index) \ - (AMS_IS_GREY(seg, index) && !AMS_IS_WHITE(seg, index)) - -#define AMS_WHITE_GREYEN(seg, index) \ - BEGIN \ - BTRes(Seg2AMSSeg(seg)->nongreyTable, index); \ - END - -#define AMS_GREY_BLACKEN(seg, index) \ - BEGIN \ - BTSet(Seg2AMSSeg(seg)->nongreyTable, index); \ - BTSet(Seg2AMSSeg(seg)->nonwhiteTable, index); \ - END - -#define AMS_WHITE_BLACKEN(seg, index) \ - BEGIN \ - BTSet(Seg2AMSSeg(seg)->nonwhiteTable, index); \ - END - -#define AMS_RANGE_WHITE_BLACKEN(seg, base, limit) \ - BEGIN \ - BTSetRange(Seg2AMSSeg(seg)->nonwhiteTable, base, limit); \ - END - -#define AMS_RANGE_BLACKEN(seg, base, limit) \ - BEGIN \ - BTSetRange(Seg2AMSSeg(seg)->nonwhiteTable, base, limit); \ - BTSetRange(Seg2AMSSeg(seg)->nongreyTable, base, limit); \ - END - -#define AMS_RANGE_WHITEN(seg, base, limit) \ - BEGIN \ - BTResRange(Seg2AMSSeg(seg)->nonwhiteTable, base, limit); \ - BTSetRange(Seg2AMSSeg(seg)->nongreyTable, base, limit); \ - END - -#define AMSFindGrey(pos, dummy, seg, base, limit) \ - BTFindShortResRange(pos, dummy, Seg2AMSSeg(seg)->nongreyTable, \ - base, limit, 1) - -#define AMSFindWhite(pos, dummy, seg, base, limit) \ - BTFindShortResRange(pos, dummy, Seg2AMSSeg(seg)->nonwhiteTable, \ - base, limit, 1) - -#define AMS_FIND_WHITE_RANGE(baseOut, limitOut, seg, base, limit) \ - BTFindLongResRange(baseOut, limitOut, Seg2AMSSeg(seg)->nonwhiteTable, \ - base, limit, 1) - -#define AMS_ALLOCED(seg, index) \ - (Seg2AMSSeg(seg)->allocTableInUse \ - ? BTGet(Seg2AMSSeg(seg)->allocTable, index) \ - : (Seg2AMSSeg(seg)->firstFree > (index))) - - -/* the rest */ - -extern Res AMSInitInternal(AMS ams, Format format, Chain chain, - Bool shareAllocTable); -extern void AMSFinish(Pool pool); -extern Bool AMSCheck(AMS ams); - -extern Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg); - -#define AMSChain(ams) ((ams)->chain) - -extern void AMSSegFreeWalk(AMSSeg amsseg, FreeBlockStepMethod f, void *p); - -extern void AMSSegFreeCheck(AMSSeg amsseg); - - -typedef SegClass AMSSegClass; -typedef SegClassStruct AMSSegClassStruct; -extern AMSSegClass AMSSegClassGet(void); -extern Bool AMSSegCheck(AMSSeg seg); - - -typedef PoolClass AMSPoolClass; -typedef PoolClassStruct AMSPoolClassStruct; - -extern AMSPoolClass AMSPoolClassGet(void); -extern AMSPoolClass AMSDebugPoolClassGet(void); - - -#endif /* poolams_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolamsi.c b/mps/code/poolamsi.c deleted file mode 100644 index 4e78c445bb4..00000000000 --- a/mps/code/poolamsi.c +++ /dev/null @@ -1,69 +0,0 @@ -/* poolamsi.c: AUTOMATIC MARK & SWEEP POOL CLASS C INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpscams.h" -#include "mps.h" -#include "poolams.h" - -SRCID(poolamsi, "$Id$"); - - -/* mps_class_ams -- return the AMS pool class descriptor */ - -mps_class_t mps_class_ams(void) -{ - return (mps_class_t)AMSPoolClassGet(); -} - - -/* mps_class_ams_debug -- return the AMS (debug) pool class descriptor */ - -mps_class_t mps_class_ams_debug(void) -{ - return (mps_class_t)AMSDebugPoolClassGet(); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c deleted file mode 100644 index e775517a7b2..00000000000 --- a/mps/code/poolawl.c +++ /dev/null @@ -1,1325 +0,0 @@ -/* poolawl.c: AUTOMATIC WEAK LINKED POOL CLASS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * - * DESIGN - * - * .design: See . This is Dylan-specific pool. - * - * - * ASSUMPTIONS (about when to scan single references on accesses) - * - * .assume.purpose: The purpose of scanning refs singly is to limit the - * amount of scanning of weak references which must be performed when - * the mutator hits a barrier. Weak references which are scanned at this - * time are not "weak splatted". Minimizing any loss of weak splats - * potentially reduces conservatism in the collector. - * - * .assume.noweak: It follows (from .assume.purpose) that there is no - * benefit from scanning single refs on barrier accesses for segments - * which don't contain any weak references. However, if a segment - * contains either all weak refs or a mixture of weak and non-weak - * references then there is a potential benefit. - * - * .assume.mixedrank: If a segment contains a mixture of references - * at different ranks (e.g. weak and strong references), there is - * no way to determine whether or not references at a rank other than - * the scan state rank will be scanned as a result of normal - * (non-barrier) scanning activity. (@@@@ This is a deficiency in MPS). - * Assume that such references will, in fact, be scanned at the - * incorrect rank. - * - * .assume.samerank: The pool doesn't support segments with mixed - * rank segments in any case (despite .assume.mixedrank). - * - * .assume.alltraceable: The pool assumes that all objects are entirely - * traceable. This must be documented elsewhere for the benefit of the - * client. - */ - -#include "mpscawl.h" -#include "mpm.h" -#include "chain.h" - -SRCID(poolawl, "$Id$"); - - -#define AWLSig ((Sig)0x519B7A37) /* SIGnature PooL AWL */ - -#define AWLGen ((Serial)1) /* "generation" for AWL pools */ -/* This and the dynamic criterion are the only ways AWL will get collected. */ - - -/* awlStat* -- Statistics gathering about instruction emulation - * - * To support change.dylan.2.0.160044. - */ - - -/* Per-segment statistics maintained between segment scans */ - -typedef struct awlStatSegStruct { - Count sameAccesses; /* accesses involving same address as last access */ - Addr lastAccess; /* the address of last access */ -} awlStatSegStruct, *awlStatSeg; - -/* Per-pool statistics updated at segment scans */ - -typedef struct awlStatTotalStruct { - Count goodScans; /* total times a segment scanned at proper rank */ - Count badScans; /* total times a segment scanned at improper rank */ - Count savedScans; /* total times an entire segment scan was avoided */ - Count savedAccesses; /* total single references leading to a saved scan */ - Count declined; /* number of declined single accesses */ -} awlStatTotalStruct, *awlStatTotal; - -/* the type of a function to find an object's dependent object */ - -typedef Addr (*FindDependentMethod)(Addr object); - -/* AWLStruct -- AWL pool structure - * - * See - */ - -typedef struct AWLStruct { - PoolStruct poolStruct; - Shift alignShift; - Chain chain; /* dummy chain */ - PoolGenStruct pgen; /* generation representing the pool */ - Size size; /* allocated size in bytes */ - Serial gen; /* associated generation (for SegAlloc) */ - Count succAccesses; /* number of successive single accesses */ - FindDependentMethod findDependent; /* to find a dependent object */ - awlStatTotalStruct stats; - Sig sig; -} AWLStruct, *AWL; - -#define Pool2AWL(pool) PARENT(AWLStruct, poolStruct, pool) - - -static Bool AWLCheck(AWL awl); - - -/* Conversion between indexes and Addrs */ -#define awlIndexOfAddr(base, awl, p) \ - (AddrOffset((base), (p)) >> (awl)->alignShift) - - -/* AWLSegStruct -- AWL segment subclass - * - * Subclass of GCSeg - */ - -#define AWLSegSig ((Sig)0x519A3759) /* SIGnature AWL SeG */ - -/* */ -typedef struct AWLSegStruct { - GCSegStruct gcSegStruct; /* superclass fields must come first */ - BT mark; - BT scanned; - BT alloc; - Count grains; - Count free; /* number of free grains */ - Count singleAccesses; /* number of accesses processed singly */ - awlStatSegStruct stats; - Sig sig; -} AWLSegStruct, *AWLSeg; - -#define Seg2AWLSeg(seg) ((AWLSeg)(seg)) -#define AWLSeg2Seg(awlseg) ((Seg)(awlseg)) - - -static SegClass AWLSegClassGet(void); - - -static Bool AWLSegCheck(AWLSeg awlseg) -{ - CHECKS(AWLSeg, awlseg); - CHECKD(GCSeg, &awlseg->gcSegStruct); - CHECKL(awlseg->mark != NULL); - CHECKL(awlseg->scanned != NULL); - CHECKL(awlseg->alloc != NULL); - /* Can't do any real check on ->grains */ - CHECKL(awlseg->grains > 0); - CHECKL(awlseg->free <= awlseg->grains); - return TRUE; -} - - -/* Management of statistics for monitoring protection-driven accesses */ - -static void awlStatSegInit(AWLSeg awlseg) -{ - awlseg->stats.sameAccesses = 0; - awlseg->stats.lastAccess = NULL; -} - -static void awlStatTotalInit(AWL awl) -{ - awl->stats.goodScans = 0; - awl->stats.badScans = 0; - awl->stats.savedAccesses = 0; - awl->stats.savedScans = 0; - awl->stats.declined = 0; -} - - -/* AWLSegInit -- Init method for AWL segments */ - -static Res AWLSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - SegClass super; - AWLSeg awlseg; - AWL awl; - Arena arena; - RankSet rankSet; - Count bits; /* number of grains */ - Res res; - Size tableSize; - void *v; - - AVERT(Seg, seg); - awlseg = Seg2AWLSeg(seg); - AVERT(Pool, pool); - arena = PoolArena(pool); - /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); - rankSet = va_arg(args, RankSet); - /* .assume.samerank */ - /* AWL only accepts two ranks */ - AVER(RankSetSingle(RankEXACT) == rankSet - || RankSetSingle(RankWEAK) == rankSet); - awl = Pool2AWL(pool); - AVERT(AWL, awl); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(AWLSegClass); - res = super->init(seg, pool, base, size, reservoirPermit, args); - if (res != ResOK) - return res; - - bits = size >> awl->alignShift; - tableSize = BTSize(bits); - res = ControlAlloc(&v, arena, tableSize, reservoirPermit); - if (res != ResOK) - goto failControlAllocMark; - awlseg->mark = v; - res = ControlAlloc(&v, arena, tableSize, reservoirPermit); - if (res != ResOK) - goto failControlAllocScanned; - awlseg->scanned = v; - res = ControlAlloc(&v, arena, tableSize, reservoirPermit); - if (res != ResOK) - goto failControlAllocAlloc; - awlseg->alloc = v; - awlseg->grains = bits; - BTResRange(awlseg->mark, 0, bits); - BTResRange(awlseg->scanned, 0, bits); - BTResRange(awlseg->alloc, 0, bits); - SegSetRankAndSummary(seg, rankSet, RefSetUNIV); - awlseg->free = bits; - awlseg->sig = AWLSegSig; - awlseg->singleAccesses = 0; - awlStatSegInit(awlseg); - AVERT(AWLSeg, awlseg); - return ResOK; - -failControlAllocAlloc: - ControlFree(arena, awlseg->scanned, tableSize); -failControlAllocScanned: - ControlFree(arena, awlseg->mark, tableSize); -failControlAllocMark: - super->finish(seg); - return res; -} - - -/* AWLSegFinish -- Finish method for AWL segments */ - -static void AWLSegFinish(Seg seg) -{ - AWL awl; - AWLSeg awlseg; - SegClass super; - Pool pool; - Size tableSize; - Arena arena; - Count segGrains; - - AVERT(Seg, seg); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - pool = SegPool(seg); - AVERT(Pool, pool); - awl = Pool2AWL(pool); - AVERT(AWL, awl); - arena = PoolArena(pool); - AVERT(Arena, arena); - - /* This is one of the few places where it is easy to check */ - /* awlseg->grains, so we do */ - segGrains = SegSize(seg) >> awl->alignShift; - AVER(segGrains == awlseg->grains); - tableSize = BTSize(segGrains); - ControlFree(arena, awlseg->alloc, tableSize); - ControlFree(arena, awlseg->scanned, tableSize); - ControlFree(arena, awlseg->mark, tableSize); - awlseg->sig = SigInvalid; - - /* finish the superclass fields last */ - super = SEG_SUPERCLASS(AWLSegClass); - super->finish(seg); -} - - -/* AWLSegClass -- Class definition for AWL segments */ - -DEFINE_SEG_CLASS(AWLSegClass, class) -{ - INHERIT_CLASS(class, GCSegClass); - SegClassMixInNoSplitMerge(class); /* no support for this (yet) */ - class->name = "AWLSEG"; - class->size = sizeof(AWLSegStruct); - class->init = AWLSegInit; - class->finish = AWLSegFinish; -} - - -/* Single access pattern control parameters - * - * These control the number of expensive emulated single-accesses we allow - * before we give up and scan a segment at whatever rank, possibly causing - * retention of weak objects. - * - * AWLSegSALimit is the number of accesses for a single segment in a GC cycle. - * AWLTotalSALimit is the total number of accesses during a GC cycle. - * - * These should be set in config.h, but are here in static variables so that - * it's possible to tweak them in a debugger. - */ - -Count AWLSegSALimit = AWL_SEG_SA_LIMIT; -Bool AWLHaveSegSALimit = AWL_HAVE_SEG_SA_LIMIT; - -Count AWLTotalSALimit = AWL_TOTAL_SA_LIMIT; -Bool AWLHaveTotalSALimit = AWL_HAVE_TOTAL_SA_LIMIT; - - -/* Determine whether to permit scanning a single ref. */ - -static Bool AWLCanTrySingleAccess(Arena arena, AWL awl, Seg seg, Addr addr) -{ - AWLSeg awlseg; - - AVERT(AWL, awl); - AVERT(Seg, seg); - AVER(addr != NULL); - - /* .assume.noweak */ - /* .assume.alltraceable */ - if (!RankSetIsMember(SegRankSet(seg), RankWEAK)) - return FALSE; - - /* If there are no traces in progress then the segment isn't read - protected and this is just an ordinary write barrier hit. No need to - scan at all. */ - if (arena->flippedTraces == TraceSetEMPTY) { - AVER(!(SegSM(seg) & AccessREAD)); - return FALSE; - } - - /* The trace is already in the weak band, so we can scan the whole - segment without retention anyway. Go for it. */ - if (TraceRankForAccess(arena, seg) == RankWEAK) - return FALSE; - - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - /* If there have been too many single accesses in a row then don't - keep trying them, even if it means retaining objects. */ - if(AWLHaveTotalSALimit) { - if(awl->succAccesses >= AWLTotalSALimit) { - STATISTIC(awl->stats.declined++); - EVENT2(AWLDeclineTotal, seg, awl->succAccesses); - return FALSE; /* decline single access because of total limit */ - } - } - - /* If there have been too many single accesses to this segment - then don't keep trying them, even if it means retaining objects. - (Observed behaviour in Open Dylan 2012-09-10 by RB.) */ - if(AWLHaveSegSALimit) { - if(awlseg->singleAccesses >= AWLSegSALimit) { - STATISTIC(awl->stats.declined++); - EVENT2(AWLDeclineSeg, seg, awlseg->singleAccesses); - return FALSE; /* decline single access because of segment limit */ - } - } - - return TRUE; -} - - -/* Record an access to a segment which required scanning a single ref */ - -static void AWLNoteRefAccess(AWL awl, Seg seg, Addr addr) -{ - AWLSeg awlseg; - - AVERT(AWL, awl); - AVERT(Seg, seg); - AVER(addr != NULL); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - awlseg->singleAccesses++; /* increment seg count of ref accesses */ - if (addr == awlseg->stats.lastAccess) { - /* If this is a repeated access, increment count */ - STATISTIC(awlseg->stats.sameAccesses++); - } - STATISTIC(awlseg->stats.lastAccess = addr); - awl->succAccesses++; /* Note a new successive access */ -} - - -/* Record an access to a segment which required scanning the entire seg */ - -static void AWLNoteSegAccess(AWL awl, Seg seg, Addr addr) -{ - AVERT(AWL, awl); - AVERT(Seg, seg); - AVER(addr != NULL); - - awl->succAccesses = 0; /* reset count of successive accesses */ -} - - -/* Record a scan of a segment which wasn't provoked by an access */ - -static void AWLNoteScan(AWL awl, Seg seg, ScanState ss) -{ - AWLSeg awlseg; - - AVERT(AWL, awl); - AVERT(Seg, seg); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - /* .assume.mixedrank */ - /* .assume.samerank */ - /* If this segment has any RankWEAK references, then */ - /* record statistics about whether weak splatting is being lost. */ - if (RankSetIsMember(SegRankSet(seg), RankWEAK)) { - if (RankWEAK == ss->rank) { - /* This is "successful" scan at proper rank. */ - STATISTIC(awl->stats.goodScans++); - if (0 < awlseg->singleAccesses) { - /* Accesses have been proceesed singly */ - /* Record that we genuinely did save a protection-provoked scan */ - STATISTIC(awl->stats.savedScans++); - STATISTIC(awl->stats.savedAccesses += awlseg->singleAccesses); - } - } else { - /* This is "failed" scan at improper rank. */ - STATISTIC(awl->stats.badScans++); - } - /* Reinitialize the segment statistics */ - awlseg->singleAccesses = 0; - STATISTIC(awlStatSegInit(awlseg)); - } -} - - -/* AWLSegCreate -- Create a new segment of at least given size */ - -static Res AWLSegCreate(AWLSeg *awlsegReturn, - RankSet rankSet, Pool pool, Size size, - Bool reservoirPermit) -{ - AWL awl; - Seg seg; - AWLSeg awlseg; - Res res; - Arena arena; - SegPrefStruct segPrefStruct; - - AVER(awlsegReturn != NULL); - AVER(RankSetCheck(rankSet)); - AVERT(Pool, pool); - AVER(size > 0); - AVER(BoolCheck(reservoirPermit)); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - - arena = PoolArena(pool); - AVERT(Arena, arena); - - size = SizeAlignUp(size, ArenaAlign(arena)); - /* beware of large sizes overflowing upon rounding */ - if (size == 0) - return ResMEMORY; - segPrefStruct = *SegPrefDefault(); - SegPrefExpress(&segPrefStruct, SegPrefCollected, NULL); - SegPrefExpress(&segPrefStruct, SegPrefGen, &awl->gen); - res = SegAlloc(&seg, AWLSegClassGet(), &segPrefStruct, size, pool, - reservoirPermit, rankSet); - if (res != ResOK) - return res; - - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - *awlsegReturn = awlseg; - return ResOK; -} - - -/* AWLSegAlloc -- allocate an object in a given segment */ - -static Bool AWLSegAlloc(Addr *baseReturn, Addr *limitReturn, - AWLSeg awlseg, AWL awl, Size size) -{ - Count n; /* number of grains equivalent to alloc size */ - Index i, j; - Seg seg; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(AWLSeg, awlseg); - AVERT(AWL, awl); - AVER(size > 0); - AVER(size << awl->alignShift >= size); - seg = AWLSeg2Seg(awlseg); - - if (size > SegSize(seg)) - return FALSE; - n = size >> awl->alignShift; - if (!BTFindLongResRange(&i, &j, awlseg->alloc, 0, awlseg->grains, n)) - return FALSE; - awl->size += size; - *baseReturn = AddrAdd(SegBase(seg), i << awl->alignShift); - *limitReturn = AddrAdd(SegBase(seg), j << awl->alignShift); - return TRUE; -} - - -/* AWLInit -- initialize an AWL pool */ - -static Res AWLInit(Pool pool, va_list arg) -{ - AWL awl; - Format format; - FindDependentMethod findDependent; - Chain chain; - Res res; - static GenParamStruct genParam = { SizeMAX, 0.5 /* dummy */ }; - - /* Weak check, as half-way through initialization. */ - AVER(pool != NULL); - - awl = Pool2AWL(pool); - - format = va_arg(arg, Format); - AVERT(Format, format); - pool->format = format; - - findDependent = va_arg(arg, FindDependentMethod); - AVER(FUNCHECK(findDependent)); - awl->findDependent = findDependent; - - res = ChainCreate(&chain, pool->arena, 1, &genParam); - if (res != ResOK) - return res; - awl->chain = chain; - /* .gen: This must be the nursery in the chain, because it's the only */ - /* generation. awl->gen is just a hack for segment placement. */ - res = PoolGenInit(&awl->pgen, chain, 0 /* .gen */, pool); - if (res != ResOK) - goto failGenInit; - - awl->alignShift = SizeLog2(pool->alignment); - awl->gen = AWLGen; - awl->size = (Size)0; - - awl->succAccesses = 0; - awlStatTotalInit(awl); - awl->sig = AWLSig; - - AVERT(AWL, awl); - EVENT2(PoolInitAWL, pool, format); - return ResOK; - -failGenInit: - ChainDestroy(chain); - return res; -} - - -/* AWLFinish -- finish an AWL pool */ - -static void AWLFinish(Pool pool) -{ - AWL awl; - Ring ring, node, nextNode; - - AVERT(Pool, pool); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - - ring = &pool->segRing; - RING_FOR(node, ring, nextNode) { - Seg seg = SegOfPoolRing(node); - AVERT(Seg, seg); - SegFree(seg); - } - awl->sig = SigInvalid; - PoolGenFinish(&awl->pgen); - ChainDestroy(awl->chain); -} - - -/* AWLBufferFill -- BufferFill method for AWL */ - -static Res AWLBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool reservoirPermit) -{ - Addr base, limit; - AWLSeg awlseg; - AWL awl; - Res res; - Ring node, nextNode; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Pool, pool); - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(BoolCheck(reservoirPermit)); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - - RING_FOR(node, &pool->segRing, nextNode) { - Seg seg; - - seg = SegOfPoolRing(node); - AVERT(Seg, seg); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - /* Only try to allocate in the segment if it is not already */ - /* buffered, and has the same ranks as the buffer. */ - if (SegBuffer(seg) == NULL && SegRankSet(seg) == BufferRankSet(buffer)) - if (awlseg->free << awl->alignShift >= size - && AWLSegAlloc(&base, &limit, awlseg, awl, size)) - goto found; - } - - /* No free space in existing awlsegs, so create new awlseg */ - - res = AWLSegCreate(&awlseg, BufferRankSet(buffer), pool, size, - reservoirPermit); - if (res != ResOK) - return res; - base = SegBase(AWLSeg2Seg(awlseg)); - limit = SegLimit(AWLSeg2Seg(awlseg)); - -found: - { - Index i, j; - Seg seg = AWLSeg2Seg(awlseg); - i = awlIndexOfAddr(SegBase(seg), awl, base); - j = awlIndexOfAddr(SegBase(seg), awl, limit); - AVER(i < j); - BTSetRange(awlseg->alloc, i, j); - /* Objects are allocated black. */ - /* Shouldn't this depend on trace phase? @@@@ */ - BTSetRange(awlseg->mark, i, j); - BTSetRange(awlseg->scanned, i, j); - awlseg->free -= j - i; - } - *baseReturn = base; - *limitReturn = limit; - return ResOK; -} - - -/* AWLBufferEmpty -- BufferEmpty method for AWL */ - -static void AWLBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) -{ - AWL awl; - AWLSeg awlseg; - Seg seg; - Addr segBase; - Index i, j; - - AVERT(Pool, pool); - AVERT(Buffer, buffer); - seg = BufferSeg(buffer); - AVERT(Seg, seg); - AVER(init <= limit); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - segBase = SegBase(seg); - - i = awlIndexOfAddr(segBase, awl, init); - j = awlIndexOfAddr(segBase, awl, limit); - AVER(i <= j); - if (i < j) { - BTResRange(awlseg->alloc, i, j); - awlseg->free += j - i; - } -} - - -/* AWLWhiten -- segment condemning method */ - -/* awlRangeWhiten -- helper function that works on a range. - * - * This function abstracts common code from AWLWhiten. - */ -static void awlRangeWhiten(AWLSeg awlseg, Index base, Index limit) -{ - if(base != limit) { - AVER(base < limit); - AVER(limit <= awlseg->grains); - BTResRange(awlseg->mark, base, limit); - BTResRange(awlseg->scanned, base, limit); - } -} - -static Res AWLWhiten(Pool pool, Trace trace, Seg seg) -{ - AWL awl; - AWLSeg awlseg; - Buffer buffer; - - /* All parameters checked by generic PoolWhiten. */ - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - buffer = SegBuffer(seg); - - /* Can only whiten for a single trace, */ - /* see */ - AVER(SegWhite(seg) == TraceSetEMPTY); - - if(buffer == NULL) { - awlRangeWhiten(awlseg, 0, awlseg->grains); - trace->condemned += SegSize(seg); - } else { - /* Whiten everything except the buffer. */ - Addr base = SegBase(seg); - Index scanLimitIndex = awlIndexOfAddr(base, awl, - BufferScanLimit(buffer)); - Index limitIndex = awlIndexOfAddr(base, awl, - BufferLimit(buffer)); - - awlRangeWhiten(awlseg, 0, scanLimitIndex); - awlRangeWhiten(awlseg, limitIndex, awlseg->grains); - - /* Check the buffer is black. */ - /* This really ought to change when we have a non-trivial */ - /* pre-flip phase. @@@@ ('coz then we'll be allocating white) */ - if(scanLimitIndex != limitIndex) { - AVER(BTIsSetRange(awlseg->mark, scanLimitIndex, limitIndex)); - AVER(BTIsSetRange(awlseg->scanned, scanLimitIndex, limitIndex)); - } - - /* We didn't condemn the buffer, subtract it from the count. */ - /* @@@@ We could subtract all the free grains. */ - trace->condemned += SegSize(seg) - - AddrOffset(BufferScanLimit(buffer), - BufferLimit(buffer)); - } - - SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace)); - return ResOK; -} - - -/* AWLGrey -- Grey method for AWL pools */ - -/* AWLRangeGrey -- subroutine for AWLGrey */ -static void AWLRangeGrey(AWLSeg awlseg, Index base, Index limit) -{ - /* AWLSeg not checked as that's already been done */ - AVER(limit <= awlseg->grains); - /* copes with degenerate case as that makes caller simpler */ - if (base < limit) { - BTSetRange(awlseg->mark, base, limit); - BTResRange(awlseg->scanned, base, limit); - } else { - AVER(base == limit); - } -} - -static void AWLGrey(Pool pool, Trace trace, Seg seg) -{ - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - - if (!TraceSetIsMember(SegWhite(seg), trace)) { - AWL awl; - AWLSeg awlseg; - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - SegSetGrey(seg, TraceSetAdd(SegGrey(seg), trace)); - if (SegBuffer(seg) != NULL) { - Addr base = SegBase(seg); - Buffer buffer = SegBuffer(seg); - - AWLRangeGrey(awlseg, - 0, - awlIndexOfAddr(base, awl, BufferScanLimit(buffer))); - AWLRangeGrey(awlseg, - awlIndexOfAddr(base, awl, BufferLimit(buffer)), - awlseg->grains); - } else { - AWLRangeGrey(awlseg, 0, awlseg->grains); - } - } -} - - -/* AWLBlacken -- Blacken method for AWL pools */ - -static void AWLBlacken(Pool pool, TraceSet traceSet, Seg seg) -{ - AWL awl; - AWLSeg awlseg; - - AVERT(Pool, pool); - AVER(TraceSetCheck(traceSet)); - AVERT(Seg, seg); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - BTSetRange(awlseg->scanned, 0, awlseg->grains); -} - - -/* awlScanObject -- scan a single object */ -/* base and limit are both offset by the header size */ - -static Res awlScanObject(Arena arena, AWL awl, ScanState ss, - Format format, Addr base, Addr limit) -{ - Res res; - Bool dependent; /* is there a dependent object? */ - Addr dependentObject; /* base address of dependent object */ - Seg dependentSeg = NULL; /* segment of dependent object */ - - AVERT(Arena, arena); - AVERT(AWL, awl); - AVERT(ScanState, ss); - AVERT(Format, format); - AVER(base != 0); - AVER(base < limit); - - dependentObject = awl->findDependent(base); - dependent = SegOfAddr(&dependentSeg, arena, dependentObject); - if (dependent) { - /* */ - ShieldExpose(arena, dependentSeg); - /* */ - SegSetSummary(dependentSeg, RefSetUNIV); - } - - res = (*format->scan)(&ss->ss_s, base, limit); - if (res == ResOK) - ss->scannedSize += AddrOffset(base, limit); - - if (dependent) - ShieldCover(arena, dependentSeg); - - return res; -} - - -/* awlScanSinglePass -- a single scan pass over a segment */ - -static Res awlScanSinglePass(Bool *anyScannedReturn, - ScanState ss, Pool pool, - Seg seg, Bool scanAllObjects) -{ - Addr base, limit, bufferScanLimit; - Addr p; - Addr hp; - Arena arena; - AWL awl; - AWLSeg awlseg; - Buffer buffer; - Format format; - - AVERT(ScanState, ss); - AVERT(Pool, pool); - AVERT(Seg, seg); - AVERT(Bool, scanAllObjects); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - arena = PoolArena(pool); - AVERT(Arena, arena); - - format = pool->format; - AVERT(Format, format); - - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - *anyScannedReturn = FALSE; - base = SegBase(seg); - limit = SegLimit(seg); - p = base; - buffer = SegBuffer(seg); - if (buffer != NULL && BufferScanLimit(buffer) != BufferLimit(buffer)) - bufferScanLimit = BufferScanLimit(buffer); - else - bufferScanLimit = limit; - - while(p < limit) { - Index i; /* the index into the bit tables corresponding to p */ - Addr objectLimit; - - /* */ - if (p == bufferScanLimit) { - p = BufferLimit(buffer); - continue; - } - - i = awlIndexOfAddr(base, awl, p); - if (!BTGet(awlseg->alloc, i)) { - p = AddrAdd(p, pool->alignment); - continue; - } - hp = AddrAdd(p, format->headerSize); - objectLimit = (format->skip)(hp); - /* */ - if (scanAllObjects - || (BTGet(awlseg->mark, i) && !BTGet(awlseg->scanned, i))) { - Res res = awlScanObject(arena, awl, ss, pool->format, - hp, objectLimit); - if (res != ResOK) - return res; - *anyScannedReturn = TRUE; - BTSet(awlseg->scanned, i); - } - objectLimit = AddrSub(objectLimit, format->headerSize); - AVER(p < objectLimit); - p = AddrAlignUp(objectLimit, pool->alignment); - } - AVER(p == limit); - - return ResOK; -} - - -/* AWLScan -- segment scan method for AWL */ - -static Res AWLScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) -{ - AWL awl; - AWLSeg awlseg; - Bool anyScanned; - Bool scanAllObjects; - Res res; - - AVER(totalReturn != NULL); - AVERT(ScanState, ss); - AVERT(Pool, pool); - AVERT(Seg, seg); - - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - - /* If the scanner isn't going to scan all the objects then the */ - /* summary of the unscanned objects must be added into the scan */ - /* state summary, so that it's a valid summary of the entire */ - /* segment on return. */ - - /* This pool assumes disjoint white sets and maintains mark and */ - /* scanned tables (effectively non-white and black tables) with */ - /* respect to the trace with respect to which the segment is */ - /* white. For any other trace, we cannot tell which objects */ - /* are grey and must therefore scan them all. */ - - scanAllObjects = - (TraceSetDiff(ss->traces, SegWhite(seg)) != TraceSetEMPTY); - - do { - res = awlScanSinglePass(&anyScanned, ss, pool, seg, scanAllObjects); - if (res != ResOK) { - *totalReturn = FALSE; - return res; - } - /* we are done if we scanned all the objects or if we did a pass */ - /* and didn't scan any objects (since then, no new object can have */ - /* gotten fixed) */ - } while(!scanAllObjects && anyScanned); - - *totalReturn = scanAllObjects; - AWLNoteScan(awl, seg, ss); - return ResOK; -} - - -/* AWLFix -- Fix method for AWL */ - -static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) -{ - Ref clientRef; - Addr base; - Index i; - AWL awl; - AWLSeg awlseg; - - AVERT(Pool, pool); - AVERT(ScanState, ss); - AVERT(Seg, seg); - AVER(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY); - AVER(refIO != NULL); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - clientRef = *refIO; - ss->wasMarked = TRUE; - - base = AddrSub((Addr)clientRef, pool->format->headerSize); - /* can get an ambiguous reference to close to the base of the - * segment, so when we subtract the header we are not in the - * segment any longer. This isn't a real reference, - * so we can just skip it. */ - if (base < SegBase(seg)) { - return ResOK; - } - i = awlIndexOfAddr(SegBase(seg), awl, base); - - switch(ss->rank) { - case RankAMBIG: - /* not a real pointer if not aligned or not allocated */ - if (!AddrIsAligned(base, pool->alignment) || !BTGet(awlseg->alloc, i)) - return ResOK; - /* falls through */ - case RankEXACT: - case RankFINAL: - case RankWEAK: - if (!BTGet(awlseg->mark, i)) { - ss->wasMarked = FALSE; - if (ss->rank == RankWEAK) { - *refIO = (Ref)0; - } else { - BTSet(awlseg->mark, i); - SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces)); - } - } - break; - default: - NOTREACHED; - return ResUNIMPL; - } - - return ResOK; -} - - -/* AWLReclaim -- reclaim dead objects in an AWL segment */ - -static void AWLReclaim(Pool pool, Trace trace, Seg seg) -{ - Addr base; - AWL awl; - AWLSeg awlseg; - Index i; - Count oldFree; - Format format; - Count preservedInPlaceCount = (Count)0; - Size preservedInPlaceSize = (Size)0; - Size freed; /* amount reclaimed, in bytes */ - - AVERT(Pool, pool); - AVERT(Trace, trace); - AVERT(Seg, seg); - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - format = pool->format; - - base = SegBase(seg); - - i = 0; oldFree = awlseg->free; - while(i < awlseg->grains) { - Addr p, q; - Index j; - - if(!BTGet(awlseg->alloc, i)) { - ++i; - continue; - } - p = AddrAdd(base, i << awl->alignShift); - if(SegBuffer(seg) != NULL) { - Buffer buffer = SegBuffer(seg); - - if(p == BufferScanLimit(buffer) - && BufferScanLimit(buffer) != BufferLimit(buffer)) - { - i = awlIndexOfAddr(base, awl, BufferLimit(buffer)); - continue; - } - } - q = format->skip(AddrAdd(p, format->headerSize)); - q = AddrSub(q, format->headerSize); - q = AddrAlignUp(q, pool->alignment); - j = awlIndexOfAddr(base, awl, q); - AVER(j <= awlseg->grains); - if(BTGet(awlseg->mark, i)) { - AVER(BTGet(awlseg->scanned, i)); - BTSetRange(awlseg->mark, i, j); - BTSetRange(awlseg->scanned, i, j); - ++preservedInPlaceCount; - preservedInPlaceSize += AddrOffset(p, q); - } else { - BTResRange(awlseg->mark, i, j); - BTSetRange(awlseg->scanned, i, j); - BTResRange(awlseg->alloc, i, j); - awlseg->free += j - i; - } - i = j; - } - AVER(i == awlseg->grains); - - freed = (awlseg->free - oldFree) << awl->alignShift; - awl->size -= freed; - trace->reclaimSize += freed; - trace->preservedInPlaceCount += preservedInPlaceCount; - trace->preservedInPlaceSize += preservedInPlaceSize; - SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace)); - /* @@@@ never frees a segment, see job001687. */ - return; -} - - -/* AWLAccess -- handle a barrier hit */ - -static Res AWLAccess(Pool pool, Seg seg, Addr addr, - AccessSet mode, MutatorFaultContext context) -{ - AWL awl; - Res res; - - AVERT(Pool, pool); - awl = Pool2AWL(pool); - AVERT(AWL, awl); - AVERT(Seg, seg); - AVER(SegBase(seg) <= addr); - AVER(addr < SegLimit(seg)); - AVER(SegPool(seg) == pool); - - /* Attempt scanning a single reference if permitted */ - if(AWLCanTrySingleAccess(PoolArena(pool), awl, seg, addr)) { - res = PoolSingleAccess(pool, seg, addr, mode, context); - switch(res) { - case ResOK: - AWLNoteRefAccess(awl, seg, addr); - return ResOK; - case ResFAIL: - /* Not all accesses can be managed singly. Default to segment */ - break; - default: - return res; - } - } - - /* Have to scan the entire seg anyway. */ - res = PoolSegAccess(pool, seg, addr, mode, context); - if(ResOK == res) { - AWLNoteSegAccess(awl, seg, addr); - } - - return res; -} - - -/* AWLWalk -- walk all objects */ - -static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, - void *p, size_t s) -{ - AWL awl; - AWLSeg awlseg; - Addr object, base, limit; - Format format; - - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(FUNCHECK(f)); - /* p and s are arbitrary closures and can't be checked */ - - awl = Pool2AWL(pool); - AVERT(AWL, awl); - awlseg = Seg2AWLSeg(seg); - AVERT(AWLSeg, awlseg); - - format = pool->format; - - base = SegBase(seg); - object = base; - limit = SegLimit(seg); - - while(object < limit) { - /* object is a slight misnomer because it might point to a */ - /* free grain */ - Addr next; - Index i; - - if (SegBuffer(seg) != NULL) { - Buffer buffer = SegBuffer(seg); - if (object == BufferScanLimit(buffer) - && BufferScanLimit(buffer) != BufferLimit(buffer)) { - /* skip over buffered area */ - object = BufferLimit(buffer); - continue; - } - /* since we skip over the buffered area we are always */ - /* either before the buffer, or after it, never in it */ - AVER(object < BufferGetInit(buffer) || BufferLimit(buffer) <= object); - } - i = awlIndexOfAddr(base, awl, object); - if (!BTGet(awlseg->alloc, i)) { - /* This grain is free */ - object = AddrAdd(object, pool->alignment); - continue; - } - object = AddrAdd(object, format->headerSize); - next = format->skip(object); - next = AddrSub(next, format->headerSize); - next = AddrAlignUp(next, pool->alignment); - if (BTGet(awlseg->mark, i) && BTGet(awlseg->scanned, i)) - (*f)(object, pool->format, pool, p, s); - object = next; - } -} - - -/* AWLPoolClass -- the class definition */ - -DEFINE_POOL_CLASS(AWLPoolClass, this) -{ - INHERIT_CLASS(this, AbstractCollectPoolClass); - PoolClassMixInFormat(this); - this->name = "AWL"; - this->size = sizeof(AWLStruct); - this->offset = offsetof(AWLStruct, poolStruct); - this->init = AWLInit; - this->finish = AWLFinish; - this->bufferClass = RankBufClassGet; - this->bufferFill = AWLBufferFill; - this->bufferEmpty = AWLBufferEmpty; - this->access = AWLAccess; - this->whiten = AWLWhiten; - this->grey = AWLGrey; - this->blacken = AWLBlacken; - this->scan = AWLScan; - this->fix = AWLFix; - this->fixEmergency = AWLFix; - this->reclaim = AWLReclaim; - this->walk = AWLWalk; -} - - -mps_class_t mps_class_awl(void) -{ - return (mps_class_t)AWLPoolClassGet(); -} - - -/* AWLCheck -- check an AWL pool */ - -static Bool AWLCheck(AWL awl) -{ - CHECKS(AWL, awl); - CHECKD(Pool, &awl->poolStruct); - CHECKL(awl->poolStruct.class == AWLPoolClassGet()); - CHECKL((Align)1 << awl->alignShift == awl->poolStruct.alignment); - CHECKD(Chain, awl->chain); - /* 30 is just a sanity check really, not a constraint. */ - CHECKL(0 <= awl->gen); - CHECKL(awl->gen <= 30); - /* Nothing to check about succAccesses. */ - CHECKL(FUNCHECK(awl->findDependent)); - /* Don't bother to check stats. */ - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poollo.c b/mps/code/poollo.c deleted file mode 100644 index 3ad825905a2..00000000000 --- a/mps/code/poollo.c +++ /dev/null @@ -1,859 +0,0 @@ -/* poollo.c: LEAF POOL CLASS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * DESIGN - * - * .design: See . This is a leaf pool class. - */ - -#include "mpsclo.h" -#include "mpm.h" -#include "mps.h" - -SRCID(poollo, "$Id$"); - - -#define LOGen ((Serial)1) - - -/* LOStruct -- leaf object pool instance structure */ - -#define LOSig ((Sig)0x51970B07) /* SIGnature LO POoL */ - -typedef struct LOStruct *LO; - -typedef struct LOStruct { - PoolStruct poolStruct; /* generic pool structure */ - Shift alignShift; /* log_2 of pool alignment */ - Serial gen; /* generation for placement */ - Chain chain; /* chain used by this pool */ - PoolGenStruct pgen; /* generation representing the pool */ - Sig sig; -} LOStruct; - -#define PoolPoolLO(pool) PARENT(LOStruct, poolStruct, pool) -#define LOPool(lo) (&(lo)->poolStruct) - - -/* forward declaration */ -static Bool LOCheck(LO lo); - - -/* LOGSegStruct -- LO segment structure */ - -typedef struct LOSegStruct *LOSeg; - -#define LOSegSig ((Sig)0x519705E9) /* SIGnature LO SEG */ - -typedef struct LOSegStruct { - GCSegStruct gcSegStruct; /* superclass fields must come first */ - LO lo; /* owning LO */ - BT mark; /* mark bit table */ - BT alloc; /* alloc bit table */ - Count free; /* number of free grains */ - Count newAlloc; /* number of grains allocated since last GC */ - Sig sig; /* */ -} LOSegStruct; - -#define SegLOSeg(seg) ((LOSeg)(seg)) -#define LOSegSeg(loseg) ((Seg)(loseg)) - - -/* forward decls */ -static Res loSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args); -static void loSegFinish(Seg seg); - - -/* LOSegClass -- Class definition for LO segments */ - -DEFINE_SEG_CLASS(LOSegClass, class) -{ - INHERIT_CLASS(class, GCSegClass); - SegClassMixInNoSplitMerge(class); - class->name = "LOSEG"; - class->size = sizeof(LOSegStruct); - class->init = loSegInit; - class->finish = loSegFinish; -} - - -/* LOSegCheck -- check an LO segment */ - -static Bool LOSegCheck(LOSeg loseg) -{ - CHECKS(LOSeg, loseg); - CHECKL(GCSegCheck(&loseg->gcSegStruct)); - CHECKU(LO, loseg->lo); - CHECKL(loseg->mark != NULL); - CHECKL(loseg->alloc != NULL); - /* Could check exactly how many bits are set in the alloc table. */ - CHECKL(loseg->free + loseg->newAlloc - <= SegSize(LOSegSeg(loseg)) >> loseg->lo->alignShift); - return TRUE; -} - - -/* loSegInit -- Init method for LO segments */ - -static Res loSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - SegClass super; - LOSeg loseg; - LO lo; - Res res; - Size tablebytes; /* # bytes in each control array */ - Arena arena; - /* number of bits needed in each control array */ - Count bits; - void *p; - - AVERT(Seg, seg); - loseg = SegLOSeg(seg); - AVERT(Pool, pool); - arena = PoolArena(pool); - /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); - lo = PoolPoolLO(pool); - AVERT(LO, lo); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(LOSegClass); - res = super->init(seg, pool, base, size, reservoirPermit, args); - if(res != ResOK) - return res; - - AVER(SegWhite(seg) == TraceSetEMPTY); - - bits = size >> lo->alignShift; - tablebytes = BTSize(bits); - res = ControlAlloc(&p, arena, tablebytes, reservoirPermit); - if(res != ResOK) - goto failMarkTable; - loseg->mark = p; - res = ControlAlloc(&p, arena, tablebytes, reservoirPermit); - if(res != ResOK) - goto failAllocTable; - loseg->alloc = p; - BTResRange(loseg->alloc, 0, bits); - BTSetRange(loseg->mark, 0, bits); - loseg->lo = lo; - loseg->free = bits; - loseg->newAlloc = (Count)0; - loseg->sig = LOSegSig; - AVERT(LOSeg, loseg); - return ResOK; - -failAllocTable: - ControlFree(arena, loseg->mark, tablebytes); -failMarkTable: - super->finish(seg); - return res; -} - - -/* loSegFinish -- Finish method for LO segments */ - -static void loSegFinish(Seg seg) -{ - LO lo; - LOSeg loseg; - SegClass super; - Pool pool; - Arena arena; - Size tablesize; - Count bits; - - AVERT(Seg, seg); - loseg = SegLOSeg(seg); - AVERT(LOSeg, loseg); - pool = SegPool(seg); - lo = PoolPoolLO(pool); - AVERT(LO, lo); - arena = PoolArena(pool); - - bits = SegSize(seg) >> lo->alignShift; - tablesize = BTSize(bits); - ControlFree(arena, (Addr)loseg->alloc, tablesize); - ControlFree(arena, (Addr)loseg->mark, tablesize); - loseg->sig = SigInvalid; - - /* finish the superclass fields last */ - super = SEG_SUPERCLASS(LOSegClass); - super->finish(seg); -} - - -static Count loSegBits(LOSeg loseg) -{ - LO lo; - Size size; - - AVERT(LOSeg, loseg); - - lo = loseg->lo; - AVERT(LO, lo); - size = SegSize(LOSegSeg(loseg)); - return size >> lo->alignShift; -} - - -/* Conversion between indexes and Addrs */ -#define loIndexOfAddr(base, lo, p) \ - (AddrOffset((base), (p)) >> (lo)->alignShift) - -#define loAddrOfIndex(base, lo, i) \ - (AddrAdd((base), (i) << (lo)->alignShift)) - - -/* loSegFree -- mark block from baseIndex to limitIndex free */ - -static void loSegFree(LOSeg loseg, Index baseIndex, Index limitIndex) -{ - AVERT(LOSeg, loseg); - AVER(baseIndex < limitIndex); - AVER(limitIndex <= loSegBits(loseg)); - - AVER(BTIsSetRange(loseg->alloc, baseIndex, limitIndex)); - BTResRange(loseg->alloc, baseIndex, limitIndex); - BTSetRange(loseg->mark, baseIndex, limitIndex); - loseg->free += limitIndex - baseIndex; -} - - -/* Find a free block of size size in the segment. - * Return pointer to base and limit of block (which may be - * bigger than the requested size to accommodate buffering). - */ -static Bool loSegFindFree(Addr *bReturn, Addr *lReturn, - LOSeg loseg, Size size) -{ - Index baseIndex, limitIndex; - LO lo; - Seg seg; - Count agrains; - Count bits; - Addr segBase; - - AVER(bReturn != NULL); - AVER(lReturn != NULL); - AVERT(LOSeg, loseg); - - lo = loseg->lo; - seg = LOSegSeg(loseg); - AVER(SizeIsAligned(size, LOPool(lo)->alignment)); - - /* agrains is the number of grains corresponding to the size */ - /* of the allocation request */ - agrains = size >> lo->alignShift; - AVER(agrains >= 1); - AVER(agrains <= loseg->free); - AVER(size <= SegSize(seg)); - - if(SegBuffer(seg) != NULL) { - /* Don't bother trying to allocate from a buffered segment */ - return FALSE; - } - - bits = SegSize(seg) >> lo->alignShift; - if(!BTFindLongResRange(&baseIndex, &limitIndex, loseg->alloc, - 0, bits, agrains)) { - return FALSE; - } - - /* check that BTFindLongResRange really did find enough space */ - AVER(baseIndex < limitIndex); - AVER((limitIndex-baseIndex) << lo->alignShift >= size); - segBase = SegBase(seg); - *bReturn = loAddrOfIndex(segBase, lo, baseIndex); - *lReturn = loAddrOfIndex(segBase, lo, limitIndex); - - return TRUE; -} - - -/* loSegCreate -- Creates a segment of size at least size. - * - * Segments will be ArenaAlign aligned . - */ - -static Res loSegCreate(LOSeg *loSegReturn, Pool pool, Size size, - Bool withReservoirPermit) -{ - LO lo; - Seg seg; - Res res; - SegPrefStruct segPrefStruct; - Serial gen; - Arena arena; - Size asize; /* aligned size */ - - AVER(loSegReturn != NULL); - AVERT(Pool, pool); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - lo = PoolPoolLO(pool); - AVERT(LO, lo); - - arena = PoolArena(pool); - asize = SizeAlignUp(size, ArenaAlign(arena)); - segPrefStruct = *SegPrefDefault(); - gen = lo->gen; - SegPrefExpress(&segPrefStruct, SegPrefCollected, NULL); - SegPrefExpress(&segPrefStruct, SegPrefGen, &gen); - res = SegAlloc(&seg, EnsureLOSegClass(), &segPrefStruct, - asize, pool, withReservoirPermit); - if (res != ResOK) - return res; - PoolGenUpdateZones(&lo->pgen, seg); - - *loSegReturn = SegLOSeg(seg); - return ResOK; -} - - -/* loSegReclaim -- reclaim white objects in an LO segment - * - * Could consider implementing this using Walk. - */ - -static void loSegReclaim(LOSeg loseg, Trace trace) -{ - Addr p, base, limit; - Bool marked; - Count bytesReclaimed = (Count)0; - Seg seg; - LO lo; - Format format; - Count preservedInPlaceCount = (Count)0; - Size preservedInPlaceSize = (Size)0; - - AVERT(LOSeg, loseg); - AVERT(Trace, trace); - - seg = LOSegSeg(loseg); - lo = loseg->lo; - base = SegBase(seg); - limit = SegLimit(seg); - marked = FALSE; - - format = LOPool(lo)->format; - AVERT(Format, format); - - /* i is the index of the current pointer, - * p is the actual address that is being considered. - * j and q act similarly for a pointer which is used to - * point at the end of the current object. - */ - p = base; - while(p < limit) { - Buffer buffer = SegBuffer(seg); - Addr q; - Index i; - - if(buffer != NULL) { - marked = TRUE; - if (p == BufferScanLimit(buffer) - && BufferScanLimit(buffer) != BufferLimit(buffer)) { - /* skip over buffered area */ - p = BufferLimit(buffer); - continue; - } - /* since we skip over the buffered area we are always */ - /* either before the buffer, or after it, never in it */ - AVER(p < BufferGetInit(buffer) || BufferLimit(buffer) <= p); - } - i = loIndexOfAddr(base, lo, p); - if(!BTGet(loseg->alloc, i)) { - /* This grain is free */ - p = AddrAdd(p, LOPool(lo)->alignment); - continue; - } - q = (*format->skip)(AddrAdd(p, format->headerSize)); - q = AddrSub(q, format->headerSize); - if(BTGet(loseg->mark, i)) { - marked = TRUE; - ++preservedInPlaceCount; - preservedInPlaceSize += AddrOffset(p, q); - } else { - Index j = loIndexOfAddr(base, lo, q); - /* This object is not marked, so free it */ - loSegFree(loseg, i, j); - bytesReclaimed += AddrOffset(p, q); - } - p = q; - } - AVER(p == limit); - - AVER(bytesReclaimed <= SegSize(seg)); - trace->reclaimSize += bytesReclaimed; - lo->pgen.totalSize -= bytesReclaimed; - trace->preservedInPlaceCount += preservedInPlaceCount; - trace->preservedInPlaceSize += preservedInPlaceSize; - - SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace)); - - if(!marked) { - SegFree(seg); - } -} - -/* This walks over _all_ objects in the heap, whether they are */ -/* black or white, they are still validly formatted as this is */ -/* a leaf pool, so there can't be any dangling references */ -static void LOWalk(Pool pool, Seg seg, - FormattedObjectsStepMethod f, - void *p, size_t s) -{ - Addr base; - LO lo; - LOSeg loseg; - Index i, limit; - Format format; - - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(FUNCHECK(f)); - /* p and s are arbitrary closures and can't be checked */ - - lo = PoolPoolLO(pool); - AVERT(LO, lo); - loseg = SegLOSeg(seg); - AVERT(LOSeg, loseg); - - format = pool->format; - AVERT(Format, format); - - base = SegBase(seg); - limit = SegSize(seg) >> lo->alignShift; - i = 0; - - while(i < limit) { - /* object is a slight misnomer because it might point to a */ - /* free grain */ - Addr object = loAddrOfIndex(base, lo, i); - Addr next; - Index j; - - if(SegBuffer(seg) != NULL) { - Buffer buffer = SegBuffer(seg); - if(object == BufferScanLimit(buffer) && - BufferScanLimit(buffer) != BufferLimit(buffer)) { - /* skip over buffered area */ - object = BufferLimit(buffer); - i = loIndexOfAddr(base, lo, object); - continue; - } - /* since we skip over the buffered area we are always */ - /* either before the buffer, or after it, never in it */ - AVER(object < BufferGetInit(buffer) || BufferLimit(buffer) <= object); - } - if(!BTGet(loseg->alloc, i)) { - /* This grain is free */ - ++i; - continue; - } - object = AddrAdd(object, format->headerSize); - next = (*format->skip)(object); - next = AddrSub(next, format->headerSize); - j = loIndexOfAddr(base, lo, next); - AVER(i < j); - (*f)(object, pool->format, pool, p, s); - i = j; - } -} - - -/* LOInit -- initialize an LO pool */ - -static Res LOInit(Pool pool, va_list arg) -{ - Format format; - LO lo; - Arena arena; - Res res; - static GenParamStruct loGenParam = { 1024, 0.2 }; - - AVERT(Pool, pool); - - arena = PoolArena(pool); - - format = va_arg(arg, Format); - AVERT(Format, format); - - lo = PoolPoolLO(pool); - - pool->format = format; - lo->poolStruct.alignment = format->alignment; - lo->alignShift = - SizeLog2((Size)PoolAlignment(&lo->poolStruct)); - lo->gen = LOGen; /* may be modified in debugger */ - res = ChainCreate(&lo->chain, arena, 1, &loGenParam); - if (res != ResOK) - return res; - /* .gen: This must be the nursery in the chain, because it's the only */ - /* generation. lo->gen is just a hack for segment placement. */ - res = PoolGenInit(&lo->pgen, lo->chain, 0 /* .gen */, pool); - if (res != ResOK) - goto failGenInit; - - lo->sig = LOSig; - AVERT(LO, lo); - EVENT2(PoolInitLO, pool, format); - return ResOK; - -failGenInit: - ChainDestroy(lo->chain); - return res; -} - - -/* LOFinish -- finish an LO pool */ - -static void LOFinish(Pool pool) -{ - LO lo; - Ring node, nextNode; - - AVERT(Pool, pool); - lo = PoolPoolLO(pool); - AVERT(LO, lo); - - RING_FOR(node, &pool->segRing, nextNode) { - Seg seg = SegOfPoolRing(node); - LOSeg loseg = SegLOSeg(seg); - - AVERT(LOSeg, loseg); - UNUSED(loseg); /* */ - SegFree(seg); - } - PoolGenFinish(&lo->pgen); - ChainDestroy(lo->chain); - - lo->sig = SigInvalid; -} - - -static Res LOBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, - Size size, Bool withReservoirPermit) -{ - Res res; - Ring node, nextNode; - LO lo; - LOSeg loseg; - Addr base, limit; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Pool, pool); - lo = PARENT(LOStruct, poolStruct, pool); - AVERT(LO, lo); - AVERT(Buffer, buffer); - AVER(BufferIsReset(buffer)); - AVER(BufferRankSet(buffer) == RankSetEMPTY); - AVER(size > 0); - AVER(SizeIsAligned(size, PoolAlignment(pool))); - AVER(BoolCheck(withReservoirPermit)); - - /* Try to find a segment with enough space already. */ - RING_FOR(node, &pool->segRing, nextNode) { - Seg seg = SegOfPoolRing(node); - loseg = SegLOSeg(seg); - AVERT(LOSeg, loseg); - if((loseg->free << lo->alignShift) >= size - && loSegFindFree(&base, &limit, loseg, size)) - goto found; - } - - /* No segment had enough space, so make a new one. */ - res = loSegCreate(&loseg, pool, size, withReservoirPermit); - if(res != ResOK) { - goto failCreate; - } - base = SegBase(LOSegSeg(loseg)); - limit = SegLimit(LOSegSeg(loseg)); - -found: - { - Index baseIndex, limitIndex; - Addr segBase; - - segBase = SegBase(LOSegSeg(loseg)); - /* mark the newly buffered region as allocated */ - baseIndex = loIndexOfAddr(segBase, lo, base); - limitIndex = loIndexOfAddr(segBase, lo, limit); - AVER(BTIsResRange(loseg->alloc, baseIndex, limitIndex)); - AVER(BTIsSetRange(loseg->mark, baseIndex, limitIndex)); - BTSetRange(loseg->alloc, baseIndex, limitIndex); - loseg->free -= limitIndex - baseIndex; - loseg->newAlloc += limitIndex - baseIndex; - } - - lo->pgen.totalSize += AddrOffset(base, limit); - lo->pgen.newSize += AddrOffset(base, limit); - - *baseReturn = base; - *limitReturn = limit; - return ResOK; - -failCreate: - return res; -} - - -/* Synchronise the buffer with the alloc Bit Table in the segment. */ - -static void LOBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) -{ - LO lo; - Addr base, segBase; - Seg seg; - LOSeg loseg; - Index baseIndex, initIndex, limitIndex; - - AVERT(Pool, pool); - lo = PARENT(LOStruct, poolStruct, pool); - AVERT(LO, lo); - AVERT(Buffer, buffer); - AVER(BufferIsReady(buffer)); - seg = BufferSeg(buffer); - AVERT(Seg, seg); - AVER(init <= limit); - - loseg = SegLOSeg(seg); - AVERT(LOSeg, loseg); - AVER(loseg->lo == lo); - - base = BufferBase(buffer); - segBase = SegBase(seg); - - AVER(AddrIsAligned(base, PoolAlignment(pool))); - AVER(segBase <= base); - AVER(base < SegLimit(seg)); - AVER(segBase <= init); - AVER(init <= SegLimit(seg)); - - /* convert base, init, and limit, to quantum positions */ - baseIndex = loIndexOfAddr(segBase, lo, base); - initIndex = loIndexOfAddr(segBase, lo, init); - limitIndex = loIndexOfAddr(segBase, lo, limit); - - /* Record the unused portion at the end of the buffer */ - /* as being free. */ - AVER(baseIndex == limitIndex - || BTIsSetRange(loseg->alloc, baseIndex, limitIndex)); - if(initIndex != limitIndex) { - loSegFree(loseg, initIndex, limitIndex); - lo->pgen.totalSize -= AddrOffset(init, limit); - /* All of the buffer must be new, since buffered segs are not condemned. */ - AVER(loseg->newAlloc >= limitIndex - baseIndex); - loseg->newAlloc -= limitIndex - initIndex; - lo->pgen.newSize -= AddrOffset(init, limit); - } -} - - -/* LOWhiten -- whiten a segment */ - -static Res LOWhiten(Pool pool, Trace trace, Seg seg) -{ - LO lo; - Count bits; - - AVERT(Pool, pool); - lo = PoolPoolLO(pool); - AVERT(LO, lo); - - AVERT(Trace, trace); - AVERT(Seg, seg); - AVER(SegWhite(seg) == TraceSetEMPTY); - - if(SegBuffer(seg) == NULL) { - LOSeg loseg = SegLOSeg(seg); - AVERT(LOSeg, loseg); - - bits = SegSize(seg) >> lo->alignShift; - /* Allocated objects should be whitened, free areas should */ - /* be left "black". */ - BTCopyInvertRange(loseg->alloc, loseg->mark, 0, bits); - /* @@@@ We could subtract all the free grains. */ - trace->condemned += SegSize(seg); - lo->pgen.newSize -= loseg->newAlloc << lo->alignShift; - loseg->newAlloc = (Count)0; - SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace)); - } - - return ResOK; -} - - -static Res LOFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) -{ - LO lo; - LOSeg loseg; - Ref clientRef; - Addr base; - - AVERT_CRITICAL(Pool, pool); - AVERT_CRITICAL(ScanState, ss); - AVERT_CRITICAL(Seg, seg); - AVER_CRITICAL(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY); - AVER_CRITICAL(refIO != NULL); - lo = PARENT(LOStruct, poolStruct, pool); - AVERT_CRITICAL(LO, lo); - loseg = SegLOSeg(seg); - AVERT_CRITICAL(LOSeg, loseg); - - ss->wasMarked = TRUE; /* */ - - clientRef = *refIO; - base = AddrSub((Addr)clientRef, pool->format->headerSize); - /* can get an ambiguous reference to close to the base of the - * segment, so when we subtract the header we are not in the - * segment any longer. This isn't a real reference, - * so we can just skip it. */ - if (base < SegBase(seg)) { - return ResOK; - } - - switch(ss->rank) { - case RankAMBIG: - if(!AddrIsAligned(base, PoolAlignment(pool))) { - return ResOK; - } - /* fall through */ - - case RankEXACT: - case RankFINAL: - case RankWEAK: { - Size i = AddrOffset(SegBase(seg), base) >> lo->alignShift; - - if(!BTGet(loseg->mark, i)) { - ss->wasMarked = FALSE; /* */ - if(ss->rank == RankWEAK) { - *refIO = (Addr)0; - } else { - BTSet(loseg->mark, i); - } - } - } break; - - default: - NOTREACHED; - break; - } - - return ResOK; -} - - -static void LOReclaim(Pool pool, Trace trace, Seg seg) -{ - LO lo; - LOSeg loseg; - - AVERT(Pool, pool); - lo = PoolPoolLO(pool); - AVERT(LO, lo); - - AVERT(Trace, trace); - AVERT(Seg, seg); - AVER(TraceSetIsMember(SegWhite(seg), trace)); - - loseg = SegLOSeg(seg); - loSegReclaim(loseg, trace); -} - - -/* LOPoolClass -- the class definition */ - -DEFINE_POOL_CLASS(LOPoolClass, this) -{ - INHERIT_CLASS(this, AbstractCollectPoolClass); - PoolClassMixInFormat(this); - this->name = "LO"; - this->size = sizeof(LOStruct); - this->offset = offsetof(LOStruct, poolStruct); - this->attr &= ~(AttrSCAN | AttrINCR_RB); - this->init = LOInit; - this->finish = LOFinish; - this->bufferFill = LOBufferFill; - this->bufferEmpty = LOBufferEmpty; - this->whiten = LOWhiten; - this->grey = PoolNoGrey; - this->blacken = PoolNoBlacken; - this->scan = PoolNoScan; - this->fix = LOFix; - this->fixEmergency = LOFix; - this->reclaim = LOReclaim; - this->walk = LOWalk; -} - - -/* mps_class_lo -- the external interface to get the LO pool class */ - -mps_class_t mps_class_lo(void) -{ - return (mps_class_t)EnsureLOPoolClass(); -} - - -/* LOCheck -- check an LO pool */ - -static Bool LOCheck(LO lo) -{ - CHECKS(LO, lo); - CHECKD(Pool, &lo->poolStruct); - CHECKL(lo->poolStruct.class == EnsureLOPoolClass()); - CHECKL(ShiftCheck(lo->alignShift)); - CHECKL((Align)1 << lo->alignShift == PoolAlignment(&lo->poolStruct)); - CHECKD(Chain, lo->chain); - CHECKD(PoolGen, &lo->pgen); - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c deleted file mode 100644 index 82044e37589..00000000000 --- a/mps/code/poolmfs.c +++ /dev/null @@ -1,345 +0,0 @@ -/* poolmfs.c: MANUAL FIXED SMALL UNIT POOL - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This is the implementation of the MFS pool class. - * - * DESIGN - * - * .design.misplaced: This design is misplaced, it should be in a - * separate document. - * - * MFS operates in a very simple manner: each region allocated from - * the arena is divided into units. Free units are kept on a linked - * list using a header stored in the unit itself. The linked list is - * not ordered; allocation anddeallocation simply pop and push from - * the head of the list. This is fast, but successive allocations might - * have poor locality if previous successive frees did. - * - * .restriction: This pool cannot allocate from the arena control - * pool (as the control pool is an instance of PoolClassMV and MV uses - * MFS in its implementation), nor can it allocate sub-pools, as that - * causes allocation in the control pool. - * - * Notes - * - * .freelist.fragments: The simple freelist policy might lead to poor - * locality of allocation if the list gets fragmented. - * - * .buffer.not: This pool doesn't support fast cache allocation, which - * is a shame. - */ - - -#include "poolmfs.h" -#include "mpm.h" - -SRCID(poolmfs, "$Id$"); - - -/* ROUND -- Round up - * - * Rounds n up to the nearest multiple of unit. - */ - -#define ROUND(unit, n) ((n)+(unit)-1 - ((n)+(unit)-1)%(unit)) - - -#define PoolPoolMFS(pool) PARENT(MFSStruct, poolStruct, pool) - - -/* HeaderStruct -- Freelist structure */ - -typedef struct MFSHeaderStruct { - struct MFSHeaderStruct *next; -} HeaderStruct, *Header; - - - -#define UNIT_MIN sizeof(HeaderStruct) - -MFSInfo MFSGetInfo(void) -{ - static const struct MFSInfoStruct info = - { - /* unitSizeMin */ UNIT_MIN - }; - return &info; -} - - -Pool (MFSPool)(MFS mfs) -{ - AVERT(MFS, mfs); - return &mfs->poolStruct; -} - - -static Res MFSInit(Pool pool, va_list arg) -{ - Size extendBy, unitSize; - MFS mfs; - Arena arena; - - AVER(pool != NULL); - - extendBy = va_arg(arg, Size); - unitSize = va_arg(arg, Size); - - AVER(unitSize >= UNIT_MIN); - AVER(extendBy >= unitSize); - - mfs = PoolPoolMFS(pool); - arena = PoolArena(pool); - - mfs->unroundedUnitSize = unitSize; - - unitSize = SizeAlignUp(unitSize, MPS_PF_ALIGN); - extendBy = SizeAlignUp(extendBy, ArenaAlign(arena)); - - mfs->extendBy = extendBy; - mfs->unitSize = unitSize; - mfs->unitsPerExtent = extendBy/unitSize; - mfs->freeList = NULL; - mfs->tractList = NULL; - mfs->sig = MFSSig; - - AVERT(MFS, mfs); - EVENT4(PoolInitMFS, pool, arena, extendBy, unitSize); - return ResOK; -} - - -static void MFSFinish(Pool pool) -{ - Tract tract; - MFS mfs; - - AVERT(Pool, pool); - mfs = PoolPoolMFS(pool); - AVERT(MFS, mfs); - - tract = mfs->tractList; - while(tract != NULL) { - Tract nextTract = (Tract)TractP(tract); /* .tract.chain */ - ArenaFree(TractBase(tract), mfs->extendBy, pool); - tract = nextTract; - } - - mfs->sig = SigInvalid; -} - - -/* == Allocate == - * - * Allocation simply involves taking a unit from the front of the freelist - * and returning it. If there are none, a new region is allocated from the - * arena. - */ - -static Res MFSAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit) -{ - Header f; - Res res; - MFS mfs; - - AVERT(Pool, pool); - mfs = PoolPoolMFS(pool); - AVERT(MFS, mfs); - - AVER(pReturn != NULL); - AVER(size == mfs->unroundedUnitSize); - AVER(BoolCheck(withReservoirPermit)); - - f = mfs->freeList; - - /* If the free list is empty then extend the pool with a new region. */ - - if(f == NULL) - { - Tract tract; - Word i, unitsPerExtent; - Size unitSize; - Addr base; - Header header = NULL, next; - - /* Create a new region and attach it to the pool. */ - res = ArenaAlloc(&base, SegPrefDefault(), mfs->extendBy, pool, - withReservoirPermit); - if(res != ResOK) - return res; - - /* .tract.chain: chain first tracts through TractP(tract) */ - tract = TractOfBaseAddr(PoolArena(pool), base); - TractSetP(tract, (void *)mfs->tractList); - mfs->tractList = tract; - - /* Sew together all the new empty units in the region, working down */ - /* from the top so that they are in ascending order of address on the */ - /* free list. */ - - unitsPerExtent = mfs->unitsPerExtent; - unitSize = mfs->unitSize; - next = NULL; - -#define SUB(b, s, i) ((Header)AddrAdd(b, (s)*(i))) - - for(i=0; ialignment)); - AVER(AddrAdd((Addr)header, unitSize) <= AddrAdd(base, mfs->extendBy)); - header->next = next; - next = header; - } - -#undef SUB - - /* The first unit in the region is now the head of the new free list. */ - f = header; - } - - AVER(f != NULL); - - /* Detach the first free unit from the free list and return its address. */ - - mfs->freeList = f->next; - - *pReturn = (Addr)f; - return ResOK; -} - - -/* == Free == - * - * Freeing a unit simply involves pushing it onto the front of the - * freelist. - */ - -static void MFSFree(Pool pool, Addr old, Size size) -{ - Header h; - MFS mfs; - - AVERT(Pool, pool); - mfs = PoolPoolMFS(pool); - AVERT(MFS, mfs); - - AVER(old != (Addr)0); - AVER(size == mfs->unroundedUnitSize); - - /* .freelist.fragments */ - h = (Header)old; - h->next = mfs->freeList; - mfs->freeList = h; -} - - -static Res MFSDescribe(Pool pool, mps_lib_FILE *stream) -{ - MFS mfs; - Res res; - - AVERT(Pool, pool); - mfs = PoolPoolMFS(pool); - AVERT(MFS, mfs); - - AVER(stream != NULL); - - res = WriteF(stream, - " unrounded unit size $W\n", (WriteFW)mfs->unroundedUnitSize, - " unit size $W\n", (WriteFW)mfs->unitSize, - " extent size $W\n", (WriteFW)mfs->extendBy, - " units per extent $U\n", (WriteFU)mfs->unitsPerExtent, - " free list begins at $P\n", (WriteFP)mfs->freeList, - " tract list begin at $P\n", (WriteFP)mfs->tractList, - NULL); - if(res != ResOK) return res; - - return ResOK; -} - - -DEFINE_POOL_CLASS(MFSPoolClass, this) -{ - INHERIT_CLASS(this, AbstractAllocFreePoolClass); - this->name = "MFS"; - this->size = sizeof(MFSStruct); - this->offset = offsetof(MFSStruct, poolStruct); - this->init = MFSInit; - this->finish = MFSFinish; - this->alloc = MFSAlloc; - this->free = MFSFree; - this->describe = MFSDescribe; -} - - -PoolClass PoolClassMFS(void) -{ - return EnsureMFSPoolClass(); -} - - -Bool MFSCheck(MFS mfs) -{ - Arena arena; - - CHECKS(MFS, mfs); - CHECKD(Pool, &mfs->poolStruct); - CHECKL(mfs->poolStruct.class == EnsureMFSPoolClass()); - CHECKL(mfs->unroundedUnitSize >= UNIT_MIN); - CHECKL(mfs->extendBy >= UNIT_MIN); - arena = PoolArena(&mfs->poolStruct); - CHECKL(SizeIsAligned(mfs->extendBy, ArenaAlign(arena))); - CHECKL(SizeAlignUp(mfs->unroundedUnitSize, mfs->poolStruct.alignment) == - mfs->unitSize); - CHECKL(mfs->unitsPerExtent == mfs->extendBy/mfs->unitSize); - if(mfs->tractList != NULL) { - CHECKL(TractCheck(mfs->tractList)); - } - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmfs.h b/mps/code/poolmfs.h deleted file mode 100644 index f77f7ef0e14..00000000000 --- a/mps/code/poolmfs.h +++ /dev/null @@ -1,91 +0,0 @@ -/* poolmfs.h: MANUAL FIXED SMALL UNIT POOL - * - * $Id$ - * - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * The MFS pool is used to manage small fixed-size chunks of memory. It - * stores control structures in the memory it manages, rather than to one - * side. It therefore achieves better locality for small objects, but - * wastes memory for large objects. It should not be used unless you are - * packing a reasonable number of objects on to a page. - * - * Create and Init take the following arguments: - * - * Size extendBy - * - * extendBy is the default number of bytes reserved by the pool at a time. - * A large size will make allocation cheaper but have a higher resource - * overhead. A typical value might be 65536. See note 2. - * - * Size unitSize - * - * unitSize is the size in bytes of the objects you with to allocate. It - * must be larger than the minimum unit size returned by GetInfo, and not - * larger than extendBy. - */ - -#ifndef poolmfs_h -#define poolmfs_h - -#include "mpm.h" - -typedef struct MFSStruct *MFS; - -extern PoolClass PoolClassMFS(void); - -extern Bool MFSCheck(MFS mfs); -extern Pool (MFSPool)(MFS mfs); - - -typedef const struct MFSInfoStruct *MFSInfo; - -struct MFSInfoStruct { - Size unitSizeMin; /* minimum unit size */ -}; - -extern MFSInfo MFSGetInfo(void); - -#endif /* poolmfs_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmrg.c b/mps/code/poolmrg.c deleted file mode 100644 index 298e5f7788f..00000000000 --- a/mps/code/poolmrg.c +++ /dev/null @@ -1,907 +0,0 @@ -/* poolmrg.c: MANUAL RANK GUARDIAN POOL - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * - * DESIGN - * - * .design: See . - * - * NOTES - * - * .improve.rank: At the moment, the pool is a guardian for the final - * rank. It could be generalized to be a guardian for an arbitrary - * rank (a guardian for RankEXACT would tell you if the object was - * ambiguously referenced, for example). The code that would need to be - * modified bears this tag. - * - * TRANSGRESSIONS - * - * .addr.void-star: Breaks all over the place, - * accessing the segments acquired from SegAlloc with C pointers. It - * would not be practical to use ArenaPeek/Poke everywhere. Blocks - * acquired from ControlAlloc must be directly accessible from C, or else - * none of the pools would work. Therefore, if we implement a variant - * where Addr != void*, we just use the same magic for the control pool - * and MRG pools, whatever that might be. - */ - -#include "ring.h" -#include "mpm.h" -#include "poolmrg.h" - -SRCID(poolmrg, "$Id$"); - - -/* Types */ - -/* enumerate the states of a guardian */ -enum { - MRGGuardianFREE = 1, - MRGGuardianPREFINAL, - MRGGuardianFINAL -}; - - -/* Link -- Unprotectable part of guardian */ - -typedef struct LinkStruct *Link; -typedef struct LinkStruct { - int state; /* Free, Prefinal, Final */ - union { - MessageStruct messageStruct; /* state = Final */ - RingStruct linkRing; /* state one of {Free, Prefinal} */ - } the; -} LinkStruct; - -#define linkOfMessage(message) \ - PARENT(LinkStruct, the.messageStruct, (message)) - -#define linkOfRing(ring) \ - PARENT(LinkStruct, the.linkRing, (ring)) - - -/* RefPart -- Protectable part of guardian - * - * This is trivial, but provides a useful abstraction - * at no performance cost. - */ -typedef struct RefPartStruct *RefPart; -typedef struct RefPartStruct { - Ref ref; -} RefPartStruct; - - -/* MRGRefPartRef,MRGRefPartSetRef -- Peek and poke the reference - * - * Might be more efficient to take a seg, rather than calculate it - * every time. - * - * See also .ref.direct which accesses it directly. - */ -static Ref MRGRefPartRef(Arena arena, RefPart refPart) -{ - Ref ref; - - AVER(refPart != NULL); - - ref = ArenaPeek(arena, &refPart->ref); - return ref; -} - -static Ref *MRGRefPartRefAddr(RefPart refPart) -{ - AVER(refPart != NULL); - - return &refPart->ref; -} - -static void MRGRefPartSetRef(Arena arena, RefPart refPart, Ref ref) -{ - AVER(refPart != NULL); - - ArenaPoke(arena, &refPart->ref, ref); -} - - -/* MRGStruct -- MRG pool structure */ - -#define MRGSig ((Sig)0x519369B0) /* SIGnature MRG POol */ - -typedef struct MRGStruct { - PoolStruct poolStruct; /* generic pool structure */ - RingStruct entryRing; /* */ - RingStruct freeRing; /* */ - RingStruct refRing; /* */ - Size extendBy; /* */ - Sig sig; /* */ -} MRGStruct; - -#define Pool2MRG(pool) PARENT(MRGStruct, poolStruct, pool) -#define MRG2Pool(mrg) (&(mrg)->poolStruct) - - -/* MRGCheck -- check an MRG pool */ - -static Bool MRGCheck(MRG mrg) -{ - CHECKS(MRG, mrg); - CHECKD(Pool, &mrg->poolStruct); - CHECKL(MRG2Pool(mrg)->class == PoolClassMRG()); - CHECKL(RingCheck(&mrg->entryRing)); - CHECKL(RingCheck(&mrg->freeRing)); - CHECKL(RingCheck(&mrg->refRing)); - CHECKL(mrg->extendBy == ArenaAlign(PoolArena(MRG2Pool(mrg)))); - return TRUE; -} - - -#define MRGRefSegSig ((Sig)0x51936965) /* SIGnature MRG Ref Seg */ -#define MRGLinkSegSig ((Sig)0x51936915) /* SIGnature MRG Link Seg */ - -typedef struct MRGLinkSegStruct *MRGLinkSeg; -typedef struct MRGRefSegStruct *MRGRefSeg; - -typedef struct MRGLinkSegStruct { - SegStruct segStruct; /* superclass fields must come first */ - MRGRefSeg refSeg; /* */ - Sig sig; /* */ -} MRGLinkSegStruct; - -typedef struct MRGRefSegStruct { - GCSegStruct gcSegStruct; /* superclass fields must come first */ - RingStruct mrgRing; /* */ - MRGLinkSeg linkSeg; /* */ - Sig sig; /* */ -} MRGRefSegStruct; - -/* macros to get between child and parent seg structures */ - -#define Seg2LinkSeg(seg) ((MRGLinkSeg)(seg)) -#define LinkSeg2Seg(linkseg) ((Seg)(linkseg)) - -#define Seg2RefSeg(seg) ((MRGRefSeg)(seg)) -#define RefSeg2Seg(refseg) ((Seg)(refseg)) - - -/* forward declarations */ - -static SegClass MRGLinkSegClassGet(void); -static SegClass MRGRefSegClassGet(void); - - -/* MRGLinkSegCheck -- check a link segment - * - * .link.nullref: During initialization of a link segment the refSeg - * field will be NULL. This will be initialized when the reference - * segment is initialized. See . - */ -static Bool MRGLinkSegCheck(MRGLinkSeg linkseg) -{ - Seg seg; - - CHECKS(MRGLinkSeg, linkseg); - CHECKL(SegCheck(&linkseg->segStruct)); - seg = LinkSeg2Seg(linkseg); - if (NULL != linkseg->refSeg) { /* see .link.nullref */ - CHECKL(SegPool(seg) == SegPool(RefSeg2Seg(linkseg->refSeg))); - CHECKU(MRGRefSeg, linkseg->refSeg); - CHECKL(linkseg->refSeg->linkSeg == linkseg); - } - return TRUE; -} - -static Bool MRGRefSegCheck(MRGRefSeg refseg) -{ - Seg seg; - - CHECKS(MRGRefSeg, refseg); - CHECKL(GCSegCheck(&refseg->gcSegStruct)); - seg = RefSeg2Seg(refseg); - CHECKL(SegPool(seg) == SegPool(LinkSeg2Seg(refseg->linkSeg))); - CHECKL(RingCheck(&refseg->mrgRing)); - CHECKD(MRGLinkSeg, refseg->linkSeg); - CHECKL(refseg->linkSeg->refSeg == refseg); - return TRUE; -} - - -/* MRGLinkSegInit -- initialise a link segment */ - -static Res MRGLinkSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - SegClass super; - MRGLinkSeg linkseg; - MRG mrg; - Res res; - - AVERT(Seg, seg); - linkseg = Seg2LinkSeg(seg); - AVERT(Pool, pool); - mrg = Pool2MRG(pool); - AVERT(MRG, mrg); - /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(MRGLinkSegClass); - res = super->init(seg, pool, base, size, reservoirPermit, args); - if (res != ResOK) - return res; - linkseg->refSeg = NULL; /* .link.nullref */ - linkseg->sig = MRGLinkSegSig; - AVERT(MRGLinkSeg, linkseg); - - return ResOK; -} - - -/* MRGRefSegInit -- initialise a ref segment - * - * .ref.initarg: The paired link segment is passed as an additional - * (vararg) parameter when creating the ref segment. Initially the - * refSeg field of the link segment is NULL (see .link.nullref). - * It's initialized here to the newly initialized ref segment. - */ -static Res MRGRefSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - MRGLinkSeg linkseg = va_arg(args, MRGLinkSeg); /* .ref.initarg */ - MRGRefSeg refseg; - MRG mrg; - SegClass super; - Res res; - - AVERT(Seg, seg); - refseg = Seg2RefSeg(seg); - AVERT(Pool, pool); - mrg = Pool2MRG(pool); - AVERT(MRG, mrg); - /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); - AVERT(MRGLinkSeg, linkseg); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(MRGRefSegClass); - res = super->init(seg, pool, base, size, reservoirPermit, args); - if (res != ResOK) - return res; - - /* , .improve.rank */ - SegSetRankSet(seg, RankSetSingle(RankFINAL)); - - RingInit(&refseg->mrgRing); - RingAppend(&mrg->refRing, &refseg->mrgRing); - refseg->linkSeg = linkseg; - AVER(NULL == linkseg->refSeg); /* .link.nullref */ - refseg->sig = MRGRefSegSig; - linkseg->refSeg = refseg; /* .ref.initarg */ - - AVERT(MRGRefSeg, refseg); - AVERT(MRGLinkSeg, linkseg); - - return ResOK; -} - - -/* MRGLinkSegClass -- Class definition */ - -DEFINE_SEG_CLASS(MRGLinkSegClass, class) -{ - INHERIT_CLASS(class, SegClass); - SegClassMixInNoSplitMerge(class); /* no support for this */ - class->name = "MRGLSEG"; - class->size = sizeof(MRGLinkSegStruct); - class->init = MRGLinkSegInit; -} - - -/* MRGRefSegClass -- Class definition */ - -DEFINE_SEG_CLASS(MRGRefSegClass, class) -{ - INHERIT_CLASS(class, GCSegClass); - SegClassMixInNoSplitMerge(class); /* no support for this */ - class->name = "MRGRSEG"; - class->size = sizeof(MRGRefSegStruct); - class->init = MRGRefSegInit; -} - - -static Count MRGGuardiansPerSeg(MRG mrg) -{ - Count nGuardians; - AVERT(MRG, mrg); - - nGuardians = mrg->extendBy / sizeof(Ref); - AVER(nGuardians > 0); - - return nGuardians; -} - - -/* */ - - -#define refPartOfIndex(refseg, index) \ - ((RefPart)SegBase(RefSeg2Seg(refseg)) + (index)) - - -static RefPart MRGRefPartOfLink(Link link, Arena arena) -{ - Seg seg = NULL; /* suppress "may be used uninitialized" */ - Bool b; - Link linkBase; - Index index; - MRGLinkSeg linkseg; - - AVER(link != NULL); /* Better checks done by SegOfAddr */ - - b = SegOfAddr(&seg, arena, (Addr)link); - AVER(b); - AVER(SegPool(seg)->class == PoolClassMRG()); - linkseg = Seg2LinkSeg(seg); - AVERT(MRGLinkSeg, linkseg); - linkBase = (Link)SegBase(seg); - AVER(link >= linkBase); - index = (Index)(link - linkBase); - AVER(index < MRGGuardiansPerSeg(Pool2MRG(SegPool(seg)))); - - return refPartOfIndex(linkseg->refSeg, index); -} - - -#define linkOfIndex(linkseg, index) \ - ((Link)SegBase(LinkSeg2Seg(linkseg)) + (index)) - - -#if 0 -static Link MRGLinkOfRefPart(RefPart refPart, Arena arena) -{ - Seg seg; - Bool b; - RefPart refPartBase; - Index index; - MRGRefSeg refseg; - - AVER(refPart != NULL); /* Better checks done by SegOfAddr */ - - b = SegOfAddr(&seg, arena, (Addr)refPart); - AVER(b); - AVER(SegPool(seg)->class == PoolClassMRG()); - refseg = Seg2RefSeg(seg); - AVERT(MRGRefSeg, refseg); - refPartBase = (RefPart)SegBase(seg); - AVER(refPart >= refPartBase); - index = refPart - refPartBase; - AVER(index < MRGGuardiansPerSeg(Pool2MRG(SegPool(seg)))); - - return linkOfIndex(refseg->linkSeg, index); -} -#endif - - -/* MRGGuardianInit -- Initialises both parts of a guardian */ - -static void MRGGuardianInit(MRG mrg, Link link, RefPart refPart) -{ - AVERT(MRG, mrg); - AVER(link != NULL); - AVER(refPart != NULL); - - RingInit(&link->the.linkRing); - link->state = MRGGuardianFREE; - RingAppend(&mrg->freeRing, &link->the.linkRing); - /* */ - MRGRefPartSetRef(PoolArena(&mrg->poolStruct), refPart, 0); -} - - -/* MRGMessage* -- Implementation of MRG's MessageClass */ - - -/* MRGMessageDelete -- deletes the message (frees up the guardian) */ - -static void MRGMessageDelete(Message message) -{ - Pool pool = NULL; /* suppress "may be used uninitialized" */ - Arena arena; - Link link; - Bool b; - - AVERT(Message, message); - - arena = MessageArena(message); - b = PoolOfAddr(&pool, arena, (Addr)message); - AVER(b); - AVER(pool->class == PoolClassMRG()); - - link = linkOfMessage(message); - AVER(link->state == MRGGuardianFINAL); - MessageFinish(message); - MRGGuardianInit(Pool2MRG(pool), link, MRGRefPartOfLink(link, arena)); -} - - -/* MRGMessageFinalizationRef -- extract the finalized reference from the msg */ - -static void MRGMessageFinalizationRef(Ref *refReturn, - Arena arena, Message message) -{ - Ref *refp; - Link link; - Ref ref; - RefPart refPart; - - AVER(refReturn != NULL); - AVERT(Arena, arena); - AVERT(Message, message); - - AVER(MessageGetType(message) == MessageTypeFINALIZATION); - - link = linkOfMessage(message); - AVER(link->state == MRGGuardianFINAL); - refPart = MRGRefPartOfLink(link, arena); - - refp = MRGRefPartRefAddr(refPart); - - /* ensure that the reference is not (white and flipped) */ - ref = ArenaRead(arena, refp); - - AVER(ref != 0); - *refReturn = ref; -} - - -static MessageClassStruct MRGMessageClassStruct = { - MessageClassSig, /* sig */ - "MRGFinal", /* name */ - MessageTypeFINALIZATION, /* Message Type */ - MRGMessageDelete, /* Delete */ - MRGMessageFinalizationRef, /* FinalizationRef */ - MessageNoGCLiveSize, /* GCLiveSize */ - MessageNoGCCondemnedSize, /* GCCondemnedSize */ - MessageNoGCNotCondemnedSize, /* GCNotCondemnedSize */ - MessageNoGCStartWhy, /* GCStartWhy */ - MessageClassSig /* */ -}; - - -/* MRGSegPairDestroy --- Destroys a pair of segments (link & ref) - * - * .segpair.destroy: We don't worry about the effect that destroying - * these segs has on any of the pool rings. - */ -static void MRGSegPairDestroy(MRGRefSeg refseg) -{ - RingRemove(&refseg->mrgRing); - RingFinish(&refseg->mrgRing); - refseg->sig = SigInvalid; - SegFree(LinkSeg2Seg(refseg->linkSeg)); - SegFree(RefSeg2Seg(refseg)); -} - - -/* MRGSegPairCreate -- create a pair of segments (link & ref) */ - -static Res MRGSegPairCreate(MRGRefSeg *refSegReturn, MRG mrg, - Bool withReservoirPermit) -{ - RefPart refPartBase; - Count nGuardians; /* guardians per seg */ - Index i; - Link linkBase; - Pool pool; - Res res; - Seg segLink, segRefPart; - MRGLinkSeg linkseg; - MRGRefSeg refseg; - Size linkSegSize; - Arena arena; - - AVER(refSegReturn != NULL); - - pool = MRG2Pool(mrg); - arena = PoolArena(pool); - - nGuardians = MRGGuardiansPerSeg(mrg); - linkSegSize = nGuardians * sizeof(LinkStruct); - linkSegSize = SizeAlignUp(linkSegSize, ArenaAlign(arena)); - - res = SegAlloc(&segLink, EnsureMRGLinkSegClass(), - SegPrefDefault(), linkSegSize, pool, - withReservoirPermit); - if (res != ResOK) - goto failLinkSegAlloc; - linkseg = Seg2LinkSeg(segLink); - - res = SegAlloc(&segRefPart, EnsureMRGRefSegClass(), - SegPrefDefault(), mrg->extendBy, pool, - withReservoirPermit, - linkseg); /* .ref.initarg */ - if (res != ResOK) - goto failRefPartSegAlloc; - refseg = Seg2RefSeg(segRefPart); - - linkBase = (Link)SegBase(segLink); - refPartBase = (RefPart)SegBase(segRefPart); - - for(i = 0; i < nGuardians; ++i) - MRGGuardianInit(mrg, linkBase + i, refPartBase + i); - AVER((Addr)(&linkBase[i]) <= SegLimit(segLink)); - AVER((Addr)(&refPartBase[i]) <= SegLimit(segRefPart)); - - *refSegReturn = refseg; - - return ResOK; - -failRefPartSegAlloc: - SegFree(segLink); -failLinkSegAlloc: - return res; -} - - -/* MRGFinalize -- finalize the indexth guardian in the segment */ - -static void MRGFinalize(Arena arena, MRGLinkSeg linkseg, Index index) -{ - Link link; - Message message; - - AVER(index < MRGGuardiansPerSeg(Pool2MRG(SegPool(LinkSeg2Seg(linkseg))))); - - link = linkOfIndex(linkseg, index); - - /* only finalize it if it hasn't been finalized already */ - if (link->state != MRGGuardianFINAL) { - AVER(link->state == MRGGuardianPREFINAL); - RingRemove(&link->the.linkRing); - RingFinish(&link->the.linkRing); - link->state = MRGGuardianFINAL; - message = &link->the.messageStruct; - MessageInit(arena, message, &MRGMessageClassStruct, MessageTypeFINALIZATION); - MessagePost(arena, message); - } -} - - -static Res MRGRefSegScan(ScanState ss, MRGRefSeg refseg, MRG mrg) -{ - Res res; - Arena arena; - MRGLinkSeg linkseg; - - RefPart refPart; - Index i; - Count nGuardians; - - AVERT(ScanState, ss); - AVERT(MRGRefSeg, refseg); - AVERT(MRG, mrg); - - arena = PoolArena(MRG2Pool(mrg)); - linkseg = refseg->linkSeg; - - nGuardians = MRGGuardiansPerSeg(mrg); - AVER(nGuardians > 0); - TRACE_SCAN_BEGIN(ss) { - for(i=0; i < nGuardians; ++i) { - refPart = refPartOfIndex(refseg, i); - - /* free guardians are not scanned */ - if (linkOfIndex(linkseg, i)->state != MRGGuardianFREE) { - ss->wasMarked = TRUE; - /* .ref.direct: We can access the reference directly */ - /* because we are in a scan and the shield is exposed. */ - if (TRACE_FIX1(ss, refPart->ref)) { - res = TRACE_FIX2(ss, &(refPart->ref)); - if (res != ResOK) - return res; - - if (ss->rank == RankFINAL && !ss->wasMarked) { /* .improve.rank */ - MRGFinalize(arena, linkseg, i); - } - } - } - } - } TRACE_SCAN_END(ss); - - return ResOK; -} - - -/* MRGInit -- init method for MRG */ - -static Res MRGInit(Pool pool, va_list args) -{ - MRG mrg; - - AVER(pool != NULL); /* Can't check more; see pool contract @@@@ */ - UNUSED(args); - - mrg = Pool2MRG(pool); - - RingInit(&mrg->entryRing); - RingInit(&mrg->freeRing); - RingInit(&mrg->refRing); - mrg->extendBy = ArenaAlign(PoolArena(pool)); - mrg->sig = MRGSig; - - AVERT(MRG, mrg); - DIAG_PRINTF(( "mrg->extendBy = %u, MRGGuardiansPerSeg = %u\n", - (unsigned int) mrg->extendBy, - (unsigned int) MRGGuardiansPerSeg(mrg) )); - EVENT3(PoolInit, pool, PoolArena(pool), ClassOfPool(pool)); - return ResOK; -} - - -/* MRGFinish -- finish a MRG pool */ - -static void MRGFinish(Pool pool) -{ - MRG mrg; - Ring node, nextNode; - - AVERT(Pool, pool); - mrg = Pool2MRG(pool); - AVERT(MRG, mrg); - - /* .finish.ring: Before destroying the segments, we isolate the */ - /* rings in the pool structure. The problem we are avoiding here */ - /* is when the rings point to memory that has been unmapped by one */ - /* segPairDestroy and a subsequent segPairDestroy calls MRGCheck which */ - /* checks the rings which causes the program to fault because */ - /* RingCheck will access unmapped memory. */ - - /* We call RingRemove on the master node for the rings, thereby */ - /* effectively emptying them, but leaving the rest of the ring */ - /* "dangling". This is okay as we are about to destroy all the */ - /* segments so the contents of the rings will dissappear soon. */ - - /* .finish.no-final: Note that this relies on the fact that no */ - /* Guardians are in the FINAL state and hence on the Arena Message */ - /* Queue. We are guaranteed this because MRGFinish is only called */ - /* from ArenaDestroy, and the message queue has been emptied prior */ - /* to the call. See */ - - if (!RingIsSingle(&mrg->entryRing)) { - RingRemove(&mrg->entryRing); - } - if (!RingIsSingle(&mrg->freeRing)) { - RingRemove(&mrg->freeRing); - } - - RING_FOR(node, &mrg->refRing, nextNode) { - MRGRefSeg refseg = RING_ELT(MRGRefSeg, mrgRing, node); - MRGSegPairDestroy(refseg); - } - - mrg->sig = SigInvalid; - RingFinish(&mrg->refRing); - /* */ -} - - -/* MRGRegister -- register an object for finalization */ - -Res MRGRegister(Pool pool, Ref ref) -{ - Ring freeNode; - Arena arena; - Link link; - RefPart refPart; - MRG mrg; - Res res; - MRGRefSeg junk; /* unused */ - - AVERT(Pool, pool); - AVER(ref != 0); - - mrg = Pool2MRG(pool); - AVERT(MRG, mrg); - - arena = PoolArena(pool); - AVERT(Arena, arena); - - /* */ - if (RingIsSingle(&mrg->freeRing)) { - /* @@@@ Should the client be able to use the reservoir for this? */ - res = MRGSegPairCreate(&junk, mrg, /* withReservoirPermit */ FALSE); - if (res != ResOK) - return res; - } - AVER(!RingIsSingle(&mrg->freeRing)); - freeNode = RingNext(&mrg->freeRing); - - link = linkOfRing(freeNode); - AVER(link->state == MRGGuardianFREE); - /* */ - RingRemove(freeNode); - link->state = MRGGuardianPREFINAL; - RingAppend(&mrg->entryRing, freeNode); - - /* */ - refPart = MRGRefPartOfLink(link, arena); - MRGRefPartSetRef(arena, refPart, ref); - - return ResOK; -} - - -/* MRGDeregister -- deregister (once) an object for finalization */ - -Res MRGDeregister(Pool pool, Ref obj) -{ - Ring node, nextNode; - Count nGuardians; /* guardians per seg */ - Arena arena; - MRG mrg; - - AVERT(Pool, pool); - /* Can't check obj */ - - mrg = Pool2MRG(pool); - AVERT(MRG, mrg); - nGuardians = MRGGuardiansPerSeg(mrg); - arena = PoolArena(pool); - - /* map over the segments */ - RING_FOR(node, &mrg->refRing, nextNode) { - MRGRefSeg refSeg = RING_ELT(MRGRefSeg, mrgRing, node); - MRGLinkSeg linkSeg; - Count i; - Link link; - RefPart refPart; - - AVERT(MRGRefSeg, refSeg); - linkSeg = refSeg->linkSeg; - /* map over each guardian in the segment */ - for(i = 0, link = (Link)SegBase(LinkSeg2Seg(linkSeg)), - refPart = (RefPart)SegBase(RefSeg2Seg(refSeg)); - i < nGuardians; - ++i, ++link, ++refPart) { - /* check if it's allocated and points to obj */ - if (link->state == MRGGuardianPREFINAL - && MRGRefPartRef(arena, refPart) == obj) { - RingRemove(&link->the.linkRing); - RingFinish(&link->the.linkRing); - MRGGuardianInit(mrg, link, refPart); - return ResOK; - } - } - } - return ResFAIL; -} - - -/* MRGDescribe -- describe an MRG pool - * - * This could be improved by implementing MRGSegDescribe - * and having MRGDescribe iterate over all the pool's segments. - */ -static Res MRGDescribe(Pool pool, mps_lib_FILE *stream) -{ - MRG mrg; - Arena arena; - Ring node, nextNode; - RefPart refPart; - Res res; - - if (!TESTT(Pool, pool)) return ResFAIL; - mrg = Pool2MRG(pool); - if (!TESTT(MRG, mrg)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - arena = PoolArena(pool); - res = WriteF(stream, " extendBy $W\n", mrg->extendBy, NULL); - if (res != ResOK) return res; - res = WriteF(stream, " Entry queue:\n", NULL); - if (res != ResOK) return res; - RING_FOR(node, &mrg->entryRing, nextNode) { - refPart = MRGRefPartOfLink(linkOfRing(node), arena); - res = WriteF(stream, " at $A Ref $A\n", - (WriteFA)refPart, (WriteFA)MRGRefPartRef(arena, refPart), - NULL); - if (res != ResOK) return res; - } - - return ResOK; -} - - -static Res MRGScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) -{ - MRG mrg; - Res res; - MRGRefSeg refseg; - - AVERT(ScanState, ss); - AVERT(Pool, pool); - AVERT(Seg, seg); - - mrg = Pool2MRG(pool); - AVERT(MRG, mrg); - - AVER(SegRankSet(seg) == RankSetSingle(RankFINAL)); /* .improve.rank */ - AVER(TraceSetInter(SegGrey(seg), ss->traces) != TraceSetEMPTY); - refseg = Seg2RefSeg(seg); - AVERT(MRGRefSeg, refseg); - - res = MRGRefSegScan(ss, refseg, mrg); - if (res != ResOK) { - *totalReturn = FALSE; - return res; - } - - *totalReturn = TRUE; - return ResOK; -} - - -DEFINE_POOL_CLASS(MRGPoolClass, this) -{ - INHERIT_CLASS(this, AbstractPoolClass); - this->name = "MRG"; - this->size = sizeof(MRGStruct); - this->offset = offsetof(MRGStruct, poolStruct); - this->attr |= (AttrSCAN | AttrFREE | AttrINCR_RB); - this->init = MRGInit; - this->finish = MRGFinish; - this->grey = PoolTrivGrey; - this->blacken = PoolTrivBlacken; - this->scan = MRGScan; - this->describe = MRGDescribe; -} - - -PoolClass PoolClassMRG(void) -{ - return MRGPoolClassGet(); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmrg.h b/mps/code/poolmrg.h deleted file mode 100644 index 65e01f2da4d..00000000000 --- a/mps/code/poolmrg.h +++ /dev/null @@ -1,61 +0,0 @@ -/* poolmrg.h: MANUAL RANK GUARDIAN POOL CLASS INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - */ - -#ifndef poolmrg_h -#define poolmrg_h - -#include "mpmtypes.h" - -typedef struct MRGStruct *MRG; - -extern PoolClass PoolClassMRG(void); -extern Res MRGRegister(Pool, Ref); -extern Res MRGDeregister(Pool, Ref); - -#endif /* poolmrg_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c deleted file mode 100644 index 91740271dd0..00000000000 --- a/mps/code/poolmv.c +++ /dev/null @@ -1,906 +0,0 @@ -/* poolmv.c: MANUAL VARIABLE POOL - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * **** RESTRICTION: This pool may not allocate from the arena control - * pool, since it is used to implement that pool. - * - * An observation: Freeing memory introduces more information - * into the system than allocating it. This causes the problem - * described in note 2. - * - * Notes - * 1. Need to measure typical fragmentation levels and adjust the - * blockExtendBy parameter appropriately. richard 1994-11-08 - * 2. free can lose memory if it can't allocate a block descriptor. The - * memory could be pushed onto a special chain to be reclaimed later. - * richard 1994-11-09 - * 3. The span chain could be adaptive. richard 1994-11-09 - * 5. An MFS pool for the block descriptors is justified, but not really - * for the spans, which are much rarer. richard 1994-11-09 - * 8. By changing MVSpanAlloc it might be possible to keep track of all - * allocated blocks using descriptors, for debugging purposes. richard - * 1994-11-10 - */ - -#include "mpscmv.h" -#include "dbgpool.h" -#include "poolmv.h" -#include "poolmfs.h" -#include "mpm.h" - -SRCID(poolmv, "$Id$"); - - -#define mvBlockPool(mv) MFSPool(&(mv)->blockPoolStruct) -#define mvSpanPool(mv) MFSPool(&(mv)->spanPoolStruct) - - -#define Pool2MV(pool) PARENT(MVStruct, poolStruct, pool) - - -/* MVDebug -- MV Debug pool class */ - -typedef struct MVDebugStruct { - MVStruct MVStruct; /* MV structure */ - PoolDebugMixinStruct debug; /* debug mixin */ -} MVDebugStruct; - -typedef MVDebugStruct *MVDebug; - - -#define MV2MVDebug(mv) PARENT(MVDebugStruct, MVStruct, mv) -#define MVDebug2MV(mvd) (&((mvd)->MVStruct)) - - -/* MVBlockStruct -- block structure - * - * The pool maintains a descriptor structure for each contiguous - * allocated block of memory it manages. The descriptor is on a simple - * linked-list of such descriptors, which is in ascending order of - * address. - */ - -typedef struct MVBlockStruct *MVBlock; -typedef struct MVBlockStruct { - MVBlock next; - Addr base, limit; -} MVBlockStruct; - - -/* MVBlockCheck -- check the consistency of a block structure */ - -static Bool MVBlockCheck(MVBlock block) -{ - AVER(block != NULL); - AVER(block->limit >= block->base); - /* Check that it is in the block pool. See note 7. */ - /* This turns out to be considerably tricky, as we cannot get hold */ - /* of the blockPool (pool is not a parameter). */ - return TRUE; -} - - -/* MVSpanStruct -- span structure - * - * The pool maintains a wrapper for each span allocated from the arena - * which contains a chain of descriptors for the allocated memory in that - * span. It also contains sentinel block descriptors which mark the - * start and end of the span. These blocks considerably simplify - * allocation, and may be zero-sized. - * - * .design.largest: If 'largestKnown' is TRUE, 'largest' is the size - * of the largest free block in the span. Otherwise, 'largest' is - * one more than the span size. - * - * .design.largest.alloc: When seeking a span in which to allocate, - * a span should not be examined if 'largest' is less than the - * space sought. - * - * .design.largest.free: When freeing, compute the size of the new - * free area. If it is larger than 'largest', set 'largest' to it. - */ - -#define MVSpanSig ((Sig)0x5193F5BA) /* SIGnature MV SPAn */ - -typedef struct MVSpanStruct *MVSpan; -typedef struct MVSpanStruct { - Sig sig; /* */ - RingStruct spans; /* all the spans */ - MV mv; /* owning MV pool */ - Tract tract; /* first tract of the span */ - Size size; /* size of the span */ - MVBlockStruct base; /* sentinel at base of span */ - MVBlockStruct limit; /* sentinel at limit of span */ - MVBlock blocks; /* allocated blocks */ - Size space; /* total free space in span */ - Size largest; /* .design.largest */ - Bool largestKnown; /* .design.largest */ - unsigned blockCount; /* number of blocks on chain */ -} MVSpanStruct; - - -#define SpanSize(span) \ - AddrOffset((span)->base.base, (span)->limit.limit) -#define SpanInsideSentinels(span) \ - AddrOffset((span)->base.limit, (span)->limit.base) - - -/* MVSpanCheck -- check the consistency of a span structure */ - -static Bool MVSpanCheck(MVSpan span) -{ - Addr addr, base, limit; - Arena arena; - Tract tract; - - CHECKS(MVSpan, span); - - CHECKL(RingCheck(&span->spans)); - CHECKU(MV, span->mv); - CHECKD_NOSIG(Tract, span->tract); - CHECKL(MVBlockCheck(&span->base)); - CHECKL(MVBlockCheck(&span->limit)); - /* The block chain starts with the base sentinel. */ - CHECKL(span->blocks == &span->base); - /* Since there is a limit sentinel, the chain can't end just after the */ - /* base sentinel... */ - CHECKL(span->base.next != NULL); - /* ... and it's sure to have at least two blocks on it. */ - CHECKL(span->blockCount >= 2); - /* This is just defined this way. It shouldn't change. */ - CHECKL(span->limit.next == NULL); - /* The sentinels should mark the ends of the span. */ - base = TractBase(span->tract); - limit = AddrAdd(base, span->size); - CHECKL(span->base.base == base); - CHECKL(span->limit.limit == limit); - /* The sentinels mustn't overlap. */ - CHECKL(span->base.limit <= span->limit.base); - /* The free space can't be more than the gap between the sentinels. */ - CHECKL(span->space <= SpanInsideSentinels(span)); - - CHECKL(BoolCheck(span->largestKnown)); - if (span->largestKnown) { /* .design.largest */ - CHECKL(span->largest <= span->space); - /* at least this much is free */ - } else { - CHECKL(span->largest == SpanSize(span)+1); - } - - /* Each tract of the span must refer to the span */ - arena = PoolArena(TractPool(span->tract)); - TRACT_FOR(tract, addr, arena, base, limit) { - CHECKD_NOSIG(Tract, tract); - CHECKL(TractP(tract) == (void *)span); - } - CHECKL(addr == limit); - - return TRUE; -} - - -/* MVInit -- init method for class MV */ - -static Res MVInit(Pool pool, va_list arg) -{ - Size extendBy, avgSize, maxSize, blockExtendBy, spanExtendBy; - MV mv; - Arena arena; - Res res; - - extendBy = va_arg(arg, Size); - avgSize = va_arg(arg, Size); - maxSize = va_arg(arg, Size); - - AVER(extendBy > 0); - AVER(avgSize > 0); - AVER(avgSize <= extendBy); - AVER(maxSize > 0); - AVER(extendBy <= maxSize); - - mv = Pool2MV(pool); - arena = PoolArena(pool); - - /* At 100% fragmentation we will need one block descriptor for every other */ - /* allocated block, or (extendBy/avgSize)/2 descriptors. See note 1. */ - blockExtendBy = sizeof(MVBlockStruct) * (extendBy/avgSize)/2; - if(blockExtendBy < sizeof(MVBlockStruct)) { - blockExtendBy = sizeof(MVBlockStruct); - } - - res = PoolInit(&mv->blockPoolStruct.poolStruct, - arena, PoolClassMFS(), - blockExtendBy, sizeof(MVBlockStruct)); - if(res != ResOK) - return res; - - spanExtendBy = sizeof(MVSpanStruct) * (maxSize/extendBy); - - res = PoolInit(&mv->spanPoolStruct.poolStruct, - arena, PoolClassMFS(), - spanExtendBy, sizeof(MVSpanStruct)); - if(res != ResOK) - return res; - - mv->extendBy = extendBy; - mv->avgSize = avgSize; - mv->maxSize = maxSize; - RingInit(&mv->spans); - - mv->space = 0; - mv->lost = 0; - - mv->sig = MVSig; - AVERT(MV, mv); - EVENT5(PoolInitMV, pool, arena, extendBy, avgSize, maxSize); - return ResOK; -} - - -/* MVFinish -- finish method for class MV */ - -static void MVFinish(Pool pool) -{ - MV mv; - Ring spans, node = NULL, nextNode; /* gcc whinge stop */ - MVSpan span; - - AVERT(Pool, pool); - mv = Pool2MV(pool); - AVERT(MV, mv); - - /* Destroy all the spans attached to the pool. */ - spans = &mv->spans; - RING_FOR(node, spans, nextNode) { - span = RING_ELT(MVSpan, spans, node); - AVERT(MVSpan, span); - ArenaFree(TractBase(span->tract), span->size, pool); - } - - mv->sig = SigInvalid; - - PoolFinish(&mv->blockPoolStruct.poolStruct); - PoolFinish(&mv->spanPoolStruct.poolStruct); -} - - -/* MVSpanAlloc -- allocate space from a span of memory - * - * MVSpanAlloc searches a span for a free block of the requested size. If it - * finds one it allocates it from the span, updates *addrReturn to point - * to it, and returns TRUE. - */ - -static Bool MVSpanAlloc(Addr *addrReturn, MVSpan span, Size size, - Pool blockPool) -{ - Size gap; - Size largest = 0; - MVBlock block; - - AVERT(MVSpan, span); - AVER(size > 0); - AVER(addrReturn != NULL); - - block = span->blocks; - AVER(block == &span->base); /* should be the base sentinel */ - - /* We're guaranteed at least one gap between sentinels, and therefore at */ - /* least one iteration of this loop. So, the test is at the end. */ - do { - AVER(block->next != NULL); - - gap = AddrOffset(block->limit, block->next->base); - - if (gap > largest) { - largest = gap; - AVER(largest <= span->largest); - } - - if(gap >= size) { - Addr new = block->limit; - - /* If the gap is exactly the right size then the preceeding and */ - /* following blocks can be merged, into the preceeding one, */ - /* unless the following block is the end sentinel. */ - if(gap == size && block->next != &span->limit) { - MVBlock old = block->next; - block->limit = old->limit; - block->next = old->next; - PoolFree(blockPool, (Addr)old, sizeof(MVBlockStruct)); - --span->blockCount; - } else - block->limit = AddrAdd(block->limit, size); - - if (gap == span->largest) { /* we've used a 'largest' gap */ - AVER(span->largestKnown); - span->largestKnown = FALSE; - span->largest = SpanSize(span) + 1; /* .design.largest */ - } - - span->space -= size; - *addrReturn = new; - return TRUE; - } - - block = block->next; - } - while(block->next != NULL); - - /* we've looked at all the gaps, so now we know the largest */ - AVER(span->largestKnown == FALSE); - span->largestKnown = TRUE; - span->largest = largest; - - return FALSE; -} - - -/* MVSpanFree -- free an area in a span of memory - * - * Searches a span for a block which contains the area specified by the - * base and limit, and frees it within that span. This may involve - * allocating a block descriptor, which may fail, in which case an error is - * returned. - * - * There are eight cases, depending on what we are freeing: - * 1. whole of non-sentinel - * 2. in body of any block - * 3. at base of non-base - * 4. at limit of non-limit - * 5. whole of base sentinel - * 6. whole of limit sentinel - * 7. at base of base sentinel - * 8. at limit of limit sentinel - */ - -static Res MVSpanFree(MVSpan span, Addr base, Addr limit, Pool blockPool) -{ - MVBlock prev, block; - Size freeAreaSize = 0; /* .design.largest.free */ - - AVERT(MVSpan, span); - AVER(span->base.base <= base); - AVER(limit <= span->limit.limit); - AVERT(Pool, blockPool); - - prev = NULL; - block = span->blocks; - - AVER(block == &span->base); /* should be base sentinel */ - do { - AVERT(MVBlock, block); - - /* Is the freed area within the block? */ - if(block->base <= base && limit <= block->limit) { - Bool isBase = block == &span->base; - Bool isLimit = block == &span->limit; - Bool isSentinel = isBase || isLimit; - - if(!isSentinel && block->base == base && limit == block->limit) { - /* case 1 : the whole of a non-sentinel block */ - AVER(block->next != NULL); /* there must at least be a sentinel */ - AVER(prev != NULL); /* block isn't sentinel */ - freeAreaSize = AddrOffset(prev->limit, block->next->base); - prev->next = block->next; - PoolFree(blockPool, (Addr)block, sizeof(MVBlockStruct)); - --span->blockCount; - } else if(!isBase && block->base == base) { - /* cases 3 and 6: at base of a block other than the base sentinel */ - AVER(prev != NULL); /* block isn't sentinel */ - freeAreaSize = AddrOffset(prev->limit, limit); - block->base = limit; - } else if(!isLimit && limit == block->limit) { - /* cases 4 and 5: at limit of a block other than the limit sentinel */ - AVER(block->next != NULL); /* should at least be a sentinel */ - freeAreaSize = AddrOffset(base, block->next->base); - block->limit = base; - } else { - /* cases 2, 7, and 8: making a new fragment */ - Res res; - MVBlock new; - Addr addr; - - /* The freed area is buried in the middle of the block, so the */ - /* block must be split into two parts. */ - res = PoolAlloc(&addr, blockPool, sizeof(MVBlockStruct), - /* withReservoirPermit */ FALSE); - if(res != ResOK) return res; - new = (MVBlock)addr; - - freeAreaSize = AddrOffset(base, limit); - - /* If the freed area is in the base sentinel then insert the new */ - /* descriptor after it, otherwise insert before. */ - if(isBase) { /* case 7: new fragment at the base of the span */ - new->base = limit; - new->limit = block->limit; - block->limit = base; - new->next = block->next; - AVER(new->next != NULL); /* should at least be a sentinel */ - block->next = new; - } else { /* cases 2 and 8 */ - new->base = block->base; - new->limit = base; - block->base = limit; - new->next = block; - AVER(prev != NULL); - prev->next = new; - } - - AVERT(MVBlock, new); - ++span->blockCount; - } - - AVERT(MVBlock, block); - - span->space += AddrOffset(base, limit); - - if (freeAreaSize > span->largest) { /* .design.largest */ - AVER(span->largestKnown); - span->largest = freeAreaSize; - } - - return ResOK; - } - - prev = block; - block = block->next; - } while(block != NULL); - - /* The freed area is in the span, but not within a block. */ - NOTREACHED; - - return ResOK; -} - - -/* MVAlloc -- allocate method for class MV */ - -static Res MVAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit) -{ - Res res; - MVSpan span; - Arena arena; - Addr base, limit, addr; - Tract tract; - MV mv; - Size regionSize; - Ring spans, node = NULL, nextNode; /* gcc whinge stop */ - - AVER(pReturn != NULL); - AVERT(Pool, pool); - mv = Pool2MV(pool); - AVERT(MV, mv); - AVER(size > 0); - AVERT(Bool, withReservoirPermit); - - size = SizeAlignUp(size, pool->alignment); - - if(size <= mv->space) { - spans = &mv->spans; - RING_FOR(node, spans, nextNode) { - span = RING_ELT(MVSpan, spans, node); - if((size <= span->largest) && /* .design.largest.alloc */ - (size <= span->space)) { - Addr new; - - if(MVSpanAlloc(&new, span, size, mvBlockPool(mv))) { - mv->space -= size; - AVER(AddrIsAligned(new, pool->alignment)); - *pReturn = new; - return ResOK; - } - } - } - } - - /* There is no block large enough in any of the spans, so extend the */ - /* pool with a new region which will hold the requested allocation. */ - /* Allocate a new span descriptor and initialize it to point at the */ - /* region. */ - res = PoolAlloc(&addr, mvSpanPool(mv), sizeof(MVSpanStruct), - withReservoirPermit); - if(res != ResOK) - return res; - span = (MVSpan)addr; - - if(size <= mv->extendBy) - regionSize = mv->extendBy; - else - regionSize = size; - - arena = PoolArena(pool); - regionSize = SizeAlignUp(regionSize, ArenaAlign(arena)); - - res = ArenaAlloc(&base, SegPrefDefault(), regionSize, pool, - withReservoirPermit); - if(res != ResOK) { /* try again with a region big enough for this object */ - regionSize = SizeAlignUp(size, ArenaAlign(arena)); - res = ArenaAlloc(&base, SegPrefDefault(), regionSize, pool, - withReservoirPermit); - if (res != ResOK) { - PoolFree(mvSpanPool(mv), (Addr)span, sizeof(MVSpanStruct)); - return res; - } - } - limit = AddrAdd(base, regionSize); - - DebugPoolFreeSplat(pool, base, limit); - - span->size = regionSize; - span->tract = TractOfBaseAddr(arena, base); - span->mv = mv; - /* Set the p field for each tract of the span */ - TRACT_FOR(tract, addr, arena, base, limit) { - AVER(TractCheck(tract)); - AVER(TractP(tract) == NULL); - AVER(TractPool(tract) == pool); - TractSetP(tract, (void *)span); - } - AVER(addr == limit); - RingInit(&span->spans); - span->base.base = span->base.limit = base; - span->limit.base = span->limit.limit = limit; - span->space = AddrOffset(span->base.limit, span->limit.base); - span->limit.next = NULL; - span->base.next = &span->limit; - span->blocks = &span->base; - span->blockCount = 2; - span->base.limit = AddrAdd(span->base.limit, size); - span->space -= size; - span->largest = span->space; - span->largestKnown = TRUE; - - span->sig = MVSpanSig; - AVERT(MVSpan, span); - - mv->space += span->space; - RingInsert(&mv->spans, &span->spans); - /* use RingInsert so that we examine this new span first when allocating */ - - *pReturn = span->base.base; - return ResOK; -} - - -/* MVFree -- free method for class MV */ - -static void MVFree(Pool pool, Addr old, Size size) -{ - Addr base, limit; - MVSpan span; - MV mv; - Res res; - Bool b; - Tract tract = NULL; /* suppress "may be used uninitialized" */ - - AVERT(Pool, pool); - mv = Pool2MV(pool); - AVERT(MV, mv); - - AVER(old != (Addr)0); - AVER(size > 0); - - size = SizeAlignUp(size, pool->alignment); - base = old; - limit = AddrAdd(base, size); - - /* Map the pointer onto the tract which contains it, and thence */ - /* onto the span. */ - b = TractOfAddr(&tract, PoolArena(pool), old); - AVER(b); - span = (MVSpan)TractP(tract); - AVERT(MVSpan, span); - - /* the to be freed area should be within the span just found */ - AVER(span->base.base <= base); - AVER(limit <= span->limit.limit); - - /* Unfortunately, if allocating the new block descriptor fails we */ - /* can't do anything, and the memory is lost. See note 2. */ - res = MVSpanFree(span, base, limit, mvBlockPool(mv)); - if(res != ResOK) - mv->lost += size; - else - mv->space += size; - - /* free space should be less than total space */ - AVER(span->space <= SpanInsideSentinels(span)); - if(span->space == SpanSize(span)) { /* the whole span is free */ - AVER(span->blockCount == 2); - /* both blocks are the trivial sentinel blocks */ - AVER(span->base.limit == span->base.base); - AVER(span->limit.limit == span->limit.base); - mv->space -= span->space; - ArenaFree(TractBase(span->tract), span->size, pool); - RingRemove(&span->spans); - RingFinish(&span->spans); - PoolFree(mvSpanPool(mv), (Addr)span, sizeof(MVSpanStruct)); - } -} - - -/* MVDebugMixin - find debug mixin in class MVDebug */ - -static PoolDebugMixin MVDebugMixin(Pool pool) -{ - MV mv; - - AVERT(Pool, pool); - mv = Pool2MV(pool); - AVERT(MV, mv); - /* Can't check MVDebug, because this is called during MVDebug init */ - return &(MV2MVDebug(mv)->debug); -} - - -static Res MVDescribe(Pool pool, mps_lib_FILE *stream) -{ - Res res; - MV mv; - MVSpan span; - Align step; - Size length; - char c; - Ring spans, node = NULL, nextNode; /* gcc whinge stop */ - - if(!TESTT(Pool, pool)) return ResFAIL; - mv = Pool2MV(pool); - if(!TESTT(MV, mv)) return ResFAIL; - if(stream == NULL) return ResFAIL; - - res = WriteF(stream, - " blockPool $P ($U)\n", - (WriteFP)mvBlockPool(mv), (WriteFU)mvBlockPool(mv)->serial, - " spanPool $P ($U)\n", - (WriteFP)mvSpanPool(mv), (WriteFU)mvSpanPool(mv)->serial, - " extendBy $W\n", (WriteFW)mv->extendBy, - " avgSize $W\n", (WriteFW)mv->avgSize, - " maxSize $W\n", (WriteFW)mv->maxSize, - " space $P\n", (WriteFP)mv->space, - NULL); - if(res != ResOK) return res; - - res = WriteF(stream, " Spans\n", NULL); - if(res != ResOK) return res; - - spans = &mv->spans; - RING_FOR(node, spans, nextNode) { - span = RING_ELT(MVSpan, spans, node); - AVERT(MVSpan, span); - - res = WriteF(stream, - " span $P", (WriteFP)span, - " tract $P", (WriteFP)span->tract, - " space $W", (WriteFW)span->space, - " blocks $U", (WriteFU)span->blockCount, - " largest ", - NULL); - if(res != ResOK) return res; - - if (span->largestKnown) /* .design.largest */ - res = WriteF(stream, "$W\n", (WriteFW)span->largest, NULL); - else - res = WriteF(stream, "unknown\n", NULL); - - if(res != ResOK) return res; - } - - res = WriteF(stream, " Span allocation maps\n", NULL); - if(res != ResOK) return res; - - step = pool->alignment; - length = 0x40 * step; - - spans = &mv->spans; - RING_FOR(node, spans, nextNode) { - Addr i, j; - MVBlock block; - span = RING_ELT(MVSpan, spans, node); - res = WriteF(stream, " MVSpan $P\n", (WriteFP)span, NULL); - if(res != ResOK) return res; - - block = span->blocks; - - for(i = span->base.base; i < span->limit.limit; i = AddrAdd(i, length)) { - res = WriteF(stream, " $A ", i, NULL); - if(res != ResOK) return res; - - for(j = i; - j < AddrAdd(i, length) && j < span->limit.limit; - j = AddrAdd(j, step)) { - - if(j >= block->limit) { - block = block->next; - if(block == NULL) return ResFAIL; /* shouldn't pass limit */ - } - - if(j == block->base) { - if(AddrAdd(j, step) == block->limit) - c = 'O'; - else - c = '['; - } else if(j < block->base) - c = '.'; - else if(AddrAdd(j, step) == block->limit) - c = ']'; - else /* j > block->base && j < block->limit */ - c = '='; - res = WriteF(stream, "$C", c, NULL); - if(res != ResOK) return res; - } - res = WriteF(stream, "\n", NULL); - if(res != ResOK) return res; - } - } - - return ResOK; -} - - -/* Pool class MV */ - - -DEFINE_POOL_CLASS(MVPoolClass, this) -{ - INHERIT_CLASS(this, AbstractBufferPoolClass); - PoolClassMixInAllocFree(this); - this->name = "MV"; - this->size = sizeof(MVStruct); - this->offset = offsetof(MVStruct, poolStruct); - this->init = MVInit; - this->finish = MVFinish; - this->alloc = MVAlloc; - this->free = MVFree; - this->describe = MVDescribe; -} - - -MVPoolClass PoolClassMV(void) -{ - return EnsureMVPoolClass(); -} - - -/* Pool class MVDebug */ - -DEFINE_POOL_CLASS(MVDebugPoolClass, this) -{ - INHERIT_CLASS(this, MVPoolClass); - PoolClassMixInDebug(this); - this->name = "MVDBG"; - this->size = sizeof(MVDebugStruct); - this->debugMixin = MVDebugMixin; -} - - -/* class functions - * - * Note this is an MPS interface extension - */ - -mps_class_t mps_class_mv(void) -{ - return (mps_class_t)(EnsureMVPoolClass()); -} - -mps_class_t mps_class_mv_debug(void) -{ - return (mps_class_t)(EnsureMVDebugPoolClass()); -} - - -/* mps_mv_free_size -- free bytes in pool */ - -size_t mps_mv_free_size(mps_pool_t mps_pool) -{ - Pool pool; - MV mv; - MVSpan span; - Size f = 0; - Ring spans, node = NULL, nextNode; /* gcc whinge stop */ - - pool = (Pool)mps_pool; - - AVERT(Pool, pool); - mv = Pool2MV(pool); - AVERT(MV, mv); - - spans = &mv->spans; - RING_FOR(node, spans, nextNode) { - span = RING_ELT(MVSpan, spans, node); - AVERT(MVSpan, span); - f += span->space; - } - - return (size_t)f; -} - - -size_t mps_mv_size(mps_pool_t mps_pool) -{ - Pool pool; - MV mv; - MVSpan span; - Size f = 0; - Ring spans, node = NULL, nextNode; /* gcc whinge stop */ - - pool = (Pool)mps_pool; - - AVERT(Pool, pool); - mv = Pool2MV(pool); - AVERT(MV, mv); - - spans = &mv->spans; - RING_FOR(node, spans, nextNode) { - span = RING_ELT(MVSpan, spans, node); - AVERT(MVSpan, span); - f += span->size; - } - - return (size_t)f; -} - - -/* MVCheck -- check the consistency of an MV structure */ - -Bool MVCheck(MV mv) -{ - CHECKS(MV, mv); - CHECKD(Pool, &mv->poolStruct); - CHECKL(IsSubclassPoly(mv->poolStruct.class, EnsureMVPoolClass())); - CHECKD(MFS, &mv->blockPoolStruct); - CHECKD(MFS, &mv->spanPoolStruct); - CHECKL(mv->extendBy > 0); - CHECKL(mv->avgSize > 0); - CHECKL(mv->extendBy >= mv->avgSize); - /* @@@@ Could do more checks here. */ - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmv.h b/mps/code/poolmv.h deleted file mode 100644 index 1eba70cafa5..00000000000 --- a/mps/code/poolmv.h +++ /dev/null @@ -1,98 +0,0 @@ -/* poolmv.h: MANUAL VARIABLE POOL - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .purpose: This is the interface to the manual-variable pool class. - * - * .mv: Manual-variable pools manage variably-sized blocks of memory in a - * flexible manner. They have higher overheads than a fixed-size pool. - * - * .init: This class adds the following arguments to PoolCreate: - * - * Size extendBy - * - * extendBy is the default number of bytes reserved by the pool at a time. - * A large size will make allocation cheaper but have a higher resource - * overhead. A typical value might be 65536. See note 2. - * - * Size avgSize - * - * avgSize is an estimate of the average size of an allocation, and is used - * to choose the size of internal tables. An accurate estimate will - * improve the efficiency of the pool. A low estimate will make the pool - * less space efficient. A high estimate will make the pool less time - * efficient. A typical value might be 32. avgSize must not be less than - * extendBy. - * - * Size maxSize - * - * maxSize is an estimate of the maximum total size that the pool will - * reach. Setting this parameter does not actually contrain the pool, but - * an accurate estimate will improve the efficiency of the pool. maxSize - * must not be less than extendBy. - * - * Notes - * 2. The documentation could suggest a segment size according to the - * distribution of allocation size requests. richard 1994-11-08 - */ - -#ifndef poolmv_h -#define poolmv_h - - -#include "mpmtypes.h" - -typedef struct MVStruct *MV; - -extern PoolClass PoolClassMV(void); - -extern Bool MVCheck(MV mv); - -#define MV2Pool(mv) (&(mv)->poolStruct) - - -#endif /* poolmv_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c deleted file mode 100644 index 9401f568b03..00000000000 --- a/mps/code/poolmv2.c +++ /dev/null @@ -1,1190 +0,0 @@ -/* poolmv2.c: MANUAL VARIABLE-SIZED TEMPORAL POOL - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: A manual-variable pool designed to take advantage of - * placement according to predicted deathtime. - * - * .design: See . - */ - -#include "mpm.h" -#include "poolmv2.h" -#include "mpscmv2.h" -#include "abq.h" -#include "cbs.h" -#include "meter.h" - -SRCID(poolmv2, "$Id$"); - - -/* Signatures */ - -#define MVTSig ((Sig)0x5193F299) /* SIGnature MVT */ - - -/* Private prototypes */ - -typedef struct MVTStruct *MVT; -static Res MVTInit(Pool pool, va_list arg); -static Bool MVTCheck(MVT mvt); -static void MVTFinish(Pool pool); -static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size minSize, - Bool withReservoirPermit); -static void MVTBufferEmpty(Pool pool, Buffer buffer, Addr base, Addr limit); -static void MVTFree(Pool pool, Addr base, Size size); -static Res MVTDescribe(Pool pool, mps_lib_FILE *stream); -static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size, Pool pool, - Bool withReservoirPermit); - -static void MVTSegFree(MVT mvt, Seg seg); -static Bool MVTReturnBlockSegs(MVT mvt, CBSBlock block, Arena arena); -static void MVTNoteNew(CBS cbs, CBSBlock block, Size oldSize, Size newSize); -static void MVTNoteDelete(CBS cbs, CBSBlock block, Size oldSize, Size newSize); -static void ABQRefillIfNecessary(MVT mvt, Size size); -static Bool ABQRefillCallback(CBS cbs, CBSBlock block, void *closureP); -static Res MVTContingencySearch(CBSBlock *blockReturn, CBS cbs, Size min); -static Bool MVTContingencyCallback(CBS cbs, CBSBlock block, void *closureP); -static Bool MVTCheckFit(CBSBlock block, Size min, Arena arena); -static ABQ MVTABQ(MVT mvt); -static CBS MVTCBS(MVT mvt); -static MVT CBSMVT(CBS cbs); -static SegPref MVTSegPref(MVT mvt); - - -/* Types */ - - -typedef struct MVTStruct -{ - PoolStruct poolStruct; - CBSStruct cbsStruct; /* The coalescing block structure */ - ABQStruct abqStruct; /* The available block queue */ - SegPrefStruct segPrefStruct; /* The preferences for segments */ - /* */ - Size minSize; /* Pool parameter */ - Size meanSize; /* Pool parameter */ - Size maxSize; /* Pool parameter */ - Count fragLimit; /* Pool parameter */ - /* */ - Size reuseSize; /* Size at which blocks are recycled */ - /* */ - Size fillSize; /* Size of pool segments */ - /* */ - Size availLimit; /* Limit on available */ - /* */ - Bool abqOverflow; /* ABQ dropped some candidates */ - /* .* */ - Bool splinter; /* Saved splinter */ - Seg splinterSeg; /* Saved splinter seg */ - Addr splinterBase; /* Saved splinter base */ - Addr splinterLimit; /* Saved splinter size */ - - /* pool accounting --- one of these first four is redundant, but - size and available are used to implement fragmentation policy */ - Size size; /* size of segs in pool */ - Size allocated; /* bytes allocated to mutator */ - Size available; /* bytes available for allocation */ - Size unavailable; /* bytes lost to fragmentation */ - - /* pool meters*/ - METER_DECL(segAllocs); - METER_DECL(segFrees); - METER_DECL(bufferFills); - METER_DECL(bufferEmpties); - METER_DECL(poolFrees); - METER_DECL(poolSize); - METER_DECL(poolAllocated); - METER_DECL(poolAvailable); - METER_DECL(poolUnavailable); - METER_DECL(poolUtilization); - /* abq meters */ - METER_DECL(finds); - METER_DECL(overflows); - METER_DECL(underflows); - METER_DECL(refills); - METER_DECL(refillPushes); - METER_DECL(refillOverflows); - METER_DECL(refillReturns); - /* fragmentation meters */ - METER_DECL(perfectFits); - METER_DECL(firstFits); - METER_DECL(secondFits); - METER_DECL(failures); - /* contingency meters */ - METER_DECL(emergencyContingencies); - METER_DECL(fragLimitContingencies); - METER_DECL(contingencySearches); - METER_DECL(contingencyHardSearches); - /* splinter meters */ - METER_DECL(splinters); - METER_DECL(splintersUsed); - METER_DECL(splintersDropped); - METER_DECL(sawdust); - /* exception meters */ - METER_DECL(exceptions); - METER_DECL(exceptionSplinters); - METER_DECL(exceptionReturns); - - Sig sig; -} MVTStruct; - - -DEFINE_POOL_CLASS(MVTPoolClass, this) -{ - INHERIT_CLASS(this, AbstractSegBufPoolClass); - this->name = "MVT"; - this->size = sizeof(MVTStruct); - this->offset = offsetof(MVTStruct, poolStruct); - this->attr |= AttrFREE; - this->init = MVTInit; - this->finish = MVTFinish; - this->free = MVTFree; - this->bufferFill = MVTBufferFill; - this->bufferEmpty = MVTBufferEmpty; - this->describe = MVTDescribe; -} - -/* Macros */ - - -/* .trans.something: the C language sucks */ -#define unless(cond) if (!(cond)) -#define when(cond) if (cond) - - -#define Pool2MVT(pool) PARENT(MVTStruct, poolStruct, pool) -#define MVT2Pool(mvt) (&(mvt)->poolStruct) - - -/* Accessors */ - - -static ABQ MVTABQ(MVT mvt) -{ - return &mvt->abqStruct; -} - - -static CBS MVTCBS(MVT mvt) -{ - return &mvt->cbsStruct; -} - - -static MVT CBSMVT(CBS cbs) -{ - return PARENT(MVTStruct, cbsStruct, cbs); -} - - -static SegPref MVTSegPref(MVT mvt) -{ - return &mvt->segPrefStruct; -} - - -/* Methods */ - - -/* MVTInit -- initialize an MVT pool - * - * Parameters are: - * minSize, meanSize, maxSize, reserveDepth, fragLimit - */ -static Res MVTInit(Pool pool, va_list arg) -{ - Arena arena; - Size minSize, meanSize, maxSize, reuseSize, fillSize; - Count reserveDepth, abqDepth, fragLimit; - MVT mvt; - Res res; - - AVERT(Pool, pool); - mvt = Pool2MVT(pool); - /* can't AVERT mvt, yet */ - arena = PoolArena(pool); - AVERT(Arena, arena); - - /* --- Should there be a ResBADARG ? */ - minSize = va_arg(arg, Size); - unless (minSize > 0) - return ResLIMIT; - meanSize = va_arg(arg, Size); - unless (meanSize >= minSize) - return ResLIMIT; - maxSize = va_arg(arg, Size); - unless (maxSize >= meanSize) - return ResLIMIT; - /* --- check that maxSize is not too large */ - reserveDepth = va_arg(arg, Count); - unless (reserveDepth > 0) - return ResLIMIT; - /* --- check that reserveDepth is not too large or small */ - fragLimit = va_arg(arg, Count); - unless (fragLimit <= 100) - return ResLIMIT; - - /* see */ - fillSize = SizeAlignUp(maxSize, ArenaAlign(arena)); - /* see */ - reuseSize = 2 * fillSize; - abqDepth = (reserveDepth * meanSize + reuseSize - 1) / reuseSize; - /* keep the abq from being useless */ - if (abqDepth < 3) - abqDepth = 3; - - res = CBSInit(arena, MVTCBS(mvt), (void *)mvt, &MVTNoteNew, &MVTNoteDelete, - NULL, NULL, reuseSize, MPS_PF_ALIGN, TRUE, FALSE); - if (res != ResOK) - goto failCBS; - - res = ABQInit(arena, MVTABQ(mvt), (void *)mvt, abqDepth); - if (res != ResOK) - goto failABQ; - - { - ZoneSet zones; - /* --- Loci needed here, what should the pref be? */ - *MVTSegPref(mvt) = *SegPrefDefault(); - zones = ZoneSetComp(ArenaDefaultZONESET); - SegPrefExpress(MVTSegPref(mvt), SegPrefZoneSet, (void *)&zones); - } - - mvt->reuseSize = reuseSize; - mvt->fillSize = fillSize; - mvt->abqOverflow = FALSE; - mvt->minSize = minSize; - mvt->meanSize = meanSize; - mvt->maxSize = maxSize; - mvt->fragLimit = fragLimit; - mvt->splinter = FALSE; - mvt->splinterSeg = NULL; - mvt->splinterBase = (Addr)0; - mvt->splinterLimit = (Addr)0; - - /* accounting */ - mvt->size = 0; - mvt->allocated = 0; - mvt->available = 0; - mvt->availLimit = 0; - mvt->unavailable = 0; - - /* meters*/ - METER_INIT(mvt->segAllocs, "segment allocations", (void *)mvt); - METER_INIT(mvt->segFrees, "segment frees", (void *)mvt); - METER_INIT(mvt->bufferFills, "buffer fills", (void *)mvt); - METER_INIT(mvt->bufferEmpties, "buffer empties", (void *)mvt); - METER_INIT(mvt->poolFrees, "pool frees", (void *)mvt); - METER_INIT(mvt->poolSize, "pool size", (void *)mvt); - METER_INIT(mvt->poolAllocated, "pool allocated", (void *)mvt); - METER_INIT(mvt->poolAvailable, "pool available", (void *)mvt); - METER_INIT(mvt->poolUnavailable, "pool unavailable", (void *)mvt); - METER_INIT(mvt->poolUtilization, "pool utilization", (void *)mvt); - METER_INIT(mvt->finds, "ABQ finds", (void *)mvt); - METER_INIT(mvt->overflows, "ABQ overflows", (void *)mvt); - METER_INIT(mvt->underflows, "ABQ underflows", (void *)mvt); - METER_INIT(mvt->refills, "ABQ refills", (void *)mvt); - METER_INIT(mvt->refillPushes, "ABQ refill pushes", (void *)mvt); - METER_INIT(mvt->refillOverflows, "ABQ refill overflows", (void *)mvt); - METER_INIT(mvt->refillReturns, "ABQ refill returns", (void *)mvt); - METER_INIT(mvt->perfectFits, "perfect fits", (void *)mvt); - METER_INIT(mvt->firstFits, "first fits", (void *)mvt); - METER_INIT(mvt->secondFits, "second fits", (void *)mvt); - METER_INIT(mvt->failures, "failures", (void *)mvt); - METER_INIT(mvt->emergencyContingencies, "emergency contingencies", - (void *)mvt); - METER_INIT(mvt->fragLimitContingencies, - "fragmentation limit contingencies", (void *)mvt); - METER_INIT(mvt->contingencySearches, "contingency searches", (void *)mvt); - METER_INIT(mvt->contingencyHardSearches, - "contingency hard searches", (void *)mvt); - METER_INIT(mvt->splinters, "splinters", (void *)mvt); - METER_INIT(mvt->splintersUsed, "splinters used", (void *)mvt); - METER_INIT(mvt->splintersDropped, "splinters dropped", (void *)mvt); - METER_INIT(mvt->sawdust, "sawdust", (void *)mvt); - METER_INIT(mvt->exceptions, "exceptions", (void *)mvt); - METER_INIT(mvt->exceptionSplinters, "exception splinters", (void *)mvt); - METER_INIT(mvt->exceptionReturns, "exception returns", (void *)mvt); - - mvt->sig = MVTSig; - - AVERT(MVT, mvt); - EVENT6(PoolInitMVT, pool, minSize, meanSize, maxSize, - reserveDepth, fragLimit); - return ResOK; - -failABQ: - CBSFinish(MVTCBS(mvt)); -failCBS: - AVER(res != ResOK); - return res; -} - - -/* MVTCheck -- validate an MVT Pool */ - -static Bool MVTCheck(MVT mvt) -{ - CHECKS(MVT, mvt); - CHECKD(Pool, &mvt->poolStruct); - CHECKL(mvt->poolStruct.class == MVTPoolClassGet()); - CHECKD(CBS, &mvt->cbsStruct); - /* CHECKL(CBSCheck(MVTCBS(mvt))); */ - CHECKD(ABQ, &mvt->abqStruct); - /* CHECKL(ABQCheck(MVTABQ(mvt))); */ - CHECKD(SegPref, &mvt->segPrefStruct); - CHECKL(mvt->reuseSize >= 2 * mvt->fillSize); - CHECKL(mvt->fillSize >= mvt->maxSize); - CHECKL(mvt->maxSize >= mvt->meanSize); - CHECKL(mvt->meanSize >= mvt->minSize); - CHECKL(mvt->minSize > 0); - CHECKL(mvt->fragLimit <= 100); - CHECKL(mvt->availLimit == mvt->size * mvt->fragLimit / 100); - CHECKL(BoolCheck(mvt->abqOverflow)); - CHECKL(BoolCheck(mvt->splinter)); - if (mvt->splinter) { - CHECKL(AddrOffset(mvt->splinterBase, mvt->splinterLimit) >= - mvt->minSize); - /* CHECKD(Seg, mvt->splinterSeg); */ - CHECKL(SegCheck(mvt->splinterSeg)); - CHECKL(mvt->splinterBase >= SegBase(mvt->splinterSeg)); - CHECKL(mvt->splinterLimit <= SegLimit(mvt->splinterSeg)); - } - CHECKL(mvt->size == mvt->allocated + mvt->available + - mvt->unavailable); - /* --- could check that sum of segment sizes == mvt->size */ - /* --- check meters? */ - - return TRUE; -} - - -/* MVTFinish -- finish an MVT pool - */ -static void MVTFinish(Pool pool) -{ - MVT mvt; - Arena arena; - Ring ring; - Ring node, nextNode; - - AVERT(Pool, pool); - mvt = Pool2MVT(pool); - AVERT(MVT, mvt); - arena = PoolArena(pool); - AVERT(Arena, arena); - - /* Free the segments in the pool */ - ring = PoolSegRing(pool); - RING_FOR(node, ring, nextNode) { - MVTSegFree(mvt, SegOfPoolRing(node)); - } - - /* Finish the ABQ and CBS structures */ - ABQFinish(arena, MVTABQ(mvt)); - CBSFinish(MVTCBS(mvt)); - - mvt->sig = SigInvalid; -} - - -/* MVTBufferFill -- refill an allocation buffer from an MVT pool - * - * See - */ -static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size minSize, - Bool withReservoirPermit) -{ - Seg seg; - MVT mvt; - Res res; - Addr base, limit; - Arena arena; - Size alignedSize, fillSize; - CBSBlock block; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Pool, pool); - mvt = Pool2MVT(pool); - AVERT(MVT, mvt); - AVERT(Buffer, buffer); - AVER(BufferIsReset(buffer)); - AVER(minSize > 0); - AVER(SizeIsAligned(minSize, pool->alignment)); - AVER(BoolCheck(withReservoirPermit)); - - arena = PoolArena(pool); - fillSize = mvt->fillSize; - alignedSize = SizeAlignUp(minSize, ArenaAlign(arena)); - - /* */ - /* Allocate oversize blocks exactly, directly from the arena */ - if (minSize > fillSize) { - res = MVTSegAlloc(&seg, mvt, alignedSize, pool, withReservoirPermit); - if (res == ResOK) { - base = SegBase(seg); - /* only allocate this block in the segment */ - limit = AddrAdd(base, minSize); - mvt->available -= alignedSize - minSize; - mvt->unavailable += alignedSize - minSize; - AVER(mvt->size == mvt->allocated + mvt->available + - mvt->unavailable); - METER_ACC(mvt->exceptions, minSize); - METER_ACC(mvt->exceptionSplinters, alignedSize - minSize); - goto done; - } - /* --- There cannot be a segment big enough to hold this object in - the free list, although there may be segments that could be - coalesced to do so. */ - AVER(res != ResOK); - return res; - } - - /* */ - /* Use any splinter, if available */ - if (mvt->splinter) { - base = mvt->splinterBase; - limit = mvt->splinterLimit; - if(AddrOffset(base, limit) >= minSize) { - seg = mvt->splinterSeg; - mvt->splinter = FALSE; - METER_ACC(mvt->splintersUsed, AddrOffset(base, limit)); - goto done; - } - } - - /* Attempt to retrieve a free block from the ABQ */ - ABQRefillIfNecessary(mvt, minSize); - res = ABQPeek(MVTABQ(mvt), &block); - if (res != ResOK) { - METER_ACC(mvt->underflows, minSize); - /* */ - if (mvt->available >= mvt->availLimit) { - METER_ACC(mvt->fragLimitContingencies, minSize); - res = MVTContingencySearch(&block, MVTCBS(mvt), minSize); - } - } else { - METER_ACC(mvt->finds, minSize); - } -found: - if (res == ResOK) { - base = CBSBlockBase(block); - limit = CBSBlockLimit(block); - { - Bool b = SegOfAddr(&seg, arena, base); - AVER(b); - UNUSED(b); /* */ - } - /* Only pass out segments - may not be the best long-term policy. */ - { - Addr segLimit = SegLimit(seg); - - if (limit <= segLimit) { - /* perfect fit */ - METER_ACC(mvt->perfectFits, AddrOffset(base, limit)); - } else if (AddrOffset(base, segLimit) >= minSize) { - /* fit in 1st segment */ - limit = segLimit; - METER_ACC(mvt->firstFits, AddrOffset(base, limit)); - } else { - /* fit in 2nd second segment */ - base = segLimit; - { - Bool b = SegOfAddr(&seg, arena, base); - AVER(b); - UNUSED(b); /* */ - } - segLimit = SegLimit(seg); - if (limit > segLimit) - limit = segLimit; - METER_ACC(mvt->secondFits, AddrOffset(base, limit)); - } - } - { - Res r = CBSDelete(MVTCBS(mvt), base, limit); - AVER(r == ResOK); - UNUSED(r); /* */ - } - goto done; - } - - /* Attempt to request a block from the arena */ - /* see */ - res = MVTSegAlloc(&seg, mvt, fillSize, pool, withReservoirPermit); - if (res == ResOK) { - base = SegBase(seg); - limit = SegLimit(seg); - goto done; - } - - /* Try contingency */ - METER_ACC(mvt->emergencyContingencies, minSize); - res = MVTContingencySearch(&block, MVTCBS(mvt), minSize); - if (res == ResOK) - goto found; - - METER_ACC(mvt->failures, minSize); - AVER(res != ResOK); - return res; - -done: - *baseReturn = base; - *limitReturn = limit; - mvt->available -= AddrOffset(base, limit); - mvt->allocated += AddrOffset(base, limit); - AVER(mvt->size == mvt->allocated + mvt->available + - mvt->unavailable); - METER_ACC(mvt->poolUtilization, mvt->allocated * 100 / mvt->size); - METER_ACC(mvt->poolUnavailable, mvt->unavailable); - METER_ACC(mvt->poolAvailable, mvt->available); - METER_ACC(mvt->poolAllocated, mvt->allocated); - METER_ACC(mvt->poolSize, mvt->size); - METER_ACC(mvt->bufferFills, AddrOffset(base, limit)); - AVER(AddrOffset(base, limit) >= minSize); - return ResOK; -} - - -/* MVTBufferEmpty -- return an unusable portion of a buffer to the MVT - * pool - * - * See - */ -static void MVTBufferEmpty(Pool pool, Buffer buffer, - Addr base, Addr limit) -{ - MVT mvt; - Size size; - Res res; - - AVERT(Pool, pool); - mvt = Pool2MVT(pool); - AVERT(MVT, mvt); - AVERT(Buffer, buffer); - AVER(BufferIsReady(buffer)); - AVER(base <= limit); - - size = AddrOffset(base, limit); - if (size == 0) - return; - - mvt->available += size; - mvt->allocated -= size; - AVER(mvt->size == mvt->allocated + mvt->available + - mvt->unavailable); - METER_ACC(mvt->poolUtilization, mvt->allocated * 100 / mvt->size); - METER_ACC(mvt->poolUnavailable, mvt->unavailable); - METER_ACC(mvt->poolAvailable, mvt->available); - METER_ACC(mvt->poolAllocated, mvt->allocated); - METER_ACC(mvt->poolSize, mvt->size); - METER_ACC(mvt->bufferEmpties, size); - - /* */ - if (size < mvt->minSize) { - res = CBSInsert(MVTCBS(mvt), base, limit); - AVER(res == ResOK); - METER_ACC(mvt->sawdust, size); - return; - } - - METER_ACC(mvt->splinters, size); - /* */ - if (mvt->splinter) { - Size oldSize = AddrOffset(mvt->splinterBase, mvt->splinterLimit); - - /* Old better, drop new */ - if (size < oldSize) { - res = CBSInsert(MVTCBS(mvt), base, limit); - AVER(res == ResOK); - METER_ACC(mvt->splintersDropped, size); - return; - } else { - /* New better, drop old */ - res = CBSInsert(MVTCBS(mvt), mvt->splinterBase, mvt->splinterLimit); - AVER(res == ResOK); - METER_ACC(mvt->splintersDropped, oldSize); - } - } - - mvt->splinter = TRUE; - mvt->splinterSeg = BufferSeg(buffer); - mvt->splinterBase = base; - mvt->splinterLimit = limit; -} - - -/* MVTFree -- free a block (previously allocated from a buffer) that - * is no longer in use - * - * see - */ -static void MVTFree(Pool pool, Addr base, Size size) -{ - MVT mvt; - Addr limit; - - AVERT(Pool, pool); - mvt = Pool2MVT(pool); - AVERT(MVT, mvt); - AVER(base != (Addr)0); - AVER(size > 0); - - - /* We know the buffer observes pool->alignment */ - size = SizeAlignUp(size, pool->alignment); - limit = AddrAdd(base, size); - METER_ACC(mvt->poolFrees, size); - mvt->available += size; - mvt->allocated -= size; - AVER(mvt->size == mvt->allocated + mvt->available + mvt->unavailable); - METER_ACC(mvt->poolUtilization, mvt->allocated * 100 / mvt->size); - METER_ACC(mvt->poolUnavailable, mvt->unavailable); - METER_ACC(mvt->poolAvailable, mvt->available); - METER_ACC(mvt->poolAllocated, mvt->allocated); - METER_ACC(mvt->poolSize, mvt->size); - - /* */ - /* Return exceptional blocks directly to arena */ - if (size > mvt->fillSize) { - Seg seg; - { - Bool b = SegOfAddr(&seg, PoolArena(pool), base); - AVER(b); - UNUSED(b); /* */ - } - AVER(base == SegBase(seg)); - AVER(limit <= SegLimit(seg)); - mvt->available += SegSize(seg) - size; - mvt->unavailable -= SegSize(seg) - size; - AVER(mvt->size == mvt->allocated + mvt->available + - mvt->unavailable); - METER_ACC(mvt->exceptionReturns, SegSize(seg)); - if (SegBuffer(seg) != NULL) - BufferDetach(SegBuffer(seg), MVT2Pool(mvt)); - MVTSegFree(mvt, seg); - return; - } - - { - Res res = CBSInsert(MVTCBS(mvt), base, limit); - AVER(res == ResOK); - UNUSED(res); /* */ - } -} - - -/* MVTDescribe -- describe an MVT pool */ - -static Res MVTDescribe(Pool pool, mps_lib_FILE *stream) -{ - Res res; - MVT mvt; - - if (!TESTT(Pool, pool)) return ResFAIL; - mvt = Pool2MVT(pool); - if (!TESTT(MVT, mvt)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, - "MVT $P\n{\n", (WriteFP)mvt, - " minSize: $U \n", (WriteFU)mvt->minSize, - " meanSize: $U \n", (WriteFU)mvt->meanSize, - " maxSize: $U \n", (WriteFU)mvt->maxSize, - " fragLimit: $U \n", (WriteFU)mvt->fragLimit, - " reuseSize: $U \n", (WriteFU)mvt->reuseSize, - " fillSize: $U \n", (WriteFU)mvt->fillSize, - " availLimit: $U \n", (WriteFU)mvt->availLimit, - " abqOverflow: $S \n", mvt->abqOverflow?"TRUE":"FALSE", - " splinter: $S \n", mvt->splinter?"TRUE":"FALSE", - " splinterSeg: $P \n", (WriteFP)mvt->splinterSeg, - " splinterBase: $A \n", (WriteFA)mvt->splinterBase, - " splinterLimit: $A \n", (WriteFU)mvt->splinterLimit, - " size: $U \n", (WriteFU)mvt->size, - " allocated: $U \n", (WriteFU)mvt->allocated, - " available: $U \n", (WriteFU)mvt->available, - " unavailable: $U \n", (WriteFU)mvt->unavailable, - NULL); - if(res != ResOK) return res; - - res = CBSDescribe(MVTCBS(mvt), stream); - if(res != ResOK) return res; - - res = ABQDescribe(MVTABQ(mvt), stream); - if(res != ResOK) return res; - - res = METER_WRITE(mvt->segAllocs, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->segFrees, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->bufferFills, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->bufferEmpties, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->poolFrees, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->poolSize, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->poolAllocated, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->poolAvailable, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->poolUnavailable, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->poolUtilization, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->finds, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->overflows, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->underflows, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->refills, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->refillPushes, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->refillOverflows, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->refillReturns, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->perfectFits, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->firstFits, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->secondFits, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->failures, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->emergencyContingencies, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->fragLimitContingencies, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->contingencySearches, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->contingencyHardSearches, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->splinters, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->splintersUsed, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->splintersDropped, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->sawdust, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->exceptions, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->exceptionSplinters, stream); - if (res != ResOK) return res; - res = METER_WRITE(mvt->exceptionReturns, stream); - if (res != ResOK) return res; - - res = WriteF(stream, "}\n", NULL); - return res; -} - - -/* Pool Interface */ - - -/* PoolClassMVT -- the Pool (sub-)Class for an MVT pool */ - -PoolClass PoolClassMVT(void) -{ - return MVTPoolClassGet(); -} - - -/* MPS Interface */ - - -/* mps_class_mvt -- the class of an mvt pool */ - -mps_class_t mps_class_mvt(void) -{ - return (mps_class_t)(PoolClassMVT()); -} - - -/* MPS Interface extensions --- should these be pool generics? */ - - -/* mps_mvt_size -- number of bytes committed to the pool */ - -size_t mps_mvt_size(mps_pool_t mps_pool) -{ - Pool pool; - MVT mvt; - - pool = (Pool)mps_pool; - - AVERT(Pool, pool); - mvt = Pool2MVT(pool); - AVERT(MVT, mvt); - - return (size_t)mvt->size; -} - - -/* mps_mvt_free_size -- number of bytes comitted to the pool that are - * available for allocation - */ -size_t mps_mvt_free_size(mps_pool_t mps_pool) -{ - Pool pool; - MVT mvt; - - pool = (Pool)mps_pool; - - AVERT(Pool, pool); - mvt = Pool2MVT(pool); - AVERT(MVT, mvt); - - return (size_t)mvt->available; -} - - -/* Internal methods */ - - -/* MVTSegAlloc -- encapsulates SegAlloc with associated accounting and - * metering - */ -static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size, - Pool pool, Bool withReservoirPermit) -{ - Res res = SegAlloc(segReturn, GCSegClassGet(), - MVTSegPref(mvt), size, pool, withReservoirPermit); - - if (res == ResOK) { - Size segSize = SegSize(*segReturn); - - /* see */ - AVER(segSize >= mvt->fillSize); - mvt->size += segSize; - mvt->available += segSize; - mvt->availLimit = mvt->size * mvt->fragLimit / 100; - AVER(mvt->size == mvt->allocated + mvt->available + mvt->unavailable); - METER_ACC(mvt->segAllocs, segSize); - } - return res; -} - - -/* MVTSegFree -- encapsulates SegFree with associated accounting and - * metering - */ -static void MVTSegFree(MVT mvt, Seg seg) -{ - Size size = SegSize(seg); - - mvt->available -= size; - mvt->size -= size; - mvt->availLimit = mvt->size * mvt->fragLimit / 100; - AVER(mvt->size == mvt->allocated + mvt->available + mvt->unavailable); - SegFree(seg); - METER_ACC(mvt->segFrees, size); -} - - -/* MVTReturnBlockSegs -- return (interior) segments of a block to the - * arena - */ -static Bool MVTReturnBlockSegs(MVT mvt, CBSBlock block, Arena arena) -{ - Addr base, limit; - Bool success = FALSE; - - base = CBSBlockBase(block); - limit = CBSBlockLimit(block); - - while (base < limit) { - Seg seg; - Addr segBase, segLimit; - - { - Bool b = SegOfAddr(&seg, arena, base); - AVER(b); - UNUSED(b); /* */ - } - segBase = SegBase(seg); - segLimit = SegLimit(seg); - if (base <= segBase && limit >= segLimit) { - Res r = CBSDelete(MVTCBS(mvt), segBase, segLimit); - - AVER(r == ResOK); - UNUSED(r); /* */ - MVTSegFree(mvt, seg); - success = TRUE; - } - base = segLimit; - } - - return success; -} - - -/* MVTNoteNew -- callback invoked when a block on the CBS >= reuseSize - */ -static void MVTNoteNew(CBS cbs, CBSBlock block, Size oldSize, Size newSize) -{ - Res res; - MVT mvt; - - AVERT(CBS, cbs); - mvt = CBSMVT(cbs); - AVERT(MVT, mvt); - AVERT(CBSBlock, block); - AVER(CBSBlockSize(block) >= mvt->reuseSize); - UNUSED(oldSize); - UNUSED(newSize); - - res = ABQPush(MVTABQ(mvt), block); - /* See */ - if (res != ResOK) { - Arena arena = PoolArena(MVT2Pool(mvt)); - CBSBlock oldBlock; - res = ABQPeek(MVTABQ(mvt), &oldBlock); - AVER(res == ResOK); - /* --- This should always succeed */ - (void)MVTReturnBlockSegs(mvt, oldBlock, arena); - res = ABQPush(MVTABQ(CBSMVT(cbs)), block); - if (res != ResOK) { - unless(MVTReturnBlockSegs(mvt, block, arena)) { - mvt->abqOverflow = TRUE; - METER_ACC(mvt->overflows, CBSBlockSize(block)); - } - } - } -} - - -/* MVTNoteDelete -- callback invoked when a block on the CBS <= reuseSize */ - -static void MVTNoteDelete(CBS cbs, CBSBlock block, Size oldSize, Size newSize) -{ - Res res; - - AVERT(CBS, cbs); - AVERT(MVT, CBSMVT(cbs)); - AVERT(CBSBlock, block); - AVER(CBSBlockSize(block) < CBSMVT(cbs)->reuseSize); - UNUSED(oldSize); - UNUSED(newSize); - - res = ABQDelete(MVTABQ(CBSMVT(cbs)), block); - AVER(res == ResOK || CBSMVT(cbs)->abqOverflow); - UNUSED(res); /* */ -} - - -/* ABQRefillIfNecessary -- refill the ABQ from the CBS if it had - * overflown and is now empty - */ -static void ABQRefillIfNecessary(MVT mvt, Size size) -{ - AVERT(MVT, mvt); - AVER(size > 0); - - if (mvt->abqOverflow && ABQIsEmpty(MVTABQ(mvt))) { - mvt->abqOverflow = FALSE; - METER_ACC(mvt->refills, size); - CBSIterateLarge(MVTCBS(mvt), &ABQRefillCallback, NULL); - } -} - - -/* ABQRefillCallback -- called from CBSIterate at the behest of - * ABQRefillIfNecessary - */ -static Bool ABQRefillCallback(CBS cbs, CBSBlock block, void *closureP) -{ - Res res; - MVT mvt; - - AVERT(CBS, cbs); - mvt = CBSMVT(cbs); - AVERT(MVT, mvt); - AVERT(ABQ, MVTABQ(mvt)); - AVERT(CBSBlock, block); - AVER(CBSBlockSize(block) >= mvt->reuseSize); - UNUSED(closureP); - - METER_ACC(mvt->refillPushes, ABQDepth(MVTABQ(mvt))); - res = ABQPush(MVTABQ(mvt), block); - if (res != ResOK) { - if (MVTReturnBlockSegs(mvt, block, PoolArena(MVT2Pool(mvt)))) { - METER_ACC(mvt->refillReturns, CBSBlockSize(block)); - return TRUE; - } else { - mvt->abqOverflow = TRUE; - METER_ACC(mvt->refillOverflows, CBSBlockSize(block)); - return FALSE; - } - } - - return TRUE; -} - - -/* Closure for MVTContingencySearch */ -typedef struct MVTContigencyStruct *MVTContigency; - -typedef struct MVTContigencyStruct -{ - CBSBlock blockReturn; - Arena arena; - Size min; - /* meters */ - Count steps; - Count hardSteps; -} MVTContigencyStruct; - - -/* MVTContingencySearch -- search the CBS for a block of size min */ - -static Res MVTContingencySearch(CBSBlock *blockReturn, CBS cbs, Size min) -{ - MVTContigencyStruct cls; - - cls.blockReturn = NULL; - cls.arena = PoolArena(MVT2Pool(CBSMVT(cbs))); - cls.min = min; - cls.steps = 0; - cls.hardSteps = 0; - - CBSIterate(cbs, &MVTContingencyCallback, (void *)&cls); - if (cls.blockReturn != NULL) { - AVER(CBSBlockSize(cls.blockReturn) >= min); - METER_ACC(CBSMVT(cbs)->contingencySearches, cls.steps); - if (cls.hardSteps) { - METER_ACC(CBSMVT(cbs)->contingencyHardSearches, cls.hardSteps); - } - *blockReturn = cls.blockReturn; - return ResOK; - } - - return ResFAIL; -} - - -/* MVTContingencyCallback -- called from CBSIterate at the behest of - * MVTContingencySearch - */ -static Bool MVTContingencyCallback(CBS cbs, CBSBlock block, void *closureP) -{ - MVTContigency cl; - Size size; - - AVERT(CBS, cbs); - AVERT(CBSBlock, block); - AVER(closureP != NULL); - - cl = (MVTContigency)closureP; - size = CBSBlockSize(block); - - cl->steps++; - if (size < cl->min) - return TRUE; - - /* verify that min will fit when seg-aligned */ - if (size >= 2 * cl->min) { - cl->blockReturn = block; - return FALSE; - } - - /* do it the hard way */ - cl->hardSteps++; - if (MVTCheckFit(block, cl->min, cl->arena)) { - cl->blockReturn = block; - return FALSE; - } - - /* keep looking */ - return TRUE; -} - - -/* MVTCheckFit -- verify that segment-aligned block of size min can - * fit in a candidate CBSblock - */ -static Bool MVTCheckFit(CBSBlock block, Size min, Arena arena) -{ - Addr base = CBSBlockBase(block); - Addr limit = CBSBlockLimit(block); - Seg seg; - Addr segLimit; - - { - Bool b = SegOfAddr(&seg, arena, base); - AVER(b); - UNUSED(b); /* */ - } - segLimit = SegLimit(seg); - - if (limit <= segLimit) { - if (AddrOffset(base, limit) >= min) - return TRUE; - } - - if (AddrOffset(base, segLimit) >= min) - return TRUE; - - base = segLimit; - { - Bool b = SegOfAddr(&seg, arena, base); - AVER(b); - UNUSED(b); /* */ - } - segLimit = SegLimit(seg); - - if (AddrOffset(base, limit < segLimit ? limit : segLimit) >= min) - return TRUE; - - return FALSE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmv2.h b/mps/code/poolmv2.h deleted file mode 100644 index dbead05725b..00000000000 --- a/mps/code/poolmv2.h +++ /dev/null @@ -1,60 +0,0 @@ -/* poolmv2.h: MANUAL VARIABLE-SIZED TEMPORAL POOL - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: The implementation of the new manual-variable pool class - * - * .design: See - */ - -#ifndef poolmv2_h -#define poolmv2_h - -#include "mpm.h" - -extern PoolClass PoolClassMVT(void); - -#endif /* poolmv2_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c deleted file mode 100644 index a2647608187..00000000000 --- a/mps/code/poolmvff.c +++ /dev/null @@ -1,733 +0,0 @@ -/* poolmvff.c: First Fit Manual Variable Pool - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .purpose: This is a pool class for manually managed objects of - * variable size where address-ordered first fit is an appropriate - * policy. Provision is made to allocate in reverse. This pool - * can allocate across segment boundaries. - * - * .design: - * - * - * TRANSGRESSIONS - * - * .trans.stat: mps_mvff_stat is a temporary hack for measurement purposes, - * see .stat below. - */ - -#include "mpscmvff.h" -#include "dbgpool.h" -#include "cbs.h" -#include "mpm.h" - -SRCID(poolmvff, "$Id$"); - - -/* Would go in poolmvff.h if the class had any MPS-internal clients. */ -extern PoolClass PoolClassMVFF(void); - - -/* MVFFStruct -- MVFF (Manual Variable First Fit) pool outer structure - * - * The signature is placed at the end, see - * - */ - -#define MVFFSig ((Sig)0x5193FFF9) /* SIGnature MVFF */ - -typedef struct MVFFStruct *MVFF; -typedef struct MVFFStruct { /* MVFF pool outer structure */ - PoolStruct poolStruct; /* generic structure */ - SegPref segPref; /* the preferences for segments */ - Size extendBy; /* segment size to extend pool by */ - Size minSegSize; /* minimum size of segment */ - Size avgSize; /* client estimate of allocation size */ - Size total; /* total bytes in pool */ - Size free; /* total free bytes in pool */ - CBSStruct cbsStruct; /* free list */ - Bool firstFit; /* as opposed to last fit */ - Bool slotHigh; /* prefers high part of large block */ - Sig sig; /* */ -} MVFFStruct; - - -#define Pool2MVFF(pool) PARENT(MVFFStruct, poolStruct, pool) -#define MVFF2Pool(mvff) (&((mvff)->poolStruct)) -#define CBSOfMVFF(mvff) (&((mvff)->cbsStruct)) -#define MVFFOfCBS(cbs) PARENT(MVFFStruct, cbsStruct, cbs) - -static Bool MVFFCheck(MVFF mvff); - - -/* MVFFDebug -- MVFFDebug class */ - -typedef struct MVFFDebugStruct { - MVFFStruct mvffStruct; /* MVFF structure */ - PoolDebugMixinStruct debug; /* debug mixin */ -} MVFFDebugStruct; - -typedef MVFFDebugStruct *MVFFDebug; - - -#define MVFF2MVFFDebug(mvff) PARENT(MVFFDebugStruct, mvffStruct, mvff) -#define MVFFDebug2MVFF(mvffd) (&((mvffd)->mvffStruct)) - - -/* MVFFAddToFreeList -- Add given range to free list - * - * Updates MVFF counters for additional free space. Returns maximally - * coalesced range containing given range. Does not attempt to free - * segments (see MVFFFreeSegs). Cannot(!) fail. - */ -static void MVFFAddToFreeList(Addr *baseIO, Addr *limitIO, MVFF mvff) { - Res res; - Addr base, limit; - - AVER(baseIO != NULL); - AVER(limitIO != NULL); - AVERT(MVFF, mvff); - base = *baseIO; - limit = *limitIO; - AVER(limit > base); - - res = CBSInsertReturningRange(baseIO, limitIO, CBSOfMVFF(mvff), base, limit); - AVER(res == ResOK); - mvff->free += AddrOffset(base, limit); - - return; -} - - -/* MVFFFreeSegs -- Free segments from given range - * - * Given a free range, attempts to find entire segments within - * it, and returns them to the arena, updating total size counter. - * - * This is usually called immediately after MVFFAddToFreeList. - * It is not combined with MVFFAddToFreeList because the latter - * is also called when new segments are added under MVFFAlloc. - */ -static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit) -{ - Seg seg = NULL; /* suppress "may be used uninitialized" */ - Arena arena; - Bool b; - Addr segLimit; /* limit of the current segment when iterating */ - Addr segBase; /* base of the current segment when iterating */ - Res res; - - AVERT(MVFF, mvff); - AVER(base < limit); - /* Could profitably AVER that the given range is free, */ - /* but the CBS doesn't provide that facility. */ - - if (AddrOffset(base, limit) < mvff->minSegSize) - return; /* not large enough for entire segments */ - - arena = PoolArena(MVFF2Pool(mvff)); - b = SegOfAddr(&seg, arena, base); - AVER(b); - - segBase = SegBase(seg); - segLimit = SegLimit(seg); - - while(segLimit <= limit) { /* segment ends in range */ - if (segBase >= base) { /* segment starts in range */ - /* Must remove from free list first, in case free list */ - /* is using inline data structures. */ - res = CBSDelete(CBSOfMVFF(mvff), segBase, segLimit); - AVER(res == ResOK); - mvff->free -= AddrOffset(segBase, segLimit); - mvff->total -= AddrOffset(segBase, segLimit); - SegFree(seg); - } - - /* Avoid calling SegNext if the next segment would fail */ - /* the loop test, mainly because there might not be a */ - /* next segment. */ - if (segLimit == limit) /* segment ends at end of range */ - break; - - b = SegNext(&seg, arena, segBase); - AVER(b); - segBase = SegBase(seg); - segLimit = SegLimit(seg); - } - - return; -} - - -/* MVFFAddSeg -- Allocates a new segment from the arena - * - * Allocates a new segment from the arena (with the given - * withReservoirPermit flag) of at least the specified size. The - * specified size should be pool-aligned. Adds it to the free list. - */ -static Res MVFFAddSeg(Seg *segReturn, - MVFF mvff, Size size, Bool withReservoirPermit) -{ - Pool pool; - Arena arena; - Size segSize; - Seg seg; - Res res; - Align align; - Addr base, limit; - - AVERT(MVFF, mvff); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - - pool = MVFF2Pool(mvff); - arena = PoolArena(pool); - align = ArenaAlign(arena); - - AVER(SizeIsAligned(size, PoolAlignment(pool))); - - /* Use extendBy unless it's too small (see */ - /* ). */ - if (size <= mvff->extendBy) - segSize = mvff->extendBy; - else - segSize = size; - - segSize = SizeAlignUp(segSize, align); - - res = SegAlloc(&seg, SegClassGet(), mvff->segPref, segSize, pool, - withReservoirPermit); - if (res != ResOK) { - /* try again for a seg just large enough for object */ - /* see */ - segSize = SizeAlignUp(size, align); - res = SegAlloc(&seg, SegClassGet(), mvff->segPref, segSize, pool, - withReservoirPermit); - if (res != ResOK) { - return res; - } - } - - mvff->total += segSize; - base = SegBase(seg); limit = AddrAdd(base, segSize); - DebugPoolFreeSplat(pool, base, limit); - MVFFAddToFreeList(&base, &limit, mvff); - AVER(base <= SegBase(seg)); - if (mvff->minSegSize > segSize) mvff->minSegSize = segSize; - - /* Don't call MVFFFreeSegs; that would be silly. */ - - *segReturn = seg; - return ResOK; -} - - -/* MVFFFindFirstFree -- Finds the first (or last) suitable free block - * - * Finds a free block of the given (pool aligned) size, according - * to a first (or last) fit policy controlled by the MVFF fields - * firstFit, slotHigh (for whether to allocate the top or bottom - * portion of a larger block). - * - * Will return FALSE if the free list has no large enough block. - * In particular, will not attempt to allocate a new segment. - */ -static Bool MVFFFindFirstFree(Addr *baseReturn, Addr *limitReturn, - MVFF mvff, Size size) -{ - Bool foundBlock; - CBSFindDelete findDelete; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(MVFF, mvff); - AVER(size > 0); - AVER(SizeIsAligned(size, PoolAlignment(MVFF2Pool(mvff)))); - - findDelete = mvff->slotHigh ? CBSFindDeleteHIGH : CBSFindDeleteLOW; - - foundBlock = - (mvff->firstFit ? CBSFindFirst : CBSFindLast) - (baseReturn, limitReturn, CBSOfMVFF(mvff), size, findDelete); - - if (foundBlock) - mvff->free -= size; - - return foundBlock; -} - - -/* MVFFAlloc -- Allocate a block */ - -static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size, - Bool withReservoirPermit) -{ - Res res; - MVFF mvff; - Addr base, limit; - Bool foundBlock; - - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - - AVER(aReturn != NULL); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - - size = SizeAlignUp(size, PoolAlignment(pool)); - - foundBlock = MVFFFindFirstFree(&base, &limit, mvff, size); - if (!foundBlock) { - Seg seg; - - res = MVFFAddSeg(&seg, mvff, size, withReservoirPermit); - if (res != ResOK) - return res; - foundBlock = MVFFFindFirstFree(&base, &limit, mvff, size); - - /* We know that the found range must intersect the new segment. */ - /* In particular, it doesn't necessarily lie entirely within it. */ - /* The next three AVERs test for intersection of two intervals. */ - AVER(base >= SegBase(seg) || limit <= SegLimit(seg)); - AVER(base < SegLimit(seg)); - AVER(SegBase(seg) < limit); - - /* We also know that the found range is no larger than the segment. */ - AVER(SegSize(seg) >= AddrOffset(base, limit)); - } - AVER(foundBlock); - AVER(AddrOffset(base, limit) == size); - - *aReturn = base; - - return ResOK; -} - - -/* MVFFFree -- free the given block */ - -static void MVFFFree(Pool pool, Addr old, Size size) -{ - Addr base, limit; - MVFF mvff; - - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - - AVER(old != (Addr)0); - AVER(AddrIsAligned(old, PoolAlignment(pool))); - AVER(size > 0); - - size = SizeAlignUp(size, PoolAlignment(pool)); - base = old; - limit = AddrAdd(base, size); - - - MVFFAddToFreeList(&base, &limit, mvff); - - MVFFFreeSegs(mvff, base, limit); -} - - -/* MVFFBufferFill -- Fill the buffer - * - * Fill it with the largest block we can find. - */ -static Res MVFFBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - Res res; - MVFF mvff; - Addr base, limit; - Bool foundBlock; - Seg seg = NULL; - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(SizeIsAligned(size, PoolAlignment(pool))); - AVERT(Bool, withReservoirPermit); - - /* Hoping the largest is big enough, delete it and return if small. */ - foundBlock = CBSFindLargest(&base, &limit, CBSOfMVFF(mvff), - CBSFindDeleteENTIRE); - if (foundBlock && AddrOffset(base, limit) < size) { - foundBlock = FALSE; - res = CBSInsert(CBSOfMVFF(mvff), base, limit); - AVER(res == ResOK); - } - if (!foundBlock) { - res = MVFFAddSeg(&seg, mvff, size, withReservoirPermit); - if (res != ResOK) - return res; - foundBlock = CBSFindLargest(&base, &limit, CBSOfMVFF(mvff), - CBSFindDeleteENTIRE); - AVER(foundBlock); /* We will find the new segment. */ - } - - AVER(AddrOffset(base, limit) >= size); - mvff->free -= AddrOffset(base, limit); - - *baseReturn = base; - *limitReturn = limit; - return ResOK; -} - - -/* MVFFBufferEmpty -- return unused portion of this buffer */ - -static void MVFFBufferEmpty(Pool pool, Buffer buffer, - Addr base, Addr limit) -{ - MVFF mvff; - - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - AVERT(Buffer, buffer); - AVER(BufferIsReady(buffer)); - AVER(base <= limit); - - if (base == limit) - return; - - MVFFAddToFreeList(&base, &limit, mvff); - MVFFFreeSegs(mvff, base, limit); - - return; -} - - -/* MVFFInit -- initialize method for MVFF */ - -static Res MVFFInit(Pool pool, va_list arg) -{ - Size extendBy, avgSize, align; - Bool slotHigh, arenaHigh, firstFit; - MVFF mvff; - Arena arena; - Res res; - void *p; - ZoneSet zones; - - AVERT(Pool, pool); - - /* .arg: class-specific additional arguments; see */ - /* */ - /* .arg.check: we do the same checks here and in MVFFCheck */ - /* except for arenaHigh, which is stored only in the segPref. */ - extendBy = va_arg(arg, Size); - avgSize = va_arg(arg, Size); - align = va_arg(arg, Size); - slotHigh = va_arg(arg, Bool); - arenaHigh = va_arg(arg, Bool); - firstFit = va_arg(arg, Bool); - AVER(extendBy > 0); /* .arg.check */ - AVER(avgSize > 0); /* .arg.check */ - AVER(avgSize <= extendBy); /* .arg.check */ - AVER(BoolCheck(slotHigh)); - AVER(BoolCheck(arenaHigh)); - AVER(BoolCheck(firstFit)); - - mvff = Pool2MVFF(pool); - arena = PoolArena(pool); - - mvff->extendBy = extendBy; - if (extendBy < ArenaAlign(arena)) - mvff->minSegSize = ArenaAlign(arena); - else - mvff->minSegSize = extendBy; - mvff->avgSize = avgSize; - pool->alignment = align; - mvff->slotHigh = slotHigh; - mvff->firstFit = firstFit; - - res = ControlAlloc(&p, arena, sizeof(SegPrefStruct), FALSE); - if (res != ResOK) - return res; - - mvff->segPref = (SegPref)p; - *mvff->segPref = *SegPrefDefault(); - SegPrefExpress(mvff->segPref, arenaHigh ? SegPrefHigh : SegPrefLow, NULL); - /* If using zoneset placement, just put it apart from the others. */ - zones = ZoneSetComp(ArenaDefaultZONESET); - SegPrefExpress(mvff->segPref, SegPrefZoneSet, (void *)&zones); - - mvff->total = 0; - mvff->free = 0; - - res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, NULL, NULL, NULL, NULL, - mvff->extendBy, align, TRUE, TRUE); - - if (res != ResOK) - goto failInit; - - mvff->sig = MVFFSig; - AVERT(MVFF, mvff); - EVENT8(PoolInitMVFF, pool, arena, extendBy, avgSize, align, - slotHigh, arenaHigh, firstFit); - return ResOK; - -failInit: - ControlFree(arena, p, sizeof(SegPrefStruct)); - return res; -} - - -/* MVFFFinish -- finish method for MVFF */ - -static void MVFFFinish(Pool pool) -{ - MVFF mvff; - Arena arena; - Seg seg; - Ring ring, node, nextNode; - - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - - ring = PoolSegRing(pool); - RING_FOR(node, ring, nextNode) { - seg = SegOfPoolRing(node); - AVER(SegPool(seg) == pool); - SegFree(seg); - } - - /* Could maintain mvff->total here and check it falls to zero, */ - /* but that would just make the function slow. If only we had */ - /* a way to do operations only if AVERs are turned on. */ - - arena = PoolArena(pool); - ControlFree(arena, mvff->segPref, sizeof(SegPrefStruct)); - - CBSFinish(CBSOfMVFF(mvff)); - - mvff->sig = SigInvalid; -} - - -/* MVFFDebugMixin - find debug mixin in class MVFFDebug */ - -static PoolDebugMixin MVFFDebugMixin(Pool pool) -{ - MVFF mvff; - - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - /* Can't check MVFFDebug, because this is called during init */ - return &(MVFF2MVFFDebug(mvff)->debug); -} - - -/* MVFFDescribe -- describe an MVFF pool */ - -static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream) -{ - Res res; - MVFF mvff; - - if (!TESTT(Pool, pool)) return ResFAIL; - mvff = Pool2MVFF(pool); - if (!TESTT(MVFF, mvff)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, - "MVFF $P {\n", (WriteFP)mvff, - " pool $P ($U)\n", - (WriteFP)pool, (WriteFU)pool->serial, - " extendBy $W\n", (WriteFW)mvff->extendBy, - " avgSize $W\n", (WriteFW)mvff->avgSize, - " total $U\n", (WriteFU)mvff->total, - " free $U\n", (WriteFU)mvff->free, - NULL); - if (res != ResOK) - return res; - - res = CBSDescribe(CBSOfMVFF(mvff), stream); - if (res != ResOK) - return res; - - res = WriteF(stream, "}\n", NULL); - - return res; -} - - -DEFINE_POOL_CLASS(MVFFPoolClass, this) -{ - INHERIT_CLASS(this, AbstractAllocFreePoolClass); - PoolClassMixInBuffer(this); - this->name = "MVFF"; - this->size = sizeof(MVFFStruct); - this->offset = offsetof(MVFFStruct, poolStruct); - this->init = MVFFInit; - this->finish = MVFFFinish; - this->alloc = MVFFAlloc; - this->free = MVFFFree; - this->bufferFill = MVFFBufferFill; - this->bufferEmpty = MVFFBufferEmpty; - this->describe = MVFFDescribe; -} - - -PoolClass PoolClassMVFF(void) -{ - return MVFFPoolClassGet(); -} - - -/* Pool class MVFFDebug */ - -DEFINE_POOL_CLASS(MVFFDebugPoolClass, this) -{ - INHERIT_CLASS(this, MVFFPoolClass); - PoolClassMixInDebug(this); - this->name = "MVFFDBG"; - this->size = sizeof(MVFFDebugStruct); - this->debugMixin = MVFFDebugMixin; -} - - - -/* MPS Interface Extensions. */ - -mps_class_t mps_class_mvff(void) -{ - return (mps_class_t)(MVFFPoolClassGet()); -} - -mps_class_t mps_class_mvff_debug(void) -{ - return (mps_class_t)(MVFFDebugPoolClassGet()); -} - - -/* Total free bytes. See */ - -size_t mps_mvff_free_size(mps_pool_t mps_pool) -{ - Pool pool; - MVFF mvff; - - pool = (Pool)mps_pool; - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - - return (size_t)mvff->free; -} - -/* Total owned bytes. See */ - -size_t mps_mvff_size(mps_pool_t mps_pool) -{ - Pool pool; - MVFF mvff; - - pool = (Pool)mps_pool; - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - - return (size_t)mvff->total; -} - - -/* MVFFCheck -- check the consistency of an MVFF structure */ - -static Bool MVFFCheck(MVFF mvff) -{ - CHECKS(MVFF, mvff); - CHECKD(Pool, MVFF2Pool(mvff)); - CHECKL(IsSubclassPoly(MVFF2Pool(mvff)->class, MVFFPoolClassGet())); - CHECKD(SegPref, mvff->segPref); - CHECKL(mvff->extendBy > 0); /* see .arg.check */ - CHECKL(mvff->minSegSize >= ArenaAlign(PoolArena(MVFF2Pool(mvff)))); - CHECKL(mvff->avgSize > 0); /* see .arg.check */ - CHECKL(mvff->avgSize <= mvff->extendBy); /* see .arg.check */ - CHECKL(mvff->total >= mvff->free); - CHECKL(SizeIsAligned(mvff->free, PoolAlignment(MVFF2Pool(mvff)))); - CHECKL(SizeIsAligned(mvff->total, ArenaAlign(PoolArena(MVFF2Pool(mvff))))); - CHECKD(CBS, CBSOfMVFF(mvff)); - CHECKL(BoolCheck(mvff->slotHigh)); - CHECKL(BoolCheck(mvff->firstFit)); - return TRUE; -} - - -/* mps_mvff_stat -- a hack to get statistics emitted - * - * .stat: The SW temp pool cannot be destroyed, so we're providing this - * to get the statistics. It breaks modularity to access CBS internals. - */ - -#include "meter.h" -extern void mps_mvff_stat(mps_pool_t pool); - -void mps_mvff_stat(mps_pool_t mps_pool) -{ - Pool pool; - MVFF mvff; - - pool = (Pool)mps_pool; - AVERT(Pool, pool); - mvff = Pool2MVFF(pool); - AVERT(MVFF, mvff); - - METER_EMIT(&CBSOfMVFF(mvff)->splaySearch); - METER_EMIT(&CBSOfMVFF(mvff)->eblSearch); - METER_EMIT(&CBSOfMVFF(mvff)->eglSearch); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/pooln.c b/mps/code/pooln.c deleted file mode 100644 index a22d81c23a2..00000000000 --- a/mps/code/pooln.c +++ /dev/null @@ -1,353 +0,0 @@ -/* pooln.c: NULL POOL CLASS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "pooln.h" -#include "mpm.h" - -SRCID(pooln, "$Id$"); - - -/* PoolNStruct -- the pool structure */ - -typedef struct PoolNStruct { - PoolStruct poolStruct; /* generic pool structure */ - /* and that's it */ -} PoolNStruct; - - -/* PoolPoolN -- get the PoolN structure from generic Pool */ - -#define PoolPoolN(pool) PARENT(PoolNStruct, poolStruct, pool) - - -/* PoolPoolN -- get the generic pool structure from a PoolN */ - -#define PoolNPool(pooln) (&(poolN)->poolStruct) - - -/* NInit -- init method for class N */ - -static Res NInit(Pool pool, va_list args) -{ - PoolN poolN = PoolPoolN(pool); - - UNUSED(args); - - /* Initialize pool-specific structures. */ - - AVERT(PoolN, poolN); - EVENT3(PoolInit, pool, PoolArena(pool), ClassOfPool(pool)); - return ResOK; -} - - -/* NFinish -- finish method for class N */ - -static void NFinish(Pool pool) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - /* Finish pool-specific structures. */ -} - - -/* NAlloc -- alloc method for class N */ - -static Res NAlloc(Addr *pReturn, Pool pool, Size size, - Bool withReservoirPermit) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVER(pReturn != NULL); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - - return ResLIMIT; /* limit of nil blocks exceeded */ -} - - -/* NFree -- free method for class N */ - -static void NFree(Pool pool, Addr old, Size size) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVER(old != (Addr)0); - AVER(size > 0); - - NOTREACHED; /* can't allocate, should never free */ -} - - -/* NBufferFill -- buffer fill method for class N */ - -static Res NBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Buffer, buffer); - AVER(BufferIsReset(buffer)); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - - NOTREACHED; /* can't create buffers, so shouldn't fill them */ - return ResUNIMPL; -} - - -/* NBufferEmpty -- buffer empty method for class N */ - -static void NBufferEmpty(Pool pool, Buffer buffer, - Addr init, Addr limit) -{ - AVERT(Pool, pool); - AVERT(Buffer, buffer); - AVER(BufferIsReady(buffer)); - AVER(init <= limit); - - NOTREACHED; /* can't create buffers, so they shouldn't trip */ -} - - -/* NDescribe -- describe method for class N */ - -static Res NDescribe(Pool pool, mps_lib_FILE *stream) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - UNUSED(stream); /* @@@@ should output something here */ - - return ResOK; -} - - -/* NWhiten -- condemn method for class N */ - -static Res NWhiten(Pool pool, Trace trace, Seg seg) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVERT(Trace, trace); - AVERT(Seg, seg); - - NOTREACHED; /* pool doesn't have any actions */ - - return ResUNIMPL; -} - - -/* NGrey -- greyen method for class N */ - -static void NGrey(Pool pool, Trace trace, Seg seg) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVERT(Trace, trace); - AVERT(Seg, seg); -} - - -/* NBlacken -- blacken method for class N */ - -static void NBlacken(Pool pool, TraceSet traceSet, Seg seg) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVERT(TraceSet, traceSet); - AVERT(Seg, seg); -} - - -/* NScan -- scan method for class N */ - -static Res NScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) -{ - PoolN poolN; - - AVER(totalReturn != NULL); - AVERT(ScanState, ss); - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - AVERT(Seg, seg); - - return ResOK; -} - - -/* NFix -- fix method for class N */ - -static Res NFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVERT(ScanState, ss); - UNUSED(refIO); - AVERT(Seg, seg); - NOTREACHED; /* Since we don't allocate any objects, should never */ - /* be called upon to fix a reference. */ - return ResFAIL; -} - - -/* NReclaim -- reclaim method for class N */ - -static void NReclaim(Pool pool, Trace trace, Seg seg) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVERT(Trace, trace); - AVERT(Seg, seg); - /* all unmarked and white objects reclaimed */ -} - - -/* NTraceEnd -- trace end method for class N */ - -static void NTraceEnd(Pool pool, Trace trace) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVERT(Trace, trace); -} - - -/* NPoolClass -- pool class definition for N */ - -DEFINE_POOL_CLASS(NPoolClass, this) -{ - INHERIT_CLASS(this, AbstractPoolClass); - this->name = "N"; - this->size = sizeof(PoolNStruct); - this->offset = offsetof(PoolNStruct, poolStruct); - this->attr = AttrSCAN | AttrALLOC | AttrFREE | AttrBUF | - AttrBUF_RESERVE | AttrGC; - this->init = NInit; - this->finish = NFinish; - this->alloc = NAlloc; - this->free = NFree; - this->bufferFill = NBufferFill; - this->bufferEmpty = NBufferEmpty; - this->whiten = NWhiten; - this->grey = NGrey; - this->blacken = NBlacken; - this->scan = NScan; - this->fix = NFix; - this->fixEmergency = NFix; - this->reclaim = NReclaim; - this->traceEnd = NTraceEnd; - this->describe = NDescribe; -} - - -/* PoolClassN -- returns the PoolClass for the null pool class */ - -PoolClass PoolClassN(void) -{ - return EnsureNPoolClass(); -} - - -/* PoolNCheck -- check a pool of class N */ - -Bool PoolNCheck(PoolN poolN) -{ - CHECKL(poolN != NULL); - CHECKD(Pool, &poolN->poolStruct); - CHECKL(poolN->poolStruct.class == EnsureNPoolClass()); - UNUSED(poolN); /* */ - - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/pooln.h b/mps/code/pooln.h deleted file mode 100644 index 36028f876d6..00000000000 --- a/mps/code/pooln.h +++ /dev/null @@ -1,82 +0,0 @@ -/* pooln.h: NULL POOL - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: The null pool class is here for pedagogical purposes. It - * is a skeleton of a pool class. The class exhibits all the generic - * pool functions; none of them have non-trivial implementations. - * - * .create: The generic create method for this class takes no extra - * parameters. - */ - - -#ifndef pooln_h -#define pooln_h - -#include "mpmtypes.h" - - -/* PoolN -- instance type */ - -typedef struct PoolNStruct *PoolN; - - -/* PoolClassN -- returns the PoolClass for the null pool class */ - -extern PoolClass PoolClassN(void); - - -/* PoolNCheck -- check a pool of class N - * - * Validates a PoolN object. This function conforms to the validation - * protocol defined in . - */ - -extern Bool PoolNCheck(PoolN poolN); - - -#endif /* pooln_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolncv.c b/mps/code/poolncv.c deleted file mode 100644 index 765664917af..00000000000 --- a/mps/code/poolncv.c +++ /dev/null @@ -1,91 +0,0 @@ -/* poolncv.c: NULL POOL COVERAGE TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" -#include "pooln.h" -#include "mpsavm.h" -#include "testlib.h" - - -static Bool testit(ArenaClass class, ...) -{ - Bool eflag = FALSE; - Arena arena; - Pool pool; - Res res; - Addr p; - va_list args; - - va_start(args, class); - die(ArenaCreateV(&arena, class, args), "ArenaCreate"); - va_end(args); - - die(PoolCreate(&pool, arena, PoolClassN()), "PoolNCreate"); - res = PoolAlloc(&p, pool, 1, /* withReservoirPermit */ FALSE); - if (res == ResOK) { - fprintf(stderr, - "Error: Unexpectedly succeeded in" - "allocating block from PoolN\n"); - eflag = TRUE; - } - PoolDestroy(pool); - ArenaDestroy(arena); - - return eflag; -} - - -int main(void) -{ - if (testit((ArenaClass)mps_arena_class_vm(), (Size)600000)) { - fprintf(stderr, "Conclusion: Defects found.\n"); - } else { - fprintf(stderr, "Conclusion: Failed to find any defects.\n"); - } - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c deleted file mode 100644 index 4dcb7115902..00000000000 --- a/mps/code/poolsnc.c +++ /dev/null @@ -1,738 +0,0 @@ -/* poolsnc.c: STACK NO CHECKING POOL CLASS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * DESIGN - * - * .design: design.mps.poolsnc - * - * LIGHTWEIGHT FRAMES - * - * .lw-frame-state: The pool uses lightweight frames as its only - * type of allocation frame. The lightweight frame state is set to - * Valid whenever a buffer has a segment and Disabled otherwise. - * See . - * - * .lw-frame-null: The frame marker NULL is used as a special value - * to indicate bottom of stack. - */ - -#include "mpscsnc.h" -#include "mpm.h" - -SRCID(poolsnc, "$Id$"); - - -#define SNCGen ((Serial)1) /* "generation" for SNC pools */ - - -/* SNCStruct -- structure for an SNC pool - * - * See design.mps.poolsnc.poolstruct. - */ - -#define SNCSig ((Sig)0x519b754c) /* SIGPooLSNC */ - -typedef struct SNCStruct { - PoolStruct poolStruct; - Seg freeSegs; - SegPrefStruct segPrefStruct; - Sig sig; -} SNCStruct, *SNC; - -#define Pool2SNC(pool) \ - PARENT(SNCStruct, poolStruct, (pool)) - - -/* Forward declarations */ - -static SegClass SNCSegClassGet(void); -static BufferClass SNCBufClassGet(void); -static Bool SNCCheck(SNC snc); -static void sncPopPartialSegChain(SNC snc, Buffer buf, Seg upTo); - - -/* Management of segment chains - * - * Each buffer has an associated segment chain in stack order - * (top of stack first). We subclass the buffer to maintain the - * head of the chain. Segments are chained using the SegP field. - */ - - - -/* SNCBufStruct -- SNC Buffer subclass - * - * This subclass of RankBuf holds a segment chain. - */ - -#define SNCBufSig ((Sig)0x51954CBF) /* SIGnature SNC BuFfer */ - -typedef struct SNCBufStruct *SNCBuf; - -typedef struct SNCBufStruct { - SegBufStruct segBufStruct; /* superclass fields must come first */ - Seg topseg; /* The segment chain head -- may be NULL */ - Sig sig; /* */ -} SNCBufStruct; - - -/* BufferSNCBuf -- convert generic Buffer to an SNCBuf */ - -#define BufferSNCBuf(buffer) ((SNCBuf)(buffer)) - - -/* SNCBufCheck -- check consistency of an SNCBuf */ - -static Bool SNCBufCheck(SNCBuf sncbuf) -{ - SegBuf segbuf; - - CHECKS(SNCBuf, sncbuf); - segbuf = &sncbuf->segBufStruct; - CHECKL(SegBufCheck(segbuf)); - if (sncbuf->topseg != NULL) { - CHECKL(SegCheck(sncbuf->topseg)); - } - return TRUE; -} - - -/* sncBufferTopSeg -- return the head of segment chain from an SNCBuf */ - -static Seg sncBufferTopSeg(Buffer buffer) -{ - SNCBuf sncbuf; - AVERT(Buffer, buffer); - sncbuf = BufferSNCBuf(buffer); - AVERT(SNCBuf, sncbuf); - return sncbuf->topseg; -} - - -/* sncBufferSetTopSeg -- set the head of segment chain from an SNCBuf */ - -static void sncBufferSetTopSeg(Buffer buffer, Seg seg) -{ - SNCBuf sncbuf; - AVERT(Buffer, buffer); - if (NULL != seg) - AVERT(Seg, seg); - sncbuf = BufferSNCBuf(buffer); - AVERT(SNCBuf, sncbuf); - sncbuf->topseg = seg; -} - - -/* SNCBufInit -- Initialize an SNCBuf */ - -static Res SNCBufInit (Buffer buffer, Pool pool, va_list args) -{ - SNCBuf sncbuf; - Res res; - BufferClass superclass; - - AVERT(Buffer, buffer); - AVERT(Pool, pool); - - /* call next method */ - superclass = BUFFER_SUPERCLASS(SNCBufClass); - res = (*superclass->init)(buffer, pool, args); - if (res != ResOK) - return res; - - sncbuf = BufferSNCBuf(buffer); - sncbuf->topseg = NULL; - sncbuf->sig = SNCBufSig; - - AVERT(SNCBuf, sncbuf); - return ResOK; -} - - -/* SNCBufFinish -- Finish an SNCBuf */ - -static void SNCBufFinish(Buffer buffer) -{ - BufferClass super; - SNCBuf sncbuf; - SNC snc; - Pool pool; - - AVERT(Buffer, buffer); - sncbuf = BufferSNCBuf(buffer); - AVERT(SNCBuf, sncbuf); - pool = BufferPool(buffer); - - snc = Pool2SNC(pool); - /* Put any segments which haven't bee popped onto the free list */ - sncPopPartialSegChain(snc, buffer, NULL); - - sncbuf->sig = SigInvalid; - - /* finish the superclass fields last */ - super = BUFFER_SUPERCLASS(SNCBufClass); - super->finish(buffer); -} - - -/* SNCBufClass -- The class definition */ - -DEFINE_BUFFER_CLASS(SNCBufClass, class) -{ - INHERIT_CLASS(class, RankBufClass); - class->name = "SNCBUF"; - class->size = sizeof(SNCBufStruct); - class->init = SNCBufInit; - class->finish = SNCBufFinish; -} - - - -/* SNCSegStruct -- SNC segment subclass - * - * This subclass of GCSeg links segments in chains. - */ - -#define SNCSegSig ((Sig)0x51954C59) /* SIGSNCSeG */ - -typedef struct SNCSegStruct *SNCSeg; - -typedef struct SNCSegStruct { - GCSegStruct gcSegStruct; /* superclass fields must come first */ - SNCSeg next; /* Next segment in chain, or NULL */ - Sig sig; -} SNCSegStruct; - -#define SegSNCSeg(seg) ((SNCSeg)(seg)) -#define SNCSegSeg(sncseg) ((Seg)(sncseg)) - -#define sncSegNext(seg) \ - (SNCSegSeg(SegSNCSeg(seg)->next)) - -#define sncSegSetNext(seg, nextseg) \ - ((void)(SegSNCSeg(seg)->next = SegSNCSeg(nextseg))) - -static Bool SNCSegCheck(SNCSeg sncseg) -{ - CHECKS(SNCSeg, sncseg); - CHECKL(GCSegCheck(&sncseg->gcSegStruct)); - if (NULL != sncseg->next) { - CHECKS(SNCSeg, sncseg->next); - } - return TRUE; -} - - -/* sncSegInit -- Init method for SNC segments */ - -static Res sncSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - SegClass super; - SNCSeg sncseg; - Res res; - - AVERT(Seg, seg); - sncseg = SegSNCSeg(seg); - AVERT(Pool, pool); - /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(SNCSegClass); - res = super->init(seg, pool, base, size, reservoirPermit, args); - if (res != ResOK) - return res; - - sncseg->next = NULL; - sncseg->sig = SNCSegSig; - AVERT(SNCSeg, sncseg); - return ResOK; -} - - -/* SNCSegClass -- Class definition for SNC segments */ - -DEFINE_SEG_CLASS(SNCSegClass, class) -{ - INHERIT_CLASS(class, GCSegClass); - SegClassMixInNoSplitMerge(class); /* no support for this (yet) */ - class->name = "SNCSEG"; - class->size = sizeof(SNCSegStruct); - class->init = sncSegInit; -} - - -/* sncRecordAllocatedSeg - stores a segment on the buffer chain */ - -static void sncRecordAllocatedSeg(Buffer buffer, Seg seg) -{ - AVERT(Buffer, buffer); - AVERT(Seg, seg); - AVER(sncSegNext(seg) == NULL); - - sncSegSetNext(seg, sncBufferTopSeg(buffer)); - sncBufferSetTopSeg(buffer, seg); -} - - -/* sncRecordFreeSeg - stores a segment on the freelist */ - -static void sncRecordFreeSeg(SNC snc, Seg seg) -{ - AVERT(SNC, snc); - AVERT(Seg, seg); - AVER(sncSegNext(seg) == NULL); - - /* Make sure it's not grey, and set to RankSetEMPTY */ - /* This means it won't be scanned */ - SegSetGrey(seg, TraceSetEMPTY); - SegSetRankAndSummary(seg, RankSetEMPTY, RefSetEMPTY); - - sncSegSetNext(seg, snc->freeSegs); - snc->freeSegs = seg; -} - - -/* sncPopPartialSegChain - * - * Pops segments from the buffer chain up to a specified limit - */ - -static void sncPopPartialSegChain(SNC snc, Buffer buf, Seg upTo) -{ - Seg free; - AVERT(SNC, snc); - AVERT(Buffer, buf); - if (upTo != NULL) { - AVERT(Seg, upTo); - } - - /* Iterate the buffer chain of segments freeing all until upTo */ - free = sncBufferTopSeg(buf); - while (free != upTo) { - Seg next; - AVER(free != NULL); - next = sncSegNext(free); - sncSegSetNext(free, NULL); - sncRecordFreeSeg(snc, free); - free = next; - } - /* Make upTo the head of the buffer chain */ - sncBufferSetTopSeg(buf, upTo); -} - - -/* sncFindFreeSeg - * - * attempts to find and detach a large enough segment from the - * freelist. returns TRUE on success. - */ -static Bool sncFindFreeSeg(Seg *segReturn, SNC snc, Size size) -{ - Seg free = snc->freeSegs; - Seg last = NULL; - - AVER(size > 0); - - /* iterate over the free list returning anything big enough */ - while (free != NULL) { - AVERT(Seg, free); - if (SegSize(free) >= size) { - /* This segment is big enough. Detach & return it */ - if (last == NULL) { - snc->freeSegs = sncSegNext(free); - } else { - sncSegSetNext(last, sncSegNext(free)); - } - sncSegSetNext(free, NULL); - *segReturn = free; - return TRUE; - } - last = free; - free = sncSegNext(free); - } - - return FALSE; -} - - -/* SNCInit -- initialize an SNC pool */ - -static Res SNCInit(Pool pool, va_list arg) -{ - SNC snc; - Format format; - - /* weak check, as half-way through initialization */ - AVER(pool != NULL); - - snc = Pool2SNC(pool); - - format = va_arg(arg, Format); - - AVERT(Format, format); - pool->format = format; - snc->freeSegs = NULL; - /* Use the default segpref for the pool. At least this should avoid */ - /* clashes with collected pools */ - snc->segPrefStruct = *SegPrefDefault(); - snc->sig = SNCSig; - - AVERT(SNC, snc); - EVENT2(PoolInitSNC, pool, format); - return ResOK; -} - - -/* SNCFinish -- finish an SNC pool */ - -static void SNCFinish(Pool pool) -{ - SNC snc; - Ring ring, node, nextNode; - - AVERT(Pool, pool); - snc = Pool2SNC(pool); - AVERT(SNC, snc); - - ring = &pool->segRing; - RING_FOR(node, ring, nextNode) { - Seg seg = SegOfPoolRing(node); - AVERT(Seg, seg); - SegFree(seg); - } -} - - -static Res SNCBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - SNC snc; - Arena arena; - Res res; - Seg seg; - Size asize; /* aligned size */ - - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - AVERT(Pool, pool); - AVERT(Buffer, buffer); - AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); - AVER(BufferIsReset(buffer)); - - snc = Pool2SNC(pool); - AVERT(SNC, snc); - - /* Try to find a free segment with enough space already */ - if (sncFindFreeSeg(&seg, snc, size)) { - goto found; - } - - /* No free seg, so create a new one */ - arena = PoolArena(pool); - asize = SizeAlignUp(size, ArenaAlign(arena)); - res = SegAlloc(&seg, SNCSegClassGet(), &snc->segPrefStruct, - asize, pool, withReservoirPermit); - if (res != ResOK) - return res; - -found: - /* */ - if (BufferRankSet(buffer) == RankSetEMPTY) - SegSetRankAndSummary(seg, BufferRankSet(buffer), RefSetEMPTY); - else - SegSetRankAndSummary(seg, BufferRankSet(buffer), RefSetUNIV); - - AVERT(Seg, seg); - /* put the segment on the buffer chain */ - sncRecordAllocatedSeg(buffer, seg); - /* Permit the use of lightweight frames - .lw-frame-state */ - BufferFrameSetState(buffer, BufferFrameVALID); - *baseReturn = SegBase(seg); - *limitReturn = SegLimit(seg); - return ResOK; -} - - -static void SNCBufferEmpty(Pool pool, Buffer buffer, - Addr init, Addr limit) -{ - SNC snc; - Seg seg; - Arena arena; - Size size; - - AVERT(Pool, pool); - AVERT(Buffer, buffer); - seg = BufferSeg(buffer); - AVER(init <= limit); - AVER(SegLimit(seg) == limit); - snc = Pool2SNC(pool); - AVERT(SNC, snc); - AVER(BufferFrameState(buffer) == BufferFrameVALID); - /* .lw-frame-state */ - BufferFrameSetState(buffer, BufferFrameDISABLED); - - arena = BufferArena(buffer); - - /* Pad the end unused space at the end of the segment */ - size = AddrOffset(init, limit); - if (size > 0) { - ShieldExpose(arena, seg); - (*pool->format->pad)(init, size); - ShieldCover(arena, seg); - } -} - - -static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) -{ - Addr base, limit; - Format format; - SNC snc; - Res res; - - AVER(totalReturn != NULL); - AVERT(ScanState, ss); - AVERT(Seg, seg); - AVERT(Pool, pool); - snc = Pool2SNC(pool); - AVERT(SNC, snc); - - format = pool->format; - base = SegBase(seg); - - /* If the segment is buffered, only walk as far as the end */ - /* of the initialized objects. */ - if (SegBuffer(seg) != NULL) { - limit = BufferScanLimit(SegBuffer(seg)); - } else { - limit = SegLimit(seg); - } - - if (base < limit) { - res = (*format->scan)(&ss->ss_s, base, limit); - if (res != ResOK) { - *totalReturn = FALSE; - return res; - } - } else { - AVER(base == limit); - } - - ss->scannedSize += AddrOffset(base, limit); - - *totalReturn = TRUE; - return ResOK; -} - - - -static Res SNCFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf) -{ - FrameState state; - AVER(frameReturn != NULL); - AVERT(Pool, pool); - AVERT(Buffer, buf); - - state = BufferFrameState(buf); - /* Sould have been notified of pending pops before this */ - AVER(state == BufferFrameVALID || state == BufferFrameDISABLED); - if (state == BufferFrameDISABLED) { - AVER(BufferIsReset(buf)); /* The buffer must be reset */ - AVER(sncBufferTopSeg(buf) == NULL); /* The stack must be empty */ - /* Use NULL to indicate an empty stack. .lw-frame-null */ - *frameReturn = NULL; - } else { - /* Use the scan limit as the lightweight frame pointer */ - *frameReturn = (AllocFrame)BufferScanLimit(buf); - } - return ResOK; -} - - - -static Res SNCFramePop(Pool pool, Buffer buf, AllocFrame frame) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - /* Normally the Pop would be handled as a lightweight pop */ - /* The only reason that might not happen is if the stack is empty */ - AVER(sncBufferTopSeg(buf) == NULL); - /* The only valid frame must also be NULL - .lw-frame-null */ - AVER(frame == NULL); - /* Popping an empty frame is a NOOP */ - return ResOK; -} - - -static void SNCFramePopPending(Pool pool, Buffer buf, AllocFrame frame) -{ - Addr addr; - SNC snc; - AVERT(Pool, pool); - AVERT(Buffer, buf); - /* frame is an Addr and can't be directly checked */ - snc = Pool2SNC(pool); - AVERT(SNC, snc); - - AVER(BufferFrameState(buf) == BufferFrameVALID); - - if (frame == NULL) { - /* corresponds to a pop to bottom of stack. .lw-frame-null */ - BufferDetach(buf, pool); - sncPopPartialSegChain(snc, buf, NULL); - - } else { - Arena arena; - Seg seg = NULL; /* suppress "may be used uninitialized" */ - Bool foundSeg; - - arena = PoolArena(pool); - addr = (Addr)frame; - foundSeg = SegOfAddr(&seg, arena, addr); - AVER(foundSeg); - - if (SegBuffer(seg) == buf) { - /* don't need to change the segment - just the alloc pointers */ - AVER(addr <= BufferScanLimit(buf)); /* check direction of pop */ - BufferSetAllocAddr(buf, addr); - } else { - /* need to change segment */ - BufferDetach(buf, pool); - sncPopPartialSegChain(snc, buf, seg); - BufferAttach(buf, SegBase(seg), SegLimit(seg), addr, (Size)0); - /* Permit the use of lightweight frames - .lw-frame-state */ - BufferFrameSetState(buf, BufferFrameVALID); - } - } -} - - -static void SNCWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, - void *p, size_t s) -{ - AVERT(Pool, pool); - AVERT(Seg, seg); - AVER(FUNCHECK(f)); - /* p and s are arbitrary closures and can't be checked */ - - /* Avoid applying the function to grey objects. */ - /* They may have pointers to old-space. */ - if (SegGrey(seg) == TraceSetEMPTY) { - Addr object = SegBase(seg); - Addr nextObject; - Addr limit; - SNC snc; - Format format; - - snc = Pool2SNC(pool); - AVERT(SNC, snc); - format = pool->format; - - /* If the segment is buffered, only walk as far as the end */ - /* of the initialized objects. Cf. SNCScan. */ - if (SegBuffer(seg) != NULL) - limit = BufferScanLimit(SegBuffer(seg)); - else - limit = SegLimit(seg); - - while(object < limit) { - (*f)(object, format, pool, p, s); - nextObject = (*format->skip)(object); - AVER(nextObject > object); - object = nextObject; - } - AVER(object == limit); - } -} - - -/* SNCPoolClass -- the class definition */ - -DEFINE_POOL_CLASS(SNCPoolClass, this) -{ - INHERIT_CLASS(this, AbstractScanPoolClass); - PoolClassMixInFormat(this); - this->name = "SNC"; - this->size = sizeof(SNCStruct); - this->offset = offsetof(SNCStruct, poolStruct); - this->init = SNCInit; - this->finish = SNCFinish; - this->bufferFill = SNCBufferFill; - this->bufferEmpty = SNCBufferEmpty; - this->scan = SNCScan; - this->framePush = SNCFramePush; - this->framePop = SNCFramePop; - this->framePopPending = SNCFramePopPending; - this->walk = SNCWalk; - this->bufferClass = SNCBufClassGet; -} - - -mps_class_t mps_class_snc(void) -{ - return (mps_class_t)SNCPoolClassGet(); -} - - -/* SNCCheck -- Check an SNC pool */ - -static Bool SNCCheck(SNC snc) -{ - CHECKS(SNC, snc); - CHECKD(Pool, &snc->poolStruct); - CHECKD(SegPref, &snc->segPrefStruct); - CHECKL(snc->poolStruct.class == SNCPoolClassGet()); - if (snc->freeSegs != NULL) { - CHECKL(SegCheck(snc->freeSegs)); - } - return TRUE; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmcan.c b/mps/code/prmcan.c deleted file mode 100644 index 0551744bfd1..00000000000 --- a/mps/code/prmcan.c +++ /dev/null @@ -1,79 +0,0 @@ -/* prmcan.c: PROTECTION MUTATOR CONTEXT (ANSI) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .design: See for the generic design of the interface - * which is implemented in this module including the contracts for the - * functions. - * - * .purpose: This module implements the part of the protection module - * that implements the MutatorFaultContext type. In this ANSI version - * none of the functions have a useful implementation. - */ - -#include "mpm.h" - -SRCID(prmcan, "$Id$"); - - -/* ProtCanStepInstruction -- can the current instruction be single-stepped */ - -Bool ProtCanStepInstruction(MutatorFaultContext context) -{ - UNUSED(context); - - return FALSE; -} - - -/* ProtStepInstruction -- step over instruction by modifying context */ - -Res ProtStepInstruction(MutatorFaultContext context) -{ - UNUSED(context); - - return ResUNIMPL; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmci3.h b/mps/code/prmci3.h deleted file mode 100644 index e3fbc4f866c..00000000000 --- a/mps/code/prmci3.h +++ /dev/null @@ -1,65 +0,0 @@ -/* prmci3.h: PROTECTION MUTATOR CONTEXT (Intel 386) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS developers. - */ - -#ifndef prmci3_h -#define prmci3_h - - -#include "mpm.h" - -typedef Word *MRef; /* pointer to a machine word */ - -MRef Prmci3AddressHoldingReg(MutatorFaultContext, unsigned int); - -void Prmci3DecodeFaultContext(MRef *, Byte **, MutatorFaultContext); - -void Prmci3StepOverIns(MutatorFaultContext, Size); - -#endif /* prmci3_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmci3fr.c b/mps/code/prmci3fr.c deleted file mode 100644 index 6dbe5de09ae..00000000000 --- a/mps/code/prmci3fr.c +++ /dev/null @@ -1,93 +0,0 @@ -/* prmci3fr.c: PROTECTION MUTATOR CONTEXT INTEL 386 (FREEBSD) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This module implements the part of the protection module - * that decodes the MutatorFaultContext. - * - * - * SOURCES - * - * .source.i486: Intel486 Microprocessor Family Programmer's - * Reference Manual - * - * - * ASSUMPTIONS - * - * .sp: The stack pointer in the context is ESP (x86) or RSP (x86_64). - * - * .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX (or - * their x86_64 equivalents) are assumed to be recorded in the context at - * pointer-aligned boundaries. - */ - -#include "prmcix.h" -#include "prmci3.h" - -SRCID(prmci3fr, "$Id$"); - - -Addr MutatorFaultContextSP(MutatorFaultContext mfc) -{ - return (Addr)mfc->ucontext->uc_mcontext.mc_esp; /* .sp */ -} - - -Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) -{ - Res res; - - /* This scans the root registers (.context.regroots). It also unnecessarily - scans the rest of the context. The optimisation to scan only relevant - parts would be machine dependent. */ - res = TraceScanAreaTagged( - ss, - (Addr *)mfc->ucontext, - (Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))) - ); - - return res; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmci3li.c b/mps/code/prmci3li.c deleted file mode 100644 index 33be380ba61..00000000000 --- a/mps/code/prmci3li.c +++ /dev/null @@ -1,146 +0,0 @@ -/* prmci3li.c: PROTECTION MUTATOR CONTEXT INTEL 386 (LINUX) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This module implements the part of the protection module - * that decodes the MutatorFaultContext. - * - * - * SOURCES - * - * .source.i486: Intel486 Microprocessor Family Programmer's - * Reference Manual - * - * .source.linux.kernel: Linux kernel source files. - * - * - * ASSUMPTIONS - * - * .sp: The stack pointer in the context is uc_stack.ss_sp. - * - * .context.regroots: The root regs are assumed to be recorded in the context - * at pointer-aligned boundaries. - * - * .assume.regref: The resisters in the context can be modified by - * storing into an MRef pointer. - */ - -#include "prmcix.h" -#include "prmci3.h" - -SRCID(prmci3li, "$Id$"); - - -/* Prmci3AddressHoldingReg -- return an address of a register in a context */ - -MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum) -{ - AVER(regnum <= 7); - AVER(regnum >= 0); - - /* .source.i486 */ - /* .assume.regref */ - /* The REG_EAX etc. symbols are only present if _GNU_SOURCE is defined. - Currently this is in lii3gc.gmk in PFMDEFS. */ - /* TODO: The current arrangement of the fix operation (taking a Ref *) - forces us to pun these registers (actually `int` on LII3GC). We can - suppress the warning my casting through `char *` and this might make - it safe, but does it really? RB 2012-09-10 */ - switch (regnum) { - case 0: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EAX]); - case 1: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ECX]); - case 2: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EDX]); - case 3: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EBX]); - case 4: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ESP]); - case 5: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EBP]); - case 6: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ESI]); - case 7: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EDI]); - } - NOTREACHED; - return (MRef)NULL; /* Avoids compiler warning. */ -} - - -/* Prmci3DecodeFaultContext -- decode fault to find faulting address and IP */ - -void Prmci3DecodeFaultContext(MRef *faultmemReturn, - Byte **insvecReturn, - MutatorFaultContext mfc) -{ - /* .source.linux.kernel (linux/arch/i386/mm/fault.c). */ - *faultmemReturn = (MRef)mfc->info->si_addr; - *insvecReturn = (Byte*)mfc->ucontext->uc_mcontext.gregs[REG_EIP]; -} - - -/* Prmci3StepOverIns -- modify context to step over instruction */ - -void Prmci3StepOverIns(MutatorFaultContext mfc, Size inslen) -{ - mfc->ucontext->uc_mcontext.gregs[REG_EIP] += (unsigned long)inslen; -} - - -Addr MutatorFaultContextSP(MutatorFaultContext mfc) -{ - return (Addr)mfc->ucontext->uc_stack.ss_sp; -} - - -Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) -{ - mcontext_t *mc; - Res res; - - /* This scans the root registers (.context.regroots). It also - unnecessarily scans the rest of the context. The optimisation - to scan only relevant parts would be machine dependent. */ - mc = &mfc->ucontext->uc_mcontext; - res = TraceScanAreaTagged(ss, - (Addr *)mc, - (Addr *)((char *)mc + sizeof(*mc))); - return res; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmci3w3.c b/mps/code/prmci3w3.c deleted file mode 100644 index dec14497988..00000000000 --- a/mps/code/prmci3w3.c +++ /dev/null @@ -1,120 +0,0 @@ -/* prmci3w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * PURPOSE - * - * .purpose: This module implements the part of the protection module - * that decodes the MutatorFaultContext. - * - * SOURCES - * - * .source.i486: Intel486 Microprocessor Family Programmer's - * Reference Manual (book.intel92). - * - * ASSUMPTIONS - * - * .assume.regref: The resisters in the context can be modified by - * storing into an MRef pointer. - */ - -#include "prmcw3.h" -#include "prmci3.h" -#include "mpm.h" - -SRCID(prmci3w3, "$Id$"); - - -/* Prmci3AddressHoldingReg -- Return an address for a given machine register */ - -MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum) -{ - PCONTEXT wincont; - - AVER(regnum <= 7); - AVER(regnum >= 0); - - wincont = context->ep->ContextRecord; - - switch (regnum) { - case 0: return (MRef)&wincont->Eax; - case 1: return (MRef)&wincont->Ecx; - case 2: return (MRef)&wincont->Edx; - case 3: return (MRef)&wincont->Ebx; - case 4: return (MRef)&wincont->Esp; - case 5: return (MRef)&wincont->Ebp; - case 6: return (MRef)&wincont->Esi; - case 7: return (MRef)&wincont->Edi; - } - NOTREACHED; - return NULL; /* suppress warning */ -} - - -/* Prmci3DecodeFaultContext -- decode fault context */ - -void Prmci3DecodeFaultContext(MRef *faultmemReturn, Byte **insvecReturn, - MutatorFaultContext context) -{ - LPEXCEPTION_RECORD er; - - er = context->ep->ExceptionRecord; - - /* Assert that this is an access violation. The computation of */ - /* faultmem depends on this. */ - AVER(er->ExceptionCode == EXCEPTION_ACCESS_VIOLATION); - - *faultmemReturn = (MRef)er->ExceptionInformation[1]; - *insvecReturn = (Byte*)context->ep->ContextRecord->Eip; -} - - -/* Prmci3StepOverIns -- skip an instruction by changing the context */ - -void Prmci3StepOverIns(MutatorFaultContext context, Size inslen) -{ - context->ep->ContextRecord->Eip += (DWORD)inslen; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmci6.h b/mps/code/prmci6.h deleted file mode 100644 index a5ed5c99b77..00000000000 --- a/mps/code/prmci6.h +++ /dev/null @@ -1,65 +0,0 @@ -/* prmci6.h: PROTECTION MUTATOR CONTEXT (x64) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS developers. - */ - -#ifndef prmci6_h -#define prmci6_h - - -#include "mpm.h" - -typedef Word *MRef; /* pointer to a machine word */ - -MRef Prmci6AddressHoldingReg(MutatorFaultContext, unsigned int); - -void Prmci6DecodeFaultContext(MRef *, Byte **, MutatorFaultContext); - -void Prmci6StepOverIns(MutatorFaultContext, Size); - -#endif /* prmci6_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmci6fr.c b/mps/code/prmci6fr.c deleted file mode 100644 index 811d2c8f99d..00000000000 --- a/mps/code/prmci6fr.c +++ /dev/null @@ -1,87 +0,0 @@ -/* prmci6li.c: PROTECTION MUTATOR CONTEXT x64 (FREEBSD) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This module implements the part of the protection module - * that decodes the MutatorFaultContext. - * - * - * ASSUMPTIONS - * - * .sp: The stack pointer in the context is ESP (x86) or RSP (x86_64). - * - * .context.regroots: The root regs are EDI, ESI, EBX, EDX, ECX, EAX (or - * their x86_64 equivalents) are assumed to be recorded in the context at - * pointer-aligned boundaries. - */ - -#include "prmcix.h" -#include "prmci6.h" - -SRCID(prmci6fr, "$Id$"); - - -Addr MutatorFaultContextSP(MutatorFaultContext mfc) -{ - return (Addr)mfc->ucontext->uc_mcontext.mc_rsp; /* .sp */ -} - - -Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) -{ - Res res; - - /* This scans the root registers (.context.regroots). It also unnecessarily - scans the rest of the context. The optimisation to scan only relevant - parts would be machine dependent. */ - res = TraceScanAreaTagged( - ss, - (Addr *)mfc->ucontext, - (Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))) - ); - - return res; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmci6li.c b/mps/code/prmci6li.c deleted file mode 100644 index 532cd386be3..00000000000 --- a/mps/code/prmci6li.c +++ /dev/null @@ -1,150 +0,0 @@ -/* prmci6li.c: PROTECTION MUTATOR CONTEXT x64 (LINUX) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This module implements the part of the protection module - * that decodes the MutatorFaultContext. - * - * - * SOURCES - * - * .source.linux.kernel: Linux kernel source files. - * - * - * ASSUMPTIONS - * - * .sp: The stack pointer in the context is uc_stack.ss_sp. - * - * .context.regroots: The root regs are assumed to be recorded in the context - * at pointer-aligned boundaries. - * - * .assume.regref: The resisters in the context can be modified by - * storing into an MRef pointer. - */ - -#include "prmcix.h" -#include "prmci6.h" - -SRCID(prmci6li, "$Id$"); - - -/* Prmci6AddressHoldingReg -- return an address of a register in a context */ - -MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum) -{ - Word *gregs; - - AVER(regnum <= 15); - AVER(regnum >= 0); - - gregs = (Word *)&mfc->ucontext->uc_mcontext.gregs; - - /* .assume.regref */ - /* The REG_EAX etc. symbols are only present if _GNU_SOURCE is defined. - * Currently this is in lii6gc.gmk in PFMDEFS. */ - switch (regnum) { - case 0: return &gregs[REG_RAX]; - case 1: return &gregs[REG_RCX]; - case 2: return &gregs[REG_RDX]; - case 3: return &gregs[REG_RBX]; - case 4: return &gregs[REG_RSP]; - case 5: return &gregs[REG_RBP]; - case 6: return &gregs[REG_RSI]; - case 7: return &gregs[REG_RDI]; - case 8: return &gregs[REG_R8]; - case 9: return &gregs[REG_R9]; - case 10: return &gregs[REG_R10]; - case 11: return &gregs[REG_R11]; - case 12: return &gregs[REG_R12]; - case 13: return &gregs[REG_R13]; - case 14: return &gregs[REG_R14]; - case 15: return &gregs[REG_R15]; - } - NOTREACHED; - return (MRef)NULL; /* Avoids compiler warning. */ -} - - -/* Prmci3DecodeFaultContext -- decode fault to find faulting address and IP */ - -void Prmci6DecodeFaultContext(MRef *faultmemReturn, - Byte **insvecReturn, - MutatorFaultContext mfc) -{ - /* .source.linux.kernel (linux/arch/x86/mm/fault.c). */ - *faultmemReturn = (MRef)mfc->info->si_addr; - *insvecReturn = (Byte*)mfc->ucontext->uc_mcontext.gregs[REG_RIP]; -} - - -/* Prmci3StepOverIns -- modify context to step over instruction */ - -void Prmci6StepOverIns(MutatorFaultContext mfc, Size inslen) -{ - mfc->ucontext->uc_mcontext.gregs[REG_RIP] += (Word)inslen; -} - - -Addr MutatorFaultContextSP(MutatorFaultContext mfc) -{ - return (Addr)mfc->ucontext->uc_stack.ss_sp; -} - - -Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) -{ - mcontext_t *mc; - Res res; - - /* This scans the root registers (.context.regroots). It also - unnecessarily scans the rest of the context. The optimisation - to scan only relevant parts would be machine dependent. */ - mc = &mfc->ucontext->uc_mcontext; - res = TraceScanAreaTagged(ss, - (Addr *)mc, - (Addr *)((char *)mc + sizeof(*mc))); - return res; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmci6w3.c b/mps/code/prmci6w3.c deleted file mode 100644 index 19ce79906ec..00000000000 --- a/mps/code/prmci6w3.c +++ /dev/null @@ -1,126 +0,0 @@ -/* prmci6w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * PURPOSE - * - * .purpose: This module implements the part of the protection module - * that decodes the MutatorFaultContext. - * - * SOURCES - * - * - * ASSUMPTIONS - * - * .assume.regref: The resisters in the context can be modified by - * storing into an MRef pointer. - */ - -#include "prmcw3.h" -#include "prmci6.h" -#include "mpm.h" - -SRCID(prmci6w3, "$Id$"); - - -/* Prmci6AddressHoldingReg -- Return an address for a given machine register */ - -MRef Prmci6AddressHoldingReg(MutatorFaultContext context, unsigned int regnum) -{ - PCONTEXT wincont; - - AVER(regnum <= 16); - AVER(regnum >= 0); - - wincont = context->ep->ContextRecord; - - switch (regnum) { - case 0: return (MRef)&wincont->Rax; - case 1: return (MRef)&wincont->Rcx; - case 2: return (MRef)&wincont->Rdx; - case 3: return (MRef)&wincont->Rbx; - case 4: return (MRef)&wincont->Rsp; - case 5: return (MRef)&wincont->Rbp; - case 6: return (MRef)&wincont->Rsi; - case 7: return (MRef)&wincont->Rdi; - case 8: return (MRef)&wincont->R8; - case 9: return (MRef)&wincont->R9; - case 10: return (MRef)&wincont->R10; - case 11: return (MRef)&wincont->R11; - case 12: return (MRef)&wincont->R12; - case 13: return (MRef)&wincont->R13; - case 14: return (MRef)&wincont->R14; - case 15: return (MRef)&wincont->R15; - } - NOTREACHED; - return NULL; /* suppress warning */ -} - - -/* Prmci6DecodeFaultContext -- decode fault context */ - -void Prmci6DecodeFaultContext(MRef *faultmemReturn, Byte **insvecReturn, - MutatorFaultContext context) -{ - LPEXCEPTION_RECORD er; - - er = context->ep->ExceptionRecord; - - /* Assert that this is an access violation. The computation of */ - /* faultmem depends on this. */ - AVER(er->ExceptionCode == EXCEPTION_ACCESS_VIOLATION); - - *faultmemReturn = (MRef)er->ExceptionInformation[1]; - *insvecReturn = (Byte*)context->ep->ContextRecord->Rip; -} - - -/* Prmci6StepOverIns -- skip an instruction by changing the context */ - -void Prmci6StepOverIns(MutatorFaultContext context, Size inslen) -{ - context->ep->ContextRecord->Rip += (DWORD64)inslen; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmcix.h b/mps/code/prmcix.h deleted file mode 100644 index a5781118607..00000000000 --- a/mps/code/prmcix.h +++ /dev/null @@ -1,64 +0,0 @@ -/* prmcix.h: PROTECTION MUTATOR CONTEXT (UNIX) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS developers. - */ - -#ifndef prmcix_h -#define prmcix_h - -#include "mpm.h" - -#include - -typedef struct MutatorFaultContextStruct { /* Protection fault context data */ - siginfo_t *info; - ucontext_t *ucontext; -} MutatorFaultContextStruct; - - -#endif /* prmcix_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/prmcw3.h b/mps/code/prmcw3.h deleted file mode 100644 index b83bd6aba7b..00000000000 --- a/mps/code/prmcw3.h +++ /dev/null @@ -1,65 +0,0 @@ -/* prmcw3.h: PROTECTION FOR WIN32 - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MPS developers. - */ - -#ifndef prmcw3_h -#define prmcw3_h - - -#include "mpm.h" - -#include "mpswin.h" - - -typedef struct MutatorFaultContextStruct { /* Protection fault context data */ - LPEXCEPTION_POINTERS ep; /* Windows Exception Pointers */ -} MutatorFaultContextStruct; - - -#endif /* prmcw3_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/protan.c b/mps/code/protan.c deleted file mode 100644 index 51b2edd6df8..00000000000 --- a/mps/code/protan.c +++ /dev/null @@ -1,120 +0,0 @@ -/* protan.c: ANSI MEMORY PROTECTION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * - * DESIGN - * - * - */ - -#include "mpm.h" - -SRCID(protan, "$Id$"); - - -/* ProtSetup -- global protection setup */ - -void ProtSetup(void) -{ - NOOP; -} - - -/* ProtSet -- set the protection for a page */ - -void ProtSet(Addr base, Addr limit, AccessSet pm) -{ - AVER(base < limit); - /* .improve.protset.check: There is nor AccessSetCheck, so we */ - /* don't check it. */ - UNUSED(pm); - NOOP; -} - - -/* ProtSync -- synchronize protection settings with hardware - * - * See . - */ - -void ProtSync(Arena arena) -{ - Bool synced; - - AVERT(Arena, arena); - - do { - Seg seg; - - synced = TRUE; - if (SegFirst(&seg, arena)) { - Addr base; - do { - base = SegBase(seg); - if (SegPM(seg) != AccessSetEMPTY) { /* */ - ShieldEnter(arena); - TraceSegAccess(arena, seg, SegPM(seg)); - ShieldLeave(arena); - synced = FALSE; - } - } while(SegNext(&seg, arena, base)); - } - } while(!synced); -} - - -/* ProtTramp -- protection trampoline */ - -void ProtTramp(void **rReturn, void *(*f)(void *, size_t), - void *p, size_t s) -{ - AVER(rReturn != NULL); - AVER(FUNCHECK(f)); - /* Can't check p and s as they are interpreted by the client */ - - *(rReturn) = (*(f))(p, s); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/proti3.c b/mps/code/proti3.c deleted file mode 100644 index 9f9480f31b0..00000000000 --- a/mps/code/proti3.c +++ /dev/null @@ -1,283 +0,0 @@ -/* proti3.c: PROTECTION MUTATOR CONTEXT (INTEL 386) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .design: See for the generic design of the interface - * which is implemented in this module, including the contracts for the - * functions. - * - * .purpose: This module implements the part of the protection module - * that implements the MutatorFaultContext type. - * - * .requirements: Current requirements are for limited support only, for - * stepping the sorts of instructions that the Dylan compiler might - * generate for table vector access - i.e., a restricted subset of MOV - * addressing modes. This avoids the need to scan entire weak tables at - * an inappropriate rank when a page fault occurs. - * - * - * SOURCES - * - * .source.i486: Intel486 Microprocessor Family Programmer's - * Reference Manual - * - * .source.dylan: Dylan table code implementation. Especially the - * following HOPE units: - * D-lib-dylan!table.dylan (class , slot entry-element) - * D-dfmc-harp-cg!harp-primitives.dylan (method op--repeated-slot-element) - * D-harp-pentium-harp!moves.dylan (pentium-template ld-index) - * - * - * ASSUMPTIONS - * - * .assume.null: It's always safe for Prot*StepInstruction to return - * ResUNIMPL. A null implementation of this module would be overly - * conservative but otherwise correct. - * - * .assume.want: The Dylan implementation is likely to access a - * weak table vector using either MOV r/m32,r32 or MOV r32,r/m32 - * instructions, where the r/m32 operand will be of one of the forms - * disp8[reg], disp8[reg1][reg2], disp8[reg1][reg2*4] (see .source.dylan - * and .source.i486) - * - * .assume.i3: Assume the following about the i386 environment: - * Steppable instructions (.assume.want) use the CS, DS & SS - * segment registers only (see .source.i486 Table 2-3). - * The procesor runs in 32 bit mode. - * The CS, DS and SS segment registers all describe identical 32- - * bit flat address spaces. - */ - -#include "mpm.h" -#include "prmci3.h" - -SRCID(proti3, "$Id$"); - - -/* DecodeCB -- Decode an Intel x86 control byte into Hi, Medium & Low fields */ - -static void DecodeCB(unsigned int *hReturn, - unsigned int *mReturn, - unsigned int *lReturn, - Byte op) -{ - /* see .source.i486 Figure 26-2 */ - unsigned int uop = (unsigned int)op; - *lReturn = uop & 7; - uop = uop >> 3; - *mReturn = uop & 7; - uop = uop >> 3; - *hReturn = uop & 3; -} - - -/* DecodeSIB -- Decode a Scale Index Base byte for an Intel x86 instruction */ - -static void DecodeSIB(unsigned int *sReturn, - unsigned int *iReturn, - unsigned int *bReturn, - Byte op) -{ - DecodeCB(sReturn, iReturn, bReturn, op); -} - - -/* DecodeModRM -- Decode a ModR/M byte for an Intel x86 instruction */ - -static void DecodeModRM(unsigned int *modReturn, - unsigned int *rReturn, - unsigned int *mReturn, - Byte op) -{ - DecodeCB(modReturn, rReturn, mReturn, op); -} - - -/* RegValue -- Return the value of a machine register from a context */ - -static Word RegValue(MutatorFaultContext context, unsigned int regnum) -{ - MRef addr; - - addr = Prmci3AddressHoldingReg(context, regnum); - return *addr; -} - - -/* Return a byte element of an instruction vector as a - * Word value, with sign extension - */ -static Word SignedInsElt(Byte insvec[], Count i) -{ - signed char eltb; - - eltb = ((signed char*)insvec)[i]; - return (Word)eltb; -} - - -/* If a MOV instruction is a sufficiently simple example of a - * move between a register and memory (in either direction), - * then find the register, the effective address and the size - * of the instruction. The instruction is considered sufficiently - * simple if it uses a single byte displacement, a base register, - * and either no index or a (possibly scaled) register. - */ -static Bool DecodeSimpleMov(unsigned int *regnumReturn, - MRef *memReturn, - Size *inslenReturn, - MutatorFaultContext context, - Byte insvec[]) -{ - unsigned int mod; - unsigned int r; - unsigned int m; - - DecodeModRM(&mod, &r, &m, insvec[1]); /* .source.i486 Table 26-3 */ - if(1 == mod) { - /* Only know about single byte displacements, .assume.want */ - Word base; - Word idx; /* can't shadow index(3) */ - Word disp; - - if(4 == m) { - /* There is an index. */ - unsigned int s; - unsigned int i; - unsigned int b; - - DecodeSIB(&s, &i, &b, insvec[2]); /* .source.i486 Table 26-3 */ - if(4 == i) { - return FALSE; /* degenerate SIB form - unused by Dylan compiler */ - } - disp = SignedInsElt(insvec, 3); - base = RegValue(context, b); - idx = RegValue(context, i) << s; - *inslenReturn = 4; - } else { - /* MOV with reg1 & [reg2+byte] parameters */ - disp = SignedInsElt(insvec, 2); - base = RegValue(context, m); - idx = 0; - *inslenReturn = 3; - } - *regnumReturn = r; - *memReturn = (MRef)(base + idx + disp); /* .assume.i3 */ - return TRUE; - } - - return FALSE; -} - - -static Bool IsSimpleMov(Size *inslenReturn, - MRef *srcReturn, - MRef *destReturn, - MutatorFaultContext context) -{ - Byte *insvec; - unsigned int regnum; - MRef mem; - MRef faultmem; - - Prmci3DecodeFaultContext(&faultmem, &insvec, context); - - /* .assume.want */ - /* .source.i486 Page 26-210 */ - if((Byte)0x8b == insvec[0]) { - /* This is an instruction of type MOV reg, r/m32 */ - if(DecodeSimpleMov(®num, &mem, inslenReturn, context, insvec)) { - AVER(faultmem == mem); /* Ensure computed address matches exception */ - *srcReturn = mem; - *destReturn = Prmci3AddressHoldingReg(context, regnum); - return TRUE; - } - } else if((Byte)0x89 == insvec[0]) { - /* This is an instruction of type MOV r/m32, reg */ - if(DecodeSimpleMov(®num, &mem, inslenReturn, context, insvec)) { - AVER(faultmem == mem); /* Ensure computed address matches exception */ - *destReturn = mem; - *srcReturn = Prmci3AddressHoldingReg(context, regnum); - return TRUE; - } - } - - return FALSE; -} - - -Bool ProtCanStepInstruction(MutatorFaultContext context) -{ - Size inslen; - MRef src; - MRef dest; - - /* .assume.null */ - /* .assume.want */ - if(IsSimpleMov(&inslen, &src, &dest, context)) { - return TRUE; - } - - return FALSE; -} - - -Res ProtStepInstruction(MutatorFaultContext context) -{ - Size inslen; - MRef src; - MRef dest; - - /* .assume.null */ - /* .assume.want */ - if(IsSimpleMov(&inslen, &src, &dest, context)) { - *dest = *src; - Prmci3StepOverIns(context, inslen); - return ResOK; - } - - return ResUNIMPL; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/proti6.c b/mps/code/proti6.c deleted file mode 100644 index 37940f1103e..00000000000 --- a/mps/code/proti6.c +++ /dev/null @@ -1,124 +0,0 @@ -/* proti6.c: PROTECTION MUTATOR CONTEXT (x64) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .design: See for the generic design of the interface - * which is implemented in this module, including the contracts for the - * functions. - * - * .purpose: This module implements the part of the protection module - * that implements the MutatorFaultContext type. - * - * - * SOURCES - * - * .source.amd64: AMD64 Architecture Programmer’s Manual Volume 3: - * General-Purpose and System Instructions - * - * - * - * ASSUMPTIONS - * - * .assume.null: It's always safe for Prot*StepInstruction to return - * ResUNIMPL. A null implementation of this module would be overly - * conservative but otherwise correct. - * - */ - -#include "mpm.h" -#include "prmci6.h" - -SRCID(proti6, "$Id$"); - - -static Bool IsSimpleMov(Size *inslenReturn, - MRef *srcReturn, - MRef *destReturn, - MutatorFaultContext context) -{ - Byte *insvec; - MRef faultmem; - - Prmci6DecodeFaultContext(&faultmem, &insvec, context); - /* Unimplemented */ - UNUSED(inslenReturn); - UNUSED(srcReturn); - UNUSED(destReturn); - - return FALSE; -} - - -Bool ProtCanStepInstruction(MutatorFaultContext context) -{ - Size inslen; - MRef src; - MRef dest; - - /* .assume.null */ - if(IsSimpleMov(&inslen, &src, &dest, context)) { - return TRUE; - } - - return FALSE; -} - - -Res ProtStepInstruction(MutatorFaultContext context) -{ - Size inslen; - MRef src; - MRef dest; - - /* .assume.null */ - if(IsSimpleMov(&inslen, &src, &dest, context)) { - *dest = *src; - Prmci6StepOverIns(context, inslen); - return ResOK; - } - - return ResUNIMPL; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/protix.c b/mps/code/protix.c deleted file mode 100644 index 31c272bc5b9..00000000000 --- a/mps/code/protix.c +++ /dev/null @@ -1,175 +0,0 @@ -/* protix.c: PROTECTION FOR UNIX - * - * $Id$ - * Copyright (c) 2001,2007 Ravenbrook Limited. See end of file for license. - * - * Somewhat generic across different Unix systems. Shared between - * Darwin (OS X), FreeBSD, and Linux. - * - * This file does not contain a signal handler. That's in protsgix.c - * (for FreeBSD and Darwin on Intel); in protxcpp.c (for Darwin on - * PowerPC); in protlii3.c (for Intel Linux). - * - * - * SOURCES - * - * [SUSV2MPROTECT] Single UNIX Specification, Version 2, mprotect man - * page: - * http://opengroup.org/onlinepubs/007908799/xsh/mprotect.html - * - * ASSUMPTIONS - * - * .assume.mprotect.base: We assume that the first argument to mprotect can - * be safely passed as a void *. Single UNIX Specification Version 2 - * (aka X/OPEN XSH5) says that the parameter is a void *. Some - * Unix-likes may declare this parameter as a caddr_t. FreeBSD used to - * do this (on the now very obsolete FreeBSD 2.2.x series). The - * Darwin man page documents it as caddr_t but it appears to be - * implemented correctly as void *. caddr_t is usually char *. - * - * .assume.write-only: More of an anti-assumption really. We - * assume that asking the OS for a write-only page (that is, flags = - * PROT_WRITE) does not work. What actually happens on all the - * Unix-like OSes that we've seen is that asking for write-permission - * (flags = PROT_WRITE) grants read-permission as well. That is why - * when the MPS requires that a page be read-protected (mode == - * AccessREAD) we must ensure that writes are also not allowed. - * The portable guarantees of mprotect (see [SUSV2MPROTECT]) are that - * writes are not permitted where PROT_WRITE is not used and no access - * is permitted when PROT_NONE alone is used. - */ - -#include "mpm.h" - -#if !defined(MPS_OS_LI) && !defined(MPS_OS_FR) && !defined(MPS_OS_XC) -#error "protix.c is Unix-specific, currently for MPS_OS_LI FR XC" -#endif -#ifndef PROTECTION -#error "protix.c implements protection, but PROTECTION is not set" -#endif - -#include -#include - -#include -#include - -SRCID(protix, "$Id$"); - -/* ProtSet -- set protection - * - * This is just a thin veneer on top of mprotect(2). - */ - -void ProtSet(Addr base, Addr limit, AccessSet mode) -{ - int flags; - - AVER(sizeof(size_t) == sizeof(Addr)); - AVER(base < limit); - AVER(base != 0); - AVER(AddrOffset(base, limit) <= INT_MAX); /* should be redundant */ - - /* Convert between MPS AccessSet and UNIX PROT thingies. - In this function, AccessREAD means protect against read accesses - (disallow them). PROT_READ means allow read accesses. Notice that - this follows a difference in contract as well as style. AccessREAD - means that no reads should be permitted (all reads should go via - the signal handler), possibly other operations (write) also go via - the signal handler; PROT_WRITE means that all writes should be - allowed, possibly that means other operations (read) are also - allowed. - */ - switch(mode) { - case AccessWRITE | AccessREAD: - case AccessREAD: /* forbids writes as well, see .assume.write-only */ - flags = PROT_NONE; - break; - case AccessWRITE: - flags = PROT_READ | PROT_EXEC; - break; - case AccessSetEMPTY: - flags = PROT_READ | PROT_WRITE | PROT_EXEC; - break; - default: - NOTREACHED; - flags = PROT_NONE; - } - - /* .assume.mprotect.base */ - if(mprotect((void *)base, (size_t)AddrOffset(base, limit), flags) != 0) - NOTREACHED; -} - - -/* ProtSync -- synchronize protection settings with hardware - * - * This does nothing under Posix. See protan.c. - */ - -void ProtSync(Arena arena) -{ - UNUSED(arena); - NOOP; -} - - -/* ProtTramp -- protection trampoline - * - * The protection trampoline is trivial under Unix, as there is - * nothing that needs to be done in the dynamic context of the mutator in - * order to catch faults. (Contrast this with Win32 Structured Exception - * Handling.) - */ - -void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), - void *p, size_t s) -{ - AVER(resultReturn != NULL); - AVER(FUNCHECK(f)); - /* Can't check p and s as they are interpreted by the client */ - - *resultReturn = (*f)(p, s); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2007 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/protli.c b/mps/code/protli.c deleted file mode 100644 index ba48cab7f51..00000000000 --- a/mps/code/protli.c +++ /dev/null @@ -1,182 +0,0 @@ -/* protli.c: PROTECTION FOR LINUX (INTEL 386) - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * SOURCES - * - * .source.i486: Intel486 Microprocessor Family Programmer's - * Reference Manual - * - * .source.linux.kernel: Linux kernel source files. - */ - -#include "prmcix.h" - -#ifndef MPS_OS_LI -#error "protli.c is Linux-specific, but MPS_OS_LI is not set" -#endif -#ifndef PROTECTION -#error "protli.c implements protection, but PROTECTION is not set" -#endif - -#include -#include -#include -#include -#include - -SRCID(protli, "$Id$"); - - - -/* The previously-installed signal action, as returned by */ -/* sigaction(3). See ProtSetup. */ - -static struct sigaction sigNext; - - -/* sigHandle -- protection signal handler - * - * This is the signal handler installed by ProtSetup to deal with - * protection faults. It is installed on the SIGSEGV signal. - * It decodes the protection fault details from the signal context - * and passes them to ArenaAccess, which attempts to handle the - * fault and remove its cause. If the fault is handled, then - * the handler returns and execution resumes. If it isn't handled, - * then sigHandle does its best to pass the signal on to the - * previously installed signal handler (sigNext). - * - * .sigh.context: We check si_code for being a memory access - * si_addr gives the fault address. See - * .source.linux.kernel (linux/arch/i386/mm/fault.c and - * linux/arch/x86/mm/fault.c). - * - * .sigh.addr: We assume that the OS decodes the address to something - * sensible - */ - -/* This is defined here to keep the sources closer to those in protsgix.c - * They can't be merged yet because protsgix doesn't pass the context to - * ArenaAccess */ - -#define PROT_SIGNAL SIGSEGV - -static void sigHandle(int sig, siginfo_t *info, void *context) /* .sigh.args */ -{ - int e; - /* sigset renamed to asigset due to clash with global on Darwin. */ - sigset_t asigset, oldset; - struct sigaction sa; - - AVER(sig == PROT_SIGNAL); - - if(info->si_code == SEGV_ACCERR) { /* .sigh.context */ - AccessSet mode; - Addr base; - ucontext_t *ucontext; - MutatorFaultContextStruct mfContext; - - ucontext = (ucontext_t *)context; - mfContext.ucontext = ucontext; - mfContext.info = info; - - /* on linux we used to be able to tell whether this was a read or a write */ - mode = AccessREAD | AccessWRITE; - - /* We assume that the access is for one word at the address. */ - base = (Addr)info->si_addr; /* .sigh.addr */ - /* limit = AddrAdd(base, (Size)sizeof(Addr)); */ - - /* Offer each protection structure the opportunity to handle the */ - /* exception. If it succeeds, then allow the mutator to continue. */ - - if(ArenaAccess(base, mode, &mfContext)) - return; - } - - /* The exception was not handled by any known protection structure, */ - /* so throw it to the previously installed handler. That handler won't */ - /* get an accurate context (the MPS would fail if it were the second in */ - /* line) but it's the best we can do. */ - - e = sigaction(PROT_SIGNAL, &sigNext, &sa); - AVER(e == 0); - sigemptyset(&asigset); - sigaddset(&asigset, PROT_SIGNAL); - e = sigprocmask(SIG_UNBLOCK, &asigset, &oldset); - AVER(e == 0); - kill(getpid(), PROT_SIGNAL); - e = sigprocmask(SIG_SETMASK, &oldset, NULL); - AVER(e == 0); - e = sigaction(PROT_SIGNAL, &sa, NULL); - AVER(e == 0); -} - - -/* ProtSetup -- global protection setup - * - * Under Linux, the global setup involves installing a signal handler - * on SIGSEGV to catch and handle page faults (see sigHandle). - * The previous handler is recorded so that it can be reached from - * sigHandle if it fails to handle the fault. - * - * NOTE: There are problems with this approach: - * 1. we can't honor the sa_flags for the previous handler, - * 2. what if this thread is suspended just after calling signal(3)? - * The sigNext variable will never be initialized! - */ - -void ProtSetup(void) -{ - struct sigaction sa; - int result; - - sa.sa_sigaction = sigHandle; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; - - result = sigaction(PROT_SIGNAL, &sa, &sigNext); - AVER(result == 0); -} - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/protocol.c b/mps/code/protocol.c deleted file mode 100644 index 6a53613d54b..00000000000 --- a/mps/code/protocol.c +++ /dev/null @@ -1,166 +0,0 @@ -/* pool.c: PROTOCOL IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * DESIGN - * - * .design: See - */ - -#include "mpm.h" - -SRCID(protocol, "$Id$"); - - -/* ProtocolClassCheck -- check a protocol class */ - -Bool ProtocolClassCheck(ProtocolClass class) -{ - CHECKS(ProtocolClass, class); - CHECKS(ProtocolClass, class->superclass); - CHECKL(FUNCHECK(class->coerceInst)); - CHECKL(FUNCHECK(class->coerceClass)); - return TRUE; -} - - -/* ProtocolInstCheck -- check a protocol instance */ - -Bool ProtocolInstCheck(ProtocolInst inst) -{ - CHECKS(ProtocolInst, inst); - CHECKL(ProtocolClassCheck(inst->class)); - return TRUE; -} - - -/* ProtocolIsSubclass -- a predicate for testing subclass relationships - * - * A protocol class is always a subclass of itself. This is implemented - * via the coerceClass method provided by each class. - */ -Bool ProtocolIsSubclass(ProtocolClass sub, ProtocolClass super) -{ - ProtocolClass coerced; - - AVERT(ProtocolClass, sub); - AVERT(ProtocolClass, super); - - if (sub->coerceClass(&coerced, sub, super)) { - AVERT(ProtocolClass, coerced); - return TRUE; - } else { - return FALSE; - } -} - - -/* ProtocolCoerceClass -- the default method for coerceClass - * - * This default method must be inherited by any subclass - * which does not perform a multiple inheritance. - */ -static Bool ProtocolCoerceClass(ProtocolClass *coerceResult, - ProtocolClass proClass, - ProtocolClass super) -{ - ProtocolClass p = proClass; - ProtocolClass root = ProtocolClassGet(); - - AVERT(ProtocolClass, proClass); - AVERT(ProtocolClass, super); - AVERT(ProtocolClass, root); - - while (p != super) { - AVERT(ProtocolClass, p); - if (p == root) - return FALSE; - p = p->superclass; - } - *coerceResult = proClass; - return TRUE; -} - - -/* ProtocolCoerceInst -- the default method for coerceInst - * - * This default method must be inherited by any subclass - * which does not perform a multiple inheritance. - */ -static Bool ProtocolCoerceInst(ProtocolInst *coerceResult, - ProtocolInst proInst, - ProtocolClass super) -{ - ProtocolClass p = proInst->class; - ProtocolClass root = ProtocolClassGet(); - - AVERT(ProtocolInst, proInst); - AVERT(ProtocolClass, super); - AVERT(ProtocolClass, root); - - while (p != super) { - AVERT(ProtocolClass, p); - if (p == root) - return FALSE; - p = p->superclass; - } - *coerceResult = proInst; - return TRUE; -} - - -/* The class definition for the root of the hierarchy */ - -DEFINE_CLASS(ProtocolClass, theClass) -{ - theClass->sig = ProtocolClassSig; - theClass->superclass = theClass; - theClass->coerceInst = ProtocolCoerceInst; - theClass->coerceClass = ProtocolCoerceClass; -} - - - - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/protocol.h b/mps/code/protocol.h deleted file mode 100644 index 4c70738e8f8..00000000000 --- a/mps/code/protocol.h +++ /dev/null @@ -1,228 +0,0 @@ -/* protocol.h: PROTOCOL INHERITANCE DEFINITIONS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef protocol_h -#define protocol_h - -#include "config.h" -#include "mpmtypes.h" - - -/* Name derivation macros. These are not intended to be used */ -/* outside of this file */ - -#define DERIVE_LOCAL(name) protocol ## name -#define DERIVE_STRUCT(name) name ## Struct -#define DERIVE_ENSURE(name) name ## Get -#define DERIVE_ENSURE_OLD(name) Ensure ## name -#define DERIVE_ENSURE_INTERNAL(name) protocolGet ## name -#define DERIVE_GUARDIAN(name) protocol ## name ## Guardian -#define DERIVE_STATIC_STORAGE(name) protocol ## name ## Struct - - -/* Macro to set the superclass field. This is not intended */ -/* to be used outside this file. This is a polymorphic macro */ -/* named as a function. See */ - -#define ProtocolClassSetSuperclassPoly(class, super) \ - (((ProtocolClass)(class))->superclass) = (ProtocolClass)(super) - - -/* DEFINE_CLASS -- the standard macro for defining a ProtocolClass */ - -#define DEFINE_CLASS(className, var) \ - static Bool DERIVE_GUARDIAN(className) = FALSE; \ - static DERIVE_STRUCT(className) DERIVE_STATIC_STORAGE(className); \ - static void DERIVE_ENSURE_INTERNAL(className)(className); \ - extern className DERIVE_ENSURE(className)(void); \ - className DERIVE_ENSURE(className)(void) \ - { \ - if (DERIVE_GUARDIAN(className) == FALSE) { \ - LockClaimGlobalRecursive(); \ - if (DERIVE_GUARDIAN(className) == FALSE) { \ - DERIVE_ENSURE_INTERNAL(className) \ - (&DERIVE_STATIC_STORAGE(className)); \ - DERIVE_GUARDIAN(className) = TRUE; \ - } \ - LockReleaseGlobalRecursive(); \ - } \ - return &DERIVE_STATIC_STORAGE(className); \ - } \ - /* old name for backward compatibility */ \ - extern className DERIVE_ENSURE_OLD(className)(void); \ - className DERIVE_ENSURE_OLD(className)(void) \ - { \ - return DERIVE_ENSURE(className)(); \ - } \ - static void DERIVE_ENSURE_INTERNAL(className) (className var) - - -/* INHERIT_CLASS -- the standard macro for inheriting from a superclass */ - -#define INHERIT_CLASS(this, parentName) \ - BEGIN \ - parentName DERIVE_LOCAL(parentName) = DERIVE_ENSURE(parentName)(); \ - *this = *(DERIVE_LOCAL(parentName)); \ - ProtocolClassSetSuperclassPoly(this, DERIVE_LOCAL(parentName)); \ - END - - -/* DEFINE_ALIAS_CLASS -- define a new class for the same type - * - * A convenience macro. Aliases the structure and pointer types - * for className to be the same as typeName, and then defines - * the class className. - */ -#define DEFINE_ALIAS_CLASS(className, typeName, var) \ - typedef typeName className; \ - typedef DERIVE_STRUCT(typeName) DERIVE_STRUCT(className); \ - DEFINE_CLASS(className, var) - - - -#define ProtocolClassSig ((Sig)0x519B60C7) /* SIGnature PROtocol CLass */ -#define ProtocolInstSig ((Sig)0x519B6014) /* SIGnature PROtocol INst */ - - -/* ProtocolClass -- the class containing the support for the protocol */ - -typedef struct ProtocolClassStruct *ProtocolClass; - - -/* ProtocolInst -- the instance structure for support of the protocol */ - -typedef struct ProtocolInstStruct *ProtocolInst; - - -/* ProtocolCoerceInstMethod -- coerce "pro" to an instance of "interface" - * - * If "pro" is an instance of "interface", then returns TRUE - * and sets coerceResult to point directly to the part of "pro" - * which contains the slots for "interface" - * RHSK 2006-04-05 s/interface/interfaceIn/: job000605, suspect msvc bug. - */ -typedef Bool (*ProtocolCoerceInstMethod)(ProtocolInst *coerceResult, - ProtocolInst pro, - ProtocolClass interfaceIn); - -/* ProtocolCoerceClassMethod -- coerce "proClass" to an "interface" class - * - * If "proClass" is a subclass of "interface", then returns TRUE - * and sets coerceResult to point directly to the part of - * "proClass" which contains the slots for "interface". - * RHSK 2006-04-05 s/interface/interfaceIn/: job000605, suspect msvc bug. - */ -typedef Bool (*ProtocolCoerceClassMethod)(ProtocolClass *coerceResult, - ProtocolClass proClass, - ProtocolClass interfaceIn); - - - -typedef struct ProtocolClassStruct { - Sig sig; /* */ - ProtocolClass superclass; /* the superclass */ - ProtocolCoerceInstMethod coerceInst; /* coerce instance to super */ - ProtocolCoerceClassMethod coerceClass; /* coerce class to superclass */ -} ProtocolClassStruct; - - -typedef struct ProtocolInstStruct { - Sig sig; /* */ - ProtocolClass class; /* the class */ -} ProtocolInstStruct; - - -/* ProtocolClassGet -- Returns the root of the protocol class hierarchy - * - * Function name conforms to standard conventions for - * protocols. - */ -extern ProtocolClass ProtocolClassGet(void); - - -/* Checking functions */ - -extern Bool ProtocolClassCheck(ProtocolClass class); -extern Bool ProtocolInstCheck(ProtocolInst pro); - - -/* ProtocolIsSubclass - use macro IsSubclass to access this. - * - * A predicate for testing subclass relationships. - * A protocol class is always a subclass of itself. - */ -extern Bool ProtocolIsSubclass(ProtocolClass sub, ProtocolClass super); - - -/* Protocol introspection interface */ - -/* The following are macros because of the need to cast */ -/* subtypes of ProtocolClass. Nevertheless they are named */ -/* as functions. See */ - - -#define ProtocolClassSuperclassPoly(class) \ - (((ProtocolClass)(class))->superclass) - -#define ClassOfPoly(inst) ((ProtocolInst)(inst)->class) - -#define IsSubclassPoly(sub, super) \ - ProtocolIsSubclass((ProtocolClass)(sub), (ProtocolClass)(super)) - - -/* SUPERCLASS - get the superclass object, given a class name - * - * Returns the superclass, with type ProtocolClass. Clients will - * probably wish to cast this. See - * - */ -#define SUPERCLASS(className) \ - ProtocolClassSuperclassPoly(DERIVE_ENSURE(className)()) - - -#endif /* protocol_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/protsgix.c b/mps/code/protsgix.c deleted file mode 100644 index 39f19c90b4c..00000000000 --- a/mps/code/protsgix.c +++ /dev/null @@ -1,183 +0,0 @@ -/* protsgix.c: PROTECTION (SIGNAL HANDLER) FOR UNIX - * - * $Id$ - * Copyright (c) 2001-2007 Ravenbrook Limited. See end of file for license. - * - * Would ordinarily be part of protix.c (as the code is common to more - * than one Unix-like operating system), but PowerPC Darwin requires a - * different implementation of this module. - * - * SOURCES - * - * .source.man: sigaction(2): FreeBSD System Calls Manual. - * - * .source.merge: A blend from primarily the FreeBSD version (protfri3.c) - * and the OSF/1 (DIGITAL UNIX) version (proto1.c); influenced by other - * Unix versions. - */ - -#include "mpm.h" - -#if !defined(MPS_OS_XC) && !defined(MPS_OS_FR) -#error "protsgix.c is Unix-specific, currently for MPS_OS_FR or XC" -#endif -#if defined(MPS_OS_XC) && defined(MPS_ARCH_PP) -#error "protsgix.c does not work on Darwin on PowerPC. Use protxcpp.c" -#endif -#ifndef PROTECTION -#error "protsgix.c implements protection, but PROTECTION is not set" -#endif - -#include /* for many functions */ -#include /* for getpid */ -#include /* for getpid */ - -SRCID(protsgix, "$Id$"); - - -/* The previously-installed signal action, as returned by */ -/* sigaction(3). See ProtSetup. */ - -static struct sigaction sigNext; - -/* sigHandle -- protection signal handler - * - * This is the signal handler installed by ProtSetup to deal with - * protection faults. It is installed on the PROT_SIGNAL (a macro - * defined according to the platform in config.h) signal. It - * decodes the protection fault details from the signal context and - * passes them to ArenaAccess, which attempts to handle the fault and - * remove its cause. If the fault is handled, then the handler - * returns and execution resumes. If it isn't handled, then - * sigHandle does its best to pass the signal on to the previously - * installed signal handler (sigNext); which it does by signalling - * itself using kill(2). - * - * .sigh.args: The sigaction manual page .source.man documents three - * different handler prototypes: ANSI C sa_handler, traditional BSD - * sa_handler, and POSIX SA_SIGINFO sa_sigaction. The ANSI C - * prototype isn't powerful enough for us (can't get addresses), and - * the manual page deprecates the BSD sa_handler in favour of the - * POSIX SA_SIGINFO sa_sigaction. In that prototype, the arguments - * are: signal number, pointer to signal info structure, pointer to - * signal context structure. - * - * .sigh.context: We use the PROT_SIGINFO_GOOD macro to (usually) check - * the info->si_code. The macro is platform dependent and defined in - * config.h. We assume that info->si_addr is the fault address. This - * assumption turns out to fail for PowerPC Darwin (we use protxcpp.c - * there). - * - * .sigh.mode: The fault type (read/write) does not appear to be - * available to the signal handler (see mail archive). - */ - -static void sigHandle(int sig, siginfo_t *info, void *context) /* .sigh.args */ -{ - int e; - /* sigset renamed to asigset due to clash with global on Darwin. */ - sigset_t asigset, oldset; - struct sigaction sa; - - UNUSED(context); - AVER(sig == PROT_SIGNAL); - - /* .sigh.context */ - if(PROT_SIGINFO_GOOD(info)) { - AccessSet mode; - Addr base; - - mode = AccessREAD | AccessWRITE; /* .sigh.mode */ - - /* We assume that the access is for one word at the address. */ - base = (Addr)info->si_addr; /* .sigh.context */ - - /* Offer each protection structure the opportunity to handle the */ - /* exception. If it succeeds, then allow the mutator to continue. */ - if(ArenaAccess(base, mode, NULL)) - return; - } - - /* The exception was not handled by any known protection structure, */ - /* so throw it to the previously installed handler. */ - - e = sigaction(PROT_SIGNAL, &sigNext, &sa); - AVER(e == 0); - sigemptyset(&asigset); - sigaddset(&asigset, PROT_SIGNAL); - e = sigprocmask(SIG_UNBLOCK, &asigset, &oldset); - AVER(e == 0); - kill(getpid(), PROT_SIGNAL); - e = sigprocmask(SIG_SETMASK, &oldset, NULL); - AVER(e == 0); - e = sigaction(PROT_SIGNAL, &sa, NULL); - AVER(e == 0); -} - - -/* ProtSetup -- global protection setup - * - * Under Unix, the global setup involves installing a signal - * handler on PROT_SIGNAL to catch and handle page faults (see - * sigHandle). The previous handler is recorded so that it can be - * reached from sigHandle if it fails to handle the fault. - * - * NOTE: There are problems with this approach: - * 1. we can't honor the sa_flags for the previous handler, - * 2. what if this thread is suspended just after calling signal(3)? - * The sigNext variable will never be initialized! */ - -void ProtSetup(void) -{ - struct sigaction sa; - int result; - - sa.sa_sigaction = sigHandle; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; - - result = sigaction(PROT_SIGNAL, &sa, &sigNext); - AVER(result == 0); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2007 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/protw3.c b/mps/code/protw3.c deleted file mode 100644 index 88f5e8bbdbe..00000000000 --- a/mps/code/protw3.c +++ /dev/null @@ -1,178 +0,0 @@ -/* protw3.c: PROTECTION FOR WIN32 - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" -/* prmcw3.h needed to share MutatorFaultContextStruct declation */ -/* with */ -#include "prmcw3.h" - -#ifndef MPS_OS_W3 -#error "protw3.c is Win32-specific, but MPS_OS_W3 is not set" -#endif -#ifndef PROTECTION -#error "protw3.c implements protection, but PROTECTION is not set" -#endif - -#include "mpswin.h" - -SRCID(protw3, "$Id$"); - - -void ProtSetup(void) -{ - return; -} - - -void ProtSet(Addr base, Addr limit, AccessSet mode) -{ - DWORD newProtect; - DWORD oldProtect; - - AVER(base < limit); - AVER(base != 0); - - newProtect = PAGE_EXECUTE_READWRITE; - if((mode & AccessWRITE) != 0) - newProtect = PAGE_EXECUTE_READ; - if((mode & AccessREAD) != 0) - newProtect = PAGE_NOACCESS; - - if(VirtualProtect((LPVOID)base, (SIZE_T)AddrOffset(base, limit), - newProtect, &oldProtect) == 0) - NOTREACHED; -} - - -LONG ProtSEHfilter(LPEXCEPTION_POINTERS info) -{ - LPEXCEPTION_RECORD er; - ULONG_PTR iswrite; - ULONG_PTR address; - AccessSet mode; - Addr base, limit; - LONG action; - MutatorFaultContextStruct context; - - er = info->ExceptionRecord; - - if(er->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) - return EXCEPTION_CONTINUE_SEARCH; - - context.ep = info; - - /* assert that the exception is continuable */ - /* Note that Microsoft say that this field should be 0 or */ - /* EXCEPTION_NONCONTINUABLE, but this is not true */ - AVER((er->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == 0); - - /* er->ExceptionRecord is pointer to next exception in chain */ - /* er->ExceptionAddress is where exception occurred */ - - AVER(er->NumberParameters >= 2); - - iswrite = er->ExceptionInformation[0]; /* 0 read; 1 write */ - AVER(iswrite == 0 || iswrite == 1); - - /* Pages cannot be made write-only, so an attempt to write must - * also cause a read-access if necessary */ - if(iswrite) - mode = AccessREAD | AccessWRITE; - else - mode = AccessREAD; - - address = er->ExceptionInformation[1]; - - base = (Addr)address; - limit = AddrAdd(address, sizeof(Addr)); - - if(base < limit) { - if(ArenaAccess(base, mode, &context)) - action = EXCEPTION_CONTINUE_EXECUTION; - else - action = EXCEPTION_CONTINUE_SEARCH; - } else { - /* Access on last sizeof(Addr) (ie 4 on this platform) bytes */ - /* in memory. We assume we can't get this page anyway (see */ - /* ) so it can't be our fault. */ - action = EXCEPTION_CONTINUE_SEARCH; - } - - return action; -} - - -/* ProtSync -- synchronize protection settings with hardware - * - * This does nothing under Win32. See protan.c. - */ - -void ProtSync(Arena arena) -{ - UNUSED(arena); - NOOP; -} - - -void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), - void *p, size_t s) -{ - void *result = NULL; /* stop warnings about uninitialized result */ - - AVER(resultReturn != NULL); - AVER(FUNCHECK(f)); - /* Can't check p and s as they are interpreted by the client */ - - __try { - result = f(p, s); - } __except(ProtSEHfilter(GetExceptionInformation())) { - NOTREACHED; - } - - *resultReturn = result; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/pthrdext.c b/mps/code/pthrdext.c deleted file mode 100644 index ab50a999ff5..00000000000 --- a/mps/code/pthrdext.c +++ /dev/null @@ -1,405 +0,0 @@ -/* pthreadext.c: POSIX THREAD EXTENSIONS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: Provides extension to Pthreads. - * - * .design: see - * - * .acknowledgements: This was derived from code posted to - * comp.programming.threads by Dave Butenhof and Raymond Lau - * (, ). - */ - - -#include "mpm.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "pthrdext.h" - -SRCID(pthreadext, "$Id$"); - - -/* PTHREADEXT_SIGSUSPEND, PTHREADEXT_SIGRESUME -- signals used - * - * See - */ - -#define PTHREADEXT_SIGSUSPEND SIGXFSZ -#define PTHREADEXT_SIGRESUME SIGXCPU - - -/* Static data initiatialized on first use of the module - * See .* - */ - -/* mutex */ -static pthread_mutex_t pthreadextMut = PTHREAD_MUTEX_INITIALIZER; - -/* semaphore */ -static sem_t pthreadextSem; - -/* initialization support */ -static pthread_once_t pthreadextOnce = PTHREAD_ONCE_INIT; -static Bool pthreadextModuleInitialized = FALSE; - - -/* Global variables protected by the mutex - * See .* - */ - -static PThreadext suspendingVictim = NULL; /* current victim */ -static RingStruct suspendedRing; /* PThreadext suspend ring */ - - -/* suspendSignalHandler -- signal handler called when suspending a thread - * - * See - * - * The interface for determining the MFC might be platform specific. - * - * Handle PTHREADEXT_SIGSUSPEND in the target thread, to suspend it until - * receiving PTHREADEXT_SIGRESUME (resume). Note that this is run with both - * PTHREADEXT_SIGSUSPEND and PTHREADEXT_SIGRESUME blocked. Having - * PTHREADEXT_SIGRESUME blocked prevents a resume before we can finish the - * suspend protocol. - */ - -#include "prmcix.h" - -static void suspendSignalHandler(int sig, - siginfo_t *info, - void *context) -{ - sigset_t signal_set; - ucontext_t ucontext; - MutatorFaultContextStruct mfContext; - - AVER(sig == PTHREADEXT_SIGSUSPEND); - UNUSED(sig); - - AVER(suspendingVictim != NULL); - /* copy the ucontext structure so we definitely have it on our stack, - * not (e.g.) shared with other threads. */ - ucontext = *(ucontext_t *)context; - mfContext.ucontext = &ucontext; - suspendingVictim->suspendedMFC = &mfContext; - /* Block all signals except PTHREADEXT_SIGRESUME while suspended. */ - sigfillset(&signal_set); - sigdelset(&signal_set, PTHREADEXT_SIGRESUME); - sem_post(&pthreadextSem); - sigsuspend(&signal_set); - - /* Once here, the resume signal handler has run to completion. */ - return; -} - - -/* resumeSignalHandler -- signal handler called when resuming a thread - * - * See - */ - -static void resumeSignalHandler(int sig) -{ - AVER(sig == PTHREADEXT_SIGRESUME); - UNUSED(sig); - return; -} - -/* PThreadextModuleInit -- Initialize the PThreadext module - * - * See - * - * Dynamically initialize all state when first used - * (called by pthread_once). - */ - -static void PThreadextModuleInit(void) -{ - int status; - struct sigaction pthreadext_sigsuspend, pthreadext_sigresume; - - AVER(pthreadextModuleInitialized == FALSE); - - /* Initialize the ring of suspended threads */ - RingInit(&suspendedRing); - - /* Initialize the semaphore */ - status = sem_init(&pthreadextSem, 0, 0); - AVER(status != -1); - - /* Install the signal handlers for suspend/resume. */ - /* We add PTHREADEXT_SIGRESUME to the sa_mask field for the */ - /* PTHREADEXT_SIGSUSPEND handler. That avoids a race if one thread */ - /* suspends the target while another resumes that same target. (The */ - /* PTHREADEXT_SIGRESUME signal cannot be delivered before the */ - /* target thread calls sigsuspend.) */ - - status = sigemptyset(&pthreadext_sigsuspend.sa_mask); - AVER(status == 0); - status = sigaddset(&pthreadext_sigsuspend.sa_mask, PTHREADEXT_SIGRESUME); - AVER(status == 0); - - pthreadext_sigsuspend.sa_flags = SA_SIGINFO; - pthreadext_sigsuspend.sa_sigaction = suspendSignalHandler; - pthreadext_sigresume.sa_flags = 0; - pthreadext_sigresume.sa_handler = resumeSignalHandler; - status = sigemptyset(&pthreadext_sigresume.sa_mask); - AVER(status == 0); - - status = sigaction(PTHREADEXT_SIGSUSPEND, &pthreadext_sigsuspend, NULL); - AVER(status == 0); - - status = sigaction(PTHREADEXT_SIGRESUME, &pthreadext_sigresume, NULL); - AVER(status == 0); - - pthreadextModuleInitialized = TRUE; -} - - -/* PThreadextCheck -- check the consistency of a PThreadext structure */ - -extern Bool PThreadextCheck(PThreadext pthreadext) -{ - int status; - - status = pthread_mutex_lock(&pthreadextMut); - AVER(status == 0); - - CHECKS(PThreadext, pthreadext); - /* can't check ID */ - CHECKL(RingCheck(&pthreadext->threadRing)); - CHECKL(RingCheck(&pthreadext->idRing)); - if (pthreadext->suspendedMFC == NULL) { - /* not suspended */ - CHECKL(RingIsSingle(&pthreadext->threadRing)); - CHECKL(RingIsSingle(&pthreadext->idRing)); - } else { - /* suspended */ - Ring node, next; - CHECKL(!RingIsSingle(&pthreadext->threadRing)); - RING_FOR(node, &pthreadext->idRing, next) { - PThreadext pt = RING_ELT(PThreadext, idRing, node); - CHECKL(pt->id == pthreadext->id); - CHECKL(pt->suspendedMFC == pthreadext->suspendedMFC); - } - } - status = pthread_mutex_unlock(&pthreadextMut); - AVER(status == 0); - - return TRUE; -} - - -/* PThreadextInit -- Initialize a pthreadext */ - -extern void PThreadextInit(PThreadext pthreadext, pthread_t id) -{ - int status; - - /* The first call to init will initialize the package. */ - status = pthread_once(&pthreadextOnce, PThreadextModuleInit); - AVER(status == 0); - - pthreadext->id = id; - pthreadext->suspendedMFC = NULL; - RingInit(&pthreadext->threadRing); - RingInit(&pthreadext->idRing); - pthreadext->sig = PThreadextSig; - AVERT(PThreadext, pthreadext); -} - - -/* PThreadextFinish -- Finish a pthreadext - * - * See - */ - -extern void PThreadextFinish(PThreadext pthreadext) -{ - int status; - - AVERT(PThreadext, pthreadext); - - status = pthread_mutex_lock(&pthreadextMut); - AVER(status == 0); - - if(pthreadext->suspendedMFC == NULL) { - AVER(RingIsSingle(&pthreadext->threadRing)); - AVER(RingIsSingle(&pthreadext->idRing)); - } else { - /* In suspended state: remove from rings. */ - AVER(!RingIsSingle(&pthreadext->threadRing)); - RingRemove(&pthreadext->threadRing); - if(!RingIsSingle(&pthreadext->idRing)) - RingRemove(&pthreadext->idRing); - } - - status = pthread_mutex_unlock(&pthreadextMut); - AVER(status == 0); - - RingFinish(&pthreadext->threadRing); - RingFinish(&pthreadext->idRing); - pthreadext->sig = SigInvalid; -} - - -/* PThreadextSuspend -- suspend a thread - * - * See - */ - -Res PThreadextSuspend(PThreadext target, MutatorFaultContext *contextReturn) -{ - Ring node, next; - Res res; - int status; - - AVERT(PThreadext, target); - AVER(contextReturn != NULL); - AVER(target->suspendedMFC == NULL); /* multiple suspends illegal */ - - /* Serialize access to suspend, makes life easier */ - status = pthread_mutex_lock(&pthreadextMut); - AVER(status == 0); - AVER(suspendingVictim == NULL); - - /* Threads are added to the suspended ring on suspension */ - /* If the same thread Id has already been suspended, then */ - /* don't signal the thread, just add the target onto the id ring */ - RING_FOR(node, &suspendedRing, next) { - PThreadext alreadySusp = RING_ELT(PThreadext, threadRing, node); - if (alreadySusp->id == target->id) { - RingAppend(&alreadySusp->idRing, &target->idRing); - target->suspendedMFC = alreadySusp->suspendedMFC; - goto noteSuspended; - } - } - - /* Ok, we really need to suspend this thread. */ - suspendingVictim = target; - status = pthread_kill(target->id, PTHREADEXT_SIGSUSPEND); - if (status != 0) { - res = ResFAIL; - goto unlock; - } - - /* Wait for the victim to acknowledge suspension. */ - while (sem_wait(&pthreadextSem) != 0) { - if (errno != EINTR) { - res = ResFAIL; - goto unlock; - } - } - -noteSuspended: - AVER(target->suspendedMFC != NULL); - RingAppend(&suspendedRing, &target->threadRing); - *contextReturn = target->suspendedMFC; - res = ResOK; - -unlock: - suspendingVictim = NULL; - status = pthread_mutex_unlock(&pthreadextMut); - AVER(status == 0); - return res; -} - - -/* PThreadextResume -- resume a suspended thread - * - * See - */ - -Res PThreadextResume(PThreadext target) -{ - Res res; - int status; - - AVERT(PThreadext, target); - AVER(pthreadextModuleInitialized); /* must have been a prior suspend */ - AVER(target->suspendedMFC != NULL); - - /* Serialize access to suspend, makes life easier. */ - status = pthread_mutex_lock(&pthreadextMut); - AVER(status == 0); - - if (RingIsSingle(&target->idRing)) { - /* Really want to resume the thread. Signal it to continue. */ - status = pthread_kill(target->id, PTHREADEXT_SIGRESUME); - if (status == 0) { - goto noteResumed; - } else { - res = ResFAIL; - goto unlock; - } - - } else { - /* Leave thread suspended on behalf of another PThreadext. */ - /* Remove it from the id ring */ - RingRemove(&target->idRing); - goto noteResumed; - } - -noteResumed: - /* Remove the thread from the suspended ring */ - RingRemove(&target->threadRing); - target->suspendedMFC = NULL; - res = ResOK; - -unlock: - status = pthread_mutex_unlock(&pthreadextMut); - AVER(status == 0); - return res; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/pthrdext.h b/mps/code/pthrdext.h deleted file mode 100644 index 3a28367126e..00000000000 --- a/mps/code/pthrdext.h +++ /dev/null @@ -1,110 +0,0 @@ -/* pthreadext.h: POSIX THREAD EXTENSIONS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .readership: MM developers. - * - * .purpose: Provides extension to Pthreads. - */ - -#ifndef pthreadext_h -#define pthreadext_h - -#include - -#include "mpm.h" - - -#define PThreadextSig ((Sig)0x519B286E) /* SIGnature PTHReadExt */ - - -/* PThreadext -- extension datatype */ - -typedef struct PThreadextStruct *PThreadext; - - -/* PThreadextStruct -- structure definition - * - * Should be embedded in a client structure - */ - -typedef struct PThreadextStruct { - Sig sig; /* */ - pthread_t id; /* Thread ID */ - MutatorFaultContext suspendedMFC; /* context if suspended */ - RingStruct threadRing; /* ring of suspended threads */ - RingStruct idRing; /* duplicate suspensions for id */ -} PThreadextStruct; - - - -/* PThreadextCheck -- Check a pthreadext */ - -extern Bool PThreadextCheck(PThreadext pthreadext); - - -/* PThreadextInit -- Initialize a pthreadext */ - -extern void PThreadextInit(PThreadext pthreadext, pthread_t id); - - -/* PThreadextFinish -- Finish a pthreadext */ - -extern void PThreadextFinish(PThreadext pthreadext); - - -/* PThreadextSuspend -- Suspend a pthreadext and return its context. */ - -extern Res PThreadextSuspend(PThreadext pthreadext, - MutatorFaultContext *contextReturn); - - -/* PThreadextResume -- Resume a suspended pthreadext */ - -extern Res PThreadextResume(PThreadext pthreadext); - - -#endif /* pthreadext_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/qs.c b/mps/code/qs.c deleted file mode 100644 index 8d5c011701c..00000000000 --- a/mps/code/qs.c +++ /dev/null @@ -1,569 +0,0 @@ -/* qs.c: QUICKSORT - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * The purpose of this program is to act as a "real" client of the MM. - * It is a test, but (hopefully) less contrived than some of the other - * tests. - * - * C stack will contain the continuations (list of PCs). The - * activation stack will parallel the C stack and contain the program's - * variables. This is all slightly bizarre. - * And qs cheats a tiny bit by using the C stack to save leaf objects - * (integers). - * - * nil, the end of list, is represented by a NULL pointer. - * - * list length 1000 makes 40404 conses (by experiment). - * - * Some registers are not nulled out when they could be. - * - * TODO: There should be fewer casts and more unions. - */ - -#include "testlib.h" -#include "mps.h" -#include "mpsavm.h" -#include "mpscamc.h" -#include "mpscmv.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include - - -#define testArenaSIZE ((size_t)1000*1024) -#define genCOUNT 2 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { 150, 0.85 }, { 170, 0.45 } }; - - -static mps_res_t scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit); -static mps_addr_t skip(mps_addr_t object); -static void move(mps_addr_t object, mps_addr_t to); -static mps_addr_t isMoved(mps_addr_t object); -static void copy(mps_addr_t object, mps_addr_t to); -static void pad(mps_addr_t base, size_t size); - -struct mps_fmt_A_s fmt_A_s = - { - (mps_align_t)4, - scan, skip, copy, - move, isMoved, - pad - }; - - - -/* Tags used by object format */ -enum {QSInt, QSRef, QSEvac, QSPadOne, QSPadMany}; - -typedef struct QSCellStruct *QSCell; -typedef struct QSCellStruct { - mps_word_t tag; - mps_addr_t value; - QSCell tail; -} QSCellStruct; - - -static mps_arena_t arena; -static mps_pool_t pool; /* automatic pool */ -static mps_ap_t ap; /* AP for above */ -static mps_pool_t mpool; /* manual pool */ -static mps_root_t regroot; -static mps_root_t actroot; - - -/* list holds an array that we qsort(), listl is its length */ -static mps_word_t *list; -static mps_word_t listl; - - -/* Machine State - * - * The machine consists of a stack and 3 registers. - */ - -static QSCell activationStack; -#define NREGS 3 -static mps_addr_t reg[NREGS]; -static mps_word_t regtag[NREGS]; - - -/* Machine Instructions - * - * The machine can perform the following operations: - * cons - * append - * swap - */ - -/* should cons return in reg[0] or should it return via C? */ -static void cons(mps_word_t tag0, mps_addr_t value0, QSCell tail) -{ - mps_addr_t p; - QSCell new; - - do { - die(mps_reserve(&p, ap, sizeof(QSCellStruct)), - "cons"); - new = (QSCell)p; - new->tag = tag0; - new->value = value0; - new->tail = tail; - } while(!mps_commit(ap, p, sizeof(QSCellStruct))); - - reg[0] = (mps_addr_t)new; - regtag[0] = QSRef; - return; -} - - -/* Appends reg[1] to reg[0] */ -/* append nil, y = y - * append x::xs, y = x::append xs, y - * append x,y = (if (null x) y (cons (car x) (append (cdr x) y))) - */ -static void append(void) -{ - cdie(regtag[0] == QSRef, "append 0"); - cdie(regtag[1] == QSRef, "append 1"); - - if(reg[0] == (mps_word_t)0) { - reg[0] = reg[1]; - regtag[0] = regtag[1]; - goto ret; - } - - cons(regtag[0], reg[0], activationStack); - activationStack = (QSCell)reg[0]; - cons(regtag[1], reg[1], activationStack); - activationStack = (QSCell)reg[0]; - - reg[0] = activationStack->tail->value; - regtag[0] = activationStack->tail->tag; - cdie(regtag[0] == QSRef, "append tail"); - reg[0] = (mps_addr_t)((QSCell)reg[0])->tail; /* (cdr x) */ - regtag[0] = QSRef; - append(); - reg[1] = reg[0]; - regtag[1] = regtag[0]; - reg[0] = activationStack->tail->value; - regtag[0] = activationStack->tail->tag; - cdie(regtag[0] == QSRef, "append sec"); - regtag[0] = ((QSCell)reg[0])->tag; - reg[0] = ((QSCell)reg[0])->value; /* (car x) */ - cons(regtag[0], reg[0], (QSCell)reg[1]); - activationStack = activationStack->tail->tail; - - ret: - /* null out reg[1] */ - regtag[1] = QSRef; - reg[1] = (mps_addr_t)0; - return; -} - - -/* swaps reg[0] with reg[1], destroys reg[2] */ -static void swap(void) -{ - regtag[2]=regtag[0]; - reg[2]=reg[0]; - regtag[0]=regtag[1]; - reg[0]=reg[1]; - regtag[1]=regtag[2]; - reg[1]=reg[2]; - regtag[2]=QSRef; - reg[2]=(mps_addr_t)0; -} - - -static void makerndlist(unsigned l) -{ - unsigned i; - mps_word_t r; - - cdie(l > 0, "list len"); - if(list != NULL) { - mps_free(mpool, (mps_addr_t)list, (listl * sizeof(mps_word_t))); - list = NULL; - } - listl = l; - die(mps_alloc((mps_addr_t *)&list, mpool, (l * sizeof(mps_word_t))), - "Alloc List"); - reg[0] = (mps_addr_t)0; - regtag[0] = QSRef; - for(i = 0; i < l; ++i) { - r = rnd(); - cons(QSInt, - (mps_addr_t)r, /* TODO: dirty cast */ - (QSCell)reg[0]); - list[i] = r; - } -} - - -/* reg[0] is split into two lists: those elements less than p, and - * those elements >= p. The two lists are returned in reg[0] and reg[1] - */ -static void part(mps_word_t p) -{ - regtag[2]=regtag[0]; - reg[2]=reg[0]; - cdie(regtag[2] == QSRef, "part 0"); - regtag[0]=QSRef; - reg[0]=(mps_addr_t)0; - regtag[1]=QSRef; - reg[1]=(mps_addr_t)0; - - while(reg[2] != (mps_word_t)0) { - cdie(((QSCell)reg[2])->tag == QSInt, "part int"); - if((mps_word_t)((QSCell)reg[2])->value < p) { - /* cons onto reg[0] */ - cons(QSInt, ((QSCell)reg[2])->value, (QSCell)reg[0]); - } else { - /* cons onto reg[1] */ - cons(QSRef, reg[0], activationStack); /* save reg0 */ - activationStack = (QSCell)reg[0]; - cons(QSInt, ((QSCell)reg[2])->value, (QSCell)reg[1]); - reg[1]=reg[0]; - reg[0]=activationStack->value; - activationStack = activationStack->tail; - } - reg[2]=(mps_addr_t)((QSCell)reg[2])->tail; - } -} - - -/* applies the quicksort algorithm to sort reg[0] */ -static void qs(void) -{ - mps_word_t pivot; - - cdie(regtag[0] == QSRef, "qs 0"); - - /* base case */ - if(reg[0] == (mps_word_t)0) { - return; - } - - /* check that we have an int list */ - cdie(((QSCell)reg[0])->tag == QSInt, "qs int"); - - pivot = (mps_word_t)((QSCell)reg[0])->value; - reg[0] = (mps_addr_t)((QSCell)reg[0])->tail; - part(pivot); - - cons(QSRef, reg[0], activationStack); - activationStack = (QSCell)reg[0]; - cons(QSRef, reg[1], activationStack); - activationStack = (QSCell)reg[0]; - - reg[0] = reg[1]; - regtag[0] = regtag[1]; - cdie(regtag[0] == QSRef, "qs 1"); - qs(); - cons(QSInt, (mps_addr_t)pivot, (QSCell)reg[0]); - activationStack = activationStack->tail; - cons(QSRef, reg[0], activationStack); - activationStack = (QSCell)reg[0]; - reg[0] = activationStack->tail->value; - regtag[0] = activationStack->tail->tag; - cdie(regtag[0] == QSRef, "qs tail"); - qs(); - reg[1] = activationStack->value; - regtag[1] = activationStack->tag; - activationStack = activationStack->tail->tail; - append(); -} - - -/* Compare - * - * Used as an argument to qsort() - */ -static int compare(const void *a, const void *b) -{ - mps_word_t aa, bb; - - aa = *(const mps_word_t *)a; - bb = *(const mps_word_t *)b; - if(aa < bb) { - return -1; - } else if(aa == bb) { - return 0; - } else { - return 1; - } -} - - -/* compares the qsort'ed list with our quicksorted list */ -static void validate(void) -{ - mps_word_t i; - - cdie(regtag[0] == QSRef, "validate 0"); - regtag[1] = regtag[0]; - reg[1] = reg[0]; - for(i = 0; i < listl; ++i) { - cdie(((QSCell)reg[1])->tag == QSInt, "validate int"); - if((mps_word_t)((QSCell)reg[1])->value != list[i]) { - fprintf(stdout, - "mps_res_t: Element %"PRIuLONGEST" of the two lists do not match.\n", - (ulongest_t)i); - return; - } - reg[1] = (mps_addr_t)((QSCell)reg[1])->tail; - } - cdie(reg[1] == (mps_word_t)0, "validate end"); - fprintf(stdout, "Note: Lists compare equal.\n"); -} - - -static void *go(void *p, size_t s) -{ - mps_fmt_t format; - mps_chain_t chain; - - testlib_unused(p); - testlib_unused(s); - - die(mps_pool_create(&mpool, arena, mps_class_mv(), - (size_t)65536, sizeof(QSCellStruct) * 1000, - (size_t)65536), - "MVCreate"); - die(mps_fmt_create_A(&format, arena, &fmt_A_s), "FormatCreate"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain), - "AMCCreate"); - die(mps_ap_create(&ap, pool, mps_rank_exact()), "APCreate"); - die(mps_root_create_table(®root, - arena, - mps_rank_ambig(), - 0, - reg, - NREGS), - "RootCreateTable"); - die(mps_root_create_table(&actroot, arena, mps_rank_ambig(), 0, - (mps_addr_t *)&activationStack, sizeof(QSCell)/sizeof(mps_addr_t)), - "RootCreateTable"); - - /* makes a random list */ - makerndlist(1000); - - part(0); - swap(); - qs(); - qsort(list, listl, sizeof(mps_word_t), &compare); - validate(); - - mps_root_destroy(regroot); - mps_root_destroy(actroot); - mps_ap_destroy(ap); - mps_pool_destroy(pool); - mps_pool_destroy(mpool); - mps_chain_destroy(chain); - mps_fmt_destroy(format); - - return NULL; -} - - -/* Machine Object Format */ - -static void pad(mps_addr_t base, size_t size) -{ - mps_word_t *object = base; - cdie(size >= sizeof(mps_word_t), "pad size"); - if(size == sizeof(mps_word_t)) { - object[0] = QSPadOne; - return; - } - cdie(size >= 2*sizeof(mps_word_t), "pad size 2"); - object[0] = QSPadMany; - object[1] = size; - return; -} - - -static mps_res_t scan1(mps_ss_t ss, mps_addr_t *objectIO) -{ - QSCell cell; - mps_res_t res; - - cdie(objectIO != NULL, "objectIO"); - - MPS_SCAN_BEGIN(ss) { - cell = (QSCell)*objectIO; - - switch(cell->tag) { - case QSRef: - if(!MPS_FIX1(ss, (mps_addr_t)cell->value)) - goto fixTail; - res = MPS_FIX2(ss, (mps_addr_t *)&cell->value); - if(res != MPS_RES_OK) - return res; - /* fall */ - - case QSInt: - fixTail: - if(!MPS_FIX1(ss, (mps_addr_t)cell->tail)) - break; - res = MPS_FIX2(ss, (mps_addr_t *)&cell->tail); - if(res != MPS_RES_OK) - return res; - break; - - case QSEvac: - /* skip */ - break; - - case QSPadOne: - *objectIO = (mps_addr_t)((mps_word_t *)cell+1); - return MPS_RES_OK; - - case QSPadMany: - *objectIO = (mps_addr_t)((mps_word_t)cell+((mps_word_t *)cell)[1]); - return MPS_RES_OK; - - default: - cdie(0, "unknown tag"); - return MPS_RES_OK; - } - } MPS_SCAN_END(ss); - - *objectIO = (mps_addr_t)(cell+1); - - return MPS_RES_OK; -} - - -static mps_res_t scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit) -{ - while(base < limit) { - mps_res_t res; - - res = scan1(ss, &base); - if(res != MPS_RES_OK) { - return res; - } - } - - cdie(base == limit, "scan limit"); - return MPS_RES_OK; -} - - -static mps_addr_t skip(mps_addr_t object) -{ - QSCell cell = (QSCell)object; - switch(cell->tag) - { - case QSPadOne: - return (mps_addr_t)((mps_word_t *)cell+1); - case QSPadMany: - return (mps_addr_t)((mps_word_t)cell+((mps_word_t *)cell)[1]); - default: - return (mps_addr_t)((QSCell)object + 1); - } -} - - -static void move(mps_addr_t object, mps_addr_t to) -{ - QSCell cell; - - cell = (QSCell)object; - - cell->tag = QSEvac; - cell->value = to; -} - - -static mps_addr_t isMoved(mps_addr_t object) -{ - QSCell cell; - - cell = (QSCell)object; - - if(cell->tag == QSEvac) { - return (mps_addr_t)cell->value; - } - return (mps_addr_t)0; -} - - -static void copy(mps_addr_t object, mps_addr_t to) -{ - QSCell cells, celld; - - cells = (QSCell)object; - celld = (QSCell)to; - - *celld = *cells; -} - - -int main(int argc, char **argv) -{ - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "mps_arena_create"); - mps_tramp(&r, &go, NULL, 0); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ref.c b/mps/code/ref.c deleted file mode 100644 index fd11743cb1e..00000000000 --- a/mps/code/ref.c +++ /dev/null @@ -1,123 +0,0 @@ -/* ref.c: REFERENCES - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: Implement operations on Ref, RefSet, ZoneSet, and Rank. - * - * .design: See design.mps.ref and design.mps.refset. - */ - -#include "mpm.h" - -SRCID(ref, "$Id$"); - - -/* RankCheck -- check a rank value */ - -Bool RankCheck(Rank rank) -{ - CHECKL(rank < RankLIMIT); - UNUSED(rank); /* */ - return TRUE; -} - - -/* RankSetCheck -- check a rank set */ - -Bool RankSetCheck(RankSet rankSet) -{ - CHECKL(rankSet < ((ULongest)1 << RankLIMIT)); - UNUSED(rankSet); /* */ - return TRUE; -} - - -/* ZoneSetOfRange -- calculate the zone set of a range of addresses */ - -RefSet ZoneSetOfRange(Arena arena, Addr base, Addr limit) -{ - Word zbase, zlimit; - - AVERT(Arena, arena); - AVER(limit > base); - - /* The base and limit zones of the range are calculated. The limit */ - /* zone is the zone after the last zone of the range, not the zone of */ - /* the limit address. */ - zbase = (Word)base >> arena->zoneShift; - zlimit = (((Word)limit-1) >> arena->zoneShift) + 1; - - - /* If the range is large enough to span all zones, its zone set is */ - /* universal. */ - if (zlimit - zbase >= MPS_WORD_WIDTH) - return ZoneSetUNIV; - - zbase &= MPS_WORD_WIDTH - 1; - zlimit &= MPS_WORD_WIDTH - 1; - - /* If the base zone is less than the limit zone, the zone set looks */ - /* like 000111100, otherwise it looks like 111000011. */ - if (zbase < zlimit) - return ((ZoneSet)1<. - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/replay.c b/mps/code/replay.c deleted file mode 100644 index 974ce5dcd07..00000000000 --- a/mps/code/replay.c +++ /dev/null @@ -1,225 +0,0 @@ -/* replay.c: Allocation replayer - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * $Id$ - */ - -#include "config.h" -/* override variety setting for EVENT */ -#define EVENT - -#include "eventcom.h" -#include "eventpro.h" -#include "eventrep.h" -#include "mpmtypes.h" - -#include /* for size_t */ -#include /* for printf */ -#include /* for va_list */ -#include /* for EXIT_FAILURE */ -#include /* for strcmp */ -#include "mpstd.h" - - -#ifdef MPS_PF_W3I6MV -#define PRIuLONGEST "llu" -#define PRIXPTR "016llX" -typedef unsigned long long ulongest_t; -#else -#define PRIuLONGEST "lu" -#define PRIXPTR "08lX" -typedef unsigned long ulongest_t; -#endif - - -typedef unsigned long ulong; - - -/* command-line arguments */ - -static char *prog; /* program name */ - - -/* Globals */ - -static Word eventTime = 0; /* current event time */ - - -/* error -- error signalling */ - -static void error(const char *format, ...) -{ - va_list args; - - fflush(stdout); /* sync */ - fprintf(stderr, "%s: @%"PRIuLONGEST" ", prog, (ulongest_t)eventTime); - va_start(args, format); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - va_end(args); - exit(EXIT_FAILURE); -} - - -/* usage -- usage message */ - -static void usage(void) -{ - fprintf(stderr, - "Usage: %s [-f logfile] [-p] [-?]\n" - "See guide.mps.telemetry for instructions.\n", - prog); -} - - -/* usageError -- explain usage and error */ - -static void usageError(void) -{ - usage(); - error("Bad usage"); -} - - -/* parseArgs -- parse command line arguments, return log file name */ - -static char *parseArgs(int argc, char *argv[]) -{ - char *name = "mpsio.log"; - int i = 1; - - if (argc >= 1) - prog = argv[0]; - else - prog = "unknown"; - - while (i < argc) { /* consider argument i */ - if (argv[i][0] == '-') { /* it's an option argument */ - switch (argv[i][1]) { - case 'f': /* file name */ - ++ i; - if (i == argc) - usageError(); - else - name = argv[i]; - break; - case '?': case 'h': /* help */ - usage(); - break; - default: - usageError(); - } - } /* if option */ - ++ i; - } - return name; -} - - -/* readLog -- read and parse log */ - - -static void readLog(EventProc proc) -{ - while (TRUE) { - Event event; - Res res; - - res = EventRead(&event, proc); - if (res == ResFAIL) break; /* eof */ - if (res != ResOK) error("Truncated log"); - eventTime = event->any.clock; - EventRecord(proc, event, eventTime); - EventReplay(event, eventTime); - EventDestroy(proc, event); - } -} - - -/* logReader -- reader function for a file log */ - -static FILE *input; - -static Res logReader(void *file, void *p, size_t len) -{ - size_t n; - - n = fread(p, 1, len, (FILE *)file); - return (n < len) ? (feof((FILE *)file) ? ResFAIL : ResIO) : ResOK; -} - - -/* main */ - -int main(int argc, char *argv[]) -{ - char *filename; - EventProc proc; - Res res; - - filename = parseArgs(argc,argv); - - if (strcmp(filename, "-") == 0) - input = stdin; - else { - input = fopen(filename, "rb"); - if (input == NULL) - error("unable to open \"%s\"\n", filename); - } - - res = EventProcCreate(&proc, logReader, (void *)input); - if (res != ResOK) - error("Can't init EventProc module: error %d.", res); - - res = EventRepInit(); - if (res != ResOK) - error("Can't init EventRep module: error %d.", res); - - readLog(proc); - - EventRepFinish(); - EventProcDestroy(proc); - return EXIT_SUCCESS; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/reserv.c b/mps/code/reserv.c deleted file mode 100644 index d50e02b931f..00000000000 --- a/mps/code/reserv.c +++ /dev/null @@ -1,447 +0,0 @@ -/* reserv.c: ARENA RESERVOIR - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * IMPROVEMENTS - * - * .improve.contiguous: There should be a means of grouping contiguous - * tracts together so that there's a likelihood of being able to meet - * requests for regions larger than the arena alignment. */ - -#include "mpm.h" - -SRCID(reserv, "$Id$"); - - -/* The reservoir pool is defined here. See */ - -#define Pool2Reservoir(pool) PARENT(ReservoirStruct, poolStruct, pool) - - -/* Management of tracts - * - * The reservoir maintains a linked list of tracts in arbitrary order. - * (see .improve.contiguous) - * - * Tracts are chained using the TractP field. */ - -#define resTractNext(tract) ((Tract)TractP((tract))) -#define resTractSetNext(tract, next) (TractSetP((tract), (void*)(next))) - - -#define reservoirArena(reservoir) ((reservoir)->poolStruct.arena) - - -/* ResPoolInit -- Reservoir pool init method */ - -static Res ResPoolInit(Pool pool, va_list arg) -{ - AVER(pool != NULL); - - UNUSED(arg); - /* Caller will set sig and AVERT. */ - EVENT3(PoolInit, pool, PoolArena(pool), ClassOfPool(pool)); - return ResOK; -} - - -/* ResPoolFinish -- Reservoir pool finish method - * - * .reservoir.finish: This might be called from ArenaFinish, so the - * arena cannot be checked at this time. In order to avoid the check, - * insist that the reservoir is empty, by AVERing that the reserve list - * is NULL. */ - -static void ResPoolFinish(Pool pool) -{ - Reservoir reservoir; - - AVERT(Pool, pool); - reservoir = Pool2Reservoir(pool); - AVERT(Reservoir, reservoir); - AVER(reservoir->reserve == NULL); /* .reservoir.finish */ -} - - -/* ReservoirPoolClass -- Class definition */ - -DEFINE_POOL_CLASS(ReservoirPoolClass, this) -{ - INHERIT_CLASS(this, AbstractPoolClass); - this->name = "Reservoir"; - this->size = sizeof(ReservoirStruct); - this->offset = offsetof(ReservoirStruct, poolStruct); - this->init = ResPoolInit; - this->finish = ResPoolFinish; -} - - -/* ReservoirCheck -- Reservoir check method */ - -Bool ReservoirCheck(Reservoir reservoir) -{ - ReservoirPoolClass reservoircl = EnsureReservoirPoolClass(); - Arena arena; - Tract tract; - - CHECKS(Reservoir, reservoir); - CHECKD(Pool, &reservoir->poolStruct); - CHECKL(reservoir->poolStruct.class == reservoircl); - UNUSED(reservoircl); /* */ - arena = reservoirArena(reservoir); - CHECKU(Arena, arena); - /* could call ReservoirIsConsistent, but it's costly. */ - tract = reservoir->reserve; - if (tract != NULL) { - CHECKL(TractCheck(tract)); - CHECKL(TractPool(tract) == &reservoir->poolStruct); - } - CHECKL(SizeIsAligned(reservoir->reservoirLimit, ArenaAlign(arena))); - CHECKL(SizeIsAligned(reservoir->reservoirSize, ArenaAlign(arena))); - - return TRUE; -} - - -/* reservoirIsConsistent -- returns FALSE if the reservoir is corrupt */ - -static Bool reservoirIsConsistent(Reservoir reservoir) -{ - Size alignment, size = 0; - Tract tract; - Pool pool; - Arena arena; - - arena = reservoirArena(reservoir); - pool = &reservoir->poolStruct; - - /* Check that the size of the tracts matches reservoirSize */ - alignment = ArenaAlign(arena); - tract = reservoir->reserve; - while (tract != NULL) { - AVERT(Tract, tract); - AVER(TractPool(tract) == pool); - tract = resTractNext(tract); - size += alignment; - } - - if (size != reservoir->reservoirSize) - return FALSE; - - /* */ - return SizeIsAligned(reservoir->reservoirLimit, alignment) - && SizeIsAligned(reservoir->reservoirSize, alignment) - && (reservoir->reservoirLimit >= reservoir->reservoirSize); -} - - -/* ReservoirEnsureFull - * - * Ensures that the reservoir is the right size, by topping it up with - * fresh memory from the arena if possible. */ - -Res ReservoirEnsureFull(Reservoir reservoir) -{ - Size limit, alignment; - Pool pool; - Arena arena; - AVERT(Reservoir, reservoir); - arena = reservoirArena(reservoir); - - AVERT(Arena, arena); - alignment = ArenaAlign(arena); - limit = reservoir->reservoirLimit; - - /* optimize the common case of a full reservoir */ - if (reservoir->reservoirSize == limit) - return ResOK; - - pool = &reservoir->poolStruct; - - /* really ought to try hard to allocate contiguous tracts */ - /* see .improve.contiguous */ - while (reservoir->reservoirSize < limit) { - Res res; - Addr base; - Tract tract; - res = (*arena->class->alloc)(&base, &tract, SegPrefDefault(), - alignment, pool); - if (res != ResOK) { - AVER(reservoirIsConsistent(reservoir)); - return res; - } - reservoir->reservoirSize += alignment; - resTractSetNext(tract, reservoir->reserve); - reservoir->reserve = tract; - } - AVER(reservoirIsConsistent(reservoir)); - return ResOK; -} - - -/* reservoirShrink -- Reduce the size of the reservoir */ - -static void reservoirShrink(Reservoir reservoir, Size want) -{ - Arena arena; - Pool pool; - Size alignment; - - pool = &reservoir->poolStruct; - arena = reservoirArena(reservoir); - AVER(SizeIsAligned(want, ArenaAlign(arena))); - AVER(reservoir->reservoirSize >= want); - - if (reservoir->reservoirSize == want) - return; - - /* Iterate over tracts, freeing them while reservoir is too big */ - alignment = ArenaAlign(arena); - while (reservoir->reservoirSize > want) { - Tract tract = reservoir->reserve; - AVER(tract != NULL); - reservoir->reserve = resTractNext(tract); - (*arena->class->free)(TractBase(tract), alignment, pool); - reservoir->reservoirSize -= alignment; - } - AVER(reservoir->reservoirSize == want); - AVER(reservoirIsConsistent(reservoir)); -} - - -/* ReservoirWithdraw -- Attempt to supply memory from the reservoir */ - -Res ReservoirWithdraw(Addr *baseReturn, Tract *baseTractReturn, - Reservoir reservoir, Size size, Pool pool) -{ - Arena arena; - - AVER(baseReturn != NULL); - AVER(baseTractReturn != NULL); - AVERT(Reservoir, reservoir); - arena = reservoirArena(reservoir); - AVERT(Arena, arena); - AVER(SizeIsAligned(size, ArenaAlign(arena))); - AVER(size > 0); - AVERT(Pool, pool); - - /* @@@@ As a short-term measure, we only permit the reservoir to */ - /* allocate single-page regions. */ - /* See .improve.contiguous & change.dylan.jackdaw.160125 */ - if (size != ArenaAlign(arena)) - return ResMEMORY; - - if (size <= reservoir->reservoirSize) { - /* Return the first tract */ - Tract tract = reservoir->reserve; - Addr base; - AVER(tract != NULL); - base = TractBase(tract); - reservoir->reserve = resTractNext(tract); - reservoir->reservoirSize -= ArenaAlign(arena); - TractFinish(tract); - TractInit(tract, pool, base); - AVER(reservoirIsConsistent(reservoir)); - *baseReturn = base; - *baseTractReturn = tract; - return ResOK; - } - - AVER(reservoirIsConsistent(reservoir)); - return ResMEMORY; /* no suitable region in the reservoir */ -} - - -/* ReservoirDeposit -- Top up the reservoir */ - -void ReservoirDeposit(Reservoir reservoir, Addr base, Size size) -{ - Pool respool; - Addr addr, limit; - Size reslimit, alignment; - Arena arena; - Tract tract; - - AVERT(Reservoir, reservoir); - arena = reservoirArena(reservoir); - AVERT(Arena, arena); - respool = &reservoir->poolStruct; - alignment = ArenaAlign(arena); - AVER(AddrIsAligned(base, alignment)); - AVER(SizeIsAligned(size, alignment)); - limit = AddrAdd(base, size); - reslimit = reservoir->reservoirLimit; - - /* put as many pages as necessary into the reserve & free the rest */ - TRACT_FOR(tract, addr, arena, base, limit) { - AVER(TractCheck(tract)); - if (reservoir->reservoirSize < reslimit) { - /* Reassign the tract to the reservoir pool */ - TractFinish(tract); - TractInit(tract, respool, addr); - reservoir->reservoirSize += alignment; - resTractSetNext(tract, reservoir->reserve); - reservoir->reserve = tract; - } else { - /* free the tract */ - (*arena->class->free)(addr, alignment, TractPool(tract)); - } - } - AVER(addr == limit); - AVER(reservoirIsConsistent(reservoir)); -} - - -/* mutatorBufferCount -- returns the number of mutator buffers for the arena - * - * This should probably be in the pool module, but it's only used here. */ - -static Count mutatorBufferCount(Globals arena) -{ - Ring nodep, nextp; - Count count = 0; - - /* Iterate over all pools, and count the mutator buffers in each */ - RING_FOR(nodep, &arena->poolRing, nextp) { - Pool pool = RING_ELT(Pool, arenaRing, nodep); - Ring nodeb, nextb; - - AVERT(Pool, pool); - RING_FOR(nodeb, &pool->bufferRing, nextb) { - Buffer buff = RING_ELT(Buffer, poolRing, nodeb); - if (buff->isMutator) - count++; - } - } - return count; -} - - -/* ReservoirSetLimit -- Set the reservoir limit */ - -void ReservoirSetLimit(Reservoir reservoir, Size size) -{ - Size needed; - Arena arena; - AVERT(Reservoir, reservoir); - arena = reservoirArena(reservoir); - AVERT(Arena, arena); - - if (size > 0) { - Size wastage; - /* */ - wastage = ArenaAlign(arena) * mutatorBufferCount(ArenaGlobals(arena)); - /* */ - needed = SizeAlignUp(size, ArenaAlign(arena)) + wastage; - } else { - needed = 0; /* */ - } - - AVER(SizeIsAligned(needed, ArenaAlign(arena))); - /* Emit event now, so subsequent change can be ascribed to it. */ - EVENT2(ReservoirLimitSet, arena, size); - - if (needed > reservoir->reservoirSize) { - /* Try to grow the reservoir */ - reservoir->reservoirLimit = needed; - (void)ReservoirEnsureFull(reservoir); - } else { - /* Shrink the reservoir */ - reservoirShrink(reservoir, needed); - reservoir->reservoirLimit = needed; - AVER(reservoirIsConsistent(reservoir)); - } -} - - -/* ReservoirLimit -- Return the reservoir limit */ - -Size ReservoirLimit(Reservoir reservoir) -{ - AVERT(Reservoir, reservoir); - AVER(reservoirIsConsistent(reservoir)); - return reservoir->reservoirLimit; -} - - -/* ReservoirAvailable -- Return the amount in the reservoir */ - -Size ReservoirAvailable(Reservoir reservoir) -{ - AVERT(Reservoir, reservoir); - (void)ReservoirEnsureFull(reservoir); - return reservoir->reservoirSize; -} - - -/* ReservoirInit -- Initialize a reservoir */ - -Res ReservoirInit(Reservoir reservoir, Arena arena) -{ - Res res; - - /* reservoir and arena are not initialized and can't be checked */ - reservoir->reservoirLimit = (Size)0; - reservoir->reservoirSize = (Size)0; - reservoir->reserve = NULL; - reservoir->sig = ReservoirSig; - /* initialize the reservoir pool, */ - res = PoolInit(&reservoir->poolStruct, - arena, EnsureReservoirPoolClass()); - if (res == ResOK) { - AVERT(Reservoir, reservoir); - } - return res; -} - - -/* ReservoirFinish -- Finish a reservoir */ - -void ReservoirFinish (Reservoir reservoir) -{ - PoolFinish(&reservoir->poolStruct); - reservoir->sig = SigInvalid; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ring.c b/mps/code/ring.c deleted file mode 100644 index ff60149ce40..00000000000 --- a/mps/code/ring.c +++ /dev/null @@ -1,171 +0,0 @@ -/* ring.c: RING IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license. - * - * .intro: This is a portable implementation of Rings. - * - * .purpose: Rings are used to manage potentially unbounded collections - * of things. - * - * .sources: , - * item 6 of mail.richard_brooksby.1996-03-25.16-02 - */ - -#include "ring.h" -#include "check.h" -#include "misc.h" - -SRCID(ring, "$Id$"); - - -/* RingCheck, RingCheckSingle -- check the validity of a ring node - * - * RingCheck performs a consistency check on the ring node. - * RingCheckSingle performs the same check, but also checks that - * the ring node is a singleton (). - */ - -Bool RingCheck(Ring ring) -{ - CHECKL(ring != NULL); - CHECKL(ring->next != NULL); - CHECKL(ring->next->prev == ring); - CHECKL(ring->prev != NULL); - CHECKL(ring->prev->next == ring); - UNUSED(ring); /* */ - return TRUE; -} - -Bool RingCheckSingle(Ring ring) -{ - CHECKL(RingCheck(ring)); - CHECKL(ring->next == ring); - CHECKL(ring->prev == ring); - UNUSED(ring); /* */ - return TRUE; -} - -Bool RingIsSingle(Ring ring) -{ - AVERT(Ring, ring); - return (ring->next == ring); -} - - -/* RingInit -- initialize a ring node - */ - -void (RingInit)(Ring ring) -{ - RingInit(ring); /* */ -} - - -/* RingFinish -- finish a ring node - */ - -void (RingFinish)(Ring ring) -{ - RingFinish(ring); /* */ -} - - -/* RingAppend -- add a ring node to the end of a ring - */ - -void (RingAppend)(Ring ring, Ring new) -{ - RingAppend(ring, new); /* */ -} - - -/* RingInsert -- add a ring node to the start of a ring - */ - -void (RingInsert)(Ring ring, Ring new) -{ - RingInsert(ring, new); /* */ -} - - -/* RingRemove -- remove a node from a ring - */ - -void (RingRemove)(Ring old) -{ - RingRemove(old); /* */ -} - - -/* RingNext -- get the next element of a ring - */ - -Ring (RingNext)(Ring ring) -{ - return RingNext(ring); /* */ -} - -/* RingPrev -- get the previous element of a ring - */ - -Ring (RingPrev)(Ring ring) -{ - return RingPrev(ring); /* */ -} - - -/* RING_ELT -- get the ring element structure - * - * RING_ELT has no function (as it does not have function-like - * behaviour), and is defined in . - */ - - -/* RING_FOR -- ring iterator construct - * - * RING_FOR has no function (as it does not have function-like - * behaviour), and is defined in . - */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ring.h b/mps/code/ring.h deleted file mode 100644 index c7d14ee43d8..00000000000 --- a/mps/code/ring.h +++ /dev/null @@ -1,155 +0,0 @@ -/* ring.h: RING INTERFACE - * - * $Id$ - * Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2001 Global Graphics Software. - */ - - -#ifndef ring_h -#define ring_h - -#include "check.h" -#include "mpmtypes.h" - - -/* RingStruct -- double-ended queue structure - * - * .ring: The ring structure is used as a field in other structures - * in order to link them together into "rings". See . - */ - -typedef struct RingStruct *Ring; -typedef struct RingStruct { /* double-ended queue structure */ - Ring next, prev; /* links to next and prev element */ -} RingStruct; - - -#define RingNONE ((Ring)0) - -extern Bool RingCheck(Ring ring); -extern Bool RingCheckSingle(Ring ring); -extern Bool RingIsSingle(Ring ring); - -/* .ring.init: */ -extern void (RingInit)(Ring ring); -#define RingInit(ring) \ - BEGIN \ - Ring _ring = (ring); \ - AVER(_ring != NULL); \ - _ring->next = _ring; \ - _ring->prev = _ring; \ - AVER(RingCheck(_ring)); \ - END - -/* .ring.finish: */ -extern void (RingFinish)(Ring ring); -#define RingFinish(ring) \ - BEGIN \ - Ring _ring = (ring); \ - AVER(RingCheckSingle(_ring)); \ - _ring->next = RingNONE; \ - _ring->prev = RingNONE; \ - END - -/* .ring.append: */ -extern void (RingAppend)(Ring ring, Ring new); -#define RingAppend(ring, new) \ - BEGIN \ - Ring _ring = (ring), _new = (new); \ - AVER(RingCheck(_ring)); \ - AVER(RingCheckSingle(_new)); \ - _new->prev = _ring->prev; \ - _new->next = _ring; \ - _ring->prev->next = _new; \ - _ring->prev = _new; \ - END - -/* .ring.insert: */ -extern void (RingInsert)(Ring ring, Ring new); -#define RingInsert(ring, new) \ - BEGIN \ - Ring _ring = (ring), _new = (new); \ - AVER(RingCheck(_ring)); \ - AVER(RingCheckSingle(_new)); \ - _new->prev = _ring; \ - _new->next = _ring->next; \ - _ring->next->prev = _new; \ - _ring->next = _new; \ - END - -/* .ring.remove: */ -extern void (RingRemove)(Ring old); -#define RingRemove(old) \ - BEGIN \ - Ring _old = (old); \ - AVER(RingCheck(_old)); \ - AVER(!RingIsSingle(_old)); \ - _old->next->prev = _old->prev; \ - _old->prev->next = _old->next; \ - _old->next = _old; \ - _old->prev = _old; \ - END - -/* .ring.next: */ -extern Ring (RingNext)(Ring ring); -#define RingNext(ring) ((ring)->next) - -/* .ring.prev: */ -extern Ring (RingPrev)(Ring ring); -#define RingPrev(ring) ((ring)->prev) - -/* .ring.elt: See */ -#define RING_ELT(type, field, node) \ - ((type)(void *)((char *)(node) - (size_t)(&((type)0)->field))) - -/* .ring.for: See */ -#define RING_FOR(node, ring, next) \ - for(node = RingNext(ring), next = RingNext(node); \ - node != (ring); \ - node = (next), next = RingNext(node)) - - -#endif /* ring_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/root.c b/mps/code/root.c deleted file mode 100644 index edb932f800a..00000000000 --- a/mps/code/root.c +++ /dev/null @@ -1,711 +0,0 @@ -/* root.c: ROOT IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This is the implementation of the root datatype. - * - * .design: For design, see and - * design.mps.root-interface. */ - -#include "mpm.h" - -SRCID(root, "$Id$"); - - -/* RootStruct -- tracing root structure */ - -#define RootSig ((Sig)0x51960029) /* SIGnature ROOT */ - -typedef struct RootStruct { - Sig sig; - Serial serial; /* from arena->rootSerial */ - Arena arena; /* owning arena */ - RingStruct arenaRing; /* attachment to arena */ - Rank rank; /* rank of references in this root */ - TraceSet grey; /* traces for which root is grey */ - RefSet summary; /* summary of references in root */ - RootMode mode; /* mode */ - Bool protectable; /* Can protect root? */ - Addr protBase; /* base of protectable area */ - Addr protLimit; /* limit of protectable area */ - AccessSet pm; /* Protection Mode */ - RootVar var; /* union discriminator */ - union RootUnion { - struct { - mps_root_scan_t scan; /* the function which does the scanning */ - void *p; /* environment for scan */ - size_t s; /* environment for scan */ - } fun; - struct { - Addr *base; /* beginning of table */ - Addr *limit; /* one off end of table */ - } table; - struct { - Addr *base; /* beginning of table */ - Addr *limit; /* one off end of table */ - Word mask; /* tag mask for scanning */ - } tableMasked; - struct { - mps_reg_scan_t scan; /* function for scanning registers */ - Thread thread; /* passed to scan */ - void *p; /* passed to scan */ - size_t s; /* passed to scan */ - } reg; - struct { - mps_fmt_scan_t scan; /* format-like scanner */ - Addr base, limit; /* passed to scan */ - } fmt; - } the; -} RootStruct; - - -/* RootVarCheck -- check a Root union discriminator - * - * .rootvarcheck: Synchronize with */ - -Bool RootVarCheck(RootVar rootVar) -{ - CHECKL(rootVar == RootTABLE || rootVar == RootTABLE_MASKED - || rootVar == RootFUN || rootVar == RootFMT || rootVar == RootREG); - UNUSED(rootVar); - return TRUE; -} - - -/* RootModeCheck */ - -Bool RootModeCheck(RootMode mode) -{ - CHECKL((mode & (RootModeCONSTANT | RootModePROTECTABLE - | RootModePROTECTABLE_INNER)) - == mode); - /* RootModePROTECTABLE_INNER implies RootModePROTECTABLE */ - CHECKL((mode & RootModePROTECTABLE_INNER) == 0 - || (mode & RootModePROTECTABLE)); - UNUSED(mode); - - return TRUE; -} - - -/* RootCheck -- check the consistency of a root structure - * - * .rootcheck: Keep synchonized with . */ - -Bool RootCheck(Root root) -{ - CHECKS(Root, root); - CHECKU(Arena, root->arena); - CHECKL(root->serial < ArenaGlobals(root->arena)->rootSerial); - CHECKL(RingCheck(&root->arenaRing)); - CHECKL(RankCheck(root->rank)); - CHECKL(TraceSetCheck(root->grey)); - /* Don't need to check var here, because of the switch below */ - switch(root->var) - { - case RootTABLE: - CHECKL(root->the.table.base != 0); - CHECKL(root->the.table.base < root->the.table.limit); - break; - - case RootTABLE_MASKED: - CHECKL(root->the.tableMasked.base != 0); - CHECKL(root->the.tableMasked.base < root->the.tableMasked.limit); - /* Can't check anything about the mask. */ - break; - - case RootFUN: - CHECKL(root->the.fun.scan != NULL); - break; - - case RootREG: - CHECKL(root->the.reg.scan != NULL); - CHECKL(ThreadCheck(root->the.reg.thread)); - break; - - case RootFMT: - CHECKL(root->the.fmt.scan != NULL); - CHECKL(root->the.fmt.base != 0); - CHECKL(root->the.fmt.base < root->the.fmt.limit); - break; - - default: - NOTREACHED; - } - CHECKL(RootModeCheck(root->mode)); - CHECKL(BoolCheck(root->protectable)); - if (root->protectable) { - CHECKL(root->protBase != (Addr)0); - CHECKL(root->protLimit != (Addr)0); - CHECKL(root->protBase < root->protLimit); - /* there is no AccessSetCheck */ - } else { - CHECKL(root->protBase == (Addr)0); - CHECKL(root->protLimit == (Addr)0); - CHECKL(root->pm == (AccessSet)0); - } - return TRUE; -} - - -/* rootCreate, RootCreateTable, RootCreateReg, RootCreateFmt, RootCreateFun - * - * RootCreate* set up the appropriate union member, and call the generic - * create function to do the actual creation - * - * See for initial value. */ - -static Res rootCreate(Root *rootReturn, Arena arena, - Rank rank, RootMode mode, RootVar type, - union RootUnion *theUnionP) -{ - Root root; - Res res; - void *p; - Globals globals; - - AVER(rootReturn != NULL); - AVERT(Arena, arena); - AVERT(Rank, rank); - AVERT(RootVar, type); - globals = ArenaGlobals(arena); - - res = ControlAlloc(&p, arena, sizeof(RootStruct), FALSE); - if (res != ResOK) - return res; - root = (Root)p; /* Avoid pun */ - - root->arena = arena; - root->rank = rank; - root->var = type; - root->the = *theUnionP; - root->grey = TraceSetEMPTY; - root->summary = RefSetUNIV; - root->mode = mode; - root->pm = AccessSetEMPTY; - root->protectable = FALSE; - root->protBase = (Addr)0; - root->protLimit = (Addr)0; - - /* See */ - RingInit(&root->arenaRing); - - root->serial = globals->rootSerial; - ++globals->rootSerial; - root->sig = RootSig; - - AVERT(Root, root); - - RingAppend(&globals->rootRing, &root->arenaRing); - - *rootReturn = root; - return ResOK; -} - -static Res rootCreateProtectable(Root *rootReturn, Arena arena, - Rank rank, RootMode mode, RootVar var, - Addr base, Addr limit, - union RootUnion *theUnion) -{ - Res res; - Root root; - Ring node, next; - - res = rootCreate(&root, arena, rank, mode, var, theUnion); - if (res != ResOK) - return res; - if (mode & RootModePROTECTABLE) { - root->protectable = TRUE; - if (mode & RootModePROTECTABLE_INNER) { - root->protBase = AddrAlignUp(base, ArenaAlign(arena)); - root->protLimit = AddrAlignDown(limit, ArenaAlign(arena)); - if (!(root->protBase < root->protLimit)) { - /* root had no inner pages */ - root->protectable = FALSE; - root->mode &=~ (RootModePROTECTABLE|RootModePROTECTABLE_INNER); - } - } else { - root->protBase = AddrAlignDown(base, ArenaAlign(arena)); - root->protLimit = AddrAlignUp(limit, ArenaAlign(arena)); - } - } - - /* Check that this root doesn't intersect with any other root */ - RING_FOR(node, &ArenaGlobals(arena)->rootRing, next) { - Root trial = RING_ELT(Root, arenaRing, node); - if (trial != root) { - /* (trial->protLimit <= root->protBase */ - /* || root->protLimit <= trial->protBase) */ - /* is the "okay" state. The negation of this is: */ - if (root->protBase < trial->protLimit - && trial->protBase < root->protLimit) { - NOTREACHED; - RootDestroy(root); - return ResFAIL; - } - } - } - - AVERT(Root, root); - - *rootReturn = root; - return ResOK; -} - -Res RootCreateTable(Root *rootReturn, Arena arena, - Rank rank, RootMode mode, Addr *base, Addr *limit) -{ - Res res; - union RootUnion theUnion; - - AVER(rootReturn != NULL); - AVERT(Arena, arena); - AVER(RankCheck(rank)); - AVER(base != 0); - AVER(base < limit); - - theUnion.table.base = base; - theUnion.table.limit = limit; - - res = rootCreateProtectable(rootReturn, arena, rank, mode, - RootTABLE, (Addr)base, (Addr)limit, &theUnion); - return res; -} - -Res RootCreateTableMasked(Root *rootReturn, Arena arena, - Rank rank, RootMode mode, Addr *base, Addr *limit, - Word mask) -{ - union RootUnion theUnion; - - AVER(rootReturn != NULL); - AVERT(Arena, arena); - AVER(RankCheck(rank)); - AVER(base != 0); - AVER(base < limit); - /* Can't check anything about mask. */ - - theUnion.tableMasked.base = base; - theUnion.tableMasked.limit = limit; - theUnion.tableMasked.mask = mask; - - return rootCreateProtectable(rootReturn, arena, rank, mode, RootTABLE_MASKED, - (Addr)base, (Addr)limit, &theUnion); -} - -Res RootCreateReg(Root *rootReturn, Arena arena, - Rank rank, Thread thread, - mps_reg_scan_t scan, void *p, size_t s) -{ - union RootUnion theUnion; - - AVER(rootReturn != NULL); - AVERT(Arena, arena); - AVER(RankCheck(rank)); - AVERT(Thread, thread); - AVER(scan != NULL); - - theUnion.reg.scan = scan; - theUnion.reg.thread = thread; - theUnion.reg.p = p; - theUnion.reg.s = s; - - return rootCreate(rootReturn, arena, rank, (RootMode)0, RootREG, &theUnion); -} - -Res RootCreateFmt(Root *rootReturn, Arena arena, - Rank rank, RootMode mode, mps_fmt_scan_t scan, - Addr base, Addr limit) -{ - union RootUnion theUnion; - - AVER(rootReturn != NULL); - AVERT(Arena, arena); - AVER(RankCheck(rank)); - AVER(FUNCHECK(scan)); - AVER(base != 0); - AVER(base < limit); - - theUnion.fmt.scan = scan; - theUnion.fmt.base = base; - theUnion.fmt.limit = limit; - - return rootCreateProtectable(rootReturn, arena, rank, mode, - RootFMT, base, limit, &theUnion); -} - -Res RootCreateFun(Root *rootReturn, Arena arena, Rank rank, - mps_root_scan_t scan, void *p, size_t s) -{ - union RootUnion theUnion; - - AVER(rootReturn != NULL); - AVERT(Arena, arena); - AVER(RankCheck(rank)); - AVER(FUNCHECK(scan)); - - theUnion.fun.scan = scan; - theUnion.fun.p = p; - theUnion.fun.s = s; - - return rootCreate(rootReturn, arena, rank, (RootMode)0, RootFUN, &theUnion); -} - - -/* RootDestroy -- destroy a root */ - -void RootDestroy(Root root) -{ - Arena arena; - - AVERT(Root, root); - - arena = RootArena(root); - - AVERT(Arena, arena); - - RingRemove(&root->arenaRing); - RingFinish(&root->arenaRing); - - root->sig = SigInvalid; - - ControlFree(arena, root, sizeof(RootStruct)); -} - - -/* RootArena -- return the rank of a root - * - * Must be thread-safe. */ - -Arena RootArena(Root root) -{ - AVER(TESTT(Root, root)); - return root->arena; -} - - -/* RootRank -- return the rank of a root */ - -Rank RootRank(Root root) -{ - AVERT(Root, root); - return root->rank; -} - - -/* RootPM -- return the protection mode of a root */ - -AccessSet RootPM(Root root) -{ - AVERT(Root, root); - return root->pm; -} - - -/* RootSummary -- return the summary of a root */ - -RefSet RootSummary(Root root) -{ - AVERT(Root, root); - return root->summary; -} - - -/* RootGrey -- mark root grey */ - -void RootGrey(Root root, Trace trace) -{ - AVERT(Root, root); - AVERT(Trace, trace); - - root->grey = TraceSetAdd(root->grey, trace); -} - - -static void rootSetSummary(Root root, RefSet summary) -{ - AVERT(Root, root); - /* Can't check summary */ - if (root->protectable) { - if (summary == RefSetUNIV) { - root->summary = summary; - root->pm &= ~AccessWRITE; - } else { - root->pm |= AccessWRITE; - root->summary = summary; - } - } else - AVER(root->summary == RefSetUNIV); -} - - -/* RootScan -- scan root */ - -Res RootScan(ScanState ss, Root root) -{ - Res res; - - AVERT(Root, root); - AVERT(ScanState, ss); - AVER(root->rank == ss->rank); - - if (TraceSetInter(root->grey, ss->traces) == TraceSetEMPTY) - return ResOK; - - AVER(ScanStateSummary(ss) == RefSetEMPTY); - - if (root->pm != AccessSetEMPTY) { - ProtSet(root->protBase, root->protLimit, AccessSetEMPTY); - } - - switch(root->var) { - case RootTABLE: - res = TraceScanArea(ss, root->the.table.base, root->the.table.limit); - ss->scannedSize += AddrOffset(root->the.table.base, root->the.table.limit); - if (res != ResOK) - goto failScan; - break; - - case RootTABLE_MASKED: - res = TraceScanAreaMasked(ss, - root->the.tableMasked.base, - root->the.tableMasked.limit, - root->the.tableMasked.mask); - ss->scannedSize += AddrOffset(root->the.table.base, root->the.table.limit); - if (res != ResOK) - goto failScan; - break; - - case RootFUN: - res = (*root->the.fun.scan)(&ss->ss_s, root->the.fun.p, root->the.fun.s); - if (res != ResOK) - goto failScan; - break; - - case RootREG: - res = (*root->the.reg.scan)(&ss->ss_s, root->the.reg.thread, - root->the.reg.p, root->the.reg.s); - if (res != ResOK) - goto failScan; - break; - - case RootFMT: - res = (*root->the.fmt.scan)(&ss->ss_s, root->the.fmt.base, root->the.fmt.limit); - ss->scannedSize += AddrOffset(root->the.fmt.base, root->the.fmt.limit); - if (res != ResOK) - goto failScan; - break; - - default: - NOTREACHED; - res = ResUNIMPL; - goto failScan; - } - - AVER(res == ResOK); - root->grey = TraceSetDiff(root->grey, ss->traces); - rootSetSummary(root, ScanStateSummary(ss)); - EVENT3(RootScan, root, ss->traces, ScanStateSummary(ss)); - -failScan: - if (root->pm != AccessSetEMPTY) { - ProtSet(root->protBase, root->protLimit, root->pm); - } - - return res; -} - - -/* RootOfAddr -- return the root at addr - * - * Returns TRUE if the addr is in a root (and returns the root in - * *rootReturn) otherwise returns FALSE. Cf. SegOfAddr. */ - -Bool RootOfAddr(Root *rootReturn, Arena arena, Addr addr) -{ - Ring node, next; - - AVER(rootReturn != NULL); - AVERT(Arena, arena); - /* addr is arbitrary and can't be checked */ - - RING_FOR(node, &ArenaGlobals(arena)->rootRing, next) { - Root root = RING_ELT(Root, arenaRing, node); - - if (root->protectable && root->protBase <= addr && addr < root->protLimit) { - *rootReturn = root; - return TRUE; - } - } - - return FALSE; -} - - -/* RootAccess -- handle barrier hit on root */ - -void RootAccess(Root root, AccessSet mode) -{ - AVERT(Root, root); - /* Can't AVERT mode. */ - AVER((root->pm & mode) != AccessSetEMPTY); - AVER(mode == AccessWRITE); /* only write protection supported */ - - rootSetSummary(root, RefSetUNIV); - - /* Access must now be allowed. */ - AVER((root->pm & mode) == AccessSetEMPTY); - ProtSet(root->protBase, root->protLimit, root->pm); -} - - -/* RootsIterate -- iterate over all the roots in the arena */ - -Res RootsIterate(Globals arena, RootIterateFn f, void *p) -{ - Res res = ResOK; - Ring node, next; - - RING_FOR(node, &arena->rootRing, next) { - Root root = RING_ELT(Root, arenaRing, node); - - res = (*f)(root, p); - if (res != ResOK) - return res; - } - return res; -} - - -/* RootDescribe -- describe a root */ - -Res RootDescribe(Root root, mps_lib_FILE *stream) -{ - Res res; - - if (!TESTT(Root, root)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, - "Root $P ($U) {\n", (WriteFP)root, (WriteFU)root->serial, - " arena $P ($U)\n", (WriteFP)root->arena, - (WriteFU)root->arena->serial, - " rank $U\n", (WriteFU)root->rank, - " grey $B\n", (WriteFB)root->grey, - " summary $B\n", (WriteFB)root->summary, - NULL); - if (res != ResOK) return res; - - switch(root->var) { - case RootTABLE: - res = WriteF(stream, - " table base $A limit $A\n", - root->the.table.base, root->the.table.limit, - NULL); - if (res != ResOK) return res; - break; - - case RootTABLE_MASKED: - res = WriteF(stream, " table base $A limit $A mask $B\n", - root->the.tableMasked.base, root->the.tableMasked.limit, - root->the.tableMasked.mask, - NULL); - if (res != ResOK) return res; - break; - - case RootFUN: - res = WriteF(stream, - " scan function $F\n", (WriteFF)root->the.fun.scan, - " environment p $P s $W\n", - root->the.fun.p, (WriteFW)root->the.fun.s, - NULL); - if (res != ResOK) return res; - break; - - case RootREG: - res = WriteF(stream, - " thread $P\n", (WriteFP)root->the.reg.thread, - " environment p $P", root->the.reg.p, - NULL); - if (res != ResOK) return res; - break; - - case RootFMT: - res = WriteF(stream, - " scan function $F\n", (WriteFF)root->the.fmt.scan, - " format base $A limit $A\n", - root->the.fmt.base, root->the.fmt.limit, - NULL); - if (res != ResOK) return res; - break; - - default: - NOTREACHED; - } - - res = WriteF(stream, - "} Root $P ($U)\n", (WriteFP)root, (WriteFU)root->serial, - NULL); - if (res != ResOK) return res; - - return ResOK; -} - - -/* RootsDescribe -- describe all roots */ - -Res RootsDescribe(Globals arenaGlobals, mps_lib_FILE *stream) -{ - Res res = ResOK; - Ring node, next; - - RING_FOR(node, &arenaGlobals->rootRing, next) { - Root root = RING_ELT(Root, arenaRing, node); - res = RootDescribe(root, stream); /* this outputs too much */ - if (res != ResOK) return res; - } - return res; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/sac.c b/mps/code/sac.c deleted file mode 100644 index 3b82cd846d8..00000000000 --- a/mps/code/sac.c +++ /dev/null @@ -1,424 +0,0 @@ -/* sac.c: SEGREGATED ALLOCATION CACHES - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" -#include "sac.h" - -SRCID(sac, "$Id$"); - - -typedef mps_sac_freelist_block_s *SACFreeListBlock; - - -/* SACCheck -- check function for SACs */ - -static Bool sacFreeListBlockCheck(SACFreeListBlock fb) -{ - Count j; - Addr cb; - - /* nothing to check about size */ - CHECKL(fb->_count <= fb->_count_max); - /* check the freelist has the right number of blocks */ - for (j = 0, cb = fb->_blocks; j < fb->_count; ++j) { - CHECKL(cb != NULL); - /* @@@@ ignoring shields for now */ - cb = *ADDR_PTR(Addr, cb); - } - CHECKL(cb == NULL); - return TRUE; -} - -static Bool SACCheck(SAC sac) -{ - Index i, j; - Bool b; - Size prevSize; - mps_sac_t esac; - - CHECKS(SAC, sac); - esac = ExternalSACOfSAC(sac); - CHECKU(Pool, sac->pool); - CHECKL(sac->classesCount > 0); - CHECKL(sac->classesCount > sac->middleIndex); - CHECKL(BoolCheck(esac->_trapped)); - CHECKL(esac->_middle > 0); - /* check classes above middle */ - prevSize = esac->_middle; - for (j = sac->middleIndex + 1, i = 0; - j <= sac->classesCount; ++j, i += 2) { - CHECKL(prevSize < esac->_freelists[i]._size); - b = sacFreeListBlockCheck(&(esac->_freelists[i])); - if (!b) return b; - prevSize = esac->_freelists[i]._size; - } - /* check overlarge class */ - CHECKL(esac->_freelists[i-2]._size == SizeMAX); - CHECKL(esac->_freelists[i-2]._count == 0); - CHECKL(esac->_freelists[i-2]._count_max == 0); - CHECKL(esac->_freelists[i-2]._blocks == NULL); - /* check classes below middle */ - prevSize = esac->_middle; - for (j = sac->middleIndex, i = 1; j > 0; --j, i += 2) { - CHECKL(prevSize > esac->_freelists[i]._size); - b = sacFreeListBlockCheck(&(esac->_freelists[i])); - if (!b) return b; - prevSize = esac->_freelists[i]._size; - } - /* check smallest class */ - CHECKL(esac->_freelists[i]._size == 0); - b = sacFreeListBlockCheck(&(esac->_freelists[i])); - return b; -} - - -/* sacSize -- calculate size of a SAC structure */ - -static Size sacSize(Index middleIndex, Count classesCount) -{ - Index indexMax; /* max index for the freelist */ - SACStruct dummy; - - if (middleIndex + 1 < classesCount - middleIndex) - indexMax = 2 * (classesCount - middleIndex - 1); - else - indexMax = 1 + 2 * middleIndex; - return PointerOffset(&dummy, &dummy.esac_s._freelists[indexMax+1]); -} - - -/* SACCreate -- create an SAC object */ - -Res SACCreate(SAC *sacReturn, Pool pool, Count classesCount, - SACClasses classes) -{ - void *p; - SAC sac; - Res res; - Index i, j; - Index middleIndex; /* index of the size in the middle */ - Size prevSize; - unsigned totalFreq = 0; - mps_sac_t esac; - - AVER(sacReturn != NULL); - AVERT(Pool, pool); - AVER(classesCount > 0); - /* In this cache type, there is no upper limit on classesCount. */ - prevSize = sizeof(Addr) - 1; /* must large enough for freelist link */ - /* @@@@ It would be better to dynamically adjust the smallest class */ - /* to be large enough, but that gets complicated, if you have to */ - /* merge classes because of the adjustment. */ - for (i = 0; i < classesCount; ++i) { - AVER(classes[i]._block_size > 0); - AVER(SizeIsAligned(classes[i]._block_size, PoolAlignment(pool))); - AVER(prevSize < classes[i]._block_size); - prevSize = classes[i]._block_size; - /* no restrictions on count */ - /* no restrictions on frequency */ - } - - /* Calculate frequency scale */ - for (i = 0; i < classesCount; ++i) { - unsigned oldFreq = totalFreq; - totalFreq += classes[i]._frequency; - AVER(oldFreq <= totalFreq); /* check for overflow */ - UNUSED(oldFreq); /* */ - } - - /* Find middle one */ - totalFreq /= 2; - for (i = 0; i < classesCount; ++i) { - if (totalFreq < classes[i]._frequency) break; - totalFreq -= classes[i]._frequency; - } - if (totalFreq <= classes[i]._frequency / 2) - middleIndex = i; - else - middleIndex = i + 1; /* there must exist another class at i+1 */ - - /* Allocate SAC */ - res = ControlAlloc(&p, PoolArena(pool), sacSize(middleIndex, classesCount), - FALSE); - if(res != ResOK) - goto failSACAlloc; - sac = p; - - /* Move classes in place */ - /* It's important this matches SACFind. */ - esac = ExternalSACOfSAC(sac); - for (j = middleIndex + 1, i = 0; j < classesCount; ++j, i += 2) { - esac->_freelists[i]._size = classes[j]._block_size; - esac->_freelists[i]._count = 0; - esac->_freelists[i]._count_max = classes[j]._cached_count; - esac->_freelists[i]._blocks = NULL; - } - esac->_freelists[i]._size = SizeMAX; - esac->_freelists[i]._count = 0; - esac->_freelists[i]._count_max = 0; - esac->_freelists[i]._blocks = NULL; - for (j = middleIndex, i = 1; j > 0; --j, i += 2) { - esac->_freelists[i]._size = classes[j-1]._block_size; - esac->_freelists[i]._count = 0; - esac->_freelists[i]._count_max = classes[j]._cached_count; - esac->_freelists[i]._blocks = NULL; - } - esac->_freelists[i]._size = 0; - esac->_freelists[i]._count = 0; - esac->_freelists[i]._count_max = classes[j]._cached_count; - esac->_freelists[i]._blocks = NULL; - - /* finish init */ - esac->_trapped = FALSE; - esac->_middle = classes[middleIndex]._block_size; - sac->pool = pool; - sac->classesCount = classesCount; - sac->middleIndex = middleIndex; - sac->sig = SACSig; - AVERT(SAC, sac); - *sacReturn = sac; - return ResOK; - -failSACAlloc: - return res; -} - - -/* SACDestroy -- destroy an SAC object */ - -void SACDestroy(SAC sac) -{ - AVERT(SAC, sac); - SACFlush(sac); - sac->sig = SigInvalid; - ControlFree(PoolArena(sac->pool), sac, - sacSize(sac->middleIndex, sac->classesCount)); -} - - -/* sacFind -- find the index corresponding to size - * - * This function replicates the loop in MPS_SAC_ALLOC_FAST, only with - * added checks. - */ - -static void sacFind(Index *iReturn, Size *blockSizeReturn, - SAC sac, Size size) -{ - Index i, j; - mps_sac_t esac; - - esac = ExternalSACOfSAC(sac); - if (size > esac->_middle) { - i = 0; j = sac->middleIndex + 1; - AVER(j <= sac->classesCount); - while (size > esac->_freelists[i]._size) { - AVER(j < sac->classesCount); - i += 2; ++j; - } - *blockSizeReturn = esac->_freelists[i]._size; - } else { - Size prevSize = esac->_middle; - - i = 1; j = sac->middleIndex; - while (size <= esac->_freelists[i]._size) { - AVER(j > 0); - prevSize = esac->_freelists[i]._size; - i += 2; --j; - } - *blockSizeReturn = prevSize; - } - *iReturn = i; -} - - -/* SACFill -- alloc an object, and perhaps fill the cache */ - -Res SACFill(Addr *p_o, SAC sac, Size size, Bool hasReservoirPermit) -{ - Index i; - Count blockCount, j; - Size blockSize; - Addr p, fl; - Res res = ResOK; /* stop compiler complaining */ - mps_sac_t esac; - - AVER(p_o != NULL); - AVERT(SAC, sac); - AVER(size != 0); - AVER(BoolCheck(hasReservoirPermit)); - esac = ExternalSACOfSAC(sac); - - sacFind(&i, &blockSize, sac, size); - /* Check it's empty (in the future, there will be other cases). */ - AVER(esac->_freelists[i]._count == 0); - - /* Fill 1/3 of the cache for this class. */ - blockCount = esac->_freelists[i]._count_max / 3; - /* Adjust size for the overlarge class. */ - if (blockSize == SizeMAX) - /* .align: align 'cause some classes don't accept unaligned. */ - blockSize = SizeAlignUp(size, PoolAlignment(sac->pool)); - for (j = 0, fl = esac->_freelists[i]._blocks; - j <= blockCount; ++j) { - res = PoolAlloc(&p, sac->pool, blockSize, hasReservoirPermit); - if (res != ResOK) - break; - /* @@@@ ignoring shields for now */ - *ADDR_PTR(Addr, p) = fl; fl = p; - } - /* If didn't get any, just return. */ - if (j == 0) { - AVER(res != ResOK); - return res; - } - - /* Take the last one off, and return it. */ - esac->_freelists[i]._count = j - 1; - *p_o = fl; - /* @@@@ ignoring shields for now */ - esac->_freelists[i]._blocks = *ADDR_PTR(Addr, fl); - return ResOK; -} - - -/* sacClassFlush -- discard elements from the cache for a given class - * - * blockCount says how many elements to discard. - */ - -static void sacClassFlush(SAC sac, Index i, Size blockSize, - Count blockCount) -{ - Addr cb, fl; - Count j; - mps_sac_t esac; - - esac = ExternalSACOfSAC(sac); - for (j = 0, fl = esac->_freelists[i]._blocks; - j < blockCount; ++j) { - /* @@@@ ignoring shields for now */ - cb = fl; fl = *ADDR_PTR(Addr, cb); - PoolFree(sac->pool, cb, blockSize); - } - esac->_freelists[i]._count -= blockCount; - esac->_freelists[i]._blocks = fl; -} - - -/* SACEmpty -- free an object, and perhaps empty the cache */ - -void SACEmpty(SAC sac, Addr p, Size size) -{ - Index i; - Size blockSize; - mps_sac_t esac; - - AVERT(SAC, sac); - AVER(p != NULL); - AVER(PoolHasAddr(sac->pool, p)); - AVER(size > 0); - esac = ExternalSACOfSAC(sac); - - sacFind(&i, &blockSize, sac, size); - /* Check it's full (in the future, there will be other cases). */ - AVER(esac->_freelists[i]._count - == esac->_freelists[i]._count_max); - - /* Adjust size for the overlarge class. */ - if (blockSize == SizeMAX) - /* see .align */ - blockSize = SizeAlignUp(size, PoolAlignment(sac->pool)); - if (esac->_freelists[i]._count_max > 0) { - Count blockCount; - - /* Flush 2/3 of the cache for this class. */ - /* Computed as count - count/3, so that the rounding works out right. */ - blockCount = esac->_freelists[i]._count; - blockCount -= esac->_freelists[i]._count / 3; - sacClassFlush(sac, i, blockSize, (blockCount > 0) ? blockCount : 1); - /* Leave the current one in the cache. */ - esac->_freelists[i]._count += 1; - /* @@@@ ignoring shields for now */ - *ADDR_PTR(Addr, p) = esac->_freelists[i]._blocks; - esac->_freelists[i]._blocks = p; - } else { - /* Free even the current one. */ - PoolFree(sac->pool, p, blockSize); - } -} - - -/* SACFlush -- flush the cache, releasing all memory held in it */ - -void SACFlush(SAC sac) -{ - Index i, j; - Size prevSize; - mps_sac_t esac; - - AVERT(SAC, sac); - - esac = ExternalSACOfSAC(sac); - for (j = sac->middleIndex + 1, i = 0; - j < sac->classesCount; ++j, i += 2) { - sacClassFlush(sac, i, esac->_freelists[i]._size, - esac->_freelists[i]._count); - AVER(esac->_freelists[i]._blocks == NULL); - } - /* no need to flush overlarge, there's nothing there */ - prevSize = esac->_middle; - for (j = sac->middleIndex, i = 1; j > 0; --j, i += 2) { - sacClassFlush(sac, i, prevSize, esac->_freelists[i]._count); - AVER(esac->_freelists[i]._blocks == NULL); - prevSize = esac->_freelists[i]._size; - } - /* flush smallest class */ - sacClassFlush(sac, i, prevSize, esac->_freelists[i]._count); - AVER(esac->_freelists[i]._blocks == NULL); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/sac.h b/mps/code/sac.h deleted file mode 100644 index 78e676125d1..00000000000 --- a/mps/code/sac.h +++ /dev/null @@ -1,94 +0,0 @@ -/* sac.h: SEGREGATED ALLOCATION CACHES INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#ifndef sac_h -#define sac_h - -#include "mpmtypes.h" -#include "mpm.h" /* for PoolArena */ - - -#define sacClassLIMIT ((Count)8) - - -/* SAC -- the real segregated allocation caches */ - -#define SACSig ((Sig)0x5195AC99) /* SIGnature SAC */ - -typedef struct SACStruct *SAC; - -typedef struct SACStruct { - Sig sig; - Pool pool; - Count classesCount; /* number of classes */ - Index middleIndex; /* index of the middle */ - mps_sac_s esac_s; /* variable length, must be last */ -} SACStruct; - -#define SACOfExternalSAC(esac) PARENT(SACStruct, esac_s, esac) - -#define ExternalSACOfSAC(sac) (&((sac)->esac_s)) - -#define SACArena(sac) PoolArena((sac)->pool) - - -/* SACClasses -- structure for specifying classes in the cache */ -/* .sacc: This structure must match . */ - -typedef struct mps_sac_classes_s *SACClasses; - - -extern Res SACCreate(SAC *sac_o, Pool pool, Count classesCount, - SACClasses classes); -extern void SACDestroy(SAC sac); -extern Res SACFill(Addr *p_o, SAC sac, Size size, Bool hasReservoirPermit); -extern void SACEmpty(SAC sac, Addr p, Size size); -extern void SACFlush(SAC sac); - - -#endif /* sac_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/sacss.c b/mps/code/sacss.c deleted file mode 100644 index 7fe5c368b3c..00000000000 --- a/mps/code/sacss.c +++ /dev/null @@ -1,245 +0,0 @@ -/* sacss.c: SAC MANUAL ALLOC STRESS TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - */ - -#include "mpscmv.h" -#include "mpscmvff.h" -#include "mpslib.h" -#include "mpsavm.h" -#include "mps.h" - -#include "testlib.h" - -#include -#include "mpstd.h" -#include -#include -#include - - -#define TRUE 1 -#define FALSE 0 - -#define testArenaSIZE ((((size_t)64)<<20) - 4) -#define testSetSIZE 200 -#define testLOOPS 10 - -#define topClassSIZE 0xA00 -#define classCOUNT 4 - - -/* make -- allocate an object */ - -static mps_res_t make(mps_addr_t *p, mps_sac_t sac, size_t size) -{ - mps_res_t res; - - MPS_SAC_ALLOC(res, *p, sac, size, FALSE); - return res; -} - - -/* stress -- create a pool of the requested type and allocate in it */ - -static mps_res_t stress(mps_class_t class, - size_t classes_count, mps_sac_classes_s *classes, - size_t (*size)(int i), mps_arena_t arena, ...) -{ - mps_res_t res; - mps_pool_t pool; - mps_sac_t sac; - va_list arg; - int i, k; - int *ps[testSetSIZE]; - size_t ss[testSetSIZE]; - - va_start(arg, arena); - res = mps_pool_create_v(&pool, arena, class, arg); - va_end(arg); - if (res != MPS_RES_OK) - return res; - - die(mps_sac_create(&sac, pool, classes_count, classes), "SACCreate"); - - /* allocate a load of objects */ - for (i = 0; i < testSetSIZE; ++i) { - ss[i] = (*size)(i); - - res = make((mps_addr_t *)&ps[i], sac, ss[i]); - if (res != MPS_RES_OK) - return res; - if (ss[i] >= sizeof(ps[i])) - *ps[i] = 1; /* Write something, so it gets swap. */ - } - - mps_pool_check_fenceposts(pool); - - for (k = 0; k < testLOOPS; ++k) { - /* shuffle all the objects */ - for (i=0; i (b)) ? (a) : (b)) - - -/* randomSize8 -- produce sizes both latge and small */ - -static size_t randomSize8(int i) -{ - size_t maxSize = 2 * 160 * 0x2000; - size_t size; - - /* Reduce by a factor of 2 every 10 cycles. Total allocation about 40 MB. */ - size = rnd() % max((maxSize >> (i / 10)), 2) + 1; - return size; -} - - -/* testInArena -- test all the pool classes in the given arena */ - -static mps_pool_debug_option_s debugOptions8 = { - /* .fence_template = */ (void *)"postpost", - /* .fence_size = */ 8, - /* .free_template = */ (void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_pool_debug_option_s debugOptions16 = { - /* .fence_template = */ (void *)"postpostpostpost", - /* .fence_size = */ 16, - /* .free_template = */ (void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_sac_classes_s classes8[4] = { {8, 1, 1}, {16, 1, 2}, {136, 9, 5}, - {topClassSIZE, 9, 4} }; - -static mps_sac_classes_s classes16[4] = { {16, 1, 1}, {32, 1, 2}, {144, 9, 5}, - {topClassSIZE, 9, 4} }; - -static int testInArena(mps_arena_t arena) -{ - mps_pool_debug_option_s *debugOptions; - mps_sac_classes_s *classes; - - debugOptions = MPS_PF_ALIGN == 8 ? &debugOptions8 : &debugOptions16; - classes = MPS_PF_ALIGN == 8 ? classes8 : classes16; - - printf("MVFF\n\n"); - die(stress(mps_class_mvff(), classCOUNT, classes, randomSize8, arena, - (size_t)65536, (size_t)32, sizeof(void *), TRUE, TRUE, TRUE), - "stress MVFF"); - printf("MV debug\n\n"); - die(stress(mps_class_mv_debug(), classCOUNT, classes, randomSize8, arena, - debugOptions, (size_t)65536, (size_t)32, (size_t)65536), - "stress MV debug"); - printf("MV\n\n"); - die(stress(mps_class_mv(), classCOUNT, classes, randomSize8, arena, - (size_t)65536, (size_t)32, (size_t)65536), - "stress MV"); - return 0; -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vmnz(), testArenaSIZE), - "mps_arena_create"); - testInArena(arena); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/sc.h b/mps/code/sc.h deleted file mode 100644 index 765c4ccb033..00000000000 --- a/mps/code/sc.h +++ /dev/null @@ -1,205 +0,0 @@ -/* sc.h: STACK CONTEXT - * - * $Id$ - * Copyright (c) 2012 Ravenbrook Limited. See end of file for license. - * - * Provides a context to hold the registers and stack pointer - * - * This file provide wrappers for using setjmp or some similar mechanism - * to save the current callee-saves on the stack. - * - * See http://info.ravenbrook.com/mail/2012/08/03/14-36-35/0/ and the rest of - * the thread for the origin of the idea. - * - * TODO: Make StackScan take a StackContext - */ - -#ifndef sc_h -#define sc_h - -#include "mpm.h" - - -/* StackContext -- holds the registers including a stack pointer - * - * This contains the callee-save registers and the stack pointer. - * - * This is used to save the registers after or on entry to the arena so that - * they can be scanned. - */ - -/* STACK_CONTEXT_SAVE - save the callee-saves and stack pointer - * - * This macro saves the callee-saves and stack pointer for the - * current function into the passed StackContext. The StackContext - * is no longer valid after the function returns. - * - * This needs to be a macro because the compiler may need to do - * setjmp magic. - */ - -/* StackContextStackTop - return the stack top from the stack context. - * - * We assume the stack is full. In other words the stack top points at - * a word that contains a potential Ref. - */ - - -/* Mac OS X on 32-bit Intel built with Clang or GCC */ - -#if defined(MPS_PF_XCI3LL) || defined(MPS_PF_XCI3GC) - -#include - -typedef struct StackContextStruct { - jmp_buf jumpBuffer; -} StackContextStruct; - -/* See the implementation of _setjmp in - * */ - -#define JB_ESP 36 /* offset into the jmp_buf in bytes as defined in _setjmp.s */ - -#define STACK_CONTEXT_SAVE(sc) ((void)_setjmp((sc)->jumpBuffer)) - -#define StackContextSP(sc) ((Addr *)(sc)->jumpBuffer[JB_ESP/sizeof(int)]) - -/* On MacOS X the stackPointer can end up pointing above the StackContext - * which we assume to be stored on the stack because it is no longer - * needed once we have _longjmp()ed back. So take the minimum of the - * SP and the base of the StackContext structure. */ -#define StackContextStackTop(sc) \ - (StackContextSP(sc) < (Addr*)(sc) ? StackContextSP(sc) : (Addr*)(sc)) - - -/* Mac OS X on 64-bit Intel build with Clang or GCC */ - -#elif defined(MPS_PF_XCI6LL) || defined(MPS_PF_XCI6GC) - -#include - -/* We could use getcontext() from libunwind but that produces - * deprecation warnings. See - * - */ - -typedef struct StackContextStruct { - jmp_buf jumpBuffer; -} StackContextStruct; - -/* See the implementation of _setjmp in - * */ - -#define STACK_CONTEXT_SAVE(sc) ((void)_setjmp((sc)->jumpBuffer)) - -#define JB_RSP 16 /* offset into the jmp_buf in bytes as defined in _setjmp.s */ - -/* jmp_buf is an int[] but the stack pointer is 8 bytes so we need a cast */ -/* FIXME: possible aliasing problem */ -#define StackContextSP(sc) \ - (*(Addr **)((char *)(sc)->jumpBuffer+JB_RSP)) - -/* On MacOS X the stackPointer can end up pointing above the StackContext - * which we assume to be stored on the stack because it is no longer - * needed once we have _longjmp()ed back. So take the minimum of the - * SP and the base of the StackContext structure. */ -#define StackContextStackTop(sc) \ - (StackContextSP(sc) < (Addr*)(sc) ? StackContextSP(sc) : (Addr*)(sc)) - - -/* Windows on 32-bit Intel with Microsoft Visual Studio */ - -#elif defined(MPS_PF_W3I3MV) - -#include - -typedef struct StackContextStruct { - jmp_buf jumpBuffer; -} StackContextStruct; - -#define STACK_CONTEXT_SAVE(sc) ((void)setjmp((sc)->jumpBuffer)) - -#define StackContextStackTop(sc) \ - ((Addr *)((_JUMP_BUFFER *)(sc)->jumpBuffer)->Esp) - - -/* Windows on 64-bit Intel with Microsoft Visual Studio */ - -#elif defined(MPS_PF_W3I6MV) - -#include - -typedef struct StackContextStruct { - jmp_buf jumpBuffer; -} StackContextStruct; - -#define STACK_CONTEXT_SAVE(sc) ((void)setjmp((sc)->jumpBuffer)) - -#define StackContextStackTop(sc) \ - ((Addr *)((_JUMP_BUFFER *)(sc)->jumpBuffer)->Rsp) - - -#else - -/* TODO: implement this on other platforms in a safer way. - * Potentially the callee saves from the calling function could be spilled - * underneath the jmp_buf so returning the address of the jmp_buf for the - * stack top is not completely safe. - */ - -#include - -typedef struct StackContextStruct { - jmp_buf jumpBuffer; -} StackContextStruct; - -#define STACK_CONTEXT_SAVE(sc) ((void)setjmp((sc)->jumpBuffer)) - -#define StackContextStackTop(sc) ((Addr *)(sc)->jumpBuffer) - - -#endif /* platform defines */ - -#endif /* sc_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2012 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/seg.c b/mps/code/seg.c deleted file mode 100644 index 051abc03c79..00000000000 --- a/mps/code/seg.c +++ /dev/null @@ -1,1716 +0,0 @@ -/* seg.c: SEGMENTS - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .design: The design for this module is . - * - * PURPOSE - * - * .purpose: This is the implementation of the generic segment interface. - * It defines the interface functions and two useful segment classes: - * .purpose.class.seg: Class Seg is a class which is as simple - * as efficiency demands permit. (It includes fields for storing colour - * for efficiency). It may be subclassed by clients of the module. - * .purpose.class.seg-gc: Class GCSeg is a concrete class support all - * all current GC features, and providing full backwards compatibility - * with "old-style" segments. It may be subclassed by clients of the - * module. - * - * TRANSGRESSIONS - * - * .check.shield: The "pm", "sm", and "depth" fields are not checked by - * SegCheck, because I haven't spent time working out the invariants. - * We should certainly work them out, by studying , and - * assert things about shielding, protection, shield cache consistency, - * etc. richard 1997-04-03 - */ - -#include "tract.h" -#include "mpm.h" - -SRCID(seg, "$Id$"); - - -/* SegGCSeg -- convert generic Seg to GCSeg */ - -#define SegGCSeg(seg) ((GCSeg)(seg)) - -/* SegPoolRing -- Pool ring accessor */ - -#define SegPoolRing(seg) (&(seg)->poolRing) - - -/* forward declarations */ - -static void SegFinish(Seg seg); - -static Res SegInit(Seg seg, Pool pool, Addr base, Size size, - Bool withReservoirPermit, va_list args); - - -/* Generic interface support */ - - -/* SegAlloc -- allocate a segment from the arena */ - -Res SegAlloc(Seg *segReturn, SegClass class, SegPref pref, - Size size, Pool pool, Bool withReservoirPermit, ...) -{ - Res res; - Arena arena; - Seg seg; - Addr base; - va_list args; - void *p; - - AVER(segReturn != NULL); - AVERT(SegClass, class); - AVERT(SegPref, pref); - AVER(size > (Size)0); - AVERT(Pool, pool); - AVER(BoolCheck(withReservoirPermit)); - - arena = PoolArena(pool); - AVERT(Arena, arena); - AVER(SizeIsAligned(size, arena->alignment)); - - /* allocate the memory from the arena */ - res = ArenaAlloc(&base, pref, size, pool, withReservoirPermit); - if (res != ResOK) - goto failArena; - - /* allocate the segment object from the control pool */ - res = ControlAlloc(&p, arena, class->size, withReservoirPermit); - if (res != ResOK) - goto failControl; - seg = p; - - va_start(args, withReservoirPermit); - seg->class = class; - res = SegInit(seg, pool, base, size, withReservoirPermit, args); - va_end(args); - if (res != ResOK) - goto failInit; - - EVENT5(SegAlloc, arena, seg, SegBase(seg), size, pool); - *segReturn = seg; - return ResOK; - -failInit: - ControlFree(arena, seg, class->size); -failControl: - ArenaFree(base, size, pool); -failArena: - EVENT3(SegAllocFail, arena, size, pool); - return res; -} - - -/* SegFree -- free a segment to the arena */ - -void SegFree(Seg seg) -{ - Arena arena; - Pool pool; - Addr base; - Size size; - SegClass class; - - AVERT(Seg, seg); - pool = SegPool(seg); - AVERT(Pool, pool); - arena = PoolArena(pool); - AVERT(Arena, arena); - base = SegBase(seg); - size = SegSize(seg); - class = seg->class; - - SegFinish(seg); - ControlFree(arena, seg, class->size); - ArenaFree(base, size, pool); - - EVENT2(SegFree, arena, seg); - return; -} - - -/* SegInit -- initialize a segment */ - -static Res SegInit(Seg seg, Pool pool, Addr base, Size size, - Bool withReservoirPermit, va_list args) -{ - Tract tract; - Addr addr, limit; - Size align; - Arena arena; - SegClass class; - Res res; - - AVER(seg != NULL); - AVERT(Pool, pool); - arena = PoolArena(pool); - align = ArenaAlign(arena); - AVER(AddrIsAligned(base, align)); - AVER(SizeIsAligned(size, align)); - class = seg->class; - AVERT(SegClass, class); - AVER(BoolCheck(withReservoirPermit)); - - limit = AddrAdd(base, size); - seg->limit = limit; - seg->rankSet = RankSetEMPTY; - seg->white = TraceSetEMPTY; - seg->nailed = TraceSetEMPTY; - seg->grey = TraceSetEMPTY; - seg->pm = AccessSetEMPTY; - seg->sm = AccessSetEMPTY; - seg->depth = 0; - seg->firstTract = NULL; - - seg->sig = SegSig; /* set sig now so tract checks will see it */ - - TRACT_FOR(tract, addr, arena, base, limit) { - AVER(TractCheck(tract)); /* */ - AVER(TractP(tract) == NULL); - AVER(!TractHasSeg(tract)); - AVER(TractPool(tract) == pool); - AVER(TractWhite(tract) == TraceSetEMPTY); - TRACT_SET_SEG(tract, seg); - if (addr == base) { - AVER(seg->firstTract == NULL); - seg->firstTract = tract; - } - AVER(seg->firstTract != NULL); - } - AVER(addr == seg->limit); - - RingInit(SegPoolRing(seg)); - - /* Class specific initialization comes last */ - res = class->init(seg, pool, base, size, withReservoirPermit, args); - if (res != ResOK) - goto failInit; - - AVERT(Seg, seg); - RingAppend(&pool->segRing, SegPoolRing(seg)); - return ResOK; - -failInit: - RingFinish(SegPoolRing(seg)); - TRACT_FOR(tract, addr, arena, base, limit) { - AVER(TractCheck(tract)); /* */ - TRACT_UNSET_SEG(tract); - } - seg->sig = SigInvalid; - return res; -} - - -/* SegFinish -- finish a segment */ - -static void SegFinish(Seg seg) -{ - Arena arena; - Addr addr, limit; - Tract tract; - SegClass class; - - AVERT(Seg, seg); - class = seg->class; - AVERT(SegClass, class); - - arena = PoolArena(SegPool(seg)); - if (seg->sm != AccessSetEMPTY) { - ShieldLower(arena, seg, seg->sm); - } - - /* Class specific finishing cames first */ - class->finish(seg); - - seg->rankSet = RankSetEMPTY; - - /* See */ - ShieldFlush(PoolArena(SegPool(seg))); - - limit = SegLimit(seg); - - TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, limit) { - AVER(TractCheck(tract)); /* */ - TractSetWhite(tract, TraceSetEMPTY); - TRACT_UNSET_SEG(tract); - } - AVER(addr == seg->limit); - - RingRemove(SegPoolRing(seg)); - RingFinish(SegPoolRing(seg)); - - seg->sig = SigInvalid; - - /* Check that the segment is not exposed, or in the shield */ - /* cache (see ). */ - AVER(seg->depth == 0); - /* Check not shielded or protected (so that pages in hysteresis */ - /* fund are not protected) */ - AVER(seg->sm == AccessSetEMPTY); - AVER(seg->pm == AccessSetEMPTY); - -} - - -/* SegSetGrey -- change the greyness of a segment - * - * Sets the segment greyness to the trace set grey. - */ - -void SegSetGrey(Seg seg, TraceSet grey) -{ - AVERT(Seg, seg); - AVER(TraceSetCheck(grey)); - AVER(SegRankSet(seg) != RankSetEMPTY); - - /* Don't dispatch to the class method if there's no actual change in - greyness, or if the segment doesn't contain any references. */ - if (grey != SegGrey(seg) && SegRankSet(seg) != RankSetEMPTY) - seg->class->setGrey(seg, grey); -} - - -/* SegSetWhite -- change the whiteness of a segment - * - * Sets the segment whiteness to the trace set ts. - */ - -void SegSetWhite(Seg seg, TraceSet white) -{ - AVERT(Seg, seg); - AVER(TraceSetCheck(white)); - seg->class->setWhite(seg, white); -} - - -/* SegSetRankSet -- set the rank set of a segment - * - * The caller must set the summary to empty before setting the rank - * set to empty. The caller must set the rank set to non-empty before - * setting the summary to non-empty. - */ - -void SegSetRankSet(Seg seg, RankSet rankSet) -{ - AVERT(Seg, seg); - AVER(RankSetCheck(rankSet)); - AVER(rankSet != RankSetEMPTY || SegSummary(seg) == RefSetEMPTY); - seg->class->setRankSet(seg, rankSet); -} - - -/* SegSetSummary -- change the summary on a segment */ - -void SegSetSummary(Seg seg, RefSet summary) -{ - AVERT(Seg, seg); - AVER(summary == RefSetEMPTY || SegRankSet(seg) != RankSetEMPTY); - -#ifdef PROTECTION_NONE - summary = RefSetUNIV; -#endif - if (summary != SegSummary(seg)) - seg->class->setSummary(seg, summary); -} - - -/* SegSetRankAndSummary -- set both the rank set and the summary */ - -void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary) -{ - AVERT(Seg, seg); - AVER(RankSetCheck(rankSet)); - -#ifdef PROTECTION_NONE - if (rankSet != RankSetEMPTY) { - summary = RefSetUNIV; - } -#endif - seg->class->setRankSummary(seg, rankSet, summary); -} - - -/* SegBuffer -- return the buffer of a segment */ - -Buffer SegBuffer(Seg seg) -{ - AVERT_CRITICAL(Seg, seg); /* .seg.critical */ - return seg->class->buffer(seg); -} - - -/* SegSetBuffer -- change the buffer on a segment */ - -void SegSetBuffer(Seg seg, Buffer buffer) -{ - AVERT(Seg, seg); - if (buffer != NULL) - AVERT(Buffer, buffer); - seg->class->setBuffer(seg, buffer); -} - - -/* SegDescribe -- describe a segment */ - -Res SegDescribe(Seg seg, mps_lib_FILE *stream) -{ - Res res; - Pool pool; - - if (!TESTT(Seg, seg)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - pool = SegPool(seg); - - res = WriteF(stream, - "Segment $P [$A,$A) {\n", (WriteFP)seg, - (WriteFA)SegBase(seg), (WriteFA)SegLimit(seg), - " class $P (\"$S\")\n", - (WriteFP)seg->class, seg->class->name, - " pool $P ($U)\n", - (WriteFP)pool, (WriteFU)pool->serial, - NULL); - if (res != ResOK) return res; - - res = seg->class->describe(seg, stream); - if (res != ResOK) return res; - - res = WriteF(stream, "\n", - "} Segment $P\n", (WriteFP)seg, NULL); - return res; -} - - -/* .seg.critical: These seg functions are low-level and used - * through-out. They are therefore on the - * [critical path](../design/critical-path.txt) and their AVERs are so-marked. - */ - -/* SegBase -- return the base address of a seg */ - -Addr (SegBase)(Seg seg) -{ - AVERT_CRITICAL(Seg, seg); - return SegBase(seg); -} - - -/* SegLimit -- return the limit address of a segment */ - -Addr (SegLimit)(Seg seg) -{ - AVERT_CRITICAL(Seg, seg); - return SegLimit(seg); -} - - -/* SegSize -- return the size of a seg */ - -Size SegSize(Seg seg) -{ - AVERT_CRITICAL(Seg, seg); - return AddrOffset(SegBase(seg), SegLimit(seg)); -} - - -/* SegOfAddr -- return the seg the given address is in, if any */ - -Bool SegOfAddr(Seg *segReturn, Arena arena, Addr addr) -{ - Tract tract; - AVER_CRITICAL(segReturn != NULL); /* .seg.critical */ - AVERT_CRITICAL(Arena, arena); /* .seg.critical */ - if (TractOfAddr(&tract, arena, addr)) { - return TRACT_SEG(segReturn, tract); - } else { - return FALSE; - } -} - - -/* SegFirst -- return the first seg in the arena - * - * This is used to start an iteration over all segs in the arena. - */ - -Bool SegFirst(Seg *segReturn, Arena arena) -{ - Tract tract; - AVER(segReturn != NULL); - AVERT(Arena, arena); - - if (TractFirst(&tract, arena)) { - do { - Seg seg; - if (TRACT_SEG(&seg, tract)) { - *segReturn = seg; - return TRUE; - } - } while (TractNext(&tract, arena, TractBase(tract))); - } - return FALSE; -} - - -/* SegNext -- return the "next" seg in the arena - * - * This is used as the iteration step when iterating over all - * segs in the arena. - * - * SegNext finds the seg with the lowest base address which is - * greater than a specified address. The address must be (or once - * have been) the base address of a seg. - */ - -Bool SegNext(Seg *segReturn, Arena arena, Addr addr) -{ - Tract tract; - Addr base = addr; - AVER_CRITICAL(segReturn != NULL); /* .seg.critical */ - AVERT_CRITICAL(Arena, arena); - - while (TractNext(&tract, arena, base)) { - Seg seg; - if (TRACT_SEG(&seg, tract)) { - if (tract == seg->firstTract) { - *segReturn = seg; - return TRUE; - } else { - /* found the next tract in a large segment */ - /* base & addr must be the base of this segment */ - AVER_CRITICAL(TractBase(seg->firstTract) == addr); - AVER_CRITICAL(addr == base); - /* set base to the last tract in the segment */ - base = AddrSub(seg->limit, ArenaAlign(arena)); - AVER_CRITICAL(base > addr); - } - } else { - base = TractBase(tract); - } - } - return FALSE; -} - - - -/* SegMerge -- Merge two adjacent segments - * - * See - */ - -Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi, - Bool withReservoirPermit, ...) -{ - SegClass class; - Addr base, mid, limit; - Arena arena; - Res res; - va_list args; - - AVER(NULL != mergedSegReturn); - AVERT(Seg, segLo); - AVERT(Seg, segHi); - class = segLo->class; - AVER(segHi->class == class); - AVER(SegPool(segLo) == SegPool(segHi)); - base = SegBase(segLo); - mid = SegLimit(segLo); - limit = SegLimit(segHi); - AVER(SegBase(segHi) == SegLimit(segLo)); - AVER(BoolCheck(withReservoirPermit)); - arena = PoolArena(SegPool(segLo)); - - ShieldFlush(arena); /* see */ - - /* Invoke class-specific methods to do the merge */ - va_start(args, withReservoirPermit); - res = class->merge(segLo, segHi, base, mid, limit, - withReservoirPermit, args); - va_end(args); - if (ResOK != res) - goto failMerge; - - EVENT3(SegMerge, segLo, segHi, withReservoirPermit); - /* Deallocate segHi object */ - ControlFree(arena, segHi, class->size); - AVERT(Seg, segLo); - *mergedSegReturn = segLo; - return ResOK; - -failMerge: - AVERT(Seg, segLo); /* check original segs are still valid */ - AVERT(Seg, segHi); - return res; -} - - -/* SegSplit -- Split a segment - * - * The segment is split at the indicated position. - * See - */ - -Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at, - Bool withReservoirPermit, ...) -{ - Addr base, limit; - SegClass class; - Seg segNew; - Arena arena; - Res res; - va_list args; - void *p; - - AVER(NULL != segLoReturn); - AVER(NULL != segHiReturn); - AVERT(Seg, seg); - class = seg->class; - arena = PoolArena(SegPool(seg)); - base = SegBase(seg); - limit = SegLimit(seg); - AVERT(Arena, arena); - AVER(AddrIsAligned(at, arena->alignment)); - AVER(at > base); - AVER(at < limit); - AVER(BoolCheck(withReservoirPermit)); - - ShieldFlush(arena); /* see */ - - /* Allocate the new segment object from the control pool */ - res = ControlAlloc(&p, arena, class->size, withReservoirPermit); - if (ResOK != res) - goto failControl; - segNew = p; - - /* Invoke class-specific methods to do the split */ - va_start(args, withReservoirPermit); - res = class->split(seg, segNew, base, at, limit, - withReservoirPermit, args); - va_end(args); - if (ResOK != res) - goto failSplit; - - EVENT4(SegSplit, seg, segNew, seg, at); - AVERT(Seg, seg); - AVERT(Seg, segNew); - *segLoReturn = seg; - *segHiReturn = segNew; - return ResOK; - -failSplit: - ControlFree(arena, segNew, class->size); -failControl: - AVERT(Seg, seg); /* check the original seg is still valid */ - return res; -} - - -/* Class Seg -- The most basic segment class - * - * .seg.method.check: Many seg methods are lightweight and used - * frequently. Their parameters are checked by the corresponding - * dispatching function, and so the their parameter AVERs are - * marked as critical. - */ - - -/* SegCheck -- check the integrity of a segment */ - -Bool SegCheck(Seg seg) -{ - Tract tract; - Arena arena; - Pool pool; - Addr addr; - Size align; - - CHECKS(Seg, seg); - CHECKL(TraceSetCheck(seg->white)); - - /* can't assume nailed is subset of white - mightn't be during whiten */ - /* CHECKL(TraceSetSub(seg->nailed, seg->white)); */ - CHECKL(TraceSetCheck(seg->grey)); - CHECKL(TractCheck(seg->firstTract)); /* */ - pool = SegPool(seg); - CHECKU(Pool, pool); - arena = PoolArena(pool); - CHECKU(Arena, arena); - align = ArenaAlign(arena); - CHECKL(AddrIsAligned(TractBase(seg->firstTract), align)); - CHECKL(AddrIsAligned(seg->limit, align)); - CHECKL(seg->limit > TractBase(seg->firstTract)); - - /* Each tract of the segment must agree about white traces */ - TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, seg->limit) { - Seg trseg = NULL; /* suppress compiler warning */ - - UNUSED(trseg); /* @@@@ unused in hot varieties */ - CHECKL(TractCheck(tract)); /* */ - CHECKL(TRACT_SEG(&trseg, tract) && (trseg == seg)); - CHECKL(TractWhite(tract) == seg->white); - CHECKL(TractPool(tract) == pool); - } - CHECKL(addr == seg->limit); - - /* The segment must belong to some pool, so it should be on a */ - /* pool's segment ring. (Actually, this isn't true just after */ - /* the segment is initialized.) */ - /* CHECKL(RingNext(&seg->poolRing) != &seg->poolRing); */ - - CHECKL(RingCheck(&seg->poolRing)); - - /* "pm", "sm", and "depth" not checked. See .check.shield. */ - CHECKL(RankSetCheck(seg->rankSet)); - if (seg->rankSet == RankSetEMPTY) { - /* : If there are no refs */ - /* in the segment then it cannot contain black or grey refs. */ - CHECKL(seg->grey == TraceSetEMPTY); - CHECKL(seg->sm == AccessSetEMPTY); - CHECKL(seg->pm == AccessSetEMPTY); - } else { - /* : The Tracer only permits */ - /* one rank per segment [ref?] so this field is either empty or a */ - /* singleton. */ - CHECKL(RankSetIsSingle(seg->rankSet)); - /* Can't check barrier invariants because SegCheck is called */ - /* when raising or lowering the barrier. */ - /* .check.wb: If summary isn't universal then it must be */ - /* write shielded. */ - /* CHECKL(seg->_summary == RefSetUNIV || (seg->_sm & AccessWRITE)); */ - /* @@@@ What can be checked about the read barrier? */ - } - return TRUE; -} - - -/* segTrivInit -- method to initialize the base fields of a segment */ - -static Res segTrivInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - /* all the initialization happens in SegInit so checks are safe */ - Size align; - Arena arena; - - AVERT(Seg, seg); - AVERT(Pool, pool); - arena = PoolArena(pool); - align = ArenaAlign(arena); - AVER(AddrIsAligned(base, align)); - AVER(SizeIsAligned(size, align)); - AVER(SegBase(seg) == base); - AVER(SegSize(seg) == size); - AVER(SegPool(seg) == pool); - AVER(BoolCheck(reservoirPermit)); - UNUSED(args); - return ResOK; -} - - -/* segTrivFinish -- finish the base fields of a segment */ - -static void segTrivFinish(Seg seg) -{ - /* all the generic finishing happens in SegFinish */ - AVERT(Seg, seg); -} - - -/* segNoSetGrey -- non-method to change the greyness of a segment */ - -static void segNoSetGrey(Seg seg, TraceSet grey) -{ - AVERT(Seg, seg); - AVER(TraceSetCheck(grey)); - AVER(seg->rankSet != RankSetEMPTY); - NOTREACHED; -} - - -/* segNoSetWhite -- non-method to change the whiteness of a segment */ - -static void segNoSetWhite(Seg seg, TraceSet white) -{ - AVERT(Seg, seg); - AVER(TraceSetCheck(white)); - NOTREACHED; -} - - -/* segNoSetRankSet -- non-method to set the rank set of a segment */ - -static void segNoSetRankSet(Seg seg, RankSet rankSet) -{ - AVERT(Seg, seg); - AVER(RankSetCheck(rankSet)); - NOTREACHED; -} - - -/* segNoSetSummary -- non-method to set the summary of a segment */ - -static void segNoSetSummary(Seg seg, RefSet summary) -{ - AVERT(Seg, seg); - UNUSED(summary); - NOTREACHED; -} - - -/* segNoSetRankSummary -- non-method to set the rank set & summary */ - -static void segNoSetRankSummary(Seg seg, RankSet rankSet, RefSet summary) -{ - AVERT(Seg, seg); - AVER(RankSetCheck(rankSet)); - UNUSED(summary); - NOTREACHED; -} - - -/* segNoBuffer -- non-method to return the buffer of a segment */ - -static Buffer segNoBuffer(Seg seg) -{ - AVERT(Seg, seg); - NOTREACHED; - return NULL; -} - - -/* segNoSetBuffer -- non-method to set the buffer of a segment */ - -static void segNoSetBuffer(Seg seg, Buffer buffer) -{ - AVERT(Seg, seg); - if (buffer != NULL) - AVERT(Buffer, buffer); - NOTREACHED; -} - - - -/* segNoMerge -- merge method for segs which don't support merge */ - -static Res segNoMerge(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - AVERT(Seg, seg); - AVERT(Seg, segHi); - AVER(SegBase(seg) == base); - AVER(SegLimit(seg) == mid); - AVER(SegBase(segHi) == mid); - AVER(SegLimit(segHi) == limit); - AVER(BoolCheck(withReservoirPermit)); - UNUSED(args); - NOTREACHED; - return ResFAIL; -} - - -/* segTrivMerge -- Basic Seg merge method - * - * .similar: Segments must be "sufficiently similar". - * See - */ - -static Res segTrivMerge(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - Pool pool; - Size align; - Arena arena; - Tract tract; - Addr addr; - - AVERT(Seg, seg); - AVERT(Seg, segHi); - pool = SegPool(seg); - arena = PoolArena(pool); - align = ArenaAlign(arena); - AVER(AddrIsAligned(base, align)); - AVER(AddrIsAligned(mid, align)); - AVER(AddrIsAligned(limit, align)); - AVER(base < mid); - AVER(mid < limit); - AVER(SegBase(seg) == base); - AVER(SegLimit(seg) == mid); - AVER(SegBase(segHi) == mid); - AVER(SegLimit(segHi) == limit); - AVER(BoolCheck(withReservoirPermit)); - UNUSED(args); - - /* .similar. */ - AVER(seg->rankSet == segHi->rankSet); - AVER(seg->white == segHi->white); - AVER(seg->nailed == segHi->nailed); - AVER(seg->grey == segHi->grey); - AVER(seg->pm == segHi->pm); - AVER(seg->sm == segHi->sm); - AVER(seg->depth == segHi->depth); - /* Neither segment may be exposed, or in the shield cache */ - /* See & */ - AVER(seg->depth == 0); - - /* no need to update fields which match. See .similar */ - - seg->limit = limit; - TRACT_FOR(tract, addr, arena, mid, limit) { - AVER(TractCheck(tract)); /* */ - AVER(TractHasSeg(tract)); - AVER(segHi == TractP(tract)); - AVER(TractPool(tract) == pool); - TRACT_SET_SEG(tract, seg); - } - AVER(addr == seg->limit); - - /* Finish segHi. */ - RingRemove(SegPoolRing(segHi)); - RingFinish(SegPoolRing(segHi)); - segHi->sig = SigInvalid; - - AVERT(Seg, seg); - return ResOK; -} - - -/* segNoSplit -- split method for segs which don't support splitting */ - -static Res segNoSplit(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - AVERT(Seg, seg); - AVER(segHi != NULL); /* can't check fully, it's not initialized */ - AVER(base < mid); - AVER(mid < limit); - AVER(SegBase(seg) == base); - AVER(SegLimit(seg) == limit); - AVER(BoolCheck(withReservoirPermit)); - UNUSED(args); - NOTREACHED; - return ResFAIL; - -} - - -/* segTrivSplit -- Basic Seg split method */ - -static Res segTrivSplit(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - Tract tract; - Pool pool; - Addr addr; - Size align; - Arena arena; - - AVERT(Seg, seg); - AVER(segHi != NULL); /* can't check fully, it's not initialized */ - pool = SegPool(seg); - arena = PoolArena(pool); - align = ArenaAlign(arena); - AVER(AddrIsAligned(base, align)); - AVER(AddrIsAligned(mid, align)); - AVER(AddrIsAligned(limit, align)); - AVER(base < mid); - AVER(mid < limit); - AVER(SegBase(seg) == base); - AVER(SegLimit(seg) == limit); - AVER(BoolCheck(withReservoirPermit)); - UNUSED(args); - - /* Segment may not be exposed, or in the shield cache */ - /* See & */ - AVER(seg->depth == 0); - - /* Full initialization for segHi. Just modify seg. */ - seg->limit = mid; - segHi->limit = limit; - segHi->rankSet = seg->rankSet; - segHi->white = seg->white; - segHi->nailed = seg->nailed; - segHi->grey = seg->grey; - segHi->pm = seg->pm; - segHi->sm = seg->sm; - segHi->depth = seg->depth; - segHi->firstTract = NULL; - segHi->class = seg->class; - segHi->sig = SegSig; - RingInit(SegPoolRing(segHi)); - - TRACT_FOR(tract, addr, arena, mid, limit) { - AVER(TractCheck(tract)); /* */ - AVER(TractHasSeg(tract)); - AVER(seg == TractP(tract)); - AVER(TractPool(tract) == pool); - TRACT_SET_SEG(tract, segHi); - if (addr == mid) { - AVER(segHi->firstTract == NULL); - segHi->firstTract = tract; - } - AVER(segHi->firstTract != NULL); - } - AVER(addr == segHi->limit); - - RingAppend(&pool->segRing, SegPoolRing(segHi)); - AVERT(Seg, seg); - AVERT(Seg, segHi); - return ResOK; -} - - -/* segTrivDescribe -- Basic Seg description method */ - -static Res segTrivDescribe(Seg seg, mps_lib_FILE *stream) -{ - Res res; - - if (!TESTT(Seg, seg)) return ResFAIL; - if (stream == NULL) return ResFAIL; - - res = WriteF(stream, - " shield depth $U\n", (WriteFU)seg->depth, - " protection mode:", - NULL); - if (res != ResOK) return res; - if (SegPM(seg) & AccessREAD) { - res = WriteF(stream, " read", NULL); - if (res != ResOK) return res; - } - if (SegPM(seg) & AccessWRITE) { - res = WriteF(stream, " write", NULL); - if (res != ResOK) return res; - } - res = WriteF(stream, "\n shield mode:", NULL); - if (res != ResOK) return res; - if (SegSM(seg) & AccessREAD) { - res = WriteF(stream, " read", NULL); - if (res != ResOK) return res; - } - if (SegSM(seg) & AccessWRITE) { - res = WriteF(stream, " write", NULL); - if (res != ResOK) return res; - } - res = WriteF(stream, "\n ranks:", NULL); - /* This bit ought to be in a RankSetDescribe in ref.c. */ - if (RankSetIsMember(seg->rankSet, RankAMBIG)) { - res = WriteF(stream, " ambiguous", NULL); - if (res != ResOK) return res; - } - if (RankSetIsMember(seg->rankSet, RankEXACT)) { - res = WriteF(stream, " exact", NULL); - if (res != ResOK) return res; - } - if (RankSetIsMember(seg->rankSet, RankFINAL)) { - res = WriteF(stream, " final", NULL); - if (res != ResOK) return res; - } - if (RankSetIsMember(seg->rankSet, RankWEAK)) { - res = WriteF(stream, " weak", NULL); - if (res != ResOK) return res; - } - res = WriteF(stream, "\n", - " white $B\n", (WriteFB)seg->white, - " grey $B\n", (WriteFB)seg->grey, - " nailed $B\n", (WriteFB)seg->nailed, - NULL); - return res; -} - - -/* Class GCSeg -- Segment class with GC support - */ - - -/* GCSegCheck -- check the integrity of a GCSeg */ - -Bool GCSegCheck(GCSeg gcseg) -{ - Seg seg; - CHECKS(GCSeg, gcseg); - seg = &gcseg->segStruct; - CHECKL(SegCheck(seg)); - - if (gcseg->buffer != NULL) { - CHECKU(Buffer, gcseg->buffer); - /* */ - CHECKL(BufferPool(gcseg->buffer) == SegPool(seg)); - CHECKL(BufferRankSet(gcseg->buffer) == SegRankSet(seg)); - } - - /* The segment should be on a grey ring if and only if it is grey. */ - CHECKL(RingCheck(&gcseg->greyRing)); - CHECKL((seg->grey == TraceSetEMPTY) == - RingIsSingle(&gcseg->greyRing)); - - if (seg->rankSet == RankSetEMPTY) { - /* */ - CHECKL(gcseg->summary == RefSetEMPTY); - } - - return TRUE; -} - - -/* gcSegInit -- method to initialize a GC segment */ - -static Res gcSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool withReservoirPermit, va_list args) -{ - SegClass super; - GCSeg gcseg; - Arena arena; - Align align; - Res res; - - AVERT(Seg, seg); - AVERT(Pool, pool); - arena = PoolArena(pool); - align = ArenaAlign(arena); - AVER(AddrIsAligned(base, align)); - AVER(SizeIsAligned(size, align)); - gcseg = SegGCSeg(seg); - AVER(&gcseg->segStruct == seg); - AVER(BoolCheck(withReservoirPermit)); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(GCSegClass); - res = super->init(seg, pool, base, size, withReservoirPermit, args); - if (ResOK != res) - return res; - - gcseg->summary = RefSetEMPTY; - gcseg->buffer = NULL; - RingInit(&gcseg->greyRing); - gcseg->sig = GCSegSig; - - AVERT(GCSeg, gcseg); - return ResOK; -} - - -/* gcSegFinish -- finish a GC segment */ - -static void gcSegFinish(Seg seg) -{ - SegClass super; - GCSeg gcseg; - - AVERT(Seg, seg); - gcseg = SegGCSeg(seg); - AVERT(GCSeg, gcseg); - AVER(&gcseg->segStruct == seg); - - if (SegGrey(seg) != TraceSetEMPTY) { - RingRemove(&gcseg->greyRing); - seg->grey = TraceSetEMPTY; - } - gcseg->summary = RefSetEMPTY; - - gcseg->sig = SigInvalid; - - /* Don't leave a dangling buffer allocating into hyperspace. */ - AVER(gcseg->buffer == NULL); - - RingFinish(&gcseg->greyRing); - - /* finish the superclass fields last */ - super = SEG_SUPERCLASS(GCSegClass); - super->finish(seg); -} - - -/* gcSegSetGreyInternal -- change the greyness of a segment - * - * Internal method for updating the greyness of a GCSeg. - * Updates the grey ring and the grey seg count. - * Doesn't affect the shield (so it can be used by split - * & merge methods). - */ - -static void gcSegSetGreyInternal(Seg seg, TraceSet oldGrey, TraceSet grey) -{ - GCSeg gcseg; - Arena arena; - Rank rank; - - /* Internal method. Parameters are checked by caller */ - gcseg = SegGCSeg(seg); - arena = PoolArena(SegPool(seg)); - seg->grey = grey; - - /* If the segment is now grey and wasn't before, add it to the */ - /* appropriate grey list so that TraceFindGrey can locate it */ - /* quickly later. If it is no longer grey and was before, */ - /* remove it from the list. */ - if (oldGrey == TraceSetEMPTY) { - if (grey != TraceSetEMPTY) { - AVER(RankSetIsSingle(seg->rankSet)); - for(rank = 0; rank < RankLIMIT; ++rank) - if (RankSetIsMember(seg->rankSet, rank)) { - /* NOTE: We push the segment onto the front of the queue, so that - we preserve some locality of scanning, and so that we tend to - forward objects that are closely linked to the same or nearby - segments. */ - RingInsert(ArenaGreyRing(arena, rank), &gcseg->greyRing); - break; - } - AVER(rank != RankLIMIT); /* there should've been a match */ - } - } else { - if (grey == TraceSetEMPTY) - RingRemove(&gcseg->greyRing); - } - - STATISTIC_STAT - ({ - TraceId ti; Trace trace; - TraceSet diff; - - diff = TraceSetDiff(grey, oldGrey); - TRACE_SET_ITER(ti, trace, diff, arena) - ++trace->greySegCount; - if (trace->greySegCount > trace->greySegMax) - trace->greySegMax = trace->greySegCount; - TRACE_SET_ITER_END(ti, trace, diff, arena); - - diff = TraceSetDiff(oldGrey, grey); - TRACE_SET_ITER(ti, trace, diff, arena) - --trace->greySegCount; - TRACE_SET_ITER_END(ti, trace, diff, arena); - }); - -} - - -/* gcSegSetGrey -- GCSeg method to change the greyness of a segment - * - * Sets the segment greyness to the trace set grey and adjusts - * the shielding on the segment appropriately. - */ - -static void gcSegSetGrey(Seg seg, TraceSet grey) -{ - GCSeg gcseg; - TraceSet oldGrey, flippedTraces; - Arena arena; - - AVERT_CRITICAL(Seg, seg); /* .seg.method.check */ - AVER_CRITICAL(TraceSetCheck(grey)); /* .seg.method.check */ - AVER(seg->rankSet != RankSetEMPTY); - gcseg = SegGCSeg(seg); - AVERT_CRITICAL(GCSeg, gcseg); - AVER_CRITICAL(&gcseg->segStruct == seg); - UNUSED(gcseg); - - arena = PoolArena(SegPool(seg)); - oldGrey = seg->grey; - gcSegSetGreyInternal(seg, oldGrey, grey); /* do the work */ - - /* The read barrier is raised when the segment is grey for */ - /* some _flipped_ trace, i.e., is grey for a trace for which */ - /* the mutator is black. */ - flippedTraces = arena->flippedTraces; - if (TraceSetInter(oldGrey, flippedTraces) == TraceSetEMPTY) { - if (TraceSetInter(grey, flippedTraces) != TraceSetEMPTY) - ShieldRaise(arena, seg, AccessREAD); - } else { - if (TraceSetInter(grey, flippedTraces) == TraceSetEMPTY) - ShieldLower(arena, seg, AccessREAD); - } - - EVENT3(SegSetGrey, arena, seg, grey); -} - - -/* gcSegSetWhite -- GCSeg method to change whiteness of a segment - * - * Sets the segment whiteness to the trace set ts. - */ - -static void gcSegSetWhite(Seg seg, TraceSet white) -{ - GCSeg gcseg; - Tract tract; - Arena arena; - Addr addr, limit; - - AVERT_CRITICAL(Seg, seg); /* .seg.method.check */ - AVER_CRITICAL(TraceSetCheck(white)); /* .seg.method.check */ - gcseg = SegGCSeg(seg); - AVERT_CRITICAL(GCSeg, gcseg); - AVER_CRITICAL(&gcseg->segStruct == seg); - - arena = PoolArena(SegPool(seg)); - AVERT_CRITICAL(Arena, arena); - limit = SegLimit(seg); - /* Each tract of the segment records white traces */ - TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, limit) { - Seg trseg = NULL; /* suppress compiler warning */ - - UNUSED(trseg); /* @@@@ unused in hot varieties */ - AVER_CRITICAL(TractCheck(tract)); /* */ - AVER_CRITICAL(TRACT_SEG(&trseg, tract) && (trseg == seg)); - TractSetWhite(tract, white); - } - AVER(addr == limit); - - seg->white = white; -} - - -/* gcSegSetRankSet -- GCSeg method to set the rank set of a segment - * - * If the rank set is made non-empty then the segment's summary is - * now a subset of the mutator's (which is assumed to be RefSetUNIV) - * so the write barrier must be imposed on the segment. If the - * rank set is made empty then there are no longer any references - * on the segment so the barrier is removed. - * - * The caller must set the summary to empty before setting the rank - * set to empty. The caller must set the rank set to non-empty before - * setting the summary to non-empty. - */ - -static void gcSegSetRankSet(Seg seg, RankSet rankSet) -{ - GCSeg gcseg; - RankSet oldRankSet; - Arena arena; - - AVERT_CRITICAL(Seg, seg); /* .seg.method.check */ - AVER_CRITICAL(RankSetCheck(rankSet)); /* .seg.method.check */ - AVER_CRITICAL(rankSet == RankSetEMPTY - || RankSetIsSingle(rankSet)); /* .seg.method.check */ - gcseg = SegGCSeg(seg); - AVERT_CRITICAL(GCSeg, gcseg); - AVER_CRITICAL(&gcseg->segStruct == seg); - - arena = PoolArena(SegPool(seg)); - oldRankSet = seg->rankSet; - seg->rankSet = rankSet; - - if (oldRankSet == RankSetEMPTY) { - if (rankSet != RankSetEMPTY) { - AVER(gcseg->summary == RefSetEMPTY); - ShieldRaise(arena, seg, AccessWRITE); - } - } else { - if (rankSet == RankSetEMPTY) { - AVER(gcseg->summary == RefSetEMPTY); - ShieldLower(arena, seg, AccessWRITE); - } - } -} - - -/* gcSegSetSummary -- GCSeg method to change the summary on a segment - * - * In fact, we only need to raise the write barrier if the - * segment contains references, and its summary is strictly smaller - * than the summary of the unprotectable data (i.e. the mutator). - * We don't maintain such a summary, assuming that the mutator can - * access all references, so its summary is RefSetUNIV. - */ - -static void gcSegSetSummary(Seg seg, RefSet summary) -{ - GCSeg gcseg; - RefSet oldSummary; - Arena arena; - - AVERT_CRITICAL(Seg, seg); /* .seg.method.check */ - gcseg = SegGCSeg(seg); - AVERT_CRITICAL(GCSeg, gcseg); - AVER_CRITICAL(&gcseg->segStruct == seg); - - arena = PoolArena(SegPool(seg)); - oldSummary = gcseg->summary; - gcseg->summary = summary; - - AVER(seg->rankSet != RankSetEMPTY); - - /* Note: !RefSetSuper is a test for a strict subset */ - if (!RefSetSuper(summary, RefSetUNIV)) { - if (RefSetSuper(oldSummary, RefSetUNIV)) - ShieldRaise(arena, seg, AccessWRITE); - } else { - if (!RefSetSuper(oldSummary, RefSetUNIV)) - ShieldLower(arena, seg, AccessWRITE); - } -} - - -/* gcSegSetRankSummary -- GCSeg method to set both rank set and summary */ - -static void gcSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary) -{ - GCSeg gcseg; - Bool wasShielded, willbeShielded; - Arena arena; - - AVERT_CRITICAL(Seg, seg); /* .seg.method.check */ - AVER_CRITICAL(RankSetCheck(rankSet)); /* .seg.method.check */ - AVER_CRITICAL(rankSet == RankSetEMPTY - || RankSetIsSingle(rankSet)); /* .seg.method.check */ - gcseg = SegGCSeg(seg); - AVERT_CRITICAL(GCSeg, gcseg); - AVER_CRITICAL(&gcseg->segStruct == seg); - - /* rankSet == RankSetEMPTY implies summary == RefSetEMPTY */ - AVER(rankSet != RankSetEMPTY || summary == RefSetEMPTY); - - arena = PoolArena(SegPool(seg)); - - wasShielded = (seg->rankSet != RankSetEMPTY && gcseg->summary != RefSetUNIV); - willbeShielded = (rankSet != RankSetEMPTY && summary != RefSetUNIV); - - seg->rankSet = rankSet; - gcseg->summary = summary; - - if (willbeShielded && !wasShielded) { - ShieldRaise(arena, seg, AccessWRITE); - } else if (wasShielded && !willbeShielded) { - ShieldLower(arena, seg, AccessWRITE); - } -} - - -/* gcSegBuffer -- GCSeg method to return the buffer of a segment */ - -static Buffer gcSegBuffer(Seg seg) -{ - GCSeg gcseg; - - AVERT_CRITICAL(Seg, seg); /* .seg.method.check */ - gcseg = SegGCSeg(seg); - AVERT_CRITICAL(GCSeg, gcseg); /* .seg.method.check */ - AVER_CRITICAL(&gcseg->segStruct == seg); - - return gcseg->buffer; -} - - -/* gcSegSetBuffer -- GCSeg method to change the buffer of a segment */ - -static void gcSegSetBuffer(Seg seg, Buffer buffer) -{ - GCSeg gcseg; - - AVERT_CRITICAL(Seg, seg); /* .seg.method.check */ - if (buffer != NULL) - AVERT_CRITICAL(Buffer, buffer); - gcseg = SegGCSeg(seg); - AVERT_CRITICAL(GCSeg, gcseg); - AVER_CRITICAL(&gcseg->segStruct == seg); - - gcseg->buffer = buffer; -} - - -/* gcSegMerge -- GCSeg merge method - * - * .buffer: Can't merge two segments both with buffers. - * See . - */ - -static Res gcSegMerge(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - SegClass super; - GCSeg gcseg, gcsegHi; - TraceSet grey; - RefSet summary; - Buffer buf; - Res res; - - AVERT(Seg, seg); - AVERT(Seg, segHi); - gcseg = SegGCSeg(seg); - gcsegHi = SegGCSeg(segHi); - AVERT(GCSeg, gcseg); - AVERT(GCSeg, gcsegHi); - AVER(base < mid); - AVER(mid < limit); - AVER(SegBase(seg) == base); - AVER(SegLimit(seg) == mid); - AVER(SegBase(segHi) == mid); - AVER(SegLimit(segHi) == limit); - AVER(BoolCheck(withReservoirPermit)); - - buf = gcsegHi->buffer; /* any buffer on segHi must be reassigned */ - AVER(buf == NULL || gcseg->buffer == NULL); /* See .buffer */ - grey = SegGrey(segHi); /* check greyness */ - AVER(SegGrey(seg) == grey); - - /* Merge the superclass fields via next-method call */ - super = SEG_SUPERCLASS(GCSegClass); - res = super->merge(seg, segHi, base, mid, limit, - withReservoirPermit, args); - if (res != ResOK) - goto failSuper; - - /* Update fields of gcseg. Finish gcsegHi. */ - summary = RefSetUnion(gcseg->summary, gcsegHi->summary); - if (summary != gcseg->summary) { - gcSegSetSummary(seg, summary); - /* */ - ShieldFlush(PoolArena(SegPool(seg))); - } - - gcSegSetGreyInternal(segHi, grey, TraceSetEMPTY); - gcsegHi->summary = RefSetEMPTY; - gcsegHi->sig = SigInvalid; - RingFinish(&gcsegHi->greyRing); - - /* Reassign any buffer that was connected to segHi */ - if (NULL != buf) { - AVER(gcseg->buffer == NULL); - gcseg->buffer = buf; - gcsegHi->buffer = NULL; - BufferReassignSeg(buf, seg); - } - - AVERT(GCSeg, gcseg); - return ResOK; - -failSuper: - AVERT(GCSeg, gcseg); - AVERT(GCSeg, gcsegHi); - return res; -} - - -/* gcSegSplit -- GCSeg split method */ - -static Res gcSegSplit(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - SegClass super; - GCSeg gcseg, gcsegHi; - Buffer buf; - TraceSet grey; - Res res; - - AVERT(Seg, seg); - AVER(segHi != NULL); /* can't check fully, it's not initialized */ - gcseg = SegGCSeg(seg); - gcsegHi = SegGCSeg(segHi); - AVERT(GCSeg, gcseg); - AVER(base < mid); - AVER(mid < limit); - AVER(SegBase(seg) == base); - AVER(SegLimit(seg) == limit); - AVER(BoolCheck(withReservoirPermit)); - - grey = SegGrey(seg); - buf = gcseg->buffer; /* Look for buffer to reassign to segHi */ - if (buf != NULL) { - if (BufferLimit(buf) > mid) { - /* Existing buffer extends above the split point */ - AVER(BufferBase(buf) > mid); /* check it's all above the split */ - } else { - buf = NULL; /* buffer lies below split and is unaffected */ - } - } - - /* Split the superclass fields via next-method call */ - super = SEG_SUPERCLASS(GCSegClass); - res = super->split(seg, segHi, base, mid, limit, - withReservoirPermit, args); - if (res != ResOK) - goto failSuper; - - /* Full initialization for segHi. */ - gcsegHi->summary = gcseg->summary; - gcsegHi->buffer = NULL; - RingInit(&gcsegHi->greyRing); - gcsegHi->sig = GCSegSig; - gcSegSetGreyInternal(segHi, TraceSetEMPTY, grey); - - /* Reassign buffer if it's now connected to segHi */ - if (NULL != buf) { - gcsegHi->buffer = buf; - gcseg->buffer = NULL; - BufferReassignSeg(buf, segHi); - } - - AVERT(GCSeg, gcseg); - AVERT(GCSeg, gcsegHi); - return ResOK; - -failSuper: - AVERT(GCSeg, gcseg); - return res; -} - - -/* gcSegDescribe -- GCSeg description method */ - -static Res gcSegDescribe(Seg seg, mps_lib_FILE *stream) -{ - Res res; - SegClass super; - GCSeg gcseg; - - if (!TESTT(Seg, seg)) return ResFAIL; - if (stream == NULL) return ResFAIL; - gcseg = SegGCSeg(seg); - if (!TESTT(GCSeg, gcseg)) return ResFAIL; - - /* Describe the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(GCSegClass); - res = super->describe(seg, stream); - if (res != ResOK) return res; - - res = WriteF(stream, - " summary $W\n", (WriteFW)gcseg->summary, - NULL); - if (res != ResOK) return res; - - if (gcseg->buffer == NULL) { - res = WriteF(stream, " buffer: NULL\n", NULL); - } - else { - res = BufferDescribe(gcseg->buffer, stream); - } - if (res != ResOK) return res; - - return ResOK; -} - - -/* SegClassCheck -- check a segment class */ - -Bool SegClassCheck(SegClass class) -{ - CHECKL(ProtocolClassCheck(&class->protocol)); - CHECKL(class->name != NULL); /* Should be <= 6 char C identifier */ - CHECKL(class->size >= sizeof(SegStruct)); - CHECKL(FUNCHECK(class->init)); - CHECKL(FUNCHECK(class->finish)); - CHECKL(FUNCHECK(class->setGrey)); - CHECKL(FUNCHECK(class->setWhite)); - CHECKL(FUNCHECK(class->setRankSet)); - CHECKL(FUNCHECK(class->setRankSummary)); - CHECKL(FUNCHECK(class->merge)); - CHECKL(FUNCHECK(class->split)); - CHECKL(FUNCHECK(class->describe)); - CHECKS(SegClass, class); - return TRUE; -} - - -/* SegClass -- the vanilla segment class definition */ - -DEFINE_CLASS(SegClass, class) -{ - INHERIT_CLASS(&class->protocol, ProtocolClass); - class->name = "SEG"; - class->size = sizeof(SegStruct); - class->init = segTrivInit; - class->finish = segTrivFinish; - class->setSummary = segNoSetSummary; - class->buffer = segNoBuffer; - class->setBuffer = segNoSetBuffer; - class->setGrey = segNoSetGrey; - class->setWhite = segNoSetWhite; - class->setRankSet = segNoSetRankSet; - class->setRankSummary = segNoSetRankSummary; - class->merge = segTrivMerge; - class->split = segTrivSplit; - class->describe = segTrivDescribe; - class->sig = SegClassSig; -} - - -/* GCSegClass -- GC-supporting segment class definition */ - -typedef SegClassStruct GCSegClassStruct; - -DEFINE_CLASS(GCSegClass, class) -{ - INHERIT_CLASS(class, SegClass); - class->name = "GCSEG"; - class->size = sizeof(GCSegStruct); - class->init = gcSegInit; - class->finish = gcSegFinish; - class->setSummary = gcSegSetSummary; - class->buffer = gcSegBuffer; - class->setBuffer = gcSegSetBuffer; - class->setGrey = gcSegSetGrey; - class->setWhite = gcSegSetWhite; - class->setRankSet = gcSegSetRankSet; - class->setRankSummary = gcSegSetRankSummary; - class->merge = gcSegMerge; - class->split = gcSegSplit; - class->describe = gcSegDescribe; -} - - -/* SegClassMixInNoSplitMerge -- Mix-in for unsupported merge - * - * Classes which don't support segment splitting and merging - * may mix this in to ensure that erroneous calls are checked. - */ - -void SegClassMixInNoSplitMerge(SegClass class) -{ - /* Can't check class because it's not initialized yet */ - class->merge = segNoMerge; - class->split = segNoSplit; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c deleted file mode 100644 index 8f7c6095308..00000000000 --- a/mps/code/segsmss.c +++ /dev/null @@ -1,904 +0,0 @@ -/* segsmss.c: Segment splitting and merging stress test - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (c) 2002 Global Graphics Software. - * - * .design: Adapted from amsss.c (because AMS already supports - * a protocol for subclassing AMS segments). Defines a new pool - * class, AMST. Segments are split and merged during BufferFill - * operations. Buffered segments are also split and merged between - * allocation requests. - */ - -#include "mpm.h" -#include "poolams.h" -#include "fmtdy.h" -#include "fmtdytst.h" -#include "testlib.h" -#include "chain.h" -#include "mpscams.h" -#include "mpsavm.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include "mps.h" -#include -#include -#include -#include - - -/* Forward declarations */ - -static SegClass AMSTSegClassGet(void); -static PoolClass AMSTPoolClassGet(void); - - -/* Start by defining the AMST pool (AMS Test pool) */ - -#define AMSTSig ((Sig)0x519A3529) /* SIGnature AMST */ - -/* AMSTStruct -- AMST pool instance structure */ - -typedef struct AMSTStruct { - AMSStruct amsStruct; /* generic AMS structure */ - Chain chain; /* chain to use */ - Bool failSegs; /* fail seg splits & merges when true */ - Count splits; /* count of successful segment splits */ - Count merges; /* count of successful segment merges */ - Count badSplits; /* count of unsuccessful segment splits */ - Count badMerges; /* count of unsuccessful segment merges */ - Count bsplits; /* count of buffered segment splits */ - Count bmerges; /* count of buffered segment merges */ - Sig sig; /* */ -} AMSTStruct; - -typedef struct AMSTStruct *AMST; - -#define Pool2AMST(pool) PARENT(AMSTStruct, amsStruct.poolStruct, (pool)) -#define AMST2AMS(amst) (&(amst)->amsStruct) - - -/* AMSTCheck -- the check method for an AMST */ - -static Bool AMSTCheck(AMST amst) -{ - CHECKS(AMST, amst); - CHECKL(AMSCheck(AMST2AMS(amst))); - return TRUE; -} - -/* AMSTFailOperation -- should a split/merge operation fail? - * - * returns TRUE if so. - */ -static Bool AMSTFailOperation(AMST amst) -{ - if (amst->failSegs) { - return rnd() % 2; - } else { - return FALSE; - } -} - -/* AMSTSegStruct: AMST segment instances */ - -#define AMSTSegSig ((Sig)0x519A3525) /* SIGnature AMST Seg */ - -typedef struct AMSTSegStruct *AMSTSeg; - -typedef struct AMSTSegStruct { - AMSSegStruct amsSegStruct; /* superclass fields must come first */ - AMSTSeg next; /* mergeable next segment, or NULL */ - AMSTSeg prev; /* mergeable prev segment, or NULL */ - Sig sig; /* */ -} AMSTSegStruct; - - - -/* AMSTSegCheck -- check the AMST segment */ - -static Bool AMSTSegCheck(AMSTSeg amstseg) -{ - CHECKS(AMSTSeg, amstseg); - CHECKL(AMSSegCheck(&amstseg->amsSegStruct)); - /* don't bother to do other checks - this is a stress test */ - return TRUE; -} - -#define Seg2AMSTSeg(seg) ((AMSTSeg)(seg)) -#define AMSTSeg2Seg(amstseg) ((Seg)(amstseg)) - - -/* amstSegInit -- initialise an amst segment */ - -static Res amstSegInit(Seg seg, Pool pool, Addr base, Size size, - Bool reservoirPermit, va_list args) -{ - SegClass super; - AMSTSeg amstseg; - AMST amst; - Res res; - - AVERT(Seg, seg); - amstseg = Seg2AMSTSeg(seg); - AVERT(Pool, pool); - amst = Pool2AMST(pool); - AVERT(AMST, amst); - /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); - - /* Initialize the superclass fields first via next-method call */ - super = SEG_SUPERCLASS(AMSTSegClass); - res = super->init(seg, pool, base, size, reservoirPermit, args); - if (res != ResOK) - return res; - - amstseg->next = NULL; - amstseg->prev = NULL; - amstseg->sig = AMSTSegSig; - AVERT(AMSTSeg, amstseg); - - return ResOK; -} - - -/* amstSegFinish -- Finish method for AMST segments */ - -static void amstSegFinish(Seg seg) -{ - SegClass super; - AMSTSeg amstseg; - - AVERT(Seg, seg); - amstseg = Seg2AMSTSeg(seg); - AVERT(AMSTSeg, amstseg); - - if (amstseg->next != NULL) - amstseg->next->prev = NULL; - if (amstseg->prev != NULL) - amstseg->prev->next = NULL; - - amstseg->sig = SigInvalid; - /* finish the superclass fields last */ - super = SEG_SUPERCLASS(AMSTSegClass); - super->finish(seg); -} - - - -/* amstSegMerge -- AMSTSeg merge method - * - * .fail: Test proper handling of the most complex failure cases - * by deliberately detecting failure sometimes after calling the - * next method. We handle the error by calling the anti-method. - * This isn't strictly safe (see ). - * But we assume here that we won't run out of memory when calling the - * anti-method. - */ -static Res amstSegMerge(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - SegClass super; - AMST amst; - AMSTSeg amstseg, amstsegHi; - Res res; - - AVERT(Seg, seg); - AVERT(Seg, segHi); - amstseg = Seg2AMSTSeg(seg); - amstsegHi = Seg2AMSTSeg(segHi); - AVERT(AMSTSeg, amstseg); - AVERT(AMSTSeg, amstsegHi); - amst = Pool2AMST(SegPool(seg)); - - /* Merge the superclass fields via direct next-method call */ - super = SEG_SUPERCLASS(AMSTSegClass); - res = super->merge(seg, segHi, base, mid, limit, - withReservoirPermit, args); - if (res != ResOK) - goto failSuper; - - if (AMSTFailOperation(amst)) { - amst->badMerges++; - printf("D"); - goto failDeliberate; - } - - amstseg->next = amstsegHi->next; - amstsegHi->sig = SigInvalid; - AVERT(AMSTSeg, amstseg); - amst->merges++; - printf("M"); - return ResOK; - -failDeliberate: - /* Call the anti-method (see .fail) */ - res = super->split(seg, segHi, base, mid, limit, - withReservoirPermit, args); - AVER(res == ResOK); - res = ResFAIL; -failSuper: - AVERT(AMSTSeg, amstseg); - AVERT(AMSTSeg, amstsegHi); - return res; -} - - -/* amstSegSplit -- AMSTSeg split method */ - -static Res amstSegSplit(Seg seg, Seg segHi, - Addr base, Addr mid, Addr limit, - Bool withReservoirPermit, va_list args) -{ - SegClass super; - AMST amst; - AMSTSeg amstseg, amstsegHi; - Res res; - - AVERT(Seg, seg); - AVER(segHi != NULL); /* can't check fully, it's not initialized */ - amstseg = Seg2AMSTSeg(seg); - amstsegHi = Seg2AMSTSeg(segHi); - AVERT(AMSTSeg, amstseg); - amst = Pool2AMST(SegPool(seg)); - - /* Split the superclass fields via direct next-method call */ - super = SEG_SUPERCLASS(AMSTSegClass); - res = super->split(seg, segHi, base, mid, limit, - withReservoirPermit, args); - if (res != ResOK) - goto failSuper; - - if (AMSTFailOperation(amst)) { - amst->badSplits++; - printf("B"); - goto failDeliberate; - } - - /* Full initialization for segHi. */ - amstsegHi->next = amstseg->next; - amstsegHi->prev = amstseg; - amstsegHi->sig = AMSTSegSig; - amstseg->next = amstsegHi; - AVERT(AMSTSeg, amstseg); - AVERT(AMSTSeg, amstsegHi); - amst->splits++; - printf("S"); - return ResOK; - -failDeliberate: - /* Call the anti-method. (see .fail) */ - res = super->merge(seg, segHi, base, mid, limit, - withReservoirPermit, args); - AVER(res == ResOK); - res = ResFAIL; -failSuper: - AVERT(AMSTSeg, amstseg); - return res; -} - - -/* AMSTSegClass -- Class definition for AMST segments */ - -DEFINE_SEG_CLASS(AMSTSegClass, class) -{ - INHERIT_CLASS(class, AMSSegClass); - class->name = "AMSTSEG"; - class->size = sizeof(AMSTSegStruct); - class->init = amstSegInit; - class->finish = amstSegFinish; - class->split = amstSegSplit; - class->merge = amstSegMerge; -} - - -/* AMSTSegSizePolicy - * - * Picks double the default segment size. - */ -static Res AMSTSegSizePolicy(Size *sizeReturn, - Pool pool, Size size, RankSet rankSet) -{ - Arena arena; - Size basic, want; - - AVER(sizeReturn != NULL); - AVERT(Pool, pool); - AVER(size > 0); - AVER(RankSetCheck(rankSet)); - - arena = PoolArena(pool); - - basic = SizeAlignUp(size, ArenaAlign(arena)); - if (basic == 0) { - /* overflow */ - return ResMEMORY; - } - want = basic + basic; - if (want <= basic) { - /* overflow */ - return ResMEMORY; - } - *sizeReturn = want; - return ResOK; -} - - -/* AMSTInit -- the pool class initialization method */ - -static Res AMSTInit(Pool pool, va_list args) -{ - AMST amst; AMS ams; - Format format; - Chain chain; - Res res; - static GenParamStruct genParam = { 1024, 0.2 }; - - AVERT(Pool, pool); - - format = va_arg(args, Format); - res = ChainCreate(&chain, pool->arena, 1, &genParam); - if (res != ResOK) - return res; - res = AMSInitInternal(Pool2AMS(pool), format, chain, FALSE); - if (res != ResOK) - return res; - amst = Pool2AMST(pool); - ams = Pool2AMS(pool); - ams->segSize = AMSTSegSizePolicy; - ams->segClass = AMSTSegClassGet; - amst->chain = chain; - amst->failSegs = TRUE; - amst->splits = 0; - amst->merges = 0; - amst->badSplits = 0; - amst->badMerges = 0; - amst->bsplits = 0; - amst->bmerges = 0; - amst->sig = AMSTSig; - AVERT(AMST, amst); - return ResOK; -} - - -/* AMSTFinish -- the pool class finish method */ - -static void AMSTFinish(Pool pool) -{ - AMST amst; - - AVERT(Pool, pool); - amst = Pool2AMST(pool); - AVERT(AMST, amst); - - printf("\nDestroying pool, having performed:\n"); - printf(" %"PRIuLONGEST" splits (S)\n", (ulongest_t)amst->splits); - printf(" %"PRIuLONGEST" merges (M)\n", (ulongest_t)amst->merges); - printf(" %"PRIuLONGEST" aborted splits (B)\n", (ulongest_t)amst->badSplits); - printf(" %"PRIuLONGEST" aborted merges (D)\n", (ulongest_t)amst->badMerges); - printf(" which included:\n"); - printf(" %"PRIuLONGEST" buffered splits (C)\n", (ulongest_t)amst->bsplits); - printf(" %"PRIuLONGEST" buffered merges (J)\n", (ulongest_t)amst->bmerges); - - AMSFinish(pool); - amst->sig = SigInvalid; - ChainDestroy(amst->chain); -} - - -/* AMSSegIsFree -- return TRUE if a seg is all unallocated */ - -static Bool AMSSegIsFree(Seg seg) -{ - AMSSeg amsseg; - AVERT(Seg, seg); - amsseg = Seg2AMSSeg(seg); - return(amsseg->free == amsseg->grains); -} - - -/* AMSSegRegionIsFree -- return TRUE if a region is all unallocated */ - -static Bool AMSSegRegionIsFree(Seg seg, Addr base, Addr limit) -{ - AMSSeg amsseg; - AMS ams; - Count bgrain, lgrain; - Addr sbase; - - AVERT(Seg, seg); - amsseg = Seg2AMSSeg(seg); - sbase = SegBase(seg); - ams = Pool2AMS(SegPool(seg)); - - bgrain = AMSGrains(ams, AddrOffset(sbase, base)); - lgrain = AMSGrains(ams, AddrOffset(sbase, limit)); - - if (amsseg->allocTableInUse) { - return BTIsResRange(amsseg->allocTable, bgrain, lgrain); - } else { - return amsseg->firstFree <= bgrain; - } -} - - -/* AMSUnallocateRange -- set a range to be unallocated - * - * Used as a means of overriding the behaviour of AMSBufferFill. - * The code is similar to AMSBufferEmpty. - */ -static void AMSUnallocateRange(Seg seg, Addr base, Addr limit) -{ - AMSSeg amsseg; - Index baseIndex, limitIndex; - /* parameters checked by caller */ - - amsseg = Seg2AMSSeg(seg); - - baseIndex = AMS_ADDR_INDEX(seg, base); - limitIndex = AMS_ADDR_INDEX(seg, limit); - - if (amsseg->allocTableInUse) { - /* check that it's allocated */ - AVER(BTIsSetRange(amsseg->allocTable, baseIndex, limitIndex)); - BTResRange(amsseg->allocTable, baseIndex, limitIndex); - } else { - /* check that it's allocated */ - AVER(limitIndex <= amsseg->firstFree); - if (limitIndex == amsseg->firstFree) /* is it at the end? */ { - amsseg->firstFree = baseIndex; - } else { /* start using allocTable */ - amsseg->allocTableInUse = TRUE; - BTSetRange(amsseg->allocTable, 0, amsseg->firstFree); - if (amsseg->firstFree < amsseg->grains) - BTResRange(amsseg->allocTable, amsseg->firstFree, amsseg->grains); - BTResRange(amsseg->allocTable, baseIndex, limitIndex); - } - } - amsseg->free += limitIndex - baseIndex; - amsseg->newAlloc -= limitIndex - baseIndex; -} - - -/* AMSAllocateRange -- set a range to be allocated - * - * Used as a means of overriding the behaviour of AMSBufferFill. - * The code is similar to AMSUnallocateRange. - */ -static void AMSAllocateRange(Seg seg, Addr base, Addr limit) -{ - AMSSeg amsseg; - Index baseIndex, limitIndex; - /* parameters checked by caller */ - - amsseg = Seg2AMSSeg(seg); - - baseIndex = AMS_ADDR_INDEX(seg, base); - limitIndex = AMS_ADDR_INDEX(seg, limit); - - if (amsseg->allocTableInUse) { - /* check that it's not allocated */ - AVER(BTIsResRange(amsseg->allocTable, baseIndex, limitIndex)); - BTSetRange(amsseg->allocTable, baseIndex, limitIndex); - } else { - /* check that it's not allocated */ - AVER(baseIndex >= amsseg->firstFree); - if (baseIndex == amsseg->firstFree) /* is it at the end? */ { - amsseg->firstFree = limitIndex; - } else { /* start using allocTable */ - amsseg->allocTableInUse = TRUE; - BTSetRange(amsseg->allocTable, 0, amsseg->firstFree); - if (amsseg->firstFree < amsseg->grains) - BTResRange(amsseg->allocTable, amsseg->firstFree, amsseg->grains); - BTSetRange(amsseg->allocTable, baseIndex, limitIndex); - } - } - AVER(amsseg->free >= limitIndex - baseIndex); - amsseg->free -= limitIndex - baseIndex; - amsseg->newAlloc += limitIndex - baseIndex; -} - - -/* AMSTBufferFill -- the pool class buffer fill method - * - * Calls next method - but possibly splits or merges the chosen - * segment. - * - * .merge: A merge is performed when the next method returns - * the entire segment, this segment had previously been split - * from the segment below, and the segment below is appropriately - * similar (i.e. not already attached to a buffer and similarly grey) - * - * .split: If we're not merging, a split is performed if the next method - * returns the entire segment, and yet lower half of the segment would - * meet the request. - */ -static Res AMSTBufferFill(Addr *baseReturn, Addr *limitReturn, - Pool pool, Buffer buffer, Size size, - Bool withReservoirPermit) -{ - PoolClass super; - Addr base, limit; - Arena arena; - AMST amst; - Bool b; - Seg seg; - AMSTSeg amstseg; - Res res; - - AVERT(Pool, pool); - AVER(baseReturn != NULL); - AVER(limitReturn != NULL); - /* other parameters are checked by next method */ - arena = PoolArena(pool); - amst = Pool2AMST(pool); - - /* call next method */ - super = POOL_SUPERCLASS(AMSTPoolClass); - res = super->bufferFill(&base, &limit, pool, buffer, size, - withReservoirPermit); - if (res != ResOK) - return res; - - b = SegOfAddr(&seg, arena, base); - AVER(b); - amstseg = Seg2AMSTSeg(seg); - - if (SegLimit(seg) == limit && SegBase(seg) == base) { - if (amstseg->prev != NULL) { - Seg segLo = AMSTSeg2Seg(amstseg->prev); - if (SegBuffer(segLo) == NULL && SegGrey(segLo) == SegGrey(seg)) { - /* .merge */ - Seg mergedSeg; - Res mres; - - AMSUnallocateRange(seg, base, limit); - mres = SegMerge(&mergedSeg, segLo, seg, withReservoirPermit); - if (ResOK == mres) { /* successful merge */ - AMSAllocateRange(mergedSeg, base, limit); - /* leave range as-is */ - } else { /* failed to merge */ - AVER(amst->failSegs); /* deliberate fails only */ - AMSAllocateRange(seg, base, limit); - } - } - - } else { - Size half = SegSize(seg) / 2; - if (half >= size && SizeIsAligned(half, ArenaAlign(arena))) { - /* .split */ - Addr mid = AddrAdd(base, half); - Seg segLo, segHi; - Res sres; - AMSUnallocateRange(seg, mid, limit); - sres = SegSplit(&segLo, &segHi, seg, mid, withReservoirPermit); - if (ResOK == sres) { /* successful split */ - limit = mid; /* range is lower segment */ - } else { /* failed to split */ - AVER(amst->failSegs); /* deliberate fails only */ - AMSAllocateRange(seg, mid, limit); - } - - } - } - } - - *baseReturn = base; - *limitReturn = limit; - return ResOK; -} - - -/* AMSTStressBufferedSeg -- Stress test for a buffered seg - * - * Test splitting or merging a buffered seg. - * - * .bmerge: A merge is performed when the segment had previously - * been split and the segment above meets the constraints (i.e. empty, - * not already attached to a buffer and similar colour) - * - * .bsplit: Whether or not a merge happpened, a split is performed if - * the limit of the buffered region is arena aligned, and yet does not - * correspond to the segment limit, provided that the part of the segment - * above the buffer is all free. - */ -static void AMSTStressBufferedSeg(Seg seg, Buffer buffer) -{ - AMSTSeg amstseg; - AMST amst; - Arena arena; - Addr limit; - - AVERT(Seg, seg); - AVERT(Buffer, buffer); - AVER(SegBuffer(seg) == buffer); - amstseg = Seg2AMSTSeg(seg); - AVERT(AMSTSeg, amstseg); - limit = BufferLimit(buffer); - arena = PoolArena(SegPool(seg)); - amst = Pool2AMST(SegPool(seg)); - AVERT(AMST, amst); - - if (amstseg->next != NULL) { - Seg segHi = AMSTSeg2Seg(amstseg->next); - if (AMSSegIsFree(segHi) && SegGrey(segHi) == SegGrey(seg)) { - /* .bmerge */ - Seg mergedSeg; - Res res; - res = SegMerge(&mergedSeg, seg, segHi, FALSE); - if (ResOK == res) { - amst->bmerges++; - printf("J"); - } else { - /* deliberate fails only */ - AVER(amst->failSegs); - } - } - } - - if (SegLimit(seg) != limit && - AddrIsAligned(limit, ArenaAlign(arena)) && - AMSSegRegionIsFree(seg, limit, SegLimit(seg))) { - /* .bsplit */ - Seg segLo, segHi; - Res res; - res = SegSplit(&segLo, &segHi, seg, limit, FALSE); - if (ResOK == res) { - amst->bsplits++; - printf("C"); - } else { - /* deliberate fails only */ - AVER(amst->failSegs); - } - } -} - - - -/* AMSTPoolClass -- the pool class definition */ - -DEFINE_POOL_CLASS(AMSTPoolClass, this) -{ - INHERIT_CLASS(this, AMSPoolClass); - this->name = "AMST"; - this->size = sizeof(AMSTStruct); - this->offset = offsetof(AMSTStruct, amsStruct.poolStruct); - this->init = AMSTInit; - this->finish = AMSTFinish; - this->bufferFill = AMSTBufferFill; -} - - -/* mps_amst_ap_stress -- stress an active buffer - * - * Attempt to either split or merge a segment attached to an AP - */ -static void mps_amst_ap_stress(mps_ap_t ap) -{ - Buffer buffer; - Seg seg; - - buffer = BufferOfAP(ap); - AVERT(Buffer, buffer); - seg = BufferSeg(buffer); - AMSTStressBufferedSeg(seg, buffer); -} - - -/* mps_class_amst -- return the pool class descriptor to the client */ - -static mps_class_t mps_class_amst(void) -{ - return (mps_class_t)AMSTPoolClassGet(); -} - - -/* AMS collection parameters */ - -#define exactRootsCOUNT 50 -#define ambigRootsCOUNT 100 -#define sizeScale 4 -/* This is enough for five GCs. */ -#define totalSizeMAX sizeScale * 800 * (size_t)1024 -#define totalSizeSTEP 200 * (size_t)1024 -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) -#define testArenaSIZE ((size_t)16<<20) -#define initTestFREQ 6000 -#define stressTestFREQ 40 - - -/* static variables for the test */ - -static mps_pool_t pool; -static mps_ap_t ap; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; -static size_t totalSize = 0; - - -/* make -- object allocation and init */ - -static mps_addr_t make(void) -{ - size_t length = rnd() % 20, size = (length+2) * sizeof(mps_word_t); - mps_addr_t p; - mps_res_t res; - - do { - MPS_RESERVE_BLOCK(res, p, ap, size); - if (res) - die(res, "MPS_RESERVE_BLOCK"); - res = dylan_init(p, size, exactRoots, exactRootsCOUNT); - if (res) - die(res, "dylan_init"); - } while(!mps_commit(ap, p, size)); - - totalSize += size; - return p; -} - - -/* test -- the actual stress test */ - -static void *test(void *arg, size_t s) -{ - mps_arena_t arena; - mps_fmt_t format; - mps_root_t exactRoot, ambigRoot; - size_t lastStep = 0, i, r; - unsigned long objs; - mps_ap_t busy_ap; - mps_addr_t busy_init; - char *indent = " "; - - arena = (mps_arena_t)arg; - (void)s; /* unused */ - - die(mps_fmt_create_A(&format, arena, dylan_fmt_A()), "fmt_create"); - - die(mps_pool_create(&pool, arena, mps_class_amst(), format), - "pool_create(amst)"); - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2"); - - for(i = 0; i < exactRootsCOUNT; ++i) - exactRoots[i] = objNULL; - for(i = 0; i < ambigRootsCOUNT; ++i) - ambigRoots[i] = rnd_addr(); - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); - - fputs(indent, stdout); - - /* create an ap, and leave it busy */ - die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); - - objs = 0; - while(totalSize < totalSizeMAX) { - if (totalSize > lastStep + totalSizeSTEP) { - lastStep = totalSize; - printf("\nSize %"PRIuLONGEST" bytes, %"PRIuLONGEST" objects.\n", - (ulongest_t)totalSize, (ulongest_t)objs); - printf("%s", indent); - fflush(stdout); - for(i = 0; i < exactRootsCOUNT; ++i) - cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]), - "all roots check"); - } - - r = (size_t)rnd(); - if (r & 1) { - i = (r >> 1) % exactRootsCOUNT; - if (exactRoots[i] != objNULL) - cdie(dylan_check(exactRoots[i]), "dying root check"); - exactRoots[i] = make(); - if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL) - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - } else { - i = (r >> 1) % ambigRootsCOUNT; - ambigRoots[(ambigRootsCOUNT-1) - i] = make(); - /* Create random interior pointers */ - ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); - } - - if (rnd() % stressTestFREQ == 0) - mps_amst_ap_stress(ap); /* stress active buffer */ - - if (rnd() % initTestFREQ == 0) - *(int*)busy_init = -1; /* check that the buffer is still there */ - - ++objs; - if (objs % 256 == 0) { - printf("."); - fflush(stdout); - } - } - - (void)mps_commit(busy_ap, busy_init, 64); - mps_ap_destroy(busy_ap); - mps_ap_destroy(ap); - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); - mps_pool_destroy(pool); - mps_fmt_destroy(format); - - return NULL; -} - - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/shield.c b/mps/code/shield.c deleted file mode 100644 index 35fdcff240f..00000000000 --- a/mps/code/shield.c +++ /dev/null @@ -1,374 +0,0 @@ -/* shield.c: SHIELD IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * See: idea.shield, design.mps.shield. - * - * This implementation of the shield avoids suspending threads for - * as long as possible. When threads are suspended, it maintains a - * cache of covered segments where the desired and actual protection - * do not match. This cache is flushed on leaving the shield. - * - * - * Definitions - * - * .def.synced: a seg is synced if the prot and shield modes are the - * same, and unsynced otherwise. - * .def.depth: the depth of a segment is defined as - * depth == #exposes - #covers + #(in cache), where - * #exposes = the total number of times the seg has been exposed - * #covers = the total number of times the seg has been covered - * #(in cache) = the number of times the seg appears in the cache - * The cache is initially empty and Cover should not be called - * without a matching Expose, so this figure should always be - * non-negative. - * .def.total.depth: The total depth is the sum of the depth over - * all segments - * .def.outside: being outside the shield is being between calls - * to leave and enter, and similarly .def.inside: being inside the - * shield is being between calls to enter and leave. - * .def.suspended: suspended is true iff the mutator is suspended. - * .def.shielded: a segment is shielded if the shield mode is non-zero. - * - * - * Properties - * - * .prop.outside.running: The mutator may not be suspended while - * outside the shield. - * .prop.mutator.access: An attempt by the mutator to access - * shielded memory must cause an ArenaAccess. - * .prop.inside.access: Inside the shield it must be possible to access - * all unshielded segments and all exposed segments. - * - * - * Invariants - * - * These invariants are maintained by the code. - * - * .inv.outside.running: The mutator is not suspended while outside the - * shield. - * .inv.unsynced.suspended: If any segment is not synced, - * the mutator is suspended. - * .inv.unsynced.depth: All unsynced segments have positive depth. - * .inv.outside.depth: The total depth is zero while outside the shield. - * .inv.prot.shield: The prot mode is never more than the shield mode. - * .inv.expose.prot: An exposed seg is not protected. - * - * Hints at proofs of properties from invariants - * - * inv.outside.running directly ensures prop.outside running. - * - * As the depth of a segment cannot be negative - * total depth == 0 => for all segments, depth == 0 - * => all segs are synced (by .inv.unsynced.depth) - * - * If the mutator is running then all segs must be synced - * (.inv.unsynced.suspend). Which means that the hardware protection - * (prot mode) must reflect the software protection (shield mode). - * Hence all shielded memory will be hardware protected while the - * mutator is running. This ensures .prop.mutator.access. - * - * inv.prot.shield and inv.expose.prot ensure prop.inside.access. - */ - -#include "mpm.h" - -SRCID(shield, "$Id$"); - - -void (ShieldSuspend)(Arena arena) -{ - AVERT(Arena, arena); - AVER(arena->insideShield); - - if (!arena->suspended) { - ThreadRingSuspend(ArenaThreadRing(arena)); - arena->suspended = TRUE; - } -} - - -void (ShieldResume)(Arena arena) -{ - AVERT(Arena, arena); - AVER(arena->insideShield); - AVER(arena->suspended); - /* It is only correct to actually resume the mutator here if shDepth is 0 */ -} - - -/* This ensures actual prot mode does not include mode */ -static void protLower(Arena arena, Seg seg, AccessSet mode) -{ - /* */ - AVERT_CRITICAL(Arena, arena); - UNUSED(arena); - AVERT_CRITICAL(Seg, seg); - - if (SegPM(seg) & mode) { - SegSetPM(seg, SegPM(seg) & ~mode); - ProtSet(SegBase(seg), SegLimit(seg), SegPM(seg)); - } -} - - -static void shieldSync(Arena arena, Seg seg) -{ - AVERT(Arena, arena); - AVERT(Seg, seg); - - if (SegPM(seg) != SegSM(seg)) { - ProtSet(SegBase(seg), SegLimit(seg), SegSM(seg)); - SegSetPM(seg, SegSM(seg)); - /* inv.prot.shield */ - } -} - - -static void flush(Arena arena, Size i) -{ - Seg seg; - AVERT(Arena, arena); - AVER(i < arena->shCacheLimit); - - seg = arena->shCache[i]; - if (seg == NULL) return; - AVERT(Seg, seg); - - AVER(arena->shDepth > 0); - AVER(SegDepth(seg) > 0); - --arena->shDepth; - SegSetDepth(seg, SegDepth(seg) - 1); - - if (SegDepth(seg) == 0) - shieldSync(arena, seg); - - arena->shCache[i] = NULL; -} - - -/* If the segment is out of sync, either sync it, or ensure - * depth > 0, and the arena is suspended. - */ -static void cache(Arena arena, Seg seg) -{ - /* */ - AVERT_CRITICAL(Arena, arena); - AVERT_CRITICAL(Seg, seg); - - if (SegSM(seg) == SegPM(seg)) return; - if (SegDepth(seg) > 0) { - ShieldSuspend(arena); - return; - } - if (ShieldCacheSIZE == 0 || !arena->suspended) - shieldSync(arena, seg); - else { - SegSetDepth(seg, SegDepth(seg) + 1); - ++arena->shDepth; - AVER(arena->shDepth > 0); - AVER(SegDepth(seg) > 0); - AVER(arena->shCacheLimit <= ShieldCacheSIZE); - AVER(arena->shCacheI < arena->shCacheLimit); - flush(arena, arena->shCacheI); - arena->shCache[arena->shCacheI] = seg; - ++arena->shCacheI; - if (arena->shCacheI == ShieldCacheSIZE) - arena->shCacheI = 0; - if (arena->shCacheI == arena->shCacheLimit) - ++arena->shCacheLimit; - } -} - - -void (ShieldRaise) (Arena arena, Seg seg, AccessSet mode) -{ - /* .seg.broken: Seg's shield invariants may not be true at */ - /* this point (this function is called to enforce them) so we */ - /* can't check seg. Nor can we check arena as that checks the */ - /* segs in the cache. */ - - AVER((SegSM(seg) & mode) == AccessSetEMPTY); - SegSetSM(seg, SegSM(seg) | mode); /* inv.prot.shield preserved */ - - /* ensure inv.unsynced.suspended & inv.unsynced.depth */ - cache(arena, seg); - AVERT(Arena, arena); - AVERT(Seg, seg); -} - - -void (ShieldLower)(Arena arena, Seg seg, AccessSet mode) -{ - /* Don't check seg or arena, see .seg.broken */ - AVER((SegSM(seg) & mode) == mode); - /* synced(seg) is not changed by the following - * preserving inv.unsynced.suspended - * Also inv.prot.shield preserved - */ - SegSetSM(seg, SegSM(seg) & ~mode); - protLower(arena, seg, mode); - AVERT(Arena, arena); - AVERT(Seg, seg); -} - - -void (ShieldEnter)(Arena arena) -{ - Size i; - - AVERT(Arena, arena); - AVER(!arena->insideShield); - AVER(arena->shDepth == 0); - AVER(!arena->suspended); - AVER(arena->shCacheLimit <= ShieldCacheSIZE); - AVER(arena->shCacheI < arena->shCacheLimit); - for(i = 0; i < arena->shCacheLimit; i++) - AVER(arena->shCache[i] == NULL); - - arena->shCacheI = (Size)0; - arena->shCacheLimit = (Size)1; - arena->insideShield = TRUE; -} - - -/* .shield.flush: Flush empties the shield cache. - * This needs to be called before segments are destroyed as there - * may be references to them in the cache. - */ -void (ShieldFlush)(Arena arena) -{ - Size i; - - for(i = 0; i < arena->shCacheLimit; ++i) { - if (arena->shDepth == 0) - break; - flush(arena, i); - } -} - - -void (ShieldLeave)(Arena arena) -{ - AVERT(Arena, arena); - AVER(arena->insideShield); - - ShieldFlush(arena); - /* Cache is empty so inv.outside.depth holds */ - AVER(arena->shDepth == 0); - - /* Ensuring the mutator is running at this point - * guarantees inv.outside.running */ - if (arena->suspended) { - ThreadRingResume(ArenaThreadRing(arena)); - arena->suspended = FALSE; - } - arena->insideShield = FALSE; -} - - -/* ShieldExpose -- allow the MPS access to a segment while denying the mutator - * - * The MPS currently does not collect concurrently, however the only thing - * that makes it not-concurrent is a critical point in the Shield - * abstraction where the MPS seeks to gain privileged access to memory - * (usually in order to scan it for GC). The critical point is where - * ShieldExpose in shield.c has to call ShieldSuspend to preserve the - * shield invariants. This is the only point in the MPS that prevents - * concurrency, and the rest of the MPS is designed to support it. - * - * The restriction could be removed if either: - * - * * the MPS could use a different set of protections to the mutator - * program - * - * * the mutator program uses a software barrier - * - * The first one is tricky, and the second one just hasn't come up in any - * implementation we've been asked to make yet. Given a VM, it could - * happen, and the MPS would be concurrent. - * - * So, I believe there's nothing fundamentally non-concurrent about the - * MPS design. It's kind of waiting to happen. - * - * (Originally written at .) - */ - -void (ShieldExpose)(Arena arena, Seg seg) -{ - AccessSet mode = AccessREAD | AccessWRITE; - /* */ - AVERT_CRITICAL(Arena, arena); - AVER_CRITICAL(arena->insideShield); - - SegSetDepth(seg, SegDepth(seg) + 1); - ++arena->shDepth; - /* */ - AVER_CRITICAL(arena->shDepth > 0); - AVER_CRITICAL(SegDepth(seg) > 0); - if (SegPM(seg) & mode) - ShieldSuspend(arena); - - /* This ensures inv.expose.prot */ - protLower(arena, seg, mode); -} - - -void (ShieldCover)(Arena arena, Seg seg) -{ - /* */ - AVERT_CRITICAL(Arena, arena); - AVERT_CRITICAL(Seg, seg); - AVER_CRITICAL(SegPM(seg) == AccessSetEMPTY); - - AVER_CRITICAL(arena->shDepth > 0); - AVER_CRITICAL(SegDepth(seg) > 0); - SegSetDepth(seg, SegDepth(seg) - 1); - --arena->shDepth; - - /* ensure inv.unsynced.depth */ - cache(arena, seg); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/span.c b/mps/code/span.c deleted file mode 100644 index 20be353a83c..00000000000 --- a/mps/code/span.c +++ /dev/null @@ -1,67 +0,0 @@ -/* span.c: ANSI STACK PROBE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * PURPOSE - * - * .purpose: The purpose of the ANSI Stack Probe is to provide a - * non-functional implementation of the StackProbe interface. - * StackProbe has a function implementation on platforms where the - * MPS takes some special action to avoid stack overflow. - */ - -#include "mpm.h" - -SRCID(span, "$Id$"); - - -/* StackProbe -- probe above the stack to provoke early stack overflow */ - -void StackProbe(Size depth) -{ - AVER(depth == 0); - NOOP; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/spi3.c b/mps/code/spi3.c deleted file mode 100644 index 6d129c6a845..00000000000 --- a/mps/code/spi3.c +++ /dev/null @@ -1,65 +0,0 @@ -/* spi3.c: STACK PROBE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2001 Global Graphics Software. - * - * This function reads a location that is probeDepth words beyond - * the current stack pointer. On intel platforms the stack grows - * downwards so this means reading from a location with a lesser address. - */ - - -#include "mpm.h" - - -void StackProbe(Size depth) -{ - __asm { - mov eax, depth - neg eax - mov eax, [esp+eax*4] /* do the actual probe */ - } -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/splay.c b/mps/code/splay.c deleted file mode 100644 index 4042f2c0e07..00000000000 --- a/mps/code/splay.c +++ /dev/null @@ -1,1069 +0,0 @@ -/* splay.c: SPLAY TREE IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: Splay trees are used to manage potentially unbounded - * collections of ordered things. - * - * .source: - * - * .note.stack: It's important that the MPS have a bounded stack - * size, and this is a problem for tree algorithms. Basically, - * we have to avoid recursion. - */ - - -#include "splay.h" -#include "mpm.h" - -SRCID(splay, "$Id$"); - - -/* Basic getter and setter methods */ - -#define SplayTreeRoot(t) RVALUE((t)->root) -#define SplayTreeSetRoot(t, r) BEGIN ((t)->root = (r)); END -#define SplayNodeLeftChild(n) RVALUE((n)->left) -#define SplayNodeSetLeftChild(n, child) \ - BEGIN ((n)->left = (child)); END -#define SplayNodeRightChild(n) RVALUE((n)->right) -#define SplayNodeSetRightChild(n, child) \ - BEGIN ((n)->right = (child)); END - - -#define SplayCompare(tree, key, node) \ - (((tree)->compare)((key), (node))) - - -Bool SplayTreeCheck(SplayTree tree) -{ - UNUSED(tree); - CHECKL(tree != NULL); - CHECKL(FUNCHECK(tree->compare)); - CHECKL(tree->updateNode == NULL || FUNCHECK(tree->updateNode)); - return TRUE; -} - - -Bool SplayNodeCheck(SplayNode node) -{ - UNUSED(node); - CHECKL(node != NULL); - return TRUE; -} - - -void SplayTreeInit(SplayTree tree, SplayCompareMethod compare, - SplayUpdateNodeMethod updateNode) -{ - AVER(tree != NULL); - AVER(FUNCHECK(compare)); - AVER(updateNode == NULL || FUNCHECK(updateNode)); - - tree->compare = compare; - tree->updateNode = updateNode; - SplayTreeSetRoot(tree, NULL); - - AVERT(SplayTree, tree); -} - - -void SplayNodeInit(SplayNode node) -{ - AVER(node != NULL); - - /* We don't try to finish the attached nodes. See .note.stack. */ - SplayNodeSetLeftChild(node, NULL); - SplayNodeSetRightChild(node, NULL); - - AVERT(SplayNode, node); -} - - -void SplayNodeFinish(SplayNode node) -{ - AVERT(SplayNode, node); - - /* we don't try to do a recursive finish. See .note.stack. */ - SplayNodeSetLeftChild(node, NULL); - SplayNodeSetRightChild(node, NULL); -} - - -void SplayTreeFinish(SplayTree tree) -{ - AVERT(SplayTree, tree); - SplayTreeSetRoot(tree, NULL); - tree->compare = NULL; -} - - -static void SplayNodeUpdate(SplayTree tree, SplayNode node) -{ - AVERT(SplayTree, tree); - AVERT(SplayNode, node); - AVER(tree->updateNode != NULL); - - (*tree->updateNode)(tree, node, SplayNodeLeftChild(node), - SplayNodeRightChild(node)); - return; -} - - -/* SplayLinkRight -- Move top to left child of top - * - * Link the current top node into the left child of the right tree, - * leaving the top node as the left child of the old top node. - * - * See . - */ - -static void SplayLinkRight(SplayNode *topIO, SplayNode *rightIO) -{ - AVERT(SplayNode, *topIO); - AVERT(SplayNode, *rightIO); - - /* Don't fix client properties yet. */ - - /* .link.right.first: *rightIO is always the first node in the */ - /* right tree, so its left child must be null. */ - AVER(SplayNodeLeftChild(*rightIO) == NULL); - - SplayNodeSetLeftChild(*rightIO, *topIO); - *rightIO = *topIO; - *topIO = SplayNodeLeftChild(*topIO); - - /* The following line is only required for .link.right.first. */ - SplayNodeSetLeftChild(*rightIO, NULL); -} - - -/* SplayLinkLeft -- Move top to right child of top - * - * Link the current top node into the right child of the left tree, - * leaving the top node as the right child of the old top node. - * - * See . - */ - -static void SplayLinkLeft(SplayNode *topIO, SplayNode *leftIO) { - AVERT(SplayNode, *topIO); - AVERT(SplayNode, *leftIO); - - /* Don't fix client properties yet. */ - - /* .link.left.first: *leftIO is always the last node in the */ - /* left tree, so its right child must be null. */ - AVER(SplayNodeRightChild(*leftIO) == NULL); - - SplayNodeSetRightChild(*leftIO, *topIO); - *leftIO = *topIO; - *topIO = SplayNodeRightChild(*topIO); - - /* The following line is only required for .link.left.first. */ - SplayNodeSetRightChild(*leftIO, NULL); -} - - -/* SplayRotateLeft -- Rotate right child edge of node - * - * Rotates node, right child of node, and left child of right - * child of node, leftwards in the order stated. - * - * See . - */ - -static void SplayRotateLeft(SplayNode *nodeIO, SplayTree tree) { - SplayNode nodeRight; - - AVER(nodeIO != NULL); - AVERT(SplayNode, *nodeIO); - AVERT(SplayNode, SplayNodeRightChild(*nodeIO)); - AVERT(SplayTree, tree); - - nodeRight = SplayNodeRightChild(*nodeIO); - SplayNodeSetRightChild(*nodeIO, SplayNodeLeftChild(nodeRight)); - SplayNodeSetLeftChild(nodeRight, *nodeIO); - *nodeIO = nodeRight; - - if (tree->updateNode != NULL) { - SplayNodeUpdate(tree, SplayNodeLeftChild(nodeRight)); - /* Don't need to update new root because we know that we will */ - /* do either a link or an assemble next, and that will sort it */ - /* out. */ - } - - return; -} - - -/* SplayRotateRight -- Rotate left child edge of node - * - * Rotates node, left child of node, and right child of left - * child of node, leftwards in the order stated. - * - * See . - */ - -static void SplayRotateRight(SplayNode *nodeIO, SplayTree tree) { - SplayNode nodeLeft; - - AVER(nodeIO != NULL); - AVERT(SplayNode, *nodeIO); - AVERT(SplayNode, SplayNodeLeftChild(*nodeIO)); - AVERT(SplayTree, tree); - - nodeLeft = SplayNodeLeftChild(*nodeIO); - SplayNodeSetLeftChild(*nodeIO, SplayNodeRightChild(nodeLeft)); - SplayNodeSetRightChild(nodeLeft, *nodeIO); - *nodeIO = nodeLeft; - - if (tree->updateNode != NULL) { - SplayNodeUpdate(tree, SplayNodeRightChild(nodeLeft)); - /* Don't need to update new root because we know that we will */ - /* do either a link or an assemble next, and that will sort it */ - /* out. */ - } - - return; -} - - -/* SplayAssemble -- Assemble left right and top trees into one - * - * We do this by moving the children of the top tree to the last and - * first nodes in the left and right trees, and then moving the tops - * of the left and right trees to the children of the top tree. - * - * When we reach this function, the nodes between the roots of the - * left and right trees and their last and first nodes respectively - * will have out of date client properties. - * - * See . - */ - -static void SplayAssemble(SplayTree tree, SplayNode top, - SplayNode leftTop, SplayNode leftLast, - SplayNode rightTop, SplayNode rightFirst) { - AVERT(SplayTree, tree); - AVERT(SplayNode, top); - AVER(leftTop == NULL || - (SplayNodeCheck(leftTop) && SplayNodeCheck(leftLast))); - AVER(rightTop == NULL || - (SplayNodeCheck(rightTop) && SplayNodeCheck(rightFirst))); - - if (leftTop != NULL) { - SplayNodeSetRightChild(leftLast, SplayNodeLeftChild(top)); - SplayNodeSetLeftChild(top, leftTop); - - if (tree->updateNode != NULL) { - /* Update client property using pointer reversal (Ugh!). */ - SplayNode node, parent, rightChild; - - /* Reverse the pointers between leftTop and leftLast */ - /* leftLast is not reversed. */ - node = leftTop; - parent = NULL; - while(node != leftLast) { - rightChild = SplayNodeRightChild(node); - SplayNodeSetRightChild(node, parent); /* pointer reversal */ - parent = node; - node = rightChild; - } - - /* Now restore the pointers, updating the client property. */ - /* node is leftLast, parent is the last parent (or NULL). */ - SplayNodeUpdate(tree, node); - while(node != leftTop) { - rightChild = node; - node = parent; - parent = SplayNodeRightChild(node); - SplayNodeSetRightChild(node, rightChild); /* un-reverse pointer */ - SplayNodeUpdate(tree, node); - } - } - } - /* otherwise leave top->left alone */ - - if (rightTop != NULL) { - SplayNodeSetLeftChild(rightFirst, SplayNodeRightChild(top)); - SplayNodeSetRightChild(top, rightTop); - - if (tree->updateNode != NULL) { - /* Update client property using pointer reversal (Ugh!). */ - SplayNode node, parent, leftChild; - - /* Reverse the pointers between rightTop and rightFirst */ - /* ightFirst is not reversed. */ - node = rightTop; - parent = NULL; - while(node != rightFirst) { - leftChild = SplayNodeLeftChild(node); - SplayNodeSetLeftChild(node, parent); /* pointer reversal */ - parent = node; - node = leftChild; - } - - /* Now restore the pointers, updating the client property. */ - /* node is rightFirst, parent is the last parent (or NULL). */ - SplayNodeUpdate(tree, node); - while(node != rightTop) { - leftChild = node; - node = parent; - parent = SplayNodeLeftChild(node); - SplayNodeSetLeftChild(node, leftChild); /* un-reverse pointer */ - SplayNodeUpdate(tree, node); - } - } - } - /* otherwise leave top->right alone */ - - if (tree->updateNode != NULL) - SplayNodeUpdate(tree, top); -} - - -/* SplaySplay -- Splay the tree (top-down) around a given key - * - * If the key is not found, splays around an arbitrary neighbour. - * Returns whether key was found. This is the real logic behind - * splay trees. - * - * See . - */ - -static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree, - void *key, SplayCompareMethod compareMethod) { - /* The sides structure avoids a boundary case in SplayLink* */ - SplayNodeStruct sides; /* rightTop and leftTop */ - SplayNode top, leftLast, rightFirst; - Bool found; - Compare compareTop; - - AVERT(SplayTree, tree); - AVER(nodeReturn != NULL); - AVER(FUNCHECK(compareMethod)); - - top = SplayTreeRoot(tree); /* will be copied back at end */ - - if (top == NULL) { - *nodeReturn = NULL; - return FALSE; - } - - /* short-circuit case where node is already top */ - compareTop = (*compareMethod)(key, top); - if (compareTop == CompareEQUAL) { - *nodeReturn = top; - return TRUE; - } - - SplayNodeInit(&sides); /* left and right trees now NULL */ - leftLast = &sides; - rightFirst = &sides; - - while(TRUE) { - /* compareTop is already initialised above. */ - switch(compareTop) { - - case CompareLESS: { - SplayNode topLeft = SplayNodeLeftChild(top); - if (topLeft == NULL) { - found = FALSE; - goto assemble; - } else { - Compare compareTopLeft = (*compareMethod)(key, topLeft); - - switch(compareTopLeft) { - - case CompareEQUAL: { /* zig */ - SplayLinkRight(&top, &rightFirst); - found = TRUE; - goto assemble; - } /* break; */ - - case CompareLESS: { /* zig-zig */ - if (SplayNodeLeftChild(topLeft) == NULL) - goto terminalZig; - SplayRotateRight(&top, tree); - SplayLinkRight(&top, &rightFirst); - } break; - - case CompareGREATER: { /* zig-zag */ - if (SplayNodeRightChild(topLeft) == NULL) - goto terminalZig; - SplayLinkRight(&top, &rightFirst); - SplayLinkLeft(&top, &leftLast); - } break; - - default: { - NOTREACHED; - } break; - } - } - } break; - - case CompareGREATER: { - SplayNode topRight = SplayNodeRightChild(top); - if (topRight == NULL) { - found = FALSE; - goto assemble; - } else { - Compare compareTopRight = (*compareMethod)(key, topRight); - - switch(compareTopRight) { - - case CompareEQUAL: { /* zag */ - SplayLinkLeft(&top, &leftLast); - found = TRUE; - goto assemble; - } /* break; */ - - case CompareGREATER: { /* zag-zag */ - if (SplayNodeRightChild(topRight) == NULL) - goto terminalZag; - SplayRotateLeft(&top, tree); - SplayLinkLeft(&top, &leftLast); - } break; - - case CompareLESS: { /* zag-zig */ - if (SplayNodeLeftChild(topRight) == NULL) - goto terminalZag; - SplayLinkLeft(&top, &leftLast); - SplayLinkRight(&top, &rightFirst); - } break; - - default: { - NOTREACHED; - } break; - } - } - } break; - - case CompareEQUAL: { - found = TRUE; - goto assemble; - } /* break; */ - - default: { - NOTREACHED; - } break; - } - compareTop = (*compareMethod)(key, top); - } /* end while(TRUE) */ - -terminalZig: - SplayLinkRight(&top, &rightFirst); - found = FALSE; - goto assemble; - -terminalZag: - SplayLinkLeft(&top, &leftLast); - found = FALSE; - goto assemble; - -assemble: - SplayAssemble(tree, top, - SplayNodeRightChild(&sides), leftLast, - SplayNodeLeftChild(&sides), rightFirst); - - SplayTreeSetRoot(tree, top); - *nodeReturn = top; - - return found; -} - - -/* SplayTreeInsert -- Insert a node into a splay tree - * - * See and - * . - */ - -Res SplayTreeInsert(SplayTree tree, SplayNode node, void *key) { - SplayNode neighbour; - - AVERT(SplayTree, tree); - AVERT(SplayNode, node); - AVER(SplayNodeLeftChild(node) == NULL); - AVER(SplayNodeRightChild(node) == NULL); - - if (SplayTreeRoot(tree) == NULL) { - SplayTreeSetRoot(tree, node); - } else if (SplaySplay(&neighbour, tree, key, tree->compare)) { - return ResFAIL; - } else { - AVER(SplayTreeRoot(tree) == neighbour); - switch(SplayCompare(tree, key, neighbour)) { - - case CompareGREATER: { /* left neighbour */ - SplayTreeSetRoot(tree, node); - SplayNodeSetRightChild(node, SplayNodeRightChild(neighbour)); - SplayNodeSetLeftChild(node, neighbour); - SplayNodeSetRightChild(neighbour, NULL); - } break; - - case CompareLESS: { /* right neighbour */ - SplayTreeSetRoot(tree, node); - SplayNodeSetLeftChild(node, SplayNodeLeftChild(neighbour)); - SplayNodeSetRightChild(node, neighbour); - SplayNodeSetLeftChild(neighbour, NULL); - } break; - - case CompareEQUAL: - default: { - NOTREACHED; - } break; - } - - if (tree->updateNode != NULL) { - SplayNodeUpdate(tree, neighbour); - SplayNodeUpdate(tree, node); - } - } - - return ResOK; -} - - -/* SplayTreeDelete -- Delete a node from a splay tree - * - * See and - * . - */ - -Res SplayTreeDelete(SplayTree tree, SplayNode node, void *key) { - SplayNode rightHalf, del, leftLast; - Bool found; - - AVERT(SplayTree, tree); - AVERT(SplayNode, node); - - found = SplaySplay(&del, tree, key, tree->compare); - AVER(!found || del == node); - - if (!found) { - return ResFAIL; - } else if (SplayNodeLeftChild(node) == NULL) { - SplayTreeSetRoot(tree, SplayNodeRightChild(node)); - } else if (SplayNodeRightChild(node) == NULL) { - SplayTreeSetRoot(tree, SplayNodeLeftChild(node)); - } else { - rightHalf = SplayNodeRightChild(node); - SplayTreeSetRoot(tree, SplayNodeLeftChild(node)); - if (SplaySplay(&leftLast, tree, key, tree->compare)) { - return ResFAIL; - } else { - AVER(SplayNodeRightChild(leftLast) == NULL); - SplayNodeSetRightChild(leftLast, rightHalf); - if (tree->updateNode != NULL) { - SplayNodeUpdate(tree, leftLast); - } - } - } - - SplayNodeFinish(node); - - return ResOK; -} - - -/* SplayTreeSearch -- Search for a node in a splay tree matching a key - * - * See and - * . - */ - -Res SplayTreeSearch(SplayNode *nodeReturn, SplayTree tree, void *key) { - SplayNode node; - - AVERT(SplayTree, tree); - AVER(nodeReturn != NULL); - - if (SplaySplay(&node, tree, key, tree->compare)) { - *nodeReturn = node; - } else { - return ResFAIL; - } - - return ResOK; -} - - -/* SplayTreePredecessor -- Splays a tree at the root's predecessor - * - * Must not be called on en empty tree. Predecessor need not exist, - * in which case NULL is returned, and the tree is unchanged. - */ - -static SplayNode SplayTreePredecessor(SplayTree tree, void *key) { - SplayNode oldRoot, newRoot; - - AVERT(SplayTree, tree); - - oldRoot = SplayTreeRoot(tree); - AVERT(SplayNode, oldRoot); - - if (SplayNodeLeftChild(oldRoot) == NULL) { - newRoot = NULL; /* No predecessor */ - } else { - /* temporarily chop off the right half-tree, inclusive of root */ - SplayTreeSetRoot(tree, SplayNodeLeftChild(oldRoot)); - SplayNodeSetLeftChild(oldRoot, NULL); - if (SplaySplay(&newRoot, tree, key, tree->compare)) { - NOTREACHED; /* Another matching node found */ - } else { - AVER(SplayNodeRightChild(newRoot) == NULL); - SplayNodeSetRightChild(newRoot, oldRoot); - } - - if (tree->updateNode != NULL) { - SplayNodeUpdate(tree, oldRoot); - SplayNodeUpdate(tree, newRoot); - } - } - - return newRoot; -} - - -/* SplayTreeSuccessor -- Splays a tree at the root's successor - * - * Must not be called on en empty tree. Successor need not exist, - * in which case NULL is returned, and the tree is unchanged. - */ - -static SplayNode SplayTreeSuccessor(SplayTree tree, void *key) { - SplayNode oldRoot, newRoot; - - AVERT(SplayTree, tree); - - oldRoot = SplayTreeRoot(tree); - AVERT(SplayNode, oldRoot); - - if (SplayNodeRightChild(oldRoot) == NULL) { - newRoot = NULL; /* No successor */ - } else { - /* temporarily chop off the left half-tree, inclusive of root */ - SplayTreeSetRoot(tree, SplayNodeRightChild(oldRoot)); - SplayNodeSetRightChild(oldRoot, NULL); - if (SplaySplay(&newRoot, tree, key, tree->compare)) { - NOTREACHED; /* Another matching node found */ - } else { - AVER(SplayNodeLeftChild(newRoot) == NULL); - SplayNodeSetLeftChild(newRoot, oldRoot); - } - - if (tree->updateNode != NULL) { - SplayNodeUpdate(tree, oldRoot); - SplayNodeUpdate(tree, newRoot); - } - } - - return newRoot; -} - - -/* SplayTreeNeighbours - * - * Search for the two nodes in a splay tree neighbouring a key. - * - * See and - * . - */ - - -Res SplayTreeNeighbours(SplayNode *leftReturn, SplayNode *rightReturn, - SplayTree tree, void *key) { - SplayNode neighbour; - - AVERT(SplayTree, tree); - AVER(leftReturn != NULL); - AVER(rightReturn != NULL); - - if (SplaySplay(&neighbour, tree, key, tree->compare)) { - return ResFAIL; - } else if (neighbour == NULL) { - *leftReturn = *rightReturn = NULL; - } else { - switch(SplayCompare(tree, key, neighbour)) { - - case CompareLESS: { - *rightReturn = neighbour; - *leftReturn = SplayTreePredecessor(tree, key); - } break; - - case CompareGREATER: { - *leftReturn = neighbour; - *rightReturn = SplayTreeSuccessor(tree, key); - } break; - - case CompareEQUAL: - default: { - NOTREACHED; - } break; - } - } - return ResOK; -} - - -/* SplayTreeFirst, SplayTreeNext -- Iterators - * - * SplayTreeFirst receives a key that must precede all - * nodes in the tree. It returns NULL if the tree is empty. - * Otherwise, it splays the tree to the first node, and returns the - * new root. See . - * - * SplayTreeNext takes a tree and splays it to the successor of the - * old root, and returns the new root. Returns NULL is there are - * no successors. It takes a key for the old root. See - * . - */ - -SplayNode SplayTreeFirst(SplayTree tree, void *zeroKey) { - SplayNode node; - AVERT(SplayTree, tree); - - if (SplayTreeRoot(tree) == NULL) { - node = NULL; - } else if (SplaySplay(&node, tree, zeroKey, tree->compare)) { - NOTREACHED; - } else { - AVER(SplayNodeLeftChild(node) == NULL); - } - - return node; -} - -SplayNode SplayTreeNext(SplayTree tree, SplayNode oldNode, void *oldKey) { - Bool b; - SplayNode node; - - AVERT(SplayTree, tree); - AVERT(SplayNode, oldNode); - - /* Make old node the root. Probably already is. */ - b = SplaySplay(&node, tree, oldKey, tree->compare); - AVER(b); - AVER(node == oldNode); - - return SplayTreeSuccessor(tree, oldKey); -} - - -/* SplayNodeDescribe -- Describe a node in the splay tree - * - * Note that this breaks the restriction of .note.stack. - * This is alright as the function is debug only. - */ - -static Res SplayNodeDescribe(SplayNode node, mps_lib_FILE *stream, - SplayNodeDescribeMethod nodeDescribe) { - Res res; - -#if defined(AVER_AND_CHECK) - if (!SplayNodeCheck(node)) return ResFAIL; - /* stream and nodeDescribe checked by SplayTreeDescribe */ -#endif - - res = WriteF(stream, "( ", NULL); - if (res != ResOK) return res; - - if (SplayNodeLeftChild(node) != NULL) { - res = SplayNodeDescribe(SplayNodeLeftChild(node), stream, nodeDescribe); - if (res != ResOK) return res; - - res = WriteF(stream, " / ", NULL); - if (res != ResOK) return res; - } - - res = (*nodeDescribe)(node, stream); - if (res != ResOK) return res; - - if (SplayNodeRightChild(node) != NULL) { - res = WriteF(stream, " \\ ", NULL); - if (res != ResOK) return res; - - res = SplayNodeDescribe(SplayNodeRightChild(node), stream, nodeDescribe); - if (res != ResOK) return res; - } - - res = WriteF(stream, " )", NULL); - if (res != ResOK) return res; - - return ResOK; -} - - -typedef struct { - SplayTestNodeMethod testNode; - SplayTestTreeMethod testTree; - void *p; - Size s; - SplayTree tree; -} SplayFindClosureStruct, *SplayFindClosure; - -static Compare SplayFindFirstCompare(void *key, SplayNode node) -{ - SplayFindClosure closure; - void *closureP; - Size closureS; - SplayTestNodeMethod testNode; - SplayTestTreeMethod testTree; - SplayTree tree; - - AVERT(SplayNode, node); - AVER(key != NULL); - - closure = (SplayFindClosure)key; - closureP = closure->p; - closureS = closure->s; - testNode = closure->testNode; - testTree = closure->testTree; - tree = closure->tree; - - if (SplayNodeLeftChild(node) != NULL && - (*testTree)(tree, SplayNodeLeftChild(node), closureP, closureS)) { - return CompareLESS; - } else if ((*testNode)(tree, node, closureP, closureS)) { - return CompareEQUAL; - } else { - AVER(SplayNodeRightChild(node) != NULL); - AVER((*testTree)(tree, SplayNodeRightChild(node), closureP, closureS)); - return CompareGREATER; - } -} - -static Compare SplayFindLastCompare(void *key, SplayNode node) -{ - SplayFindClosure closure; - void *closureP; - Size closureS; - SplayTestNodeMethod testNode; - SplayTestTreeMethod testTree; - SplayTree tree; - - AVERT(SplayNode, node); - AVER(key != NULL); - - closure = (SplayFindClosure)key; - closureP = closure->p; - closureS = closure->s; - testNode = closure->testNode; - testTree = closure->testTree; - tree = closure->tree; - - if (SplayNodeRightChild(node) != NULL && - (*testTree)(tree, SplayNodeRightChild(node), closureP, closureS)) { - return CompareGREATER; - } else if ((*testNode)(tree, node, closureP, closureS)) { - return CompareEQUAL; - } else { - AVER(SplayNodeLeftChild(node) != NULL); - AVER((*testTree)(tree, SplayNodeLeftChild(node), closureP, closureS)); - return CompareLESS; - } -} - - -/* SplayFindFirst -- Find first node that satisfies client property - * - * This function finds the first node (in address order) in the given - * tree that satisfies some property defined by the client. The - * property is such that the client can detect, given a sub-tree, - * whether that sub-tree contains any nodes satisfying the property. - * - * The given callbacks testNode and testTree detect this property in - * a single node or a sub-tree rooted at a node, and both receive the - * arbitrary closures closureP and closureS. - */ - -Bool SplayFindFirst(SplayNode *nodeReturn, SplayTree tree, - SplayTestNodeMethod testNode, - SplayTestTreeMethod testTree, - void *closureP, Size closureS) -{ - SplayNode node; - SplayFindClosureStruct closureStruct; - - AVER(nodeReturn != NULL); - AVERT(SplayTree, tree); - AVER(FUNCHECK(testNode)); - AVER(FUNCHECK(testTree)); - - node = SplayTreeRoot(tree); - - if (node == NULL || !(*testTree)(tree, node, closureP, closureS)) - return FALSE; /* no suitable nodes in tree */ - - closureStruct.p = closureP; - closureStruct.s = closureS; - closureStruct.testNode = testNode; - closureStruct.testTree = testTree; - closureStruct.tree = tree; - - if (SplaySplay(&node, tree, (void *)&closureStruct, - &SplayFindFirstCompare)) { - *nodeReturn = node; - return TRUE; - } else { - return FALSE; - } -} - - -/* SplayFindLast -- As SplayFindFirst but in reverse address order */ - -Bool SplayFindLast(SplayNode *nodeReturn, SplayTree tree, - SplayTestNodeMethod testNode, - SplayTestTreeMethod testTree, - void *closureP, Size closureS) -{ - SplayNode node; - SplayFindClosureStruct closureStruct; - - AVER(nodeReturn != NULL); - AVERT(SplayTree, tree); - AVER(FUNCHECK(testNode)); - AVER(FUNCHECK(testTree)); - - node = SplayTreeRoot(tree); - - if (node == NULL || !(*testTree)(tree, node, closureP, closureS)) - return FALSE; /* no suitable nodes in tree */ - - closureStruct.p = closureP; - closureStruct.s = closureS; - closureStruct.testNode = testNode; - closureStruct.testTree = testTree; - closureStruct.tree = tree; - - if (SplaySplay(&node, tree, (void *)&closureStruct, - &SplayFindLastCompare)) { - *nodeReturn = node; - return TRUE; - } else { - return FALSE; - } -} - - -/* SplayRoot -- return the root node of the tree */ - -Bool SplayRoot(SplayNode *nodeReturn, SplayTree tree) -{ - SplayNode node; - - AVER(nodeReturn != NULL); - AVERT(SplayTree, tree); - - node = SplayTreeRoot(tree); - if (node == NULL) - return FALSE; - else { - *nodeReturn = node; - return TRUE; - } -} - - -/* SplayNodeRefresh -- Updates the client property that has changed at a node - * - * This function undertakes to call the client updateNode callback for each - * node affected by the change in properties at the given node (which has - * the given key) in an appropriate order. - * - * The function fullfils its job by first splaying at the given node, and - * updating the single node. This may change. - */ - -void SplayNodeRefresh(SplayTree tree, SplayNode node, void *key) -{ - Bool b; - SplayNode node2; - - AVERT(SplayTree, tree); - AVERT(SplayNode, node); - - b = SplaySplay(&node2, tree, key, tree->compare); - AVER(b); - AVER(node == node2); - - (*tree->updateNode)(tree, node, SplayNodeLeftChild(node), - SplayNodeRightChild(node)); -} - - -/* SplayTreeDescribe -- Describe a splay tree - * - * See . - */ - -Res SplayTreeDescribe(SplayTree tree, mps_lib_FILE *stream, - SplayNodeDescribeMethod nodeDescribe) { - Res res; - -#if defined(AVER_AND_CHECK) - if (!SplayTreeCheck(tree)) return ResFAIL; - if (stream == NULL) return ResFAIL; - if (!FUNCHECK(nodeDescribe)) return ResFAIL; -#endif - - res = WriteF(stream, - "Splay $P {\n", (WriteFP)tree, - " compare $F\n", (WriteFF)tree->compare, - NULL); - if (res != ResOK) return res; - - if (SplayTreeRoot(tree) != NULL) { - res = SplayNodeDescribe(SplayTreeRoot(tree), stream, nodeDescribe); - if (res != ResOK) return res; - } - - res = WriteF(stream, "\n}\n", NULL); - return res; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/splay.h b/mps/code/splay.h deleted file mode 100644 index 8fa31af7fd3..00000000000 --- a/mps/code/splay.h +++ /dev/null @@ -1,126 +0,0 @@ -/* splay.h: SPLAY TREE HEADER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .source: - */ - -#ifndef splay_h -#define splay_h - -#include "mpmtypes.h" /* for Res, etc. */ - - -typedef struct SplayTreeStruct *SplayTree; -typedef struct SplayNodeStruct *SplayNode; -typedef unsigned Compare; -typedef Compare (*SplayCompareMethod)(void *key, SplayNode node); -typedef Bool (*SplayTestNodeMethod)(SplayTree tree, SplayNode node, - void *closureP, Size closureS); -typedef Bool (*SplayTestTreeMethod)(SplayTree tree, SplayNode node, - void *closureP, Size closureS); -typedef void (*SplayUpdateNodeMethod)(SplayTree tree, SplayNode node, - SplayNode leftChild, - SplayNode rightChild); -typedef Res (*SplayNodeDescribeMethod)(SplayNode node, mps_lib_FILE *stream); -enum { - CompareLESS = 1, - CompareEQUAL, - CompareGREATER -}; - - -typedef struct SplayTreeStruct { - SplayCompareMethod compare; - SplayUpdateNodeMethod updateNode; - SplayNode root; -} SplayTreeStruct; - -typedef struct SplayNodeStruct { - SplayNode left; - SplayNode right; -} SplayNodeStruct; - - -extern Bool SplayTreeCheck(SplayTree tree); -extern Bool SplayNodeCheck(SplayNode node); -extern void SplayTreeInit(SplayTree tree, SplayCompareMethod compare, - SplayUpdateNodeMethod updateNode); -extern void SplayNodeInit(SplayNode node); -extern void SplayNodeFinish(SplayNode node); -extern void SplayTreeFinish(SplayTree tree); - -extern Res SplayTreeInsert(SplayTree tree, SplayNode node, void *key); -extern Res SplayTreeDelete(SplayTree tree, SplayNode node, void *key); - -extern Res SplayTreeSearch(SplayNode *nodeReturn, - SplayTree tree, void *key ); -extern Res SplayTreeNeighbours(SplayNode *leftReturn, - SplayNode *rightReturn, - SplayTree tree, void *key); - -extern SplayNode SplayTreeFirst(SplayTree tree, void *zeroKey); -extern SplayNode SplayTreeNext(SplayTree tree, SplayNode oldNode, - void *oldKey); - -extern Bool SplayFindFirst(SplayNode *nodeReturn, SplayTree tree, - SplayTestNodeMethod testNode, - SplayTestTreeMethod testTree, - void *closureP, Size closureS); -extern Bool SplayFindLast(SplayNode *nodeReturn, SplayTree tree, - SplayTestNodeMethod testNode, - SplayTestTreeMethod testTree, - void *closureP, Size closureS); - -extern void SplayNodeRefresh(SplayTree tree, SplayNode node, void *key); - -extern Res SplayTreeDescribe(SplayTree tree, mps_lib_FILE *stream, - SplayNodeDescribeMethod nodeDescribe); - -extern Bool SplayRoot(SplayNode *nodeReturn, SplayTree tree); - - -#endif /* splay_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ss.c b/mps/code/ss.c deleted file mode 100644 index 084682b2a23..00000000000 --- a/mps/code/ss.c +++ /dev/null @@ -1,106 +0,0 @@ -/* ss.c: STACK SCANNING - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This is part of the code that scans the stack and fixes the registers - * that may contain roots. See - * - * Each platform ABI has a set of callee-save registers that may still - * contain roots. The StackScan function is defined for each ABI in source - * files like ss*.c and ss*.asm. That function saves the callee save - * registers in its frame, then calls StackScanInner to do the scanning. - */ - -#include "mpm.h" - -SRCID(ss, "$Id$"); - - -/* StackScanInner -- carry out stack scanning - * - * This function should be called by StackScan once it has saved the - * callee-save registers for the platform ABI in order to do the actual - * scanning. - */ - -Res StackScanInner(ScanState ss, - Addr *stackBot, - Addr *stackTop, - Count nSavedRegs) -{ - Arena arena; - Res res; - - AVERT(ScanState, ss); - AVER(stackTop < stackBot); - AVER(AddrIsAligned((Addr)stackTop, sizeof(Addr))); /* .assume.align */ - AVER(0 < nSavedRegs && nSavedRegs < 128); /* sanity check */ - - arena = ss->arena; - - /* If a stack pointer was stored when we entered the arena (through the - MPS interface in mpsi*.c) then we scan just the saved registers and - the stack starting there, in order to avoid false ambiguous references - in the MPS stack. This is particularly important for transforms - (trans.c). Otherwise, scan the whole stack. */ - - if (arena->stackAtArenaEnter != NULL) { - AVER(stackTop < arena->stackAtArenaEnter); - AVER(arena->stackAtArenaEnter < stackBot); - res = TraceScanAreaTagged(ss, stackTop, stackTop + nSavedRegs); - if (res != ResOK) - return res; - res = TraceScanAreaTagged(ss, arena->stackAtArenaEnter, stackBot); - if (res != ResOK) - return res; - } else { - res = TraceScanAreaTagged(ss, stackTop, stackBot); - if (res != ResOK) - return res; - } - - return ResOK; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ss.h b/mps/code/ss.h deleted file mode 100644 index 831ad98aea8..00000000000 --- a/mps/code/ss.h +++ /dev/null @@ -1,85 +0,0 @@ -/* ss.h: STACK SCANNING - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * Provides a function for scanning the stack and registers - */ - -#ifndef ss_h -#define ss_h - -#include "mpm.h" - - -/* StackScan -- scan the current thread's stack - * - * StackScan scans the stack of the current thread, Between stackBot and the - * current top of stack. It also fixes any roots which may be in callee-save - * registers. - * - * See the specific implementation for the exact registers which are scanned. - * - * If a stack pointer has been stashed at arena entry (through the MPS - * interface in mpsi*.c) then only the registers and the stack between - * stackAtArenaEnter and stackBot is scanned, to avoid scanning false - * ambiguous references on the MPS's own stack. This is particularly - * important for transforms (trans.c). - * - * The word pointed to by stackBot is fixed if the stack is by convention - * empty, and not fixed if it is full. Where empty means sp points to first - * free word beyond the top of stack. Full means sp points to the top of - * stack itself. - */ - -extern Res StackScan(ScanState ss, Addr *stackBot); - - -extern Res StackScanInner(ScanState ss, - Addr *stackBot, - Addr *stackTop, - Count nSavedRegs); - -#endif /* ss_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ssan.c b/mps/code/ssan.c deleted file mode 100644 index 6f632dd1d24..00000000000 --- a/mps/code/ssan.c +++ /dev/null @@ -1,64 +0,0 @@ -/* ssan.c: ANSI STACK SCANNER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This module provides zero functionality. It exists to feed the - * linker (prevent linker errors). - */ - -#include "mpmtypes.h" -#include "misc.h" -#include "ss.h" - - -SRCID(ssan, "$Id$"); - - -Res StackScan(ScanState ss, Addr *stackBot) -{ - UNUSED(ss); UNUSED(stackBot); - return ResUNIMPL; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ssixi3.c b/mps/code/ssixi3.c deleted file mode 100644 index 8cc1f8cbd45..00000000000 --- a/mps/code/ssixi3.c +++ /dev/null @@ -1,108 +0,0 @@ -/* ssixi3.c: UNIX/INTEL STACK SCANNING - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This scans the stack and fixes the registers which may contain - * roots. See - * - * This code was originally developed and tested on Linux, and then - * copied to the FreeBSD and Darwin (OS X) operating systems where it - * also seems to work. Note that on FreeBSD and Darwin it has not - * been indepently verified with respect to any ABI documentation. - * - * This code is common to more than one Unix implementation on - * Intel hardware (but is not portable Unix code). - * - * The registers edi, esi, ebx are the registers defined to be preserved - * across function calls and therefore may contain roots. - * These are pushed on the stack for scanning. - * - * SOURCES - * - * .source.callees.saves: Set of callee-saved registers taken from - * CALL_USED_REGISTERS in /config/i386/i386.h. - * ebp added to the list because gcc now doesn't always use it as - * a frame pointer so it could contain a root. - * - * ASSUMPTIONS - * - * .assume.align: The stack pointer is assumed to be aligned on a word - * boundary. - * - * .assume.asm.stack: The compiler must not do wacky things with the - * stack pointer around a call since we need to ensure that the - * callee-save regs are visible during TraceScanArea. - * - * .assume.asm.order: The volatile modifier should prevent movement - * of code, which might break .assume.asm.stack. - * - */ - - -#include "mpm.h" - -SRCID(ssixi3, "$Id$"); - - -/* .assume.asm.order */ -#define ASMV(x) __asm__ volatile (x) - - -Res StackScan(ScanState ss, Addr *stackBot) -{ - Addr calleeSaveRegs[4]; - - /* .assume.asm.stack */ - /* Store the callee save registers on the stack so they get scanned - * as they may contain roots. - */ - ASMV("mov %%ebx, %0" : "=m" (calleeSaveRegs[0])); - ASMV("mov %%esi, %0" : "=m" (calleeSaveRegs[1])); - ASMV("mov %%edi, %0" : "=m" (calleeSaveRegs[2])); - ASMV("mov %%ebp, %0" : "=m" (calleeSaveRegs[3])); - - return StackScanInner(ss, stackBot, calleeSaveRegs, NELEMS(calleeSaveRegs)); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ssixi6.c b/mps/code/ssixi6.c deleted file mode 100644 index 70954edb5da..00000000000 --- a/mps/code/ssixi6.c +++ /dev/null @@ -1,108 +0,0 @@ -/* ssixi6.c: UNIX/x64 STACK SCANNING - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This scans the stack and fixes the registers which may contain - * roots. See - * - * This code was branched from ssixi3.c (32-bit Intel) initially for the - * port to W3I6LL (Mac OS X on x86_64 with Clang). - * - * This code is common to more than one Unix implementation on - * Intel hardware (but is not portable Unix code). According to Wikipedia, - * all the non-Windows platforms use the System V AMD64 ABI. See - * .sources.callees.saves. - * - * SOURCES - * - * .sources.callees.saves: - * "Registers %rbp, %rbx and %r12 through %r15 "belong" to the calling - * function and the called function is required to preserve their values. - * In other words, a called function must preserve these registers’ values - * for its caller." -- System V AMD64 ABI - * - * - * ASSUMPTIONS - * - * .assume.align: The stack pointer is assumed to be aligned on a word - * boundary. - * - * .assume.asm.stack: The compiler must not do wacky things with the - * stack pointer around a call since we need to ensure that the - * callee-save regs are visible during TraceScanArea. - * - * .assume.asm.order: The volatile modifier should prevent movement - * of code, which might break .assume.asm.stack. - * - */ - - -#include "mpm.h" - -SRCID(ssixi6, "$Id$"); - - -/* .assume.asm.order */ -#define ASMV(x) __asm__ volatile (x) - - -Res StackScan(ScanState ss, Addr *stackBot) -{ - Addr calleeSaveRegs[6]; - - /* .assume.asm.stack */ - /* Store the callee save registers on the stack so they get scanned - * as they may contain roots. - */ - ASMV("mov %%rbp, %0" : "=m" (calleeSaveRegs[0])); - ASMV("mov %%rbx, %0" : "=m" (calleeSaveRegs[1])); - ASMV("mov %%r12, %0" : "=m" (calleeSaveRegs[2])); - ASMV("mov %%r13, %0" : "=m" (calleeSaveRegs[3])); - ASMV("mov %%r14, %0" : "=m" (calleeSaveRegs[4])); - ASMV("mov %%r15, %0" : "=m" (calleeSaveRegs[5])); - - return StackScanInner(ss, stackBot, calleeSaveRegs, NELEMS(calleeSaveRegs)); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ssw3i3mv.c b/mps/code/ssw3i3mv.c deleted file mode 100644 index ac0b09fd670..00000000000 --- a/mps/code/ssw3i3mv.c +++ /dev/null @@ -1,85 +0,0 @@ -/* ssw3i3mv.c: STACK SCANNING FOR WIN32 WITH MICROSOFT C - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This scans the stack and fixes the registers which may contain roots. - * See . - * - * REFERENCES - * - * "Argument Passing and Naming Conventions"; MSDN; Microsoft Corporation; - * . - * - * "Calling conventions for different C++ compilers and operating systems"; - * Agner Fog; Copenhagen University College of Engineering; 2012-02-29; - * . - */ - -#include "mpm.h" -#include - -SRCID(ssw3i3mv, "$Id$"); - - -Res StackScan(ScanState ss, Addr *stackBot) -{ - jmp_buf jb; - - /* We rely on the fact that Microsoft C's setjmp stores the callee-save - registers in the jmp_buf. */ - (void)setjmp(jb); - - /* These checks will just serve to warn us at compile-time if the - setjmp.h header changes to indicate that the registers we want aren't - saved any more. */ - AVER(sizeof(((_JUMP_BUFFER *)jb)->Edi) == sizeof(Addr)); - AVER(sizeof(((_JUMP_BUFFER *)jb)->Esi) == sizeof(Addr)); - AVER(sizeof(((_JUMP_BUFFER *)jb)->Ebx) == sizeof(Addr)); - - AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4); - AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8); - - return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Ebx, 3); -} - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/ssw3i6mv.c b/mps/code/ssw3i6mv.c deleted file mode 100644 index 807577a89a2..00000000000 --- a/mps/code/ssw3i6mv.c +++ /dev/null @@ -1,104 +0,0 @@ -/* ssw3i6mv.c: STACK SCANNING FOR WIN32 WITH MICROSOFT C - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This scans the stack and fixes the registers which may contain roots. - * See . It's unlikely that the callee-save - * registers contain mutator roots by the time this function is called, but - * we can't be certain, so we must scan them anyway. - * - * REFERENCES - * - * "Overview of x64 Calling Conventions"; MSDN; Microsoft Corporation; - * . - * - * "Caller/Callee Saved Registers"; MSDN; Microsoft Corporation; - * . - * - * "Register Usage"; MSDN; Microsoft Corporation; - * . - * - * "Calling conventions for different C++ compilers and operating systems"; - * Agner Fog; Copenhagen University College of Engineering; 2012-02-29; - * . - */ - -#include "mpm.h" -#include - -SRCID(ssw3i6mv, "$Id$"); - - -Res StackScan(ScanState ss, Addr *stackBot) -{ - jmp_buf jb; - - /* We rely on the fact that Microsoft C's setjmp stores the callee-save - registers in the jmp_buf. */ - (void)setjmp(jb); - - /* These checks will just serve to warn us at compile-time if the - setjmp.h header changes to indicate that the registers we want aren't - saved any more. */ - AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Addr)); - AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Addr)); - AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Addr)); - AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Addr)); - AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Addr)); - AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Addr)); - AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Addr)); - - /* The layout of the jmp_buf forces us to harmlessly scan Rsp as well. */ - AVER(offsetof(_JUMP_BUFFER, Rsp) == offsetof(_JUMP_BUFFER, Rbx) + 8); - AVER(offsetof(_JUMP_BUFFER, Rbp) == offsetof(_JUMP_BUFFER, Rbx) + 16); - AVER(offsetof(_JUMP_BUFFER, Rsi) == offsetof(_JUMP_BUFFER, Rbx) + 24); - AVER(offsetof(_JUMP_BUFFER, Rdi) == offsetof(_JUMP_BUFFER, Rbx) + 32); - AVER(offsetof(_JUMP_BUFFER, R12) == offsetof(_JUMP_BUFFER, Rbx) + 40); - AVER(offsetof(_JUMP_BUFFER, R13) == offsetof(_JUMP_BUFFER, Rbx) + 48); - AVER(offsetof(_JUMP_BUFFER, R14) == offsetof(_JUMP_BUFFER, Rbx) + 56); - AVER(offsetof(_JUMP_BUFFER, R15) == offsetof(_JUMP_BUFFER, Rbx) + 64); - - return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Rbx, 9); -} - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/steptest.c b/mps/code/steptest.c deleted file mode 100644 index b4f957af79a..00000000000 --- a/mps/code/steptest.c +++ /dev/null @@ -1,555 +0,0 @@ -/* steptest.c: TEST FOR ARENA STEPPING - * - * $Id$ - * Copyright (C) 1998 Ravenbrook Limited. See end of file for license. - * - * Loosely based on . - */ - -#include "fmtdy.h" -#include "fmtdytst.h" -#include "testlib.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include "mps.h" -#include -#include - -#define testArenaSIZE ((size_t)((size_t)64 << 20)) -#define avLEN 3 -#define exactRootsCOUNT 200 -#define ambigRootsCOUNT 50 -#define objCOUNT 2000000 -#define clockSetFREQ 10000 -#define multiStepFREQ 500000 -#define multiStepMULT 100 - -#define genCOUNT 3 -#define gen1SIZE 750 /* kB */ -#define gen2SIZE 2000 /* kB */ -#define gen3SIZE 5000 /* kB */ -#define gen1MORTALITY 0.85 -#define gen2MORTALITY 0.60 -#define gen3MORTALITY 0.40 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - {gen1SIZE, gen1MORTALITY}, - {gen2SIZE, gen2MORTALITY}, - {gen3SIZE, gen3MORTALITY}, -}; - -/* run the test several times, calling mps_arena_step at a different - * frequency each time. When we call it often, tracing is never done - * during allocation. When we call it never, tracing is always done - * during allocation. - */ - -static unsigned long step_frequencies[] = { - 1000, - 5000, - 10000, - 1000000000, /* one billion */ -}; - -#define TESTS (sizeof(step_frequencies) / sizeof(step_frequencies[0])) - -static unsigned test_number = 0; - - -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) - -static mps_pool_t pool; -static mps_ap_t ap; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static mps_addr_t ambigRoots[ambigRootsCOUNT]; - -/* Things we want to measure. Times are all in microseconds. */ - -double alloc_time; /* Time spent allocating */ -double max_alloc_time; /* Max time taken to allocate one object */ -double step_time; /* Time spent in mps_arena_step returning 1 */ -double max_step_time; /* Max time of mps_arena_step returning 1 */ -double no_step_time; /* Time spent in mps_arena_step returning 0 */ -double max_no_step_time; /* Max time of mps_arena_step returning 0 */ - -double total_clock_time; /* Time spent reading the clock */ -long clock_reads; /* Number of times clock is read */ -long steps; /* # of mps_arena_step calls returning 1 */ -long no_steps; /* # of mps_arena_step calls returning 0 */ -size_t alloc_bytes; /* # of bytes allocated */ -long commit_failures; /* # of times mps_commit fails */ - - -/* Operating-system dependent timing. Defines two functions, void - * prepare_clock(void) and double my_clock(void). my_clock() returns - * the number of microseconds of CPU time used so far by the process. - * prepare_clock() sets things up so that my_clock() can run - * efficiently. - */ - -#ifdef MPS_OS_W3 - -static HANDLE currentProcess; - -static void prepare_clock(void) -{ - currentProcess = GetCurrentProcess(); -} - -static double my_clock(void) -{ - FILETIME ctime, etime, ktime, utime; - double dk, du; - GetProcessTimes(currentProcess, &ctime, &etime, &ktime, &utime); - dk = ktime.dwHighDateTime * 4096.0 * 1024.0 * 1024.0 + - ktime.dwLowDateTime; - dk /= 10.0; - du = utime.dwHighDateTime * 4096.0 * 1024.0 * 1024.0 + - utime.dwLowDateTime; - du /= 10.0; - ++ clock_reads; - return (du+dk); -} - -#else -/* on Posix systems, we can use getrusage. */ - -#include -#include -#include - -static void prepare_clock(void) -{ - /* do nothing */ -} - -static double my_clock(void) -{ - struct rusage ru; - getrusage(RUSAGE_SELF, &ru); - ++ clock_reads; - return ((ru.ru_utime.tv_sec + - ru.ru_stime.tv_sec) * 1000000.0 + - (ru.ru_utime.tv_usec + - ru.ru_stime.tv_usec)); -} -#endif - -/* Need to calibrate the clock. */ -/* In fact we need to do this repeatedly while the tests run because - * on some platforms the time taken to read the clock changes - * significantly during program execution. Yes, really (e.g. fri4gc - * on thrush.ravenbrook.com on 2002-06-28, clock_time goes from 5.43 - * us near process start to 7.45 us later). */ - -double clock_time; /* current estimate of time to read the clock */ - -/* take at least this many microseconds to set the clock */ -#define CLOCK_TIME_SET 10000 - -/* set_clock_timing() sets clock_time. */ - -static void set_clock_timing(void) -{ - long i; - double t1, t2, t3; - - t2 = 0.0; - t3 = my_clock(); - i = 0; - do { - t1 = my_clock(); - /* do nothing here */ - t2 += my_clock()-t1; - ++i; - } while (t1 < t3 + CLOCK_TIME_SET); - clock_time = t2/i; - total_clock_time += my_clock() - t3 + clock_time; -} - -/* How much time has elapsed since a recent call to my_clock? - * Deducts the calibrated clock timing, clamping to zero. - * - * The idea is to have code like this: - * - * t = my_clock(); - * do_something(); - * t = time_since(t); - * - * and the result will be our best estimate of how much CPU time the - * call to do_something() took. - */ - -static double time_since(double t) -{ - t = my_clock() - t; - total_clock_time += clock_time + clock_time; - if (t < clock_time) - return 0.0; - else - return (t - clock_time); -} - -/* print a number of microseconds in a useful format. */ - -#define MAXPRINTABLE 100.0 -#define MINPRINTABLE (MAXPRINTABLE / 1000.0) - -static void print_time(char *before, double t, char *after) -{ - char prefixes[] = "\0munpfazy"; /* don't print "ks" etc */ - char *x = prefixes+2; /* start at micro */ - double ot = t; - if (before) - printf("%s", before); - if (t > MAXPRINTABLE) { - while (x[-1] && t > MAXPRINTABLE) { - t /= 1000.0; - -- x; - } - if (t < MAXPRINTABLE) { - printf("%.3f %cs", t, *x); - } else { - printf("%.3f s", t/1000.0); - } - } else { - while (x[1] && t < MINPRINTABLE) { - t *= 1000.0; - ++ x; - } - if (t > MINPRINTABLE) - printf("%.3f %cs", t, *x); - else - printf("%g s", ot/1000000.0); - } - if (after) - printf("%s", after); -} - -/* Make a single Dylan object */ - -static mps_addr_t make(void) -{ - size_t length = rnd() % (avLEN * 2); - size_t size = (length+2) * sizeof(mps_word_t); - mps_addr_t p; - mps_res_t res; - - alloc_bytes += size; - - for(;;) { - mps_bool_t commit_res; - double t1, t2; - t1 = my_clock(); - MPS_RESERVE_BLOCK(res, p, ap, size); - t1 = time_since(t1); /* reserve time */ - if(res) - die(res, "MPS_RESERVE_BLOCK"); - res = dylan_init(p, size, exactRoots, exactRootsCOUNT); - if(res) - die(res, "dylan_init"); - t2 = my_clock(); - commit_res = mps_commit(ap, p, size); - t2 = time_since(t2); /* commit time */ - t1 += t2; /* total MPS time for this allocation */ - alloc_time += t1; - if (t1 > max_alloc_time) - max_alloc_time = t1; - if (commit_res) - break; - else - ++ commit_failures; - } - - return p; -} - -/* call mps_arena_step() */ - -static void test_step(mps_arena_t arena, double multiplier) -{ - mps_bool_t res; - double t1 = my_clock(); - res = mps_arena_step(arena, 0.1, multiplier); - t1 = time_since(t1); - if (res) { - if (t1 > max_step_time) - max_step_time = t1; - step_time += t1; - ++ steps; - } else { - if (t1 > max_no_step_time) - max_no_step_time = t1; - no_step_time += t1; - ++ no_steps; - } -} - -/* test -- the body of the test */ - -static void *test(void *arg, size_t s) -{ - mps_arena_t arena; - mps_fmt_t format; - mps_chain_t chain; - mps_root_t exactRoot, ambigRoot; - unsigned long objs; - size_t i; - mps_message_t message; - size_t live, condemned, not_condemned; - size_t messages; - mps_word_t collections, old_collections; - double total_mps_time, total_time; - double t1; - - arena = (mps_arena_t)arg; - (void)s; /* unused */ - - die(dylan_fmt(&format, arena), "fmt_create"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - - die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain), - "pool_create(amc)"); - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); - - for(i = 0; i < exactRootsCOUNT; ++i) - exactRoots[i] = objNULL; - for(i = 0; i < ambigRootsCOUNT; ++i) - ambigRoots[i] = rnd_addr(); - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, - mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), - "root_create_table(ambig)"); - - printf("Stepping every %lu allocations.\n", - (unsigned long)step_frequencies[test_number]); - - mps_message_type_enable(arena, mps_message_type_gc()); - - /* zero all our counters and timers. */ - - objs = 0; - clock_reads = 0; - steps = no_steps = 0; - alloc_bytes = 0; - commit_failures = 0; - alloc_time = step_time = no_step_time = 0.0; - max_alloc_time = max_step_time = max_no_step_time = 0.0; - total_clock_time = 0.0; - collections = old_collections = 0; - - t1 = my_clock(); - - while(objs < objCOUNT) { - size_t r; - - r = (size_t)rnd(); - if(r & 1) { - i = (r >> 1) % exactRootsCOUNT; - if(exactRoots[i] != objNULL) - cdie(dylan_check(exactRoots[i]), "dying root check"); - exactRoots[i] = make(); - if(exactRoots[(exactRootsCOUNT-1) - i] != objNULL) - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - } else { - i = (r >> 1) % ambigRootsCOUNT; - ambigRoots[(ambigRootsCOUNT-1) - i] = make(); - /* Create random interior pointers */ - ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); - } - - ++objs; - - if (objs % step_frequencies[test_number] == 0) - test_step(arena, 0.0); - - if (objs % multiStepFREQ == 0) - test_step(arena, multiStepMULT); - - if (objs % clockSetFREQ == 0) - set_clock_timing(); - - collections = mps_collections(arena); - if (collections > old_collections) { - old_collections = collections; - putchar('.'); - fflush(stdout); - } - } - - total_time = time_since(t1) - total_clock_time; - - if (collections > 0) - printf("\n"); - - messages = live = condemned = not_condemned = 0; - while (mps_message_get(&message, arena, mps_message_type_gc())) { - ++ messages; - live += mps_message_gc_live_size(arena, message); - condemned += mps_message_gc_condemned_size(arena, message); - not_condemned += mps_message_gc_not_condemned_size(arena, - message); - mps_message_discard(arena, message); - } - if (collections != messages) { - printf("%lu collections but %lu messages\n", - (unsigned long)collections, (unsigned long)messages); - collections = messages; - } - - total_mps_time = alloc_time + step_time + no_step_time; - printf("Collection statistics:\n"); - printf(" %"PRIuLONGEST" collections\n", (ulongest_t)collections); - printf(" %"PRIuLONGEST" bytes condemned.\n", (ulongest_t)condemned); - printf(" %lu bytes not condemned.\n", - (unsigned long)not_condemned); - printf(" %"PRIuLONGEST" bytes survived.\n", (ulongest_t)live); - if (condemned) { - printf(" Mortality %5.2f%%.\n", - (1.0 - ((double)live)/condemned) * 100.0); - printf(" Condemned fraction %5.2f%%.\n", - ((double)condemned/(condemned + not_condemned)) * 100.0); - } - if (collections) { - printf(" Condemned per collection %lu bytes.\n", - (unsigned long)condemned/collections); - printf(" Reclaimed per collection %lu bytes.\n", - (unsigned long)(condemned - live)/collections); - } - - printf("Allocation statistics:\n"); - printf(" %"PRIuLONGEST" objects (%"PRIuLONGEST" bytes) allocated.\n", - (ulongest_t)objs, (ulongest_t)alloc_bytes); - printf(" Commit failed %ld times.\n", commit_failures); - - printf("Timings:\n"); - print_time(" Allocation took ", alloc_time, ""); - print_time(", mean ", alloc_time / objs, ""); - print_time(", max ", max_alloc_time, ".\n"); - if (steps) { - printf(" %ld steps took ", steps); - print_time("", step_time, ""); - print_time(", mean ", step_time/steps, ""); - print_time(", max ", max_step_time, ".\n"); - } - if (no_steps) { - printf(" %ld non-steps took ", no_steps); - print_time("", no_step_time, ""); - print_time(", mean ", no_step_time / no_steps, ""); - print_time(", max ", max_no_step_time, ".\n"); - } - if (alloc_time > 0.0) - printf(" Allocated %.2f bytes per us.\n", - (double)alloc_bytes/alloc_time); - if (step_time > 0.0) { - printf(" Reclaimed %.2f bytes per us of step.\n", - (double)(condemned - live)/step_time); - if (collections > 0) { - printf(" Took %.2f steps ", (double)steps/collections); - print_time("(", step_time / collections, ") per collection.\n"); - } - } - print_time(" Total time ", total_time, ".\n"); - print_time(" Total MPS time ", total_mps_time, ""); - printf(" (%5.2f%%, ", total_mps_time * 100.0 / total_time); - print_time("", total_mps_time/alloc_bytes, " per byte, "); - print_time("", total_mps_time/objs, " per object)\n"); - print_time(" (adjusted for clock timing: ", - total_clock_time, - " spent reading the clock;\n"); - printf(" %"PRIuLONGEST" clock reads; ", (ulongest_t)clock_reads); - print_time("", total_clock_time / clock_reads, " per read;"); - print_time(" recently measured as ", clock_time, ").\n"); - mps_ap_destroy(ap); - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); - mps_pool_destroy(pool); - mps_chain_destroy(chain); - mps_fmt_destroy(format); - - return NULL; -} - -int main(int argc, char **argv) -{ - prepare_clock(); - - randomize(argc, argv); - - while (test_number < TESTS) { - mps_arena_t arena; - mps_thr_t thread; - void *r; - - set_clock_timing(); - die(mps_arena_create(&arena, mps_arena_class_vm(), - testArenaSIZE), - "arena_create"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - ++ test_number; - } - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/table.c b/mps/code/table.c deleted file mode 100644 index 3e5cc0c14ae..00000000000 --- a/mps/code/table.c +++ /dev/null @@ -1,422 +0,0 @@ -/* table.h: A dictionary mapping a Word to a void* - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .note.good-hash: As is common in hash table implementations, we - * assume that the hash function is good. - */ - -#include "table.h" -#include "mpm.h" - -#include - - -SRCID(table, "$Id$"); - - -/* tableHash -- return a hash value from an address - * - * This uses a single cycle of an MLCG, more commonly seen as a - * pseudorandom number generator. It works extremely well as a - * hash function. - * - * (In particular, it is substantially better than simply doing this: - * seed = (unsigned long)addr * 48271; - * Tested by RHSK 2010-12-28.) - * - * This MLCG is a full period generator: it cycles through every - * number from 1 to m-1 before repeating. Therefore, no two numbers - * in that range hash to the same value. Furthermore, it has prime - * modulus, which tends to avoid recurring patterns in the low-order - * bits, which is good because the hash will be used modulus the - * number of slots in the table. - * - * Of course it's only a 31-bit cycle, so we start by losing the top - * bit of the address, but that's hardly a great problem. - * - * See `rnd` in testlib.c for more technical details. - * - * The implementation is quite subtle. See rnd() in testlib.c, where - * it has been exhaustively (ie: totally) tested. RHSK 2010-12-28. - * - * NOTE: According to NB, still a fine function for producing a 31-bit hash - * value, although of course it only hashes on the lower 31 bits of the - * key; we could cheaply make it choose a different 31 bits if we'd prefer - * (e.g. ((key >> 2) & 0x7FFFFFFF)), or combine more of the key bits (e.g. - * ((key ^ (key >> 31)) & 0x7fffffff)). - */ - -#define R_m 2147483647UL -#define R_a 48271UL - -typedef Word Hash; - -static Hash tableHash(Word key) -{ - Hash hash = (Hash)(key & 0x7FFFFFFF); - /* requires m == 2^31-1, a < 2^16 */ - Hash bot = R_a * (hash & 0x7FFF); - Hash top = R_a * (hash >> 15); - hash = bot + ((top & 0xFFFF) << 15) + (top >> 16); - if(hash > R_m) - hash -= R_m; - return hash; -} - - -Bool TableCheck(Table table) -{ - CHECKS(Table, table); - CHECKL(table->count <= table->length); - CHECKL(table->length == 0 || table->array != NULL); - CHECKL(FUNCHECK(table->alloc)); - CHECKL(FUNCHECK(table->free)); - /* can't check allocClosure -- it could be anything */ - CHECKL(table->unusedKey != table->deletedKey); - return TRUE; -} - - -static Bool entryIsActive(Table table, TableEntry entry) -{ - return !(entry->key == table->unusedKey || - entry->key == table->deletedKey); -} - - -/* tableFind -- finds the entry for this key, or NULL - * - * .worst: In the worst case, this looks at every slot before giving up, - * but that's what you have to do in a closed hash table, to make sure - * that all the items still fit in after growing the table. - */ - -static TableEntry tableFind(Table table, Word key, Bool skip_deleted) -{ - Hash hash; - Index i; - Word mask; - - /* .find.visit: Ensure the length is a power of two so that the stride - is coprime and so visits all entries in the array eventually. */ - AVER(WordIsP2(table->length)); /* .find.visit */ - - mask = table->length - 1; - hash = tableHash(key) & mask; - i = hash; - do { - Word k = table->array[i].key; - if (k == key || - k == table->unusedKey || - (!skip_deleted && key == table->deletedKey)) - return &table->array[i]; - i = (i + (hash | 1)) & mask; /* .find.visit */ - } while(i != hash); - - return NULL; -} - - -/* TableGrow -- increase the capacity of the table - * - * Ensure the transform's hashtable can accommodate N entries (filled - * slots), without becoming cramped. If necessary, resize the - * hashtable by allocating a new one and rehashing all old entries. - * If insufficient memory, return error without modifying table. - * - * .hash.spacefraction: As with all closed hash tables, we must choose - * an appropriate proportion of slots to remain free. More free slots - * help avoid large-sized contiguous clumps of full cells and their - * associated linear search costs. - * - * .hash.initial: Any reasonable number. - * - * .hash.growth: A compromise between space inefficency (growing bigger - * than required) and time inefficiency (growing too slowly, with all - * the rehash costs at every step). A factor of 2 means that at the - * point of growing to a size X table, hash-work equivalent to filling - * a size-X table has already been done. So we do at most 2x the - * hash-work we would have done if we had been able to guess the right - * table size initially. - * - * Numbers of slots maintain this relation: - * occupancy <= capacity < enough <= cSlots - */ - -#define SPACEFRACTION 0.75 /* .hash.spacefraction */ - -Res TableGrow(Table table, Count extraCapacity) -{ - TableEntry oldArray, newArray; - Count oldLength, newLength; - Count required, minimum; - Count i, found; - - required = table->count + extraCapacity; - if (required < table->count) /* overflow? */ - return ResLIMIT; - - /* Calculate the minimum table length that would allow for the required - capacity without growing again. */ - minimum = (Count)(required / SPACEFRACTION); - if (minimum < required) /* overflow? */ - return ResLIMIT; - - /* Double the table length until it's larger than the minimum */ - oldLength = table->length; - newLength = oldLength; - while(newLength < minimum) { - Count doubled = newLength > 0 ? newLength * 2 : 1; /* .hash.growth */ - if (doubled <= newLength) /* overflow? */ - return ResLIMIT; - newLength = doubled; - } - - if (newLength == oldLength) /* already enough space? */ - return ResOK; - - /* TODO: An event would be good here */ - - oldArray = table->array; - newArray = table->alloc(table->allocClosure, - sizeof(TableEntryStruct) * newLength); - if(newArray == NULL) - return ResMEMORY; - - for(i = 0; i < newLength; ++i) { - newArray[i].key = table->unusedKey; - newArray[i].value = NULL; - } - - table->length = newLength; - table->array = newArray; - - found = 0; - for(i = 0; i < oldLength; ++i) { - if (entryIsActive(table, &oldArray[i])) { - TableEntry entry; - entry = tableFind(table, oldArray[i].key, FALSE /* none deleted */); - AVER(entry != NULL); - AVER(entry->key == table->unusedKey); - entry->key = oldArray[i].key; - entry->value = oldArray[i].value; - ++found; - } - } - AVER(found == table->count); - - if (oldLength > 0) { - AVER(oldArray != NULL); - table->free(table->allocClosure, - oldArray, - sizeof(TableEntryStruct) * oldLength); - } - - return ResOK; -} - - -/* TableCreate -- makes a new table */ - -extern Res TableCreate(Table *tableReturn, - Count length, - TableAllocMethod tableAlloc, - TableFreeMethod tableFree, - void *allocClosure, - Word unusedKey, - Word deletedKey) -{ - Table table; - Res res; - - AVER(tableReturn != NULL); - AVER(FUNCHECK(tableAlloc)); - AVER(FUNCHECK(tableFree)); - AVER(unusedKey != deletedKey); - - table = tableAlloc(allocClosure, sizeof(TableStruct)); - if(table == NULL) - return ResMEMORY; - - table->length = 0; - table->count = 0; - table->array = NULL; - table->alloc = tableAlloc; - table->free = tableFree; - table->allocClosure = allocClosure; - table->unusedKey = unusedKey; - table->deletedKey = deletedKey; - table->sig = TableSig; - - AVERT(Table, table); - - res = TableGrow(table, length); - if (res != ResOK) - return res; - - *tableReturn = table; - return ResOK; -} - - -/* TableDestroy -- destroy a table */ - -extern void TableDestroy(Table table) -{ - AVER(table != NULL); - if (table->length > 0) { - AVER(table->array != NULL); - table->free(table->allocClosure, - table->array, - sizeof(TableEntryStruct) * table->length); - } - table->sig = SigInvalid; - table->free(table->allocClosure, table, sizeof(TableStruct)); -} - - -/* TableLookup -- look up */ - -extern Bool TableLookup(void **valueReturn, Table table, Word key) -{ - TableEntry entry = tableFind(table, key, TRUE /* skip deleted */); - - if(entry == NULL || !entryIsActive(table, entry)) - return FALSE; - *valueReturn = entry->value; - return TRUE; -} - - -/* TableDefine -- add a new mapping */ - -extern Res TableDefine(Table table, Word key, void *value) -{ - TableEntry entry; - - AVER(key != table->unusedKey); - AVER(key != table->deletedKey); - - if (table->count >= table->length * SPACEFRACTION) { - Res res = TableGrow(table, 1); - if(res != ResOK) return res; - entry = tableFind(table, key, FALSE /* no deletions yet */); - AVER(entry != NULL); - if (entryIsActive(table, entry)) - return ResFAIL; - } else { - entry = tableFind(table, key, TRUE /* skip deleted */); - if (entry != NULL && entryIsActive(table, entry)) - return ResFAIL; - /* Search again to find the best slot, deletions included. */ - entry = tableFind(table, key, FALSE /* don't skip deleted */); - AVER(entry != NULL); - } - - entry->key = key; - entry->value = value; - ++table->count; - - return ResOK; -} - - -/* TableRedefine -- redefine an existing mapping */ - -extern Res TableRedefine(Table table, Word key, void *value) -{ - TableEntry entry; - - AVER(key != table->unusedKey); - AVER(key != table->deletedKey); - - entry = tableFind(table, key, TRUE /* skip deletions */); - if (entry == NULL || !entryIsActive(table, entry)) - return ResFAIL; - AVER(entry->key == key); - entry->value = value; - return ResOK; -} - - -/* TableRemove -- remove a mapping */ - -extern Res TableRemove(Table table, Word key) -{ - TableEntry entry; - - AVER(key != table->unusedKey); - AVER(key != table->deletedKey); - - entry = tableFind(table, key, TRUE); - if (entry == NULL || !entryIsActive(table, entry)) - return ResFAIL; - entry->key = table->deletedKey; - --table->count; - return ResOK; -} - - -/* TableMap -- apply a function to all the mappings */ - -extern void TableMap(Table table, - void (*fun)(void *closure, Word key, void*value), - void *closure) -{ - Index i; - for (i = 0; i < table->length; i++) - if (entryIsActive(table, &table->array[i])) - (*fun)(closure, table->array[i].key, table->array[i].value); -} - - -/* TableCount -- count the number of mappings in the table */ - -extern Count TableCount(Table table) -{ - return table->count; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/table.h b/mps/code/table.h deleted file mode 100644 index 1697be09b9b..00000000000 --- a/mps/code/table.h +++ /dev/null @@ -1,100 +0,0 @@ -/* table.h: Interface for a dictionary - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * $Id$ - */ - -#ifndef table_h -#define table_h - -#include "mpmtypes.h" -#include - - -typedef struct TableStruct *Table; - -#define TableSig ((Sig)0x5192AB13) /* SIGnature TABLE */ - -typedef void *(*TableAllocMethod)(void *closure, size_t size); -typedef void (*TableFreeMethod)(void *closure, void *p, size_t size); - -typedef struct TableEntryStruct { - Word key; - void *value; -} TableEntryStruct, *TableEntry; - -typedef struct TableStruct { - Sig sig; /* */ - Count length; /* Number of slots in the array */ - Count count; /* Active entries in the table */ - TableEntry array; /* Array of table slots */ - TableAllocMethod alloc; - TableFreeMethod free; - void *allocClosure; - Word unusedKey; /* key marking unused (undefined) entries */ - Word deletedKey; /* key marking deleted entries */ -} TableStruct; - -extern Res TableCreate(Table *tableReturn, - Count length, - TableAllocMethod tableAlloc, - TableFreeMethod tableFree, - void *allocClosure, - Word unusedKey, - Word deletedKey); -extern void TableDestroy(Table table); -extern Bool TableCheck(Table table); -extern Res TableDefine(Table table, Word key, void *value); -extern Res TableRedefine(Table table, Word key, void *value); -extern Bool TableLookup(void **valueReturn, Table table, Word key); -extern Res TableRemove(Table table, Word key); -extern Count TableCount(Table table); -extern void TableMap(Table table, - void(*fun)(void *closure, Word key, void *value), - void *closure); -extern Res TableGrow(Table table, Count extraCapacity); - - -#endif /* table_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/teletest.c b/mps/code/teletest.c deleted file mode 100644 index b857494da73..00000000000 --- a/mps/code/teletest.c +++ /dev/null @@ -1,262 +0,0 @@ -/* teletest.c: TELEMETRY TEST - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .source: The command parser here was taken and adapted from bttest.c. - */ - -#include "mpm.h" -#include "mps.h" -#include "mpsavm.h" -#include "testlib.h" - -#include - -SRCID(teletest, "$Id$"); - - -static mps_arena_t arena; - - -#define MAX_ARGS 3 -#define INPUT_BUFFER_SIZE 512 - -#if (MPS_WORD_WIDTH == 32) -#define WORD_FORMAT "0x%08lx" -#elif (MPS_WORD_WIDTH == 64) -#define WORD_FORMAT "0x%016lx" -#else -#error "Unrecognized word width" -#endif - - -static mps_word_t args[MAX_ARGS]; -static char *stringArg; -static Count argCount; - - -static void callControl(mps_word_t reset, mps_word_t flip) -{ - mps_word_t old, new; - old = mps_telemetry_control(reset, flip); - new = mps_telemetry_control((mps_word_t)0, (mps_word_t)0); - - (void)printf(WORD_FORMAT " -> " WORD_FORMAT "\n", old, new); -} - - -static void doControl(void) -{ - callControl(args[0], args[1]); -} - - -static void doRead(void) -{ - mps_word_t old; - old = mps_telemetry_control((mps_word_t)0, (mps_word_t)0); - - (void)printf(WORD_FORMAT "\n", old); -} - - -static void doSet(void) -{ - callControl(args[0], args[0]); -} - - -static void doReset(void) -{ - callControl(args[0], (mps_word_t)0); -} - - -static void doFlip(void) -{ - callControl((mps_word_t)0, args[0]); -} - - -static void doIntern(void) -{ - mps_word_t id; - - id = mps_telemetry_intern(stringArg); - (void)printf(WORD_FORMAT "\n", id); -} - -static void doLabel(void) -{ - mps_telemetry_label((mps_addr_t)args[0], args[1]); -} - -static void doFlush(void) -{ - mps_telemetry_flush(); -} - -static void doQuit(void) -{ - mps_arena_destroy(arena); - exit(0); -} - - -static void doHelp(void) -{ - (void)printf("control -> Control filter\n" - "read -> Read filter\n" - "set -> Set filter\n" - "reset -> Reset filter\n" - "flip -> Toggle filter\n"); - (void)printf("intern -> Intern string\n" - "label
Label address\n" - "flush Flush buffer\n" - "help Print this message\n" - "quit Quit\n"); -} - - -static struct commandShapeStruct { - char *name; - Count int_args; - mps_bool_t string_arg; - void (*fun)(void); -} commandShapes[] = { - {"control", 2, 0, doControl}, - {"read", 0, 0, doRead}, - {"set", 1, 0, doSet}, - {"reset", 1, 0, doReset}, - {"flip", 1, 0, doFlip}, - {"intern", 0, 1, doIntern}, - {"label", 2, 0, doLabel}, - {"flush", 0, 0, doFlush}, - {"help", 0, 0, doHelp}, - {"quit", 0, 0, doQuit}, - {NULL, 0, 0, NULL} -}; - - -typedef struct commandShapeStruct *commandShape; - - -static void obeyCommand(char *command) -{ - commandShape shape = commandShapes; - while(shape->name != NULL) { - char *csp = shape->name; - char *p = command; - while (*csp == *p) { - csp++; - p++; - } - if ((*csp == 0) && ((*p == '\n') || (*p == ' '))) { /* complete match */ - argCount = 0; - while ((*p == ' ') && (argCount < shape->int_args)) { - /* get an argument */ - char *newP; - mps_word_t word; - word = (mps_word_t)strtoul(p, &newP, 0); - args[argCount] = word; - if (newP == p) { /* strtoul failed */ - printf("couldn't parse an integer argument\n"); - return; - } - p = newP; - ++ argCount; - } - if(shape->string_arg) { - char *end; - while(*p == ' ') - ++p; - for(end = p; *end != '\n'; end++) - NOOP; - *end = '\0'; - stringArg = p; - } else { - stringArg = NULL; - } - if (argCount < shape->int_args) { - printf("insufficient arguments to command\n"); - } else if (*p != '\n' && stringArg == NULL) { - printf("too many arguments to command\n"); - } else { /* do the command */ - shape->fun(); - } - return; - } else { - ++ shape; /* try next command */ - } - } - printf("command not understood\n> %s\n", command); - doHelp(); -} - - -#define testArenaSIZE (((size_t)64)<<20) - -extern int main(int argc, char *argv[]) -{ - testlib_unused(argc); - testlib_unused(argv); - - die(mps_arena_create((mps_arena_t*)&arena, mps_arena_class_vm(), - testArenaSIZE), - "mps_arena_create"); - doHelp(); - while(1) { - char input[INPUT_BUFFER_SIZE]; - printf("telemetry test> "); - fflush(stdout); - if (fgets(input, INPUT_BUFFER_SIZE , stdin)) { - obeyCommand(input); - } else { - doQuit(); - } - } - return EXIT_SUCCESS; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/test.c b/mps/code/test.c deleted file mode 100644 index b4eff710269..00000000000 --- a/mps/code/test.c +++ /dev/null @@ -1,2 +0,0 @@ -extern void hello(void); -int main(void) { hello(); return 0; } diff --git a/mps/code/testlib.c b/mps/code/testlib.c deleted file mode 100644 index 06d0641c688..00000000000 --- a/mps/code/testlib.c +++ /dev/null @@ -1,426 +0,0 @@ -/* testlib.c: TEST LIBRARY - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .purpose: A library of functions that may be of use to unit tests. - */ - -#include "testlib.h" -#include "mps.h" -#include "misc.h" /* for NOOP */ -#include -#include -#include -#ifdef MPS_OS_IA -struct itimerspec; /* stop complaints from time.h */ -#endif -#include - -#ifdef MPS_BUILD_MV -/* MSVC warning 4702 = unreachable code - * - * job000605: believed needed to prevent VC7 warning - * for error() below, in which va_end is mandated by - * ISO C (C99:7.15.1) even though it is unreachable. - */ -#pragma warning(disable: 4702) -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: sscanf. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - - -/* fail -- like assert, but (notionally) returns a value, so usable in an expression */ - -int fail(void) -{ - Insist(FALSE); - return 1111UL; -} - - -/* rnd -- a random number generator - * - * We use the (Multiplicative) Linear Congruential Generator - * Xn = a * Xn-1 mod m - * with: m = 2147483647 (2^31 - 1, a Mersenne prime), and a = 48271. - * This is a 'full-period' generator: all values in [1..(mod-1)] - * (ie. 0x00000001 to 0x7ffffffe inclusive) are returned once, and then - * the cycle begins again. The value 0 is not part of the cycle and - * is never returned. So the period = mod-1, ie. 2147483646. - * - * This generator is extremely simple and has been very well studied. - * It is free of major vices we might care about for this application. - * In particular, as m is prime, low order bits are random. Therefore - * to roll an N-sided die (N << m), "rnd() % N" is acceptable, giving - * a value in [0..N-1]. - * - * It was popularised by the much-cited Park & Miller paper: - * Stephen K Park & Keith W Miller (1988). Random number generators: - * good ones are hard to find. Communications of the ACM, - * 31:1192-1201. - * The recommended multiplier a was later updated from 16807 to 48271: - * Stephen K Park, Keith W Miller, Paul K. Stockmeyer (1993). - * Technical Correspondence. Communications of the ACM, 36:105-110. - * - * (Many more elaborate generators have been invented. The next simple - * step would be to combine with the MLCG m = 2147483399 a = 40692, to - * make the period "about 74 quadrillion". See the summary of chapter - * 3 in Knuth's "The Art of Computer Programming".) - * - * This (fast) implementation uses the identity: - * 0x80000000 == 0x7FFFFFFF + 0x00000001 - * noted by David Carta (1990), where 0x7FFFFFFF == 2^31-1 == m, which - * means that bits above the first 31 can simply be shifted >> 31 and - * added, preserving Xn mod m. To remain within 32-bit unsigned - * arithmetic when multiplying the previous seed (31 bits) by a (16 - * bits), the seed is split into bottom and top halves; bits above - * the first 31 are simply "top >> 16". (Code by RHSK, inspired by - * Robin Whittle's article at "http://www.firstpr.com.au/dsp/rand31/"). - * - * Slower implementations, used for verification: - * rnd_verify_schrage uses the method of L. Schrage (1979 & 1983), - * namely splitting the seed by q, where q = m div a. - * rnd_verify_float simply uses floating point arithmetic. - */ - -static unsigned long seed = 1; -#define R_m 2147483647UL -#define R_a 48271UL -unsigned long rnd(void) -{ - /* requires m == 2^31-1, a < 2^16 */ - unsigned long bot = R_a * (seed & 0x7FFF); - unsigned long top = R_a * (seed >> 15); - seed = bot + ((top & 0xFFFF) << 15) + (top >> 16); - if(seed > R_m) - seed -= R_m; - return seed; - /* Have you modified this code? Run rnd_verify(3) please! RHSK */ -} - -static unsigned long seed_verify_schrage = 1; -#define R_q (R_m / R_a) -#define R_r (R_m % R_a) -static unsigned long rnd_verify_schrage(void) -{ - /* requires m < 2^31, q > r; see Park & Miller (1988) */ - unsigned long alpha = R_a * (seed_verify_schrage % R_q); /* < m */ - unsigned long beta = R_r * (seed_verify_schrage / R_q); /* < m */ - seed_verify_schrage = alpha - beta; - if(alpha < beta) - seed_verify_schrage += R_m; - return seed_verify_schrage; -} - -static unsigned long seed_verify_float = 1; -#define R_m_float 2147483647.0 -#define R_a_float 48271.0 -static unsigned long rnd_verify_float(void) -{ - double s; - s = seed_verify_float; - s *= R_a_float; - s = fmod(s, R_m_float); - seed_verify_float = (unsigned long)s; - return seed_verify_float; -} - -/* rnd_verify -- verify that rnd() returns the correct results - * - * depth = how much time to spend verifying - * 0: very quick -- just verify the next rnd() value - * 1: quick -- verify the first 10000 calls from seed = 1 - * 2: slow (~ 1 minute) -- run the fast generator for a full cycle - * 3: very slow (several minutes) -- verify a full cycle - */ -void rnd_verify(int depth) -{ - unsigned long orig_seed = seed; - unsigned long i; - unsigned long r = 0; - - /* 0: the next value from rnd() matches rnd_verify_*() */ - if(depth >= 0) { - seed_verify_schrage = seed; - seed_verify_float = seed; - r = rnd(); - Insist(rnd_verify_schrage() == r); - Insist(rnd_verify_float() == r); - } - - /* 1: first 10000 (from Park & Miller, note: 1-based indexing!) */ - if(depth >= 1) { - i = 1; - seed = 1; - seed_verify_schrage = seed; - seed_verify_float = seed; - for(i = 2; i <= 10001; i += 1) { - r = rnd(); - Insist(rnd_verify_schrage() == r); - Insist(rnd_verify_float() == r); - } - /* Insist(r == 1043618065UL); -- correct value for a = 16807 */ - Insist(r == 399268537UL); /* correct for a = 48271 */ - } - - /* 1: observe wrap-around (note: 0-based indexing) */ - if(depth >= 1) { - /* set-up seed value for i = 2147483645 */ - /* seed = 1407677000UL; -- correct value for a = 16807 */ - seed = 1899818559UL; /* correct for a = 48271 */ - seed_verify_schrage = seed; - seed_verify_float = seed; - r = rnd(); - Insist(rnd_verify_schrage() == r); - Insist(rnd_verify_float() == r); - Insist(r == 1); /* wrap-around */ - } - - /* 2 & 3: Full cycle (3 => verifying each value) */ - if(depth >= 2) { - int verify = (depth >= 3); - unsigned long r1 = 1; - - i = 0; - seed = 1; - seed_verify_schrage = seed; - seed_verify_float = seed; - while(1) { - i += 1; - r = rnd(); - if(verify) { - Insist(rnd_verify_schrage() == r); - Insist(rnd_verify_float() == r); - } - if(r == 1) { - printf("Full cycle complete%s:\n", - verify ? " (verifying every value)" - : " (fast implementation only)" ); - printf("Wrapped at i=%lu, r=%lu, r(i-1)=%lu.\n", - i, r, r1); - break; - } else { - r1 = r; - } - } - } - - seed = orig_seed; -} - -/* rnd_addr -- a random address generator - * - * rnd gives 31 random bits, we run it repeatedly to get enough bits. - */ - -#define ADDR_BITS (sizeof(mps_addr_t) * CHAR_BIT) - -mps_addr_t rnd_addr(void) -{ - mps_word_t res; - unsigned bits; - - for (bits = 0, res = 0; bits < ADDR_BITS; - bits += 31, res = res << 31 | (mps_word_t)rnd()) - NOOP; - return (mps_addr_t)res; -} - - -/* randomize -- randomize the generator, or initialize to replay - * - * There have been 3 versions of the rnd-states reported by this - * function: - * - * 1. before RHSK got his hands on rnd(), ie. pre-2008. These seed - * values are not currently supported, but it might be easy to - * add support. - * - * 2. v2 states: the published "seed" (state) value was the seed - * *before* the 10 rnds to churn up and separate nearby values - * from time(). This was unfortunate: you can't write a rnd_state - * getter, because it would have to go 10 steps backwards, and - * that's impossible. - * (2008..2010-03-22) - * - * 3. v3 states: when autogenerated from time(), the published state - * (printf'd) is that *after* the 10 rnds. Therefore you can get - * the state easily, store it, re-use it, etc. - * (New from 2010-03-22, changelist 170093) - */ - -void randomize(int argc, char **argv) -{ - int i; - int n; - unsigned long seedt; - unsigned long seed0; - - if (argc > 1) { - n = sscanf(argv[1], "%lu", &seed0); - Insist(n == 1); - printf("randomize(): resetting initial state (v3) to: %lu.\n", seed0); - rnd_state_set(seed0); - } else { - /* time_t uses an arbitrary encoding, but hopefully the low order */ - /* 31 bits will have at least one bit changed from run to run. */ - seedt = 1 + (unsigned long)time(NULL) % (R_m - 1); - - /* The value returned by time() on some OSs may simply be a - * count of seconds: therefore successive runs may start with - * nearby seeds, possibly differing only by 1. So the first value - * returned by rnd() may differ by only 48271. It is conceivable - * that some tests might be able to 'spot' this pattern (for - * example: by using the first rnd() value, mod 100M and rounded - * to multiple of 1024K, as arena size in bytes). - * - * So to mix it up a bit, we do a few iterations now. How many? - * Very roughly, 48271^2 is of the same order as 2^31, so two - * iterations would make the characteristic difference similar to - * the period. Hey, let's go wild and do 10. - */ - rnd_state_set(seedt); - for(i = 0; i < 10; i += 1) { - (void)rnd(); - } - - seed0 = rnd_state(); - printf("randomize(): choosing initial state (v3): %lu.\n", seed0); - rnd_state_set(seed0); - } -} - -unsigned long rnd_state(void) -{ - return seed; -} - -void rnd_state_set(unsigned long seed0) -{ - Insist(seed0 < R_m); - Insist(seed0 != 0); - seed = seed0; - - rnd_verify(0); - Insist(seed == seed0); -} - -/* rnd_state_set_2 -- legacy support for v2 rnd states - * - * In v2, the published "seed" (state) value was the seed *before* - * the 10 rnds to churn up and separate nearby values from time(). - * - * Set the seed, then convert it to a v3 state by doing those 10 rnds. - */ -void rnd_state_set_v2(unsigned long seed0_v2) -{ - int i; - unsigned long seed0; - - rnd_state_set(seed0_v2); - for(i = 0; i < 10; i += 1) { - (void)rnd(); - } - - seed0 = rnd_state(); - printf("rnd_state_set_v2(): seed0_v2 = %lu, converted to state_v3 = %lu.\n", seed0_v2, seed0); - rnd_state_set(seed0); -} - - -/* verror -- die with message */ - -void verror(const char *format, va_list args) -{ - fflush(stdout); /* synchronize */ - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - exit(1); -} - - -/* error -- die with message */ - -void error(const char *format, ...) -{ - va_list args; - - va_start(args, format); - verror(format, args); - va_end(args); -} - - -/* die -- Test a return code, and exit on error */ - -void die(mps_res_t res, const char *s) -{ - if (res != MPS_RES_OK) { - error("\n%s: %d\n", s, res); - } -} - - -/* die_expect -- Test a return code, and exit on unexpected result */ - -void die_expect(mps_res_t res, mps_res_t expected, const char *s) -{ - if (res != expected) { - error("\n%s: %d\n", s, res); - } -} - - -/* cdie -- Test a C boolean, and exit on error */ - -void cdie(int res, const char *s) -{ - if (!res) { - error("\n%s: %d\n", s, res); - } -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/testlib.h b/mps/code/testlib.h deleted file mode 100644 index 2bcd50e7c18..00000000000 --- a/mps/code/testlib.h +++ /dev/null @@ -1,250 +0,0 @@ -/* testlib.h: TEST LIBRARY INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .purpose: A library of functions that may be of use to unit tests. - */ - -#ifndef testlib_h -#define testlib_h - -#include "mps.h" -#include "misc.h" /* for STR */ - -/* Include system header hackery. */ -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpswin.h" -#endif -#ifdef MPS_OS_XC -#include "osxc.h" -#endif - -#include - - -/* Suppress Visual C warnings at warning level 4, */ -/* see mail.richard.1997-09-25.13-26. */ -/* Essentially the same settings are done in config.h. */ - -#ifdef MPS_BUILD_MV - -/* "unreferenced inline function has been removed" (windows.h) */ -#pragma warning(disable: 4514) - -/* "constant conditional" (MPS_END) */ -#pragma warning(disable: 4127) - -/* MSVC 2.0 generates a warning when using NOCHECK or UNUSED */ -#ifdef _MSC_VER -#if _MSC_VER < 1000 -#pragma warning(disable: 4705) -#endif -#else /* _MSC_VER */ -#error "Expected _MSC_VER to be defined for builder.mv" -#endif /* _MSC_VER */ - - -/* MSVC 10.00 on PowerPC generates erroneous warnings about */ -/* uninitialized local variables, if you take their address. */ -#ifdef MPS_ARCH_PP -#pragma warning(disable: 4701) -#endif - - -/* Non-checking varieties give many spurious warnings because parameters - * are suddenly unused, etc. We aren't interested in these. - */ - -#if defined(AVER_AND_CHECK_NONE) - -/* "unreferenced formal parameter" */ -#pragma warning(disable: 4100) - -/* "unreferenced local function has been removed" */ -#pragma warning(disable: 4505) - -#endif - - -#endif /* MPS_BUILD_MV */ - - -/* ulongest_t -- longest unsigned integer type - * - * Define a longest unsigned integer type for testing and printing. We'd - * like to use C99's uintmax_t and PRIuMAX here, but the MPS is in C89 - * and C99 isn't supported by Microsoft. - * - * We avoid using the ones defined in mpstd.h because we want the tests to - * root out any incompatible assumptions by breaking. - */ - -#ifdef MPS_PF_W3I6MV -#define PRIuLONGEST "llu" -#define SCNuLONGEST "llu" -#define PRIXLONGEST "llX" -#define PRIwWORD "16" -typedef unsigned long long ulongest_t; -typedef long long longest_t; -#define MPS_WORD_CONST(n) (n##ull) -#else -#define PRIuLONGEST "lu" -#define SCNuLONGEST "lu" -#define PRIXLONGEST "lX" -#define PRIwWORD "8" -typedef unsigned long ulongest_t; -typedef long longest_t; -#define MPS_WORD_CONST(n) (n##ul) -#endif -#define PRIXPTR "0"PRIwWORD PRIXLONGEST - - -/* testlib_unused -- declares that a variable is unused - * - * It should be used to prevent compiler warnings about unused - * variables. Care should be exercised; the fact that a variable - * is unused may need justification. - */ - -#define testlib_unused(v) ((void)(v)) - - -/* die -- succeed or die - * - * If the first argument is not ResOK then prints the second - * argument on stderr and exits the program. Otherwise does nothing. - * - * Typical use: - * die(mps_ap_create(&ap, pool, mps_rank_exact()), "APCreate"); - */ - -extern void die(mps_res_t res, const char *s); - - -/* die_expect -- get expected result or die - * - * If the first argument is not the same as the second argument, - * prints the third argument on stderr and exits the program. - * Otherwise does nothing. - * - * Typical use: - * die_expect(res, MPS_RES_COMMIT_LIMIT, "Commit limit allocation"); - */ - -extern void die_expect(mps_res_t res, mps_res_t expected, const char *s); - - -/* cdie -- succeed or die - * - * If the first argument is not true (non-zero) then prints the second - * argument on stderr and exits the program. Otherwise does nothing. - * - * Typical use: - * cdie(foo != NULL, "No foo"); - */ - -extern void cdie(int res, const char *s); - - -/* error, verror -- die with message */ - -extern void error(const char *format, ...); -extern void verror(const char *format, va_list args); - - -/* Insist -- like assert, but even in release varieties */ - -#define Insist(cond) insist1(cond, #cond) - -#define insist1(cond, condstring) \ - if(cond) \ - NOOP; \ - else \ - cdie(cond, condstring "\n" __FILE__ "\n" STR(__LINE__)) - - -/* fail -- like assert, but (notionally) returns a value, so usable in an expression */ - -extern int fail(void); - - -/* rnd -- random number generator - * - * rnd() generates a sequence of integers in the range [1, 2^31-2]. - */ - -extern unsigned long rnd(void); -typedef unsigned long rnd_state_t; -extern rnd_state_t rnd_state(void); -extern void rnd_state_set(rnd_state_t state_v3); -extern void rnd_state_set_v2(rnd_state_t seed0_v2); /* legacy */ - - -/* rnd_verify() -- checks behaviour of rnd() */ -extern void rnd_verify(int depth); - - -/* rnd_addr -- random number generator - * - * rnd_addr() generates a sequence of addresses all over the address space. - */ - -extern mps_addr_t rnd_addr(void); - - -/* randomize -- randomize the generator, or initialize to replay - * - * randomize(argc, argv) randomizes the rnd generator (using time(3)) - * and prints out the randomization seed, or takes a seed (as a command- - * line argument) and initializes the generator to the same state. - */ - -extern void randomize(int argc, char **argv); - - -#endif /* testlib_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/th.h b/mps/code/th.h deleted file mode 100644 index 30a2205a356..00000000000 --- a/mps/code/th.h +++ /dev/null @@ -1,115 +0,0 @@ -/* th.h: THREAD MANAGER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: Provides thread suspension facilities to the shield. - * See . Each thread has to be - * individually registered and deregistered with an arena. - */ - -#ifndef th_h -#define th_h - -#include "mpmtypes.h" -#include "ring.h" - - -#define ThreadSig ((Sig)0x519286ED) /* SIGnature THREaD */ - -extern Bool ThreadCheck(Thread thread); - - -/* ThreadCheckSimple - * - * Simple thread-safe check of a thread object. - */ - -extern Bool ThreadCheckSimple(Thread thread); - - -extern Res ThreadDescribe(Thread thread, mps_lib_FILE *stream); - - -/* Register/Deregister - * - * Explicitly register/deregister a thread on the arena threadRing. - * Register returns a "Thread" value which needs to be used - * for deregistration. - * - * Threads must not be multiply registered in the same arena. - */ - -extern Res ThreadRegister(Thread *threadReturn, Arena arena); - -extern void ThreadDeregister(Thread thread, Arena arena); - - -/* ThreadRingSuspend/Resume - * - * These functions suspend/resume the threads on the ring. - * If the current thread is among them, it is not suspended, - * nor is any attempt to resume it made. - */ - -extern void ThreadRingSuspend(Ring threadRing); -extern void ThreadRingResume(Ring threadRing); - - -/* ThreadRingThread - * - * Return the thread from an element of the Arena's - * thread ring. - */ - -extern Thread ThreadRingThread(Ring threadRing); - - -extern Arena ThreadArena(Thread thread); - -extern Res ThreadScan(ScanState ss, Thread thread, void *stackBot); - - -#endif /* th_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/than.c b/mps/code/than.c deleted file mode 100644 index 752ef3ed64c..00000000000 --- a/mps/code/than.c +++ /dev/null @@ -1,186 +0,0 @@ -/* than.c: ANSI THREADS MANAGER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This is a single-threaded implementation of the threads manager. - * Has stubs for thread suspension. - * See . - * - * .single: We only expect at most one thread on the ring. - * - * This supports the - */ - -#include "mpm.h" - -SRCID(than, "$Id$"); - - -typedef struct mps_thr_s { /* ANSI fake thread structure */ - Sig sig; /* */ - Serial serial; /* from arena->threadSerial */ - Arena arena; /* owning arena */ - RingStruct arenaRing; /* attaches to arena */ -} ThreadStruct; - - -Bool ThreadCheck(Thread thread) -{ - CHECKS(Thread, thread); - CHECKU(Arena, thread->arena); - CHECKL(thread->serial < thread->arena->threadSerial); - CHECKL(RingCheck(&thread->arenaRing)); - return TRUE; -} - - -Bool ThreadCheckSimple(Thread thread) -{ - CHECKS(Thread, thread); - return TRUE; -} - - -Res ThreadRegister(Thread *threadReturn, Arena arena) -{ - Res res; - Thread thread; - Ring ring; - void *p; - - AVER(threadReturn != NULL); - - res = ControlAlloc(&p, arena, sizeof(ThreadStruct), - /* withReservoirPermit */ FALSE); - if(res != ResOK) return res; - thread = (Thread)p; - - thread->arena = arena; - RingInit(&thread->arenaRing); - - thread->sig = ThreadSig; - thread->serial = arena->threadSerial; - ++arena->threadSerial; - - AVERT(Thread, thread); - - ring = ArenaThreadRing(arena); - AVER(RingCheckSingle(ring)); /* .single */ - - RingAppend(ring, &thread->arenaRing); - - *threadReturn = thread; - return ResOK; -} - - -void ThreadDeregister(Thread thread, Arena arena) -{ - AVERT(Thread, thread); - AVERT(Arena, arena); - - RingRemove(&thread->arenaRing); - - thread->sig = SigInvalid; - - RingFinish(&thread->arenaRing); - - ControlFree(arena, thread, sizeof(ThreadStruct)); -} - - -void ThreadRingSuspend(Ring threadRing) -{ - AVERT(Ring, threadRing); - return; -} - -void ThreadRingResume(Ring threadRing) -{ - AVERT(Ring, threadRing); - return; -} - -Thread ThreadRingThread(Ring threadRing) -{ - Thread thread; - AVERT(Ring, threadRing); - thread = RING_ELT(Thread, arenaRing, threadRing); - AVERT(Thread, thread); - return thread; -} - - -/* Must be thread-safe. See . */ -Arena ThreadArena(Thread thread) -{ - /* Can't AVER thread as that would not be thread-safe */ - /* AVERT(Thread, thread); */ - return thread->arena; -} - - -Res ThreadScan(ScanState ss, Thread thread, void *stackBot) -{ - UNUSED(thread); - return StackScan(ss, stackBot); -} - - -Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) -{ - Res res; - - res = WriteF(stream, - "Thread $P ($U) {\n", (WriteFP)thread, (WriteFU)thread->serial, - " arena $P ($U)\n", - (WriteFP)thread->arena, (WriteFU)thread->arena->serial, - "} Thread $P ($U)\n", (WriteFP)thread, (WriteFU)thread->serial, - NULL); - if(res != ResOK) return res; - - return ResOK; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/thix.c b/mps/code/thix.c deleted file mode 100644 index b792cd96783..00000000000 --- a/mps/code/thix.c +++ /dev/null @@ -1,332 +0,0 @@ -/* thix.c: Threads Manager for Posix threads - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .purpose: This is a pthreads implementation of the threads manager. - * This implements . - * - * .design: See . - * - * .thread.id: The thread id is used to identify the current thread. - * - * ASSUMPTIONS - * - * .error.resume: PThreadextResume is assumed to succeed unless the thread - * has been destroyed. - * .error.suspend: PThreadextSuspend is assumed to succeed unless the thread - * has been destroyed. In this case, the suspend context is set to NULL; - * - * .stack.full-descend: assumes full descending stack. - * i.e. stack pointer points to the last allocated location; - * stack grows downwards. - * - * .stack.below-bottom: it's legal for the stack pointer to be at a - * higher address than the registered bottom of stack. This might - * happen if the stack of another thread doesn't contain any frames - * belonging to the client language. In this case, the stack should - * not be scanned. - * - * .stack.align: assume roots on the stack are always word-aligned, - * but don't assume that the stack pointer is necessarily - * word-aligned at the time of reading the context of another thread. - */ - -#include "prmcix.h" -#include "mpm.h" - -#include -#include "pthrdext.h" - -SRCID(thix, "$Id$"); - - -/* ThreadStruct -- thread desriptor */ - -typedef struct mps_thr_s { /* PThreads thread structure */ - Sig sig; /* */ - Serial serial; /* from arena->threadSerial */ - Arena arena; /* owning arena */ - RingStruct arenaRing; /* threads attached to arena */ - PThreadextStruct thrextStruct; /* PThreads extension */ - pthread_t id; /* Pthread object of thread */ - MutatorFaultContext mfc; /* Context if thread is suspended */ -} ThreadStruct; - - -/* ThreadCheck -- check a thread */ - -Bool ThreadCheck(Thread thread) -{ - CHECKS(Thread, thread); - CHECKU(Arena, thread->arena); - CHECKL(thread->serial < thread->arena->threadSerial); - CHECKL(RingCheck(&thread->arenaRing)); - CHECKD(PThreadext, &thread->thrextStruct); - return TRUE; -} - -Bool ThreadCheckSimple(Thread thread) -{ - CHECKS(Thread, thread); - return TRUE; -} - - -/* ThreadRegister -- register a thread with an arena */ - -Res ThreadRegister(Thread *threadReturn, Arena arena) -{ - Res res; - Thread thread; - void *p; - - AVER(threadReturn != NULL); - AVERT(Arena, arena); - - res = ControlAlloc(&p, arena, sizeof(ThreadStruct), - /* withReservoirPermit */ FALSE); - if(res != ResOK) - return res; - thread = (Thread)p; - - thread->id = pthread_self(); - - RingInit(&thread->arenaRing); - - thread->sig = ThreadSig; - thread->serial = arena->threadSerial; - ++arena->threadSerial; - thread->arena = arena; - thread->mfc = NULL; - - PThreadextInit(&thread->thrextStruct, thread->id); - - AVERT(Thread, thread); - - RingAppend(ArenaThreadRing(arena), &thread->arenaRing); - - *threadReturn = thread; - return ResOK; -} - - -/* ThreadDeregister -- deregister a thread from an arena */ - -void ThreadDeregister(Thread thread, Arena arena) -{ - AVERT(Thread, thread); - AVERT(Arena, arena); - - RingRemove(&thread->arenaRing); - - thread->sig = SigInvalid; - - RingFinish(&thread->arenaRing); - - PThreadextFinish(&thread->thrextStruct); - - ControlFree(arena, thread, sizeof(ThreadStruct)); -} - - -/* mapThreadRing -- map over threads on ring calling a function on each one - * except the current thread - */ - -static void mapThreadRing(Ring threadRing, void (*func)(Thread)) -{ - Ring node, next; - pthread_t self; - - AVERT(Ring, threadRing); - - self = pthread_self(); - RING_FOR(node, threadRing, next) { - Thread thread = RING_ELT(Thread, arenaRing, node); - AVERT(Thread, thread); - if(! pthread_equal(self, thread->id)) /* .thread.id */ - (*func)(thread); - } -} - - -/* ThreadRingSuspend -- suspend all threads on a ring, expect the current one */ - - -static void threadSuspend(Thread thread) -{ - /* .error.suspend */ - /* In the error case (PThreadextSuspend returning ResFAIL), we */ - /* assume the thread has been destroyed. */ - /* In which case we simply continue. */ - Res res; - res = PThreadextSuspend(&thread->thrextStruct, &thread->mfc); - if(res != ResOK) - thread->mfc = NULL; -} - - - -void ThreadRingSuspend(Ring threadRing) -{ - mapThreadRing(threadRing, threadSuspend); -} - - -/* ThreadRingResume -- resume all threads on a ring (expect the current one) */ - - -static void threadResume(Thread thread) -{ - /* .error.resume */ - /* If the previous suspend failed (thread->mfc == NULL), */ - /* or in the error case (PThreadextResume returning ResFAIL), */ - /* assume the thread has been destroyed. */ - /* In which case we simply continue. */ - if(thread->mfc != NULL) { - (void)PThreadextResume(&thread->thrextStruct); - thread->mfc = NULL; - } -} - -void ThreadRingResume(Ring threadRing) -{ - mapThreadRing(threadRing, threadResume); -} - - -/* ThreadRingThread -- return the thread at the given ring element */ - -Thread ThreadRingThread(Ring threadRing) -{ - Thread thread; - AVERT(Ring, threadRing); - thread = RING_ELT(Thread, arenaRing, threadRing); - AVERT(Thread, thread); - return thread; -} - - -/* ThreadArena -- get the arena of a thread - * - * Must be thread-safe. See . - */ - -Arena ThreadArena(Thread thread) -{ - /* Can't check thread as that would not be thread-safe. */ - return thread->arena; -} - - -/* ThreadScan -- scan the state of a thread (stack and regs) */ - -Res ThreadScan(ScanState ss, Thread thread, void *stackBot) -{ - pthread_t self; - Res res; - - AVERT(Thread, thread); - self = pthread_self(); - if(pthread_equal(self, thread->id)) { - /* scan this thread's stack */ - res = StackScan(ss, stackBot); - if(res != ResOK) - return res; - } else { - MutatorFaultContext mfc; - Addr *stackBase, *stackLimit, stackPtr; - - mfc = thread->mfc; - if(mfc == NULL) { - /* .error.suspend */ - /* We assume that the thread must have been destroyed. */ - /* We ignore the situation by returning immediately. */ - return ResOK; - } - - stackPtr = MutatorFaultContextSP(mfc); - /* .stack.align */ - stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); - stackLimit = (Addr *)stackBot; - if (stackBase >= stackLimit) - return ResOK; /* .stack.below-bottom */ - - /* scan stack inclusive of current sp and exclusive of - * stackBot (.stack.full-descend) - */ - res = TraceScanAreaTagged(ss, stackBase, stackLimit); - if(res != ResOK) - return res; - - /* scan the registers in the mutator fault context */ - res = MutatorFaultContextScan(ss, mfc); - if(res != ResOK) - return res; - } - - return ResOK; -} - - -/* ThreadDescribe -- describe a thread */ - -Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) -{ - Res res; - - res = WriteF(stream, - "Thread $P ($U) {\n", (WriteFP)thread, (WriteFU)thread->serial, - " arena $P ($U)\n", - (WriteFP)thread->arena, (WriteFU)thread->arena->serial, - " id $U\n", (WriteFU)thread->id, - "} Thread $P ($U)\n", (WriteFP)thread, (WriteFU)thread->serial, - NULL); - if(res != ResOK) - return res; - - return ResOK; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/thw3.c b/mps/code/thw3.c deleted file mode 100644 index 250951018da..00000000000 --- a/mps/code/thw3.c +++ /dev/null @@ -1,273 +0,0 @@ -/* thw3i3.c: WIN32 THREAD MANAGER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * Implements thread registration, suspension, and stack - * scanning. See . - * - * This supports the along with or - * - * .thread.id: The thread id is used to identify the current thread. - * .thread.handle: The thread handle needs the enough access to - * be able to suspend threads and to get their context. i.e. - * .thread.handle.susp-res: THREAD_SUSPEND_RESUME access - * .thread.handle.get-context: THREAD_GET_CONTEXT access - * An appropriate handle is created on registration. - * - * - * ASSUMPTIONS - * - * .error: some major errors are assumed not to happen. - * .error.close-handle: CloseHandle is assumed to succeed. - * - * Other errors are assumed to only happen in certain circumstances. - * .error.resume: ResumeThread is assumed to succeed unless the thread - * has been destroyed (in fact, perversely, it appears to succeeed even - * when the thread has been destroyed). - * .error.suspend: SuspendThread is assumed to succeed unless the thread - * has been destroyed. - * - * - * .nt: uses Win32 specific stuff - * HANDLE - * DWORD - * GetCurrentProcess - * DuplicateHandle - * THREAD_SUSPEND_RESUME - * GetCurrentThreadId - * CloseHandle - * SuspendThread - * ResumeThread - * - */ - -#include "mpm.h" - -#if !defined(MPS_OS_W3) /* .nt */ -#error "Compiling thw3 when MPS_OS_W3 not defined." -#endif - -#include "thw3.h" - -#include "mpswin.h" - -SRCID(thw3, "$Id$"); - - -Bool ThreadCheck(Thread thread) -{ - CHECKS(Thread, thread); - CHECKU(Arena, thread->arena); - CHECKL(thread->serial < thread->arena->threadSerial); - CHECKL(RingCheck(&thread->arenaRing)); - return TRUE; -} - - -Bool ThreadCheckSimple(Thread thread) -{ - CHECKS(Thread, thread); - return TRUE; -} - - -Res ThreadRegister(Thread *threadReturn, Arena arena) -{ - Res res; - Thread thread; - HANDLE procHandle; - BOOL b; - void *p; - - AVER(threadReturn != NULL); - AVERT(Arena, arena); - - res = ControlAlloc(&p, arena, sizeof(ThreadStruct), - /* withReservoirPermit */ FALSE); - if(res != ResOK) - return res; - thread = (Thread)p; /* avoid pun */ - - /* Duplicate handle gives us a new handle with updated privileges. - * .thread.handle describes the ones needed. - */ - procHandle = GetCurrentProcess(); - - b = DuplicateHandle(procHandle, GetCurrentThread(), procHandle, - &thread->handle, - THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT, - FALSE, 0); - if(!b) - return ResRESOURCE; - - thread->id = GetCurrentThreadId(); - - RingInit(&thread->arenaRing); - - thread->sig = ThreadSig; - thread->serial = arena->threadSerial; - ++arena->threadSerial; - thread->arena = arena; - - AVERT(Thread, thread); - - RingAppend(ArenaThreadRing(arena), &thread->arenaRing); - - *threadReturn = thread; - return ResOK; -} - -void ThreadDeregister(Thread thread, Arena arena) -{ - Bool b; - - AVERT(Thread, thread); - AVERT(Arena, arena); - - RingRemove(&thread->arenaRing); - - thread->sig = SigInvalid; - - RingFinish(&thread->arenaRing); - - b = CloseHandle(thread->handle); - AVER(b); /* .error.close-handle */ - - ControlFree(arena, thread, sizeof(ThreadStruct)); -} - - -/* Map over threads on ring calling f on each one except the - * current thread. - */ -static void mapThreadRing(Ring ring, void (*f)(Thread thread)) -{ - Ring node; - DWORD id; - - id = GetCurrentThreadId(); - node = RingNext(ring); - while(node != ring) { - Ring next = RingNext(node); - Thread thread; - - thread = RING_ELT(Thread, arenaRing, node); - AVERT(Thread, thread); - if(id != thread->id) /* .thread.id */ - (*f)(thread); - - node = next; - } -} - -static void suspend(Thread thread) -{ - /* .thread.handle.susp-res */ - /* .error.suspend */ - /* In the error case (SuspendThread returning 0xFFFFFFFF), we */ - /* assume the thread has been destroyed (as part of process shutdown). */ - /* In which case we simply continue. */ - /* [GetLastError appears to return 5 when SuspendThread is called */ - /* on a destroyed thread, but I'm not sufficiently confident of this */ - /* to check -- drj 1998-04-09] */ - (void)SuspendThread(thread->handle); -} - -void ThreadRingSuspend(Ring ring) -{ - mapThreadRing(ring, suspend); -} - -static void resume(Thread thread) -{ - /* .thread.handle.susp-res */ - /* .error.resume */ - /* In the error case (ResumeThread returning 0xFFFFFFFF), we */ - /* assume the thread has been destroyed (as part of process shutdown). */ - /* In which case we simply continue. */ - (void)ResumeThread(thread->handle); -} - -void ThreadRingResume(Ring ring) -{ - mapThreadRing(ring, resume); -} - - -Thread ThreadRingThread(Ring threadRing) -{ - Thread thread; - AVERT(Ring, threadRing); - thread = RING_ELT(Thread, arenaRing, threadRing); - AVERT(Thread, thread); - return thread; -} - -/* Must be thread-safe. See . */ -Arena ThreadArena(Thread thread) -{ - /* Can't AVER thread as that would not be thread-safe */ - /* AVERT(Thread, thread); */ - return thread->arena; -} - -Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) -{ - Res res; - - res = WriteF(stream, - "Thread $P ($U) {\n", (WriteFP)thread, (WriteFU)thread->serial, - " arena $P ($U)\n", - (WriteFP)thread->arena, (WriteFU)thread->arena->serial, - " handle $W\n", (WriteFW)thread->handle, - " id $U\n", (WriteFU)thread->id, - "} Thread $P ($U)\n", (WriteFP)thread, (WriteFU)thread->serial, - NULL); - if(res != ResOK) - return res; - - return ResOK; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/thw3.h b/mps/code/thw3.h deleted file mode 100644 index 7e3cd68e2f1..00000000000 --- a/mps/code/thw3.h +++ /dev/null @@ -1,75 +0,0 @@ -/* thw3.h: WIN32 THREAD MANAGER HEADER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * This is used in and and - * - * .nt: uses Win32 specific stuff - * HANDLE - * DWORD - */ - -#ifndef thw3_h -#define thw3_h - -#include "mpm.h" - -#if !defined(MPS_OS_W3) /* .nt */ -#error "Compiling thw3 when MPS_OS_W3 not defined." -#endif - -#include "mpswin.h" - -typedef struct mps_thr_s { /* Win32 thread structure */ - Sig sig; /* */ - Serial serial; /* from arena->threadSerial */ - Arena arena; /* owning arena */ - RingStruct arenaRing; /* threads attached to arena */ - HANDLE handle; /* Handle of thread, see - * */ - DWORD id; /* Thread id of thread */ -} ThreadStruct; - -#endif /* thw3_h */ - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/thw3i3.c b/mps/code/thw3i3.c deleted file mode 100644 index 3e2e6ee1a5c..00000000000 --- a/mps/code/thw3i3.c +++ /dev/null @@ -1,168 +0,0 @@ -/* thw3i3.c: WIN32 THREAD MANAGER x86 - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * Implements thread stack scanning. See . - * - * This supports the together with - * - * .thread.id: The thread id is used to identify the current thread. - * - * - * ASSUMPTIONS - * - * .error: some major errors are assumed not to happen. - * - * Other errors are assumed to only happen in certain circumstances. - * .error.get-context: GetThreadContext is assumed to succeed unless the - * thread has been destroyed. - * - * .stack.full-descend: assumes full descending stack. - * i.e. stack pointer points to the last allocated location; - * stack grows downwards. - * - * .stack.below-bottom: it's legal for the stack pointer to be at a - * higher address than the registered bottom of stack. This might - * happen if the stack of another thread doesn't contain any frames - * belonging to the client language. In this case, the stack should - * not be scanned. - * - * .stack.align: assume roots on the stack are always word-aligned, - * but don't assume that the stack pointer is necessarily - * word-aligned at the time of reading the context of another thread. - * - * .i3: assumes MPS_ARCH_I3 - * .i3.sp: The sp in the context is Esp - * .i3.context: Esp is in control context so .context.sp holds - * The root registers are Edi, Esi, Ebx, Edx, Ecx, Eax - * these are given by CONTEXT_INTEGER, so .context.regroots holds. - * - * .nt: uses Win32 specific stuff - * HANDLE - * DWORD - * GetCurrentThreadId - * CONTEXT - * CONTEXT_CONTROL | CONTEXT_INTEGER - * GetThreadContext - * - * .context: ContextFlags determine what is recorded by - * GetThreadContext. This should be set to whichever bits of the - * context that need to be recorded. This should include: - * .context.sp: sp assumed to be recorded by CONTEXT_CONTROL. - * .context.regroots: assumed to be recorded by CONTEXT_INTEGER. - * see winnt.h for description of CONTEXT and ContextFlags. - */ - -#include "mpm.h" - -#if !defined(MPS_OS_W3) || !defined(MPS_ARCH_I3) /* .i3 .nt */ -#error "Compiling thw3i3 when MPS_OS_W3 or MPS_ARCH_I3 not defined." -#endif - -#include "thw3.h" - -#include "mpswin.h" - -SRCID(thw3i3, "$Id$"); - - -Res ThreadScan(ScanState ss, Thread thread, void *stackBot) -{ - DWORD id; - Res res; - - id = GetCurrentThreadId(); - - if(id != thread->id) { /* .thread.id */ - CONTEXT context; - BOOL success; - Addr *stackBase, *stackLimit, stackPtr; - - /* scan stack and register roots in other threads */ - - /* This dumps the relevent registers into the context */ - /* .context.flags */ - context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; - /* .thread.handle.get-context */ - success = GetThreadContext(thread->handle, &context); - if(!success) { - /* .error.get-context */ - /* We assume that the thread must have been destroyed. */ - /* We ignore the situation by returning immediately. */ - return ResOK; - } - - stackPtr = (Addr)context.Esp; /* .i3.sp */ - /* .stack.align */ - stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); - stackLimit = (Addr *)stackBot; - if (stackBase >= stackLimit) - return ResOK; /* .stack.below-bottom */ - - /* scan stack inclusive of current sp and exclusive of - * stackBot (.stack.full-descend) - */ - res = TraceScanAreaTagged(ss, stackBase, stackLimit); - if(res != ResOK) - return res; - - /* (.context.regroots) - * This scans the root registers (.context.regroots). It also - * unecessarily scans the rest of the context. The optimisation - * to scan only relevent parts would be machine dependent. - */ - res = TraceScanAreaTagged(ss, (Addr *)&context, - (Addr *)((char *)&context + sizeof(CONTEXT))); - if(res != ResOK) - return res; - - } else { /* scan this thread's stack */ - res = StackScan(ss, stackBot); - if(res != ResOK) - return res; - } - - return ResOK; -} - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/thw3i6.c b/mps/code/thw3i6.c deleted file mode 100644 index 86e5f6edc8f..00000000000 --- a/mps/code/thw3i6.c +++ /dev/null @@ -1,168 +0,0 @@ -/* thw3i3.c: WIN32 THREAD MANAGER x86 - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * Implements thread stack scanning. See . - * - * This supports the together with - * - * .thread.id: The thread id is used to identify the current thread. - * - * - * ASSUMPTIONS - * - * .error: some major errors are assumed not to happen. - * - * Other errors are assumed to only happen in certain circumstances. - * .error.get-context: GetThreadContext is assumed to succeed unless the - * thread has been destroyed. - * - * .stack.full-descend: assumes full descending stack. - * i.e. stack pointer points to the last allocated location; - * stack grows downwards. - * - * .stack.below-bottom: it's legal for the stack pointer to be at a - * higher address than the registered bottom of stack. This might - * happen if the stack of another thread doesn't contain any frames - * belonging to the client language. In this case, the stack should - * not be scanned. - * - * .stack.align: assume roots on the stack are always word-aligned, - * but don't assume that the stack pointer is necessarily - * word-aligned at the time of reading the context of another thread. - * - * .i6: assumes MPS_ARCH_I6 - * .i6.sp: The sp in the context is Rsp - * .i6.context: Rsp is in control context so .context.sp holds - * The root registers are Rdi, Rsi, Rbx, Rbp, Rdx, Rcx, Rax, R8 - R15 - * these are given by CONTEXT_INTEGER, so .context.regroots holds. - * - * .nt: uses Win32 specific stuff - * HANDLE - * DWORD - * GetCurrentThreadId - * CONTEXT - * CONTEXT_CONTROL | CONTEXT_INTEGER - * GetThreadContext - * - * .context: ContextFlags determine what is recorded by - * GetThreadContext. This should be set to whichever bits of the - * context that need to be recorded. This should include: - * .context.sp: sp assumed to be recorded by CONTEXT_CONTROL. - * .context.regroots: assumed to be recorded by CONTEXT_INTEGER. - * see winnt.h for description of CONTEXT and ContextFlags. - */ - -#include "mpm.h" - -#if !defined(MPS_OS_W3) || !defined(MPS_ARCH_I6) /* .i6 .nt */ -#error "Compiling thw3i6 when MPS_OS_W3 or MPS_ARCH_I6 not defined." -#endif - -#include "thw3.h" - -#include "mpswin.h" - -SRCID(thw3i6, "$Id$"); - - -Res ThreadScan(ScanState ss, Thread thread, void *stackBot) -{ - DWORD id; - Res res; - - id = GetCurrentThreadId(); - - if(id != thread->id) { /* .thread.id */ - CONTEXT context; - BOOL success; - Addr *stackBase, *stackLimit, stackPtr; - - /* scan stack and register roots in other threads */ - - /* This dumps the relevent registers into the context */ - /* .context.flags */ - context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; - /* .thread.handle.get-context */ - success = GetThreadContext(thread->handle, &context); - if(!success) { - /* .error.get-context */ - /* We assume that the thread must have been destroyed. */ - /* We ignore the situation by returning immediately. */ - return ResOK; - } - - stackPtr = (Addr)context.Rsp; /* .i6.sp */ - /* .stack.align */ - stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); - stackLimit = (Addr *)stackBot; - if (stackBase >= stackLimit) - return ResOK; /* .stack.below-bottom */ - - /* scan stack inclusive of current sp and exclusive of - * stackBot (.stack.full-descend) - */ - res = TraceScanAreaTagged(ss, stackBase, stackLimit); - if(res != ResOK) - return res; - - /* (.context.regroots) - * This scans the root registers (.context.regroots). It also - * unecessarily scans the rest of the context. The optimisation - * to scan only relevent parts would be machine dependent. - */ - res = TraceScanAreaTagged(ss, (Addr *)&context, - (Addr *)((char *)&context + sizeof(CONTEXT))); - if(res != ResOK) - return res; - - } else { /* scan this thread's stack */ - res = StackScan(ss, stackBot); - if(res != ResOK) - return res; - } - - return ResOK; -} - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/trace.c b/mps/code/trace.c deleted file mode 100644 index e7ab41c8d80..00000000000 --- a/mps/code/trace.c +++ /dev/null @@ -1,2042 +0,0 @@ -/* trace.c: GENERIC TRACER IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2001-2003, 2006, 2007 Ravenbrook Limited. - * See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * .design: . */ - -#include "chain.h" -#include "mpm.h" -#include /* for LONG_MAX */ - -SRCID(trace, "$Id$"); - -/* Forward declarations */ -Rank traceBand(Trace); -Bool traceBandAdvance(Trace); -Bool traceBandFirstStretch(Trace); -void traceBandFirstStretchDone(Trace); -DIAG_DECL( static void traceFindGrey_diag(Bool found, Rank rank); ) - -/* Types */ - -enum { - traceAccountingPhaseRootScan = 1, - traceAccountingPhaseSegScan, - traceAccountingPhaseSingleScan -}; -typedef int traceAccountingPhase; - -/* ScanStateCheck -- check consistency of a ScanState object */ - -Bool ScanStateCheck(ScanState ss) -{ - TraceId ti; - Trace trace; - ZoneSet white; - - CHECKS(ScanState, ss); - CHECKL(FUNCHECK(ss->fix)); - /* Can't check ss->fixClosure. */ - CHECKL(ScanStateZoneShift(ss) == ss->arena->zoneShift); - white = ZoneSetEMPTY; - TRACE_SET_ITER(ti, trace, ss->traces, ss->arena) - white = ZoneSetUnion(white, ss->arena->trace[ti].white); - TRACE_SET_ITER_END(ti, trace, ss->traces, ss->arena); - CHECKL(ScanStateWhite(ss) == white); - CHECKU(Arena, ss->arena); - /* Summaries could be anything, and can't be checked. */ - CHECKL(TraceSetCheck(ss->traces)); - CHECKL(TraceSetSuper(ss->arena->busyTraces, ss->traces)); - CHECKL(RankCheck(ss->rank)); - CHECKL(BoolCheck(ss->wasMarked)); - /* @@@@ checks for counts missing */ - return TRUE; -} - - -/* ScanStateInit -- Initialize a ScanState object */ - -void ScanStateInit(ScanState ss, TraceSet ts, Arena arena, - Rank rank, ZoneSet white) -{ - TraceId ti; - Trace trace; - - AVER(TraceSetCheck(ts)); - AVERT(Arena, arena); - AVER(RankCheck(rank)); - /* white is arbitrary and can't be checked */ - - /* NOTE: We can only currently support scanning for a set of traces with - the same fix method and closure. To remove this restriction, - it would be necessary to dispatch to the fix methods of sets of traces - in TraceFix. */ - ss->fix = NULL; - ss->fixClosure = NULL; - TRACE_SET_ITER(ti, trace, ts, arena) { - if (ss->fix == NULL) { - ss->fix = trace->fix; - ss->fixClosure = trace->fixClosure; - } else { - AVER(ss->fix == trace->fix); - AVER(ss->fixClosure == trace->fixClosure); - } - } TRACE_SET_ITER_END(ti, trace, ts, arena); - AVER(ss->fix != NULL); - - /* If the fix method is the normal GC fix, then we optimise the test for - whether it's an emergency or not by updating the dispatch here, once. */ - if (ss->fix == PoolFix && ArenaEmergency(arena)) - ss->fix = PoolFixEmergency; - - ss->rank = rank; - ss->traces = ts; - ScanStateSetZoneShift(ss, arena->zoneShift); - ScanStateSetUnfixedSummary(ss, RefSetEMPTY); - ss->fixedSummary = RefSetEMPTY; - ss->arena = arena; - ss->wasMarked = TRUE; - ScanStateSetWhite(ss, white); - STATISTIC(ss->fixRefCount = (Count)0); - STATISTIC(ss->segRefCount = (Count)0); - STATISTIC(ss->whiteSegRefCount = (Count)0); - STATISTIC(ss->nailCount = (Count)0); - STATISTIC(ss->snapCount = (Count)0); - STATISTIC(ss->forwardedCount = (Count)0); - ss->forwardedSize = (Size)0; /* see .message.data */ - STATISTIC(ss->preservedInPlaceCount = (Count)0); - ss->preservedInPlaceSize = (Size)0; /* see .message.data */ - STATISTIC(ss->copiedSize = (Size)0); - ss->scannedSize = (Size)0; /* see .workclock */ - ss->sig = ScanStateSig; - - AVERT(ScanState, ss); -} - - -/* ScanStateFinish -- Finish a ScanState object */ - -void ScanStateFinish(ScanState ss) -{ - AVERT(ScanState, ss); - ss->sig = SigInvalid; -} - - -/* TraceIdCheck -- check that a TraceId is valid */ - -Bool TraceIdCheck(TraceId ti) -{ - CHECKL(ti < TraceLIMIT); - UNUSED(ti); /* */ - return TRUE; -} - - -/* TraceSetCheck -- check that a TraceSet is valid */ - -Bool TraceSetCheck(TraceSet ts) -{ - CHECKL(ts < ((ULongest)1 << TraceLIMIT)); - UNUSED(ts); /* */ - return TRUE; -} - - -/* TraceCheck -- check consistency of Trace object */ - -Bool TraceCheck(Trace trace) -{ - CHECKS(Trace, trace); - CHECKU(Arena, trace->arena); - CHECKL(TraceIdCheck(trace->ti)); - CHECKL(trace == &trace->arena->trace[trace->ti]); - CHECKL(TraceSetIsMember(trace->arena->busyTraces, trace)); - CHECKL(ZoneSetSub(trace->mayMove, trace->white)); - /* Use trace->state to check more invariants. */ - switch(trace->state) { - case TraceINIT: - /* @@@@ What can be checked here? */ - break; - - case TraceUNFLIPPED: - CHECKL(!TraceSetIsMember(trace->arena->flippedTraces, trace)); - /* @@@@ Assert that mutator is grey for trace. */ - break; - - case TraceFLIPPED: - CHECKL(TraceSetIsMember(trace->arena->flippedTraces, trace)); - /* @@@@ Assert that mutator is black for trace. */ - break; - - case TraceRECLAIM: - CHECKL(TraceSetIsMember(trace->arena->flippedTraces, trace)); - /* @@@@ Assert that grey set is empty for trace. */ - break; - - case TraceFINISHED: - CHECKL(TraceSetIsMember(trace->arena->flippedTraces, trace)); - /* @@@@ Assert that grey and white sets is empty for trace. */ - break; - - default: - NOTREACHED; - break; - } - /* Valid values for band depend on state. */ - if(trace->state == TraceFLIPPED) { - CHECKL(RankCheck(trace->band)); - } - if(trace->chain != NULL) { - CHECKU(Chain, trace->chain); - } - CHECKL(FUNCHECK(trace->fix)); - /* Can't check trace->fixClosure. */ - - /* @@@@ checks for counts missing */ - - /* check pre-allocated messages for this traceid */ - CHECKL(TraceIdMessagesCheck(trace->arena, trace->ti)); - - return TRUE; -} - -/* traceBand - current band of the trace. - * - * The current band is the band currently being discovered. Each band - * corresponds to a rank. The R band is all objects that are reachable - * only by tracing references of rank R or earlier _and_ are not in some - * earlier band (thus, the bands are disjoint). Whilst a particular - * band is current all the objects that become marked are the objects in - * that band. - */ -Rank traceBand(Trace trace) -{ - AVERT(Trace, trace); - - return trace->band; -} - -/* traceBandAdvance - advance to next band. - * - * Advances (increments) the current band to the next band and returns TRUE - * if possible; - * otherwise, there are no more bands, so resets the band state and - * returns FALSE. - */ -Bool traceBandAdvance(Trace trace) -{ - AVER(trace->state == TraceFLIPPED); - - ++trace->band; - trace->firstStretch = TRUE; - if(trace->band >= RankLIMIT) { - trace->band = RankAMBIG; - return FALSE; - } - EVENT3(TraceBandAdvance, trace->arena, trace->ti, trace->band); - return TRUE; -} - -/* traceBandFirstStretch - whether in first stretch or not. - * - * For a band R (see traceBand) the first stretch is defined as all the - * scanning work done up until the first point where we run out of grey - * rank R segments (and either scan something of an earlier rank or - * change bands). - * - * This function returns TRUE whilst we are in the first stretch, FALSE - * otherwise. - * - * Entering the first stretch is automatically performed by - * traceBandAdvance, but finishing it is detected in traceFindGrey. - */ -Bool traceBandFirstStretch(Trace trace) -{ - return trace->firstStretch; -} - -void traceBandFirstStretchDone(Trace trace) -{ - trace->firstStretch = FALSE; -} - -/* traceUpdateCounts - dumps the counts from a ScanState into the Trace */ - -static void traceUpdateCounts(Trace trace, ScanState ss, - traceAccountingPhase phase) -{ - switch(phase) { - case traceAccountingPhaseRootScan: { - trace->rootScanSize += ss->scannedSize; - trace->rootCopiedSize += ss->copiedSize; - STATISTIC(++trace->rootScanCount); - break; - } - case traceAccountingPhaseSegScan: { - trace->segScanSize += ss->scannedSize; /* see .workclock */ - trace->segCopiedSize += ss->copiedSize; - STATISTIC(++trace->segScanCount); - break; - } - case traceAccountingPhaseSingleScan: { - STATISTIC(trace->singleScanSize += ss->scannedSize); - STATISTIC(trace->singleCopiedSize += ss->copiedSize); - break; - } - default: - NOTREACHED; - } - STATISTIC(trace->fixRefCount += ss->fixRefCount); - STATISTIC(trace->segRefCount += ss->segRefCount); - STATISTIC(trace->whiteSegRefCount += ss->whiteSegRefCount); - STATISTIC(trace->nailCount += ss->nailCount); - STATISTIC(trace->snapCount += ss->snapCount); - STATISTIC(trace->forwardedCount += ss->forwardedCount); - trace->forwardedSize += ss->forwardedSize; /* see .message.data */ - STATISTIC(trace->preservedInPlaceCount += ss->preservedInPlaceCount); - trace->preservedInPlaceSize += ss->preservedInPlaceSize; - - return; -} - - -/* traceSetUpdateCounts -- update counts for a set of traces */ - -static void traceSetUpdateCounts(TraceSet ts, Arena arena, ScanState ss, - traceAccountingPhase phase) -{ - TraceId ti; Trace trace; - - AVERT(ScanState, ss); /* check that we're not copying garbage */ - - TRACE_SET_ITER(ti, trace, ts, arena) - traceUpdateCounts(trace, ss, phase); - TRACE_SET_ITER_END(ti, trace, ts, arena); - return; -} - - -/* traceSetWhiteUnion - * - * Returns a ZoneSet describing the union of the white sets of all the - * specified traces. */ - -static ZoneSet traceSetWhiteUnion(TraceSet ts, Arena arena) -{ - TraceId ti; - Trace trace; - ZoneSet white = ZoneSetEMPTY; - - TRACE_SET_ITER(ti, trace, ts, arena) - white = ZoneSetUnion(white, trace->white); - TRACE_SET_ITER_END(ti, trace, ts, arena); - - return white; -} - - -/* TraceAddWhite -- add a segment to the white set of a trace */ - -Res TraceAddWhite(Trace trace, Seg seg) -{ - Res res; - Pool pool; - - AVERT(Trace, trace); - AVERT(Seg, seg); - AVER(!TraceSetIsMember(SegWhite(seg), trace)); /* .start.black */ - - pool = SegPool(seg); - AVERT(Pool, pool); - - /* Give the pool the opportunity to turn the segment white. */ - /* If it fails, unwind. */ - res = PoolWhiten(pool, trace, seg); - if(res != ResOK) - return res; - - /* Add the segment to the approximation of the white set if the */ - /* pool made it white. */ - if(TraceSetIsMember(SegWhite(seg), trace)) { - trace->white = ZoneSetUnion(trace->white, ZoneSetOfSeg(trace->arena, seg)); - /* if the pool is a moving GC, then condemned objects may move */ - if(pool->class->attr & AttrMOVINGGC) { - trace->mayMove = ZoneSetUnion(trace->mayMove, - ZoneSetOfSeg(trace->arena, seg)); - } - } - - return ResOK; -} - - -/* TraceCondemnZones -- condemn all objects in the given zones - * - * TraceCondemnZones is passed a trace in state TraceINIT, and a set of - * objects to condemn. - * - * @@@@ For efficiency, we ought to find the condemned set and the - * foundation in one search of the segment ring. This hasn't been done - * because some pools still use TraceAddWhite for the condemned set. - * - * @@@@ This function would be more efficient if there were a cheaper - * way to select the segments in a particular zone set. */ - -Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) -{ - Seg seg; - Arena arena; - Res res; - - AVERT(Trace, trace); - AVER(condemnedSet != ZoneSetEMPTY); - AVER(trace->state == TraceINIT); - AVER(trace->white == ZoneSetEMPTY); - - arena = trace->arena; - - if(SegFirst(&seg, arena)) { - Addr base; - do { - base = SegBase(seg); - /* Segment should be black now. */ - AVER(!TraceSetIsMember(SegGrey(seg), trace)); - AVER(!TraceSetIsMember(SegWhite(seg), trace)); - - /* A segment can only be white if it is GC-able. */ - /* This is indicated by the pool having the GC attribute */ - /* We only condemn segments that fall entirely within */ - /* the requested zone set. Otherwise, we would bloat the */ - /* foundation to no gain. Note that this doesn't exclude */ - /* any segments from which the condemned set was derived, */ - if((SegPool(seg)->class->attr & AttrGC) != 0 - && ZoneSetSuper(condemnedSet, ZoneSetOfSeg(arena, seg))) { - res = TraceAddWhite(trace, seg); - if(res != ResOK) - return res; - } - } while (SegNext(&seg, arena, base)); - } - - /* The trace's white set must be a subset of the condemned set */ - AVER(ZoneSetSuper(condemnedSet, trace->white)); - - return ResOK; -} - - -/* traceFlipBuffers -- flip all buffers in the arena */ - -static void traceFlipBuffers(Globals arena) -{ - Ring nodep, nextp; - - RING_FOR(nodep, &arena->poolRing, nextp) { - Pool pool = RING_ELT(Pool, arenaRing, nodep); - Ring nodeb, nextb; - - AVERT(Pool, pool); - RING_FOR(nodeb, &pool->bufferRing, nextb) { - BufferFlip(RING_ELT(Buffer, poolRing, nodeb)); - } - } -} - - -/* traceScanRootRes -- scan a root, with result code */ - -static Res traceScanRootRes(TraceSet ts, Rank rank, Arena arena, Root root) -{ - ZoneSet white; - Res res; - ScanStateStruct ss; - - white = traceSetWhiteUnion(ts, arena); - - ScanStateInit(&ss, ts, arena, rank, white); - - res = RootScan(&ss, root); - - traceSetUpdateCounts(ts, arena, &ss, traceAccountingPhaseRootScan); - ScanStateFinish(&ss); - return res; -} - - -/* traceScanRoot - * - * Scan a root, entering emergency mode on allocation failure. - */ - -static Res traceScanRoot(TraceSet ts, Rank rank, Arena arena, Root root) -{ - Res res; - - res = traceScanRootRes(ts, rank, arena, root); - - if (ResIsAllocFailure(res)) { - ArenaSetEmergency(arena, TRUE); - res = traceScanRootRes(ts, rank, arena, root); - /* Should be OK in emergency mode */ - AVER(!ResIsAllocFailure(res)); - } - - return res; -} - - -/* traceFlip -- blacken the mutator */ - -struct rootFlipClosureStruct { - TraceSet ts; - Arena arena; - Rank rank; -}; - -static Res rootFlip(Root root, void *p) -{ - struct rootFlipClosureStruct *rf = (struct rootFlipClosureStruct *)p; - Res res; - - AVERT(Root, root); - AVER(p != NULL); - AVER(TraceSetCheck(rf->ts)); - AVERT(Arena, rf->arena); - AVER(RankCheck(rf->rank)); - - AVER(RootRank(root) <= RankEXACT); /* see .root.rank */ - - if(RootRank(root) == rf->rank) { - res = traceScanRoot(rf->ts, rf->rank, rf->arena, root); - if (res != ResOK) - return res; - } - - return ResOK; -} - - -/* traceFlip -- flip the mutator from grey to black w.r.t. a trace - * - * The main job of traceFlip is to scan references which can't be protected - * from the mutator, changing the colour of the mutator from grey to black - * with respect to a trace. The mutator threads are suspended while this - * is happening, and the mutator perceives an instantaneous change in all - * the references, enforced by the shield (barrier) system. - * - * NOTE: We don't have a way to shield the roots, so they are all scanned - * here. This is a coincidence. There is no theoretical reason that the - * roots have to be scanned at flip time, provided we could protect them - * from the mutator. (The thread registers are unlikely ever to be - * protectable on stock hardware, however, as they were -- kind of -- on - * Lisp machines.) - * - * NOTE: Ambiguous references may only exist in roots, because we can't - * shield the exact roots and defer them for later scanning (after ambiguous - * heap references). - * - * NOTE: We don't support weak or final roots because we can't shield them - * and defer scanning until later. See above. - * - * If roots and segments were more similar, we could melt a lot of these - * problems. - */ - -static Res traceFlip(Trace trace) -{ - Ring node, nextNode; - Arena arena; - Rank rank; - struct rootFlipClosureStruct rfc; - Res res; - - AVERT(Trace, trace); - rfc.ts = TraceSetSingle(trace); - - arena = trace->arena; - rfc.arena = arena; - ShieldSuspend(arena); - - AVER(trace->state == TraceUNFLIPPED); - AVER(!TraceSetIsMember(arena->flippedTraces, trace)); - - EVENT2(TraceFlipBegin, trace, arena); - - traceFlipBuffers(ArenaGlobals(arena)); - - /* Update location dependency structures. */ - /* mayMove is a conservative approximation of the zones of objects */ - /* which may move during this collection. */ - if(trace->mayMove != ZoneSetEMPTY) { - LDAge(arena, trace->mayMove); - } - - /* .root.rank: At the moment we must scan all roots, because we don't have */ - /* a mechanism for shielding them. There can't be any weak or final roots */ - /* either, since we must protect these in order to avoid scanning them too */ - /* early, before the pool contents. @@@@ This isn't correct if there are */ - /* higher ranking roots than data in pools. */ - - for(rank = RankAMBIG; rank <= RankEXACT; ++rank) { - rfc.rank = rank; - res = RootsIterate(ArenaGlobals(arena), rootFlip, (void *)&rfc); - if (res != ResOK) - goto failRootFlip; - } - - /* .flip.alloc: Allocation needs to become black now. While we flip */ - /* at the start, we can get away with always allocating black. This */ - /* needs to change when we flip later (i.e. have a read-barrier */ - /* collector), so that we allocate grey or white before the flip */ - /* and black afterwards. For instance, see */ - /* . */ - /* (surely we mean "write-barrier" not "read-barrier" above? */ - /* drj 2003-02-19) */ - - /* Now that the mutator is black we must prevent it from reading */ - /* grey objects so that it can't obtain white pointers. This is */ - /* achieved by read protecting all segments containing objects */ - /* which are grey for any of the flipped traces. */ - for(rank = 0; rank < RankLIMIT; ++rank) - RING_FOR(node, ArenaGreyRing(arena, rank), nextNode) { - Seg seg = SegOfGreyRing(node); - if(TraceSetInter(SegGrey(seg), arena->flippedTraces) == TraceSetEMPTY - && TraceSetIsMember(SegGrey(seg), trace)) - ShieldRaise(arena, seg, AccessREAD); - } - - /* @@@@ When write barrier collection is implemented, this is where */ - /* write protection should be removed for all segments which are */ - /* no longer blacker than the mutator. Possibly this can be done */ - /* lazily as they are touched. */ - - /* Mark the trace as flipped. */ - trace->state = TraceFLIPPED; - arena->flippedTraces = TraceSetAdd(arena->flippedTraces, trace); - - EVENT2(TraceFlipEnd, trace, arena); - - ShieldResume(arena); - return ResOK; - -failRootFlip: - ShieldResume(arena); - return res; -} - -/* traceCopySizes -- preserve size information for later use - * - * A PoolGen's newSize is important information that we want to emit in - * a diagnostic message at TraceStart. In order to do that we must copy - * the information before Whiten changes it. This function does that. - */ - -static void traceCopySizes(Trace trace) -{ - Ring node, nextNode; - Index i; - Arena arena = trace->arena; - - RING_FOR(node, &arena->chainRing, nextNode) { - Chain chain = RING_ELT(Chain, chainRing, node); - - for(i = 0; i < chain->genCount; ++i) { - Ring n, nn; - GenDesc desc = &chain->gens[i]; - RING_FOR(n, &desc->locusRing, nn) { - PoolGen gen = RING_ELT(PoolGen, genRing, n); - gen->newSizeAtCreate = gen->newSize; - } - } - } - return; -} - -/* TraceCreate -- create a Trace object - * - * Allocates and initializes a new Trace object with a TraceId which is - * not currently active. - * - * Returns ResLIMIT if there aren't any available trace IDs. - * - * Trace objects are allocated directly from a small array in the arena - * structure which is indexed by the TraceId. This is so that it's - * always possible to start a trace (provided there's a free TraceId) - * even if there's no available memory. - * - * This code is written to be adaptable to allocating Trace objects - * dynamically. */ - -Res TraceCreate(Trace *traceReturn, Arena arena, int why) -{ - TraceId ti; - Trace trace; - - AVER(traceReturn != NULL); - AVERT(Arena, arena); - - /* Find a free trace ID */ - TRACE_SET_ITER(ti, trace, TraceSetComp(arena->busyTraces), arena) - goto found; - TRACE_SET_ITER_END(ti, trace, TraceSetComp(arena->busyTraces), arena); - return ResLIMIT; /* no trace IDs available */ - -found: - trace = ArenaTrace(arena, ti); - AVER(trace->sig == SigInvalid); /* */ - - trace->arena = arena; - trace->why = why; - trace->white = ZoneSetEMPTY; - trace->mayMove = ZoneSetEMPTY; - trace->ti = ti; - trace->state = TraceINIT; - trace->band = RankAMBIG; /* Required to be the earliest rank. */ - trace->fix = PoolFix; - trace->fixClosure = NULL; - trace->chain = NULL; - STATISTIC(trace->preTraceArenaReserved = ArenaReserved(arena)); - trace->condemned = (Size)0; /* nothing condemned yet */ - trace->notCondemned = (Size)0; - trace->foundation = (Size)0; /* nothing grey yet */ - trace->rate = (Size)0; /* no scanning to be done yet */ - STATISTIC(trace->greySegCount = (Count)0); - STATISTIC(trace->greySegMax = (Count)0); - STATISTIC(trace->rootScanCount = (Count)0); - trace->rootScanSize = (Size)0; - trace->rootCopiedSize = (Size)0; - STATISTIC(trace->segScanCount = (Count)0); - trace->segScanSize = (Size)0; /* see .workclock */ - trace->segCopiedSize = (Size)0; - STATISTIC(trace->singleScanCount = (Count)0); - STATISTIC(trace->singleScanSize = (Size)0); - STATISTIC(trace->singleCopiedSize = (Size)0); - STATISTIC(trace->fixRefCount = (Count)0); - STATISTIC(trace->segRefCount = (Count)0); - STATISTIC(trace->whiteSegRefCount = (Count)0); - STATISTIC(trace->nailCount = (Count)0); - STATISTIC(trace->snapCount = (Count)0); - STATISTIC(trace->readBarrierHitCount = (Count)0); - STATISTIC(trace->pointlessScanCount = (Count)0); - STATISTIC(trace->forwardedCount = (Count)0); - trace->forwardedSize = (Size)0; /* see .message.data */ - STATISTIC(trace->preservedInPlaceCount = (Count)0); - trace->preservedInPlaceSize = (Size)0; /* see .message.data */ - STATISTIC(trace->reclaimCount = (Count)0); - STATISTIC(trace->reclaimSize = (Size)0); - trace->sig = TraceSig; - arena->busyTraces = TraceSetAdd(arena->busyTraces, trace); - AVERT(Trace, trace); - - /* We suspend the mutator threads so that the PoolWhiten methods */ - /* can calculate white sets without the mutator allocating in */ - /* buffers under our feet. */ - /* @@@@ This is a short-term fix for request.dylan.160098. */ - ShieldSuspend(arena); - - traceCopySizes(trace); - - *traceReturn = trace; - return ResOK; -} - - -/* TraceDestroy -- destroy a trace object - * - * Finish and deallocate a Trace object, freeing up a TraceId. - * - * This code does not allow a Trace to be destroyed while it is active. - * It would be possible to allow this, but the colours of segments - * etc. would need to be reset to black. This also means the error - * paths in this file don't work. @@@@ */ - -void TraceDestroy(Trace trace) -{ - AVERT(Trace, trace); - AVER(trace->state == TraceFINISHED); - - if(trace->chain == NULL) { - Ring chainNode, nextChainNode; - - /* Notify all the chains. */ - RING_FOR(chainNode, &trace->arena->chainRing, nextChainNode) { - Chain chain = RING_ELT(Chain, chainRing, chainNode); - - ChainEndGC(chain, trace); - } - } else { - ChainEndGC(trace->chain, trace); - } - - STATISTIC_STAT(EVENT13 - (TraceStatScan, trace, - trace->rootScanCount, trace->rootScanSize, - trace->rootCopiedSize, - trace->segScanCount, trace->segScanSize, - trace->segCopiedSize, - trace->singleScanCount, trace->singleScanSize, - trace->singleCopiedSize, - trace->readBarrierHitCount, trace->greySegMax, - trace->pointlessScanCount)); - STATISTIC_STAT(EVENT10 - (TraceStatFix, trace, - trace->fixRefCount, trace->segRefCount, - trace->whiteSegRefCount, - trace->nailCount, trace->snapCount, - trace->forwardedCount, trace->forwardedSize, - trace->preservedInPlaceCount, - trace->preservedInPlaceSize)); - STATISTIC_STAT(EVENT3 - (TraceStatReclaim, trace, - trace->reclaimCount, trace->reclaimSize)); - - trace->sig = SigInvalid; - trace->arena->busyTraces = TraceSetDel(trace->arena->busyTraces, trace); - trace->arena->flippedTraces = TraceSetDel(trace->arena->flippedTraces, trace); - EVENT1(TraceDestroy, trace); -} - - -/* traceReclaim -- reclaim the remaining objects white for this trace */ - -static void traceReclaim(Trace trace) -{ - Arena arena; - Seg seg; - Ring node, nextNode; - - AVER(trace->state == TraceRECLAIM); - - EVENT1(TraceReclaim, trace); - arena = trace->arena; - if(SegFirst(&seg, arena)) { - Addr base; - do { - base = SegBase(seg); - /* There shouldn't be any grey stuff left for this trace. */ - AVER_CRITICAL(!TraceSetIsMember(SegGrey(seg), trace)); - - if(TraceSetIsMember(SegWhite(seg), trace)) { - AVER_CRITICAL((SegPool(seg)->class->attr & AttrGC) != 0); - STATISTIC(++trace->reclaimCount); - PoolReclaim(SegPool(seg), trace, seg); - - /* If the segment still exists, it should no longer be white. */ - /* Note that the seg returned by this SegOfAddr may not be */ - /* the same as the one above, but in that case it's new and */ - /* still shouldn't be white for this trace. */ - - /* The code from the class-specific reclaim methods to */ - /* unwhiten the segment could in fact be moved here. */ - { - Seg nonWhiteSeg = NULL; /* prevents compiler warning */ - AVER_CRITICAL(!(SegOfAddr(&nonWhiteSeg, arena, base) - && TraceSetIsMember(SegWhite(nonWhiteSeg), trace))); - UNUSED(nonWhiteSeg); /* */ - } - } - } while(SegNext(&seg, arena, base)); - } - - trace->state = TraceFINISHED; - - /* Call each pool's TraceEnd method -- do end-of-trace work */ - RING_FOR(node, &ArenaGlobals(arena)->poolRing, nextNode) { - Pool pool = RING_ELT(Pool, arenaRing, node); - PoolTraceEnd(pool, trace); - } - - ArenaCompact(arena, trace); /* let arenavm drop chunks */ - - TracePostMessage(trace); /* trace end */ - /* Immediately pre-allocate messages for next time; failure is okay */ - (void)TraceIdMessagesCreate(arena, trace->ti); -} - -/* TraceRankForAccess -- Returns rank to scan at if we hit a barrier. - * - * We assume a single trace as otherwise we need to implement rank - * filters on scanning. - * - * .scan.conservative: It's safe to scan at EXACT unless the band is - * WEAK and in that case the segment should be weak. - * - * If the trace band is EXACT then we scan EXACT. This might prevent - * finalisation messages and may preserve objects pointed to only by weak - * references but tough luck -- the mutator wants to look. - * - * If the trace band is FINAL and the segment is FINAL, we scan it FINAL. - * Any objects not yet preserved deserve to die, and we're only giving - * them a temporary reprieve. All the objects on the segment should be FINAL, - * otherwise they might get sent finalization messages. - * - * If the trace band is FINAL, and the segment is not FINAL, we scan at EXACT. - * This is safe to do for FINAL and WEAK references. - * - * If the trace band is WEAK then the segment must be weak only, and we - * scan at WEAK. All other segments for this trace should be scanned by now. - * We must scan at WEAK to avoid bringing any objects back to life. - * - * See the message - * for a description of these semantics. - */ -Rank TraceRankForAccess(Arena arena, Seg seg) -{ - TraceSet ts; - Trace trace; - TraceId ti; - Rank band; - RankSet rankSet; - - AVERT(Arena, arena); - AVERT(Seg, seg); - - band = RankAMBIG; /* initialize band to avoid warning */ - ts = arena->flippedTraces; - AVER(TraceSetIsSingle(ts)); - TRACE_SET_ITER(ti, trace, ts, arena) - band = traceBand(trace); - TRACE_SET_ITER_END(ti, trace, ts, arena); - rankSet = SegRankSet(seg); - switch(band) { - case RankAMBIG: - NOTREACHED; - break; - case RankEXACT: - return RankEXACT; - case RankFINAL: - if(rankSet == RankSetSingle(RankFINAL)) { - return RankFINAL; - } - /* It's safe to scan at exact in the final band so do so if there are - * any non-final references. */ - return RankEXACT; - case RankWEAK: - AVER(rankSet == RankSetSingle(RankWEAK)); - return RankWEAK; - default: - NOTREACHED; - break; - } - NOTREACHED; - return RankEXACT; -} - -/* traceFindGrey -- find a grey segment - * - * This function finds the next segment to scan. It does this according - * to the current band of the trace. See design/trace/ - * - * This code also performs various checks about the ranks of the object - * graph. Explanations of the checks would litter the code, so the - * explanations are here, and the code references these. - * - * .check.ambig.not: RankAMBIG segments never appear on the grey ring. - * The current tracer cannot support ambiguous reference except as - * roots, so it's a bug if we ever find any. This behaviour is not set - * in stone, it's possible to imagine changing the tracer so that we can - * support ambiguous objects one day. For example, a fully conservative - * non-moving mode. - * - * .check.band.begin: At the point where we start working on a new band - * of Rank R, there are no grey objects at earlier ranks. If there - * were, we would've found them whilst the current band was the previous - * band. We don't check this, but I rely on this fact in the next - * check, .check.weak.no-preserve. - * - * .check.weak.band: Weak references cannot cause objects to be - * newly preserved (marked). Because of .check.band.begin all the - * scanning work performed when the current band is a weak rank will be - * scanning objects at that rank. There is currently only one weak - * rank, RankWEAK. - * - * .check.final.one-pass: Because all the RankFINAL references are - * allocated in PoolMRG and effectively treated as roots, all the - * RankFINAL references will be scanned in one push (possibly split up, - * incrementally). Once they have been scanned, no new RankFINAL - * references will be discovered (the mutator is not permitted to - * allocate RankFINAL references wherever they like). In fact because - * of various coincidences (no Ambig segments so band Exact never - * discovers an Ambig segment and then more Exact segments; the only - * other rank is weak so never discovers any new segments) it is the - * case that for any band R there is an initial burst of scanning - * segments at rank R then after that we see no more rank R segments - * whilst working in this band. That's what we check, although we - * expect to have to change the check if we introduce more ranks, or - * start changing the semantics of them. A flag is used to implement - * this check. See . - * - * For further discussion on the semantics of rank based tracing see - * - */ - -static Bool traceFindGrey(Seg *segReturn, Rank *rankReturn, - Arena arena, TraceId ti) -{ - Rank rank; - Trace trace; - Ring node, nextNode; - - AVER(segReturn != NULL); - AVER(TraceIdCheck(ti)); - - trace = ArenaTrace(arena, ti); - - while(1) { - Rank band = traceBand(trace); - - /* Within the R band we look for segments of rank R first, */ - /* then succesively earlier ones. Slight hack: We never */ - /* expect to find any segments of RankAMBIG, so we use */ - /* this as a terminating condition for the loop. */ - for(rank = band; rank > RankAMBIG; --rank) { - RING_FOR(node, ArenaGreyRing(arena, rank), nextNode) { - Seg seg = SegOfGreyRing(node); - - AVERT(Seg, seg); - AVER(SegGrey(seg) != TraceSetEMPTY); - AVER(RankSetIsMember(SegRankSet(seg), rank)); - - if(TraceSetIsMember(SegGrey(seg), trace)) { - /* .check.band.weak */ - AVER(band != RankWEAK || rank == band); - if(rank != band) { - traceBandFirstStretchDone(trace); - } else { - /* .check.final.one-pass */ - AVER(traceBandFirstStretch(trace)); - } - *segReturn = seg; - *rankReturn = rank; - EVENT4(TraceFindGrey, arena, ti, seg, rank); - DIAG( traceFindGrey_diag(TRUE, rank); ); - return TRUE; - } - } - } - /* .check.ambig.not */ - AVER(RingIsSingle(ArenaGreyRing(arena, RankAMBIG))); - if(!traceBandAdvance(trace)) { - /* No grey segments for this trace. */ - DIAG( traceFindGrey_diag(FALSE, rank); ); - return FALSE; - } - } -} - - -/* diagnostic output for traceFindGrey */ -DIAG_DECL( -static void traceFindGrey_diag(Bool found, Rank rank) -{ - char this; - static char prev = '.'; - static int segcount; - static char report_array[20]; - static char *report_lim; - int report_maxchars = sizeof(report_array) - 2; /* '.' + '\0' */ - - this = (char)(!found ? '.' - : (rank == RankAMBIG) ? 'A' - : (rank == RankEXACT) ? 'E' - : (rank == RankFINAL) ? 'F' - : (rank == RankWEAK) ? 'W' - : '?'); - - if(prev == '.') { - /* First seg of new trace */ - prev = this; - segcount = 0; - report_lim = report_array; - } - - if(this == prev) { - segcount += 1; - } else { - /* Change of rank: add prev rank and segcount to report */ - if((report_lim - report_array) + 2 > report_maxchars) { - /* no space to add 2 chars */ - report_array[0] = '!'; - } else { - /* prev rank */ - *report_lim++ = prev; - /* prev rank's segcount [0..9, a..z (x10), or *] */ - if(segcount < 10) { - *report_lim++ = (char)('0' + segcount); - } else if(segcount < 260) { - *report_lim++ = (char)(('a' - 1) + (segcount / 10)); - } else { - *report_lim++ = '*'; - } - } - /* begin new rank */ - prev = this; - segcount = 1; - } - - if(!found) { - /* No more grey in this trace: output report */ - AVER(this == '.'); - AVER(segcount == 1); /* single failed attempt to find a seg */ - *report_lim++ = this; - *report_lim++ = '\0'; - DIAG_SINGLEF(( "traceFindGrey", - "rank sequence: $S", - (WriteFS)report_array, - NULL )); - } - return; -} -) - -/* ScanStateSetSummary -- set the summary of scanned references - * - * This function sets unfixedSummary and fixedSummary such that - * ScanStateSummary will return the summary passed. Subsequently fixed - * references are accumulated into this result. */ - -void ScanStateSetSummary(ScanState ss, RefSet summary) -{ - AVERT(ScanState, ss); - /* Can't check summary, as it can be anything. */ - - ScanStateSetUnfixedSummary(ss, RefSetEMPTY); - ss->fixedSummary = summary; - AVER(ScanStateSummary(ss) == summary); -} - - -/* ScanStateSummary -- calculate the summary of scanned references - * - * The summary of the scanned references is the summary of the unfixed - * references, minus the white set, plus the summary of the fixed - * references. This is because TraceFix is called for all references in - * the white set, and accumulates a summary of references after they - * have been fixed. */ - -RefSet ScanStateSummary(ScanState ss) -{ - AVERT(ScanState, ss); - - return RefSetUnion(ss->fixedSummary, - RefSetDiff(ScanStateUnfixedSummary(ss), - ScanStateWhite(ss))); -} - - -/* traceScanSegRes -- scan a segment to remove greyness - * - * @@@@ During scanning, the segment should be write-shielded to prevent - * any other threads from updating it while fix is being applied to it - * (because fix is not atomic). At the moment, we don't bother, because - * we know that all threads are suspended. */ - -static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg) -{ - Bool wasTotal; - ZoneSet white; - Res res; - - /* The reason for scanning a segment is that it's grey. */ - AVER(TraceSetInter(ts, SegGrey(seg)) != TraceSetEMPTY); - EVENT4(TraceScanSeg, ts, rank, arena, seg); - - white = traceSetWhiteUnion(ts, arena); - - /* Only scan a segment if it refers to the white set. */ - if(ZoneSetInter(white, SegSummary(seg)) == ZoneSetEMPTY) { - PoolBlacken(SegPool(seg), ts, seg); - /* Setup result code to return later. */ - res = ResOK; - } else { /* scan it */ - ScanStateStruct ssStruct; - ScanState ss = &ssStruct; - ScanStateInit(ss, ts, arena, rank, white); - - /* Expose the segment to make sure we can scan it. */ - ShieldExpose(arena, seg); - res = PoolScan(&wasTotal, ss, SegPool(seg), seg); - /* Cover, regardless of result */ - ShieldCover(arena, seg); - - traceSetUpdateCounts(ts, arena, ss, traceAccountingPhaseSegScan); - /* Count segments scanned pointlessly */ - STATISTIC_STAT - ({ - TraceId ti; Trace trace; - Count whiteSegRefCount = 0; - - TRACE_SET_ITER(ti, trace, ts, arena) - whiteSegRefCount += trace->whiteSegRefCount; - TRACE_SET_ITER_END(ti, trace, ts, arena); - if(whiteSegRefCount == 0) - TRACE_SET_ITER(ti, trace, ts, arena) - ++trace->pointlessScanCount; - TRACE_SET_ITER_END(ti, trace, ts, arena); - }); - - /* Following is true whether or not scan was total. */ - /* See . */ - /* .verify.segsummary: were the seg contents, as found by this - * scan, consistent with the recorded SegSummary? - */ - AVER(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg))); - - if(res != ResOK || !wasTotal) { - /* scan was partial, so... */ - /* scanned summary should be ORed into segment summary. */ - SegSetSummary(seg, RefSetUnion(SegSummary(seg), ScanStateSummary(ss))); - } else { - /* all objects on segment have been scanned, so... */ - /* scanned summary should replace the segment summary. */ - SegSetSummary(seg, ScanStateSummary(ss)); - } - - ScanStateFinish(ss); - } - - if(res == ResOK) { - /* The segment is now black only if scan was successful. */ - /* Remove the greyness from it. */ - SegSetGrey(seg, TraceSetDiff(SegGrey(seg), ts)); - } - - return res; -} - - -/* traceScanSeg - * - * Scans a segment, switching to emergency mode if there is an allocation - * failure. - */ - -static Res traceScanSeg(TraceSet ts, Rank rank, Arena arena, Seg seg) -{ - Res res; - - res = traceScanSegRes(ts, rank, arena, seg); - if(ResIsAllocFailure(res)) { - ArenaSetEmergency(arena, TRUE); - res = traceScanSegRes(ts, rank, arena, seg); - /* Should be OK in emergency mode. */ - AVER(!ResIsAllocFailure(res)); - } - - return res; -} - - -/* TraceSegAccess -- handle barrier hit on a segment */ - -void TraceSegAccess(Arena arena, Seg seg, AccessSet mode) -{ - Res res; - - AVERT(Arena, arena); - AVERT(Seg, seg); - - /* If it's a read access, then the segment must be grey for a trace */ - /* which is flipped. */ - AVER((mode & SegSM(seg) & AccessREAD) == 0 - || TraceSetInter(SegGrey(seg), arena->flippedTraces) != TraceSetEMPTY); - - /* If it's a write acess, then the segment must have a summary that */ - /* is smaller than the mutator's summary (which is assumed to be */ - /* RefSetUNIV). */ - AVER((mode & SegSM(seg) & AccessWRITE) == 0 || SegSummary(seg) != RefSetUNIV); - - EVENT3(TraceAccess, arena, seg, mode); - - if((mode & SegSM(seg) & AccessREAD) != 0) { /* read barrier? */ - Trace trace; - TraceId ti; - Rank rank; - TraceSet traces; - - AVER(SegRankSet(seg) != RankSetEMPTY); - - /* Pick set of traces to scan for: */ - traces = arena->flippedTraces; - rank = TraceRankForAccess(arena, seg); - res = traceScanSeg(traces, rank, arena, seg); - - /* Allocation failures should be handled my emergency mode, and we don't - expect any other kind of failure in a normal GC that causes access - faults. */ - AVER(res == ResOK); - - /* The pool should've done the job of removing the greyness that */ - /* was causing the segment to be protected, so that the mutator */ - /* can go ahead and access it. */ - AVER(TraceSetInter(SegGrey(seg), traces) == TraceSetEMPTY); - - STATISTIC_STAT({ - TRACE_SET_ITER(ti, trace, traces, arena) - ++trace->readBarrierHitCount; - TRACE_SET_ITER_END(ti, trace, traces, arena); - }); - } else { /* write barrier */ - STATISTIC(++arena->writeBarrierHitCount); - } - - /* The write barrier handling must come after the read barrier, */ - /* because the latter may set the summary and raise the write barrier. */ - if((mode & SegSM(seg) & AccessWRITE) != 0) /* write barrier? */ - SegSetSummary(seg, RefSetUNIV); - - /* The segment must now be accessible. */ - AVER((mode & SegSM(seg)) == AccessSetEMPTY); -} - - -/* _mps_fix2 (a.k.a. "TraceFix") -- second stage of fixing a reference - * - * _mps_fix2 is on the [critical path](../design/critical-path.txt). A - * one-instruction difference in the early parts of this code will have a - * significant impact on overall run time. The priority is to eliminate - * irrelevant references early and fast using the colour information stored - * in the tract table. - * - * The name "TraceFix" is pervasive in the MPS and its documents to describe - * this function. Optimisation and strict aliasing rules have meant that we - * need to use the external name for it here. - */ - -mps_res_t _mps_fix2(mps_ss_t mps_ss, mps_addr_t *mps_ref_io) -{ - ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss); - Ref ref; - Tract tract; - - /* Special AVER macros are used on the critical path. */ - /* See */ - AVERT_CRITICAL(ScanState, ss); - AVER_CRITICAL(mps_ref_io != NULL); - - ref = (Ref)*mps_ref_io; - - /* The zone test should already have been passed by MPS_FIX1 in mps.h. */ - AVER_CRITICAL(ZoneSetInter(ScanStateWhite(ss), - ZoneSetAdd(ss->arena, ZoneSetEMPTY, ref)) != - ZoneSetEMPTY); - - STATISTIC(++ss->fixRefCount); - EVENT4(TraceFix, ss, mps_ref_io, ref, ss->rank); - - TRACT_OF_ADDR(&tract, ss->arena, ref); - if(tract) { - if(TraceSetInter(TractWhite(tract), ss->traces) != TraceSetEMPTY) { - Seg seg; - if(TRACT_SEG(&seg, tract)) { - Res res; - Pool pool; - STATISTIC(++ss->segRefCount); - STATISTIC(++ss->whiteSegRefCount); - EVENT1(TraceFixSeg, seg); - EVENT0(TraceFixWhite); - pool = TractPool(tract); - res = (*ss->fix)(pool, ss, seg, &ref); - if(res != ResOK) { - /* PoolFixEmergency should never fail. */ - AVER_CRITICAL(ss->fix != PoolFixEmergency); - /* Fix protocol (de facto): if Fix fails, ref must be unchanged - * Justification for this restriction: - * A: it simplifies; - * B: it's reasonable (given what may cause Fix to fail); - * C: the code (here) already assumes this: it returns without - * updating ss->fixedSummary. RHSK 2007-03-21. - */ - AVER(ref == (Ref)*mps_ref_io); - return res; - } - } else { - /* Only tracts with segments ought to have been condemned. */ - /* SegOfAddr FALSE => a ref into a non-seg Tract (poolmv etc) */ - /* .notwhite: ...But it should NOT be white. - * [I assert this both from logic, and from inspection of the - * current condemn code. RHSK 2010-11-30] - */ - NOTREACHED; - } - } else { - /* Tract isn't white. Don't compute seg for non-statistical */ - /* variety. See */ - STATISTIC_STAT - ({ - Seg seg; - if(TRACT_SEG(&seg, tract)) { - ++ss->segRefCount; - EVENT1(TraceFixSeg, seg); - } - }); - } - } else { - /* See */ - AVER(ss->rank < RankEXACT - || !ArenaIsReservedAddr(ss->arena, ref)); - } - - /* See */ - ss->fixedSummary = RefSetAdd(ss->arena, ss->fixedSummary, ref); - - *mps_ref_io = (mps_addr_t)ref; - return ResOK; -} - - -/* traceScanSingleRefRes -- scan a single reference, with result code */ - -static Res traceScanSingleRefRes(TraceSet ts, Rank rank, Arena arena, - Seg seg, Ref *refIO) -{ - RefSet summary; - ZoneSet white; - Res res; - ScanStateStruct ss; - - EVENT4(TraceScanSingleRef, ts, rank, arena, (Addr)refIO); - - white = traceSetWhiteUnion(ts, arena); - if(ZoneSetInter(SegSummary(seg), white) == ZoneSetEMPTY) { - return ResOK; - } - - ScanStateInit(&ss, ts, arena, rank, white); - ShieldExpose(arena, seg); - - TRACE_SCAN_BEGIN(&ss) { - res = TRACE_FIX(&ss, refIO); - } TRACE_SCAN_END(&ss); - ss.scannedSize = sizeof *refIO; - - summary = SegSummary(seg); - summary = RefSetAdd(arena, summary, *refIO); - SegSetSummary(seg, summary); - ShieldCover(arena, seg); - - traceSetUpdateCounts(ts, arena, &ss, traceAccountingPhaseSingleScan); - ScanStateFinish(&ss); - - return res; -} - - -/* TraceScanSingleRef -- scan a single reference - * - * This one can't fail. It may put the traces into emergency mode in - * order to achieve this. */ - -void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena, - Seg seg, Ref *refIO) -{ - Res res; - - AVER(TraceSetCheck(ts)); - AVER(RankCheck(rank)); - AVERT(Arena, arena); - AVER(SegCheck(seg)); - AVER(refIO != NULL); - - res = traceScanSingleRefRes(ts, rank, arena, seg, refIO); - if(res != ResOK) { - ArenaSetEmergency(arena, TRUE); - res = traceScanSingleRefRes(ts, rank, arena, seg, refIO); - /* Ought to be OK in emergency mode now. */ - } - AVER(ResOK == res); - - return; -} - - -/* TraceScanArea -- scan contiguous area of references - * - * This is a convenience function for scanning the contiguous area - * [base, limit). I.e., it calls Fix on all words from base up to - * limit, inclusive of base and exclusive of limit. */ - -Res TraceScanArea(ScanState ss, Addr *base, Addr *limit) -{ - Res res; - Addr *p; - Ref ref; - - AVER(base != NULL); - AVER(limit != NULL); - AVER(base < limit); - - EVENT3(TraceScanArea, ss, base, limit); - - TRACE_SCAN_BEGIN(ss) { - p = base; - loop: - if(p >= limit) goto out; - ref = *p++; - if(!TRACE_FIX1(ss, ref)) - goto loop; - res = TRACE_FIX2(ss, p-1); - if(res == ResOK) - goto loop; - return res; - out: - AVER(p == limit); - } TRACE_SCAN_END(ss); - - return ResOK; -} - - -/* TraceScanAreaTagged -- scan contiguous area of tagged references - * - * .tagging: This is as TraceScanArea except words are only fixed they are - * tagged as zero according to the alignment of a Word. - * - * See also PoolSingleAccess . - * - * TODO: Generalise the handling of tags so that pools can decide how - * their objects are tagged. This may use the user defined format - * to describe how tags are done */ -Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit) -{ - Word mask; - - /* NOTE: An optimisation that maybe worth considering is setting some of the - * top bits in the mask as an early catch of addresses outside the arena. - * This might help slightly on 64-bit windows. However these are picked up - * soon afterwards by later checks. The bottom bits are more important - * to check as we ignore them in AMCFix, so the non-reference could - * otherwise end up pinning an object. */ - mask = sizeof(Word) - 1; - AVER(WordIsP2(mask + 1)); - return TraceScanAreaMasked(ss, base, limit, mask); -} - - -/* TraceScanAreaMasked -- scan contiguous area of filtered references - * - * This is as TraceScanArea except words are only fixed if they are zero - * when masked with a mask. */ - -Res TraceScanAreaMasked(ScanState ss, Addr *base, Addr *limit, Word mask) -{ - Res res; - Addr *p; - Ref ref; - - AVERT(ScanState, ss); - AVER(base != NULL); - AVER(limit != NULL); - AVER(base < limit); - - EVENT3(TraceScanAreaTagged, ss, base, limit); - - TRACE_SCAN_BEGIN(ss) { - p = base; - loop: - if(p >= limit) goto out; - ref = *p++; - if(((Word)ref & mask) != 0) goto loop; - if(!TRACE_FIX1(ss, ref)) goto loop; - res = TRACE_FIX2(ss, p-1); - if(res == ResOK) - goto loop; - return res; - out: - AVER(p == limit); - } TRACE_SCAN_END(ss); - - return ResOK; -} - - -/* traceCondemnAll -- condemn everything and notify all the chains */ - -static Res traceCondemnAll(Trace trace) -{ - Res res; - Arena arena; - Ring chainNode, nextChainNode; - Bool haveWhiteSegs = FALSE; - - arena = trace->arena; - AVERT(Arena, arena); - /* Condemn all the chains. */ - RING_FOR(chainNode, &arena->chainRing, nextChainNode) { - Chain chain = RING_ELT(Chain, chainRing, chainNode); - - AVERT(Chain, chain); - res = ChainCondemnAll(chain, trace); - if(res != ResOK) - goto failBegin; - haveWhiteSegs = TRUE; - } - /* Notify all the chains. */ - RING_FOR(chainNode, &arena->chainRing, nextChainNode) { - Chain chain = RING_ELT(Chain, chainRing, chainNode); - - ChainStartGC(chain, trace); - } - return ResOK; - -failBegin: - AVER(!haveWhiteSegs); /* Would leave white sets inconsistent. */ - return res; -} - - -/* Collection control parameters */ - -double TraceTopGenMortality = 0.51; -double TraceWorkFactor = 0.25; - - -/* TraceStart -- condemn a set of objects and start collection - * - * TraceStart should be passed a trace with state TraceINIT, i.e., - * recently returned from TraceCreate, with some condemned segments - * added. mortality is the fraction of the condemned set expected to - * survive. finishingTime is relative to the current polling clock, see - * . - * - * .start.black: All segments are black w.r.t. a newly allocated trace. - * However, if TraceStart initialized segments to black when it - * calculated the grey set then this condition could be relaxed, making - * it easy to destroy traces half-way through. */ - -static Res rootGrey(Root root, void *p) -{ - Trace trace = (Trace)p; - - AVERT(Root, root); - AVERT(Trace, trace); - - if(ZoneSetInter(RootSummary(root), trace->white) != ZoneSetEMPTY) { - RootGrey(root, trace); - } - - return ResOK; -} - - -static void TraceStartGenDesc_diag(GenDesc desc, Bool top, Index i) -{ - Ring n, nn; - -#if !defined(DIAG_WITH_STREAM_AND_WRITEF) - UNUSED(i); -#endif - - if(top) { - DIAG_WRITEF(( DIAG_STREAM, - " GenDesc [top]", - NULL )); - } else { - DIAG_WRITEF(( DIAG_STREAM, - " GenDesc [$U]", (WriteFU)i, - NULL )); - } - DIAG_WRITEF(( DIAG_STREAM, - " $P capacity: $U KiB, mortality $D\n", - (WriteFP)desc, (WriteFU)desc->capacity, (WriteFD)desc->mortality, - " ZoneSet:$B\n", (WriteFB)desc->zones, - NULL )); - RING_FOR(n, &desc->locusRing, nn) { - DIAG_DECL( PoolGen gen = RING_ELT(PoolGen, genRing, n); ) - DIAG_WRITEF(( DIAG_STREAM, - " PoolGen $U ($S)", - (WriteFU)gen->nr, (WriteFS)gen->pool->class->name, - " totalSize $U", (WriteFU)gen->totalSize, - " newSize $U\n", (WriteFU)gen->newSizeAtCreate, - NULL )); - } -} - - -/* TraceStart -- start a trace whose white set has been established - * - * The main job of TraceStart is to set up the grey list for a trace. The - * trace is first created with TraceCreate, objects are whitened, then - * TraceStart is called to initialise the tracing process. - * - * NOTE: At present, TraceStart also flips the mutator, so there is no - * grey-mutator tracing. - */ - -Res TraceStart(Trace trace, double mortality, double finishingTime) -{ - Arena arena; - Res res; - Seg seg; - Size size; - - AVERT(Trace, trace); - AVER(trace->state == TraceINIT); - AVER(0.0 <= mortality); - AVER(mortality <= 1.0); - AVER(finishingTime >= 0.0); - - arena = trace->arena; - - /* From the already set up white set, derive a grey set. */ - - /* @@@@ Instead of iterating over all the segments, we could */ - /* iterate over all pools which are scannable and thence over */ - /* all their segments. This might be better if the minority */ - /* of segments are scannable. Perhaps we should choose */ - /* dynamically which method to use. */ - - if(SegFirst(&seg, arena)) { - Addr base; - do { - base = SegBase(seg); - size = SegSize(seg); - AVER(!TraceSetIsMember(SegGrey(seg), trace)); - - /* A segment can only be grey if it contains some references. */ - /* This is indicated by the rankSet begin non-empty. Such */ - /* segments may only belong to scannable pools. */ - if(SegRankSet(seg) != RankSetEMPTY) { - /* Segments with ranks may only belong to scannable pools. */ - AVER((SegPool(seg)->class->attr & AttrSCAN) != 0); - - /* Turn the segment grey if there might be a reference in it */ - /* to the white set. This is done by seeing if the summary */ - /* of references in the segment intersects with the */ - /* approximation to the white set. */ - if(ZoneSetInter(SegSummary(seg), trace->white) != ZoneSetEMPTY) { - /* Note: can a white seg get greyed as well? At this point */ - /* we still assume it may. (This assumption runs out in */ - /* PoolTrivGrey). */ - PoolGrey(SegPool(seg), trace, seg); - if(TraceSetIsMember(SegGrey(seg), trace)) { - trace->foundation += size; - } - } - - if((SegPool(seg)->class->attr & AttrGC) - && !TraceSetIsMember(SegWhite(seg), trace)) { - trace->notCondemned += size; - } - } - } while (SegNext(&seg, arena, base)); - } - - DIAG_FIRSTF(( "TraceStart", - "because code $U: $S\n", - (WriteFU)trace->why, (WriteFS)TraceStartWhyToString(trace->why), - NULL )); - - DIAG( ArenaDescribe(arena, DIAG_STREAM); ); - - DIAG_MOREF(( - " white set:$B\n", - (WriteFB)trace->white, - NULL )); - - { - /* @@ */ - /* Iterate over all chains, all GenDescs within a chain, */ - /* (and all PoolGens within a GenDesc). */ - Ring node, nextNode; - Index i; - - RING_FOR(node, &arena->chainRing, nextNode) { - Chain chain = RING_ELT(Chain, chainRing, node); - DIAG_WRITEF(( DIAG_STREAM, - " Chain $P\n", (WriteFP)chain, - NULL )); - - for(i = 0; i < chain->genCount; ++i) { - GenDesc desc = &chain->gens[i]; - TraceStartGenDesc_diag(desc, FALSE, i); - } - } - - /* Now do topgen GenDesc (and all PoolGens within it). */ - DIAG_WRITEF(( DIAG_STREAM, - " topGen\n", - NULL )); - TraceStartGenDesc_diag(&arena->topGen, TRUE, 0); - } - - DIAG_END( "TraceStart" ); - - res = RootsIterate(ArenaGlobals(arena), rootGrey, (void *)trace); - AVER(res == ResOK); - - STATISTIC_STAT(EVENT2(ArenaWriteFaults, arena, arena->writeBarrierHitCount)); - - /* Calculate the rate of scanning. */ - { - Size sSurvivors = (Size)(trace->condemned * (1.0 - mortality)); - double nPolls = finishingTime / ArenaPollALLOCTIME; - - /* There must be at least one poll. */ - if(nPolls < 1.0) - nPolls = 1.0; - /* We use casting to long to truncate nPolls down to the nearest */ - /* integer, so try to make sure it fits. */ - if(nPolls >= (double)LONG_MAX) - nPolls = (double)LONG_MAX; - /* rate equals scanning work per number of polls available */ - trace->rate = (trace->foundation + sSurvivors) / (unsigned long)nPolls + 1; - } - - /* @@ DIAG for rate of scanning here. */ - - STATISTIC_STAT(EVENT7(TraceStatCondemn, trace, - trace->condemned, trace->notCondemned, - trace->foundation, trace->rate, - mortality, finishingTime)); - - trace->state = TraceUNFLIPPED; - TracePostStartMessage(trace); - - /* All traces must flip at beginning at the moment. */ - return traceFlip(trace); -} - - -/* traceWorkClock -- a measure of the work done for this trace - * - * .workclock: Segment and root scanning work is the regulator. */ - -#define traceWorkClock(trace) ((trace)->segScanSize + (trace)->rootScanSize) - - -/* TraceQuantum -- progresses a trace by one quantum */ - -void TraceQuantum(Trace trace) -{ - Size pollEnd; - Arena arena = trace->arena; - - pollEnd = traceWorkClock(trace) + trace->rate; - do { - switch(trace->state) { - case TraceUNFLIPPED: - /* all traces are flipped in TraceStart at the moment */ - NOTREACHED; - break; - case TraceFLIPPED: { - Seg seg; - Rank rank; - - if(traceFindGrey(&seg, &rank, arena, trace->ti)) { - Res res; - AVER((SegPool(seg)->class->attr & AttrSCAN) != 0); - res = traceScanSeg(TraceSetSingle(trace), rank, arena, seg); - /* Allocation failures should be handled by emergency mode, and we - don't expect any other error in a normal GC trace. */ - AVER(res == ResOK); - } else { - trace->state = TraceRECLAIM; - } - break; - } - case TraceRECLAIM: - traceReclaim(trace); - break; - default: - NOTREACHED; - break; - } - } while(trace->state != TraceFINISHED - && (ArenaEmergency(arena) || traceWorkClock(trace) < pollEnd)); -} - -/* TraceStartCollectAll: start a trace which condemns everything in - * the arena. - * - * "why" is a TraceStartWhy* enum member that specifies why the - * collection is starting. */ - -Res TraceStartCollectAll(Trace *traceReturn, Arena arena, int why) -{ - Trace trace = NULL; - Res res; - double finishingTime; - - AVERT(Arena, arena); - AVER(arena->busyTraces == TraceSetEMPTY); - - res = TraceCreate(&trace, arena, why); - AVER(res == ResOK); /* succeeds because no other trace is busy */ - res = traceCondemnAll(trace); - if(res != ResOK) /* should try some other trace, really @@@@ */ - goto failCondemn; - finishingTime = ArenaAvail(arena) - - trace->condemned * (1.0 - TraceTopGenMortality); - if(finishingTime < 0) { - /* Run out of time, should really try a smaller collection. @@@@ */ - finishingTime = 0.0; - } - res = TraceStart(trace, TraceTopGenMortality, finishingTime); - if (res != ResOK) - goto failStart; - *traceReturn = trace; - return ResOK; - -failStart: - /* TODO: We can't back-out from a failed TraceStart that has - already done some scanning, so this error path is somewhat bogus if it - destroys the trace. In the current system, TraceStartCollectAll is - only used for a normal GC, so TraceStart should not fail and this case - should never be reached. There's a chance the mutator will survive - if the assertion isn't hit, so drop through anyway. */ - NOTREACHED; -failCondemn: - TraceDestroy(trace); - /* We don't know how long it'll be before another collection. Make sure - the next one starts in normal mode. */ - ArenaSetEmergency(arena, FALSE); - return res; -} - - -/* TracePoll -- Check if there's any tracing work to be done */ - -Size TracePoll(Globals globals) -{ - Trace trace; - Res res; - Arena arena; - Size scannedSize; - - AVERT(Globals, globals); - arena = GlobalsArena(globals); - - scannedSize = (Size)0; - if(arena->busyTraces == TraceSetEMPTY) { - /* If no traces are going on, see if we need to start one. */ - Size sFoundation, sCondemned, sSurvivors, sConsTrace; - double tTracePerScan; /* tTrace/cScan */ - double dynamicDeferral; - - /* Compute dynamic criterion. See strategy.lisp-machine. */ - AVER(TraceTopGenMortality >= 0.0); - AVER(TraceTopGenMortality <= 1.0); - sFoundation = (Size)0; /* condemning everything, only roots @@@@ */ - /* @@@@ sCondemned should be scannable only */ - sCondemned = ArenaCommitted(arena) - ArenaSpareCommitted(arena); - sSurvivors = (Size)(sCondemned * (1 - TraceTopGenMortality)); - tTracePerScan = sFoundation + (sSurvivors * (1 + TraceCopyScanRATIO)); - AVER(TraceWorkFactor >= 0); - AVER(sSurvivors + tTracePerScan * TraceWorkFactor <= (double)SizeMAX); - sConsTrace = (Size)(sSurvivors + tTracePerScan * TraceWorkFactor); - dynamicDeferral = (double)ArenaAvail(arena) - (double)sConsTrace; - - if(dynamicDeferral < 0.0) { /* start full GC */ - res = TraceStartCollectAll(&trace, arena, TraceStartWhyDYNAMICCRITERION); - if(res != ResOK) - goto failStart; - scannedSize = traceWorkClock(trace); - } else { /* Find the nursery most over its capacity. */ - Ring node, nextNode; - double firstTime = 0.0; - Chain firstChain = NULL; - - RING_FOR(node, &arena->chainRing, nextNode) { - Chain chain = RING_ELT(Chain, chainRing, node); - double time; - - AVERT(Chain, chain); - time = ChainDeferral(chain); - if(time < firstTime) { - firstTime = time; firstChain = chain; - } - } - - /* If one was found, start collection on that chain. */ - if(firstTime < 0) { - double mortality; - - res = TraceCreate(&trace, arena, TraceStartWhyCHAIN_GEN0CAP); - AVER(res == ResOK); - res = ChainCondemnAuto(&mortality, firstChain, trace); - if(res != ResOK) /* should try some other trace, really @@@@ */ - goto failCondemn; - trace->chain = firstChain; - ChainStartGC(firstChain, trace); - res = TraceStart(trace, mortality, trace->condemned * TraceWorkFactor); - /* We don't expect normal GC traces to fail to start. */ - AVER(res == ResOK); - scannedSize = traceWorkClock(trace); - } - } /* (dynamicDeferral > 0.0) */ - } /* (arena->busyTraces == TraceSetEMPTY) */ - - /* If there is a trace, do one quantum of work. */ - if(arena->busyTraces != TraceSetEMPTY) { - Size oldScanned; - - trace = ArenaTrace(arena, (TraceId)0); - AVER(arena->busyTraces == TraceSetSingle(trace)); - oldScanned = traceWorkClock(trace); - TraceQuantum(trace); - scannedSize = traceWorkClock(trace) - oldScanned; - if(trace->state == TraceFINISHED) { - TraceDestroy(trace); - /* A trace finished, and hopefully reclaimed some memory, so clear any - emergency. */ - ArenaSetEmergency(arena, FALSE); - } - } - return scannedSize; - -failCondemn: - TraceDestroy(trace); - /* This is an unlikely case, but clear the emergency flag so the next attempt - starts normally. */ - ArenaSetEmergency(arena, FALSE); -failStart: - return (Size)0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003, 2006, 2007 Ravenbrook Limited - * . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/traceanc.c b/mps/code/traceanc.c deleted file mode 100644 index 24da7a92741..00000000000 --- a/mps/code/traceanc.c +++ /dev/null @@ -1,842 +0,0 @@ -/* traceanc.c: ANCILLARY SUPPORT FOR TRACER - * - * $Id$ - * Copyright (c) 2001-2003, 2006-2008 Ravenbrook Limited. - * See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * All this ancillary stuff was making trace.c very cluttered. - * Put it here instead. RHSK 2008-12-09. - * - * CONTENTS - * - * - TraceStartMessage. Posted when a trace starts. - * - * - TraceMessage. Posted when a trace ends. - * - * - TraceIdMessages. Pre-allocated messages for traceid. - * - * - ArenaRelease, ArenaClamp, ArenaPark. - * - * - ArenaExposeRemember and ArenaRestoreProtection. - */ - -#include "mpm.h" - - - -/* -------- TraceStartMessage -------- */ - - -/* TraceStartMessage -- posted when a trace starts - * - * Internal names: - * trace start - * TraceStartMessage, tsMessage (struct *) - * MessageTypeGCSTART (enum) - * - * External names: - * mps_message_type_gc_start (enum macro) - * MPS_MESSAGE_TYPE_GC_START (enum) - * - * (Note: this should properly be called "trace begin", but it's much - * too late to change it now!) - * - * See . - */ - -#define TraceStartMessageSig ((Sig)0x51926535) /* SIG TRaceStartMeSsage */ - -/* .whybuf: - * .whybuf.len: Length (in chars) of a char buffer used to store the - * reason why a collection started in the TraceStartMessageStruct - * (used by mps_message_type_gc_start). If the reason is too long to - * fit, it must be truncated. - * .whybuf.nul: Check insists that the last char in the array is NUL - * (even if there is another NUL earlier in the buffer); this makes - * the NUL-termination check fast. - */ -#define TRACE_START_MESSAGE_WHYBUF_LEN 128 - -typedef struct TraceStartMessageStruct { - Sig sig; - char why[TRACE_START_MESSAGE_WHYBUF_LEN]; /* .whybuf */ - MessageStruct messageStruct; -} TraceStartMessageStruct; - -#define TraceStartMessageMessage(traceStartMessage) \ - (&((traceStartMessage)->messageStruct)) -#define MessageTraceStartMessage(message) \ - (PARENT(TraceStartMessageStruct, messageStruct, message)) - -Bool TraceStartMessageCheck(TraceStartMessage tsMessage) -{ - CHECKS(TraceStartMessage, tsMessage); - CHECKD(Message, TraceStartMessageMessage(tsMessage)); - CHECKL(MessageGetType(TraceStartMessageMessage(tsMessage)) == - MessageTypeGCSTART); - - /* Check that why is NUL terminated. See .whybuf.nul */ - CHECKL(tsMessage->why[NELEMS(tsMessage->why)-1] == '\0'); - - return TRUE; -} - -static void TraceStartMessageDelete(Message message) -{ - TraceStartMessage tsMessage; - Arena arena; - - AVERT(Message, message); - tsMessage = MessageTraceStartMessage(message); - AVERT(TraceStartMessage, tsMessage); - - arena = MessageArena(message); - tsMessage->sig = SigInvalid; - MessageFinish(message); - - ControlFree(arena, (void *)tsMessage, sizeof(TraceStartMessageStruct)); -} - -static const char *TraceStartMessageWhy(Message message) -{ - TraceStartMessage tsMessage; - - AVERT(Message, message); - tsMessage = MessageTraceStartMessage(message); - AVERT(TraceStartMessage, tsMessage); - - return tsMessage->why; -} - -static MessageClassStruct TraceStartMessageClassStruct = { - MessageClassSig, /* sig */ - "TraceGCStart", /* name */ - MessageTypeGCSTART, /* Message Type */ - TraceStartMessageDelete, /* Delete */ - MessageNoFinalizationRef, /* FinalizationRef */ - MessageNoGCLiveSize, /* GCLiveSize */ - MessageNoGCCondemnedSize, /* GCCondemnedSize */ - MessageNoGCNotCondemnedSize, /* GCNotCondemnedSize */ - TraceStartMessageWhy, /* GCStartWhy */ - MessageClassSig /* */ -}; - -static void traceStartMessageInit(Arena arena, TraceStartMessage tsMessage) -{ - AVERT(Arena, arena); - - MessageInit(arena, TraceStartMessageMessage(tsMessage), - &TraceStartMessageClassStruct, MessageTypeGCSTART); - tsMessage->why[0] = '\0'; - tsMessage->why[NELEMS(tsMessage->why)-1] = '\0'; /* .whybuf.nul */ - - tsMessage->sig = TraceStartMessageSig; - AVERT(TraceStartMessage, tsMessage); -} - -/* TraceStartWhyToString -- why-code to text - * - * Converts a TraceStartWhy* code into a constant string describing - * why a trace started. - */ - -const char *TraceStartWhyToString(int why) -{ - const char *r; - - switch(why) { - case TraceStartWhyCHAIN_GEN0CAP: - r = "Generation 0 of a chain has reached capacity:" - " start a minor collection."; - break; - case TraceStartWhyDYNAMICCRITERION: - r = "Need to start full collection now, or there won't be enough" - " memory (ArenaAvail) to complete it."; - break; - case TraceStartWhyOPPORTUNISM: - r = "Opportunism: client predicts plenty of idle time," - " so start full collection."; - break; - case TraceStartWhyCLIENTFULL_INCREMENTAL: - r = "Client requests: start incremental full collection now."; - break; - case TraceStartWhyCLIENTFULL_BLOCK: - r = "Client requests: immediate full collection."; - break; - case TraceStartWhyWALK: - r = "Walking all live objects."; - break; - case TraceStartWhyEXTENSION: - r = "Extension: an MPS extension started the trace."; - break; - default: - NOTREACHED; - r = "Unknown reason (internal error)."; - break; - } - - /* Should fit in buffer without truncation; see .whybuf.len */ - AVER(StringLength(r) < TRACE_START_MESSAGE_WHYBUF_LEN); - - return r; -} - - -/* traceStartWhyToTextBuffer - * - * Converts a TraceStartWhy* code into a string describing why a trace - * started, and copies that into the text buffer the caller provides. - * s specifies the beginning of the buffer to write the string - * into, len specifies the length of the buffer. - * The string written will be NUL terminated, and truncated if - * necessary. - */ - -static void traceStartWhyToTextBuffer(char *s, size_t len, int why) -{ - const char *r; - size_t i; - - AVER(s); - /* len can be anything, including 0. */ - AVER(TraceStartWhyBASE <= why); - AVER(why < TraceStartWhyLIMIT); - - r = TraceStartWhyToString(why); - - for(i=0; istate == TraceUNFLIPPED); - - arena = trace->arena; - AVERT(Arena, arena); - - ti = trace->ti; - AVERT(TraceId, ti); - - tsMessage = arena->tsMessage[ti]; - if(tsMessage) { - AVERT(TraceStartMessage, tsMessage); - - traceStartWhyToTextBuffer(tsMessage->why, - sizeof tsMessage->why, trace->why); - - MessagePost(arena, TraceStartMessageMessage(tsMessage)); - arena->tsMessage[ti] = NULL; - } else { - arena->droppedMessages += 1; - } - - /* We have consumed the pre-allocated message */ - AVER(!arena->tsMessage[ti]); - - if(arena->alertCollection) { - (*arena->alertCollection)(MPS_ALERT_COLLECTION_BEGIN, trace->why); - } -} - - - -/* -------- TraceMessage (trace end) -------- */ - - -/* TraceMessage -- posted when a trace ends - * - * Internal names: - * trace end - * TraceMessage, tMessage (struct *) - * MessageTypeGC (enum) - * - * External names: - * mps_message_type_gc (enum macro) - * MPS_MESSAGE_TYPE_GC (enum) - * - * (Note: this should properly be called "trace end", but it's much - * too late to change it now!) - * - * See . - */ - - -/* TraceMessage -- type of trace end messages */ - -#define TraceMessageSig ((Sig)0x51926359) - -typedef struct TraceMessageStruct { - Sig sig; - Size liveSize; - Size condemnedSize; - Size notCondemnedSize; - MessageStruct messageStruct; -} TraceMessageStruct; - -#define TraceMessageMessage(traceMessage) (&((traceMessage)->messageStruct)) -#define MessageTraceMessage(message) \ - (PARENT(TraceMessageStruct, messageStruct, message)) - -Bool TraceMessageCheck(TraceMessage tMessage) -{ - CHECKS(TraceMessage, tMessage); - CHECKD(Message, TraceMessageMessage(tMessage)); - CHECKL(MessageGetType(TraceMessageMessage(tMessage)) == - MessageTypeGC); - /* We can't check anything about the statistics. In particular, */ - /* liveSize may exceed condemnedSize because they are only estimates. */ - - return TRUE; -} - -static void TraceMessageDelete(Message message) -{ - TraceMessage tMessage; - Arena arena; - - AVERT(Message, message); - tMessage = MessageTraceMessage(message); - AVERT(TraceMessage, tMessage); - - arena = MessageArena(message); - tMessage->sig = SigInvalid; - MessageFinish(message); - - ControlFree(arena, (void *)tMessage, sizeof(TraceMessageStruct)); -} - -static Size TraceMessageLiveSize(Message message) -{ - TraceMessage tMessage; - - AVERT(Message, message); - tMessage = MessageTraceMessage(message); - AVERT(TraceMessage, tMessage); - - return tMessage->liveSize; -} - -static Size TraceMessageCondemnedSize(Message message) -{ - TraceMessage tMessage; - - AVERT(Message, message); - tMessage = MessageTraceMessage(message); - AVERT(TraceMessage, tMessage); - - return tMessage->condemnedSize; -} - -static Size TraceMessageNotCondemnedSize(Message message) -{ - TraceMessage tMessage; - - AVERT(Message, message); - tMessage = MessageTraceMessage(message); - AVERT(TraceMessage, tMessage); - - return tMessage->notCondemnedSize; -} - -static MessageClassStruct TraceMessageClassStruct = { - MessageClassSig, /* sig */ - "TraceGC", /* name */ - MessageTypeGC, /* Message Type */ - TraceMessageDelete, /* Delete */ - MessageNoFinalizationRef, /* FinalizationRef */ - TraceMessageLiveSize, /* GCLiveSize */ - TraceMessageCondemnedSize, /* GCCondemnedSize */ - TraceMessageNotCondemnedSize, /* GCNotCondemnedSize */ - MessageNoGCStartWhy, /* GCStartWhy */ - MessageClassSig /* */ -}; - -static void traceMessageInit(Arena arena, TraceMessage tMessage) -{ - AVERT(Arena, arena); - - MessageInit(arena, TraceMessageMessage(tMessage), - &TraceMessageClassStruct, MessageTypeGC); - tMessage->liveSize = (Size)0; - tMessage->condemnedSize = (Size)0; - tMessage->notCondemnedSize = (Size)0; - - tMessage->sig = TraceMessageSig; - AVERT(TraceMessage, tMessage); -} - -/* TracePostMessage -- complete and post trace end message - * - * .message.data: The trace end message contains the live size - * (forwardedSize + preservedInPlaceSize), the condemned size - * (condemned), and the not-condemned size (notCondemned). - */ - -void TracePostMessage(Trace trace) -{ - Arena arena; - TraceId ti; - TraceMessage tMessage; - - AVERT(Trace, trace); - AVER(trace->state == TraceFINISHED); - - arena = trace->arena; - AVERT(Arena, arena); - - ti = trace->ti; - AVERT(TraceId, ti); - - tMessage = arena->tMessage[ti]; - if(tMessage) { - AVERT(TraceMessage, tMessage); - - tMessage->liveSize = trace->forwardedSize + trace->preservedInPlaceSize; - tMessage->condemnedSize = trace->condemned; - tMessage->notCondemnedSize = trace->notCondemned; - - MessagePost(arena, TraceMessageMessage(tMessage)); - arena->tMessage[ti] = NULL; - } else { - arena->droppedMessages += 1; - } - - /* We have consumed the pre-allocated message */ - AVER(!arena->tMessage[ti]); - - if(arena->alertCollection) { - (*arena->alertCollection)(MPS_ALERT_COLLECTION_END, trace->why); - } -} - - - -/* -------- TraceIdMessages -------- */ - - -/* TraceIdMessagesCheck - pre-allocated messages for this traceid. - * - * Messages are absent when already sent, or when (exceptionally) - * ControlAlloc failed at the end of the previous trace. If present, - * they must be valid. - * - * Messages are pre-allocated all-or-nothing. So if we've got a - * start but no end, that's wrong. - * - * Note: this function does not take a pointer to a struct, so it is - * not a 'proper' _Check function. It can be used in CHECKL, but - * not CHECKD etc. - */ - -Bool TraceIdMessagesCheck(Arena arena, TraceId ti) -{ - CHECKL(!arena->tsMessage[ti] - || TraceStartMessageCheck(arena->tsMessage[ti])); - CHECKL(!arena->tMessage[ti] - || TraceMessageCheck(arena->tMessage[ti])); - CHECKL(! (arena->tsMessage[ti] && !arena->tMessage[ti]) ); - - return TRUE; -} - -/* TraceIdMessagesCreate -- pre-allocate all messages for this traceid - * - * See . - * - * For remote control of ControlAlloc, to simulate low memory: - * #define ControlAlloc !TIMCA_remote() ? ResFAIL : ControlAlloc - * extern Bool TIMCA_remote(void); - * See TIMCA_remote() in zmess.c - */ - -Res TraceIdMessagesCreate(Arena arena, TraceId ti) -{ - void *p; - TraceStartMessage tsMessage; - TraceMessage tMessage; - Res res; - - /* Ensure we don't leak memory */ - AVER(!arena->tsMessage[ti]); - AVER(!arena->tMessage[ti]); - - res = ControlAlloc(&p, arena, sizeof(TraceStartMessageStruct), FALSE); - if(res != ResOK) - goto failTraceStartMessage; - tsMessage = p; - - res = ControlAlloc(&p, arena, sizeof(TraceMessageStruct), FALSE); - if(res != ResOK) - goto failTraceMessage; - tMessage = p; - - traceStartMessageInit(arena, tsMessage); - AVERT(TraceStartMessage, tsMessage); - arena->tsMessage[ti] = tsMessage; - - traceMessageInit(arena, tMessage); - AVERT(TraceMessage, tMessage); - arena->tMessage[ti] = tMessage; - - AVER(TraceIdMessagesCheck(arena, ti)); - - return ResOK; - -failTraceMessage: - ControlFree(arena, tsMessage, sizeof(TraceStartMessageStruct)); -failTraceStartMessage: - AVER(TraceIdMessagesCheck(arena, ti)); - return res; -} - -/* TraceIdMessagesDestroy -- destroy any pre-allocated messages - * - * Only used during ArenaDestroy. - * - * See . - */ - -void TraceIdMessagesDestroy(Arena arena, TraceId ti) -{ - TraceStartMessage tsMessage; - TraceMessage tMessage; - - AVER(TraceIdMessagesCheck(arena, ti)); - - tsMessage = arena->tsMessage[ti]; - if(tsMessage) { - arena->tsMessage[ti] = NULL; - TraceStartMessageDelete(TraceStartMessageMessage(tsMessage)); - } - - tMessage = arena->tMessage[ti]; - if(tMessage) { - arena->tMessage[ti] = NULL; - TraceMessageDelete(TraceMessageMessage(tMessage)); - } - - AVER(!arena->tsMessage[ti]); - AVER(!arena->tMessage[ti]); - AVER(TraceIdMessagesCheck(arena, ti)); -} - - - -/* -------- ArenaRelease, ArenaClamp, ArenaPark -------- */ - - -/* ArenaRelease, ArenaClamp, ArenaPark -- allow/prevent collection work. - * - * These functions allow or prevent collection work. - */ - - -/* Forward Declarations */ -static void arenaForgetProtection(Globals globals); - - -/* ArenaClamp -- clamp the arena (no optional collection increments) */ - -void ArenaClamp(Globals globals) -{ - AVERT(Globals, globals); - globals->clamped = TRUE; -} - - -/* ArenaRelease -- release the arena (allow optional collection - * increments) */ - -void ArenaRelease(Globals globals) -{ - AVERT(Globals, globals); - arenaForgetProtection(globals); - globals->clamped = FALSE; - (void)TracePoll(globals); -} - - -/* ArenaPark -- finish all current collections and clamp the arena */ - -void ArenaPark(Globals globals) -{ - TraceId ti; - Trace trace; - Arena arena; - - AVERT(Globals, globals); - arena = GlobalsArena(globals); - - globals->clamped = TRUE; - - while(arena->busyTraces != TraceSetEMPTY) { - /* Poll active traces to make progress. */ - TRACE_SET_ITER(ti, trace, arena->busyTraces, arena) - TraceQuantum(trace); - if(trace->state == TraceFINISHED) { - TraceDestroy(trace); - } - TRACE_SET_ITER_END(ti, trace, arena->busyTraces, arena); - } - - /* Clear any emergency flag so that the next collection starts normally. - Any traces that have been finished may have reclaimed memory. */ - ArenaSetEmergency(arena, FALSE); -} - -/* ArenaStartCollect -- start a collection of everything in the - * arena; leave unclamped. */ - -Res ArenaStartCollect(Globals globals, int why) -{ - Arena arena; - Res res; - Trace trace; - - AVERT(Globals, globals); - arena = GlobalsArena(globals); - - ArenaPark(globals); - res = TraceStartCollectAll(&trace, arena, why); - if(res != ResOK) - goto failStart; - ArenaRelease(globals); - return ResOK; - -failStart: - ArenaRelease(globals); - return res; -} - -/* ArenaCollect -- collect everything in arena; leave clamped */ - -Res ArenaCollect(Globals globals, int why) -{ - Res res; - - AVERT(Globals, globals); - res = ArenaStartCollect(globals, why); - if(res != ResOK) - return res; - - ArenaPark(globals); - return ResOK; -} - - - -/* -------- ExposeRemember and RestoreProtection -------- */ - - -/* Low level stuff for Expose / Remember / Restore */ - -struct RememberedSummaryBlockStruct { - RingStruct globalRing; /* link on globals->rememberedSummaryRing */ - struct SummaryPair { - Addr base; - RefSet summary; - } the[RememberedSummaryBLOCK]; -}; - -typedef struct RememberedSummaryBlockStruct *RememberedSummaryBlock; - -static void rememberedSummaryBlockInit(struct RememberedSummaryBlockStruct *block) -{ - size_t i; - - RingInit(&block->globalRing); - for(i = 0; i < RememberedSummaryBLOCK; ++ i) { - block->the[i].base = (Addr)0; - block->the[i].summary = RefSetUNIV; - } -} - -static Res arenaRememberSummaryOne(Globals global, Addr base, RefSet summary) -{ - Arena arena; - RememberedSummaryBlock block; - - AVER(summary != RefSetUNIV); - - arena = GlobalsArena(global); - - if(global->rememberedSummaryIndex == 0) { - void *p; - RememberedSummaryBlock newBlock; - int res; - - res = ControlAlloc(&p, arena, sizeof *newBlock, 0); - if(res != ResOK) { - return res; - } - newBlock = p; - rememberedSummaryBlockInit(newBlock); - RingAppend(GlobalsRememberedSummaryRing(global), - &newBlock->globalRing); - } - block = RING_ELT(RememberedSummaryBlock, globalRing, - RingPrev(GlobalsRememberedSummaryRing(global))); - AVER(global->rememberedSummaryIndex < RememberedSummaryBLOCK); - AVER(block->the[global->rememberedSummaryIndex].base == (Addr)0); - AVER(block->the[global->rememberedSummaryIndex].summary == RefSetUNIV); - block->the[global->rememberedSummaryIndex].base = base; - block->the[global->rememberedSummaryIndex].summary = summary; - ++ global->rememberedSummaryIndex; - if(global->rememberedSummaryIndex >= RememberedSummaryBLOCK) { - AVER(global->rememberedSummaryIndex == RememberedSummaryBLOCK); - global->rememberedSummaryIndex = 0; - } - - return ResOK; -} - -/* ArenaExposeRemember -- park arena and then lift all protection - barriers. Parameter 'remember' specifies whether to remember the - protection state or not (for later restoration with - ArenaRestoreProtection). - */ -void ArenaExposeRemember(Globals globals, int remember) -{ - Seg seg; - Arena arena; - - AVERT(Globals, globals); - - ArenaPark(globals); - - arena = GlobalsArena(globals); - if(SegFirst(&seg, arena)) { - Addr base; - - do { - base = SegBase(seg); - if(IsSubclassPoly(ClassOfSeg(seg), GCSegClassGet())) { - if(remember) { - RefSet summary; - - summary = SegSummary(seg); - if(summary != RefSetUNIV) { - Res res = arenaRememberSummaryOne(globals, base, summary); - if(res != ResOK) { - /* If we got an error then stop trying to remember any - protections. */ - remember = 0; - } - } - } - SegSetSummary(seg, RefSetUNIV); - AVER(SegSM(seg) == AccessSetEMPTY); - } - } while(SegNext(&seg, arena, base)); - } -} - -void ArenaRestoreProtection(Globals globals) -{ - Ring node, next; - Arena arena; - - arena = GlobalsArena(globals); - - RING_FOR(node, GlobalsRememberedSummaryRing(globals), next) { - RememberedSummaryBlock block = - RING_ELT(RememberedSummaryBlock, globalRing, node); - size_t i; - - for(i = 0; i < RememberedSummaryBLOCK; ++ i) { - Seg seg; - Bool b; - - if(block->the[i].base == (Addr)0) { - AVER(block->the[i].summary == RefSetUNIV); - continue; - } - b = SegOfAddr(&seg, arena, block->the[i].base); - if(b && SegBase(seg) == block->the[i].base) { - AVER(IsSubclassPoly(ClassOfSeg(seg), GCSegClassGet())); - SegSetSummary(seg, block->the[i].summary); - } else { - /* Either seg has gone or moved, both of which are */ - /* client errors. */ - NOTREACHED; - } - } - } - - arenaForgetProtection(globals); -} - -static void arenaForgetProtection(Globals globals) -{ - Ring node, next; - Arena arena; - - arena = GlobalsArena(globals); - /* Setting this early means that we preserve the invariant - */ - globals->rememberedSummaryIndex = 0; - RING_FOR(node, GlobalsRememberedSummaryRing(globals), next) { - RememberedSummaryBlock block = - RING_ELT(RememberedSummaryBlock, globalRing, node); - - RingRemove(node); - ControlFree(arena, block, sizeof *block); - } -} - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003, 2006-2008 Ravenbrook Limited - * . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/tract.c b/mps/code/tract.c deleted file mode 100644 index 2aa0f9a5468..00000000000 --- a/mps/code/tract.c +++ /dev/null @@ -1,689 +0,0 @@ -/* tract.c: PAGE TABLES - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .ullagepages: Pages whose page index is < allocBase are recorded as - * free but never allocated as alloc starts searching after the tables. - * TractOfAddr uses the fact that these pages are marked as free in order - * to detect "references" to these pages as being bogus. - */ - -#include "tract.h" -#include "boot.h" -#include "bt.h" -#include "mpm.h" - -SRCID(tract, "$Id$"); - - -static void ChunkDecache(Arena arena, Chunk chunk); - - -/* TractArena -- get the arena of a tract */ - -#define TractArena(tract) PoolArena(TractPool(tract)) - - -/* TractCheck -- check the integrity of a tract */ - -Bool TractCheck(Tract tract) -{ - CHECKU(Pool, TractPool(tract)); - CHECKL(AddrIsAligned(TractBase(tract), ArenaAlign(TractArena(tract)))); - if (TractHasSeg(tract)) { - CHECKL(TraceSetCheck(TractWhite(tract))); - CHECKU(Seg, (Seg)TractP(tract)); - } else { - CHECKL(TractWhite(tract) == TraceSetEMPTY); - } - return TRUE; -} - - -/* TractInit -- initialize a tract */ - -void TractInit(Tract tract, Pool pool, Addr base) -{ - AVER(tract != NULL); - AVERT(Pool, pool); - - tract->pool = pool; - tract->base = base; - tract->p = NULL; - tract->white = TraceSetEMPTY; - tract->hasSeg = FALSE; - - AVERT(Tract, tract); - -} - - -/* TractFinish -- finish a tract */ - -void TractFinish(Tract tract) -{ - AVERT(Tract, tract); - - /* Check that there's no segment - and hence no shielding. */ - AVER(!TractHasSeg(tract)); - tract->pool = NULL; -} - - - -/* .tract.critical: These tract functions are low-level and used - * throughout. They are therefore on the - * [critical path](../design/critical-path.txt) and their - * AVERs are so-marked. - */ - - -/* TractBase -- return the base address of a tract */ - -Addr (TractBase)(Tract tract) -{ - Addr base; - AVERT_CRITICAL(Tract, tract); /* .tract.critical */ - - base = tract->base; - return base; -} - - -/* TractLimit -- return the limit address of a segment */ - -Addr TractLimit(Tract tract) -{ - Arena arena; - AVERT_CRITICAL(Tract, tract); /* .tract.critical */ - arena = TractArena(tract); - AVERT_CRITICAL(Arena, arena); - return AddrAdd(TractBase(tract), arena->alignment); -} - - -/* Chunk functions */ - - -/* ChunkCheck -- check a chunk */ - -Bool ChunkCheck(Chunk chunk) -{ - CHECKS(Chunk, chunk); - CHECKU(Arena, chunk->arena); - CHECKL(chunk->serial < chunk->arena->chunkSerial); - CHECKL(RingCheck(&chunk->chunkRing)); - CHECKL(ChunkPagesToSize(chunk, 1) == ChunkPageSize(chunk)); - CHECKL(ShiftCheck(ChunkPageShift(chunk))); - - CHECKL(chunk->base != (Addr)0); - CHECKL(chunk->base < chunk->limit); - /* check chunk is in itself */ - CHECKL(chunk->base <= (Addr)chunk); - CHECKL((Addr)(chunk+1) <= chunk->limit); - CHECKL(ChunkSizeToPages(chunk, AddrOffset(chunk->base, chunk->limit)) - == chunk->pages); - /* check that the tables fit in the chunk */ - CHECKL(chunk->allocBase <= chunk->pages); - CHECKL(chunk->allocBase >= chunk->pageTablePages); - - CHECKL(chunk->allocTable != NULL); - /* check that allocTable is in the chunk overhead */ - CHECKL((Addr)chunk->allocTable >= chunk->base); - CHECKL(AddrAdd((Addr)chunk->allocTable, BTSize(chunk->pages)) - <= PageIndexBase(chunk, chunk->allocBase)); - - /* check they don't overlap (knowing the order) */ - CHECKL(AddrAdd((Addr)chunk->allocTable, BTSize(chunk->pages)) - <= (Addr)chunk->pageTable); - - CHECKL(chunk->pageTable != NULL); - CHECKL((Addr)chunk->pageTable >= chunk->base); - CHECKL((Addr)&chunk->pageTable[chunk->pageTablePages] - <= PageIndexBase(chunk, chunk->allocBase)); - /* check there's enough space in the page table */ - CHECKL(INDEX_OF_ADDR(chunk, (Addr)chunk->pageTable) >= 0); - CHECKL(INDEX_OF_ADDR(chunk, AddrSub(chunk->limit, 1)) < chunk->pages); - CHECKL(chunk->pageTablePages < chunk->pages); - - /* Could check the consistency of the tables, but not O(1). */ - return TRUE; -} - - -/* ChunkInit -- initialize generic part of chunk */ - -Res ChunkInit(Chunk chunk, Arena arena, - Addr base, Addr limit, Align pageSize, BootBlock boot) -{ - Size size; - Count pages; - PageStruct *pageTable; - Shift pageShift; - Size pageTableSize; - void *p; - Res res; - - /* chunk is supposed to be uninitialized, so don't check it. */ - AVERT(Arena, arena); - AVER(base != NULL); - AVER(AddrIsAligned(base, pageSize)); - AVER(base < limit); - AVER(AddrIsAligned(limit, pageSize)); - AVERT(Align, pageSize); - AVER(pageSize > MPS_PF_ALIGN); - AVERT(BootBlock, boot); - - chunk->serial = (arena->chunkSerial)++; - chunk->arena = arena; - RingInit(&chunk->chunkRing); - RingAppend(&arena->chunkRing, &chunk->chunkRing); - - chunk->pageSize = pageSize; - chunk->pageShift = pageShift = SizeLog2(pageSize); - chunk->base = base; - chunk->limit = limit; - size = AddrOffset(base, limit); - - chunk->pages = pages = size >> pageShift; - res = BootAlloc(&p, boot, (size_t)BTSize(pages), MPS_PF_ALIGN); - if (res != ResOK) - goto failAllocTable; - chunk->allocTable = p; - - pageTableSize = SizeAlignUp(pages * sizeof(PageStruct), pageSize); - chunk->pageTablePages = pageTableSize >> pageShift; - - res = (arena->class->chunkInit)(chunk, boot); - if (res != ResOK) - goto failClassInit; - - /* Put the page table as late as possible, as in VM systems we don't want */ - /* to map it. */ - res = BootAlloc(&p, boot, (size_t)pageTableSize, (size_t)pageSize); - if (res != ResOK) - goto failAllocPageTable; - chunk->pageTable = pageTable = p; - - /* @@@@ Is BootAllocated always right? */ - /* Last thing we BootAlloc'd is pageTable. We requested pageSize */ - /* alignment, and pageTableSize is itself pageSize aligned, so */ - /* BootAllocated should also be pageSize aligned. */ - AVER(AddrIsAligned(BootAllocated(boot), pageSize)); - chunk->allocBase = (Index)(BootAllocated(boot) >> pageShift); - - /* Init allocTable after class init, because it might be mapped there. */ - BTResRange(chunk->allocTable, 0, pages); - - chunk->sig = ChunkSig; - AVERT(Chunk, chunk); - return ResOK; - - /* .no-clean: No clean-ups needed for boot, as we will discard the chunk. */ -failAllocPageTable: - (arena->class->chunkFinish)(chunk); -failClassInit: -failAllocTable: - return res; -} - - -/* ChunkFinish -- finish the generic fields of a chunk */ - -void ChunkFinish(Chunk chunk) -{ - AVERT(Chunk, chunk); - AVER(BTIsResRange(chunk->allocTable, 0, chunk->pages)); - ChunkDecache(chunk->arena, chunk); - chunk->sig = SigInvalid; - RingRemove(&chunk->chunkRing); - /* Finish all other fields before class finish, because they might be */ - /* unmapped there. */ - (chunk->arena->class->chunkFinish)(chunk); -} - - -/* Chunk Cache - * - * Functions for manipulating the chunk cache in the arena. - */ - - -/* ChunkCacheEntryCheck -- check a chunk cache entry - * - * The cache is EITHER empty: - * - chunk is null; AND - * - base & limit are both null - * OR full: - * - chunk is non-null, points to a ChunkStruct; AND - * - base & limit are not both null; - * - * .chunk.empty.fields: Fields of an empty cache are nonetheless read, - * and must be correct. - */ - -Bool ChunkCacheEntryCheck(ChunkCacheEntry entry) -{ - CHECKS(ChunkCacheEntry, entry); - if (entry->chunk == NULL) { - CHECKL(entry->base == NULL); /* .chunk.empty.fields */ - CHECKL(entry->limit == NULL); /* .chunk.empty.fields */ - } else { - CHECKL(!(entry->base == NULL && entry->limit == NULL)); - CHECKD(Chunk, entry->chunk); - CHECKL(entry->base == entry->chunk->base); - CHECKL(entry->limit == entry->chunk->limit); - } - return TRUE; -} - - -/* ChunkCacheEntryInit -- initialize a chunk cache entry */ - -void ChunkCacheEntryInit(ChunkCacheEntry entry) -{ - entry->chunk = NULL; - entry->base = NULL; /* .chunk.empty.fields */ - entry->limit = NULL; /* .chunk.empty.fields */ - entry->sig = ChunkCacheEntrySig; - AVERT(ChunkCacheEntry, entry); - return; -} - - -/* ChunkEncache -- cache a chunk */ - -static void ChunkEncache(Arena arena, Chunk chunk) -{ - /* [Critical path](../design/critical-path.txt); called by ChunkOfAddr */ - AVERT_CRITICAL(Arena, arena); - AVERT_CRITICAL(Chunk, chunk); - AVER_CRITICAL(arena == chunk->arena); - AVERT_CRITICAL(ChunkCacheEntry, &arena->chunkCache); - - /* check chunk already in cache first */ - if (arena->chunkCache.chunk == chunk) { - return; - } - - arena->chunkCache.chunk = chunk; - arena->chunkCache.base = chunk->base; - arena->chunkCache.limit = chunk->limit; - - AVERT_CRITICAL(ChunkCacheEntry, &arena->chunkCache); - return; -} - - -/* ChunkDecache -- make sure a chunk is not in the cache */ - -static void ChunkDecache(Arena arena, Chunk chunk) -{ - AVERT(Arena, arena); - AVERT(Chunk, chunk); - AVER(arena == chunk->arena); - AVERT(ChunkCacheEntry, &arena->chunkCache); - if (arena->chunkCache.chunk == chunk) { - arena->chunkCache.chunk = NULL; - arena->chunkCache.base = NULL; /* .chunk.empty.fields */ - arena->chunkCache.limit = NULL; /* .chunk.empty.fields */ - } - AVERT(ChunkCacheEntry, &arena->chunkCache); -} - - -/* ChunkOfAddr -- return the chunk which encloses an address */ - -Bool ChunkOfAddr(Chunk *chunkReturn, Arena arena, Addr addr) -{ - Ring node, next; - - AVER_CRITICAL(chunkReturn != NULL); - AVERT_CRITICAL(Arena, arena); - /* addr is arbitrary */ - - /* check cache first; see also .chunk.empty.fields */ - AVERT_CRITICAL(ChunkCacheEntry, &arena->chunkCache); - if (arena->chunkCache.base <= addr && addr < arena->chunkCache.limit) { - *chunkReturn = arena->chunkCache.chunk; - AVER_CRITICAL(*chunkReturn != NULL); - return TRUE; - } - RING_FOR(node, &arena->chunkRing, next) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - if (chunk->base <= addr && addr < chunk->limit) { - /* Gotcha! */ - ChunkEncache(arena, chunk); - *chunkReturn = chunk; - return TRUE; - } - } - return FALSE; -} - - -/* ChunkOfNextAddr - * - * Finds the next higher chunk in memory which does _not_ contain addr. - * Returns FALSE if there is none. - * - * [The name is misleading; it should be "NextChunkAboveAddr" -- the - * word "Next" applies to chunks, not to addrs. RHSK 2010-03-20.] - */ - -static Bool ChunkOfNextAddr(Chunk *chunkReturn, Arena arena, Addr addr) -{ - Addr leastBase; - Chunk leastChunk; - Ring node, next; - - leastBase = (Addr)(Word)-1; - leastChunk = NULL; - RING_FOR(node, &arena->chunkRing, next) { - Chunk chunk = RING_ELT(Chunk, chunkRing, node); - if (addr < chunk->base && chunk->base < leastBase) { - leastBase = chunk->base; - leastChunk = chunk; - } - } - if (leastChunk != NULL) { - *chunkReturn = leastChunk; - return TRUE; - } - return FALSE; -} - - -/* ArenaIsReservedAddr -- is address managed by this arena? */ - -Bool ArenaIsReservedAddr(Arena arena, Addr addr) -{ - Chunk dummy; - - AVERT(Arena, arena); - /* addr is arbitrary */ - - return ChunkOfAddr(&dummy, arena, addr); -} - - -/* IndexOfAddr -- return the index of the page containing an address - * - * Function version of INDEX_OF_ADDR, for debugging purposes. - */ - -Index IndexOfAddr(Chunk chunk, Addr addr) -{ - AVERT(Chunk, chunk); - /* addr is arbitrary */ - - return INDEX_OF_ADDR(chunk, addr); -} - - -/* Page table functions */ - -/* .tract.critical: These Tract functions are low-level and are on - * the [critical path](../design/critical-path.txt) in various ways. The - * more common therefore use AVER_CRITICAL. - */ - - -/* TractOfAddr -- return the tract the given address is in, if any - * - * If the address is within the bounds of the arena, calculate the - * page table index from the address and see if the page is allocated. - * If so, return it. - */ - -Bool TractOfAddr(Tract *tractReturn, Arena arena, Addr addr) -{ - Bool b; - Index i; - Chunk chunk; - - /* */ - AVER_CRITICAL(tractReturn != NULL); /* .tract.critical */ - AVERT_CRITICAL(Arena, arena); - - b = ChunkOfAddr(&chunk, arena, addr); - if (!b) - return FALSE; - /* */ - i = INDEX_OF_ADDR(chunk, addr); - /* .addr.free: If the page is recorded as being free then */ - /* either the page is free or it is */ - /* part of the arena tables (see .ullagepages). */ - if (BTGet(chunk->allocTable, i)) { - Page page = &chunk->pageTable[i]; - *tractReturn = PageTract(page); - return TRUE; - } - - return FALSE; -} - - -/* TractOfBaseAddr -- return a tract given a base address - * - * The address must have been allocated to some pool. - */ - -Tract TractOfBaseAddr(Arena arena, Addr addr) -{ - Tract tract = NULL; - Bool found; - - AVERT_CRITICAL(Arena, arena); - AVER_CRITICAL(AddrIsAligned(addr, arena->alignment)); - - /* Check first in the cache, see . */ - if (arena->lastTractBase == addr) { - tract = arena->lastTract; - } else { - found = TractOfAddr(&tract, arena, addr); - AVER_CRITICAL(found); - } - - AVER_CRITICAL(TractBase(tract) == addr); - return tract; -} - - -/* tractSearchInChunk -- search for a tract - * - * .tract-search: Searches for a tract in the chunk starting at page - * index i, return NULL if there is none. .tract-search.private: This - * function is private to this module and is used in the tract iteration - * protocol (TractFirst and TractNext). - */ - -static Bool tractSearchInChunk(Tract *tractReturn, Chunk chunk, Index i) -{ - AVER_CRITICAL(chunk->allocBase <= i); - AVER_CRITICAL(i <= chunk->pages); - - while(i < chunk->pages - && !(BTGet(chunk->allocTable, i) - && PageIsAllocated(&chunk->pageTable[i]))) { - ++i; - } - if (i == chunk->pages) - return FALSE; - AVER(i < chunk->pages); - *tractReturn = PageTract(&chunk->pageTable[i]); - return TRUE; -} - - -/* tractSearch - * - * Searches for the next tract in increasing address order. - * The tract returned is the next one along from addr (i.e., - * it has a base address bigger than addr and no other tract - * with a base address bigger than addr has a smaller base address). - * - * Returns FALSE if there is no tract to find (end of the arena). - */ - -static Bool tractSearch(Tract *tractReturn, Arena arena, Addr addr) -{ - Bool b; - Chunk chunk; - - b = ChunkOfAddr(&chunk, arena, addr); - if (b) { - Index i; - - i = INDEX_OF_ADDR(chunk, addr); - /* There are fewer pages than addresses, therefore the */ - /* page index can never wrap around */ - AVER_CRITICAL(i+1 != 0); - - if (tractSearchInChunk(tractReturn, chunk, i+1)) { - return TRUE; - } - } - while (ChunkOfNextAddr(&chunk, arena, addr)) { - /* If the ring was kept in address order, this could be improved. */ - addr = chunk->base; - /* Start from allocBase to skip the tables. */ - if (tractSearchInChunk(tractReturn, chunk, chunk->allocBase)) { - return TRUE; - } - } - return FALSE; -} - - -/* TractFirst -- return the first tract in the arena - * - * This is used to start an iteration over all tracts in the arena, not - * including the ones used for page tables and other arena structures. - */ - -Bool TractFirst(Tract *tractReturn, Arena arena) -{ - AVER(tractReturn != NULL); - AVERT(Arena, arena); - - /* .tractfirst.assume.nozero: We assume that there is no tract */ - /* with base address (Addr)0. Happily this assumption is sound */ - /* for a number of reasons. */ - return tractSearch(tractReturn, arena, (Addr)0); -} - - -/* TractNext -- return the "next" tract in the arena - * - * TractNext finds the tract with the lowest base address which is - * greater than a specified address. The address must be (or once - * have been) the base address of a tract. - * - * This is used as the iteration step when iterating over all - * tracts in the arena. - */ - -Bool TractNext(Tract *tractReturn, Arena arena, Addr addr) -{ - AVER_CRITICAL(tractReturn != NULL); /* .tract.critical */ - AVERT_CRITICAL(Arena, arena); - AVER_CRITICAL(AddrIsAligned(addr, arena->alignment)); - - return tractSearch(tractReturn, arena, addr); -} - - -/* PageAlloc - * - * Sets up the PageStruct for an allocated page to turn it into a Tract. - */ - -void PageAlloc(Chunk chunk, Index pi, Pool pool) -{ - Tract tract; - Addr base; - - AVERT(Chunk, chunk); - AVER(pi >= chunk->allocBase); - AVER(pi < chunk->pages); - AVER(!BTGet(chunk->allocTable, pi)); - AVERT(Pool, pool); - - tract = PageTract(&chunk->pageTable[pi]); - base = PageIndexBase(chunk, pi); - BTSet(chunk->allocTable, pi); - TractInit(tract, pool, base); - return; -} - - -/* PageInit -- initialize a page (as free) */ - -void PageInit(Chunk chunk, Index pi) -{ - AVERT(Chunk, chunk); - AVER(pi < chunk->pages); - - BTRes(chunk->allocTable, pi); - PagePool(&chunk->pageTable[pi]) = NULL; - PageType(&chunk->pageTable[pi]) = PageTypeFree; - return; -} - - -/* PageFree -- free an allocated page */ - -void PageFree(Chunk chunk, Index pi) -{ - AVERT(Chunk, chunk); - AVER(pi >= chunk->allocBase); - AVER(pi < chunk->pages); - AVER(BTGet(chunk->allocTable, pi)); - - PageInit(chunk, pi); - return; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/tract.h b/mps/code/tract.h deleted file mode 100644 index 794591f9f1b..00000000000 --- a/mps/code/tract.h +++ /dev/null @@ -1,323 +0,0 @@ -/* tract.h: PAGE TABLE INTERFACE - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - - -#ifndef tract_h -#define tract_h - -#include "mpmtypes.h" -#include "ring.h" -#include "bt.h" - - -/* TractStruct -- tract structure - * - * .tract: Tracts represent the grains of memory allocation from - * the arena. See . - * - * .bool: The hasSeg field is a boolean, but can't be represented - * as type Bool. See . - */ - -typedef struct TractStruct { /* Tract structure */ - Pool pool; /* MUST BE FIRST ( pool) */ - void *p; /* pointer for use of owning pool */ - Addr base; /* Base address of the tract */ - TraceSet white : TraceLIMIT; /* traces for which tract is white */ - unsigned int hasSeg : 1; /* does tract have a seg in p? See .bool */ -} TractStruct; - - -extern Addr (TractBase)(Tract tract); -#define TractBase(tract) ((tract)->base) -extern Addr TractLimit(Tract tract); - -#define TractPool(tract) ((tract)->pool) -#define TractP(tract) ((tract)->p) -#define TractSetP(tract, pp) ((void)((tract)->p = (pp))) -#define TractHasSeg(tract) ((Bool)(tract)->hasSeg) -#define TractSetHasSeg(tract, b) ((void)((tract)->hasSeg = (b))) -#define TractWhite(tract) ((tract)->white) -#define TractSetWhite(tract, w) ((void)((tract)->white = (w))) - -extern Bool TractCheck(Tract tract); -extern void TractInit(Tract tract, Pool pool, Addr base); -extern void TractFinish(Tract tract); - - -/* TRACT_*SEG -- Test / set / unset seg->tract associations - * - * These macros all multiply evaluate the tract parameter - */ - -#define TRACT_SEG(segReturn, tract) \ - (TractHasSeg(tract) && ((*(segReturn) = (Seg)TractP(tract)), TRUE)) - -#define TRACT_SET_SEG(tract, seg) \ - (TractSetHasSeg(tract, TRUE), TractSetP(tract, seg)) - -#define TRACT_UNSET_SEG(tract) \ - (TractSetHasSeg(tract, FALSE), TractSetP(tract, NULL)) - - -/* PageStruct -- Page structure - * - * .page-table: The page table (defined as a PageStruct array) - * is central to the design of the arena. - * See .*. - * - * .page: The "pool" field must be the first field of the "tail" - * field of this union. See . - * - * .states: Pages (hence PageStructs that describe them) can be in - * one of 3 states: - * allocated (to a pool as tracts) - * allocated pages are mapped - * BTGet(allocTable, i) == 1 - * PageRest()->pool == pool - * spare - * these pages are mapped - * BTGet(allocTable, i) == 0 - * PageRest()->pool == NULL - * PageRest()->type == PageTypeSpare - * free - * these pages are not mapped - * BTGet(allocTable, i) == 0 - * PTE may itself be unmapped, but when it is (use pageTableMapped - * to determine whether page occupied by page table is mapped): - * PageRest()->pool == NULL - * PageRest()->type == PageTypeFree - */ - -enum {PageTypeSpare=1, PageTypeFree}; - -typedef struct PageStruct { /* page structure */ - union { - TractStruct tractStruct; /* allocated tract */ - struct { - Pool pool; /* NULL, must be first field (.page) */ - int type; /* see .states */ - } rest; /* other (non-allocated) page */ - } the; -} PageStruct; - - -/* PageTract -- tract descriptor of an allocated page */ - -#define PageTract(page) (&(page)->the.tractStruct) - -/* PageOfTract -- VM page descriptor from arena tract */ - -#define PageOfTract(tract) PARENT(PageStruct, the.tractStruct, (tract)) - -/* PagePool -- pool field of a page */ - -#define PagePool(page) ((page)->the.rest.pool) - -/* PageIsAllocated -- is a page allocated? - * - * See . - */ - -#define PageIsAllocated(page) ((page)->the.rest.pool != NULL) - -/* PageType -- type of page */ - -#define PageType(page) ((page)->the.rest.type) - - -/* Chunks */ - - -#define ChunkSig ((Sig)0x519C804C) /* SIGnature CHUNK */ - -typedef struct ChunkStruct { - Sig sig; /* */ - Serial serial; /* serial within the arena */ - Arena arena; /* parent arena */ - RingStruct chunkRing; /* ring of all chunks in arena */ - Size pageSize; /* size of pages */ - Shift pageShift; /* log2 of page size, for shifts */ - Addr base; /* base address of chunk */ - Addr limit; /* limit address of chunk */ - Index allocBase; /* index of first page allocatable to clients */ - Index pages; /* index of the page after the last allocatable page */ - BT allocTable; /* page allocation table */ - PageStruct* pageTable; /* the page table */ - Count pageTablePages; /* number of pages occupied by page table */ -} ChunkStruct; - - -#define ChunkArena(chunk) ((chunk)->arena) -#define ChunkPageSize(chunk) ((chunk)->pageSize) -#define ChunkPageShift(chunk) ((chunk)->pageShift) -#define ChunkPagesToSize(chunk, pages) ((Size)(pages) << (chunk)->pageShift) -#define ChunkSizeToPages(chunk, size) ((Count)((size) >> (chunk)->pageShift)) - -extern Bool ChunkCheck(Chunk chunk); -extern Res ChunkInit(Chunk chunk, Arena arena, - Addr base, Addr limit, Align pageSize, BootBlock boot); -extern void ChunkFinish(Chunk chunk); - -extern Bool ChunkCacheEntryCheck(ChunkCacheEntry entry); -extern void ChunkCacheEntryInit(ChunkCacheEntry entry); - -extern Bool ChunkOfAddr(Chunk *chunkReturn, Arena arena, Addr addr); - -/* CHUNK_OF_ADDR -- return the chunk containing an address - * - * arena and addr are evaluated multiple times. - */ - -#define CHUNK_OF_ADDR(chunkReturn, arena, addr) \ - (((arena)->chunkCache.base <= (addr) && (addr) < (arena)->chunkCache.limit) \ - ? (*(chunkReturn) = (arena)->chunkCache.chunk, TRUE) \ - : ChunkOfAddr(chunkReturn, arena, addr)) - - -/* AddrPageBase -- the base of the page this address is on */ - -#define AddrPageBase(chunk, addr) \ - AddrAlignDown((addr), ChunkPageSize(chunk)) - - -/* Page table functions */ - -extern Tract TractOfBaseAddr(Arena arena, Addr addr); -extern Bool TractOfAddr(Tract *tractReturn, Arena arena, Addr addr); - -/* TRACT_OF_ADDR -- return the tract containing an address */ - -#define TRACT_OF_ADDR(tractReturn, arena, addr) \ - BEGIN \ - Arena _arena = (arena); \ - Addr _addr = (addr); \ - Chunk _chunk; \ - Index _i; \ - \ - if (CHUNK_OF_ADDR(&_chunk, _arena, _addr)) { \ - _i = INDEX_OF_ADDR(_chunk, _addr); \ - if (BTGet(_chunk->allocTable, _i)) \ - *(tractReturn) = PageTract(&_chunk->pageTable[_i]); \ - else \ - *(tractReturn) = NULL; \ - } else \ - *(tractReturn) = NULL; \ - END - - -/* INDEX_OF_ADDR -- return the index of the page containing an address - * - * .index.addr: The address passed may be equal to the limit of the - * arena, in which case the last page index plus one is returned. (It - * is, in a sense, the limit index of the page table.) - */ - -#define INDEX_OF_ADDR(chunk, addr) \ - ((Index)ChunkSizeToPages(chunk, AddrOffset((chunk)->base, addr))) - -extern Index IndexOfAddr(Chunk chunk, Addr addr); - - -/* PageIndexBase -- map page index to base address of page - * - * See - */ - -#define PageIndexBase(chunk, i) \ - AddrAdd((chunk)->base, ChunkPagesToSize(chunk, i)) - - -/* TractAverContiguousRange -- verify that range is contiguous */ - -#define TractAverContiguousRange(arena, rangeBase, rangeLimit) \ - BEGIN \ - Chunk _ch = NULL; \ - \ - UNUSED(_ch); \ - AVER(ChunkOfAddr(&_ch, arena, rangeBase) && (rangeLimit) <= _ch->limit); \ - END - - -extern Bool TractFirst(Tract *tractReturn, Arena arena); -extern Bool TractNext(Tract *tractReturn, Arena arena, Addr addr); - - -/* TRACT_TRACT_FOR -- iterate over a range of tracts - * - * See . - * Parameters arena & limit are evaluated multiple times. - * Check first tract & last tract lie with the same chunk. - */ - -#define TRACT_TRACT_FOR(tract, addr, arena, firstTract, limit) \ - tract = (firstTract); addr = TractBase(tract); \ - TractAverContiguousRange(arena, addr, limit); \ - for(; tract != NULL; \ - (addr = AddrAdd(addr, (arena)->alignment)), \ - (addr < (limit) ? \ - (tract = PageTract(PageOfTract(tract) + 1)) : \ - (tract = NULL) /* terminate loop */)) - - -/* TRACT_FOR -- iterate over a range of tracts - * - * See . - * Parameters arena & limit are evaluated multiple times. - */ - -#define TRACT_FOR(tract, addr, arena, base, limit) \ - TRACT_TRACT_FOR(tract, addr, arena, TractOfBaseAddr(arena, base), limit) - - -extern void PageAlloc(Chunk chunk, Index pi, Pool pool); -extern void PageInit(Chunk chunk, Index pi); -extern void PageFree(Chunk chunk, Index pi); - - -#endif /* tract_h */ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/version.c b/mps/code/version.c deleted file mode 100644 index 03e7b78334e..00000000000 --- a/mps/code/version.c +++ /dev/null @@ -1,104 +0,0 @@ -/* version.c: VERSION INSPECTION - * - * $Id$ - * Copyright (c) 2001-2002, 2006-2010 Ravenbrook Limited. - * See end of file for license. - * - * PURPOSE - * - * The purpose of this module is to provide a means by which the - * version of the MM library being used can be determined. - * - * DESIGN - * - * .design: See , but -- to let you in on a - * secret -- it works by declaring a string with all the necessary info - * in. */ - -#include "mpm.h" - -SRCID(version, "$Id$"); - - -/* MPS_RELEASE -- the release name - * - * .release: When making a new release, change the expansion of - * MPS_RELEASE to be a string of the form "release/1.106.1" or - * whatever. - * - * (Note: before 2006-02-01 the style was "release.epcore.chub") - */ - -#define MPS_RELEASE "release/1.110.0" - - -/* MPSCopyrightNotice -- copyright notice for the binary - * - * .copyright.year: This one should have the current year in it - * (assuming we've made any substantial changes to the library this year). - */ - -char MPSCopyrightNotice[] = - "Portions copyright (c) 2010 Ravenbrook Limited and Global Graphics Software."; - - -/* MPSVersion -- return version string - * - * The value of MPSVersion is a declared object comprising the - * concatenation of all the version info. The "@(#)" prefix - * is the convention used by the BSD Unix command what(1); - * see also guide.mps.version. - */ - -char MPSVersionString[] = - "@(#)Ravenbrook MPS, " - "product." MPS_PROD_STRING ", " MPS_RELEASE ", platform." MPS_PF_STRING - ", variety." MPS_VARIETY_STRING ", compiled on " __DATE__ " " __TIME__; - -char *MPSVersion(void) -{ - return MPSVersionString; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2006-2010 Ravenbrook Limited - * . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/vman.c b/mps/code/vman.c deleted file mode 100644 index c4d4060f89a..00000000000 --- a/mps/code/vman.c +++ /dev/null @@ -1,246 +0,0 @@ -/* vman.c: ANSI VM: MALLOC-BASED PSEUDO MEMORY MAPPING - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" - -#include /* for malloc and free */ -#include /* for memset */ - -SRCID(vman, "$Id$"); - - -/* VMStruct -- virtual memory structure */ - -#define VMSig ((Sig)0x519B3999) /* SIGnature VM */ - -/* ANSI fake VM structure, see */ -typedef struct VMStruct { - Sig sig; /* */ - Addr base, limit; /* boundaries of malloc'd memory */ - void *block; /* pointer to malloc'd block, for free() */ - Size reserved; /* total reserved address space */ - Size mapped; /* total mapped memory */ -} VMStruct; - - -/* VMCheck -- check a VM structure */ - -Bool VMCheck(VM vm) -{ - CHECKS(VM, vm); - CHECKL(vm->base != (Addr)0); - CHECKL(vm->limit != (Addr)0); - CHECKL(vm->base < vm->limit); - CHECKL(AddrIsAligned(vm->base, VMANPageALIGNMENT)); - CHECKL(AddrIsAligned(vm->limit, VMANPageALIGNMENT)); - CHECKL(vm->block != NULL); - CHECKL((Addr)vm->block <= vm->base); - CHECKL(vm->mapped <= vm->reserved); - return TRUE; -} - - -/* VMAlign -- return the page size */ - -Align VMAlign(VM vm) -{ - UNUSED(vm); - return VMANPageALIGNMENT; -} - - -/* VMCreate -- reserve some virtual address space, and create a VM structure */ - -Res VMCreate(VM *vmReturn, Size size) -{ - VM vm; - - AVER(vmReturn != NULL); - - /* Note that because we add VMANPageALIGNMENT rather than */ - /* VMANPageALIGNMENT-1 we are not in danger of overflowing */ - /* vm->limit even if malloc were perverse enough to give us */ - /* a block at the end of memory. */ - size = SizeAlignUp(size, VMANPageALIGNMENT) + VMANPageALIGNMENT; - if ((size < VMANPageALIGNMENT) || (size > (Size)(size_t)-1)) - return ResRESOURCE; - - vm = (VM)malloc(sizeof(VMStruct)); - if (vm == NULL) - return ResMEMORY; - - vm->block = malloc((size_t)size); - if (vm->block == NULL) { - free(vm); - return ResMEMORY; - } - - vm->base = AddrAlignUp((Addr)vm->block, VMANPageALIGNMENT); - vm->limit = AddrAdd(vm->base, size - VMANPageALIGNMENT); - AVER(vm->limit < AddrAdd((Addr)vm->block, size)); - - memset((void *)vm->block, VMJunkBYTE, size); - - /* Lie about the reserved address space, to simulate real */ - /* virtual memory. */ - vm->reserved = size - VMANPageALIGNMENT; - vm->mapped = (Size)0; - - vm->sig = VMSig; - - AVERT(VM, vm); - - EVENT3(VMCreate, vm, vm->base, vm->limit); - *vmReturn = vm; - return ResOK; -} - - -/* VMDestroy -- destroy the VM structure */ - -void VMDestroy(VM vm) -{ - /* All vm areas should have been unmapped. */ - AVERT(VM, vm); - AVER(vm->mapped == (Size)0); - AVER(vm->reserved == AddrOffset(vm->base, vm->limit)); - - memset((void *)vm->base, VMJunkBYTE, AddrOffset(vm->base, vm->limit)); - free(vm->block); - - vm->sig = SigInvalid; - free(vm); - - EVENT1(VMDestroy, vm); -} - - -/* VMBase -- return the base address of the memory reserved */ - -Addr VMBase(VM vm) -{ - AVERT(VM, vm); - - return vm->base; -} - - -/* VMLimit -- return the limit address of the memory reserved */ - -Addr VMLimit(VM vm) -{ - AVERT(VM, vm); - - return vm->limit; -} - - -/* VMReserved -- return the amount of address space reserved */ - -Size VMReserved(VM vm) -{ - AVERT(VM, vm); - - return vm->reserved; -} - - -/* VMMapped -- return the amount of memory actually mapped */ - -Size VMMapped(VM vm) -{ - AVERT(VM, vm); - - return vm->mapped; -} - - -/* VMMap -- map the given range of memory */ - -Res VMMap(VM vm, Addr base, Addr limit) -{ - Size size; - - AVER(base != (Addr)0); - AVER(vm->base <= base); - AVER(base < limit); - AVER(limit <= vm->limit); - AVER(AddrIsAligned(base, VMANPageALIGNMENT)); - AVER(AddrIsAligned(limit, VMANPageALIGNMENT)); - - size = AddrOffset(base, limit); - memset((void *)base, (int)0, size); - - vm->mapped += size; - - EVENT3(VMMap, vm, base, limit); - return ResOK; -} - - -/* VMUnmap -- unmap the given range of memory */ - -void VMUnmap(VM vm, Addr base, Addr limit) -{ - Size size; - - AVER(base != (Addr)0); - AVER(vm->base <= base); - AVER(base < limit); - AVER(limit <= vm->limit); - AVER(AddrIsAligned(base, VMANPageALIGNMENT)); - AVER(AddrIsAligned(limit, VMANPageALIGNMENT)); - - size = AddrOffset(base, limit); - memset((void *)base, 0xCD, size); - - AVER(vm->mapped >= size); - vm->mapped -= size; - - EVENT3(VMUnmap, vm, base, limit); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/vmix.c b/mps/code/vmix.c deleted file mode 100644 index bc26b647dc8..00000000000 --- a/mps/code/vmix.c +++ /dev/null @@ -1,352 +0,0 @@ -/* vmix.c: VIRTUAL MEMORY MAPPING FOR UNIX (ISH) - * - * $Id$ - * Copyright (c) 2001,2007 Ravenbrook Limited. See end of file for license. - * - * .purpose: This is the implementation of the virtual memory mapping - * interface (vm.h) for Unix-like operating systems. It was created - * by copying vmfr.c (the FreeBSD) implementation (as that seemed to - * use the most standards conforming interfaces). vmfr.c was itself - * copied from vli.c (Linux) which was itself copied from vmo1.c (OSF/1 - * / DIGITAL UNIX / Tru64). - * - * .deployed: Currently used on Darwin (OS X) and FreeBSD. - * - * .design: See . .design.mmap: mmap(2) is used to - * reserve address space by creating a mapping with page access none. - * mmap(2) is used to map pages onto store by creating a copy-on-write - * (MAP_PRIVATE) mapping with the flag MAP_ANON. - * - * .non-standard: Note that the MAP_ANON flag is non-standard; it is - * available on Darwin and FreeBSD. .non-standard.linux: Linux - * seems to use MAP_ANONYMOUS instead. Some Linux systems make MAP_ANON - * available and deprecate it. .non-standard.sesame: On Linux getting - * a definition of MAP_ANON requires a macro to be defined prior to - * . - * - * .assume.not-last: The implementation of VMCreate assumes that - * mmap() will not choose a region which contains the last page - * in the address space, so that the limit of the mapped area - * is representable. - * - * .assume.mmap.err: ENOMEM is the only error we really expect to - * get from mmap. The others are either caused by invalid params - * or features we don't use. See mmap(2) for details. - * - * .remap: Possibly this should use mremap to reduce the number of - * distinct mappings. According to our current testing, it doesn't - * seem to be a problem. - */ - -/* .non-standard.sesame */ -#define _BSD_SOURCE 1 - -/* for mmap(2), munmap(2) */ -#include -#include - -/* for errno(2) */ -#include - -/* for getpagesize(3) */ -#include - -#include "mpm.h" - - -#if !defined(MPS_OS_FR) && !defined(MPS_OS_XC) && !defined(MPS_OS_LI) -#error "vmix.c is Unix-like specific, currently MPS_OS_FR XC LI" -#endif - -SRCID(vmix, "$Id$"); - - -/* VMStruct -- virtual memory structure */ - -#define VMSig ((Sig)0x519B3999) /* SIGnature VM */ - -typedef struct VMStruct { - Sig sig; /* */ - Align align; /* page size */ - Addr base, limit; /* boundaries of reserved space */ - Size reserved; /* total reserved address space */ - Size mapped; /* total mapped memory */ -} VMStruct; - - -/* VMAlign -- return page size */ - -Align VMAlign(VM vm) -{ - return vm->align; -} - - -/* VMCheck -- check a VM */ - -Bool VMCheck(VM vm) -{ - CHECKS(VM, vm); - CHECKL(vm->base != 0); - CHECKL(vm->limit != 0); - CHECKL(vm->base < vm->limit); - CHECKL(vm->mapped <= vm->reserved); - CHECKL(SizeIsP2(vm->align)); - CHECKL(AddrIsAligned(vm->base, vm->align)); - CHECKL(AddrIsAligned(vm->limit, vm->align)); - return TRUE; -} - - -/* VMCreate -- reserve some virtual address space, and create a VM structure */ - -Res VMCreate(VM *vmReturn, Size size) -{ - Align align; - VM vm; - int pagesize; - void *addr; - Res res; - - AVER(vmReturn != NULL); - - /* Find out the page size from the OS */ - pagesize = getpagesize(); - /* check the actual returned pagesize will fit in an object of */ - /* type Align. */ - AVER(pagesize > 0); - AVER((unsigned long)pagesize <= (unsigned long)(Align)-1); - align = (Align)pagesize; - AVER(SizeIsP2(align)); - size = SizeAlignUp(size, align); - if((size == 0) || (size > (Size)(size_t)-1)) - return ResRESOURCE; - - /* Map in a page to store the descriptor on. */ - addr = mmap(0, (size_t)SizeAlignUp(sizeof(VMStruct), align), - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, - -1, 0); - /* On Darwin the MAP_FAILED return value is not documented, but does - * work. MAP_FAILED _is_ documented by POSIX. - */ - if(addr == MAP_FAILED) { - int e = errno; - AVER(e == ENOMEM); /* .assume.mmap.err */ - return ResMEMORY; - } - vm = (VM)addr; - - vm->align = align; - - /* See .assume.not-last. */ - addr = mmap(0, (size_t)size, - PROT_NONE, MAP_ANON | MAP_PRIVATE, - -1, 0); - if(addr == MAP_FAILED) { - int e = errno; - AVER(e == ENOMEM); /* .assume.mmap.err */ - res = ResRESOURCE; - goto failReserve; - } - - vm->base = (Addr)addr; - vm->limit = AddrAdd(vm->base, size); - vm->reserved = size; - vm->mapped = (Size)0; - - vm->sig = VMSig; - - AVERT(VM, vm); - - EVENT3(VMCreate, vm, vm->base, vm->limit); - DIAG_SINGLEF(( - "VM_ix_Create_ok", - "[$W..<$W>..$W)", - (WriteFW)vm->base, - (WriteFW)AddrOffset(vm->base, vm->limit), - (WriteFW)vm->limit, - NULL )); - - *vmReturn = vm; - return ResOK; - -failReserve: - (void)munmap((void *)vm, (size_t)SizeAlignUp(sizeof(VMStruct), align)); - return res; -} - - -/* VMDestroy -- release all address space and destroy VM structure */ - -void VMDestroy(VM vm) -{ - int r; - - AVERT(VM, vm); - AVER(vm->mapped == (Size)0); - - DIAG_SINGLEF(( - "VM_ix_Destroy", - "[$W..<$W>..$W)", - (WriteFW)vm->base, - (WriteFW)AddrOffset(vm->base, vm->limit), - (WriteFW)vm->limit, - NULL )); - - /* This appears to be pretty pointless, since the descriptor */ - /* page is about to vanish completely. However, munmap might fail */ - /* for some reason, and this would ensure that it was still */ - /* discovered if sigs were being checked. */ - vm->sig = SigInvalid; - - r = munmap((void *)vm->base, (size_t)AddrOffset(vm->base, vm->limit)); - AVER(r == 0); - r = munmap((void *)vm, - (size_t)SizeAlignUp(sizeof(VMStruct), vm->align)); - AVER(r == 0); - - EVENT1(VMDestroy, vm); -} - - -/* VMBase -- return the base address of the memory reserved */ - -Addr VMBase(VM vm) -{ - AVERT(VM, vm); - - return vm->base; -} - - -/* VMLimit -- return the limit address of the memory reserved */ - -Addr VMLimit(VM vm) -{ - AVERT(VM, vm); - - return vm->limit; -} - - -/* VMReserved -- return the amount of memory reserved */ - -Size VMReserved(VM vm) -{ - AVERT(VM, vm); - - return vm->reserved; -} - - -/* VMMapped -- return the amount of memory actually mapped */ - -Size VMMapped(VM vm) -{ - AVERT(VM, vm); - - return vm->mapped; -} - - -/* VMMap -- map the given range of memory */ - -Res VMMap(VM vm, Addr base, Addr limit) -{ - Size size; - - AVERT(VM, vm); - AVER(sizeof(void *) == sizeof(Addr)); - AVER(base < limit); - AVER(base >= vm->base); - AVER(limit <= vm->limit); - AVER(AddrIsAligned(base, vm->align)); - AVER(AddrIsAligned(limit, vm->align)); - - size = AddrOffset(base, limit); - - if(mmap((void *)base, (size_t)size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_ANON | MAP_PRIVATE | MAP_FIXED, - -1, 0) - == MAP_FAILED) { - AVER(errno == ENOMEM); /* .assume.mmap.err */ - return ResMEMORY; - } - - vm->mapped += size; - - EVENT3(VMMap, vm, base, limit); - return ResOK; -} - - -/* VMUnmap -- unmap the given range of memory */ - -void VMUnmap(VM vm, Addr base, Addr limit) -{ - Size size; - void *addr; - - AVERT(VM, vm); - AVER(base < limit); - AVER(base >= vm->base); - AVER(limit <= vm->limit); - AVER(AddrIsAligned(base, vm->align)); - AVER(AddrIsAligned(limit, vm->align)); - - size = AddrOffset(base, limit); - - /* see */ - addr = mmap((void *)base, (size_t)size, - PROT_NONE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, - -1, 0); - AVER(addr == (void *)base); - - vm->mapped -= size; - - EVENT3(VMUnmap, vm, base, limit); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2007 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/vmw3.c b/mps/code/vmw3.c deleted file mode 100644 index 6bff4fe757a..00000000000 --- a/mps/code/vmw3.c +++ /dev/null @@ -1,312 +0,0 @@ -/* vmw3.c: VIRTUAL MEMORY MAPPING FOR WIN32 - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - * - * .design: See . - * - * .purpose: This is the implementation of the virtual memory mapping - * interface (vm.h) for Win32s. - * - * The documentation for Win32 used is the "Win32 Programmer's Reference" - * provided with Microsoft Visual C++ 2.0. - * - * VirtualAlloc is used to reserve address space and to "commit" (map) - * address ranges onto storage. VirtualFree is used to release and - * "decommit" (unmap) pages. These functions are documented in the - * Win32 SDK help, under System Services/Memory Management. - * - * .assume.free.success: We assume that VirtualFree will never return - * an error; this is because we always pass in legal parameters - * (hopefully). - * - * .assume.not-last: We assume that VirtualAlloc will never return - * a block of memory that occupies the last page in memory, so - * that limit is representable and bigger than base. - * - * .assume.lpvoid-addr: We assume that the windows type LPVOID and - * the MM type Addr are assignment-compatible. - * - * .assume.sysalign: We assume that the page size on the system - * is a power of two. - * - * Notes - * 1. GetSystemInfo returns a thing called szAllocationGranularity - * the purpose of which is unclear but which might affect the - * reservation of address space. Experimentally, it does not. - * Microsoft's documentation is extremely unclear on this point. - * richard 1995-02-15 - */ - -#include "mpm.h" - -#ifndef MPS_OS_W3 -#error "vmw3.c is Win32 specific, but MPS_OS_W3 is not set" -#endif -#ifdef VM_RM -#error "vmw3.c compiled with VM_RM set" -#endif - -#include "mpswin.h" - -SRCID(vmw3, "$Id$"); - - -/* VMStruct -- virtual memory structure */ - -#define VMSig ((Sig)0x519B3999) /* SIGnature VM */ - -typedef struct VMStruct { - Sig sig; /* */ - Align align; /* page size */ - Addr base, limit; /* boundaries of reserved space */ - Size reserved; /* total reserved address space */ - Size mapped; /* total mapped memory */ -} VMStruct; - - -/* VMAlign -- return the page size */ - -Align VMAlign(VM vm) -{ - AVERT(VM, vm); - - return vm->align; -} - - -/* VMCheck -- check a VM structure */ - -Bool VMCheck(VM vm) -{ - CHECKS(VM, vm); - CHECKL(vm->base != 0); - CHECKL(vm->limit != 0); - CHECKL(vm->base < vm->limit); - CHECKL(vm->mapped <= vm->reserved); - CHECKL(AddrIsAligned(vm->base, vm->align)); - CHECKL(AddrIsAligned(vm->limit, vm->align)); - return TRUE; -} - - -/* VMCreate -- reserve some virtual address space, and create a VM structure */ - -Res VMCreate(VM *vmReturn, Size size) -{ - LPVOID vbase; - SYSTEM_INFO si; - Align align; - VM vm; - Res res; - BOOL b; - - AVER(vmReturn != NULL); - - AVER(COMPATTYPE(LPVOID, Addr)); /* .assume.lpvoid-addr */ - AVER(COMPATTYPE(SIZE_T, Size)); - - GetSystemInfo(&si); - align = (Align)si.dwPageSize; - AVER((DWORD)align == si.dwPageSize); /* check it didn't truncate */ - AVER(SizeIsP2(align)); /* see .assume.sysalign */ - size = SizeAlignUp(size, align); - if ((size == 0) || (size > (Size)(SIZE_T)-1)) - return ResRESOURCE; - - /* Allocate the vm descriptor. This is likely to be wasteful. */ - vbase = VirtualAlloc(NULL, SizeAlignUp(sizeof(VMStruct), align), - MEM_COMMIT, PAGE_READWRITE); - if (vbase == NULL) - return ResMEMORY; - vm = (VM)vbase; - - /* Allocate the address space. */ - vbase = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS); - if (vbase == NULL) { - res = ResRESOURCE; - goto failReserve; - } - - AVER(AddrIsAligned(vbase, align)); - - vm->align = align; - vm->base = (Addr)vbase; - vm->limit = AddrAdd(vbase, size); - vm->reserved = size; - vm->mapped = 0; - AVER(vm->base < vm->limit); /* .assume.not-last */ - - vm->sig = VMSig; - AVERT(VM, vm); - - EVENT3(VMCreate, vm, vm->base, vm->limit); - *vmReturn = vm; - return ResOK; - -failReserve: - b = VirtualFree((LPVOID)vm, (SIZE_T)0, MEM_RELEASE); - AVER(b != 0); - return res; -} - - -/* VMDestroy -- destroy the VM structure */ - -void VMDestroy(VM vm) -{ - BOOL b; - - AVERT(VM, vm); - AVER(vm->mapped == 0); - - /* This appears to be pretty pointless, since the vm descriptor page - * is about to vanish completely. However, the VirtualFree might - * fail and it would be nice to have a dead sig there. */ - vm->sig = SigInvalid; - - b = VirtualFree((LPVOID)vm->base, (SIZE_T)0, MEM_RELEASE); - AVER(b != 0); - - b = VirtualFree((LPVOID)vm, (SIZE_T)0, MEM_RELEASE); - AVER(b != 0); - EVENT1(VMDestroy, vm); -} - - -/* VMBase -- return the base address of the memory reserved */ - -Addr VMBase(VM vm) -{ - AVERT(VM, vm); - - return vm->base; -} - - -/* VMLimit -- return the limit address of the memory reserved */ - -Addr VMLimit(VM vm) -{ - AVERT(VM, vm); - - return vm->limit; -} - - -/* VMReserved -- return the amount of address space reserved */ - -Size VMReserved(VM vm) -{ - AVERT(VM, vm); - - return vm->reserved; -} - - -/* VMMapped -- return the amount of memory actually mapped */ - -Size VMMapped(VM vm) -{ - AVERT(VM, vm); - - return vm->mapped; -} - - -/* VMMap -- map the given range of memory */ - -Res VMMap(VM vm, Addr base, Addr limit) -{ - LPVOID b; - Align align; - - AVERT(VM, vm); - align = vm->align; - AVER(AddrIsAligned(base, align)); - AVER(AddrIsAligned(limit, align)); - AVER(vm->base <= base); - AVER(base < limit); - AVER(limit <= vm->limit); - - /* .improve.query-map: We could check that the pages we are about to - * map are unmapped using VirtualQuery. */ - - b = VirtualAlloc((LPVOID)base, (SIZE_T)AddrOffset(base, limit), - MEM_COMMIT, PAGE_EXECUTE_READWRITE); - if (b == NULL) - return ResMEMORY; - AVER((Addr)b == base); /* base should've been aligned */ - - vm->mapped += AddrOffset(base, limit); - - EVENT3(VMMap, vm, base, limit); - return ResOK; -} - - -/* VMUnmap -- unmap the given range of memory */ - -void VMUnmap(VM vm, Addr base, Addr limit) -{ - Align align; - BOOL b; - - AVERT(VM, vm); - align = vm->align; - AVER(AddrIsAligned(base, align)); - AVER(AddrIsAligned(limit, align)); - AVER(vm->base <= base); - AVER(base < limit); - AVER(limit <= vm->limit); - - /* .improve.query-unmap: Could check that the pages we are about */ - /* to unmap are mapped, using VirtualQuery. */ - b = VirtualFree((LPVOID)base, (SIZE_T)AddrOffset(base, limit), MEM_DECOMMIT); - AVER(b != 0); /* .assume.free.success */ - vm->mapped -= AddrOffset(base, limit); - - EVENT3(VMUnmap, vm, base, limit); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/w3i3mv.nmk b/mps/code/w3i3mv.nmk deleted file mode 100644 index ebe971e1626..00000000000 --- a/mps/code/w3i3mv.nmk +++ /dev/null @@ -1,221 +0,0 @@ -# w3i3mv.nmk: WINDOWS (INTEL) NMAKE FILE -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - -PFM = w3i3mv - -# /Gs appears to be necessary to suppress stack checks. Stack checks -# (if not suppressed) generate a dependency on the C library, __chkesp, -# which causes the linker step to fail when building the DLL, mpsdy.dll. -PFMDEFS = /DCONFIG_PF_STRING="w3i3mv" /DCONFIG_PF_W3I3MV \ - /DWIN32 /D_WINDOWS /Gs - -MPM = \ - \ - \ - \ - \ - \ - \ - \ - -PLINTH = -AMC = -AMS = -AWL = -LO = -SNC = -MVFF = -N = -DW = -FMTTEST = -POOLN = -TESTLIB = - - -!INCLUDE commpre.nmk - - -# Source to object file mappings and CFLAGS amalgamation -# -# %%VARIETY %%PART: When adding a new variety or part, add new macros which -# expand to the files included in the part for each variety -# -# %%VARIETY: When adding a new variety, add a CFLAGS macro which expands to -# the flags that that variety should use when compiling C. And a LINKFLAGS -# macro which expands to the flags that the variety should use when building -# executables. And a LIBFLAGS macro which expands to the flags that the -# variety should use when building libraries - -!IF "$(VARIETY)" == "hot" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT) -MPMOBJ0 = $(MPM:<=w3i3mv\hot\) -PLINTHOBJ0 = $(PLINTH:<=w3i3mv\hot\) -AMSOBJ0 = $(AMS:<=w3i3mv\hot\) -AMCOBJ0 = $(AMC:<=w3i3mv\hot\) -AWLOBJ0 = $(AWL:<=w3i3mv\hot\) -LOOBJ0 = $(LO:<=w3i3mv\hot\) -SNCOBJ0 = $(SNC:<=w3i3mv\hot\) -MVFFOBJ0 = $(MVFF:<=w3i3mv\hot\) -DWOBJ0 = $(DW:<=w3i3mv\hot\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i3mv\hot\) -POOLNOBJ0 = $(POOLN:<=w3i3mv\hot\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\hot\) - -!ELSEIF "$(VARIETY)" == "di" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFDI) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFDI) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSDI) -MPMOBJ0 = $(MPM:<=w3i3mv\di\) -PLINTHOBJ0 = $(PLINTH:<=w3i3mv\di\) -AMSOBJ0 = $(AMS:<=w3i3mv\di\) -AMCOBJ0 = $(AMC:<=w3i3mv\di\) -AWLOBJ0 = $(AWL:<=w3i3mv\di\) -LOOBJ0 = $(LO:<=w3i3mv\di\) -SNCOBJ0 = $(SNC:<=w3i3mv\di\) -MVFFOBJ0 = $(MVFF:<=w3i3mv\di\) -DWOBJ0 = $(DW:<=w3i3mv\di\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i3mv\di\) -POOLNOBJ0 = $(POOLN:<=w3i3mv\di\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\di\) - -!ELSEIF "$(VARIETY)" == "cool" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL) -MPMOBJ0 = $(MPM:<=w3i3mv\cool\) -PLINTHOBJ0 = $(PLINTH:<=w3i3mv\cool\) -AMSOBJ0 = $(AMS:<=w3i3mv\cool\) -AMCOBJ0 = $(AMC:<=w3i3mv\cool\) -AWLOBJ0 = $(AWL:<=w3i3mv\cool\) -LOOBJ0 = $(LO:<=w3i3mv\cool\) -SNCOBJ0 = $(SNC:<=w3i3mv\cool\) -MVFFOBJ0 = $(MVFF:<=w3i3mv\cool\) -DWOBJ0 = $(DW:<=w3i3mv\cool\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i3mv\cool\) -POOLNOBJ0 = $(POOLN:<=w3i3mv\cool\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\cool\) - -!ELSEIF "$(VARIETY)" == "ti" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFTI) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFTI) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSTI) -MPMOBJ0 = $(MPM:<=w3i3mv\ti\) -PLINTHOBJ0 = $(PLINTH:<=w3i3mv\ti\) -AMSOBJ0 = $(AMS:<=w3i3mv\ti\) -AMCOBJ0 = $(AMC:<=w3i3mv\ti\) -AWLOBJ0 = $(AWL:<=w3i3mv\ti\) -LOOBJ0 = $(LO:<=w3i3mv\ti\) -SNCOBJ0 = $(SNC:<=w3i3mv\ti\) -MVFFOBJ0 = $(MVFF:<=w3i3mv\ti\) -DWOBJ0 = $(DW:<=w3i3mv\ti\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i3mv\ti\) -POOLNOBJ0 = $(POOLN:<=w3i3mv\ti\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\ti\) - -!ELSEIF "$(VARIETY)" == "rash" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH) -MPMOBJ0 = $(MPM:<=w3i3mv\rash\) -PLINTHOBJ0 = $(PLINTH:<=w3i3mv\rash\) -AMSOBJ0 = $(AMS:<=w3i3mv\rash\) -AMCOBJ0 = $(AMC:<=w3i3mv\rash\) -AWLOBJ0 = $(AWL:<=w3i3mv\rash\) -LOOBJ0 = $(LO:<=w3i3mv\rash\) -SNCOBJ0 = $(SNC:<=w3i3mv\rash\) -MVFFOBJ0 = $(MVFF:<=w3i3mv\rash\) -DWOBJ0 = $(DW:<=w3i3mv\rash\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i3mv\rash\) -POOLNOBJ0 = $(POOLN:<=w3i3mv\rash\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\rash\) - -#!ELSEIF "$(VARIETY)" == "cv" -#CFLAGS=$(CFLAGSCOMMON) $(CFCV) -#LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCV) -#LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCV) -#MPMOBJ0 = $(MPM:<=w3i3mv\cv\) -#MPMOBJ = $(MPMOBJ0:>=.obj) -#PLINTHOBJ0 = $(PLINTH:<=w3i3mv\cv\) -#PLINTHOBJ = $(PLINTHOBJ0:>=.obj) -#AMSOBJ0 = $(AMS:<=w3i3mv\cv\) -#AMSOBJ = $(AMSOBJ0:>=.obj) -#AMCOBJ0 = $(AMC:<=w3i3mv\cv\) -#AMCOBJ = $(AMCOBJ0:>=.obj) -#AWLOBJ0 = $(AWL:<=w3i3mv\cv\) -#AWLOBJ = $(AWLOBJ0:>=.obj) -#LOOBJ0 = $(LO:<=w3i3mv\cv\) -#LOOBJ = $(LOOBJ0:>=.obj) -#SNCOBJ0 = $(SNC:<=w3i3mv\cv\) -#SNCOBJ = $(SNCOBJ0:>=.obj) -#DWOBJ0 = $(DW:<=w3i3mv\cv\) -#DWOBJ = $(DWOBJ0:>=.obj) -#POOLNOBJ0 = $(POOLN:<=w3i3mv\cv\) -#POOLNOBJ = $(POOLNOBJ0:>=.obj) -#TESTLIBOBJ0 = $(TESTLIB:<=w3i3mv\cv\) -#TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj) - -!ENDIF - -# %%PART: When adding a new part, add new macros which expand to the object -# files included in the part - -MPMOBJ = $(MPMOBJ0:>=.obj) -PLINTHOBJ = $(PLINTHOBJ0:>=.obj) -AMSOBJ = $(AMSOBJ0:>=.obj) -AMCOBJ = $(AMCOBJ0:>=.obj) -AWLOBJ = $(AWLOBJ0:>=.obj) -LOOBJ = $(LOOBJ0:>=.obj) -SNCOBJ = $(SNCOBJ0:>=.obj) -MVFFOBJ = $(MVFFOBJ0:>=.obj) -DWOBJ = $(DWOBJ0:>=.obj) -FMTTESTOBJ = $(FMTTESTOBJ0:>=.obj) -POOLNOBJ = $(POOLNOBJ0:>=.obj) -TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj) - - -!INCLUDE commpost.nmk - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/w3i6mv.nmk b/mps/code/w3i6mv.nmk deleted file mode 100644 index 729509f05dc..00000000000 --- a/mps/code/w3i6mv.nmk +++ /dev/null @@ -1,221 +0,0 @@ -# w3i6mv.nmk: WINDOWS (x64) NMAKE FILE -# -# $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - -PFM = w3i6mv - -# /Gs appears to be necessary to suppress stack checks. Stack checks -# (if not suppressed) generate a dependency on the C library, __chkesp, -# which causes the linker step to fail when building the DLL, mpsdy.dll. -PFMDEFS = /DCONFIG_PF_STRING="w3i6mv" /DCONFIG_PF_W3I6MV \ - /DWIN32 /D_WINDOWS /Gs -MASM = ml64 - -MPM = \ - \ - \ - \ - \ -
\ - \ - \ - -PLINTH = -AMC = -AMS = -AWL = -LO = -SNC = -MVFF = -DW = -FMTTEST = -POOLN = -TESTLIB = - - -!INCLUDE commpre.nmk - - -# Source to object file mappings and CFLAGS amalgamation -# -# %%VARIETY %%PART: When adding a new variety or part, add new macros which -# expand to the files included in the part for each variety -# -# %%VARIETY: When adding a new variety, add a CFLAGS macro which expands to -# the flags that that variety should use when compiling C. And a LINKFLAGS -# macro which expands to the flags that the variety should use when building -# executables. And a LIBFLAGS macro which expands to the flags that the -# variety should use when building libraries - -!IF "$(VARIETY)" == "hot" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT) -MPMOBJ0 = $(MPM:<=w3i6mv\hot\) -PLINTHOBJ0 = $(PLINTH:<=w3i6mv\hot\) -AMSOBJ0 = $(AMS:<=w3i6mv\hot\) -AMCOBJ0 = $(AMC:<=w3i6mv\hot\) -AWLOBJ0 = $(AWL:<=w3i6mv\hot\) -LOOBJ0 = $(LO:<=w3i6mv\hot\) -SNCOBJ0 = $(SNC:<=w3i6mv\hot\) -MVFFOBJ0 = $(MVFF:<=w3i6mv\hot\) -DWOBJ0 = $(DW:<=w3i6mv\hot\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i6mv\hot\) -POOLNOBJ0 = $(POOLN:<=w3i6mv\hot\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\hot\) - -!ELSEIF "$(VARIETY)" == "di" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFDI) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFDI) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSDI) -MPMOBJ0 = $(MPM:<=w3i6mv\di\) -PLINTHOBJ0 = $(PLINTH:<=w3i6mv\di\) -AMSOBJ0 = $(AMS:<=w3i6mv\di\) -AMCOBJ0 = $(AMC:<=w3i6mv\di\) -AWLOBJ0 = $(AWL:<=w3i6mv\di\) -LOOBJ0 = $(LO:<=w3i6mv\di\) -SNCOBJ0 = $(SNC:<=w3i6mv\di\) -MVFFOBJ0 = $(MVFF:<=w3i6mv\di\) -DWOBJ0 = $(DW:<=w3i6mv\di\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i6mv\di\) -POOLNOBJ0 = $(POOLN:<=w3i6mv\di\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\di\) - -!ELSEIF "$(VARIETY)" == "cool" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL) -MPMOBJ0 = $(MPM:<=w3i6mv\cool\) -PLINTHOBJ0 = $(PLINTH:<=w3i6mv\cool\) -AMSOBJ0 = $(AMS:<=w3i6mv\cool\) -AMCOBJ0 = $(AMC:<=w3i6mv\cool\) -AWLOBJ0 = $(AWL:<=w3i6mv\cool\) -LOOBJ0 = $(LO:<=w3i6mv\cool\) -SNCOBJ0 = $(SNC:<=w3i6mv\cool\) -MVFFOBJ0 = $(MVFF:<=w3i6mv\cool\) -DWOBJ0 = $(DW:<=w3i6mv\cool\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i6mv\cool\) -POOLNOBJ0 = $(POOLN:<=w3i6mv\cool\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\cool\) - -!ELSEIF "$(VARIETY)" == "ti" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFTI) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFTI) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSTI) -MPMOBJ0 = $(MPM:<=w3i6mv\ti\) -PLINTHOBJ0 = $(PLINTH:<=w3i6mv\ti\) -AMSOBJ0 = $(AMS:<=w3i6mv\ti\) -AMCOBJ0 = $(AMC:<=w3i6mv\ti\) -AWLOBJ0 = $(AWL:<=w3i6mv\ti\) -LOOBJ0 = $(LO:<=w3i6mv\ti\) -SNCOBJ0 = $(SNC:<=w3i6mv\ti\) -MVFFOBJ0 = $(MVFF:<=w3i6mv\ti\) -DWOBJ0 = $(DW:<=w3i6mv\ti\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i6mv\ti\) -POOLNOBJ0 = $(POOLN:<=w3i6mv\ti\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\ti\) - -!ELSEIF "$(VARIETY)" == "rash" -CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST) -LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH) -LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH) -MPMOBJ0 = $(MPM:<=w3i6mv\rash\) -PLINTHOBJ0 = $(PLINTH:<=w3i6mv\rash\) -AMSOBJ0 = $(AMS:<=w3i6mv\rash\) -AMCOBJ0 = $(AMC:<=w3i6mv\rash\) -AWLOBJ0 = $(AWL:<=w3i6mv\rash\) -LOOBJ0 = $(LO:<=w3i6mv\rash\) -SNCOBJ0 = $(SNC:<=w3i6mv\rash\) -MVFFOBJ0 = $(MVFF:<=w3i6mv\rash\) -DWOBJ0 = $(DW:<=w3i6mv\rash\) -FMTTESTOBJ0 = $(FMTTEST:<=w3i6mv\rash\) -POOLNOBJ0 = $(POOLN:<=w3i6mv\rash\) -TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\rash\) - -#!ELSEIF "$(VARIETY)" == "cv" -#CFLAGS=$(CFLAGSCOMMON) $(CFCV) -#LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCV) -#LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCV) -#MPMOBJ0 = $(MPM:<=w3i6mv\cv\) -#MPMOBJ = $(MPMOBJ0:>=.obj) -#PLINTHOBJ0 = $(PLINTH:<=w3i6mv\cv\) -#PLINTHOBJ = $(PLINTHOBJ0:>=.obj) -#AMSOBJ0 = $(AMS:<=w3i6mv\cv\) -#AMSOBJ = $(AMSOBJ0:>=.obj) -#AMCOBJ0 = $(AMC:<=w3i6mv\cv\) -#AMCOBJ = $(AMCOBJ0:>=.obj) -#AWLOBJ0 = $(AWL:<=w3i6mv\cv\) -#AWLOBJ = $(AWLOBJ0:>=.obj) -#LOOBJ0 = $(LO:<=w3i6mv\cv\) -#LOOBJ = $(LOOBJ0:>=.obj) -#SNCOBJ0 = $(SNC:<=w3i6mv\cv\) -#SNCOBJ = $(SNCOBJ0:>=.obj) -#DWOBJ0 = $(DW:<=w3i6mv\cv\) -#DWOBJ = $(DWOBJ0:>=.obj) -#POOLNOBJ0 = $(POOLN:<=w3i6mv\cv\) -#POOLNOBJ = $(POOLNOBJ0:>=.obj) -#TESTLIBOBJ0 = $(TESTLIB:<=w3i6mv\cv\) -#TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj) - -!ENDIF - -# %%PART: When adding a new part, add new macros which expand to the object -# files included in the part - -MPMOBJ = $(MPMOBJ0:>=.obj) -PLINTHOBJ = $(PLINTHOBJ0:>=.obj) -AMSOBJ = $(AMSOBJ0:>=.obj) -AMCOBJ = $(AMCOBJ0:>=.obj) -AWLOBJ = $(AWLOBJ0:>=.obj) -LOOBJ = $(LOOBJ0:>=.obj) -SNCOBJ = $(SNCOBJ0:>=.obj) -MVFFOBJ = $(MVFFOBJ0:>=.obj) -DWOBJ = $(DWOBJ0:>=.obj) -FMTTESTOBJ = $(FMTTESTOBJ0:>=.obj) -POOLNOBJ = $(POOLNOBJ0:>=.obj) -TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj) - - -!INCLUDE commpost.nmk - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2002 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/w3mv/amcss/amcss.vcxproj b/mps/code/w3mv/amcss/amcss.vcxproj deleted file mode 100755 index e263332de92..00000000000 --- a/mps/code/w3mv/amcss/amcss.vcxproj +++ /dev/null @@ -1,153 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE} - Win32Proj - amcss - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - true - - - true - - - false - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - - - - - - - - - {339b244a-c76f-4663-a39d-fa90b97f5381} - - - - - - \ No newline at end of file diff --git a/mps/code/w3mv/eventcnv/eventcnv.vcxproj b/mps/code/w3mv/eventcnv/eventcnv.vcxproj deleted file mode 100755 index 42c03ba76ab..00000000000 --- a/mps/code/w3mv/eventcnv/eventcnv.vcxproj +++ /dev/null @@ -1,149 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {945E1C40-AADC-4F3D-B59E-3028338805A5} - Win32Proj - eventcnv - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - true - - - true - - - false - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - - - - - {339b244a-c76f-4663-a39d-fa90b97f5381} - - - - - - \ No newline at end of file diff --git a/mps/code/w3mv/mps.sln b/mps/code/w3mv/mps.sln deleted file mode 100755 index c1c1c78ccb2..00000000000 --- a/mps/code/w3mv/mps.sln +++ /dev/null @@ -1,44 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "amcss", "amcss\amcss.vcxproj", "{8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mps", "mps\mps.vcxproj", "{339B244A-C76F-4663-A39D-FA90B97F5381}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eventcnv", "eventcnv\eventcnv.vcxproj", "{945E1C40-AADC-4F3D-B59E-3028338805A5}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}.Debug|Win32.ActiveCfg = Debug|Win32 - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}.Debug|Win32.Build.0 = Debug|Win32 - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}.Debug|x64.ActiveCfg = Debug|x64 - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}.Debug|x64.Build.0 = Debug|x64 - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}.Release|Win32.ActiveCfg = Release|Win32 - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}.Release|Win32.Build.0 = Release|Win32 - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}.Release|x64.ActiveCfg = Release|x64 - {8412D60D-8D05-4D41-AB7C-8FEA3A7F32CE}.Release|x64.Build.0 = Release|x64 - {339B244A-C76F-4663-A39D-FA90B97F5381}.Debug|Win32.ActiveCfg = Debug|Win32 - {339B244A-C76F-4663-A39D-FA90B97F5381}.Debug|Win32.Build.0 = Debug|Win32 - {339B244A-C76F-4663-A39D-FA90B97F5381}.Debug|x64.ActiveCfg = Debug|x64 - {339B244A-C76F-4663-A39D-FA90B97F5381}.Debug|x64.Build.0 = Debug|x64 - {339B244A-C76F-4663-A39D-FA90B97F5381}.Release|Win32.ActiveCfg = Release|Win32 - {339B244A-C76F-4663-A39D-FA90B97F5381}.Release|Win32.Build.0 = Release|Win32 - {339B244A-C76F-4663-A39D-FA90B97F5381}.Release|x64.ActiveCfg = Release|Win32 - {945E1C40-AADC-4F3D-B59E-3028338805A5}.Debug|Win32.ActiveCfg = Debug|Win32 - {945E1C40-AADC-4F3D-B59E-3028338805A5}.Debug|Win32.Build.0 = Debug|Win32 - {945E1C40-AADC-4F3D-B59E-3028338805A5}.Debug|x64.ActiveCfg = Debug|x64 - {945E1C40-AADC-4F3D-B59E-3028338805A5}.Debug|x64.Build.0 = Debug|x64 - {945E1C40-AADC-4F3D-B59E-3028338805A5}.Release|Win32.ActiveCfg = Release|Win32 - {945E1C40-AADC-4F3D-B59E-3028338805A5}.Release|Win32.Build.0 = Release|Win32 - {945E1C40-AADC-4F3D-B59E-3028338805A5}.Release|x64.ActiveCfg = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/mps/code/w3mv/mps/mps.vcxproj b/mps/code/w3mv/mps/mps.vcxproj deleted file mode 100755 index 3cc75482e1c..00000000000 --- a/mps/code/w3mv/mps/mps.vcxproj +++ /dev/null @@ -1,132 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - {339B244A-C76F-4663-A39D-FA90B97F5381} - Win32Proj - mps - - - - StaticLibrary - true - Unicode - - - StaticLibrary - true - Unicode - - - StaticLibrary - false - true - Unicode - - - StaticLibrary - false - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - Level4 - Disabled - CONFIG_VAR_COOL;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - - - - - - - Level4 - Disabled - CONFIG_VAR_COOL;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/mps/code/walk.c b/mps/code/walk.c deleted file mode 100644 index 9828eb49f57..00000000000 --- a/mps/code/walk.c +++ /dev/null @@ -1,406 +0,0 @@ -/* walk.c: OBJECT WALKER - * - * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. - */ - -#include "mpm.h" -#include "mps.h" - -SRCID(walk, "$Id$"); - - -/* Heap Walking - */ - - -#define FormattedObjectsStepClosureSig ((Sig)0x519F05C1) - -typedef struct FormattedObjectsStepClosureStruct *FormattedObjectsStepClosure; - -typedef struct FormattedObjectsStepClosureStruct { - Sig sig; - mps_formatted_objects_stepper_t f; - void *p; - size_t s; -} FormattedObjectsStepClosureStruct; - - -static Bool FormattedObjectsStepClosureCheck(FormattedObjectsStepClosure c) -{ - CHECKS(FormattedObjectsStepClosure, c); - CHECKL(FUNCHECK(c->f)); - /* p and s fields are arbitrary closures which cannot be checked */ - return TRUE; -} - - -static void ArenaFormattedObjectsStep(Addr object, Format format, Pool pool, - void *p, size_t s) -{ - FormattedObjectsStepClosure c; - /* Can't check object */ - AVERT(Format, format); - AVERT(Pool, pool); - c = p; - AVERT(FormattedObjectsStepClosure, c); - AVER(s == 0); - - (*c->f)((mps_addr_t)object, (mps_fmt_t)format, (mps_pool_t)pool, - c->p, c->s); -} - - -/* ArenaFormattedObjectsWalk -- iterate over all objects - * - * So called because it walks all formatted objects in an arena. */ - -static void ArenaFormattedObjectsWalk(Arena arena, FormattedObjectsStepMethod f, - void *p, size_t s) -{ - Seg seg; - FormattedObjectsStepClosure c; - - AVERT(Arena, arena); - AVER(FUNCHECK(f)); - AVER(f == ArenaFormattedObjectsStep); - /* p and s are arbitrary closures. */ - /* Know that p is a FormattedObjectsStepClosure */ - /* Know that s is 0 */ - AVER(p != NULL); - AVER(s == 0); - - c = p; - AVERT(FormattedObjectsStepClosure, c); - - if (SegFirst(&seg, arena)) { - Addr base; - do { - Pool pool; - base = SegBase(seg); - pool = SegPool(seg); - if (pool->class->attr & AttrFMT) { - ShieldExpose(arena, seg); - PoolWalk(pool, seg, f, p, s); - ShieldCover(arena, seg); - } - } while(SegNext(&seg, arena, base)); - } -} - - -/* mps_arena_formatted_objects_walk -- iterate over all objects - * - * Client interface to ArenaFormattedObjectsWalk. */ - -void mps_arena_formatted_objects_walk(mps_arena_t mps_arena, - mps_formatted_objects_stepper_t f, - void *p, size_t s) -{ - Arena arena = (Arena)mps_arena; - FormattedObjectsStepClosureStruct c; - - ArenaEnter(arena); - AVERT(Arena, arena); - AVER(FUNCHECK(f)); - /* p and s are arbitrary closures, hence can't be checked */ - c.sig = FormattedObjectsStepClosureSig; - c.f = f; - c.p = p; - c.s = s; - ArenaFormattedObjectsWalk(arena, ArenaFormattedObjectsStep, &c, 0); - ArenaLeave(arena); -} - - - -/* Root Walking - * - * This involves more code than it should. The roots are walked by - * scanning them. But there's no direct support for invoking the scanner - * without there being a trace, and there's no direct support for - * creating a trace without also condemning part of the heap. (@@@@ This - * looks like a useful candidate for inclusion in the future). For now, - * the root walker contains its own code for creating a minimal trace - * and scan state. - * - * ASSUMPTIONS - * - * .assume.parked: The root walker must be invoked with a parked - * arena. It's only strictly necessary for there to be no current trace, - * but the client has no way to ensure this apart from parking the - * arena. - * - * .assume.rootaddr: The client closure is called with a parameter which - * is the address of a reference to an object referenced from a - * root. The client may desire this address to be the address of the - * actual reference in the root (so that the debugger can be used to - * determine details about the root). This is not always possible, since - * the root might actually be a register, or the format scan method - * might not pass this address directly to the fix method. If the format - * code does pass on the address, the client can be sure to be passed - * the address of any root other than a register or stack. */ - - -/* rootsStepClosure -- closure environment for root walker - * - * Defined as a subclass of ScanState. */ - -/* SIGnature Roots Step CLOsure */ -#define rootsStepClosureSig ((Sig)0x51965C10) - -typedef struct rootsStepClosureStruct *rootsStepClosure; -typedef struct rootsStepClosureStruct { - ScanStateStruct ssStruct; /* generic scan state object */ - mps_roots_stepper_t f; /* client closure function */ - void *p; /* client closure data */ - size_t s; /* client closure data */ - Root root; /* current root, or NULL */ - Sig sig; /* */ -} rootsStepClosureStruct; - -#define rootsStepClosure2ScanState(rsc) (&(rsc)->ssStruct) -#define ScanState2rootsStepClosure(ss) \ - PARENT(rootsStepClosureStruct, ssStruct, ss) - - -/* rootsStepClosureCheck -- check a rootsStepClosure */ - -static Bool rootsStepClosureCheck(rootsStepClosure rsc) -{ - CHECKS(rootsStepClosure, rsc); - CHECKD(ScanState, &rsc->ssStruct); - CHECKL(FUNCHECK(rsc->f)); - /* p and s fields are arbitrary closures which cannot be checked */ - if (rsc->root != NULL) { - CHECKL(RootCheck(rsc->root)); - } - return TRUE; -} - - -/* rootsStepClosureInit -- Initialize a rootsStepClosure - * - * Initialize the parent ScanState too. */ - -static void rootsStepClosureInit(rootsStepClosure rsc, - Globals arena, Trace trace, - PoolFixMethod rootFix, - mps_roots_stepper_t f, void *p, size_t s) -{ - ScanState ss; - - /* First initialize the ScanState superclass */ - ss = &rsc->ssStruct; - ScanStateInit(ss, TraceSetSingle(trace), GlobalsArena(arena), RankAMBIG, - trace->white); - - /* Initialize the fix method in the ScanState */ - ss->fix = rootFix; - - /* Initialize subclass specific data */ - rsc->f = f; - rsc->p = p; - rsc->s = s; - rsc->root = NULL; - - rsc->sig = rootsStepClosureSig; - - AVERT(rootsStepClosure, rsc); -} - - -/* rootsStepClosureFinish -- Finish a rootsStepClosure - * - * Finish the parent ScanState too. */ - -static void rootsStepClosureFinish(rootsStepClosure rsc) -{ - ScanState ss; - - ss = rootsStepClosure2ScanState(rsc); - rsc->sig = SigInvalid; - ScanStateFinish(ss); -} - - -/* RootsWalkFix -- the fix method used during root walking - * - * This doesn't cause further scanning of transitive references, it just - * calls the client closure. */ - -static Res RootsWalkFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) -{ - rootsStepClosure rsc; - Ref ref; - - UNUSED(pool); - - AVERT(ScanState, ss); - AVER(refIO != NULL); - rsc = ScanState2rootsStepClosure(ss); - AVERT(rootsStepClosure, rsc); - - ref = *refIO; - - /* If the segment isn't GCable then the ref is not to the heap and */ - /* shouldn't be passed to the client. */ - AVER((SegPool(seg)->class->attr & AttrGC) != 0); - - /* Call the client closure - .assume.rootaddr */ - rsc->f((mps_addr_t*)refIO, (mps_root_t)rsc->root, rsc->p, rsc->s); - - AVER(ref == *refIO); /* can walk object graph - but not modify it */ - - return ResOK; -} - - -/* rootWalk -- the step function for ArenaRootsWalk */ - -static Res rootWalk(Root root, void *p) -{ - ScanState ss = (ScanState)p; - - AVERT(ScanState, ss); - - if (RootRank(root) == ss->rank) { - /* set the root for the benefit of the fix method */ - ScanState2rootsStepClosure(ss)->root = root; - /* Scan it */ - ScanStateSetSummary(ss, RefSetEMPTY); - return RootScan(ss, root); - } else - return ResOK; -} - - -/* ArenaRootsWalk -- walks all the root in the arena */ - -static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f, - void *p, size_t s) -{ - Arena arena; - rootsStepClosureStruct rscStruct; - rootsStepClosure rsc = &rscStruct; - Trace trace; - ScanState ss; - Rank rank; - Res res; - Seg seg; - - AVERT(Globals, arenaGlobals); - AVER(FUNCHECK(f)); - /* p and s are arbitrary client-provided closure data. */ - arena = GlobalsArena(arenaGlobals); - - /* Scan all the roots with a minimal trace. Invoke the scanner with a */ - /* rootsStepClosure, which is a subclass of ScanState and contains the */ - /* client-provided closure. Supply a special fix method in order to */ - /* call the client closure. This fix method must perform no tracing */ - /* operations of its own. */ - - res = TraceCreate(&trace, arena, TraceStartWhyWALK); - /* Have to fail if no trace available. Unlikely due to .assume.parked. */ - if (res != ResOK) - return res; - - /* ArenaRootsWalk only passes references to GCable pools to the client. */ - /* NOTE: I'm not sure why this is. RB 2012-07-24 */ - if (SegFirst(&seg, arena)) { - Addr base; - do { - base = SegBase(seg); - if ((SegPool(seg)->class->attr & AttrGC) != 0) { - TraceAddWhite(trace, seg); - } - } while (SegNext(&seg, arena, base)); - } - - /* Make the roots grey so that they are scanned */ - res = RootsIterate(arenaGlobals, (RootIterateFn)RootGrey, (void *)trace); - /* Make this trace look like any other trace. */ - arena->flippedTraces = TraceSetAdd(arena->flippedTraces, trace); - - rootsStepClosureInit(rsc, arenaGlobals, trace, RootsWalkFix, f, p, s); - ss = rootsStepClosure2ScanState(rsc); - - for(rank = RankAMBIG; rank < RankLIMIT; ++rank) { - ss->rank = rank; - AVERT(ScanState, ss); - res = RootsIterate(arenaGlobals, rootWalk, (void *)ss); - if (res != ResOK) - break; - } - - rootsStepClosureFinish(rsc); - /* Make this trace look like any other finished trace. */ - trace->state = TraceFINISHED; - TraceDestroy(trace); - AVER(!ArenaEmergency(arena)); /* There was no allocation. */ - - return res; -} - - -/* mps_arena_roots_walk -- Client interface for walking */ - -void mps_arena_roots_walk(mps_arena_t mps_arena, mps_roots_stepper_t f, - void *p, size_t s) -{ - Arena arena = (Arena)mps_arena; - Res res; - - ArenaEnter(arena); - AVER(FUNCHECK(f)); - /* p and s are arbitrary closures, hence can't be checked */ - - AVER(ArenaGlobals(arena)->clamped); /* .assume.parked */ - AVER(arena->busyTraces == TraceSetEMPTY); /* .assume.parked */ - - res = ArenaRootsWalk(ArenaGlobals(arena), f, p, s); - AVER(res == ResOK); - ArenaLeave(arena); -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/walkt0.c b/mps/code/walkt0.c deleted file mode 100644 index f4618fd420c..00000000000 --- a/mps/code/walkt0.c +++ /dev/null @@ -1,258 +0,0 @@ -/* walkt0.c: WALK TEST 0 - * - * $Id$ - * Copyright (C) 1998,2003 Ravenbrook Limited. See end of file for license. - * - * Loosely based on . - */ - -#include "fmtdy.h" -#include "fmtdytst.h" -#include "testlib.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include "mps.h" - -#include -#include - -#define testArenaSIZE ((size_t)((size_t)64 << 20)) -#define avLEN 3 -#define exactRootsCOUNT 200 -#define objCOUNT 20000 - -#define genCOUNT 3 -#define gen1SIZE 750 /* kB */ -#define gen2SIZE 2000 /* kB */ -#define gen3SIZE 5000 /* kB */ -#define gen1MORTALITY 0.85 -#define gen2MORTALITY 0.60 -#define gen3MORTALITY 0.40 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - {gen1SIZE, gen1MORTALITY}, - {gen2SIZE, gen2MORTALITY}, - {gen3SIZE, gen3MORTALITY}, -}; - -/* objNULL needs to be odd so that it's ignored in exactRoots. */ -#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) - -static mps_ap_t ap; -static mps_addr_t exactRoots[exactRootsCOUNT]; -static size_t alloc_bytes; - -/* Make a single Dylan object */ - -static mps_addr_t make(void) -{ - size_t length = rnd() % (avLEN * 2); - size_t size = (length+2) * sizeof(mps_word_t); - mps_addr_t p; - mps_res_t res; - - alloc_bytes += size; - - for(;;) { - mps_bool_t commit_res; - MPS_RESERVE_BLOCK(res, p, ap, size); - if(res) - die(res, "MPS_RESERVE_BLOCK"); - res = dylan_init(p, size, exactRoots, exactRootsCOUNT); - if(res) - die(res, "dylan_init"); - commit_res = mps_commit(ap, p, size); - if(commit_res) - break; - } - - return p; -} - -/* A stepper function. Passed to mps_arena_formatted_objects_walk. - * - * Tests the (pool, format) values that MPS passes to it for each - * object, by... - * - * ...1: making explicit queries with: - * mps_arena_has_addr - * mps_addr_pool - * mps_addr_fmt - * - * ...2: comparing with what we expect for: - * pool - * fmt - */ -struct stepper_data { - mps_arena_t arena; - mps_pool_t expect_pool; - mps_fmt_t expect_fmt; - unsigned long count; -}; - -static void stepper(mps_addr_t object, mps_fmt_t format, - mps_pool_t pool, void *p, size_t s) -{ - struct stepper_data *sd; - mps_arena_t arena; - mps_bool_t b; - mps_pool_t query_pool; - mps_fmt_t query_fmt; - - Insist(s == sizeof *sd); - sd = p; - arena = sd->arena; - - Insist(mps_arena_has_addr(arena, object)); - - b = mps_addr_pool(&query_pool, arena, object); - Insist(b); - Insist(query_pool == pool); - Insist(pool == sd->expect_pool); - - b = mps_addr_fmt(&query_fmt, arena, object); - Insist(b); - Insist(query_fmt == format); - Insist(format == sd->expect_fmt); - - sd->count += 1; - return; -} - -/* test -- the body of the test */ - -static void *test(void *arg, size_t s) -{ - mps_arena_t arena; - mps_chain_t chain; - mps_fmt_t format; - mps_pool_t pool; - mps_root_t exactRoot; - size_t i; - unsigned long objs; - struct stepper_data sdStruct, *sd; - - arena = (mps_arena_t)arg; - (void)s; /* unused */ - - die(dylan_fmt(&format, arena), "fmt_create"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - - die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain), - "pool_create(amc)"); - - die(mps_ap_create(&ap, pool, mps_rank_exact()), "ap_create"); - - for(i = 0; i < exactRootsCOUNT; ++i) - exactRoots[i] = objNULL; - - die(mps_root_create_table_masked(&exactRoot, arena, - mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, - (mps_word_t)1), - "root_create_table(exact)"); - - objs = 0; - - while(objs < objCOUNT) { - size_t r; - - r = objs; - i = r % exactRootsCOUNT; - if(exactRoots[i] != objNULL) { - cdie(dylan_check(exactRoots[i]), "dying root check"); - } - exactRoots[i] = make(); - if(exactRoots[(exactRootsCOUNT-1) - i] != objNULL) - dylan_write(exactRoots[(exactRootsCOUNT-1) - i], - exactRoots, exactRootsCOUNT); - - ++objs; - } - - sd = &sdStruct; - sd->arena = arena; - sd->expect_pool = pool; - sd->expect_fmt = format; - sd->count = 0; - mps_arena_formatted_objects_walk(arena, stepper, sd, sizeof *sd); - /* Note: stepper finds more than we expect, due to pad objects */ - /* printf("stepper found %ld objs\n", sd->count); */ - - mps_ap_destroy(ap); - mps_root_destroy(exactRoot); - mps_pool_destroy(pool); - mps_chain_destroy(chain); - mps_fmt_destroy(format); - - return NULL; -} - -int main(int argc, char **argv) -{ - mps_arena_t arena; - mps_thr_t thread; - void *r; - - randomize(argc, argv); - - die(mps_arena_create(&arena, mps_arena_class_vm(), - testArenaSIZE), - "arena_create"); - die(mps_thread_reg(&thread, arena), "thread_reg"); - mps_tramp(&r, test, arena, 0); - mps_thread_dereg(thread); - mps_arena_destroy(arena); - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2003 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/xci3gc.gmk b/mps/code/xci3gc.gmk deleted file mode 100644 index 1aea3bc22d5..00000000000 --- a/mps/code/xci3gc.gmk +++ /dev/null @@ -1,62 +0,0 @@ -# xci3gc.gmk: BUILD FOR MACOS X (CARBON)/INTEL IA32/GCC PLATFORM -# -# $Id$ -# Copyright (c) 2001,2006 Ravenbrook Limited. See end of file for license. -# -# Naively copied from xcppgc.gmk, could do with going over properly. - -PFM = xci3gc - -MPMPF = lockix.c than.c vmix.c \ - protix.c protsgix.c prmcan.c span.c ssixi3.c - -LIBS = - -RANLIB=ranlib - -include gc.gmk - -CC = gcc -arch i386 - -include comm.gmk - - -# C. COPYRIGHT AND LICENSE -# -# Copyright (C) 2001-2006 Ravenbrook Limited . -# All rights reserved. This is an open source license. Contact -# Ravenbrook for commercial licensing options. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Redistributions in any form must be accompanied by information on how -# to obtain complete source code for this software and any accompanying -# software that uses this software. The source code must either be -# included in the distribution or be available for no more than the cost -# of distribution plus a nominal fee, and must be freely redistributable -# under reasonable conditions. For an executable file, complete source -# code means the source code for all modules it contains. It does not -# include source code for modules or files that typically accompany the -# major components of the operating system on which the executable file -# runs. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/zcoll.c b/mps/code/zcoll.c deleted file mode 100644 index be698733a73..00000000000 --- a/mps/code/zcoll.c +++ /dev/null @@ -1,977 +0,0 @@ -/* zcoll.c: Collection test - * - * $Id$ - * Copyright (c) 2008 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * OBJECTIVE - * - * Test MPS collections. In particular, reporting of how collections - * progress. - * - * Please add tests for other collection behaviour into this file. - * (It's easier to maintain a few big tests than myriad small tests). - * Expand the script language as necessary! RHSK 2008-12-22. - * - * - * DESIGN OVERVIEW - * - * Each script runs in a newly created arena. - * - * [preliminary, incomplete, code still being written] - * The commands are: - * Arena -- governs initial arena size, required, must be first - * Make -- makes some objects, stores a proportion (chosen at - * random) in the specified myroot array slots, and - * drops the rest (which therefore become garbage) - * Katalog -- (will be renamed Catalog) makes a Catalog, which - * is a 40 MB 4-level tree of 10^5 objects; see .catalog; - * see also .catalog.broken. - * Collect -- request a synchronous full garbage collection - * - * - * CODE OVERVIEW - * - * main() has the list of testscripts. - * - * testscriptA() sets up a new arena and trampolines to testscriptB(). - * - * testscriptB() creates pools and objects for this test script. - * - * testscriptC() actually runs the script. - * - * - * DEPENDENCIES - * - * This test uses the dylan object format, but the reliance on this - * particular format is not great and could be removed. - * - * - * BUGS, FUTURE IMPROVEMENTS, ETC - * - * HISTORY - * - * This code was created by first copying . - */ - -#include "testlib.h" -#include "mps.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "fmtdy.h" -#include "fmtdytst.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include -#include /* clock */ - - -#ifdef MPS_BUILD_MV -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: sscanf. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - - -/* testChain -- generation parameters for the test */ -#define genCOUNT 2 -static mps_gen_param_s testChain[genCOUNT] = { - { 100, 0.85 }, { 170, 0.45 } }; - - -/* myroot -- arrays of references that are the root */ -#define myrootAmbigCOUNT 30000 -static void *myrootAmbig[myrootAmbigCOUNT]; -#define myrootExactCOUNT 30000 -static void *myrootExact[myrootExactCOUNT]; - -static mps_root_t root_stackreg; -static void *stack_start; -static mps_thr_t stack_thr; - - -static ulongest_t cols(size_t bytes) -{ - double M; /* Mebibytes */ - ulongest_t cM; /* hundredths of a Mebibyte */ - - M = (double)bytes / ((ulongest_t)1<<20); - cM = (ulongest_t)(M * 100.0 + 0.5); /* round to nearest */ - return cM; -} - -/* showStatsAscii -- present collection stats, 'graphically' - * - */ -static void showStatsAscii(size_t notcon, size_t con, size_t live, size_t alimit) -{ - ulongest_t n = cols(notcon); - ulongest_t c = cols(notcon + con); - ulongest_t l = cols(notcon + live); /* a fraction of con */ - ulongest_t a = cols(alimit); - ulongest_t count; - ulongest_t i; - - /* if we can show alimit within 200 cols, do so */ - count = (a < 200) ? a + 1 : c; - - for(i = 0; i < count; i++) { - printf( (i == a) ? "A" - : (i < n) ? "n" - : (i < l) ? "L" - : (i < c) ? "_" - : " " - ); - } - printf("\n"); -} - - -/* print_M -- print count of bytes as Mebibytes or Megabytes - * - * Print as a whole number, "m" for the decimal point, and - * then the decimal fraction. - * - * Input: 208896 - * Output: (Mebibytes) 0m199 - * Output: (Megabytes) 0m209 - */ -#if 0 -#define bPerM ((size_t)1 << 20) /* Mebibytes */ -#else -#define bPerM ((size_t)1000000) /* Megabytes */ -#endif -static void print_M(size_t bytes) -{ - size_t M; /* M thingies */ - double Mfrac; /* fraction of an M thingy */ - - M = bytes / bPerM; - Mfrac = (double)(bytes % bPerM); - Mfrac = (Mfrac / bPerM); - - printf("%1"PRIuLONGEST"m%03.f", (ulongest_t)M, Mfrac * 1000); -} - - -/* showStatsText -- present collection stats - * - * prints: - * Coll End 0m137[->0m019 14%-live] (0m211-not ) - */ -static void showStatsText(size_t notcon, size_t con, size_t live) -{ - double liveFrac = (double)live / (double)con; - - print_M(con); - printf("[->"); - print_M(live); - printf("% 3.f%%-live]", liveFrac * 100); - printf(" ("); - print_M(notcon); - printf("-not "); - printf(")\n"); -} - -/* get -- get messages - * - */ -static void get(mps_arena_t arena) -{ - mps_message_type_t type; - - while (mps_message_queue_type(&type, arena)) { - mps_message_t message; - static mps_clock_t mclockBegin = 0; - static mps_clock_t mclockEnd = 0; - mps_word_t *obj; - mps_word_t objind; - mps_addr_t objaddr; - - cdie(mps_message_get(&message, arena, type), - "get"); - - switch(type) { - case mps_message_type_gc_start(): { - mclockBegin = mps_message_clock(arena, message); - printf(" %5lu: (%5lu)", - mclockBegin, mclockBegin - mclockEnd); - printf(" Coll Begin (%s)\n", - mps_message_gc_start_why(arena, message)); - break; - } - case mps_message_type_gc(): { - size_t con = mps_message_gc_condemned_size(arena, message); - size_t notcon = mps_message_gc_not_condemned_size(arena, message); - /* size_t other = 0; -- cannot determine; new method reqd */ - size_t live = mps_message_gc_live_size(arena, message); - size_t alimit = mps_arena_reserved(arena); - - mclockEnd = mps_message_clock(arena, message); - - printf(" %5lu: (%5lu)", - mclockEnd, mclockEnd - mclockBegin); - printf(" Coll End "); - showStatsText(notcon, con, live); - if(rnd()==0) showStatsAscii(notcon, con, live, alimit); - break; - } - case mps_message_type_finalization(): { - mps_message_finalization_ref(&objaddr, arena, message); - obj = objaddr; - objind = DYLAN_INT_INT(DYLAN_VECTOR_SLOT(obj, 0)); - printf(" Finalization for object %lu at %p\n", objind, objaddr); - break; - } - default: { - cdie(0, "message type"); - break; - } - } - - mps_message_discard(arena, message); - } -} - - -/* .catalog: The Catalog client: - * - * This is an MPS client for testing the MPS. It simulates - * converting a multi-page "Catalog" document from a page-description - * into a bitmap. - * - * The intention is that this task will cause memory usage that is - * fairly realistic (much more so than randomly allocated objects - * with random interconnections. The patterns in common with real - * clients are: - * - the program input and its task are 'fractal', with a - * self-similar hierarchy; - * - object allocation is prompted by each successive element of - * the input/task; - * - objects are often used to store a transformed version of the - * program input; - * - there may be several stages of transformation; - * - at each stage, the old object (holding the untransformed data) - * may become dead; - * - sometimes a tree of objects becomes dead once an object at - * some level of the hierarchy has been fully processed; - * - there is more than one hierarchy, and objects in different - * hierarchies interact. - * - * The entity-relationship diagram is: - * Catalog -< Page -< Article -< Polygon - * v - * | - * Palette --------------------< Colour - * - * The first hierarchy is a Catalog, containing Pages, each - * containing Articles (bits of artwork etc), each composed of - * Polygons. Each polygon has a single colour. - * - * The second hierarchy is a top-level Palette, containing Colours. - * Colours (in this client) are expensive, large objects (perhaps - * because of complex colour modelling or colour blending). - * - * The things that matter for their effect on MPS behaviour are: - * - when objects are allocated, and how big they are; - * - how the reference graph mutates over time; - * - how the mutator accesses objects (barrier hits). - */ - - -#define CatalogRootIndex 0 -#define CatalogSig MPS_WORD_CONST(0x0000CA2A) /* CATAlog */ -#define CatalogFix 1 -#define CatalogVar 10 -#define PageSig MPS_WORD_CONST(0x0000BA9E) /* PAGE */ -#define PageFix 1 -#define PageVar 100 -#define ArtSig MPS_WORD_CONST(0x0000A621) /* ARTIcle */ -#define ArtFix 1 -#define ArtVar 100 -#define PolySig MPS_WORD_CONST(0x0000B071) /* POLYgon */ -#define PolyFix 1 -#define PolyVar 100 - - -static void CatalogCheck(void) -{ - mps_word_t w; - void *Catalog, *Page, *Art, *Poly; - unsigned long Catalogs = 0, Pages = 0, Arts = 0, Polys = 0; - int i, j, k; - - /* retrieve Catalog from root */ - Catalog = myrootExact[CatalogRootIndex]; - if(!Catalog) - return; - Insist(DYLAN_VECTOR_SLOT(Catalog, 0) == DYLAN_INT(CatalogSig)); - Catalogs += 1; - - for(i = 0; i < CatalogVar; i += 1) { - /* retrieve Page from Catalog */ - w = DYLAN_VECTOR_SLOT(Catalog, CatalogFix + i); - /* printf("Page = 0x%8x\n", (unsigned int) w); */ - if(w == DYLAN_INT(0)) - break; - Page = (void *)w; - Insist(DYLAN_VECTOR_SLOT(Page, 0) == DYLAN_INT(PageSig)); - Pages += 1; - - for(j = 0; j < PageVar; j += 1) { - /* retrieve Art from Page */ - w = DYLAN_VECTOR_SLOT(Page, PageFix + j); - if(w == DYLAN_INT(0)) - break; - Art = (void *)w; - Insist(DYLAN_VECTOR_SLOT(Art, 0) == DYLAN_INT(ArtSig)); - Arts += 1; - - for(k = 0; k < ArtVar; k += 1) { - /* retrieve Poly from Art */ - w = DYLAN_VECTOR_SLOT(Art, ArtFix + k); - if(w == DYLAN_INT(0)) - break; - Poly = (void *)w; - Insist(DYLAN_VECTOR_SLOT(Poly, 0) == DYLAN_INT(PolySig)); - Polys += 1; - } - } - } - printf("Catalog ok with: Catalogs: %lu, Pages: %lu, Arts: %lu, Polys: %lu.\n", - Catalogs, Pages, Arts, Polys); -} - - -/* CatalogDo -- make a Catalog and its tree of objects - * - * .catalog.broken: this code, when compiled with - * moderate optimization, may have ambiguous interior pointers but - * lack corresponding ambiguous base pointers to MPS objects. This - * means the interior pointers are unmanaged references, and the - * code goes wrong. The hack in poolamc.c#4 cures this, but not very - * nicely. For further discussion, see: - * - */ -static void CatalogDo(mps_arena_t arena, mps_ap_t ap) -{ - mps_word_t v; - void *Catalog, *Page, *Art, *Poly; - int i, j, k; - - die(make_dylan_vector(&v, ap, CatalogFix + CatalogVar), "Catalog"); - DYLAN_VECTOR_SLOT(v, 0) = DYLAN_INT(CatalogSig); - Catalog = (void *)v; - - /* store Catalog in root */ - myrootExact[CatalogRootIndex] = Catalog; - get(arena); - - fflush(stdout); - CatalogCheck(); - - for(i = 0; i < CatalogVar; i += 1) { - die(make_dylan_vector(&v, ap, PageFix + PageVar), "Page"); - DYLAN_VECTOR_SLOT(v, 0) = DYLAN_INT(PageSig); - Page = (void *)v; - - /* store Page in Catalog */ - DYLAN_VECTOR_SLOT(Catalog, CatalogFix + i) = (mps_word_t)Page; - get(arena); - - printf("Page %d: make articles\n", i); - fflush(stdout); - - for(j = 0; j < PageVar; j += 1) { - die(make_dylan_vector(&v, ap, ArtFix + ArtVar), "Art"); - DYLAN_VECTOR_SLOT(v, 0) = DYLAN_INT(ArtSig); - Art = (void *)v; - - /* store Art in Page */ - DYLAN_VECTOR_SLOT(Page, PageFix + j) = (mps_word_t)Art; - get(arena); - - for(k = 0; k < ArtVar; k += 1) { - die(make_dylan_vector(&v, ap, PolyFix + PolyVar), "Poly"); - DYLAN_VECTOR_SLOT(v, 0) = DYLAN_INT(PolySig); - Poly = (void *)v; - - /* store Poly in Art */ - DYLAN_VECTOR_SLOT(Art, ArtFix + k) = (mps_word_t)Poly; - /* get(arena); */ - } - } - } - fflush(stdout); - CatalogCheck(); -} - - -/* MakeThing -- make an object of the size requested (in bytes) - * - * Any size is accepted. MakeThing may round it up (MakeThing always - * makes a dylan vector, which has a minimum size of 8 bytes). Vector - * slots, if any, are initialized to DYLAN_INT(0). - * - * After making the object, calls get(), to retrieve MPS messages. - * - * make_dylan_vector [fmtdytst.c] says: - * size = (slots + 2) * sizeof(mps_word_t); - * That is: a dylan vector has two header words before the first slot. - */ -static void* MakeThing(mps_arena_t arena, mps_ap_t ap, size_t size) -{ - mps_word_t v; - ulongest_t words; - ulongest_t slots; - - words = (size + (sizeof(mps_word_t) - 1) ) / sizeof(mps_word_t); - if(words < 2) - words = 2; - - slots = words - 2; - die(make_dylan_vector(&v, ap, slots), "make_dylan_vector"); - get(arena); - - return (void *)v; -} - -static void BigdropSmall(mps_arena_t arena, mps_ap_t ap, size_t big, char small_ref) -{ - static unsigned keepCount = 0; - unsigned i; - - mps_arena_park(arena); - for(i = 0; i < 100; i++) { - (void) MakeThing(arena, ap, big); - if(small_ref == 'A') { - myrootAmbig[keepCount++ % myrootAmbigCOUNT] = MakeThing(arena, ap, 1); - } else if(small_ref == 'E') { - myrootExact[keepCount++ % myrootExactCOUNT] = MakeThing(arena, ap, 1); - } else { - cdie(0, "BigdropSmall: small must be 'A' or 'E'.\n"); - } - } -} - - -/* df -- diversity function - * - * Either deterministic based on "number", or 'random' (ie. call rnd). - */ - -static unsigned long df(unsigned randm, unsigned number) -{ - if(randm == 0) { - return number; - } else { - return rnd(); - } -} - -static void Make(mps_arena_t arena, mps_ap_t ap, unsigned randm, unsigned keep1in, unsigned keepTotal, unsigned keepRootspace, unsigned sizemethod) -{ - unsigned keepCount = 0; - unsigned objCount = 0; - - Insist(keepRootspace <= myrootExactCOUNT); - - objCount = 0; - while(keepCount < keepTotal) { - mps_word_t v; - unsigned slots = 2; /* minimum */ - switch(sizemethod) { - case 0: { - /* minimum */ - slots = 2; - break; - } - case 1: { - slots = 2; - if(df(randm, objCount) % 10000 == 0) { - printf("*"); - slots = 300000; - } - break; - } - case 2: { - slots = 2; - if(df(randm, objCount) % 6661 == 0) { /* prime */ - printf("*"); - slots = 300000; - } - break; - } - default: { - printf("bad script command: sizemethod %u unknown.\n", sizemethod); - cdie(FALSE, "bad script command!"); - break; - } - } - die(make_dylan_vector(&v, ap, slots), "make_dylan_vector"); - DYLAN_VECTOR_SLOT(v, 0) = DYLAN_INT(objCount); - DYLAN_VECTOR_SLOT(v, 1) = (mps_word_t)NULL; - objCount++; - if(df(randm, objCount) % keep1in == 0) { - /* keep this one */ - myrootExact[df(randm, keepCount) % keepRootspace] = (void*)v; - keepCount++; - } - get(arena); - } - printf(" ...made and kept: %u objects, storing cyclically in " - "first %u roots " - "(actually created %u objects, in accord with " - "keep-1-in %u).\n", - keepCount, keepRootspace, objCount, keep1in); -} - - -static void Rootdrop(char rank_char) -{ - unsigned i; - - if(rank_char == 'A') { - for(i = 0; i < myrootAmbigCOUNT; ++i) { - myrootAmbig[i] = NULL; - } - } else if(rank_char == 'E') { - for(i = 0; i < myrootExactCOUNT; ++i) { - myrootExact[i] = NULL; - } - } else { - cdie(0, "Rootdrop: rank must be 'A' or 'E'.\n"); - } -} - - -#define stackwipedepth 50000 -static void stackwipe(void) -{ - unsigned iw; - unsigned long aw[stackwipedepth]; - - /* Do some pointless work that the compiler won't optimise away, so that - this function wipes over the stack by filling stuff into the "aw" - array. */ - - /* http://xkcd.com/710/ */ - /* I don't want my friends to stop calling; I just want the */ - /* compiler to stop optimising away my code. */ - - /* Do you ever get two even numbers next to each other? Hmmmm :-) */ - for(iw = 0; iw < stackwipedepth; iw++) { - if((iw & 1) == 0) { - aw[iw] = 1; - } else { - aw[iw] = 0; - } - } - for(iw = 1; iw < stackwipedepth; iw++) { - if(aw[iw - 1] + aw[iw] != 1) { - printf("Errrr....\n"); - break; - } - } -} - - -static void StackScan(mps_arena_t arena, int on) -{ - if(on) { - Insist(root_stackreg == NULL); - die(mps_root_create_reg(&root_stackreg, arena, - mps_rank_ambig(), (mps_rm_t)0, stack_thr, - mps_stack_scan_ambig, stack_start, 0), - "root_stackreg"); - Insist(root_stackreg != NULL); - } else { - Insist(root_stackreg != NULL); - mps_root_destroy(root_stackreg); - root_stackreg = NULL; - Insist(root_stackreg == NULL); - } -} - - -/* checksi -- check count of sscanf items is correct - */ - -static void checksi(int si, int si_shouldBe, const char *script, const char *scriptAll) -{ - if(si != si_shouldBe) { - printf("bad script command (sscanf found wrong number of params) %s (full script %s).\n", script, scriptAll); - cdie(FALSE, "bad script command!"); - } -} - -/* testscriptC -- actually runs a test script - * - */ -static void testscriptC(mps_arena_t arena, mps_ap_t ap, const char *script) -{ - const char *scriptAll = script; - int si, sb; /* sscanf items, sscanf bytes */ - - while(*script != '\0') { - switch(*script) { - case 'C': { - si = sscanf(script, "Collect%n", - &sb); - checksi(si, 0, script, scriptAll); - script += sb; - printf(" Collect\n"); - stackwipe(); - mps_arena_collect(arena); - mps_arena_release(arena); - break; - } - case 'K': { - si = sscanf(script, "Katalog()%n", - &sb); - checksi(si, 0, script, scriptAll); - script += sb; - printf(" Katalog()\n"); - CatalogDo(arena, ap); - break; - } - case 'B': { - ulongest_t big = 0; - char small_ref = ' '; - si = sscanf(script, "BigdropSmall(big %"SCNuLONGEST", small %c)%n", - &big, &small_ref, &sb); - checksi(si, 2, script, scriptAll); - script += sb; - printf(" BigdropSmall(big %"PRIuLONGEST", small %c)\n", - big, small_ref); - BigdropSmall(arena, ap, big, small_ref); - break; - } - case 'M': { - unsigned randm = 0; - unsigned keep1in = 0; - unsigned keepTotal = 0; - unsigned keepRootspace = 0; - unsigned sizemethod = 0; - si = sscanf(script, "Make(random %u, keep-1-in %u, keep %u, rootspace %u, sizemethod %u)%n", - &randm, &keep1in, &keepTotal, &keepRootspace, &sizemethod, &sb); - checksi(si, 5, script, scriptAll); - script += sb; - printf(" Make(random %u, keep-1-in %u, keep %u, rootspace %u, sizemethod %u).\n", - randm, keep1in, keepTotal, keepRootspace, sizemethod); - Make(arena, ap, randm, keep1in, keepTotal, keepRootspace, sizemethod); - break; - } - case 'R': { - char drop_ref = ' '; - si = sscanf(script, "Rootdrop(rank %c)%n", - &drop_ref, &sb); - checksi(si, 1, script, scriptAll); - script += sb; - printf(" Rootdrop(rank %c)\n", drop_ref); - Rootdrop(drop_ref); - break; - } - case 'S': { - unsigned on = 0; - si = sscanf(script, "StackScan(%u)%n", - &on, &sb); - checksi(si, 1, script, scriptAll); - script += sb; - printf(" StackScan(%u)\n", on); - StackScan(arena, on != 0); - break; - } - case 'Z': { - unsigned long s0; - si = sscanf(script, "ZRndStateSet(%lu)%n", - &s0, &sb); - checksi(si, 1, script, scriptAll); - script += sb; - printf(" ZRndStateSet(%lu)\n", s0); - rnd_state_set(s0); - break; - } - case ' ': - case ',': - case '.': { - script++; - break; - } - default: { - printf("unknown script command '%c' (script %s).\n", - *script, scriptAll); - cdie(FALSE, "unknown script command!"); - return; - } - } - get(arena); - } - -} - - -/* testscriptB -- create pools and objects; call testscriptC - * - * Is called via mps_tramp, so matches mps_tramp_t function prototype, - * and use trampDataStruct to pass parameters. - */ - -typedef struct trampDataStruct { - mps_arena_t arena; - mps_thr_t thr; - const char *script; -} trampDataStruct; - -static void *testscriptB(void *arg, size_t s) -{ - trampDataStruct trampData; - mps_arena_t arena; - mps_thr_t thr; - const char *script; - mps_fmt_t fmt; - mps_chain_t chain; - mps_pool_t amc; - int i; - mps_root_t root_table_Ambig; - mps_root_t root_table_Exact; - mps_ap_t ap; - void *stack_starts_here; /* stack scanning starts here */ - - Insist(s == sizeof(trampDataStruct)); - trampData = *(trampDataStruct*)arg; - arena = trampData.arena; - thr = trampData.thr; - script = trampData.script; - - die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain), - "pool_create amc"); - - for(i = 0; i < myrootAmbigCOUNT; ++i) { - myrootAmbig[i] = NULL; - } - die(mps_root_create_table(&root_table_Ambig, arena, mps_rank_ambig(), (mps_rm_t)0, - myrootAmbig, (size_t)myrootAmbigCOUNT), - "root_create - ambig"); - - for(i = 0; i < myrootExactCOUNT; ++i) { - myrootExact[i] = NULL; - } - die(mps_root_create_table(&root_table_Exact, arena, mps_rank_exact(), (mps_rm_t)0, - myrootExact, (size_t)myrootExactCOUNT), - "root_create - exact"); - - die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_create"); - - /* root_stackreg: stack & registers are ambiguous roots = mutator's workspace */ - stack_start = &stack_starts_here; - stack_thr = thr; - die(mps_root_create_reg(&root_stackreg, arena, - mps_rank_ambig(), (mps_rm_t)0, stack_thr, - mps_stack_scan_ambig, stack_start, 0), - "root_stackreg"); - - - mps_message_type_enable(arena, mps_message_type_gc_start()); - mps_message_type_enable(arena, mps_message_type_gc()); - mps_message_type_enable(arena, mps_message_type_finalization()); - - testscriptC(arena, ap, script); - - printf(" Destroy roots, pools, arena etc.\n\n"); - mps_root_destroy(root_stackreg); - mps_ap_destroy(ap); - mps_root_destroy(root_table_Exact); - mps_root_destroy(root_table_Ambig); - mps_pool_destroy(amc); - mps_chain_destroy(chain); - mps_fmt_destroy(fmt); - - return NULL; -} - - -/* testscriptA -- create arena, thr, and tramp; call testscriptB - */ -static void testscriptA(const char *script) -{ - mps_arena_t arena; - int si, sb; /* sscanf items, sscanf bytes */ - unsigned long arenasize = 0; - mps_thr_t thr; - mps_tramp_t trampFunction; - trampDataStruct trampData; - void *trampResult; - - si = sscanf(script, "Arena(size %lu)%n", &arenasize, &sb); - cdie(si == 1, "bad script command: Arena(size %%lu)"); - script += sb; - printf(" Create arena, size = %lu.\n", arenasize); - - /* arena */ - die(mps_arena_create(&arena, mps_arena_class_vm(), (size_t)arenasize), - "arena_create"); - - /* thr: used to stop/restart multiple threads */ - die(mps_thread_reg(&thr, arena), "thread"); - - /* tramp: used for protection (barrier hits) */ - /* call testscriptB! */ - trampFunction = testscriptB; - trampData.arena = arena; - trampData.thr = thr; - trampData.script = script; - mps_tramp(&trampResult, trampFunction, &trampData, sizeof trampData); - - mps_thread_dereg(thr); - mps_arena_destroy(arena); -} - - -/* main -- runs various test scripts - * - */ -int main(int argc, char **argv) -{ - randomize(argc, argv); - - /* 1<<19 == 524288 == 1/2 Mebibyte */ - /* 16<<20 == 16777216 == 16 Mebibyte */ - - /* 1<<19 == 524288 == 1/2 Mebibyte */ - /* This is bogus! sizemethod 1 can make a 300,000-slot dylan vector, ie. 1.2MB. */ - /* Try 10MB arena */ - /* testscriptA("Arena(size 10485760), Make(keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect."); */ - if(1) { - testscriptA("Arena(size 10000000), " - "Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect, " - "Rootdrop(rank E), StackScan(0), Collect, Collect, StackScan(1), " - "Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect, " - "Rootdrop(rank E), Collect, Collect."); - } - if(1) { - testscriptA("Arena(size 4000000), " - "Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect, " - "Rootdrop(rank E), StackScan(0), Collect, Collect, StackScan(1), " - "Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect, " - "Rootdrop(rank E), Collect, Collect."); - } - if(1) { - testscriptA("Arena(size 4000000), " - "Make(random 1, keep-1-in 5, keep 10000, rootspace 30000, sizemethod 1), " - "Rootdrop(rank E), Collect, " - "Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), " - "Rootdrop(rank E), Collect, " - "Make(random 1, keep-1-in 5, keep 100000, rootspace 30000, sizemethod 1), " - "Rootdrop(rank E), Collect, " - "Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), " - "Rootdrop(rank E), Collect."); - } - if(1) { - testscriptA("Arena(size 10485760), " - "Make(random 0, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 2), " - "Collect, " - "Rootdrop(rank E), Collect, Collect, " - "Make(random 0, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 2), " - "Collect, " - "Rootdrop(rank E), Collect, Collect."); - } - if(1) { - testscriptA("Arena(size 10485760), " - "ZRndStateSet(239185672), " - "Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect, " - "Rootdrop(rank E), StackScan(0), Collect, Collect, StackScan(1), " - "ZRndStateSet(239185672), " - "Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect, " - "Rootdrop(rank E), Collect, Collect."); - } - - /* LSP -- Large Segment Padding (job001811) - * - * BigdropSmall creates a big object & drops ref to it, - * then a small object but keeps a ref to it. Do this 100 - * times. (It also parks the arena, to avoid incremental - * collections). - * - * If big is 28000, it is <= 28672 bytes and therefore fits on a seg - * of 7 pages. AMC classes this as a Medium Segment and uses the - * remainder, placing the subsequent small object there. If the ref - * to small is "A" = ambig, the entire 7-page seg is retained. - * - * If big is > 28672 bytes (7 pages), it requires a seg of >= 8 - * pages. AMC classes this as a Large Segment, and does LSP (Large - * Segment Padding), to prevent the subsequent small object being - * placed in the remainder. If the ref to small is "A" = ambig, - * only its 1-page seg is retained. This greatly reduces the - * retention page-count. - * - * If the ref to small is "E" = exact, then the small object is - * preserved-by-copy onto a new seg. In this case there is no - * seg/page retention, so LSP does not help. It has a small cost: - * total pages increase from 700 to 900. So in this case (no ambig - * retention at all, pessimal allocation pattern) LSP would slightly - * increase the frequency of minor collections. - */ - /* 7p = 28672b; 8p = 32768b */ - /* 28000 = Medium segment */ - /* 29000 = Large segment */ - testscriptA("Arena(size 16777216), BigdropSmall(big 28000, small A), Collect."); - testscriptA("Arena(size 16777216), BigdropSmall(big 29000, small A), Collect."); - testscriptA("Arena(size 16777216), BigdropSmall(big 28000, small E), Collect."); - testscriptA("Arena(size 16777216), BigdropSmall(big 29000, small E), Collect."); - - /* 16<<20 == 16777216 == 16 Mebibyte */ - /* See .catalog.broken. - testscriptA("Arena(size 16777216), Katalog(), Collect."); - */ - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/code/zmess.c b/mps/code/zmess.c deleted file mode 100644 index 6d2840f86a9..00000000000 --- a/mps/code/zmess.c +++ /dev/null @@ -1,611 +0,0 @@ -/* zmess.c: Message test - * - * $Id$ - * Copyright (c) 2008 Ravenbrook Limited. See end of file for license. - * Portions copyright (C) 2002 Global Graphics Software. - * - * OBJECTIVE - * - * Test MPS messages. In particular: - * - Check prompt finalization even when there are several segs - * of guardians. This test replaces fin1658a.c. See job001658. - * - Check GC messages are correctly generated, posted, and queued, - * regardless of when the client gets them. (Note: "get" means - * "mps_message_get", throughout). See job001989. - * - * Please add tests for other message behaviour into this file. - * Expand the script language as necessary! RHSK 2008-12-19. - * - * - * DESIGN OVERVIEW - * - * Client (this test) does various actions that are known to provoke - * MPS messages. Client (this test) gets these messages at variable - * times. - * - * Verification is: - * - client gets all the expected messages, and no others, at the - * expected time; - * - no asserts or failures. - * - * Additionally: client checks the message order. MPS specification - * does not currently guarantee that messages are queued in order of - * posting, but in fact they should be, and it is a useful check. - * (But finalization messages from a single collection may be posted - * in any order). - * - * The actions, messages to check for, and get times, are scripted - * using a simple text code: - * C - action: request garbage-collection; - * F - action: make a (registered)finalized object unreachable - * (note: this drops the myroot ref, but some objects are - * deliberately kept alive by additional references; see - * .keep-alive) - * b - message produced: collection begin (mps_message_type_gc_start); - * e - message produced: collection end (mps_message_type_gc); - * f - message produced: finalization (mps_message_type_finalization); - * . - get messages. - * ! - get messages without discarding (see .discard). - * - * Example: - * script "Cbe.FFCbffe.Cbe" - * means: - * Request a collection and check for _gc_start and _gc messages - * (in that order, and no other messages). Then drop refs to two - * objects, request another collection, and check for _gc_start, - * the two finalization messages (in either order), and _gc. Then - * request a third collection and end the test WITHOUT GETTING - * the last two messages (note: no "."), to test that - * mps_arena_destroy copes with ungot messages. - * - * Each script runs in a newly created arena. - * - * - * CODE OVERVIEW - * - * main() has the list of testscripts. - * - * testscriptA() sets up a new arena and trampolines to testscriptB(). - * - * testscriptB() creates pools and objects for this test script. - * - * testscriptC() actually runs the script. - * - * - * DEPENDENCIES - * - * This test uses the dylan object format, but the reliance on this - * particular format is not great and could be removed. - * - * - * BUGS, FUTURE IMPROVEMENTS, ETC - * - * There are a few special objects with refs to each other (see - * .keep-alive). For clarity and flexibility, there should be special - * actions to drop the myroot ref to these, eg. '0', '1', '2', 'Y', 'Z'. - * Whereas (for clarity) 'F' should be an action that drops the myroot - * ref to a plain (non-kept-alive) object, thereby simply provoking a - * single finalization message. - * - * Actions could be expanded to include: - * - mps_arena_start_collect; - * - mps_arena_step; - * - automatic (not client-requested) collections. - * etc. - * - * HISTORY - * - * This code was created by first copying . - */ - -#include "testlib.h" -#include "mps.h" -#include "mpscamc.h" -#include "mpsavm.h" -#include "fmtdy.h" -#include "fmtdytst.h" -#include "mpstd.h" -#ifdef MPS_OS_W3 -#include "mpsw3.h" -#endif -#include - - -#define testArenaSIZE ((size_t)16<<20) - -/* usually (ArenaAlign / sizeof(Ref)) = 1024 */ -/* so choose 3000 to force 3 segments of guardians */ -#define myrootCOUNT 3000 - -/* testChain -- generation parameters for the test */ -#define genCOUNT 2 -static mps_gen_param_s testChain[genCOUNT] = { - { 150, 0.85 }, { 170, 0.45 } }; - - -/* note: static, so auto-initialised to NULL */ -static void *myroot[myrootCOUNT]; -enum { - rootSTATE, - deadSTATE, - finalizableSTATE, - finalizedSTATE -}; -static int state[myrootCOUNT]; - - -/* report -- get and check messages - * - * Get messages, report what was got, check they are the expected - * messages, and (for finalization messages) check that these objects - * should have been finalized (because we made them unreachable). - * - * .discard: The client should always call mps_message_discard when - * it has finished with the message. But calling with the "discard" - * parameter set to false lets us check how the MPS handles naughty - * clients. The undiscarded messages should be cleared up by - * ArenaDestroy. In a diagnostic variety (eg .variety.di) the - * ArenaDestroy diag shows the contents of the control pool, and you - * can clearly see the undiscarded messages (just before the control - * pool is destroyed). - */ -static void report(mps_arena_t arena, const char *pm, Bool discard) -{ - int found = 0; - char mFound = '\0'; - mps_message_type_t type; - - while (mps_message_queue_type(&type, arena)) { - mps_message_t message; - mps_word_t *obj; - mps_word_t objind; - mps_addr_t objaddr; - - cdie(mps_message_get(&message, arena, type), - "get"); - found += 1; - - switch(type) { - case mps_message_type_gc_start(): { - printf(" Begin Collection\n"); - mFound = 'b'; - break; - } - case mps_message_type_gc(): { - printf(" End Collection\n"); - mFound = 'e'; - break; - } - case mps_message_type_finalization(): { - mps_message_finalization_ref(&objaddr, arena, message); - obj = objaddr; - objind = DYLAN_INT_INT(DYLAN_VECTOR_SLOT(obj, 0)); - printf(" Finalization for object %lu at %p\n", objind, objaddr); - cdie(myroot[objind] == NULL, "finalized live"); - cdie(state[objind] == finalizableSTATE, "not finalizable"); - state[objind] = finalizedSTATE; - mFound = 'f'; - break; - } - default: { - cdie(0, "message type"); - break; - } - } - - if(discard) { - mps_message_discard(arena, message); /* .discard */ - } - - cdie('\0' != *pm, "Found message, but did not expect any"); - cdie(mFound == *pm, "Found message type != Expected message type"); - pm++; - } - - mFound = '\0'; - cdie(mFound == *pm, "No message found, but expected one"); -} - - -/* testscriptC -- actually runs a test script - * - */ -static void testscriptC(mps_arena_t arena, const char *script) -{ - unsigned isLoNext = 1; - unsigned loNext = 0; - unsigned hiNext = myrootCOUNT - 1; - unsigned i; - const char *scriptAll = script; - char am[100]; /* Array of Messages (expected but not yet got) */ - char *pmNext = am; /* Pointer to where Next Message will be stored */ - - while(*script != '\0') { - switch(*script) { - case '.': { - *pmNext = '\0'; - printf(" Getting messages (expecting \"%s\")...\n", am); - report(arena, am, TRUE); - printf(" ...done.\n"); - pmNext = am; - break; - } - case '!': { - /* Like '.', but not discarding got messages; see .discard */ - *pmNext = '\0'; - printf(" Getting messages (expecting \"%s\")...\n", am); - report(arena, am, FALSE); /* FALSE: see .discard */ - printf(" ...done.\n"); - printf(" NOTE: DELIBERATELY FAILING TO DISCARD MESSAGES, " - "TO SEE HOW MPS COPES.\n"); /* .discard */ - pmNext = am; - break; - } - case 'C': { - printf(" Collect\n"); - mps_arena_collect(arena); - break; - } - case 'F': { - /* (perhaps) make an object Finalizable - * - * .alternate: We alternately pick objects from the low and - * high ends of the myroot array. This is used to test for - * the defect described in job001658. - */ - Insist(loNext <= hiNext); - i = isLoNext ? loNext++ : hiNext--; - isLoNext = 1 - isLoNext; - - printf(" Drop myroot ref to object %u -- " - "this might make it Finalizable\n", i); - /* drop myroot ref, to perhaps make i finalizable */ - /* (but see .keep-alive) */ - myroot[i] = NULL; - state[i] = finalizableSTATE; - break; - } - case 'b': - case 'e': - case 'f': { - /* expect that MPS has posted a particular message */ - *pmNext++ = *script; - break; - } - default: { - printf("unknown script command %c (script %s).\n", - *script, scriptAll); - cdie(FALSE, "unknown script command"); - return; - } - } - Insist(am <= pmNext && pmNext < am + NELEMS(am)); - script++; - } -} - - -/* testscriptB -- create pools and objects; call testscriptC - * - * Is called via mps_tramp, so matches mps_tramp_t function prototype, - * and use trampDataStruct to pass parameters. - */ - -typedef struct trampDataStruct { - mps_arena_t arena; - mps_thr_t thr; - const char *script; -} trampDataStruct; - -static void *testscriptB(void *arg, size_t s) -{ - trampDataStruct trampData; - mps_arena_t arena; - mps_thr_t thr; - const char *script; - mps_fmt_t fmt; - mps_chain_t chain; - mps_pool_t amc; - mps_root_t root_table; - mps_ap_t ap; - mps_root_t root_stackreg; - int i; - int N = myrootCOUNT - 1; - void *stack_starts_here; /* stack scanning starts here */ - - Insist(s == sizeof(trampDataStruct)); - trampData = *(trampDataStruct*)arg; - arena = trampData.arena; - thr = trampData.thr; - script = trampData.script; - - die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain), - "pool_create amc"); - for(i = 0; i < myrootCOUNT; ++i) { - myroot[i] = NULL; - } - die(mps_root_create_table(&root_table, arena, mps_rank_exact(), (mps_rm_t)0, - myroot, (size_t)myrootCOUNT), - "root_create"); - die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_create"); - - /* root_stackreg: stack & registers are ambiguous roots = mutator's workspace */ - die(mps_root_create_reg(&root_stackreg, arena, - mps_rank_ambig(), (mps_rm_t)0, thr, - mps_stack_scan_ambig, &stack_starts_here, 0), - "root_stackreg"); - - /* Make myrootCOUNT registered-for-finalization objects. */ - /* Each is a dylan vector with 2 slots, inited to: (index, NULL) */ - for(i = 0; i < myrootCOUNT; ++i) { - mps_word_t v; - mps_addr_t v_ref; - die(make_dylan_vector(&v, ap, 2), "make_dylan_vector"); - DYLAN_VECTOR_SLOT(v, 0) = DYLAN_INT(i); - DYLAN_VECTOR_SLOT(v, 1) = (mps_word_t)NULL; - v_ref = (mps_addr_t)v; - die(mps_finalize(arena, &v_ref), "finalize"); - myroot[i] = (void*)v; - state[i] = rootSTATE; - } - - /* .keep-alive: Create some additional inter-object references. - * - * 1 and N-1 don't die until myroot refs to both have been nulled. - * - * 2 and 3 don't die until myroot refs to both have been nulled. - * - * We do this to check that reachability via non-root refs prevents - * finalization. - */ - - /* Leave 0 and N containing NULL refs */ - - /* Make 1 and N-1 refer to each other */ - DYLAN_VECTOR_SLOT(myroot[1] , 1) = (mps_word_t)myroot[N-1]; - DYLAN_VECTOR_SLOT(myroot[N-1], 1) = (mps_word_t)myroot[1]; - - /* Make 2 and 3 refer to each other */ - DYLAN_VECTOR_SLOT(myroot[2], 1) = (mps_word_t)myroot[3]; - DYLAN_VECTOR_SLOT(myroot[3], 1) = (mps_word_t)myroot[2]; - - /* Stop stack scanning, otherwise stack or register dross from */ - /* these setup functions can cause unwanted object retention, */ - /* which would mean we don't get the finalization messages we */ - /* expect. */ - mps_root_destroy(root_stackreg); - - mps_message_type_enable(arena, mps_message_type_gc_start()); - mps_message_type_enable(arena, mps_message_type_gc()); - mps_message_type_enable(arena, mps_message_type_finalization()); - - testscriptC(arena, script); - - mps_ap_destroy(ap); - mps_root_destroy(root_table); - mps_pool_destroy(amc); - mps_chain_destroy(chain); - mps_fmt_destroy(fmt); - - return NULL; -} - - -/* testscriptA -- create arena, thr, and tramp; call testscriptB - */ -static void testscriptA(const char *script) -{ - mps_arena_t arena; - mps_thr_t thr; - mps_tramp_t trampFunction; - trampDataStruct trampData; - void *trampResult; - - printf("Script: \"%s\"\n Create arena etc.\n", script); - - /* arena */ - die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), - "arena_create"); - - /* thr: used to stop/restart multiple threads */ - die(mps_thread_reg(&thr, arena), "thread"); - - /* tramp: used for protection (barrier hits) */ - /* call testscriptB! */ - trampFunction = testscriptB; - trampData.arena = arena; - trampData.thr = thr; - trampData.script = script; - mps_tramp(&trampResult, trampFunction, &trampData, sizeof trampData); - - mps_thread_dereg(thr); - mps_arena_destroy(arena); - - printf(" Destroy arena etc.\n\n"); - -} - -/* TIMCA_remote -- TraceIdMessagesCreate Alloc remote control - * - * In low memory situations, ControlAlloc may be unable to allocate - * memory for GC messages. This needs to work flawlessly, but is - * hard to test. - * - * To simulate it for testing purposes, add the following lines to - * traceanc.c, before the definition of TraceIdMessagesCreate: - * #define ControlAlloc !TIMCA_remote() ? ResFAIL : ControlAlloc - * extern Bool TIMCA_remote(void); - * (See changelist 166959). - * - * TIMCA_remote returns a Bool, true for let "ControlAlloc succeed". - */ -static const char *TIMCA_str = ""; -static int TIMCA_done = 0; -static void TIMCA_setup(const char *string) -{ - /* TIMCA_setup -- TraceIdMessagesCreate Alloc remote control - * - * 1..9 -- succeed this many times - * 0 -- fail once - * NUL -- succeed from now on - * - * Eg: "1400" succeeds 5 times, fails 2 times, then succeeds forever. - */ - TIMCA_str = string; - TIMCA_done = 0; -} - -extern Bool TIMCA_remote(void); -Bool TIMCA_remote(void) -{ - Bool succeed; - - if(*TIMCA_str == '\0') { - succeed = TRUE; - } else if(*TIMCA_str == '0') { - succeed = FALSE; - TIMCA_str++; - } else { - Insist(*TIMCA_str >= '1' && *TIMCA_str <= '9'); - succeed = TRUE; - TIMCA_done++; - if(TIMCA_done == *TIMCA_str - '0') { - TIMCA_done = 0; - TIMCA_str++; - } - } - - return succeed; -} - - -/* main -- runs various test scripts - * - */ -int main(int argc, char **argv) -{ - - randomize(argc, argv); - - /* Scripts that should fail (uncomment to show failure is detected) */ - /*testscriptA("C.");*/ - /*testscriptA("b.");*/ - - /* The most basic scripts */ - testscriptA("."); - testscriptA("Cbe."); - testscriptA("Cbe.Cbe."); - - /* Get messages, but not promptly */ - testscriptA(".Cbe.CbeCbeCbe."); - - /* Ungot messages at ArenaDestroy */ - testscriptA("Cbe"); - testscriptA("Cbe.CbeCbeCbe"); - - /* Fail to call mps_message_discard */ - testscriptA("Cbe!"); - testscriptA("Cbe!CbeCbeCbe!"); - - /* Simple finalization - * - * These tests rely on the particular order in which the "F" command - * nulls-out references. Not every "F" makes an object finalizable. - * See .keep-alive. - */ - testscriptA("FFCbffe."); - testscriptA("FFCbffe.FFCbffe."); - testscriptA("FFCbffe.FCbe.F.Cbffe.FFCbfe.FF.Cbfffe."); - - /* Various other scripts */ - testscriptA("Cbe.FFCbffe.Cbe"); - - /* Simulate low memory situations - * - * These scripts only work with a manually edited traceanc.c -- - * see TIMCA_remote() above. - * - * When TraceIdMessagesCreate is trying to pre-allocate GC messages, - * either "0" or "10" makes it fail -- "0" fails the trace start - * message alloc, whereas "10" fails the trace end message alloc. - * In either case TraceIdMessagesCreate promptly gives up, and - * neither start nor end message will be sent for the next trace. - * - * See . - */ - if(0) { - /* ArenaCreate unable to pre-allocate: THESE SHOULD FAIL */ - /* manually edit if(0) -> if(1) to test these */ - if(0) { - TIMCA_setup("0"); testscriptA("Fail at create 1"); - } - if(0) { - TIMCA_setup("10"); testscriptA("Fail at create 2"); - } - - /* ArenaDestroy with no pre-allocated messages */ - TIMCA_setup("20"); testscriptA("Cbe."); - TIMCA_setup("210"); testscriptA("Cbe."); - - /* Collect with no pre-allocated messages: drops messages, */ - /* hence "C." instead of "Cbe.". Also, in diagnostic varieties, */ - /* these should produce a "droppedMessages" diagnostic at */ - /* ArenaDestroy. */ - TIMCA_setup("2022"); testscriptA("Cbe.C.Cbe."); - TIMCA_setup("21022"); testscriptA("Cbe.C.Cbe."); - - /* 2 Collects and ArenaDestroy with no pre-allocated messages */ - TIMCA_setup("2000"); testscriptA("Cbe.C.C."); - TIMCA_setup("201010"); testscriptA("Cbe.C.C."); - - TIMCA_setup(""); /* must reset it! */ - } - - fflush(stdout); /* synchronize */ - fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); - return 0; -} - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2001-2002, 2008 Ravenbrook Limited . - * All rights reserved. This is an open source license. Contact - * Ravenbrook for commercial licensing options. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Redistributions in any form must be accompanied by information on how - * to obtain complete source code for this software and any accompanying - * software that uses this software. The source code must either be - * included in the distribution or be available for no more than the cost - * of distribution plus a nominal fee, and must be freely redistributable - * under reasonable conditions. For an executable file, complete source - * code means the source code for all modules it contains. It does not - * include source code for modules or files that typically accompany the - * major components of the operating system on which the executable file - * runs. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/mps/configure b/mps/configure deleted file mode 100755 index 455fecde27f..00000000000 --- a/mps/configure +++ /dev/null @@ -1,4023 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for Memory Pool System Kit master. -# -# Report bugs to . -# -# -# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Use a proper internal environment variable to ensure we don't fall - # into an infinite loop, continuously re-executing ourselves. - if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then - _as_can_reexec=no; export _as_can_reexec; - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -as_fn_exit 255 - fi - # We don't want this to propagate to other subprocesses. - { _as_can_reexec=; unset _as_can_reexec;} -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : - -else - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || exit 1 -test -x / || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes -else - as_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - if test "x$CONFIG_SHELL" != x; then : - export CONFIG_SHELL - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: mps-questions@ravenbrook.com about your system, -$0: including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." - fi - exit 1 -fi -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # If we had to re-execute with $CONFIG_SHELL, we're ensured to have - # already done that, so ensure we don't try to do so again and fall - # in an infinite loop. This has already happened in practice. - _as_can_reexec=no; export _as_can_reexec - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -test -n "$DJDIR" || exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME='Memory Pool System Kit' -PACKAGE_TARNAME='mps-kit' -PACKAGE_VERSION='master' -PACKAGE_STRING='Memory Pool System Kit master' -PACKAGE_BUGREPORT='mps-questions@ravenbrook.com' -PACKAGE_URL='http://www.ravenbrook.com/project/mps/' - -ac_unique_file="code/mps.c" -ac_subst_vars='LTLIBOBJS -LIBOBJS -INSTALL_TARGET -CLEAN_TARGET -BUILD_TARGET -MPS_TARGET_NAME -MAKE -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build -INSTALL_DATA -INSTALL_SCRIPT -INSTALL_PROGRAM -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -' - ac_precious_vars='build_alias -host_alias -target_alias -CC -CFLAGS -LDFLAGS -LIBS -CPPFLAGS' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures Memory Pool System Kit master to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/mps-kit] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of Memory Pool System Kit master:";; - esac - cat <<\_ACEOF - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to . -Memory Pool System Kit home page: . -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -Memory Pool System Kit configure master -generated by GNU Autoconf 2.69 - -Copyright (C) 2012 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## - -# ac_fn_c_try_compile LINENO -# -------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_compile -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by Memory Pool System Kit $as_me master, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - $as_echo "## ---------------- ## -## Cache variables. ## -## ---------------- ##" - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - $as_echo "## ----------------- ## -## Output variables. ## -## ----------------- ##" - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## -## File substitutions. ## -## ------------------- ##" - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - $as_echo "## ----------- ## -## confdefs.h. ## -## ----------- ##" - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5; } - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -ac_aux_dir= -for ac_dir in tool/autoconf/build-aux "$srcdir"/tool/autoconf/build-aux; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in tool/autoconf/build-aux \"$srcdir\"/tool/autoconf/build-aux" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - - - -# Checks for programs. -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` - -# The possible output files: -ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" - -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { { ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } -ac_exeext=$ac_cv_exeext - -rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } -if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -FILE *f = fopen ("conftest.out", "w"); - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -ac_clean_files="$ac_clean_files conftest.out" -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -if test "$cross_compiling" != yes; then - { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if { ac_try='./conftest$ac_cv_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if ${ac_cv_objext+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } -if test -z "$INSTALL"; then -if ${ac_cv_path_install+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - fi - done - done - ;; -esac - - done -IFS=$as_save_IFS - -rm -rf conftest.one conftest.two conftest.dir - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - - -AX_CFLAGS_WARN_ALL - -# These flags aren't used for building the MPS, but for sample programs. -CFLAGS_GC="-ansi -pedantic -Wall -Werror -Wpointer-arith \ - -Wstrict-prototypes -Wmissing-prototypes \ - -Winline -Waggregate-return -Wnested-externs \ - -Wcast-qual -Wshadow -Wstrict-aliasing=2 -O -g3" -CFLAGS_LL="$CFLAGS_GC -Wno-extended-offsetof" - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target platform" >&5 -$as_echo_n "checking target platform... " >&6; } -BUILD_TARGET=build-via-make -CLEAN_TARGET=clean-make-build -INSTALL_TARGET=install-make-build -case $host in - i*86-*-linux*) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux x86" >&5 -$as_echo "Linux x86" >&6; } - MPS_TARGET_NAME=lii3gc - CFLAGS="$CFLAGS_GC" - ;; - x86_64-*-linux*) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux x86_64" >&5 -$as_echo "Linux x86_64" >&6; } - MPS_TARGET_NAME=lii6gc - CFLAGS="$CFLAGS_GC" - ;; - i*86-*-darwin*) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Mac OS X x86" >&5 -$as_echo "Mac OS X x86" >&6; } - MPS_TARGET_NAME=xci3ll - BUILD_TARGET=build-via-xcode - CLEAN_TARGET=clean-xcode-build - INSTALL_TARGET=install-xcode-build - CFLAGS="$CFLAGS_LL" - ;; - x86_64-apple-darwin*) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Mac OS X x86_64" >&5 -$as_echo "Mac OS X x86_64" >&6; } - MPS_TARGET_NAME=xci6ll - BUILD_TARGET=build-via-xcode - CLEAN_TARGET=clean-xcode-build - INSTALL_TARGET=install-xcode-build - CFLAGS="$CFLAGS_LL" - ;; - i*86-*-freebsd*) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD x86" >&5 -$as_echo "FreeBSD x86" >&6; } - MPS_TARGET_NAME=fri3gc - CFLAGS="$CFLAGS_GC" - ;; - amd64-*-freebsd*) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD x86_64" >&5 -$as_echo "FreeBSD x86_64" >&6; } - MPS_TARGET_NAME=fri6gc - CFLAGS="$CFLAGS_GC" - ;; - *) - as_fn_error $? "MPS does not support this platform out of the box. See manual/build.txt" "$LINENO" 5 -esac - -for ac_prog in gnumake gmake make -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_MAKE+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$MAKE"; then - ac_cv_prog_MAKE="$MAKE" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_MAKE="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -MAKE=$ac_cv_prog_MAKE -if test -n "$MAKE"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 -$as_echo "$MAKE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$MAKE" && break -done -test -n "$MAKE" || MAKE="as_fn_error $? "Unable to find a make program." "$LINENO" 5" - -if ! $MAKE --version | grep -q "GNU" 2> /dev/null; then - as_fn_error $? "MPS requires GNU make to build from configure, but see manual/build.txt" "$LINENO" 5 -fi - - - - - - -ac_config_files="$ac_config_files Makefile example/scheme/Makefile" - - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by Memory Pool System Kit $as_me master, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Report bugs to . -Memory Pool System Kit home page: ." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -Memory Pool System Kit config.status master -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "example/scheme/Makefile") CONFIG_FILES="$CONFIG_FILES example/scheme/Makefile" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES " -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - - - - esac - -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - - -echo 1>&2 "CONFIGURE/MAKE IS NOT THE BEST WAY TO BUILD THE MPS -- see " diff --git a/mps/configure.ac b/mps/configure.ac deleted file mode 100644 index aba59690caa..00000000000 --- a/mps/configure.ac +++ /dev/null @@ -1,100 +0,0 @@ -# configure.ac -- autoconf configuration for the MPS -*- Autoconf -*- -# -# $Id$ -# Copyright (C) 2012 Ravenbrook Limited. See end of file for license. -# -# YOU DON'T NEED AUTOCONF TO BUILD THE MPS -# This is just here for people who want or expect a configure script. -# See [Building the Memory Pool System](manual/build.txt) for how best -# to build and integrate the MPS. -# -# Generate the configure script with -# -# autoreconf -vif -# - -AC_PREREQ([2.50]) -# http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Initializing-configure.html#Initializing-configure -AC_INIT([Memory Pool System Kit], - [master], - [mps-questions@ravenbrook.com], - [mps-kit], - [http://www.ravenbrook.com/project/mps/]) -AC_CONFIG_AUX_DIR(tool/autoconf/build-aux) -AC_CONFIG_SRCDIR([code/mps.c]) - -# Checks for programs. -AC_PROG_CC -AC_LANG_C -AC_PROG_INSTALL - -AX_CFLAGS_WARN_ALL - -# These flags aren't used for building the MPS, but for sample programs. -CFLAGS_GC="-ansi -pedantic -Wall -Werror -Wpointer-arith \ - -Wstrict-prototypes -Wmissing-prototypes \ - -Winline -Waggregate-return -Wnested-externs \ - -Wcast-qual -Wshadow -Wstrict-aliasing=2 -O -g3" -CFLAGS_LL="$CFLAGS_GC -Wno-extended-offsetof" - -AC_CANONICAL_HOST -AC_MSG_CHECKING([target platform]) -BUILD_TARGET=build-via-make -CLEAN_TARGET=clean-make-build -INSTALL_TARGET=install-make-build -case $host in - i*86-*-linux*) - AC_MSG_RESULT([Linux x86]) - MPS_TARGET_NAME=lii3gc - CFLAGS="$CFLAGS_GC" - ;; - x86_64-*-linux*) - AC_MSG_RESULT([Linux x86_64]) - MPS_TARGET_NAME=lii6gc - CFLAGS="$CFLAGS_GC" - ;; - i*86-*-darwin*) - AC_MSG_RESULT([Mac OS X x86]) - MPS_TARGET_NAME=xci3ll - BUILD_TARGET=build-via-xcode - CLEAN_TARGET=clean-xcode-build - INSTALL_TARGET=install-xcode-build - CFLAGS="$CFLAGS_LL" - ;; - x86_64-apple-darwin*) - AC_MSG_RESULT([Mac OS X x86_64]) - MPS_TARGET_NAME=xci6ll - BUILD_TARGET=build-via-xcode - CLEAN_TARGET=clean-xcode-build - INSTALL_TARGET=install-xcode-build - CFLAGS="$CFLAGS_LL" - ;; - i*86-*-freebsd*) - AC_MSG_RESULT([FreeBSD x86]) - MPS_TARGET_NAME=fri3gc - CFLAGS="$CFLAGS_GC" - ;; - amd64-*-freebsd*) - AC_MSG_RESULT([FreeBSD x86_64]) - MPS_TARGET_NAME=fri6gc - CFLAGS="$CFLAGS_GC" - ;; - *) - AC_MSG_ERROR([MPS does not support this platform out of the box. See manual/build.txt]) -esac - -AC_CHECK_PROGS([MAKE],[gnumake gmake make],[AC_MSG_ERROR([Unable to find a make program.])]) -if ! $MAKE --version | grep -q "GNU" 2> /dev/null; then - AC_MSG_ERROR([MPS requires GNU make to build from configure, but see manual/build.txt]) -fi - -AC_SUBST(MPS_TARGET_NAME) -AC_SUBST(BUILD_TARGET) -AC_SUBST(CLEAN_TARGET) -AC_SUBST(INSTALL_TARGET) -AC_SUBST(CFLAGS) -AC_CONFIG_FILES(Makefile example/scheme/Makefile) - -AC_OUTPUT - -echo 1>&2 "CONFIGURE/MAKE IS NOT THE BEST WAY TO BUILD THE MPS -- see " diff --git a/mps/design/alloc-frame/index.html b/mps/design/alloc-frame/index.html deleted file mode 100644 index b9395a57ed3..00000000000 --- a/mps/design/alloc-frame/index.html +++ /dev/null @@ -1,517 +0,0 @@ - - - - - - - - -Design of the MPS allocation frame protocol - - - - - - - -
-              DESIGN OF THE MPS ALLOCATION FRAME PROTOCOL
-                         design.mps.alloc-frame
-                             incomplete doc
-                            tony 1998-10-02
-
-INTRODUCTION
-
-.intro: This document explains the design of the support for allocation frames 
-in MPS. 
-
-.readership: This document is intended for any MM developer.
-
-.overview: Allocation frames are used for implementing stack pools; each stack 
-frame corresponds to an allocation frame.  Allocation frames may also be 
-suitable for implementing other sub-pool groupings, such as generations and 
-ramp allocation patterns.  .overview.ambition: We now believe this to be a 
-design that loses too many advantages of stack allocation for questionable 
-gains.  The requirements are almost entirely based on unanalysed anecdote, 
-instead of actual clients.  [We plan to supersede this with a stack pool design 
-at some point in the future.  pekka 2000-03-09]
-
-.hist.0: Written by Tony 1998-10-02
-
-
-DEFINITIONS
-
-.def.alloc-frame: An allocation frame is a generic name for a device which 
-groups objects together with other objects at allocation time, and which may 
-have a parent/child relationship with other allocation frames.
-
-
-PURPOSE
-
-.purpose.stack-allocation: The allocation frame protocol is intended to support 
-efficient memory management for stack allocation, i.e., the allocation of 
-objects which have dynamic extent.
-
-.purpose.general: The allocation frame protocol is intended to be sufficiently 
-general that it will be useful in supporting other types of nested allocation 
-patterns too.  For example, it could be used to for EPVM-style save and 
-restore, ramp allocation patterns or generations. 
-
-
-REQUIREMENTS
-
-Known requirements
-
-.req.stack-alloc: Provide a interface for clients to describe a stack 
-allocation pattern, as an alternative to using the control stack.
-
-.req.efficient: Permit an implementation which is comparable in efficiency to 
-allocating on the control stack.
-
-.req.ap: Support allocation via allocation points (APs).
-
-.req.format: Support the allocation of formatted objects.
-
-.req.scan: Ensure that objects in allocation frames can participate in garbage 
-collection by being scanned.
-
-.req.fix: Ensure that objects in allocation frames can participate in garbage 
-collection by accepting Fix requests.
-
-.req.condemn: Ensure that objects in allocation frames can participate in 
-garbage collection by being condemned.
-
-.attr.locking: Minimize the synchronization cost for the creation and 
-destruction of frames.
-
-
-Proto-requirements
-
-.proto-req: The following are possible requirements that might be important in 
-the future. The design does not necessarily meet all these requirements, but it 
-does consider them all. Each requirement either has direct support in the 
-framework, or could be supported with future additions to the framework.
-
-.req.parallels: The allocation frame protocol should provide a framework for 
-exploiting the parallels between stack extents, generations and "ramps".
-
-.req.pool-destroy: It should be possible to use allocation frames to free all 
-objects in a pool without destroying the pool.
-
-.req.epvm: It should be possible to implement EPVM-style save and restore 
-operations by creating and destroying allocation frames.
-
-.req.subst: It should be possible to substitute a stack pool with a GC-ed pool 
-so that erroneous use of a stack pool can be detected.
-
-.req.format-extensions: It should be possible for stack pools to utilize the 
-same format as any other pool, including debugging formats that include 
-fenceposting, etc.
-
-.req.mis-nest: Should ensure "mis-nested" stacks are safe.
-
-.req.non-top-level: Should support allocation in the non-top stack extent.
-
-.req.copy-if-necessary: Should ensure that stack pools can support 
-"copy-if-necessary" (so that low-level system code can heapify stack objects.)
-
-.req.preserve: When an object is in an allocation frame which is being 
-destroyed, it should be possible to preserve that object in the parent frame.
-
-.req.contained: Should allow clients to ask if an object is "contained" in a 
-frame. The object is contained in a frame if it is affected when the frame is 
-ended.
-
-.req.alloc-with-other:  Should allow clients to allocate an object in the same 
-frame as another object.
-
-
-OVERVIEW
-
-.frame-classes: The protocol supports different types of allocation frames, 
-which are represented as "frame classes".  It's up to pools to determine which 
-classes of allocation frames they support.  Pools which support more than one 
-frame class rely on the client to indicate which class is currently of 
-interest.  The client indicates this by means of an operation which stores the 
-class in the buffer to which the allocation point is attached.
-
-.frame-handles: Allocation frames are described via abstract "frame handles".  
-Pools may choose what the representation of a frame handle should be.  Frame 
-handles are static, and the client need not store them in a GC root.
-
-.lightweight-frames: The design includes an extension to the allocation point 
-protocol, which permits the creation and destruction of allocation frames 
-without the necessity for claiming the arena lock.  Such frames are called 
-"lightweight frames".
-
-
-OPERATIONS
-
-.op.intro: Each operation has both an external (client) interface and an 
-internal (MPS) interface.  The external function takes an allocation point as a 
-parameter, determines which buffer and pool it belongs to, and calls the 
-internal function with the buffer and pool as parameters.
-
-.op.obligatory: The following operations are supported on any allocation point 
-which supports allocation frames:-
-
-.operation.push: The PushFrame operation creates a new allocation frame of the 
-currently chosen frame class, makes this new frame the current frame, and 
-returns a handle for the frame.
-
-.operation.pop: The PopFrame operation takes a frame handle as a parameter.  
-Some pool classes might insist or assume that this is the handle for the 
-current frame.  It finds the parent of that frame and makes it the current 
-frame.  The operation indicates that all children of the new current frame 
-contain objects which are likely to be dead.  The reclaim policy is up to the 
-pool; some classes might insist or assume that the objects must be dead, and 
-eagerly free them.  Note that this might introduce the possibility of leaving 
-dangling pointers elsewhere in the arena.  If so, it's up to the pool to decide 
-what to do about this.
-
-.op.optional: The following operations are supported for some allocation 
-frames, but not all. Pools may choose to support some or all of these 
-operations for certain frame classes. An unsupported operation will return a 
-failure value:-
-
-.operation.select: The SelectFrame operation takes a frame handle as a 
-parameter and makes that frame the current frame.  It does not indicate that 
-any children of the current frame contain objects which are likely to be dead.
-
-.operation.select-addr: The SelectFrameOfAddr operation takes an address as a 
-parameter and makes the frame of that address the current frame.  It does not 
-indicate that any children of the current frame contain objects which are 
-likely to be dead.
-
-.operation.in-frame: The AddrInFrame operation determines whether the supplied 
-address is the address of an object allocated in the supplied frame, or any 
-child of that frame.
-
-.operation.set: The SetFrameClass operation takes a frame class and an 
-allocation point as parameters, and makes that the current frame class for the 
-allocation point.  The next PushFrame operation will create a new frame of that 
-class.
-
-
-INTERFACE
-
-External types (used by all client of allocation frames)
-
-.type.client.frame-handle: Frame handles are defined as an abstract type:
-        typedef struct mps_frame_s *mps_frame_t;  
-
-
-External types  (complete set)
-
-.type.client.frame-class: Frame classes are defined as an abstract type:
-        typedef struct mps_frame_class_s *mps_frame_class_t;  
-
-.type.client.frame-class.access: Clients access frame classes by means of 
-dedicated functions for each frame class. 
-
-
-External functions (used by all client of allocation frames)
-
-.fn.client.push: The following function is used by clients to invoke the 
-PushFrame operation.  For lightweight frames, this might not invoke the 
-corresponding internal function:
-       mps_res_t mps_ap_frame_push(mps_frame_t *frame_o, mps_ap_t buf);  
-
-.fn.client.pop:  The following function is used by clients to invoke the 
-PopFrame operation.  For lightweight frames, this might not invoke the 
-corresponding internal function:
-       mps_res_t mps_ap_frame_pop(mps_ap_t buf, mps_frame_t frame);
-
-
-External functions (complete set)
-
-.fn.client.select:  The following function is used by clients to invoke the 
-SelectFrame operation:
-       mps_res_t mps_ap_frame_select(mps_ap_t buf, mps_frame_t frame);
-
-.fn.client.select-addr:  The following function is used by clients to invoke 
-the SelectFrameOfAddr operation:
-       mps_res_t mps_ap_frame_select_from_addr(mps_ap_t buf, mps_addr_t addr);
-
-.fn.client.in-frame:  The following function is used by clients to invoke the 
-AddrInFrame operation:
-       mps_res_t mps_ap_addr_in_frame(mps_bool_t *inframe_o, mps_ap_t buf, 
-                                      mps_addr_t *addrref, mps_frame_t frame);  
-
-.fn.client.set: The following function is used by clients to invoke the 
-SetFrameClass operation:
-       mps_res_t mps_ap_set_frame_class(mps_ap_t buf, mps_frame_class_t 
-class);  
-
-
-.fn.client.stack-frame-class: The following function is used by clients to 
-access the frame class used for simple stack allocation:
-       mps_frame_class_t mps_alloc_frame_class_stack(void);  
-
-
-Internal types (used by all implementations of allocation frames)
-
-.type.frame-handle: Frame handles are defined as an abstract type:
-       typedef struct AllocFrameStruct *AllocFrame;
-
-
-Internal types  (complete set)
-
-.type.frame-class: Frame classes are defined as an abstract type:
-       typedef struct AllocFrameClassStruct *AllocFrameClass;
-
-
-Internal functions (used by all implementations of allocation frames)
-
-
-.fn.push: A pool method of the following type is called (if needed) to invoke 
-the PushFrame operation:
-       typedef Res (*PoolFramePushMethod)(AllocFrame *frameReturn,
-                                          Pool pool, Buffer buf);
- 
-.fn.pop: A pool method of the following type is called (if needed) to invoke 
-the PopFrame operation:
-       typedef Res (*PoolFramePopMethod)(Pool pool, Buffer buf,
-                                         AllocFrame frame);
-
-Internal functions (complete set)
-
-.fn.select: A pool method of the following type is called to invoke the 
-SelectFrame operation:
-       typedef Res (*PoolFrameSelectMethod)(Pool pool, Buffer buf,
-                                            AllocFrame frame);
-
-.fn.select-addr: A pool method of the following type is called to invoke the 
-SelectFrameOfAddr operation:
-       typedef Res (*PoolFrameSelectFromAddrMethod)(Pool pool, Buffer buf,
-                                                    Addr addr);
-
-.fn.in-frame: A pool method of the following type is called to invoke the 
-AddrInFrame operation:
-       typedef Res (*PoolAddrInFrameMethod)(Bool *inframeReturn, 
-                                            Pool pool, Seg seg, Addr *addrref, 
-                                            AllocFrame frame);
-
-.fn.set: A pool method of the following type is called to invoke the 
-SetFrameClass operation:
-       typedef Res (*PoolSetFrameClassMethod)(Pool pool, Buffer buf, 
-                                              AllocFrameClass class);
-
-
-LIGHTWEIGHT FRAMES 
-
-Overview
-
-.lw-frame.overview: Allocation points provide direct support for lightweight 
-frames, and are designed to permit PushFrame and PopFrame operations without 
-the need for locking and delegation to the pool method.  Pools can disable this 
-mechanism for any allocation point, so that the pool method is always called.  
-The pool method will be called whenever synchronization is required for other 
-reasons (e.g. the buffer is tripped).
-
-.lw-frame.model: Lightweight frames offer direct support for a particular model 
-of allocation frame use, whereby the PushFrame operation returns the current 
-allocation pointer as a frame handle, and the PopFrame operation causes the 
-allocation pointer to be reset to the address of the frame handle.  This model 
-should be suitable for simple stack frames, where more advanced operations like 
-SelectFrame are not supported.  It may also be suitable for more advanced 
-allocation frame models when they are being used simply.  The use of a complex 
-operation always involves synchronization via locking, and the pool may disable 
-lightweight synchronization temporarily at this time.
-
-State
-
-.lw-frame.states: Allocation points supporting lightweight frames will be in 
-one of the following states:-
-Valid:        Indicates that PushFrame can be a lightweight operation and need 
-not be synchronized
-PopPending:   Indicates that there has been a PopFrame operation that the pool 
-must respond to
-Disabled:     Indicates that the pool has disabled support for lightweight 
-operations for this AP
-These states are in addition to the state normally held by an AP for allocation 
-purposes. An AP will be in the Disabled state at creation.
-
-.lw-frame.transitions: State transitions happen under the following 
-circumstances:-
-Valid -> PopPending    :  As a result of a client PopFrame operation
-Valid -> Disabled      :  At the choice of the pool (e.g. when responding to a 
-SelectFrame operation)
-PopPending -> Valid    :  At the choice of the pool, when processing a PopFrame
-PopPending -> Disabled :  At the choice of the pool, when processing a PopFrame
-Disabled -> Valid      :  At the choice of the pool
-Disabled -> Popframe   :  Illegal
-
-.lw-frame.state-impl: Each AP contains 3 additional fields to hold this state:
-
-  mps_addr_t frameptr; 
-  mps_bool_t enabled; 
-  mps_bool_t lwPopPending;
-
-.lw-frame.enabled: The enabled slot holds the following values for each state:
-Valid:      TRUE
-PopPending: TRUE
-Disabled:   FALSE
-
-.lw-frame.frameptr: The frameptr slot holds the following values for each state:
-
-Valid:      NULL
-PopPending: Frame handle for most recently popped frame.
-Disabled:   NULL
-
-.lw-frame.lwPopPending: The lwPopPending slot holds the following values for 
-each state:
-
-Valid:      FALSE
-PopPending: TRUE
-Disabled:   FALSE
-
-
-.lw-frame.state-for-gc: It is not necessary for the tracer, format code, pool, 
-or any other part of the GC support in MPS to read either of the 2 additional 
-AP fields in order to scan a segment which supports a lightweight allocation 
-frame.
-
-
-Synchronization
-
-.lw-frame.sync: The purpose of the design is that mutator may access the state 
-of an AP without locking with MPS (via the external functions).  The design 
-assumes the normal MPS restriction that an operation on an AP may only be 
-performed by a single mutator thread at a time.  Each of the operations on 
-allocation frames counts as an operation on an AP.
-
-.lw-frame.sync.pool: Pools are permitted to read or modify the lightweight 
-frame state of an AP only in response to an operation on that AP.
-
-.lw-frame.sync.external: The external functions mps_ap_frame_push and 
-mps_ap_frame_pop are permitted to read the values of the enabled and frameptr 
-fields for the supplied AP without claiming the arena lock.  They are permitted 
-to modify the frameptr field iff enabled == FALSE.
-
-.lw-frame.sync.trip: When a buffer trip happens, and the trap wasn't set by MPS 
-itself (i.e. it wasn't because of a flip or for logging), then the buffer code 
-must check whether the AP has state PopPending.  If it does, the buffer code 
-must call the Pool.
-
-
-Implementation
-
-.lw-frame.push: The external PushFrame operation (mps_ap_frame_push) performs 
-the following operations:
-   IF (!APIsTrapped(ap) && StateOfFrame(ap) == Valid && ap->init == ap->alloc)
-      *frame_o = ap->init;
-   ELSE
-     WITH_ARENA_LOCK
-       PerformInternalPushFrameOperation(...)
-     END
-   END
-
-
-.lw-frame.pop: The external PopFrame operation (mps_ap_frame_pop) performs the 
-following operations:
-   IF (StateOfFrame(ap) != Disabled)
-     TrapAP(ap);  /* ensure next allocation or push involves the pool */
-     ap->frameptr = frame;
-     ap->lwpopPending = TRUE;
-   ELSE
-     WITH_ARENA_LOCK
-       PerformInternalPopFrameOperation(...)
-     END
-   END
-
- - -

A. References

- - - - -

B. Document History

- -
- - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1997-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/arena/index.html b/mps/design/arena/index.html deleted file mode 100644 index 69541f3a71c..00000000000 --- a/mps/design/arena/index.html +++ /dev/null @@ -1,559 +0,0 @@ - - - - - - - - -The design of the MPS arena - - - - - - - -
-                      THE DESIGN OF THE MPS ARENA
-                            design.mps.arena
-                           incomplete design
-                            pekka 1997-08-11
-
-INTRODUCTION
-
-
-.intro: This is the design of the arena structure.
-
-.readership: MM developers.
-
-
-Document History
-
-.hist.0: Version 0 is a different document.
-
-.hist.1: First draft written by Pekka P. Pirinen 1997-08-11, based on 
-design.mps.space(0) and mail.richard.1997-04-25.11-52(0).
-
-.hist.2: Updated for separation of tracts and segments.  tony 1999-04-16
-
-
-OVERVIEW
-
-.overview: The arena serves two purposes: A structure that is the top-level 
-state of the MPS, and as such contains a lot of fields which are considered 
-"global"; Provision of raw memory to pools.
-
-An arena is of a particular arena class, the class is selected when the arena 
-is created.  Classes encapsulate both policy (such as how pools placement 
-preferences map into actual placement) and mechanism (such as where the memory 
-originates: OS VM, client provided, via malloc).  Some behaviour (most in the 
-former "top-level datastructure" category) is implemented by generic arena 
-code, some by arena class code.  To some extent the arena coordinates placement 
-policies between different pools active in the same arena, however this 
-functionality is likely to be replaced by something more modular and which does 
-a better job: The Locus Manager.
-
-
-DEFINITIONS
-
-.def.tract: Pools request memory from the arena (using ArenaAlloc) as a block 
-comprising a contiguous sequence of units.  The units are known as tracts.  A 
-tract has a specific size (the arena alignment, often corresponds to the OS 
-page size) and all tracts are aligned to that size.  Also used to mean the 
-datastructure used to manage tracts.
-
-
-REQUIREMENTS
-
-[copied from design.mps.arena.vm(1) and edited slightly -- drj 1999-06-23]
-
-[Where do these come from?  Need to identify and document the sources of 
-requirements so that they are traceable to client requirements.  Most of these 
-come from the architectural design (design.mps.architecture) or the fix 
-function design (design.mps.fix). -- richard 1995-08-28]
-
-These requirements are the responsibility of the class implementations as well 
-as the generic arena.  However, some classes (ANSI arena, arenaan.c, in 
-particular) are not intended for production use so do not have to meet all the 
-speed and space requirements.
-
-
-Block Management
-
-.req.fun.block.alloc: The Arena Manager must provide allocation of contiguous 
-blocks of memory.
-
-.req.fun.block.free: It must also provide freeing of contiguously allocated 
-blocks owned by a pool - whether or not the block was allocated via a single 
-request.
-
-.req.attr.block.size.min: The Arena Manager must support management of blocks 
-down to the size of the grain (page) provided by the virtual mapping interface 
-if a VM interface is being used, a comparable size otherwise.
-
-.req.attr.block.size.max: It must also support management of blocks up to the 
-maximum size allowed by the combination of operating system and architecture.  
-This is derived from req.dylan.attr.obj.max (at least).
-
-.req.attr.block.align.min: The alignment of blocks shall not be less than 
-MPS_PF_ALIGN (defined in "mpstd.h" included via "config.h") for the 
-architecture.  This is so that pool classes can conveniently guarantee pool 
-allocated blocks are aligned to MPS_PF_ALIGN.  (A trivial requirement)
-
-.req.attr.block.grain.max: The granularity of allocation shall not be more than 
-the grain size provided by the virtual mapping interface.
-
-
-Address Translation
-
-.req.fun.trans: The Arena must provide a translation from any address to either 
-an indication that the address is not in any tract (if that is so) or the 
-following data associated with the tract containing that address:
-.req.fun.trans.pool: The pool that allocated the tract.
-.req.fun.trans.arbitrary: An arbitrary pointer value that the pool can 
-associate with the tract at any time.
-.req.fun.trans.white: The tracer whiteness information.  IE a bit for each 
-active trace that indicates whether this tract is white (contains white 
-objects).  This is required so that the tracer resolve / preserve (aka "Fix") 
-protocol can run very quickly.
-
-.req.attr.trans.time: The translation shall take no more than @@@@ [something 
-not very large -- drj 1999-06-23]
-
-Iteration Protocol
-
-.req.iter: er, there's a tract iteration protocol which is presumably required 
-for some reason?
-
-
-Arena Partition
-
-.req.fun.set: The Arena Manager must provide a method for approximating sets of 
-addresses.  .req.fun.set.time: The determination of membership shall take no 
-more than ???? [something very small indeed].  (the non-obvious solution is 
-refsets)
-
-
-Constraints
-
-.req.attr.space.overhead: req.dylan.attr.space.struct implies that the arena 
-must limit the space overhead.  The arena is not the only part that introduces 
-an overhead (pool classes being the next most obvious), so multiple parts must 
-cooperate in order to meet the ultimate requirements.
-.req.attr.time.overhead: Time overhead constraint? [how can there be a time 
-"overhead" on a necessary component?  drj 1999-06-23]
-
-
-
-ARCHITECTURE
-
-Statics
-
-.static: There is no higher-level data structure than a arena, so in order to 
-support several arenas, we have to have some static data in impl.c.arena.  See 
-impl.c.arena.static.
-
-.static.init: All the static data items are initialized when the first arena is 
-created.
-
-.static.serial: arenaSerial is a static Serial, containing the serial number of 
-the next arena to be created. The serial of any existing arena is less than 
-this.
-
-.static.ring: arenaRing is the sentinel of the ring of arenas.
-
-.static.ring.init: arenaRingInit is a bool showing whether the ring of arenas 
-has been initialized. 
-
-.static.ring.lock: The ring of arenas has to be locked when traversing the 
-ring, to prevent arenas being added or removed. This is achieved by using the 
-(non-recursive) global lock facility, provided by the lock module.
-
-.static.check: The statics are checked each time any arena is checked.
-
-
-Arena Classes
-
-.class: The Arena datastructure is designed to be subclassable (see 
-design.mps.protocol(0)). Clients can select what arena class they'd like when 
-instantiating one with mps_arena_create().  The arguments to mps_arena_create 
-are class dependent.
-
-.class.init: However, the generic ArenaInit is called from the class-specific 
-method, rather than vice versa, because the method is responsible for 
-allocating the memory for the arena descriptor and the arena lock in the first 
-place.  Likewise, ArenaFinish is called from the finish method.
-
-.class.fields: The alignment (for tract allocations) and zoneShift (for 
-computing zone sizes and what zone an address is in) fields in the arena are 
-the responsibility of the each class, and are initialized by the init method.  
-The responsibility for maintaining the commitLimit, spareCommitted, 
-spareCommitLimit fields is shared between the (generic) arena and the arena 
-class.  commitLimit (see .commit-limit below) is changed by the generic arena 
-code, but arena classes are responsible for ensuring the semantics.  For 
-spareCommitted and spareCommitLimit see .spare-committed below.
-
-.class.abstract: The basic arena class (AbstractArenaClass) is abstract and 
-must not be instantiated. It provides little useful behaviour, and exists 
-primarily as the root of the tree of arena classes. Each concrete class must 
-specialize each of the class method fields, with the exception of the describe 
-method (which has a trivial implementation) and the extend, retract and 
-spareCommitExceeded methods which have non-callable methods for the benefit of 
-arena classes which don't implement these features. .class.abstract.null: The 
-abstract class does not provide dummy implementations of those methods which 
-must be overridden. Instead each abstract method is initialized to NULL.
-
-
-Tracts
-
-.tract: The arena allocation function (ArenaAlloc) allocates a block of memory 
-to pools, of a size which is aligned to the arena alignment. Each alignment 
-unit (grain) of allocation is represented by an object called a Tract. Tracts 
-are the hook on which the segment module is implemented. Pools which don't use 
-segments may use tracts for associating their own data with each allocation 
-grain.
-
-.tract.structure: The tract structure definition looks as follows:-
-
-typedef struct TractStruct { /* Tract structure */
-  Pool pool;   /* MUST BE FIRST (design.mps.arena.tract.field.pool) */
-  void *p;                    /* pointer for use of owning pool */
-  Addr base;                  /* Base address of the tract */
-  TraceSet white : TRACE_MAX; /* traces for which tract is white */
-  unsigned int hasSeg : 1;    /* does tract have a seg in p?  */
-} TractStruct;
-
-.tract.field.pool: The pool field indicates to which pool the tract has been 
-allocated (.req.fun.trans.pool). Tracts are only valid when they are allocated 
-to pools. When tracts are not allocated to pools, arena classes are free to 
-reuse tract objects in undefined ways. A standard technique is for arena class 
-implementations to internally describe the objects as a union type of 
-TractStruct and some private representation, and to set the pool field to NULL 
-when the tract is not allocated. The pool field must come first so that the 
-private representation can share a common prefix with TractStruct. This permits 
-arena classes to determine from their private representation whether such an 
-object is allocated or not, without requiring an extra field.
-
-.tract.field.p: The p field is used by pools to associate tracts with other 
-data (.req.fun.trans.arbitrary). It's used by the segment module to indicate 
-which segment a tract belongs to.  If a pool doesn't use segments it may use 
-the p field for its own purposes. This field has the non-specific type (void *) 
-so that pools can use it for any purpose.
-
-.tract.field.hasSeg: The hasSeg bit-field is a boolean which indicates whether 
-the p field is being used by the segment module. If this field is TRUE, then 
-the value of p is a Seg. hasSeg is typed as an unsigned int, rather than a 
-Bool. This ensures that there won't be sign conversion problems when converting 
-the bit-field value. 
-
-.tract.field.base: The base field contains the base address of the memory 
-represented by the tract.
-
-.tract.field.white: The white bit-field indicates for which traces the tract is 
-white (.req.fun.trans.white). This information is also stored in the segment, 
-but is duplicated here for efficiency during a call to TraceFix (see 
-design.mps.trace.fix).
-
-.tract.limit: The limit of the tract's memory may be determined by adding the 
-arena alignment to the base address.
-
-.tract.iteration: Iteration over tracts is described in 
-design.mps.arena.tract-iter(0).
-
-.tract.if.tractofaddr: Function TractOfAddr finds the tract corresponding to an 
-address in memory. (.req.fun.trans).
-
-Bool TractOfAddr(Tract *tractReturn, Arena arena, Addr addr);
-
-If addr is an address which has been allocated to some pool, then returns TRUE, 
-and sets *tractReturn to the tract corresponding to that address. Otherwise, 
-returns false.  This function is similar to TractOfBaseAddr (see 
-design.mps.arena.tract-iter.if.contig-base) but serves a more general purpose 
-and is less efficient. 
-
-.tract.if.TRACT_OF_ADDR: TRACT_OF_ADDR is a macro version of TractOfAddr. It's 
-provided for efficiency during a call to TraceFix (see 
-design.mps.trace.fix.tractofaddr)
-
-
-Control Pool
-
-.pool: Each arena has a "control pool", arena->controlPoolStruct, which is used 
-for allocating MPS control data structures (using ControlAlloc()).
-
-
-Polling
-
-.poll: ArenaPoll is called "often" by other MM code (for instance, on buffer 
-fill or allocation).  It is the entry point for doing tracing work.  If the 
-polling clock exceeds a set threshold, and we're not already doing some tracing 
-work (i.e., insidePoll is not set), it calls TracePoll on all busy traces.  
-.poll.size: The actual clock is arena->fillMutatorSize.  This is because 
-internal allocation is only significant when copy segments are being allocated, 
-and we don't want to have the pause times to shrink because of that.  (There is 
-no current requirement for the trace rate to guard against running out of 
-memory. [clearly it really ought to though, we have a requirement to not run 
-out of memory (req.dylan.prot.fail-alloc, req.dylan.prot.consult), emergency 
-tracing should not be our only story.  drj 1999-06-22])  BufferEmpty is not 
-taken into account, because the splinter will rarely be useable for allocation 
-and we are wary of the clock running backward.
-
-.poll.clamp: Polling is disabled when the arena is "clamped", in which case 
-arena->clamped is TRUE.  Clamping the arena prevents background tracing work, 
-and further new garbage collections from starting.  Clamping and releasing are 
-implemented by the ArenaClamp and ArenaRelease methods.
-
-.poll.park: The arena is "parked" by clamping it, then polling until there are 
-no active traces.  This finishes all the active collections and prevents 
-further collection.  Parking is implemented by the ArenaPark method.
-
-
-Commit Limit
-
-.commit-limit: The arena supports a client configurable "commit limit" which is 
-a limit on the total amount of committed memory.  The generic arena structure 
-contains a field to hold the value of the commit limit and the implementation 
-provides two functions for manipulating it (ArenaCommitLimit to read it and 
-ArenaSetCommitLimit to set it).  Actually abiding by the contract of not 
-committing more memory than the commit limit is left up to the individual arena 
-classes.
-
-.commit-limit.err: When allocation from the arena would otherwise succeed but 
-cause the MPS to use more committed memory than specified by the commit limit 
-ArenaAlloc should refuse the request and return ResCOMMIT_LIMIT.  
-.commit-limit.err.multi: In the case where an ArenaAlloc request cannot be 
-fulfilled for more than one reason including exceeding the commit limit then 
-class implementations should strive to return a result code other than 
-ResCOMMIT_LIMIT (ie ResCOMMIT_LIMIT should only be returned if the _only_ 
-reason for failing the ArenaAlloc request is that the commit limit would be 
-exceeded).  The (client) documentation allows implementations to be ambiguous 
-with respect to which result code in returned in such a situation however.
-
-
-Spare Committed (aka "hysteresis")
-
-.spare-committed: (See symbol.mps.c.mps_arena_spare_committed(0))  The generic 
-arena structure contains two fields for the spare committed memory fund: 
-spareCommitted records the total number of spare committed bytes; 
-spareCommitLimit records the limit (set by the user) on the amount of spare 
-committed memory.  spareCommitted is modified by the arena class but its value 
-is used by the generic arena code.  There are two uses: a getter function for 
-this value is provided through the MPS interface 
-(mps_arena_spare_commit_limit_set), and by the SetSpareCommitLimit function to 
-determine whether the amount of spare committed memory needs to be reduced.  
-spareCommitLimit is manipulated by generic arena code, however the associated 
-semantics are the responsibility of the class.  It is the class's responsibility 
-to ensure that it doesn't use more spare committed bytes than the value in 
-spareCommitLimit.
-
-.spare-commit-limit: The function ArenaSetSpareCommitLimit sets the 
-spareCommitLimit field.  If the limit is set to a value lower than the amount 
-of spare committed memory (stored in spareCommitted) then the class specific 
-function spareCommitExceeded is called.
-
-
-Locks
-
-.lock.ring: ArenaAccess is called when we fault on a barrier.  The first thing 
-it does is claim the non-recursive global lock to protect the arena ring (see 
-design.mps.lock(0)).  .lock.arena: After the arena ring lock is claimed, 
-ArenaEnter is called on one or more arenas.  This claims the lock for that 
-arena.  When the correct arena is identified or we run out of arenas, the lock 
-on the ring is released.
-
-.lock.avoid: Deadlocking is avoided as follows:
-
-.lock.avoid.mps: Firstly we require the MPS not to fault (i.e., when any of 
-these locks are held by a thread, that thread does not fault).
-
-.lock.avoid.thread: Secondly, we require that in a multi-threaded system, 
-memory fault handlers do not suspend threads (although the faulting thread 
-will, of course, wait for the fault handler to finish).
-
-.lock.avoid.conflict: Thirdly, we avoid conflicting deadlock between the arena 
-and global locks by ensuring we never claim the arena lock when the recursive 
-global lock is already held, and we never claim the binary global lock when the 
-arena lock is held. 
-
-
-Location Dependencies
-
-.ld: Location dependencies use fields in the arena to maintain a history of 
-summaries of moved objects, and to keep a notion of time, so that the staleness 
-of location dependency can be determined.
-
-
-Finalization
-
-.final: There is a pool which is optionally (and dynamically) instantiated to 
-implement finalization.  The fields finalPool and isFinalPool are used.
-
-
-IMPLEMENTATION
-
-
-Tract Cache
-
-.tract.cache: When tracts are allocated to pools (by ArenaAlloc), the first 
-tract of the block and it's base address are cached in arena fields lastTract 
-and lastTractBase. The function TractOfBaseAddr (see 
-design.mps.arena.tract-iter.if.block-base(0)) checks against these cached 
-values and only calls the class method on a cache miss. This optimizes for the 
-common case where a pool allocates a block and then iterates over all its 
-tracts (e.g. to attach them to a segment).
-
-.tract.uncache: When blocks of memory are freed by pools, ArenaFree checks to 
-see if the cached value for the most recently allocated tract (see 
-.tract.cache) is being freed. If so, the cache is invalid, and must be reset. 
-The lastTract and lastTractBase fields are set to NULL.
-
-
-Control Pool
-
-.pool.init: The control pool is initialized by a call to PoolInit() during 
-ArenaCreate().
-
-.pool.ready: All the other fields in the arena are made checkable before 
-calling PoolInit(), so PoolInit can call ArenaCheck(arena).  The pool itself 
-is, of course, not checkable, so we have a field arena->poolReady, which is 
-false until after the return from PoolInit.  ArenaCheck only checks the pool 
-if(poolReady).
-
-
-Traces
-
-.trace: arena->trace[ti] is valid if and only if 
-TraceSetIsMember(arena->busyTraces, ti).
-
-.trace.create: Since the arena created by ArenaCreate has arena->busyTraces = 
-TraceSetEMPTY, none of the traces are meaningful.
-
-.trace.invalid: Invalid traces have signature SigInvalid, which can be checked.
-
-
-Polling
-
-.poll.fields: There are three fields of a arena used for polling: 
-pollThreshold, insidePoll, and clamped (see above).  pollThreshold is the 
-threshold for the next poll: it is set at the end of ArenaPoll to the current 
-polling time plus ARENA_POLL_MAX.
-
-
-Location Dependencies
-
-.ld.epoch: arena->epoch is the "current epoch".  This is the number of 'flips' 
-of traces in the arena since the arena was created.  From the mutator's point 
-of view locations change atomically at flip.
-
-.ld.history: arena->history is an array of ARENA_LD_LENGTH RefSets.  These are 
-the summaries of moved objects since the last ARENA_LD_LENGTH epochs.  If e is 
-one of these recent epochs, arena->history[e % ARENA_LD_LENGTH] is a summary of 
-(the original locations of) objects moved since epoch e.
-
-.ld.prehistory: arena->prehistory is a RefSet summarizing the original 
-locations of all objects ever moved.  When considering whether a really old 
-location dependency is stale, it is compared with this summary.
-
-
-Roots
-
-.root-ring: The arena holds a member of a ring of roots in the arena.  It holds 
-an incremental serial which is the serial of the next root.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/arenavm/index.html b/mps/design/arenavm/index.html deleted file mode 100644 index ce904517723..00000000000 --- a/mps/design/arenavm/index.html +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - - - -Virtual memory arena - - - - - - - -
-                          VIRTUAL MEMORY ARENA
-                          design.mps.arena.vm
-                             incomplete doc
-                             drj 1996-07-16
-
-INTRODUCTION
-
-.intro: This document describes the detailed design of the Virtual Memory Arena 
-Class of the Memory Pool System.  The VM Arena Class is just one class 
-available in the MPS.  The generic arena part is described in design.mps.arena.
-
-
-OVERVIEW
-
-.overview: VM arenas provide blocks of memory to all other parts of the MPS in 
-the form of "tracts" using the virtual mapping interface (design.mps.vm) to the 
-operating system.  The VM Arena Class is not expected to be provided on 
-platforms that do not have virtual memory (like MacOS, os.s7(1)).
-
-.overview.gc: The VM Arena Class provides some special services on these blocks 
-in order to facilitate garbage collection:
-
-.overview.gc.zone: Allocation of blocks with specific zones.  This means that 
-the generic fix function (design.mps.fix) can use a fast refset test to 
-eliminate references to addresses that are not in the condemned set.  This 
-assumes that a pool class that uses this placement appropriately is being used 
-(such as the generation placement policy used by AMC, see design.mps.poolamc(1)
-) and that the pool selects the condemned sets to coincide with zone stripes.
-
-.overview.gc.tract: A fast translation from addresses to tract. (See 
-design.mps.arena.req.fun.trans)
-
-
-NOTES
-
-.note.refset: Some of this document simply assumes that RefSets (see the 
-horribly incomplete design.mps.refset) have been chosen as the solution for 
-design.mps.arena.req.fun.set.  It's a lot simpler that way.  Both to write and 
-understand.
-
-
-REQUIREMENTS
-
-
-Most of the requirements are in fact on the generic arena (See design.mps.arena
-.req.*).  However, many of those requirements can only be met by a suitable 
-arena class design.
-
-Requirements particular to this arena class:
-
-Placement
-
-.req.fun.place: It must be possible for pools to obtain tracts at particular 
-addresses.  Such addresses shall be declared by the pool specifying what refset 
-zones the tracts should lie in and what refset zones the tracts should not lie 
-in.  It is acceptable for the arena to not always honour the request in terms 
-of placement if it has run out of suitable addresses.
-
-Arena Partition
-
-.req.fun.set: See design.mps.arena.req.fun.set.  The approximation to sets of 
-address must cooperate with the placement mechanism in the way required by 
-.req.fun.place (above).
-
-
-ARCHITECTURE
-
-.arch.memory: The underlying memory is obtained from whatever Virtual Memory 
-interface (see design.mps.vm).  Explain why this is used ###
-
-
-SOLUTION IDEAS
-
-.idea.grain: Set the arena granularity to the grain provided by the virtual 
-mapping module.
-
-.idea.mem: Get a single large contiguous address area from the virtual mapping 
-interface and divide that up.
-
-.idea.table: Maintain a table with one entry per grain in order to provide fast 
-mapping (shift and add) between addresses and table entries.
-
-.idea.table.figure:
-  
-
-.idea.map: Store the pointers (.req.fun.trans) in the table directly for every 
-grain.
-
-.idea.zones: Partition the managed address space into zones (see idea.zones) 
-and provide the set approximation as a reference signature.
-
-.idea.first-fit: Use a simple first-fit allocation policy for tracts within 
-each zone (.idea.zones).  Store the freelist in the table (.idea.table).
-
-.idea.base: Store information about each contiguous area (allocated of free) in 
-the table entry (.idea.table) corresponding to the base address of the area.
-
-.idea.shadow: Use the table (.idea.table) as a "shadow" of the operating 
-system's page table.  Keep information such as last access, protection, etc. in 
-this table, since we can't get at this information otherwise.
-
-.idea.barrier: Use the table (.idea.table) to implement the software barrier.  
-Each segment can have a read and/or write barrier placed on it by each 
-process.  (.idea.barrier.bits: Store a bit-pattern which remembers which 
-process protected what.)  This will give a fast translation from a 
-barrier-protected address to the barrier handler via the process table.
-
-.idea.demand-table: For a 1Gb managed address space with a 4Kb page size, the 
-table will have 256K-entries.  At (say) four words per entry, this is 4Mb of 
-table.  Although this is only an 0.4%, the table shouldn't be preallocated or 
-initially it is an infinite overhead, and with 1Mb active, it is a 300% 
-overhead!  The address space for the table should be reserved, but the pages 
-for it mapped and unmapped on demand.  By storing the table in a tract, the 
-status of the table's pages can be determined by looking at it's own entries in 
-itself, and thus the translation lookup (.req.fun.trans) is slowed to two 
-lookups rather than one.
-
-.idea.pool: Make the Arena Manager a pool class.  Arena initialization becomes 
-pool creation.  Tract allocation becomes PoolAlloc.  Other operations become 
-class-specific operations on the "arena pool".
-
-
-DATA STRUCTURES
-
-.tables: There are two table data structures: a page table, and an alloc table.
-
-.table.page.map: Each page in the VM has a corresponding page table entry.
-
-.table.page.linear: The table is a linear array of PageStruct entries; there is 
-a simple mapping between the index in the table and the base address in the VM 
-(viz. base-address = arena-base + (index * page-size), one way, index = 
-(base-address - arena-base) / page-size, the other).
-
-.table.page.partial: The table is partially mapped on an "as-needed" basis.  
-The function unusedTablePages identifies entirely unused pages occupied by the 
-page table itself (ie those pages of the page table which are occupied by 
-PageStructs which all describe free pages).  Tract allocation and freeing use 
-this function to map and unmap the page table with no hysteresis.  (there is 
-restriction on the parameters you may pass to unusedTablePages)
-
-.table.page.tract: Each page table entry contains a tract, which is only valid 
-if it is allocated to a pool. If it is not allocated to a pool, the fields of 
-the tract are used for other purposes. (See design.mps.arena.tract.field.pool)
-
-.table.alloc: The alloc table is a simple bit table (implemented using the BT 
-module, design.mps.bt).
-
-.table.alloc.map: Each page in the VM has a corresponding alloc table entry.
-
-.table.alloc.semantics: The bit in the alloc table is set iff the corresponding 
-page is allocated (to a pool).  
-
-
-
-NOTES
-
-
-.fig.page: How the pages in the arena area are represented in the tables.
-
-.fig.count: How a count table can be used to partially map the page table, as 
-proposed in request.dylan.170049.sol.map.
-
- - arenavm diagrams 
-
-ATTACHMENT
-   "arenavm diagrams"
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/bt/index.html b/mps/design/bt/index.html deleted file mode 100644 index 8bb960c1b87..00000000000 --- a/mps/design/bt/index.html +++ /dev/null @@ -1,723 +0,0 @@ - - - - - - - - -Bit tables - - - - - - - -
-                               BIT TABLES
-                             design.mps.bt
-                               draft doc
-                             drj 1997-03-04
-
-INTRODUCTION
-
-.readership: Any MPS developer.
-
-.intro: This is the design of the Bit Tables module.  A Bit Table is a linear 
-array of bits.  A Bit Table of length n is indexed using an integer from 0 to 
-(but not including) n.  Each bit in a Bit Table can hold either the value 0 
-(aka FALSE) or 1 (aka TRUE).  A variety of operations are provided including: 
-set, reset, and retrieve, individual bits; set and reset a contiguous range of 
-bits; search for a contiguous range of reset bits; making a "negative image" 
-copy of a range.
-
-
-HISTORY
-
-.history.0-3: The history for versions 0-3 is lost pending possible 
-reconstruction.
-
-.history.4: Prepared for review.  Added full requirements section.  Made 
-notation more consistent throughout.  Documented all functions.  drj 1999-04-29
-
-
-DEFINITIONS
-
-.def.set: Set.  Used as a verb meaning to assign the value 1 or TRUE to a bit.  
-Used descriptively to denote a bit containing the value 1.  Note 1 and TRUE are 
-synonyms in MPS C code (see design.mps.type(0).bool.value).
-
-.def.reset: Reset.  Used as a verb meaning to assign the value 0 or FALSE to a 
-bit.  Used descriptively to denote a bit containing the value 0.  Note 0 and 
-FALSE are synonyms in MPS C code (see design.mps.type(0).bool.value).
-
-[consider using "fill/empty" or "mark/clear" instead of "set/reset", set/reset 
-is probably a hangover from drj's z80 hacking days -- drj 1999-04-26]
-
-.def.bt: Bit Table.  A Bit Table is a mapping from [0,n) to {0,1} for some n 
-represented as a linear array of bits.  .def.bt.justify: They are called bit 
-tables because a single bit is used to encode whether the image of a particular 
-integer under the map is 0 or 1.
-
-.def.range: Range.  A contiguous sequence of bits in a Bit Table.  Ranges are 
-typically specified as a base--limit pair where the range includes the position 
-specified by the base, but excludes that specified by the limit.  The 
-mathematical interval notation for half-open intervals, [base, limit), is used.
-
-
-REQUIREMENTS
-
-.req.bit: The storage for a Bit Table of n bits shall take no more than a small 
-constant addition to the storage required for n bits.  .req.bit.why: This is so 
-that clients can make some predictions about how much storage their algorithms 
-use.  A small constant is allowed over the minimal for two reasons: inevitable 
-implementation overheads (such as only being able to allocate storage in 
-multiples of 32 bits), extra storage for robustness or speed (such as signature 
-and length fields).
-.req.create: A means to create Bit Tables.  .req.create.why: Obvious.
-.req.destroy: A means to destroy Bit Tables.  .req.destroy.why: Obvious.
-.req.ops: The following operations shall be supported:
-  .req.ops.get: Get.  Get the value of a bit at a specified index.
-  .req.ops.set: Set.  Set a bit at a specified index.
-  .req.ops.reset: Reset.  Reset a bit at a specified index.
-  .req.ops.minimal.why: Get, Set, Reset, are the minimal operations.  All 
-possible mappings can be created and inspected using these operations.
-  .req.ops.set.range: SetRange.  Set a range of bits.  .req.ops.set.range.why: 
-It's expected that clients will often want to set a range of bits; providing 
-this operation allows the implementation of the BT module to make the operation 
-efficient.
-  .req.ops.reset.range: ResetRange.  Reset a range of bits.  
-.req.ops.reset.range.why: as for SetRange, see .req.ops.set.range.why.
-  .req.ops.test.range.set: IsSetRange.  Test whether a range of bits are all 
-set.  .req.ops.test.range.set.why: Mostly for checking.  For example, often 
-clients will know that a range they are about to reset is currently all set, 
-they can use this operation to assert that fact.
-  .req.ops.test.range.reset: IsResetRange.  Test whether a range of bits are 
-all reset.  .req.ops.test.range.reset.why: As for IsSetRange, see 
-.req.ops.test.range.set.why.
-  .req.ops.find: Find a range (which we'll denote [i,j)) of at least L reset 
-bits that lies in a specified subrange of the entire Bit Table.  Various find 
-operations are required according to the (additional) properties of the 
-required range:
-    .req.ops.find.short.low: FindShortResetRange.  Of all candidate ranges, 
-find the range with least j (find the leftmost range that has at least L reset 
-bits and return just enough of that).  .req.ops.find.short.low.why: Required by 
-client and VM arenas to allocate segments.  The arenas implement definite 
-placement policies (such as lowest addressed segment first) so they need the 
-lowest (or highest) range that will do.  It's not currently useful to allocate 
-segments larger than the requested size, so finding a short range is 
-sufficient.  
-    .req.ops.find.short.high: FindShortResetRangeHigh.  Of all candidate 
-ranges, find the range with greatest i (find the rightmost range that has at 
-least L reset bits and return just enough of that).  
-.req.ops.find.short.high.why: Required by arenas to implement a specific 
-segment placement policy (highest addressed segment first).
-    .req.ops.find.long.low: FindLongResetRange.  Of all candidate ranges, 
-identify the ranges with least i and of those find the one with greatest j 
-(find the leftmost range that has at least L reset bits and return all of it).  
-.req.ops.find.long.low.why: Required by the mark and sweep Pool Classes (AMS, 
-AWL, LO) for allocating objects (filling a buffer).  It's more efficient to 
-fill a buffer with as much memory as is conveniently possible.  There's no 
-strong reason to find the lowest range but it's bound to have some beneficial 
-(small) cache effect and makes the algorithm more predictable.
-    .req.ops.find.long.high: FindLongResetRangeHigh.  Provided, but not 
-required, see .non-req.ops.find.long.high.
-  .req.ops.copy: Copy a range of bits from one Bit Table to another Bit Table . 
-Various copy operations are required:
-    .req.ops.copy.simple: Copy a range of bits from one Bit Table to the same 
-position in another Bit Table.  .req.ops.copy.why: Required to support copying 
-of the tables for the "low" segment during segment merging and splitting, for 
-pools using tables (e.g. PoolClassAMS).
-    .req.ops.copy.offset: Copy a range of bits from one Bit Table to an offset 
-position in another Bit Table.  .req.ops.copy.why: Required to support copying 
-of the tables for the "high" segment during segment merging and splitting, for 
-pools which support this (currently none, as of 2000-01-17).
-    .req.ops.copy.invert: Copy a range of bits from one Bit Table to the same 
-position in another Bit Table inverting all the bits in the target copy.  
-.req.ops.copy.invert.why: Required by colour manipulation code in PoolClassAMS 
-and PoolClassLO.
-.req.speed: Operations shall take no more than a few memory operations per bit 
-manipulated.  .req.speed.why: Any slower would be gratuitous.
-.req.speed.fast: The following operations shall be very fast:
-
-.req.speed.fast.find.short: 
-FindShortResRange (the operation used to meet .req.ops.find.short.low)
-FindShortResRangeHigh (the operation used to meet .req.ops.find.short.high)
-
-.req.speed.fast.find.short.why: These two are used by the client arena 
-(design.mps.arena.client) and the VM arena (design.mps.arena.vm) for finding 
-segments in page tables.  The operation will be used sufficiently often that 
-its speed will noticeably affect the overall speed of the MPS.  They will be 
-called with a length equal to the number of pages in a segment.  Typical values 
-of this length depend on the pool classes used and their configuration, but we 
-can expect length to be small (1 to 16) usually.  We can expect the Bit Table 
-to be populated densely where it is populated at all, that is set bits will 
-tend to be clustered together in subranges.
-
-.req.speed.fast.find.long:
-FindLongResRange (the operation used to meet .req.ops.find.long.low)
-
-.req.speed.fast.find.long.why:
-Used in the allocator for PoolClassAWL (design.mps.poolawl(1)), PoolClassAMS 
-(design.mps.poolams(2)), PoolClassEPVM (design.mps.poolepvm(0)).  Of these AWL 
-and EPVM have speed requirements.  For AWL the length of range to be found will 
-be the length of a Dylan table in words.  According to 
-mail.tony.1999-05-05.11-36(0), only <entry-vector> objects are allocated in AWL 
-(though not all <entry-vector> objects are allocated in AWL), and the mean 
-length of an <entry-vector> object is 486 Words.  No data for EPVM alas.
-
-.req.speed.fast.other.why: We might expect mark and sweep pools to make use of 
-Bit Tables, the MPS has general requirements to support efficient mark and 
-sweep pools, so that imposes general speed requirements on Bit Tables.
-
-
-NON REQUIREMENTS
-
-The following are not requirements but the current design could support them 
-with little modification or does support them.  Often they used to be 
-requirements, but are no longer, or were added speculatively or experimentally 
-but aren't currently used.
-
-  .non-req.ops.test.range.same: RangesSame.  Test whether two ranges that 
-occupy the same positions in different Bit Tables are the same.  This used to 
-be required by PoolClassAMS, but is no longer.  Currently (1999-05-04) the 
-functionality still exists.
-  .non-req.ops.find.long.high: FindLongResetRangeHigh.  (see .req.ops.find) Of 
-all candidate ranges, identify the ranges with greatest j and of those find the 
-one with least i (find the rightmost range that has at least L reset bits and 
-return all of it).  Provided for symmetry but only currently used by the BT 
-tests and cbstest.c.
-
-
-
-
-BACKGROUND
-
-.background: Originally Bit Tables were used and implemented by PoolClassLO 
-(design.mps.poollo).  It was decided to lift them out into a separate module 
-when designing the Pool to manage Dylan Weak Tables which is also a mark and 
-sweep pool and will make use of Bit Tables (see design.mps.poolawl).
-.background.analysis: analysis.mps.bt(0) contains some of the analysis of the 
-design decisions that were and were not made in this document.
-
-
-CLIENTS
-
-.clients: Bit Tables are used throughout the MPS but the important uses are: In 
-the client and VM arenas (design.mps.arena.client(0) and 
-design.mps.arena.vm(1)) a bit table is used to record whether each page is free 
-or not; several pool classes (PoolClassLO, PoolClassEPVM, PoolClassAMS) use bit 
-tables to record which locations are free and also to store colour.
-
-
-OVERVIEW
-
-.over: Mostly, the design is as simple as possible.  The significant 
-complications are iteration (see .iteration below) and searching (see 
-.fun.find-res-range below) because both of these are required to be fast.
-
-
-INTERFACE
-
-.if.representation.abstract: A Bit Table is represented by the type BT.
-
-.if.declare: The module declares a type BT and a prototype for each of the 
-functions below.  The type is declared in impl.h.mpmtypes, the prototypes are 
-declared in impl.h.mpm.  Some of the functions are in fact implemented as 
-macros in the usual way (doc.mps.ref-man.if-conv(0).macro.std).
-
-.if.general.index: Many of the functions specified below take indexes.  If 
-otherwise unspecified an index must be in the interval [0,n) (note, up to, but 
-not including, n) where n is the number of bits in the relevant Bit Table (as 
-passed to the BTCreate function).  .if.general.range: Where a range is 
-specified by two indexes base and limit, base, which specifies the beginning of 
-the range, must be in the interval [0,n), limit, which specifies the end of the 
-range, must be in the interval [1,n] (note can be n), and base must be strictly 
-less than limit (empty ranges are not allowed).  Sometimes i and j are used 
-instead of base and limit.
-
-.if.create:
-Res BTCreate(BT *btReturn, Arena arena, Count n)
-
-Attempts to create a table of length n in the arena control pool, putting the 
-table in '*btReturn'. Returns ResOK if and only if the table is created OK.  
-The initial values of the bits in the table are undefined (so the client should 
-probably call BTResRange on the entire range before using the BT).  Meets 
-.req.create.
-
-.if.destroy:
-void BTDestroy(BT t, Arena arena, Count n);
-
-Destroys the table t, which must have been created with BTCreate (.if.create).  
-The value of argument n must be same as the value of the argument passed to 
-BTCreate.  Meets .req.destroy.
-
-
-.if.size:
-size_t BTSize(Count n);
-
-BTSize(n) returns the number of bytes needed for a Bit Table of n bits. 
-BTSize is a macro, but (BTSize)(n) will assert if n exceeds COUNT_MAX -
-MPS_WORD_WIDTH + 1.  This is used by clients that allocate storage for
-the BT themselves.  Before BTCreate and BTDestroy were implemented that
-was the only way to allocate a Bit Table, but is now deprecated.
-
-.if.get:
-int BTGet(BT t, Index i);
-
-BTGet(t, i) returns the ith bit of the table t (i.e. the image of i under the 
-mapping).  Meets .req.ops.get.
-
-.if.set:
-void BTSet(BT t, Index i);
-
-BTSet(t, i) sets the ith bit of the table t (to 1).  BTGet(t, i) will now 
-return 1.  Meets .req.ops.set.
-
-.if.res:
-void BTRes(BT t, Index i);
-
-BTRes(t, i) resets the ith bit of the table t (to 0).  BTGet(t, i) will now 
-return 0.  Meets .req.ops.res.
-
-.if.set-range:
-void BTSetRange(BT t, Index base, Index limit);
-
-BTSetRange(t, base, limit) sets the range of bits [base, limit) in the table 
-t.  BTGet(t, x) will now return 1 for base<=x<limit.  Meets .req.ops.range.set.
-
-.if.res-range:
-void BTResRange(BT t, Index base, Index limit);
-
-BTResRange(t, base, limit) resets the range of bits [base, limit) in the table 
-t.  BTGet(t, x) will now return 0 for base<=x<limit.  Meets .req.ops.range.res.
-
-.if.test.range.set:
-Bool BTIsSetRange(BT bt, Index base, Index limit);
-
-Returns TRUE if all the bits in the range [base, limit) are set, FALSE 
-otherwise.  Meets .req.ops.test.range.set.
-
-.if.test.range.reset:
-Bool BTIsResRange(BT bt, Index base, Index limit);
-
-Returns TRUE if all the bits in the range [base, limit) are reset, FALSE 
-otherwise.  Meets .req.ops.test.range.reset.
-
-.if.test.range.same: 
-Bool BTRangesSame(BT BTx, BT BTy, Index base, Index limit);
-
-returns TRUE if BTGet(BTx,i) equals BTGet(BTy,i) for i in [base, limit), and 
-false otherwise.  Meets .req.ops.test.range.same
-
-.if.find.general: There are four functions (below) to find reset ranges.  All 
-the functions have the same prototype (for symmetry):
-Bool find(Index *baseReturn, Index *limitReturn,
-          BT bt,
-          Index searchBase, Index searchLimit,
-          Count length);
-
-bt is the Bit Table in which to search.  searchBase and searchLimit specify a 
-subset of the Bit Table to use, the functions will only find ranges that are 
-subsets of [searchBase, searchLimit) (when set *baseReturn will never be less 
-than searchBase and *limitReturn will never be greater than searchLimit).  
-searchBase, searchLimit specify a range that must conform to the general range 
-requirements for a range [i,j), as per .if.general.range modified 
-appropriately.  length is the number of contiguous reset bits to find; it must 
-not be bigger than searchLimit - searchBase (that would be silly).  If a 
-suitable range cannot be found the function returns FALSE (0) and leaves 
-*baseReturn and *limitReturn untouched.  If a suitable range is found then the 
-function returns the range's base in *baseReturn and its limit in *limitReturn 
-and returns TRUE (1).
-
-.if.find-short-res-range:
-Bool BTFindShortResRange(Index *baseReturn, Index *limitReturn,
-                         BT bt,
-                         Index searchBase, Index searchLimit,
-                         Count length);
-
-BTFindShortResRange(&base, &limit, table, searchBase, searchLimit, length) 
-finds a range of reset bits in the table, starting at searchBase and working 
-upwards.  This function is intended to meet .req.ops.find.short.low so it will 
-find the leftmost range that will do, and never finds a range longer than the 
-requested length (the intention is that it will not waste time looking).
-
-.if.find-short-res-range-high:
-Bool BTFindShortResRangeHigh(Index *baseReturn, Index *limitReturn,
-                             BT bt,
-                             Index searchBase, Index searchLimit,
-                             Count length);
-
-BTFindShortResRangeHigh(&base, &limit, table, searchBase, searchLimit, length) 
-finds a range of reset bits in the table, starting at searchLimit and working 
-downwards. This function is intended to meet .req.ops.find.short.high so it 
-will find the rightmost range that will do, and never finds a range longer than 
-the requested length.
-
-.if.find-long-res-range:
-Bool BTFindLongResRange(Index *baseReturn, Index *limitReturn,
-                        BT bt,
-                        Index searchBase, Index searchLimit,
-                        Count length);
-
-BTFindLongResRange(&base, &limit, table, searchBase, searchLimit, length) finds 
-a range of reset bits in the table, starting at searchBase and working 
-upwards.  This function is intended to meet .req.ops.find.long.low so it will 
-find the leftmost range that will do and returns all of that range (which can 
-be longer than the requested length).
-
-.if.find-long-res-range-high:
-Bool BTFindLongResRangeHigh(Index *baseReturn, Index *limitReturn,
-                            BT bt,
-                            Index searchBase, Index searchLimit,
-                            Count length);
-
-BTFindLongResRangeHigh(&base, &limit, table, searchBase, searchLimit, length) 
-finds a range of reset bits in the table, starting at searchLimit and working 
-downwards.  This function is intended to meet .req.ops.find.long.high so it 
-will find the rightmost range that will do and returns all that range (which 
-can be longer than the requested length).
-
-.if.copy-range:
-extern void BTCopyRange(BT fromBT, BT toBT, Index base, Index limit);
-
-overwrites the ith bit of toBT with the ith bit of fromBT, for all i in [base, 
-limit).  Meets .req.ops.copy.simple.
-
-.if.copy-offset-range:
-extern void BTCopyOffsetRange(BT fromBT, BT toBT, Index fromBase, Index 
-fromLimit, Index toBase, Index toLimit);
-
-overwrites the ith bit of toBT with the jth bit of fromBT, for all i in [toBase,
-toLimit) and corresponding j in [fromBase, fromLimit).  Each of these 2 
-ranges must be the same size. This might be significantly less efficient than 
-BTCopyRange. Meets .req.ops.copy.offset.
-
-.if.copy-invert-range:
-extern void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit);
-
-overwrites the ith bit of toBT with the inverse of the ith bit of fromBT, for 
-all i in [base, limit).  Meets .req.ops.copy.invert.
-
-
-DETAILED DESIGN
-
-
-DataStructures
-
-.datastructure: Bit Tables will be represented as (a pointer to) an array of 
-Words.  A plain array is used instead of the more usual design convention of 
-implementing an ADT as a structure with a signature etc (see 
-guide.impl.c.adt(0)).  .datastructure.words.justify: Words are used as these 
-will probably map to the object that can be most efficiently accessed on any 
-particular platform.  .datastructure.non-adt.justify: The usual ADT conventions 
-are not followed because a) The initial design (drj) was lazy, b) Bit Tables 
-are more likely to come in convenient powers of two with the extra one or two 
-words overhead.  However, the loss of checking is severe.  Perhaps it would be 
-better to use the usual ADT style.
-
-
-Functions
-
-.fun.size: BTSize.
-Since Bit Tables are an array of Words, the size of a Bit Table of n bits is 
-simply the number of Words that it takes to store n bits times the number of 
-bytes in a Word.  This is ceiling(n/MPS_WORD_WIDTH)*sizeof(Word).  
-.fun.size.justify: Since there can be at most MPS_WORD_WIDTH-1 unused bits in 
-the entire table, this satisfies .req.bit.
-
-.index: The designs for the following functions use a decomposition of a 
-bit-index, i, into two parts, iw, ib.  .index.word: iw is the "word-index" 
-which is the index into the word array of the word that contains the bit 
-referred to by the bit-index.  iw = i / MPS_WORD_WIDTH.  Since MPS_WORD_WIDTH 
-is a power-of-two, this is the same as iw = i >> MPS_WORD_SHIFT.  The latter 
-expression is used in the code.  .index.word.justify: The compiler is more 
-likely to generate good code without the divide.  .index.sub-word: ib is the 
-"sub-word-index" which is the index of the bit referred to by the bit-index in 
-the above word.  ib = i % MPS_WORD_WIDTH.  Since MPS_WORD_WIDTH is a 
-power-of-two, this is the same as ib = i & ~((Word)-1<<MPS_WORD_SHIFT).  The 
-latter expression is used in the code.  .index.sub-word.justify: The compiler 
-is more likely to generate good code without the modulus.
-
-.index.justify.dubious: The above justifications are dubious; gcc 2.7.2 (with 
--O2) running on a sparc (zaphod) produces identical code for the following two 
-functions:
-
-unsigned long f(unsigned long i)
-{ return i/32 + i%32; }
-
-unsigned long g(unsigned long i)
-{ return (i>>5) + (i&31); }
-
-.iteration: Many of the following functions involve iteration over ranges in a 
-Bit Table. This is performed on whole words rather than individual bits, 
-whenever possible (to improve speed). This is implemented internally by the 
-macros ACT_ON_RANGE & ACT_ON_RANGE_HIGH for iterating over the range forwards 
-and backwards respectively. These macros do not form part of the interface of 
-the module, but are used extensively in the implementation.  The macros are 
-often used even when speed is not an issue because it simplifies the 
-implementation and makes it more uniform.  The iteration macros take the 
-parameters (base, limit, single_action, bits_action, word_action).
-  
-  base, limit are of type Index and define the range of the iteration
-  single_action is the name of a macro which will be used for iterating over 
-bits in the table individually. This macro must take a single Index parameter 
-corresponding to the index for the bit.  The macro must not use break or 
-continue because it will be called from within a loop from the expansion of 
-ACT_ON_RANGE.
-  bits_action is the name of a macro which will be used for iterating over 
-part-words. This macro must take parameters (wordIndex, base, limit) where 
-wordIndex is the index into the array of words, and base & limit define a range 
-of bits within the indexed word.
-  word_action is the name of a macro which will be used for iterating over 
-whole-words. This macro must take the parameter (wordIndex) where wordIndex is 
-the index of the whole-word in the array.  The macro must not use break or 
-continue because it will be called from within a loop from the expansion of 
-ACT_ON_RANGE.
-
-.iteration.exit: The code in the single_action, bits_action, and word_action 
-macros is allowed to use 'return' or 'goto' to terminate the iteration early.  
-This is used by the test (.fun.test.*) and find (.fun.find.*) operations.
-
-.iteration.small: If the range is sufficiently small only the single_action 
-macro will be used as this is more efficient in practice.  The choice of what 
-constitutes a small range is made entirely on the basis of experimental 
-performance results (and currently, 1999-04-27, a "small range" is 6 bits or 
-fewer.  See change.mps.epcore.brisling.160181 for some justification).  
-Otherwise (for a bigger range) bits_action is used on the part words at either 
-end of the range (or the whole of the range it if it fits in a single word), 
-and word_action is used on the words that comprise the inner portion of the 
-range.
-
-The implementation of ACT_ON_RANGE (and ACT_ON_RANGE_HIGH) is simple enough.  
-It decides which macros it should invoke and invokes them.  single_action and 
-word_action are invoked inside loops.
-
-
-.fun.get: BTGet.
-The bit-index will be converted in the usual way, see .index.  The relevant 
-Word will be read out of the Bit Table and shifted right by the sub-Word index 
-(this brings the relevant bit down to the least significant bit of the Word), 
-the Word will then be masked with 1 producing the answer.
-
-.fun.set: BTSet
-
-.fun.res: BTRes
-
-In both BTSet and BTRes a mask is constructed by shifting 1 left by the 
-sub-word-index (see .index).  For BTSet the mask is ORed into the relevant word 
-(thereby setting a single bit).  For BTRes the mask is inverted and ANDed into 
-the relevant word (thereby resetting a single bit).
-
-.fun.set-range: BTSetRange
-ACT_ON_RANGE (see .iteration above) is used with macros that set a single bit 
-(using BTSet), set a range of bits in a word, and set a whole word.
-
-.fun.res-range: BTResRange
-This is implemented similarly to BTSetRange (.fun.set-range) except using BTRes 
-& reverse bit masking logic.
-
-.fun.test.range.set: BTIsSetRange
-ACT_ON_RANGE (see .iteration above) is used with macros that test whether all 
-the relevant bits are set; if some of the relevant bits are not set then 
-'return FALSE' is used to terminate the iteration early and return from the 
-BTIsSetRange function.  If the iteration completes then TRUE is returned.
-
-.fun.test.range.reset: BTIsResRange
-As for BTIsSetRange (.fun.test.range.set above) but testing whether the bits 
-are reset.
-
-.fun.test.range.same: BTRangesSame
-As for BTIsSetRange (.fun.test.range.set above) but testing whether 
-corresponding ranges in the two Bit Tables are the same.  Note there are no 
-speed requirements, but ACT_ON_RANGE is used for simplicity and uniformity.
-
-.fun.find: The four external find functions (BTFindShortResRange, 
-BTFindShortResRangeHigh, BTFindLongResRange, BTFindLongResRangeHigh) simply 
-call through to one of the two internal functions: BTFindResRange, 
-BTFindResRangeHigh.   BTFindResRange and BTFindResRangeHigh both have the 
-following prototype (with a different name obviously):
-
-Bool BTFindResRange(Index *baseReturn, Index *limitReturn,
-                    BT bt,
-                    Index searchBase, Index searchLimit,
-                    Count minLength,
-                    Count maxLength)
-
-There are two length parameters, one specifying the minimum length of the range 
-to be found, the other the maximum length.  For BTFindShort* maxLength is equal 
-to minLength when passed; for BTFindLong* maxLength is equal to the maximum 
-possible range (searchLimit - searchBase).
-
-.fun.find-res-range: BTFindResRange
-Iterate within the search boundaries, identifying candidate ranges by searching 
-for a reset bit.  The Boyer-Moore algorithm (reference please?) is used (it's 
-particularly easy when there are only two symbols, 0 and 1, in the alphabet).  
-For each candidate range, iterate backwards over the bits from the end of the 
-range towards the beginning.  If a set bit is found, this candidate has failed 
-and a new candidate range is selected.  If when scanning for the set bit a 
-range of reset bits was found before finding the set bit, then this (small) 
-range of reset bits is used as the start of the next candidate.  Additionally 
-the end of this small range of reset bits (the end of the failed candidate 
-range) is remembered so that we don't have to iterate over this range again.  
-But if no reset bits were found in the candidate range, then iterate again 
-(starting from the end of the failed candidate) to look for one.  If during the 
-backwards search no set bit is found, then we have found a sufficiently large 
-range of reset bits; now extend the valid range as far as possible up to the 
-maximum length by iterating forwards up to the maximum limit looking for a set 
-bit.  The iterations make use of the ACT_ON_RANGE & ACT_ON_RANGE_HIGH macros 
-using of 'goto' to effect an early termination of the iteration when a 
-set/reset (as appropriate) bit is found.  The macro ACTION_FIND_SET_BIT is used 
-in the iterations, it efficiently finds the first (that is, with lowest index 
-or weight) set bit in a word or subword.  
-
-.fun.find-res-range.improve: Various other performance improvements have been 
-suggested in the past, including some from request.epcore.170534.  Here is a 
-list of potential improvements which all sound plausible, but which have not 
-led to performance improvements in practice:
-
-.fun.find-res-range.improve.step.partial: When the top index in a candidate
-range fails, skip partial words as well as whole words, using
-e.g. lookup tables.
-
-.fun.find-res-range.improve.lookup: When testing a candidate run,
-examine multiple bits at once (e.g. 8), using lookup tables for (e.g)
-index of first set bit, index of last set bit, number of reset bits,
-length of maximum run of reset bits.
-
-.fun.find-res-range-high: BTFindResRangeHigh
-Exactly the same algorithm as in BTFindResRange (see .fun.find-res-range 
-above), but moving over the table in the opposite direction.
-
-.fun.copy-simple-range: BTCopyRange.
-Uses ACT_ON_RANGE (see .iteration above) with the obvious implementation.  
-Should be fast.
-
-.fun.copy-offset-range: BTCopyOffsetRange.
-Uses a simple iteration loop, reading bits with BTGet and setting them with 
-BTSet. Doesn't use ACT_ON_RANGE because the two ranges will not, in general, be 
-similarly word-aligned.
-
-.fun.copy-invert-range: BTCopyInvertRange.
-Uses ACT_ON_RANGE (see .iteration above) with the obvious implementation.  
-Should be fast - although there are no speed requirements.
-
-
-TESTING
-
-.test: The following tests are available / have been used during development.
-
-.test.btcv: MMsrc!btcv.c.  This is supposed to be a coverage test, intended to 
-execute all of the module's code in at least some minimal way.
-
-.test.cbstest: MMsrc!cbstest.c.  This was written as a test of the CBS module 
-(design.mps.cbs(2)).  It compares the functional operation of a CBS with that 
-of a BT so is a good functional test of either module.
-
-.test.mmqa.120: MMQA_test_function!210.c.  This is used because it has a fair 
-amount of segment allocation and freeing so exercises the arena code that uses 
-Bit Tables.
-
-.test.bttest: MMsrc!bttest.c.  This is an interactive test that can be used to 
-exercise some of the BT functionality by hand.
-
-.test.dylan: It is possible to modify Dylan so that it uses Bit Tables more 
-extensively.  See change.mps.epcore.brisling.160181 TEST1 and TEST2.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/buffer/index.html b/mps/design/buffer/index.html deleted file mode 100644 index e63214fb357..00000000000 --- a/mps/design/buffer/index.html +++ /dev/null @@ -1,858 +0,0 @@ - - - - - - - - -Allocation buffers and allocation points - - - - - -
- -

-Ravenbrook / -Projects / -Memory Pool System / -Master Product Sources / -Design Documents -

- -

Memory Pool System Project

- -
- -

Allocation buffers and allocation points

- -
- -

This document contains a guide to allocation buffers and allocation points, followed by the historical initial design. References, History, Copyright and License are at the end.

- -
- -

Guide

- -

Readership: any MPS developer. Not confidential.

- -

Introduction

- -

Glossary:

-
-
Trapped
-
means the buffer is in a state such that the MPS gets to know about the next use of that buffer
-
- - - -
- -

Initial Design

- -
-                ALLOCATION BUFFERS AND ALLOCATION POINTS
-                           design.mps.buffer
-                           incomplete design
-                           richard 1996-09-02
-
-INTRODUCTION
-
-.scope: This document describes the design of allocation buffers and allocation 
-points.
-
-.purpose: The purpose of this document is to record design decisions made 
-concerning allocation buffers and allocation points and justify those decisions 
-in terms of requirements.
-
-.readership: The document is intended for reading by any Memory Management 
-Group developer.
-
-
-HISTORY
-
-.history.0-1: The history for versions 0-1 is lost pending possible 
-reconstruction.
-
-.history.2: Added class hierarchy and subclassing information.
-
-
-SOURCE
-
-.source.mail: Much of the juicy stuff about buffers is only floating around in 
-mail discussions.  You might like to try searching the archives if you can't 
-find what you want here.
-
-[Note: mail archives are only accessible to Ravenbrook staff.  RHSK 2006-06-09]
-
-.source.synchronize: For a discussion of the synchronization issues: 
-  mail.richard.1995-05-19.17-10
-  mail.ptw.1995-05-19.19-15
-  mail.richard.1995-05-24.10-18
-[drj - I believe that the sequence for flip in ptw's message is incorrect.  The 
-operations should be in the other order]
-
-.source.interface: For a description of the buffer interface in C prototypes: 
-  mail.richard.1997-04-28.09-25(0)
-
-.source.qa: Discussions with QA were useful in pinning down the semantics and 
-understanding of some obscure but important boundary cases.  See 
-mail.richard.tucker.1997-05-12.09-45(0) et seq (mail subject: "notes on our 
-allocation points discussion"):
-  ./1997/05/12/09-45/0.txt:X-MMInfo-Tag: mail.richard.tucker.1997-05-12.09-45
-  ./1997/05/12/12-46/1.txt:X-MMInfo-Tag: mail.ptw.1997-05-12.12-46(1)        
-  ./1997/05/12/13-15/0.txt:X-MMInfo-Tag: mail.richard.1997-05-12.13-15       
-  ./1997/05/12/13-28/0.txt:X-MMInfo-Tag: mail.richard.1997-05-12.13-28       
-  ./1997/05/13/15-15/0.txt:X-MMInfo-Tag: mail.ptw.1997-05-13.15-15           
-  ./1997/05/14/11-52/0.txt:X-MMInfo-Tag: mail.sheep.1997-05-14.11-52         
-  ./1997/05/15/09-19/0.txt:X-MMInfo-Tag: mail.rit.1997-05-15.09-19           
-  ./1997/05/15/21-22/0.txt:X-MMInfo-Tag: mail.ptw.1997-05-15.21-22           
-  ./1997/05/15/21-35/0.txt:X-MMInfo-Tag: mail.ptw.1997-05-15.21-35           
-  ./1997/05/16/08-02/0.txt:X-MMInfo-Tag: mail.rit.1997-05-16.08-02           
-  ./1997/05/16/08-42/0.txt:X-MMInfo-Tag: mail.rit.1997-05-16.08-42           
-  ./1997/05/16/12-36/0.txt:X-MMInfo-Tag: mail.ptw.1997-05-16.12-36           
-  ./1997/05/16/12-47/0.txt:X-MMInfo-Tag: mail.ptw.1997-05-16.12-47           
-  ./1997/05/19/15-46/0.txt:X-MMInfo-Tag: mail.richard.1997-05-19.15-46       
-  ./1997/05/19/15-56/0.txt:X-MMInfo-Tag: mail.richard.1997-05-19.15-56       
-  ./1997/05/20/20-47/0.txt:X-MMInfo-Tag: mail.ptw.1997-05-20.20-47           
-
-
-
-REQUIREMENTS
-
-.req.fast: Allocation must be very fast
-.req.thread-safe: Must run safely in a multi-threaded environment
-.req.no-synch: Must avoid the use of thread-synchronization (.req.fast)
-.req.manual: Support manual memory management
-.req.exact: Support exact collectors
-.req.ambig: Support ambiguous collectors
-.req.count: Must record (approximately) the amount of allocation (in bytes).  
-Actually not a requirement any more, but once was put forward as a Dylan 
-requirement.  Bits of the code still reflect this requirement.  See 
-request.dylan.170554.
-
-
-CLASSES
-
-.class.hierarchy: The Buffer datastructure is designed to be subclassable (see 
-design.mps.protocol). 
-
-.class.hierarchy.buffer: The basic buffer class (BufferClass) supports basic 
-allocation-point buffering, and is appropriate for those manual pools which 
-don't use segments (.req.manual).  The Buffer class doesn't support reference 
-ranks (i.e. the buffers have RankSetEMPTY).  Clients may use BufferClass 
-directly, or create their own subclasses (see .subclassing). 
-
-.class.hierarchy.segbuf: Class SegBufClass is also provided for the use of 
-pools which additionally need to associate buffers with segments.  SegBufClass 
-is a subclass of BufferClass.  Manual pools may find it convenient to use 
-SegBufClass, but it is primarily intended for automatic pools (.req.exact, 
-.req.ambig).  An instance of SegBufClass may be attached to a region of memory 
-that lies within a single segment.  The segment is associated with the buffer, 
-and may be accessed with the BufferSeg function.  SegBufClass also supports 
-references at any rank set. Hence this class or one of its subclasses should be 
-used by all automatic pools (with the possible exception of leaf pools).  The 
-rank sets of buffers and the segments they are attached to must match.  Clients 
-may use SegBufClass directly, or create their own subclasses (see 
-.subclassing).
-
-.class.hierarchy.rankbuf: Class RankBufClass is also provided as a subclass of 
-SegBufClass.  The only way in which this differs from its superclass is that 
-the rankset of a RankBufClass is set during initialization to the singleton 
-rank passed as an additional parameter to BufferCreate.  Instances of 
-RankBufClass are of the same type as instances of SegBufClass, i.e., SegBuf.  
-Clients may use RankBufClass directly, or create their own subclasses (see 
-.subclassing).
-
-.class.create: The buffer creation functions (BufferCreate and BufferCreateV) 
-take a class parameter, which determines the class of buffer to be created.
-
-.class.choice: Pools which support buffered allocation should specify a default 
-class for buffers.  This class will be used when a buffer is created in the 
-normal fashion by MPS clients (for example by a call to mps_ap_create).  Pools 
-specify the default class by means of the bufferClass field in the pool class 
-object.  This should be a pointer to a function of type PoolBufferClassMethod.  
-The normal class "Ensure" function (e.g. Ensure*Buffer*Class) has the 
-appropriate type.
-
-.subclassing: Pools may create their own subclasses of the standard buffer 
-classes.  This is sometimes useful if the pool needs to add an extra field to 
-the buffer.  The convenience macro DEFINE_BUFFER_CLASS may be used to define 
-subclasses of buffer classes.  See design.mps.protocol.int.define-special.  
-.replay: To work with the allocation replayer (see 
-design.mps.telemetry.replayer), the buffer class has to emit an event for each 
-call to an external interface, containing all the parameters passed by the 
-user.  If a new event type is required to carry this information, the replayer 
-(impl.c.eventrep) must then be extended to recreate the call.  
-.replay.pool-buffer: The replayer must also be updated if the association of 
-buffer class to pool or the buffer class hierarchy is changed.
-
-.class.method: Buffer classes provide the following methods (these should not 
-be confused with the pool class methods related to the buffer protocol, 
-described in .method.*):
-
-.class.method.init: "init" is a class-specific initialization method called 
-from BufferInitV.  It receives the optional (vararg) parameters passed to 
-BufferInitV.  Client-defined methods must call their superclass method (via a 
-next-method call) before performing any class-specific behaviour.  .replay.init
-: The init method should emit a BufferInit<foo> event (if there aren't any 
-extra parameters, <foo> = "").
-
-.class.method.finish: "finish" is a class-specific finish method called from 
-BufferFinish.  Client-defined methods must call their superclass method (via a 
-next-method call) after performing any class-specific behaviour.
-
-.class.method.attach: "attach" is a class-specific method called whenever a 
-buffer is attached to memory, via BufferAttach.   Client-defined methods must 
-call their superclass method (via a next-method call) before performing any 
-class-specific behaviour.
-
-.class.method.detach: "detach" is a class-specific method called whenever a 
-buffer is detached from memory, via BufferDetach.  Client-defined methods must 
-call their superclass method (via a next-method call) after performing any 
-class-specific behaviour.
-
-.class.method.seg: "seg" is a class-specific accessor method which returns the 
-segment attached to a buffer (or NULL if there isn't one).  It is called from 
-BufferSeg.  Clients should not need to define their own methods for this.
-
-.class.method.rankSet: "rankSet" is a class-specific accessor method which 
-returns the rank set of a buffer.  It is called from BufferRankSet.  Clients 
-should not need to define their own methods for this.
-
-.class.method.setRankSet: "setRankSet" is a class-specific setter method which 
-sets the rank set of a buffer.  It is called from BufferSetRankSet.  Clients 
-should not need to define their own methods for this.
-
-.class.method.describe: "describe" is a class-specific method called to 
-describe a buffer, via BufferDescribe.  Client-defined methods must call their 
-superclass method (via a next-method call) before describing any class-specific 
-state.
-
-
-NOTES
-
-.logging.control: Buffers have a separate control for whether they are logged 
-or not, this is because they are particularly high volume.  This is a boolean 
-flags (bufferLogging) in the ArenaStruct.
-
-.count: Counting the allocation volume is done by maintaining two fields in the 
-buffer struct:  .count.fields: fillSize, emptySize.  .count.monotonic: both of 
-these fields are monotonically increasing.  .count.fillsize: fillSize is an 
-accumulated total of the size of all the fills (as a result of calling the 
-PoolClass BufferFill method) that happen on the buffer.  .count.emptysize: 
-emptySize is an accumulated total of the size of all the empties than happen on 
-the buffer (which are notified to the pool using the PoolClass BufferEmpty 
-method).  .count.generic: These fields are maintained by the generic buffer 
-code (in BufferAttach and BufferDetach). 
-
-.count.other: Similar count fields are maintained in the pool and the arena.  
-They are maintained on an internal (buffers used internally by MPS) and 
-external (buffers used for mutator APs) basis.  The fields are also updated by 
-the buffer code.  The fields are: in the pool, 
-{fill|empty}{Mutator|Internal}Size (4 fields); in the arena, 
-{fill|empty}{Mutator|Internal}Size allocMutatorSize (5 fields). 
-
- .count.alloc.how: The amount of allocation in the buffer just after an empty 
-is (fillSize - emptySize).  At other times this computation will include space 
-that the buffer has the use of (between base and init) but which may not get 
-allocated in (because the remaining space may be too large for the next reserve 
-so some or all of it may get emptied).  The arena field allocMutatorSize is 
-incremented by the allocated size (between base and init) whenever a buffer is 
-detached. Symmetrically this field is decremented by by the pre-allocated size 
-(between base and init) whenever a buffer is attached. The overall count is 
-asymptotically correct.
-
-.count.type: All the count fields are type double.  .count.type.justify: This 
-is because double is the type most likely to give us enough precision.  Because 
-of the lack of genuine requirements the type isn't so important.  It's nice to 
-have it more precise than long.  Which double usually is.
-
-
-
-From the whiteboard:
-
-REQ
-atomic update of words
-guarantee order of reads and write to certain memory locations.
-
-FLIP
-limit:=0
-record init for scanner
-
-COMMIT
-init:=alloc
-if(limit = 0) ...
-
-L written only by MM
-A \ written only by client (except during synchronized MM op)
-I /
-I read by MM during flip
-
-
-States
-
-BUSY
-READY
-TRAPPED
-RESET
-[drj: there are many more states]
-
-
-Misc
-
-.misc: During buffer ops all field values can change.  Might trash perfectly 
-good ("valid"?) object if pool isn't careful.
-
-
-Not from the whiteboard.
-
-
-SYNCHRONIZATION
-
-Buffers provide a loose form of synchronization between the mutator and the 
-collector. 
-
-The crucial synchronization issues are between the operation the pool performs 
-on flip and the mutator's commit operation.
-
-Commit
-
-read init
-write init
-Memory Barrier
-read limit
-
-Flip
-
-write limit
-Memory Barrier
-read init
-
-Commit consists of two parts.  The first is the update to init.  This is a 
-declaration that the new object just before init is now correctly formatted and 
-can be scanned.  The second is a check to see if the buffer has been 
-"tripped".  The ordering of the two parts is crucial.
-
-Note that the declaration that the object is correctly formatted is independent 
-of whether the buffer has been tripped or not.  In particular a pool can scan 
-up to the init pointer (including the newly declared object) whether or not the 
-pool will cause the commit to fail.  In the case where the pool scans the 
-object, but then causes the commit to fail (and presumably the allocation to 
-occur somewhere else), the pool will have scanned a "dead" object, but this is 
-just another example of conservatism in the general sense.
-
-Not that the read of init in the Flip sequence can in fact be arbitrarily 
-delayed (as long as it is read before a buffered segment is scanned).
-
-On processors with Relaxed Memory Order (such as the DEC Alpha), Memory 
-Barriers will need to be placed at the points indicated.
-
- * DESIGN
- *
- * design.mps.buffer.
- *
- * An allocation buffer is an interface to a pool which provides
- * very fast allocation, and defers the need for synchronization in
- * a multi-threaded environment.
- *
- * Pools which contain formatted objects must be synchronized so
- * that the pool can know when an object is valid.  Allocation from
- * such pools is done in two stages: reserve and commit.  The client
- * first reserves memory, then initializes it, then commits.
- * Committing the memory declares that it contains a valid formatted
- * object.  Under certain conditions, some pools may cause the
- * commit operation to fail.  (See the documentation for the pool.)
- * Failure to commit indicates that the whole allocation failed and
- * must be restarted.  When using a pool which introduces the
- * possibility of commit failing, the allocation sequence could look
- * something like this:
- *
- * do {
- *   res = BufferReserve(&p, buffer, size);
- *   if(res != ResOK) return res;       // allocation fails, reason res
- *   initialize(p);                     // p now points at valid object
- * } while(!BufferCommit(buffer, p, size));
- *
- * Pools which do not contain formatted objects can use a one-step
- * allocation as usual.  Effectively any random rubbish counts as a
- * "valid object" to such pools.
- *
- * An allocation buffer is an area of memory which is pre-allocated
- * from a pool, plus a buffer descriptor, which contains, inter
- * alia, four pointers: base, init, alloc, and limit.  Base points
- * to the base address of the area, limit to the last address plus
- * one.  Init points to the first uninitialized address in the
- * buffer, and alloc points to the first unallocated address.
- *
- *    L . - - - - - .         ^
- *      |           |     Higher addresses -'
- *      |   junk    |
- *      |           |       the "busy" state, after Reserve
- *    A |-----------|
- *      |  uninit   |
- *    I |-----------|
- *      |   init    |
- *      |           |     Lower addresses  -.
- *    B `-----------'         v
- *
- *    L . - - - - - .         ^
- *      |           |     Higher addresses -'
- *      |   junk    |
- *      |           |       the "ready" state, after Commit
- *  A=I |-----------|
- *      |           |
- *      |           |
- *      |   init    |
- *      |           |     Lower addresses  -.
- *    B `-----------'         v
- *
- * Access to these pointers is restricted in order to allow
- * synchronization between the pool and the client.  The client may
- * only write to init and alloc, but in a restricted and atomic way
- * detailed below.  The pool may read the contents of the buffer
- * descriptor at _any_ time.  During calls to the fill and trip
- * methods, the pool may update any or all of the fields
- * in the buffer descriptor.  The pool may update the limit at _any_
- * time.
- *
- * Access to buffers by these methods is not synchronized.  If a buffer
- * is to be used by more than one thread then it is the client's
- * responsibility to ensure exclusive access.  It is recommended that
- * a buffer be used by only a single thread.
- *
- * [Only one thread may use a buffer at once, unless the client
- * places a mutual exclusion around the buffer access in the usual
- * way.  In such cases it is usually better to create one buffer for
- * each thread.]
- *
- * Here are pseudo-code descriptions of the reserve and commit
- * operations.  These may be implemented in-line by the client.
- * Note that the client is responsible for ensuring that the size
- * (and therefore the alloc and init pointers) are aligned according
- * to the buffer's alignment.
- *
- * Reserve(buf, size)                   ; size must be aligned to pool
- *   if buf->limit - buf->alloc >= size then
- *     buf->alloc +=size                ; must be atomic update
- *     p = buf->init
- *   else
- *     res = BufferFill(&p, buf, size)  ; buf contents may change
- *
- * Commit(buf, p, size)
- *   buf->init = buf->alloc             ; must be atomic update
- *   if buf->limit == 0 then
- *     res = BufferTrip(buf, p, size)   ; buf contents may change
- *   else
- *     res = True
- * (returns True on successful commit)
- *
- * The pool must allocate the buffer descriptor and initialize it by
- * calling BufferInit.  The descriptor this creates will fall
- * through to the fill method on the first allocation.  In general,
- * pools should not assign resources to the buffer until the first
- * allocation, since the buffer may never be used.
- *
- * The pool may update the base, init, alloc, and limit fields when
- * the fallback methods are called.  In addition, the pool may set
- * the limit to zero at any time.  The effect of this is either:
- *
- *   1. cause the _next_ allocation in the buffer to fall through to
- *      the buffer fill method, and allow the buffer to be flushed
- *      and relocated;
- *
- *   2. cause the buffer trip method to be called if the client was
- *      between reserve and commit.
- *
- * A buffer may not be relocated under other circumstances because
- * there is a race between updating the descriptor and the client
- * allocation sequence.
-
-
-.method.create:
-
-BufferCreate
-
-Create an allocation buffer in a pool.
-
-The buffer is created in the "ready" state.
-
-A buffer structure is allocated from the space control pool and partially 
-initialized (in particularly neither the signature nor the serial field are 
-initialized).  The pool class's bufferCreate method is then called.  This 
-method can update (some undefined subset of) the fields of the structure; it 
-should return with the buffer in the "ready" state (or fail).  The remainder of 
-the initialization then occurs.
-
-If and only if successful then a valid buffer is returned.
-
-
-.method.destroy:
-
-BufferDestroy
-
-Destroy frees a buffer descriptor.  The buffer must be in the "ready" state, 
-i.e. not between a Reserve and Commit.  Allocation in the area of memory to 
-which the descriptor refers must cease after Destroy is called.
-
-Destroying an allocation buffer does not affect objects which have been 
-allocated, it just frees resources associated with the buffer itself.
-
-The pool class's bufferDestroy method is called and then the buffer structure 
-is uninitialized and freed.
-
-
-.method.check:
-
-BufferCheck
-
-The check method is straightforward, the non-trivial dependencies checked are:
-  The ordering constraints between base, init, alloc, and limit.
-  The alignment constraints on base, init, alloc, and limit.
-  That the buffer's rank is identical to the segment's rank.
-  
-.method.set-reset:
-
-/* BufferSet/Reset -- set/reset a buffer
- *
- * Set sets the buffer base, init, alloc, and limit fields so that
- * the buffer is ready to start allocating in area of memory.  The
- * alloc field is a copy of the init field.
- *
- * Reset sets the seg, base, init, alloc, and limit fields to
- * zero, so that the next reserve request will call the fill
- * method.
- */
-
-.method.set.unbusy: BufferSet must only be applied to buffers that are not busy.
-.method.reset.unbusy: BufferReset must only be applied to buffers that are not 
-busy.
-
-
-.method.accessors:
-
-/* Buffer Information
- *
- * BufferIsReset returns TRUE if and only if the buffer is in the
- * reset state, i.e.  with base, init, alloc, and limit set to zero.
- *
- * BufferIsReady returns TRUE iff the buffer is not between a
- * reserve and commit.  The result is only reliable if the client is
- * not currently using the buffer, since it may update the alloc and
- * init pointers asynchronously.
- *
- * BufferAP returns the APStruct substructure of a buffer.
- *
- * BufferOfAP is a thread-safe (impl.c.mpsi.thread-safety) method of
- * getting the buffer which owns an APStruct.
- *
- * BufferSpace is a thread-safe (impl.c.mpsi.thread-safety) method of
- * getting the space which owns a buffer.
- *
- * BufferPool returns the pool to which a buffer is attached.
- */
-
-.method.ofap:
-
-.method.ofap.thread-safe:
-BufferOfAP must be thread safe (see impl.c.mpsi.thread-safety).  This is 
-achieved simply because the underlying operation involved is simply a 
-subtraction.
-
-.method.space:
-.method.space.thread-safe:
-BufferSpace must be thread safe (see impl.c.mpsi.thread-safety).  This is 
-achieved simple because the underlying operation is a read of 
-shared-non-mutable data (see design.mps.thread-safety).
-
-.method.reserve:
-
-/* BufferReserve -- reserve memory from an allocation buffer
- *
- * This is a provided version of the reserve procedure described
- * above.  The size must be aligned according to the buffer
- * alignment.  Iff successful, ResOK is returned and
- * *pReturn updated with a pointer to the reserved memory.
- * Otherwise *pReturn is not touched.  The reserved memory is not
- * guaranteed to have any particular contents.  The memory must be
- * initialized with a valid object (according to the pool to which
- * the buffer belongs) and then passed to the Commit method (see
- * below).  Reserve may not be applied twice to a buffer without a
- * Commit in-between.  In other words, Reserve/Commit pairs do not
- * nest.
- */
-
-Res BufferReserve(Addr *pReturn, Buffer buffer, Size size)
-{
-  Addr next;
-
-  AVER(pReturn != NULL);
-  AVERT(Buffer, buffer);
-  AVER(size > 0);
-  AVER(SizeIsAligned(size, BufferPool(buffer)->alignment));
-  AVER(BufferIsReady(buffer));
-
-  /* Is there enough room in the unallocated portion of the buffer to */
-  /* satisfy the request?  If so, just increase the alloc marker and */
-  /* return a pointer to the area below it. */
-
-  next = AddrAdd(buffer->ap.alloc, size);
-  if(next > buffer->ap.alloc && next <= buffer->ap.limit)
-  {
-    buffer->ap.alloc = next;
-    *pReturn = buffer->ap.init;
-    return ResOK;
-  }
-
-  /* If the buffer can't accommodate the request, fall through to the */
-  /* pool-specific allocation method. */
-
-  return BufferFill(pReturn, buffer, size);
-}
-
-.method.fill:
-
-/* BufferFill -- refill an empty buffer
- *
- * If there is not enough space in a buffer to allocate in-line,
- * BufferFill must be called to "refill" the buffer.  (See the
- * description of the in-line Reserve method in the leader comment.)
- */
-
-Res BufferFill(Addr *pReturn, Buffer buffer, Size size)
-{
-  Res res;
-  Pool pool;
-
-  AVER(pReturn != NULL);
-  AVERT(Buffer, buffer);
-  AVER(size > 0);
-  AVER(SizeIsAligned(size, BufferPool(buffer)->alignment));
-  AVER(BufferIsReady(buffer));
-
-  pool = BufferPool(buffer);
-  res = (*pool->class->bufferFill)(pReturn, pool, buffer, size);
-
-  AVERT(Buffer, buffer);
-
-  return res;
-}
-
-
-.method.commit:
-
-/* BufferCommit -- commit memory previously reserved
- *
- * Commit notifies the pool that memory which has been previously
- * reserved (see above) has been initialized with a valid object
- * (according to the pool to which the buffer belongs).  The pointer
- * p must be the same as that returned by Reserve, and the size must
- * match the size passed to Reserve.
- *
- * Commit may not be applied twice to a buffer without a reserve
- * in-between.  In other words, objects must be reserved,
- * initialized, then committed only once.
- *
- * Commit returns TRUE iff successful.  If commit fails and returns
- * FALSE, the client may try to allocate again by going back to the
- * reserve stage, and may not use the memory at p again for any
- * purpose.
- *
- * Some classes of pool may cause commit to fail under rare
- * circumstances.
- */
-
-Bool BufferCommit(Buffer buffer, Addr p, Size size)
-{
-  AVERT(Buffer, buffer);
-  AVER(size > 0);
-  AVER(SizeIsAligned(size, BufferPool(buffer)->alignment));
-  /* Buffer is "busy" */
-  AVER(!BufferIsReady(buffer));
-
-  /* See design.mps.collection.flip.
-   * If a flip occurs before this point, when the pool reads
-   * buffer->init it will point below the object, so it will be trashed
-   * and the commit must fail when trip is called.  The pool will also
-   * read p (during the call to trip) which points to the invalid
-   * object at init.
-   */
-
-  AVER(p == buffer->ap.init);
-  AVER(AddrAdd(buffer->ap.init, size) == buffer->ap.alloc);
-
-  /* Atomically update the init pointer to declare that the object */
-  /* is initialized (though it may be invalid if a flip occurred). */
-
-  buffer->ap.init = buffer->ap.alloc;
-
-  /* .improve.memory-barrier: Memory barrier here on the DEC Alpha
-   * (and other relaxed memory order architectures). */
-
-  /* If a flip occurs at this point, the pool will see init */
-  /* above the object, which is valid, so it will be collected. */
-  /* The commit must succeed when trip is called.  The pointer */
-  /* p will have been fixed up. */
-
-  /* Trip the buffer if a flip has occurred. */
-
-  if(buffer->ap.limit == 0)
-    return BufferTrip(buffer, p, size);
-
-  /* No flip occurred, so succeed. */
-
-  return TRUE;
-}
-
-
-.method.trip:
-
-BufferTrip -- act on a tripped buffer
-
-The pool which owns a buffer may asynchronously set the buffer limit to zero in 
-order to get control over the buffer.  If this occurs after a Reserve (but 
-before the corresponding commit), then the Commit method calls BufferTrip and 
-the Commit method returns with BufferTrip's return value.  (See the description 
-of Commit.)
-
-.method.trip.precondition:
-At the time trip is called (see Commit), the following are true:
-.method.trip.precondition.limit: limit == 0
-.method.trip.precondition.init: init == alloc
-.method.trip.precondition.p: p+size == alloc
-
-
-
-.method.expose-cover:
-
-Expose / Cover
-
-BufferExpose/Cover are used by collectors that want to allocate in a forwarding 
-buffer.  Since the forwarding buffer may be Shielded the potential problem of 
-handling a recursive fault appears (mutator causes a page fault, collector 
-fixes some objects causing allocation, the allocation takes place is a 
-protected area of memory which cause a page fault).  BufferExpose guarantees 
-that allocation can take place in the buffer without causing a page fault, 
-BufferCover removes this guarantee.
-
-[The following paragraph is reverse-constructed conjecture]
-BufferExpose puts the buffer in an "exposed" state, BufferCover puts the buffer 
-in a "covered" state.  BufferExpose can only be called if the buffer is 
-"covered".  BufferCover can only be called if the buffer is "exposed".
-[Is this part of the "Protection/Suspension Protocol"? (see mail with that 
-subject)]
-
-
-
-
-
-
-
--------------------------------
-
-Here are a number of diagrams showing how buffers behave. In general, the 
-horizontal axis corresponds to mutator action (reserve, commit) and the 
-vertical axis corresponds to collector action. I'm not sure which of the 
-diagrams are the same as each other, and which are best or most complete when 
-they are different, but they all attempt to show essentially the same 
-information. It's very difficult to get all the details in. These diagrams were 
-drawn by richard, rit, gavinm, &c, &c in April 1997. In general, the later 
-diagrams are, I suspect, more correct, complete and useful than the earlier 
-ones. I have put them all here for the record. rit 1998-02-09
-
-Buffer Diagram:
-Buffer States
-
-Buffer States (3-column)
-Buffer States (4-column)
-Buffer States (gavinised)
-Buffer States (interleaved)
-Buffer States (richardized)
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
2007-03-22RHSKCreated Guide.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002, 2007 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/cbs/index.html b/mps/design/cbs/index.html deleted file mode 100644 index cf6643e1e98..00000000000 --- a/mps/design/cbs/index.html +++ /dev/null @@ -1,672 +0,0 @@ - - - - - - - - -Design for coalescing block structure - - - - - - - -
-                 DESIGN FOR COALESCING BLOCK STRUCTURE
-                             design.mps.cbs
-                             incomplete doc
-                           gavinm 1998-05-01
-
-INTRODUCTION
-
-.intro: This is the design for impl.c.cbs, which implements a data structure 
-for the management of non-intersecting memory ranges, with eager coalescence.
-
-.readership: This document is intended for any MM developer.
-
-.source: design.mps.poolmv2, design.mps.poolmvff.
-
-.overview: The "coalescing block structure" is a set of addresses (or a subset 
-of address space), with provision for efficient management of contiguous 
-ranges, including insertion and deletion, high level communication with the 
-client about the size of contiguous ranges, and detection of protocol 
-violations.
-
-
-Document History
-
-.hist.0: This document was derived from the outline in design.mps.poolmv2(2).  
-Written by Gavin Matthews 1998-05-01.
-
-.hist.1: Updated by Gavin Matthews 1998-07-22 in response to approval comments 
-in change.epcore.anchovy.160040 There is too much fragmentation in trapping 
-memory.
-
-.hist.2: Updated by Gavin Matthews (as part of change.epcore.brisling.160158: 
-MVFF cannot be instantiated with 4-byte alignment) to document new alignment 
-restrictions.
-
-
-DEFINITIONS
-
-.def.range: A (contiguous) range of addresses is a semi-open interval on 
-address space.
-
-.def.isolated: A contiguous range is isolated with respect to some property it 
-has, if adjacent elements do not have that property.
-
-.def.interesting: A block is interesting if it is of at least the minimum 
-interesting size specified by the client. 
-
-
-REQUIREMENTS
-
-.req.set: Must maintain a set of addresses.
-
-.req.fast: Common operations must have a low amortized cost.
-
-.req.add: Must be able to add address ranges to the set.
-
-.req.remove: Must be able to remove address ranges from the set.
-
-.req.size: Must report concisely to the client when isolated contiguous ranges 
-of at least a certain size appear and disappear.
-
-.req.iterate: Must support the iteration of all isolated contiguous ranges.  
-This will not be a common operation.
-
-.req.protocol: Must detect protocol violations.
-
-.req.debug: Must support debugging of client code.
-
-.req.small: Must have a small space overhead for the storage of typical subsets 
-of address space and not have abysmal overhead for the storage of any subset of 
-address space.
-
-.req.align: Must support an alignment (the alignment of all addresses 
-specifying ranges) of down to sizeof(void *) without losing memory.
-
-
-INTERFACE
-
-.header: CBS is used through impl.h.cbs.
-
-
-External Types
-
-.type.cbs: CBS is the main data-structure for manipulating a CBS.  It is 
-intended that a CBSStruct be embedded in another structure.  No convenience 
-functions are provided for the allocation or deallocation of the CBS.
-  typedef struct CBSStruct CBSStruct, *CBS;
-
-.type.cbs.block: CBSBlock is the data-structure that represents an isolated 
-contiguous range held by the CBS.  It is returned by the new and delete methods 
-described below.
-  typedef struct CBSBlockStruct CBSBlockStruct, *CBSBlock;
-
-.type.cbs.method: The following methods are provided as callbacks to advise the 
-client of certain events.  The implementation of these functions should not 
-cause any CBS function to be called on the same CBS.  In this respect, the CBS 
-module is not re-entrant.
-
-.type.cbs.change.size.method: CBSChangeSizeMethod is the function pointer type, 
-four instances of which are optionally registered via CBSInit.
-  typedef void (*CBSChangeSizeMethod)(CBS cbs, CBSBlock block, Size oldSize, 
-SizeNewSize);
-These callbacks are invoked under CBSInsert, CBSDelete, or CBSSetMinSize in 
-certain circumstances.  Unless otherwise stated, oldSize and newSize will both 
-be non-zero, and different.  The accessors CBSBlockBase, CBSBlockLimit, and 
-CBSBlockSize may be called from within these callbacks, except within the 
-delete callback when newSize is zero.  See .impl.callback for implementation 
-details.
-
-.type.cbs.iterate.method: CBSIterateMethod is a function pointer type is a 
-client method invoked by the CBS module for every isolated contiguous range in 
-address order, when passed to the CBSIterate or CBSIterateLarge functions.  The 
-function returns a boolean indicating whether to continue with the iteration.
-  typedef Bool (*CBSIterateMethod)(CBS cbs, CBSBlock block, void *closureP, 
-unsigned long closureS);
-
-
-External Functions
-
-.function.cbs.init: CBSInit is the function that initialises the CBS 
-structure.  It performs allocation in the supplied arena.  Four methods are 
-passed in as function pointers (see .type.* above), any of which may be NULL.  
-It receives a minimum size, which is used when determining whether to call the 
-optional methods.  The mayUseInline boolean indicates whether the CBS may use 
-the memory in the ranges as a low-memory fallback (see .impl.low-mem).  The 
-alignment indicates the alignment of ranges to be maintained.  An initialised 
-CBS contains no ranges.
-  Res CBSInit(Arena arena, CBS cbs, CBSChangeSizeMethod new, 
-CBSChangeSizeMethod delete, CBSChangeSizeMethod grow, CBSChangeSizeMethod 
-shrink, Size minSize, Align alignment, Bool mayUseInline);
-
-.function.cbs.init.may-use-inline: If mayUseInline is set, then alignment must 
-be at least sizeof(void *).  In this mode, the CBS will never fail to insert or 
-delete ranges, even if memory for control structures becomes short.  Note that, 
-in such cases, the CBS may defer notification of new/grow events, but will 
-report available blocks in CBSFindFirst and CBSFindLast.  Such low memory 
-conditions will be rare and transitory.  See .align for more details.
-
-.function.cbs.finish: CBSFinish is the function that finishes the CBS structure 
-and discards any other resources associated with the CBS.
-  void CBSFinish(CBS cbs);
-
-.function.cbs.insert: CBSInsert is the function used to add a contiguous range 
-specified by [base,limit) to the CBS.  If any part of the range is already in 
-the CBS, then ResFAIL is returned, and the CBS is unchanged.  This function may 
-cause allocation; if this allocation fails, and any contingency mechanism 
-fails, then ResMEMORY is returned, and the CBS is unchanged.
-  Res CBSInsert(CBS cbs, Addr base, Addr limit);
-
-.function.cbs.insert.callback: CBSInsert will invoke callbacks as follows:
-  new: when a new block is created that is interesting.  oldSize == 0; newSize 
->= minSize.
-  new: when an uninteresting block coalesces to become interesting.  0 < 
-oldSize < minSize <= newSize.
-  delete: when two interesting blocks are coalesced.  grow will also be invoked 
-in this case on the larger of the two blocks.  newSize == 0; oldSize >= minSize.
-  grow: when an interesting block grows in size.  minSize <= oldSize < newSize.
- 
-.function.cbs.delete: CBSDelete is the function used to remove a contiguous 
-range specified by [base,limit) from the CBS.  If any part of the range is not 
-in the CBS, then ResFAIL is returned, and the CBS is unchanged.  This function 
-may cause allocation; if this allocation fails, and any contingency mechanism 
-fails, then ResMEMORY is returned, and the CBS is unchanged.
-  Res CBSDelete(CBS cbs, Addr base, Addr limit);
-
-.function.cbs.delete.callback: CBSDelete will invoke callbacks as follows:
-  delete: when an interesting block is entirely removed.  newSize == 0; oldSize 
->= minSize.
-  delete: when an interesting block becomes uninteresting. 0 < newSize < 
-minSize <= oldSize.
-  new: when a block is split into two blocks, both of which are interesting.  
-shrink will also be invoked in this case on the larger of the two blocks.  
-oldSize == 0; newSize >= minSize.
-  shrink: when an interesting block shrinks in size, but remains interesting.  
-minSize <= newSize < oldSize.
-
-.function.cbs.iterate: CBSIterate is the function used to iterate all isolated 
-contiguous ranges in a CBS.  It receives a pointer, unsigned long closure pair 
-to pass on to the iterator method, and an iterator method to invoke on every 
-range in address order.  If the iterator method returns FALSE, then the 
-iteration is terminated.
-  void CBSIterate(CBS cbs, CBSIterateMethod iterate, void *closureP, unsigned 
-long closureS);
-
-.function.cbs.iterate.large: CBSIterateLarge is the function used to iterate 
-all isolated contiguous ranges of size greater than or equal to the client 
-indicated minimum size in a CBS.  It receives a pointer, unsigned long closure 
-pair to pass on to the iterator method, and an iterator method to invoke on 
-every large range in address order.  If the iterator method returns FALSE, then 
-the iteration is terminated.
-  void CBSIterateLarge(CBS cbs, CBSIterateMethod iterate, void *closureP, 
-unsigned long closureS);
-
-.function.cbs.set.min-size: CBSSetMinSize is the function used to change the 
-minimum size of interest in a CBS.  This minimum size is used to determine 
-whether to invoke the client callbacks from CBSInsert and CBSDelete.  This 
-function will invoke either the new or delete callback for all blocks that are 
-(in the semi-open interval) between the old and new values.  oldSize and 
-newSize will be the same in these cases.
-  void CBSSetMinSize(CBS cbs, Size minSize);
-
-.function.cbs.describe: CBSDescribe is a function that prints a textual 
-representation of the CBS to the given stream, indicating the contiguous ranges 
-in order, as well as the structure of the underlying splay tree 
-implementation.  It is provided for debugging purposes only.
-  Res CBSDescribe(CBS cbs, mps_lib_FILE *stream);
-
-.function.cbs.block.base: The CBSBlockBase function returns the base of the 
-range represented by the CBSBlock.  This function may not be called from the 
-delete callback when the block is being deleted entirely.
-  Addr CBSBlockBase(CBSBlock block);
-Note that the value of the base of a particular CBSBlock is not guaranteed to 
-remain constant across calls to CBSDelete and CBSInsert, regardless of whether 
-a callback is invoked.
-
-.function.cbs.block.limit: The CBSBlockLimit function returns the limit of the 
-range represented by the CBSBlock.  This function may not be called from the 
-delete callback when the block is being deleted entirely.
-  Addr CBSBlockLimit(CBSBlock block);
-Note that the value of the limit of a particular CBSBlock is not guaranteed to 
-remain constant across calls to CBSDelete and CBSInsert, regardless of whether 
-a callback is invoked.
-
-.function.cbs.block.size: The CBSBlockSize function returns the size of the 
-range represented by the CBSBlock.  This function may not be called from the 
-delete callback when the block is being deleted entirely.
-  Size CBSBlockSize(CBSBlock block);
-Note that the value of the size of a particular CBSBlock is not guaranteed to 
-remain constant across calls to CBSDelete and CBSInsert, regardless of whether 
-a callback is invoked.
-
-.function.cbs.block.describe: The CBSBlockDescribe function prints a textual 
-representation of the CBSBlock to the given stream.  It is provided for 
-debugging purposes only.
-  Res CBSBlockDescribe(CBSBlock block, mps_lib_FILE *stream);
-
-.function.cbs.find.first: The CBSFindFirst function locates the first block (in 
-address order) within the CBS of at least the specified size, and returns its 
-range.  If there are no such blocks, it returns FALSE.  It optionally deletes 
-the top, bottom, or all of the found range, depending on the findDelete 
-argument (this saves a separate call to CBSDelete, and uses the knowledge of 
-exactly where we found the range).
-  Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, CBS cbs, Size size, 
-CBSFindDelete findDelete);
-  enum {
-    CBSFindDeleteNONE,    /* don't delete after finding */
-    CBSFindDeleteLOW,     /* delete precise size from low end */
-    CBSFindDeleteHIGH,    /* delete precise size from high end */
-    CBSFindDeleteENTIRE   /* delete entire range */
-  };
-
-.function.cbs.find.last: The CBSFindLast function locates the last block (in 
-address order) within the CBS of at least the specified size, and returns its 
-range.  If there are no such blocks, it returns FALSE.  Like CBSFindFirst, it 
-optionally deletes the range.
-  Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, CBS cbs, Size size, 
-CBSFindDelete findDelete);
-
-.function.cbs.find.largest: The CBSFindLargest function locates the largest 
-block within the CBS, and returns its range.  If there are no blocks, it 
-returns FALSE.  Like CBSFindFirst, it optionally deletes the range (specifying 
-CBSFindDeleteLOW or CBSFindDeleteHIGH has the same effect as 
-CBSFindDeleteENTIRE).
-  Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, CBS cbs, 
-CBSFindDelete findDelete)
-
-
-Alignment
-
-.align: When mayUseInline is specified to permit inline data structures and 
-hence avoid losing memory in low memory situations, the alignments that the CBS 
-supports are constrained by three requirements:
-  - The smallest possible range (namely one that is the alignment in size) must 
-be large enough to contain a single void * pointer (see 
-.impl.low-mem.inline.grain);
-  - Any larger range (namely one that is at least twice the alignment in size) 
-must be large enough to contain two void * pointers (see 
-.impl.low-mem.inline.block);
-  - It must be valid on all platforms to access a void * pointer stored at the 
-start of an aligned range.
-
-All alignments that meet these requirements are aligned to sizeof(void *), so 
-we take that as the minimum alignment.
-
-
-IMPLEMENTATION
-
-
-.impl: Note that this section is concerned with describing various aspects of 
-the implementation.  It does not form part of the interface definition.
-
-
-Size Change Callback Protocol
-
-.impl.callback: The size change callback protocol concerns the mechanism for 
-informing the client of the appearance and disappearance of interesting 
-ranges.  The intention is that each range has an identity (represented by the 
-CBSBlock).  When blocks are split, the larger fragment retains the identity.  
-When blocks are merged, the new block has the identity of the larger fragment.
-
-.impl.callback.delete: Consider the case when the minimum size is <minSize>, 
-and CBSDelete is called to remove a range of size <middle>.  The two (possibly 
-non-existant) neighbouring ranges have (possibly zero) sizes <left> and 
-<right>.  <middle> is part of the CBSBlock <middleBlock>.
-
-.impl.callback.delete.delete: The delete callback will be called in this case 
-if and only if:
-  left + middle + right >= minSize  &&  left < minSize  &&  right < minSize
-That is, the combined range is interesting, but neither remaining fragment is.  
-It will be called with the following parameters:
-  block: middleBlock
-  oldSize: left + middle + right
-  newSize: left >= right ? left : right
- 
-.impl.callback.delete.new: The new callback will be called in this case if and 
-only if:
-  left >= minSize  &&  right >= minSize
-That is, both remaining fragments are interesting.  It will be called with the 
-following parameters:
-  block: a new block
-  oldSize: 0
-  newSize: left >= right ? right : left
-
-.impl.callback.delete.shrink: The shrink callback will be called in this case 
-if and only if:
-  left + middle + right >= minSize && (left >= minSize || right >= minSize)
-That is, at least one of the remaining fragments is still interesting.  It will 
-be called with the following parameters:
-  block: middleBlock
-  oldSize: left + middle + right
-  newSize: left >= right ? left : right
-
-.impl.callback.insert: Consider the case when the minimum size is <minSize>, 
-and CBSInsert is called to add a range of size <middle>.  The two (possibly 
-non-existant) neighbouring blocks are <leftBlock> and <rightBlock>, and have 
-(possibly zero) sizes <left> and <right>.
-
-.impl.callback.insert.delete: The delete callback will be called in this case 
-if and only if:
-  left >= minSize  &&  right >= minSize
-That is, both neighbours were interesting.  It will be called with the 
-following parameters:
-  block: left >= right ? rightBlock : leftBlock
-  oldSize: left >= right ? right : left
-  newSize: 0
-
-.impl.callback.insert.new: The new callback will be called in this case if and 
-only if:
-  left + middle + right >= minSize  &&  left < minSize  &&  right < minSize
-That is, the combined block is interesting, but neither neighbour was.  It will 
-be called with the following parameters:
-  block: left >= right ? leftBlock : rightBlock
-  oldSize: left >= right ? left : right
-  newSize: left + middle + right
-
-.impl.callback.insert.grow: The grow callback will be called in this case if 
-and only if:
-  left + middle + right >= minSize && (left >= minSize || right >= minSize)
-That is, at least one of the neighbours was interesting.  It will be called 
-with the following parameters:
-  block: left >= right ? leftBlock : rightBlock
-  oldSize: left >= right ? left : right
-  newSize: left + middle + right
-
-
-Splay Tree
-
-.impl.splay: The CBS is principally implemented using a splay tree (see 
-design.mps.splay).  Each splay tree node is embedded in a CBSBlock that 
-represents a semi-open address range.  The key passed for comparison is the 
-base of another range.
-
-.impl.splay.fast-find: CBSFindFirst and CBSFindLast use the update/refresh 
-facility of splay trees to store, in each CBSBlock, an accurate summary of the 
-maximum block size in the tree rooted at the corresponding splay node.  This 
-allows rapid location of the first or last suitable block, and very rapid 
-failure if there is no suitable block.
-
-.impl.find-largest: CBSFindLargest simply finds out the size of the largest 
-block in the CBS from the root of the tree (using SplayRoot), and does 
-SplayFindFirst for a block of that size.  This is O(log(n)) in the size of the 
-free list, so it's about the best you can do without maintaining a separate 
-priority queue, just to do CBSFindLargest.  Except when the emergency lists 
-(see .impl.low-mem) are in use, they are also searched.
-
-
-Low Memory Behaviour
-
-.impl.low-mem: Low memory situations cause problems when the CBS tries to 
-allocate a new CBSBlock structure for a new isolated range as a result of 
-either CBSInsert or CBSDelete, and there is insufficient memory to allocation 
-the CBSBlock structure:
-
-.impl.low-mem.no-inline: If mayUseInline is FALSE, then the range is not added 
-to the CBS, and the call to CBSInsert or CBSDelete returns ResMEMORY.
-
-.impl.low-mem.inline: If mayUseInline is TRUE:
-
-.impl.low-mem.inline.block: If the range is large enough to contain an inline 
-block descriptor consisting of two pointers, then it is kept on an emergency 
-block list.  The CBS will eagerly attempt to add this block back into the splay 
-tree during subsequent calls to CBSInsert and CBSDelete.  The CBS will also 
-keep its emergency block list in address order, and will coalesce this list 
-eagerly.  Some performance degradation will be seen when the emergency block 
-list is in use.  Ranges on this emergency block list will not be made available 
-to the CBS's client via callbacks.  CBSIterate* will not iterate over ranges on 
-this list.
-
-.impl.low-mem.inline.block.structure: The two pointers stored are to the next 
-such block (or NULL), and to the limit of the block, in that order.
-
-.impl.low-mem.inline.grain: Otherwise, the range must be large enough to 
-contain an inline grain descriptor consisting of one pointer, then it is kept 
-on an emergency grain list.  The CBS will eagerly attempt to add this grain 
-back into either the splay tree or the emergency block list during subsequent 
-calls to CBSInsert and CBSDelete.  The CBS will also keep its emergency grain 
-list in address order.  Some performance degradation will be seen when the 
-emergency grain list is in use.  Ranges on this emergency grain list will not 
-be made available to the CBS's client via callbacks.  CBSIterate* will not 
-iterate over ranges on this list.
-
-.impl.low-mem.inline.grain.structure: The pointer stored is to the next such 
-grain, or NULL.
-
-
-The CBS Block
-
-.impl.cbs.block: The block contains a base-limit pair and a splay tree node.  
-
-.impl.cbs.block.special: The base and limit may be equal if the block is 
-halfway through being deleted.
-
-.impl.cbs.block.special.just: This conflates values and status, but is 
-justified because block size is very important.
-
-
-TESTING
-
-.test: The following testing will be performed on this module:
-
-.test.cbstest: There is a stress test for this module in impl.c.cbstest.  This 
-allocates a large block of memory and then simulates the allocation and 
-deallocation of ranges within this block using both a CBS and a BT.  It makes 
-both valid and invalid requests, and compares the CBS response to the correct 
-behaviour as determined by the BT.  It also iterates the ranges in the CBS, 
-comparing them to the BT.  It also invokes the CBS describe method, but makes 
-no automatic test of the resulting output.  It does not currently test the 
-callbacks.
-
-.test.pool: Several pools (currently MV2 and MVFF) are implemented on top of a 
-CBS.  These pool are subject to testing in development, QA, and are/will be 
-heavily exercised by customers.
-
-
-NOTES FOR FUTURE DEVELOPMENT
-
-.future.not-splay: The initial implementation of CBSs is based on splay trees.  
-It could be revised to use any other data structure that meets the requirements 
-(especially .req.fast).
-
-.future.hybrid: It would be possible to attenuate the problem of .risk.overhead 
-(below) by using a single word bit set to represent the membership in a 
-(possibly aligned) word-width of grains.  This might be used for block sizes 
-less than a word-width of grains, converting them when they reach all free in 
-the bit set.  Note that this would make coalescence slightly less eager, by up 
-to (word-width - 1).
-
-
-RISKS
-
-.risk.overhead: Clients should note that the current implementation of CBSs has 
-a space overhead proportional to the number of isolated contiguous ranges.  [ 
-Four words per range. ]  If the CBS contains every other grain in an area, then 
-the overhead will be large compared to the size of that area.  [ Four words per 
-two grains. ]  See .future.hybrid for a suggestion to solve this problem.  An 
-alternative solution is to use CBSs only for managing long ranges.
----
-The following relates to a pending re-design and does not yet relate to any 
-working source version.  GavinM 1998-09-25
-
-The CBS system provides its services by combining the services provided by 
-three subsidiary CBS modules:
-
-  - CBSST -- Splay Tree: Based on out-of-line splay trees; must allocate to 
-insert isolated, which may therefore fail. 
-
-  - CBSBL -- Block List: Based on a singly-linked list of variable sized ranges 
-with inline descriptors; ranges must be at least large enough to store the 
-inline descriptor.
-
-  - CBSGL -- Grain List: Based on a singly-linked list of fixed size ranges 
-with inline descriptors; the ranges must be the alignment of the CBS.
-
-The three sub-modules have a lot in common.  Although their methods are not 
-invoked via a dispatcher, they have been given consistent interfaces, and 
-consistent internal appearance, to aid maintenance.
-
-Methods supported by sub-modules (not all sub-modules support all methods):
-
-  - MergeRange -- Finds any ranges in the specific CBS adjacent to the supplied 
-one.  If there are any, it extends the ranges, possibly deleting one of them.  
-This cannot fail, but should return FALSE if there is an intersection between 
-the supplied range and a range in the specific CBS.  
-
-  - InsertIsolatedRange -- Adds a range to the specific CBS that is not 
-adjacent to any range already in there.  Depending on the specific CBS, this 
-may be able to fail for allocation reasons, in which case it should return 
-FALSE.  It should AVER if the range is adjacent to or intersects with a range 
-already there.
-
-  - RemoveAdjacentRanges -- Finds and removes from the specific CBS any ranges 
-that are adjacent to the supplied range.  Should return FALSE if the supplied 
-range intersects with any ranges already there.
-
-  - DeleteRange -- Finds and deletes the supplied range from the specific CBS.  
-Returns a tri-state result:
-    - Success -- The range was successfully deleted.  This may have involved 
-the creation of a new range, which should be done via CBSInsertIsolatedRange.
-    - ProtocolError -- Either some non-trivial strict subset of the supplied 
-range was in the specific CBS, or a range adjacent to the supplied range was in 
-the specific CBS.  Either of these indicates a protocol error. 
-    - NoIntersection -- The supplied range was not found in the CBS.  This may 
-or not be a protocol error, depending on the invocation context.
-
-  - FindFirst -- Returns the first (in address order) range in the specific CBS 
-that is at least as large as the supplied size, or FALSE if there is no such 
-range.
-
-  - FindFirstBefore -- As FindFirst, but only finds ranges prior to the 
-supplied address.
-
-  - FindLast -- As FindFirst, but finds the last such range in address order.
-
-  - FindLastAfter -- FindLast's equivalent of FindFirstBefore.
-
-  - Init -- Initialise the control structure embedded in the CBS.
-
-  - Finish -- Finish the control structure embedded in the CBS.
-
-  - InlineDescriptorSize -- Returns the aligned size of the inline descriptor.
-
-  - Check -- Checks the control structure embedded in the CBS.
-
-The CBS supplies the following utilities:
-
-  - CBSAlignment -- Returns the alignment of the CBS.
-
-  - CBSMayUseInline -- Returns whether the CBS may use the memory in the ranges 
-stored.
-
-  - CBSInsertIsolatedRange -- Wrapper for CBS*InsertIsolatedRange.
- 
-Internally, the CBS* sub-modules each have an internal structure CBS*Block that 
-represents an isolated range within the module.  It supports the following 
-methods (for sub-module internal use):
-  - BlockBase -- Returns the base of the associated range;
-  - BlockLimit 
-  - BlockRange
-  - BlockSize
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/check/index.html b/mps/design/check/index.html deleted file mode 100644 index b64e7cae946..00000000000 --- a/mps/design/check/index.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - -Design of checking in MPS - - - - - - - -
-                       DESIGN OF CHECKING IN MPS
-                            design.mps.check
-                           incomplete design
-                           gavinm 1996-08-05
-
-
-INTRODUCTION:
-
-This documents the design of structure checking within the MPS
-
-
-IMPLEMENTATION:
-
-.level: There are three levels of checking:
-  .level.sig: The lowest level checks only that the structure has a valid 
-Signature (see design.mps.sig).
-  .level.shallow: Shallow checking checks all local fields (including 
-signature) and also checks the signatures of any parent or child structures.
-  .level.deep: Deep checking checks all local fields (including signatures), 
-the signatures of any parent structures, and does full recursive checking on 
-any child structures.
-  .level.control: control over the levels of checking is via the definition of 
-at most one of the macros TARGET_CHECK_SHALLOW (which if defined gives 
-.level.shallow), TARGET_CHECK_DEEP (which if defined gives .level.deep).  If 
-neither macro is defined then .level.sig is used.  These macros are not 
-intended to be manipulated directly by developers, they should use the 
-interface in impl.h.target.
-
-.order: Because deep checking (.level.deep) uses unchecked recursion, it is 
-important that child relationships are acyclic (.macro.down).
-
-.fun: Every abstract data type which is a structure pointer should have a 
-function <type>Check which takes a pointer of type <type> and returns a Bool.  
-It should check all fields in order, using one of the macros in .macro, or 
-document why not.
-
-.fun.omit: The only fields which should be omitted from a check function are 
-those for
-which there is no meaningful check (e.g. unlimited unsigned integer with no 
-relation to
-other fields).
-
-.fun.return: Although the function returns a Bool, if the assert handler 
-returns (or there is no assert handler), then this is taken to mean "ignore and 
-continue", and the check function hence returns TRUE.
-
-.macro: Checking is implemented by invoking four macros in impl .h.assert:
-  .macro.sig: CHECKS(type, val) checks the signature only, and should be called 
-precisely on type <type> and the received object pointer.
-  .macro.local: CHECKL(cond) checks a local field (depending on level (see 
-.level)), and should be called on each local field that is not an abstract data 
-type structure pointer itself (apart from the signature), with an appropriate 
-normally-true test condition.
-  .macro.up: CHECKU(type, val) checks a parent abstract data type structure 
-pointer, performing at most signature checks (depending on level (see 
-.level)).  It should be called with the parent type and pointer.
-  .macro.down: CHECKD(type, val) checks a child abstract data type structure 
-pointer, possibly invoking <type>Check (depending on level (see .level)).  It 
-should be called with the child type and pointer.
-
-.full-type: CHECKS, CHECKD, CHECKU, all operate only on fully fledged types.  
-This means the type has to provide a function Bool TypeCheck(Type type) where 
-Type is substituted for the name of the type (eg, PoolCheck), and the 
-expression obj->sig must be a valid value of type Sig whenever obj is a valid 
-value of type Type.
-
-.type.no-sig: This tag is to be referenced in implementations whenever the form 
-CHECKL(ThingCheck(thing)) is used instead of CHECK{U,D}(Thing, thing) because 
-Thing is not a fully fledged type (.full-type).
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/class-interface/index.html b/mps/design/class-interface/index.html deleted file mode 100644 index 27e3edc17ea..00000000000 --- a/mps/design/class-interface/index.html +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - -Design of the pool class interface - - - - - - - -
-                   DESIGN OF THE POOL CLASS INTERFACE
-                       design.mps.class-interface
-                           incomplete design
-                             drj 1996-04-17
-
-
-INTRODUCTION:
-
-This document describes the interface and protocols between the MPM and the 
-pool class implementations.  [This document should be merged into 
-design.mps.pool.  pekka 1999-07-20]
-
-
-Document History
-
-.hist.1: Richard started it.  drj has added comments about how accurate this 
-document is at 1997-08-19.
-
-
-ARCHITECTURE:
-
-Methods
-
-.methods: These methods are provided by pool classes as part of the PoolClass 
-object (see impl.h.mpmst.class).  They form the interface which allows the MPM 
-to treat pools in a uniform manner.
-
-The following description is based on the definition of the PoolClassStruct 
-(impl.h.mpmst.class).
-
-If a class is not required to provide a certain method then they should set the 
-appropriate PoolNo* method for that method.  It is not acceptable to use NULL. 
-[there are also some PoolTriv* methods -- drj 1997-08-19]
-
-.method.name: The name field should be a short, pithy, cryptic name for the 
-pool class. Examples are "AMC", "MV".
-
-The size field is the size of the pool instance structure.  For the Foo 
-PoolClass this can reasonably be expected to be sizeof(FooStruct).
-
-The offset field is the offset into the pool instance structure of the generic 
-PoolStruct.  Typically this field is called poolStruct, so something like 
-offsetof(FooStruct, poolStruct) is typical.  If possible, arrange for this to 
-be zero.
-
-The init field is the class's init method.  This method is called via the 
-generic function PoolInit, which is in turn called by PoolCreate.  The generic 
-function allocates the pool's structure (using the size and offset 
-information), initializes the PoolStruct (generic part) then calls the init 
-method to do any class-specific initialization.  Typically this means 
-initializing the fields in the class instance structure.  If init returns a 
-non-OK result code the instance structure will be deallocated and the code 
-returned to the caller of PoolInit or Create.  Note that the PoolStruct isn't 
-made fully valid until PoolInit returns.
-
-The finish field is the class's finish method.  This method is called via the 
-generic function PoolFinish, which is in turn called by PoolDestroy.  It is 
-expected to finalise the pool instance structure and release any resources 
-allocated to the pool, it is expected to release the memory associated with the 
-pool instance structure.  Note that the pool is valid when it is passed to 
-finish.  The PoolStruct (generic part) is finished off when the class's finish 
-method returns.
-
-The alloc field is the class's allocation method.  This method is called via 
-the generic function PoolAlloc.  It is expected to return a pointer to a fresh 
-(i.e., not overlapping with any other live object) object of the required 
-size.  Failure to allocate should be indicated by returning an appropriate 
-Error code, and in such a case, *pReturn should not be updated.  Classes are 
-not required to provide this method, but they should provide at least one of 
-alloc and bufferCreate.
-
-The free_ field is the class's free method.  This is intended primarily for 
-manual style pools.  this method is called via the generic function PoolFree.  
-The parameters to this method are required to correspond to a previous 
-allocation request (possibly via a buffer).  It is an assertion by the client 
-that the indicated object is no longer required and the resources associated 
-with it can be recycled.  Pools are not required to provide this method.
-
-The bufferInit field is the class's buffer initialization method.  It is called 
-by the generic function BufferCreate, which allocates the buffer descriptor and 
-initializes the generic fields.  The pool may optionally adjust these fields or 
-fill in extra values when bufferInit is called, but often pools set bufferInit 
-to PoolTrivBufferInit because they don't need to do any.  If bufferInit returns 
-a non-OK result code the buffer structure is deallocated and the code is 
-returned to the called of BufferCreate.  Note that the BufferStruct isn't fully 
-valid until BufferCreate returns.
-
-The bufferFinish field is the class's buffer finishing method.  It is called by 
-the the generic function BufferDestroy.  The pool is expected to detach the 
-buffer from any memory and prepare the buffer for destruction.  The class is 
-expected to release the resources associated with the buffer structure, and any 
-unreserved memory in the buffer may be recycled.  It is illegal for a buffer to 
-be destroyed when there are pending allocations on it (ie an allocation has 
-been reserved, but not committed) and this is checked in the generic function.  
-This method should be provided if and only if bufferCreate is provided. [there 
-is no bufferCreate -- drj 1997-08-19]
-
-The condemn field is used to condemn a pool.  This method is called via the 
-generic function PoolCondemn.  The class is expected to condemn a subset 
-(possible the whole set) of objects it manages and participate in a global 
-trace to determine liveness.  The class should register the refsig of the 
-condemned set with the trace using TraceCondemn.  The class should expect fix 
-requests (via the fix method below) during a global trace.  Classes are not 
-required to provide this method, it is expected that automatic style classes 
-will.  This interface is expected to change in the future. [condemn now takes 
-an action and a segment and should condemn the segment (turn it white) if it 
-corresponds to the interpretation of the action -- drj 1997-08-19  and is 
-called Whiten drj 1998-02-02]
-
-The mark field is used to mark an entire pool.  This method is called via the 
-generic function PoolMark.  The class should consider all of its objects, 
-except any set that has been condemned in this trace, to be marked, that is 
-ready for scanning.  The class should arrange that any appropriate invariants 
-are preserved possibly by the Protection interface.  Classes are not required 
-to provide this method, and not doing so indicates that all instances of this 
-class will have no fixable or traceable references in them.  [no longer 
-present, grey turns an entire segment grey -- drj 1997-08-19]
-
-The scan field is used to perform scanning.  This method is called via the 
-generic function PoolScan.  The class should scan the segment specified.  It 
-should scan all the known live (marked, ie those objects on which fix has been 
-called) on the segment and accumulate a summary of _all_ the objects on the 
-segment.  This means that mark and sweep pools may have to jump through hoops a 
-little bit (see design.mps.poolasm.summary for a pedagogical example).  Classes 
-are not required to provide this method, and not doing so indicates that all 
-instances of this class will have no fixable or traceable reference in them.  
-[scan method now takes an extra return parameter which classes should use to 
-indicate whether they scanned all objects in segment or not.  Classes should 
-return summary only of object they scanned.  Caller of this method (ie 
-TraceScan) is responsible for updating summaries correctly when not a total 
-scan.  Hence no jumping through hoops required.  drj 1998-01-30]
-
-The fix field is used to perform fixing.  This method is called via the generic 
-function TraceFix.  It indicates that the specified reference has been found 
-and the class should consider the object live.  There is provision for 
-adjusting the value of the reference (to allow for classes that move objects).  
-Classes are not required to provide this method, and not doing so indicates 
-that the class is not automatic style (ie it does not use global tracing to 
-determine liveness).
-
-The reclaim field is used to reclaim memory.  This method is called via the 
-generic function PoolReclaim.  It indicates that the trace has fixed all 
-references to reachable objects [actually it indicates that any remaining white 
-objects have now been proved unreachable, hence are dead].  The class should 
-consider objects that have been condemned and not fixed in this trace to be 
-dead and may reclaim the resources associated with them.  Classes are not 
-required to provide this method. [reclaim is now called on each segment -- drj 
-1997-08-19]
-
-The access field is used to indicate client access.  This method is called via 
-the generic functions SpaceAccess and PoolAccess.  It indicates that the client 
-has attempted to access the specified region, but has been denied and the 
-request trapped due to a protection state.  The class should perform any work 
-necessary to remove the protection whilst still preserving appropriate 
-invariants (typically this will be scanning work).  Classes are not required to 
-provide this method, and not doing
-so indicates they never protect any memory managed by the pool.  [access is no 
-longer present -- drj 1997-08-19]
-
-.method.act: Act is called when the MPM has decided to execute an action that 
-the class declared.  The Class should arrange execution of the associated work 
-(usually by beginning an incremental trace).
-
-.method.walk: Walk is used by the heap walker.  Walk is only required to be 
-implemented by classes which specify the AttrFMT attribute (formatted pools).  
-The Walk method should apply the passed in function (along with its closure 
-variables (which are also passed in) and the object format) to all _black_ 
-objects in the segment.  Padding objects may or may not be included in the walk 
-at the classes discretion, in any case in will be the responsibility of the 
-client to do something sensible with padding objects.  [what about broken 
-hearts?  drj 1998-01-30].
-
-The describe field is used to print out a description of a pool.  This method 
-is called via the generic function PoolDescribe.  The class should emit an 
-textual description of the pool's contents onto the specified stream.  Each 
-line should begin with 2 spaces.  Classes are not required to provide this 
-method.
-
-
-Events
-
-.replay: To work with the allocation replayer (see 
-design.mps.telemetry.replayer), the pool has to emit an event for each call to 
-an external interface, containing all the parameters passed by the user.  If a 
-new event type is required to carry this information, the replayer 
-(impl.c.eventrep) must then be extended to recreate the call.  .replay.Init: In 
-particular, the Init method should emit a PoolInit<foo> event with all the pool 
-parameters.
-
-
-
-TEXT:
-
-.alloc.size: The pool class implementation defines the meaning of the "size" 
-parameter to the alloc and free methods.  It may not actually correspond to a 
-number of bytes of memory.  .alloc.size.align: In particular, the class may 
-allow an unaligned size to be passed.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/collection/index.html b/mps/design/collection/index.html deleted file mode 100644 index eecfb2eb504..00000000000 --- a/mps/design/collection/index.html +++ /dev/null @@ -1,400 +0,0 @@ - - - - - - - - -The collection framework - - - - - - - -
-                        THE COLLECTION FRAMEWORK
-                         design.mps.collection
-                           incomplete design
-                            pekka 1998-03-20
-
-INTRODUCTION
-
-.intro: This document describes the Collection Framework.  It's a framework for 
-implementing garbage collection techniques and integrating them into a system 
-of collectors that all cooperate in recycling garbage.
-
-
-Document History
-
-.hist.0: Version 0 was a different document.
-
-.hist.1: Version 1 was a different document.
-
-.hist.2: Written in January and February 1998 by Pekka P. Pirinen on the basis 
-of the current implementation of the MPS, analysis.async-gc, [that note on the 
-independence of collections] and analysis.tracer.
-
-
-OVERVIEW
-
-.framework: MPS provides a framework that allows the integration of many 
-different types of GC strategies and provides many of the basic services that 
-those strategies use.  .framework.cover: The framework subsumes most major GC 
-strategies and allows many efficient techniques, like in-line allocation or 
-software barriers.
-
-.framework.overhead: The overhead due to cooperation is low. [But not 
-non-existent.  Can we say something useful about it?]
-
-.framework.benefits: The ability to combine collectors contributes 
-significantly to the flexibility of the system.  The reduction in code 
-duplication contributes to reliability and integrity.  The services of the 
-framework make it easier to write new MM strategies and collectors.
-
-.framework.mpm: The Collection Framework is merely a part of the structure of 
-the MPM.  See design.mps.architecture and design.mps.arch [Those two documents 
-should be combined into one.  Pekka 1998-01-15] for the big picture.  Other 
-notable components that the MPM manages to integrate into a single framework 
-are manually-managed memory [another missing document here?] and finalization 
-services (see design.mps.finalize).
-
-.see-also: This document assumes basic familiarity with the ideas of pool (see 
-design.mps.arch.pools) and segment (see design.mps.seg.over.*).
-
-
-COLLECTION ABSTRACTIONS
-
-Colours, scanning and fixing
-
-.state: The framework knows about the three colours of the tri-state 
-abstraction and free blocks.  Recording the state of each object is the 
-responsibility of the pool, but the framework gets told about changes in the 
-states and keeps track of colours in each segment.  Specifically, it records 
-whether a segment might contain white, grey and black objects wrt. each active 
-trace (see .tracer) [black not currently implemented -- Pekka 1998-01-04].  (A 
-segment might contain objects of all colours at once, or none.)  This 
-information is approximate, because when an object changes colour, or dies, it 
-usually is too expensive to determine if it was the last object of its former 
-colour.
-
-.state.transitions: The possible state transitions are as follows:
-
-free   ---alloc--> black (or grey) or white or none
-none   --condemn-> white
-none   --refine--> grey
-grey   ---scan---> black
-white  ----fix---> grey (or black)
-black  --revert--> grey
-white  --reclaim-> free
-black  --reclaim-> none
-
-.none-is-black: Outside of a trace, objects don't really have colour, but 
-technically, the colour is black.  Objects are only allocated grey or white 
-during a trace, and by the time the trace has finished, they are either dead or 
-black, like the other surviving objects.  We might then reuse the colour field 
-for another trace, so it's convenient to set the colour to black when 
-allocating outside a trace.  This means that refining the foundation 
-(analysis.tracer.phase.condemn.refine), actually turns black segments grey, 
-rather than vice versa, but the principle is the same.
-
-.scan-fix: "Scanning" an object means applying the "fix" function to all 
-references in that object.  Fixing is the generic name for the operation that 
-takes a reference to a white object and makes it non-white (usually grey, but 
-black is a possibility, and so is changing the reference as we do for weak 
-references).  Typical examples of fix methods are copying the object into 
-to-space or setting its mark bit.
-
-.cooperation: The separation of scanning and fixing is what allows different GC 
-techniques to cooperate.  The scanning is done by a method on the pool that the 
-scanned object resides in, and the fixing is done by a method on the pool that 
-the reference points to.
-
-.scan-all: Pools provide a method to scan all the grey objects in a segment.
-
-
-Reference sets
-
-.refsets: The cost of scanning can be significantly reduced by storing 
-remembered sets.  We have chosen a very compact and efficient implementation, 
-called reference sets, or refsets for short (see idea.remember 
-[design.mps.refset is empty!  Perhaps some of this should go there.  -- Pekka 
-1998-02-19]).  This makes the cost of maintaining them low, so we maintain them 
-for all references out of all scannable segments.
-
-.refsets.approx: You might describe refsets as summaries of all references out 
-of an area of memory, so they are only approximations of remembered sets.  When 
-a refset indicates that an interesting reference might be present in a segment, 
-we still have to scan the segment to find it.
-
-.refsets.scan: The refset information is collected during scanning.  The scan 
-state protocol provides a way for the pool and the format scan methods to 
-cooperate in this, and to pass this information to the tracer module which 
-checks it and updates the segment (see design.mps.scan [Actually, there's very 
-little doc there.  Pekka 1998-02-17]).
-
-.refsets.maintain: The MPS tries to maintain the refset information when it 
-moves or changes object.
-
-.refsets.pollution: Ambiguous references and pointers outside the arena will 
-introduce spurious zones into the refsets.  We put up with this to keep the 
-scanning costs down.  Consistency checks on refsets have to take this into 
-account.
-
-.refsets.write-barrier: A write-barrier are needed to keep the mutator from 
-invalidating the refsets when writing to a segment.  We need one on any 
-scannable segment whose refset is not a superset of the mutator's (and that the 
-mutator can see).  If we know what the mutator is writing and whether it's a 
-reference, we can just add that reference to the refset (figuring out whether 
-anything can be removed from the refset is too expensive).  If we don't know or 
-if we cannot afford to keep the barrier up, the framework can union the 
-mutator's refset to the segment's refset.
-
-.refset.mutator: The mutator's refset could be computed during root scanning in 
-the usual way, and then kept up to date by using a read-barrier.  It's not a 
-problem that the mutator can create new pointers out of nothing behind the 
-read-barrier, as they won't be real references.  However, this is probably not 
-cost-effective, since it would cause lots of barrier hits.  We'd need a 
-read-barrier on every scannable segment whose refset is not a subset of the 
-mutator's (and that the mutator can see).  So instead we approximate the 
-mutator's refset with the universal refset.
-
-
-THE TRACER
-
-.tracer: The tracer is an engine for implementing multiple garbage collection 
-processes.  Each process (called a "trace") proceeds independently of the 
-others through five phases as described in analysis.tracer.  The following 
-sections describe how the action of each phase fits into the framework.  See 
-design.mps.trace for details [No, there's not much there, either.  Possibly 
-some of this section should go there.  Pekka 1998-02-18]).
-
-.combine: The tracer can also combine several traces for some actions, like 
-scanning a segment or a root.  The methods the tracer calls to do the work get 
-an argument that tells them which traces they are expected to act for.  [extend 
-this@@@@]
-
-.trace.begin: Traces are started by external request, usually from a client 
-function or an action (see design.mps.action).
-
-.trace.progress: The tracer gets time slices from the arena to work on a given 
-trace [This is just a provisional arrangement, in lieu of real progress 
-control.  Pekka 1998-02-18].  In each slice, it selects a small amount of work 
-to do, based on the state of the trace, and does it, using facilities provided 
-by the pools.  .trace.scan: A typical unit of work is to scan a single 
-segment.  The tracer can choose to do this for multiple traces at once, 
-provided the segment is grey for more than one trace.
-
-.trace.barrier: Barrier hits might also cause a need to scan a segment (see 
-.hw-barriers.hit).  Again, the tracer can choose to combine traces, when it 
-does this.
-
-.mutator-colour: The framework keeps track of the colour of the mutator 
-separately for each trace.
-
-
-The Condemn Phase
-
-.phase.condemn: The agent that creates the trace (see .trace.begin) determines 
-the condemned set and colours it white.  The tracer then examines the refsets 
-on all scannable segments, and if it can deduce some segment cannot refer to 
-the white set, it's immediately coloured black, otherwise the pool is asked to 
-grey any objects in the segment that might need to be scanned (in copying 
-pools, this is typically the whole segment).
-
-.phase.condemn.zones: To get the maximum benefit from the refsets, we try to 
-arrange that the zones are a minimal superset (e.g., generations uniquely 
-occupy zones) and a maximal subset (there's nothing else in the zone) of the 
-condemned set.  This needs to be arranged at allocation time (or when copying 
-during collection, which is much like allocation) [soon, this will be handled 
-by segment loci, see design.mps.locus].
-
-.phase.condemn.mutator: At this point, the mutator might reference any objects, 
-i.e., it is grey.  Allocation can be in any colour, most commonly white [more 
-could be said about this].
-
-
-The Grey Mutator Phase
-
-.phase.grey-mutator: Grey segments are chosen according to some sort of 
-progress control and scanned by the pool to make them black.  Eventually, the 
-tracer will decide to flip or it runs out of grey segments, and proceeds to the 
-next phase.  [Currently, this phase has not been implemented; all traces flip 
-immediately after condemn.  Pekka 1998-02-18]
-
-.phase.grey-mutator.copy: At this stage, we don't want to copy condemned 
-objects, because we would need an additional barrier to keep the mutator's view 
-of the heap consistent (see analysis.async-gc.copied.pointers-and-new-copy).
-
-.phase.grey-mutator.ambig: This is a good time to get all ambiguous scanning 
-out of the way, because we usually can't do any after the flip [write a 
-detailed explanation of this some day] and because it doesn't cause any copying.
-
-
-The Flip Phase
-
-.phase.flip: The roots (see design.mps.root) are scanned.  This has to be an 
-atomic action as far as the mutator is concerned, so all threads are suspended 
-for the duration.
-
-.phase.flip.mutator: After this, the mutator is black: if we use a strong 
-barrier (analysis.async-gc.strong), this means it cannot refer to white 
-objects.  Allocation will be in black (could be grey as well, but there's no 
-point to it).
-
-
-The Black Mutator Phase
-
-.phase.black-mutator: Grey segments are chosen according to some sort of 
-progress control and scanned by the pool to make them black.  Eventually, the 
-tracer runs out of segments that are grey for this trace, and proceeds to the 
-next phase.
-
-.phase.black-mutator.copy: At this stage white objects can be relocated, 
-because the mutator cannot see them (as long as a strong barrier is used, as we 
-must do for a copying collection, see analysis.async-gc.copied.pointers).
-
-
-The Reclaim Phase
-
-.phase.reclaim: The tracer finds the remaining white segments and asks the pool 
-to reclaim any white objects in them.
-
-.phase.reclaim.barrier: Once a trace has started reclaiming objects, the others 
-shouldn't try to scan any objects that are white for it, because they might 
-have dangling pointers in them [xref doc yet to be written].  [Currently, we 
-reclaim atomically, but it could be incremental, or even overlapped with a new 
-trace on the same condemned set.  Pekka 1997-12-31]
-
-
-BARRIERS
-
-[An introduction and a discussion of general principles should go here.  This 
-is a completely undesigned area.]
-
-
-Hardware Barriers
-
-.hw-barriers: Hardware barrier services cannot, by their very nature, be 
-independently provided to each trace.  A segment is either protected or not, 
-and we have to set the protection on a segment if any trace needs a hardware 
-barrier on it.
-
-.hw-barriers.supported: The framework currently supports segment-oriented 
-Appel-Ellis-Li barriers (analysis.async-gc.barrier.appel-ellis-li), and 
-write-barriers for keeping the refsets up-to-date.  It would not be hard to add 
-Steele barriers (analysis.async-gc.barrier.steele.scalable).
-
-.hw-barriers.hit: When a barrier hit happens, the arena determines which 
-segment it was on.  The segment colour info is used to determine whether it had 
-trace barriers on it, and if so, the appropriate barrier action is performed, 
-using the methods of the owning pool.  If the segment was write-protected, its 
-refset is unioned with the refset of the mutator [in practice, RefSetUNIV].
-
-.hw-barriers.hit.multiple: Fortunately, if we get a barrier hit on a segment 
-with multiple trace barriers on it, we can scan it for all the traces that it 
-had a barrier for, see .combine.@@@@
-
-
-Software barriers
-
-[@@@@Have to say something about software barriers]
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/config/index.html b/mps/design/config/index.html deleted file mode 100644 index 829addd1a94..00000000000 --- a/mps/design/config/index.html +++ /dev/null @@ -1,537 +0,0 @@ - - - - - - - - -The design of MPS configuration - - - - - - - -
-                    THE DESIGN OF MPS CONFIGURATION
-                           design.mps.config
-                           incomplete design
-                           richard 1997-02-19
-
-INTRODUCTION
-
-.intro: This document describes how the MPS configuration is parameterized so 
-that it can target different architectures, operating systems, build 
-environments, varieties, and products.
-
-.bg: For background see [build system mail, configuration mail, 
-meeting.general.something]
-
-
-Document History
-
-.hist.0: Initial draft created by Richard Brooksby <richard> on 1997-02-19 
-based on discussions of configuration at meeting.general.1997-02-05.
-
-.hist.1: Various improvements and clarifications to the draft discussed between 
-Richard and Nick Barnes <nickb> at meeting.general.1997-02-19.
-
-
-REQUIREMENTS
-
-.req.arch: Allow architecture specific configurations of the MPS.
-
-.req.os: Allow operating system specific configurations of the MPS.
-
-.req.builder: Allow build environment (compiler, etc.) specific configurations 
-of the MPS.
-
-.req.prod: Allow product specific
-configurations of the MPS.  [This requirement has been retired on
-2012-09-03.  Client-specific customisation of the MPS will be handled by
-configuration management, while the MPS source remains generic, to
-reduce costs and increase reliability.  RB 2012-09-03]
-
-.req.var: Allow configurations with different amounts of instrumentation 
-(assertions, metering, etc.).
-
-.req.impact: The configuration system should have a minimal effect on 
-maintainability of the implementation.
-
-.req.port: The system should be easy to port across operating systems.
-
-.req.maint: Maintenance of the configuration and build system should not 
-consume much developer time.
-
-
-
-DEFINITIONS
-
-.def.platform: A platform is a combination of an architecture (.def.arch), an 
-operating system (.def.os), and a builder (.def.builder).  The set of supported 
-platforms is platform.*.
-
-.def.arch: An architecture is processor type with associated calling 
-conventions and other binary interface stuff.
-
-.def.os: An operating system is the interface to external resources.
-
-.def.builder: A builder is the tools (C compiler, etc.) used to make the target 
-(.def.target).
-
-.def.var: A variety is a combination of annotations such as assertions, 
-metering, etc.
-
-.def.prod: A product is the intended product into which the MPS will fit, e.g. 
-ScriptWorks, Dylan, etc.
-
-.def.target: The target is the result of the build.
-
-
-OVERVIEW
-
-- No automatically generated code.  Use only C compiler and linker.
-- Simple build function (design.mps.buildsys.????)
-- Avoid conditional code spaghetti in implementations.
-- Dependency on a particular configuration should be minimized and localized 
-when developing code.
-
-
-THE BUILD SYSTEM
-
-
-Abstract Build Function
-
-.build.fun: The MPS implementation assumes only a simple "build function" which 
-takes a set of sources, possibly in several languages, compiles them with a set 
-of predefined preprocessor symbols, and links the result with a set of 
-libraries to form the target:
-
-  target := build(<defs>, <srcs>, <libs>)
-
-.build.sep: Separate compilation and linkage can be seen as a memoization of 
-this function, and is not strictly necessary for the build.
-
-.build.cc: A consequence of this approach is that it should always be possible 
-to build a complete target with a single UNIX command line calling the compiler 
-driver (usually "cc" or "gcc"), for example:
-
-  cc -o main -DCONFIG_VAR_DF foo.c bar.c baz.s -lz
-
-.build.defs: The "defs" are the set of preprocessor macros which are to be 
-predefined when compiling the module sources.
-
-  CONFIG_VAR_<variety-code>
-
-The variety-codes are the letter code that appears after "variety." in the 
-tag of the relevant variety document (see variety.*) converted to upper case.  
-Currently (2012-09-03): RASH, HOT, COOL, DIAG, TI
-
-If no CONFIG_VAR is present, HOT is assumed in .
-
-.build.srcs: The "srcs" are the set of sources that must be compiled in order 
-to build the target.  The set of sources may vary depending on the 
-configuration.  For example, different sets of sources may be required to build 
-on different architectures.  [This is a dependency between the makefile (or whatever) 
-and the module configuration in config.h.]
-
-.build.libs: The "libs" are the set of libraries to which the compiled sources 
-must be linked in order to build the target.  For example, when building a test 
-program, it might include the ANSI C library and an operating system interface 
-library.
-
-
-File Structure
-
-.file.dir: Each product consists of a single directory (corresponding to a HOPE 
-compound) containing all the sources for the whole family of targets.  
-.file.base: The names of sources must be unique in the first eight characters 
-in order to conform to FAT filesystem naming restrictions.  .file.ext: The 
-extension may be up to three characters and directly indicates the source 
-language.
-
-[Where is the set of valid extensions and languages defined?]
-
-
-Modules and Naming
-
-.mod.unique: Each module has an identifier which is unique within the MPS.  
-.mod.impls: Each module has one or more implementations which may be in any 
-language supported by the relevant build environment.  .mod.primary: The 
-primary implementation of a module is written in target-independent ANSI C in a 
-source file with the same name as the module.  [This seems to be with an "an" 
-suffix now.  GavinM 1997-08-07]  .mod.secondary: The names of other 
-implementations should begin with the same prefix (the module id or a shortened 
-version of it) and be suffixed with on or more target parameter codes (defined 
-below).  In particular, the names of assembly language sources must include the 
-target parameter code for the relevant architecture.
-
-
-Build System Rationale
-
-.build.rat: This simple design makes it possible to build the MPS using many 
-different tools.  Microsoft Visual C++, Metrowerks Codewarrior, and other 
-graphical development tools do not support much in the way of generated 
-sources, staged building, or other such stuff.  The Visual C and Metrowerks 
-"project" files correspond closely to a closure of the build function 
-(.build.fun).  The simplicity of the build function has also made it easy to 
-set up builds using NMAKE (DOS), MPW (Macintosh), and to get the MPS up and 
-running on other platforms such as FreeBSD and Linux in very little time.  The 
-cost of maintaining the build systems on these various platforms is also 
-reduced to a minimum, allowing the MM Group to concentrate on primary 
-development.  The source code is kept simple and straightforward.  When looking 
-at MPS sources you can tell exactly what is going to be generated with very 
-little context.  The sources are not munged beyond the standard ANSI C 
-preprocessor.
-
-.build.port: The portability requirement (.req.port) implies that the build 
-system must use only standard tools that will be available on all conceivable 
-target platforms.  Experience of development environments on the Macintosh 
-(Metrowerks Codewarrior) and Windows NT (Visual C++) indicates that we cannot 
-assume much sophistication in the use of file structure by development 
-environments.  The best that we can hope for is the ability to combine a fixed 
-list of source files, libraries, and predefined preprocessor symbols into a 
-single target.
-
-.build.maint: The maintainability requirement (.req.maint) implies that we 
-don't spend time trying to develop a set of tools to support anything more 
-complicated than the simple build function described above.  The effort in 
-constructing and maintaining a portable system of this kind is considerable.  
-Such efforts have failed in EP.
-
-
-IMPLEMENTATION
-
-[ Now in impl.h.config, may symbols out of date.  GavinM 1997-08-07 ]
-
-.impl: The two implementation files impl.h.config and impl.h.mpstd can be seen 
-as preprocessor programs which "accept" build parameters and "emit" 
-configuration parameters (.fig.impl).  The build parameters are defined either 
-by the builder (in the case of target detection) or by the build function (in 
-the case of selecting the variety).
-
-.fig.impl:
-
-   build parameters                       configuration parameters
-
-   CONFIG_VAR_COOL     -->  config.h  --> ASSERT_AND_CHECK, TELEMETRY, etc.
-
-   _WIN32              -->  mpstd.h   --> MPS_OS_W3, etc.
-
-.impl.dep: No source code, other than the directives in impl.h.config and 
-impl.h.mpstd, should depend on any build parameters.  That is, identifiers 
-beginning "CONFIG_" should only appear in impl.h.config.  Code may depend on 
-configuration parameters in certain, limited ways, as defined below (.conf).
-
-
-Target Platform Detection
-
-.pf: The target platform is "detected" by the preprocessor directives in 
-impl.h.mpstd.
-.pf.form: This file consists of sets of directives of the form:
-
-  #elif <conjunction of builder predefinitions>
-  #define MPS_PF_<platform code>
-  #define MPS_OS_<operating system code>
-  #define MPS_ARCH_<architecture code>
-  #define MPS_BUILD_<builder code>
-  #define MPS_T_WORD           <word type>
-  #define MPS_WORD_SHIFT       <word shift>
-  #define MPS_PF_ALIGN         <minimum alignment>
-
-.pf.detect: The conjunction of builder predefinitions is a constant expression 
-which detects the target platform.  It is a logical AND of expressions which 
-look for preprocessor symbols defined by the build environment to indicate the 
-target.  These must be accompanied by a reference to the build tool 
-documentation from which the symbols came.  For example:
-
-  /* Visual C++ 2.0, Books Online, C/C++ Book, Preprocessor Reference, */
-  /* Chapter 1: The Preprocessor, Macros, Predefined 
-
-  #elif defined(_MSC_VER) && defined(_WIN32) && defined(_M_IX86)
-
-.pf.codes: The declarations of the platform, operating system, architecture, 
-and builder codes define preprocessor macros corresponding the the target 
-detected (.pfm.detect).  For example:
-
-  #define MPS_PF_W3I3MV
-  #define MPS_OS_W3
-  #define MPS_ARCH_I3
-  #define MPS_BUILD_MV
-
-.pf.word: The declaration of MPS_T_WORD defines the unsigned integral type 
-which corresponds, on the detected target, to the machine word.  It is used to 
-defined the MPS Word type (design.mps.type.word).  [Insert backwards ref 
-there.]  For example:
-
-  #define MPS_T_WORD      unsigned long
-
-.pf.word-width: The declaration of MPS_WORD_WIDTH defines the number of bits in 
-the type defined by MPS_T_WORD (.pf.word) on the target.  For example:
-
-  #define MPS_WORD_WIDTH  32
-
-.pf.word-shift: The declaration of MPS_WORD_SHIFT defines the log to the base 2 
-of MPS_WORD_WIDTH.  For example:
-
-  #define MPS_WORD_SHIFT  5
-
-.pf.pf-align: The declaration of MPS_PF_ALIGN defines the minimum alignment 
-which must be used for a memory block to permit any normal processor memory 
-access.  In other words, it is the maximum alignment required by the processor 
-for normal memory access.  For example:
-
-  #define MPS_PF_ALIGN    4
-
-
-Target Varieties
-
-.var: The target variety is handled by preprocessor directives in 
-impl.h.config.  .var.form: The file contains sets of directives of the form:
-
-  #elif defined(CONFIG_VAR_DF)
-  #define MPS_VAR_DF
-  #define ASSERT_MPSI
-  #define ASSERT_MPM
-  etc.
-
-.var.detect: The configured variety is one of the variety preprocessor 
-definitions passed to the build function (.build.defs), e.g. CONFIG_VAR_DF.  
-[These are decoupled so that it's possible to tell the difference between 
-overridden settings etc.  Explain.]
-
-.var.symbols: The directives should define whatever symbols are necessary to 
-control annotations.  These symbols parameterize other parts of the code, such 
-as the declaration of assertions, etc.  The symbols should all begin with the 
-prefix "MPS_VAR_".
-
-
-[Tidy this up:]
-Note, anything which can be configured, is configured, even if it's just 
-configured to "NONE" meaning nothing.  This makes sure that you can't choose 
-something by omission.  Where these symbols are used there will be a #error to 
-catch the unused case.
-Exception: To allow simple building of the MPS with "cc -c mps.c" we choose
-CONFIG_VAR_HOT by default.
-[This is a general principle which applies to other configuration stuff too.]
-
-
-SOURCE CODE CONFIGURATION
-
-.conf: This section describes how the configuration may affect the source code 
-of the MPS.
-
-.conf.limit: The form of dependency allowed is carefully limited to ensure that 
-code remains maintainable and portable (.req.impact).
-
-.conf.min: The dependency of code on configuration parameters should be kept to 
-a minimum in order to keep the system maintainable (.req.impact).
-
-
-Configuration Parameters
-
-.conf.params: The compilation of a module is parameterized by:
-
-  MPS_ARCH_<arch-code>
-  MPS_OS_<os-code>
-  MPS_BUILDER_<builder-code>
-  MPS_PF_<platform-code>
-
-
-Abstract and Concrete Module Interfaces
-
-Basic principle: the caller must not be affected by configuration of a module.  
-This reduces complexity and dependency of configuration.
-
-All callers use the same abstract interface.  Caller code does not change.
-
-Abstract interface includes:
-  - method definitions (logical function prototypes which may be macro methods)
-  - names of types
-  - names of constants
-  - names of structures and fields which form part of the interface, and 
-possibly their types, depending on the protocol defined
-  - the protocols
-
-The abstract interface to a module may not be altered by a configuration 
-parameter.  However, the concrete interface may vary.
-
-
-Configuring Module Implementations
-
-For example, this isn't allowed, because there is a change in the interface.
-
-  #if defined(PROT_FOO)
-  void ProtSpong(Foo foo, Bar bar);
-  #else
-  int ProtSpong(Bar bar, Foo foo);
-  #endif
-
-This example shows how:
-
-  #ifdef PROTECTION
-  void ProtSync(Space space);
-  /* more decls. */
-  #else /* PROTECTION not */
-  #define ProtSync(space) NOOP
-  /* more decls. */
-  #endif /* PROTECTION */
-
-or
-
-  #if defined(PROT_FOO)
-  typedef struct ProtStruct {
-    int foo;
-  } ProtStruct;
-  #define ProtSpong(prot)  X((prot)->foo)
-  #elif defined(PROT_BAR)
-  typedef struct ProtStruct {
-    float bar;
-  } ProtStruct;
-  #define ProtSpong(prot)  Y((prot)->bar)
-  #else
-  #error "No PROT_* configured."
-  #endif
-
-Configuration parameters may not be used to vary implementations in .c files.  
-For example, this sort of thing:
-
-  int map(void *base, size_t size)
-  {
-  #if defined(MPS_OS_W3)
-    VirtualAlloc(foo, bar, base, size);
-  #elif defined(MPS_OS_SU)
-    mmap(base, size, frob);
-  #else
-  #error "No implementation of map."
-  #endif
-  }
-
-This leads to extreme code spaghetti.  In effect, it's a "candy machine 
-interface" on source code.  This kind of thing should be done by having several 
-implementations of the same interface in separate source files.  If this leads 
-to duplication of code then that code should be placed in a separate, common 
-module.
-
-
-PROCEDURES
-
-[Adding an architecture, etc.]
-
-
-NOTES
-
-What about constants?
-
-To do:
-- Renaming of some stuff.
-- Introduce product selection.
-- Change makefiles.
-- Eliminate mpmconf.h by moving stuff to config.h.
-- Update files to refer to this design document.
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.2012-09-03RBUpdated for variety-reform branch, to remove untrue things, though the document could do with a rewrite.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/critical-path.txt b/mps/design/critical-path.txt deleted file mode 100644 index 9d48f02c7e5..00000000000 --- a/mps/design/critical-path.txt +++ /dev/null @@ -1,391 +0,0 @@ -The critical path through the MPS -================================= -Richard Brooksby, Ravenbrook Limited, 2012-09-07 - - -1. Introduction ---------------- -The critical path is a key concept in the design of the [Memory Pool -System](http://www.ravenbrook.com/project/mps/). Code on the critical -path is usually executed more than any other code in the process. A -change of just one instruction on the critical path can make as much as -a 1% difference in overall run-time. A lot of the design of the MPS is -arranged around making the critical path as short and fast as possible. -This document describes the critical path and explains some of that -design, with reference to more detailed documents. - - -2. What makes the critical path critical ----------------------------------------- -In order to determine which object can be recycled, the garbage -collector has to frequently examine a very large number of pointers in -the program's objects. It does this by [scanning][] memory, both -allocated objects and roots (such as the thread stacks). - -This means that the scanning functions must loop over pretty much *every -word in memory* sooner or later. The MPS takes great pains to avoid -scanning memory which does not need scanning, but to get good -performance, scanning must be highly optimised. - -What's more, the scanning functions apply an operation called "fix" to -every pointer (or potential pointer) that they find in the objects in -memory. Fixing also attempts to eliminate uninteresting pointers as -fast as possible, but it has to do some work on every object that is -being considered for recycling, and that can be a large proportion of -the objects in existence. The path through fixing must also be highly -optimised, especially in the early stages. - - -3. How the MPS avoids scanning and fixing ------------------------------------------ -This is just a brief overview of how the MPS is designed to reduce -unnecessary scanning and fixing. - -Firstly, the MPS must occasionally decide which objects to try to -recycle. It does this using various facts it knows about the objects, -primarily their age and whether they've survived previous attempts at -recycling them. It then ["condemns"][condemn] a large number of objects -at once, and each of these objects must be "preserved" by fixing -references to them. - -When the MPS condemns objects it chooses sets of objects in a small set -of "zones" in memory (preferably a single zone). The zone of an object -can be determined extremely quickly from its address, without looking at -the object or any other data structure. - -The MPS arranges that objects which will probably die at the same time -are in the same zones. - -The MPS allocates in "segments". Each segment is of the order of one -"tract" of memory (generally the same as the operating system page -size, usually 4KiB or 8KiB) but may be larger if there are large -objects inside. The MPS maintains a "summary" of the zones pointed to -by all the pointers in a segment from previous scans. - -So, once the MPS has decided what to condemn, it can quickly eliminate -all segments which definitely do not point to anything in those zones. -This avoids a large amount of scanning. It is an implementation of a -[remembered set][], though it is unlike that in most other GCs. - -In addition, the fix operation can quickly ignore pointers to the wrong -zones. This is called the "zone check" and is a [BIBOP][] technique. - -Even if a pointer passes the zone check, it may still not point to a -segment containing condemned objects. The next stage of the fix -operation is to look up the segment pointed to by the pointer and see if -it was condemned. This is a fast lookup. - -After that, each pool class must decide whether the pointer is to a -condemned object and do something to preserve it. This code is still -critical. The MPS will have tried to condemn objects that are dead, but -those objects are still likely to be in segments with other objects that -must be preserved. The pool class fix method must quickly distinguish -between them. - -Furthermore, many objects will be preserved at least once in their -lifetime, so even the code that preserves an object needs to be highly -efficient. (Programs in languages like ML might not preserve 95% of -their objects even once, but many other programs will preserve nearly -all of theirs many times.) - - -4. Where to find the critical path ----------------------------------- -Very briefly, the critical path consists of five stages: - - 1. The scanner, which iterates over pointers in objects. The MPS has - several internal scanners, but the most important ones will be format - scanners in client code registered through `mps_format_create` - functions. [Insert ref to manual explaining how to write a good - scanner.] - - 2. The first-stage fix, which filters out pointers inline in the - scanner. This is implemented in `MPS_FIX` macros in - [mps.h](..\code\mps.h). - - 3. The second-stage fix, which filters out pointers using general - information about segments. This is `_mps_fix2` in - [trace.c](..\code\trace.c). - - 4. The third-stage fix, which filters out pointers using pool-specific - information. Implemented in pool class functions called `AMCFix`, - `LOFix`, etc. in pool*.c. - - 5. Preserving the object, which might entail - - - [marking][] it to prevent it being recycled; and/or - - - [copying][] it and updating the original pointer (or just - updating the pointer, if the object has previously been - copied); and/or - - - adding it to a queue of objects to be scanned later, if it - contains pointers. - - Found in or near the pool class fix functions. - - -5. The format scanner ---------------------- -The critical path starts when a format scan method is called. That is a -call from the MPS to a client function of type `mps_fmt_scan_t` -registered with one of the `mps_format_create` functions in `mps.h`. - -Here is an example of part of a format scanner for scanning contiguous -runs of pointers, from `fmtdy.c`, the scanner for the [Open Dylan][] -runtime. - - static mps_res_t dylan_scan_contig(mps_ss_t mps_ss, - mps_addr_t *base, mps_addr_t *limit) - { - mps_res_t res; - mps_addr_t *p; /* reference cursor */ - mps_addr_t r; /* reference to be fixed */ - - MPS_SCAN_BEGIN(mps_ss) { - p = base; - loop: if(p >= limit) goto out; - r = *p++; - if(((mps_word_t)r&3) != 0) /* pointers tagged with 0 */ - goto loop; /* not a pointer */ - if(!MPS_FIX1(mps_ss, r)) goto loop; - res = MPS_FIX2(mps_ss, p-1); - if(res == MPS_RES_OK) goto loop; - return res; - out: assert(p == limit); - } MPS_SCAN_END(mps_ss); - - return MPS_RES_OK; - } - -(To help with understanding optimisation of this code, it's written in a -pseudo-assembler style, with one line roughly corresponding to each -instruction of an idealized intermediate code.) - -The MPS C interface provides macros to try to help optimise this code. -The `mps_ss` object is a "scan state" and contains data that is used to -eliminate uninteresting pointers now, and record information which will -be used to reduce scanning in future by maintaining the remembered set. - -The macros `MPS_SCAN_BEGIN` and `MPS_SCAN_END` load key data from the -scan state into local variables, and hopefully into processor registers. - This avoids aliasing values that we know won't change when calls are -made to `_mps_fix2` later, and so allows the compiler to keep the scan -loop small and avoid unnecessary memory references. - -This scanner knows that words not ending in 0b00 aren't pointers to -objects, so it eliminates them straight away. This is a kind of -[reference tag][] chosen by the client for its object representation. - -Next, the pointer is tested using `MPS_FIX1`. This performs fast tests -on the pointer without using any other memory. In particular, it does -the "zone check" described in section 3. If a pointer fails these -tests, it isn't interesting and can be skipped. It is very important to -proceed to the next pointer as fast as possible in this case. - -Having passed these tests, we need to fix the pointer using other data -in memory, and possibly call the MPS to preserve the object. This is -what `MPS_FIX2` does. The important distinction here is that `MPS_FIX2` -can fail and return an error code, which must be propagated without ado -by returning from the scanner. Separating `MPS_FIX1` from `MPS_FIX2` -helps keep the error handling code away from the tight loop with the -zone check. - -`MPS_FIX*`, the macro/inline part of the fix operation, are referred to -as "fix stage 1" or "the first stage fix" in other documents and comments. - -If these inline checks pass, `_mps_fix2` is called. If the MPS has been -built as a separate object file or library, this is where the function -call out of the scan loop happens. Since version 1.110 of the MPS, we -encourage clients to compile the MPS in the same translation unit as -their format code, so that the compiler can be intelligent about -inlining parts of `_mps_fix2` in the format scanner. The instructions -for doing this are in [Building the Memory Pool -System](..\manual\build.txt), part of the manual. - - -6. The second stage fix in the MPM ----------------------------------- -If a pointer gets past the first-stage fix filters, it is passed to -`_mps_fix2`, the "second stage fix". The second stage can filter out -yet more pointers using information about segments before it has to -consult the pool class. - -The first test applied is the "tract test". The MPS looks up the tract -containing the address in the tract table, which is a simple linear -table indexed by the address shifted -- a kind of flat page table. - -Note that if the arena has been extended, the tract table becomes less -simple, and this test may involved looking in more than one table. This -will cause a considerable slow-down in garbage collection scanning. -This is the reason that it's important to give a good estimate of the -amount of address space you will ever occupy with objects when you -initialize the arena. - -The pointer might not even be in the arena (and so not in any tract). -The first stage fix doesn't guarantee it. So we eliminate any pointers -not in the arena at this stage. - -If the pointer is in an allocated tract, then the table also contains a -cache of the "white set" -- the set of garbage collection traces for -which the tract is "interesting". If a tract isn't interesting, then we -know that it contains no condemned objects, and we can filter out the -pointer. - -If the tract is interesting them it's part of a segment containing -objects that have been condemned. The MPM can't know anything about the -internal layout of the segment, so at this point we dispatch to the -third stage fix. - -This dispatch is slightly subtle. We have a cache of the function to -dispatch to in the scan state, which has recently been looked at and is -with luck still in the processor cache. The reason there is a dispatch -at all is to allow for a fast changeover to emergency garbage -collection, or overriding of garbage collection with extra operations. -Those are beyond the scope of this document. Normally, `ss->fix` points -at `PoolFix`, and we rely somewhat on modern processor [branch target -prediction](https://en.wikipedia.org/wiki/Branch_target_predictor). -`PoolFix` is passed the pool, which is fetched from the tract table -entry, and that should be in the cache. - -`PoolFix` itself dispatches to the pool class. Normally, a dispatch to -a pool class would indirect through the pool class object. That would -be a double indirection from the tract, so instead we have a cache of -the pool's fix method in the pool object. This also allows a pool class -to vary its fix method per pool instance, a fact that is exploited to -optimize fixing in the AMC Pool depending on what kind of object format -it is managing. - - -7. The third stage fix in the pool class ----------------------------------------- -The final stage of fixing is entirely dependent on the pool class. The -MPM can't, in general, know how the objects within a pool are arranged, -so this is pool class specific code. - -Furthermore, the pool class must make decisions based on the "reference -rank" of the pointer. If a pointer is ambiguous (`RankAMBIG`) then it -can't be changed, so even a [copying] pool class can't move an object. -On the other hand, if the pointer is weak (`RankWEAK`) then the pool fix -method shouldn't preserve the object at all, even if it's condemned. - -The exact details of the logic that the pool fix must implement in -order to co-operate with the MPM and other pools are beyond the scope -of this document, which is about the critical path. Since it is on -the critical path, it's important that whatever the pool fix does is -simple and fast and returns to scanning as soon as possible. - -The first step, though, is to further filter out pointers which aren't -to objects, if that's its policy. Then, it may preserve the object, -according to its policy, and possibly ensure that the object gets -scanned at some point in the future, if it contains more pointers. - -If the object is moved to preserve it (for instance, if the pool class -implements a copying GC), or was already moved when fixing a previous -reference to it, the reference being fixed must be updated (this is -the origin of the term "fix"). - -As a simple example, `LOFix` is the pool fix method for the Leaf Only -pool class. It implements a [marking] garbage collector, and does not -have to worry about scanning preserved objects because it is used to -store objects that don't contain pointers. (It is used in compiler -run-time systems to store binary data such as character strings, thus -avoiding any scanning, decoding, or remembered set overhead for them.) - -`LOFix` filters any ambiguous pointers that aren't aligned, since they -can't point to objects it allocated. Otherwise it subtracts the segment -base address and shifts the result to get an index into a mark bit -table. If the object wasn't marked and the pointer is weak, then it -sets the pointer to zero, since the object is about to be recycled. -Otherwise, the mark bit is set, which preserves the object from -recycling when `LOReclaim` is called later on. `LOFix` illustrates -about the minimum and most efficient thing a pool fix method can do. - - -8. Other considerations ------------------------ -So far this document has described the ways in which the garbage -collector is designed around optimising the critical path. There are a -few other things that the MPS does that are important. - -Firstly, inlining is very important. The first stage fix is inlined -into the format scanner by being implemented in macros in -[mps.h](..\code\mps.h). And to get even better inlining, [we -recommend](..\manual\build.txt) that the whole MPS is compiled in a -single translation unit with the client format and that strong global -optimisation is applied. - -Secondly, we are very careful with code annotations on the critical -path. Assertions, statistics, and telemetry are all disabled on the -critical path in "hot" (production) builds. (In fact, it's because the -critical path is critical that we can afford to leave annotations -switched on elsewhere.) - -Last, but by no means least, we pay a lot of brainpower and measurement -to the critical path, and are very very careful about changing it. Code -review around the critical path is especially vigilant. - -And we write long documents about it. - - -A. References -------------- -[MMRef] "The Memory Management Reference"; . -[scanning]: http://www.memorymanagement.org/glossary/s.html#scan -[marking]: http://www.memorymanagement.org/glossary/m.html#marking -[copying]: http://www.memorymanagement.org/glossary/c.html#copying.garbage.collection -[condemn]: http://www.memorymanagement.org/glossary/c.html#condemned.set -[BIBOP]: http://www.memorymanagement.org/glossary/b.html#bibop -[remembered set]: http://www.memorymanagement.org/glossary/r.html#remembered.set -[reference tag]: http://www.memorymanagement.org/glossary/t.html#tag - -[Open Dylan] "Welcome to Open Dylan!"; . -[Open Dylan]: http://opendylan.org/ - - -B. Document History -------------------- -- 2012-09-07 RB First draft. - - -C. Copyright and License ------------------------- -Copyright (C) 2012 Ravenbrook Limited. All rights reserved. -. This is an open source license. Contact -Ravenbrook for commercial licensing options. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -3. Redistributions in any form must be accompanied by information on how -to obtain complete source code for this software and any -accompanying software that uses this software. The source code must -either be included in the distribution or be available for no more than -the cost of distribution plus a nominal fee, and must be freely -redistributable under reasonable conditions. For an executable file, -complete source code means the source code for all modules it contains. -It does not include source code for modules or files that typically -accompany the major components of the operating system on which the -executable file runs. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -$Id$ diff --git a/mps/design/cstyle/index.html b/mps/design/cstyle/index.html deleted file mode 100644 index 59f53f61257..00000000000 --- a/mps/design/cstyle/index.html +++ /dev/null @@ -1,614 +0,0 @@ - - - - - - - - -C Style -- Formatting - - - - - -
- -

-Ravenbrook / -Projects / -Memory Pool System -

- -

Memory Pool System Project

- -
- - -

C Style -- Formatting

- -
-MPS Staff, -Ravenbrook Limited, -1995-08-07 -
- -
- -

1. Introduction

- -

-.scope: This document describes the Ravenbrook conventions for the general format -of C source code in the MPS. -

- -

-.readership: This document is intended for anyone working on or with the C -source code. -

- - - -

2. General Formatting Conventions

- -

Line Width

- -

-.width: Lines should be no wider than 72 characters. .width.why: Many -people use 80 column terminal windows so that multiple windows can be -placed side by side. Restricting lines to 72 characters allows line -numbering to be used (in vi for example) and also allows diffs to be -displayed without overflowing the terminal. -

- - -

White Space

- -

-.space.notab: No tab characters should appear in the source files. Ordinary -spaces should be used to indent and format the sources. -.space.notab.why: Tab characters are -displayed differently on different platforms, and sometimes translated back and -forth, destroying layout information. -

- -

-.space.punct: There should always be whitespace after commas and semicolons and -similar punctuation. -

- -

-.space.op: Put white space around operators in expressions, except when -removing it would make the expression clearer by binding certain -sub-expressions more tightly. For example: -

- -
-  foo = x + y*z;
-
- -

-.space.control.not: No space between the keywords if, -switch, while, for and the following paren. -

- -

-.space.function.not: No space between a function name and the -following paren beginning its argument list. -

- - - -

Sections and Paragraphs

- -

-.section: Source files can be thought of as breaking down into "sections" and -"paragraphs". A section might be the leader comment of a file, the imports, or -a set of declarations which are related. -

- -

-.section.space: Precede sections by two blank lines (except the first one in -the file, which should be the leader comment in any case). -

- -

-.section.comment: Each section should start with a banner comment (see -.comment.banner) describing what the section contains. -

- -

-.para: Within sections, code often breaks down into natural units called -"paragraphs". A paragraph might be a set of strongly related declarations -(Init and Finish, for example), or a few lines of code which it makes sense to -consider together (the assignment of fields into a structure, for example). -

- -

-.para.space: Precede paragraphs by a single blank line. -

- - -

Statements

- -

-.statement.one: Generally only have at most one statement per line. In -particular the following are deprecated: -

- -
-  if(thing) return;  
-
-  a=0; b=0;
-
-  case 0: f = inRampMode ? AMCGen0RampmodeFrequency : AMCGen0Frequency;
-
- -

-.statement.one.why: Debuggers can often only place breakpoints on lines, not -expressions or statements within a line. The "if(thing) return;" is a -particularly important case, if thing is a reasonably rare return condition -then you might want to breakpoint it in a debugger session. Annoying because -"if(thing) return;" is quite compact and pleasing otherwise. -

- - -

Indentation

- -

-.indent: Indent the body of a block by two spaces. -For formatting purposes, the "body of a block" means: -

- -
    -
  • statements between braces,
  • -
  • a single statement following a lone if;
  • -
  • statements in a case-clause; see .switch.
  • -
- -

-(.indent.logical: The aim is to group what we think of as logical -blocks, even though they may not exactly match how "block" is used -in the definition of C syntax). -

- -

-Some examples: -

- -
-  if(res != ResOK) {
-    SegFinish(&span->segStruct);
-    PoolFreeP(MV->spanPool, span, sizeof(SpanStruct));
-    return res;
-  }
-
-  if(res != ResOK)
-    goto error;
-
-  if(j == block->base) {
-    if(j+step == block->limit) {
-      if(block->thing)
-        putc('@', stream);
-    }
-  } else if(j+step == block->limit) {
-    putc(']', stream);
-    pop_bracket();
-  } else {
-    putc('.', stream);
-  }
-
-  case 'A': {
-    c = 'A';
-    p += 1;
-    break;
-  }
-
- -

-.indent.goto-label: Place each goto-label on a line of its own, -outdented to the same level as the surrounding block. Then indent -the non-label part of the statement normally. -

- -
-  result foo(void)
-  {
-    statement();
-    if(error)
-      goto foo;
-    statement();
-    return OK;
-
-  foo:
-    unwind();
-    return ERROR;
-  }
-
- -

-.indent.case-label.not: Do not outdent case- and default-labels in a -switch statement. See .switch. -

- -

-.indent.cont: If an expression or statement won't fit on a single line, -indent the continuation lines by two spaces, apart from the following -exception: -

- -

-.indent.cont.parens: if you break a statement inside a parameter list -or other parenthesized expression, indent so that the continuation -lines up just after the open parenthesis. For example: -

-
-  PoolClassInit(&PoolClassMVStruct,
-                "MV", init, finish, allocP, freeP,
-                NULL, NULL, describe, isValid);
-
- -

-.indent.cont.expr: Note that when breaking an expression it is clearer -to place the operator at the start of the continuation line: -

- -
-  CHECKL(AddrAdd((Addr)chunk->pageTableMapped,
-                 BTSize(chunk->pageTablePages))
-         <= AddrAdd(chunk->base, chunk->ullageSize));
-
- -

-This is particularly useful in long conditional expressions that use -&& and ||. For example: -

- -
-  } while(trace->state != TraceFINISHED
-          && (trace->emergency || traceWorkClock(trace) < pollEnd));
-
- -

-.indent.hint: -Usually, it is possible to determine the correct indentation for a line -by looking to see if the previous line ends with a semicolon. If it -does, indent to the same amount, otherwise indent by two more spaces. -The main exceptions are lines starting with a close brace, goto-labels, -and line-breaks between parentheses. -

- - -

Positioning of Braces

- -

-.brace.otb: Use the "One True Brace" (or OTB) style. -This places the open brace after the control -word or expression, separated by a space, and when there is an else, -places that after the close brace. For example: -

- -
-  if(isBase) {
-    new->base = limit;
-    new->limit = block->limit;
-    block->limit = base;
-    new->next = block->next;
-    block->next = new;
-  } else {
-    new->base = block->base;
-    new->limit = base;
-    block->base = limit;
-    new->next = block;
-    *prev = new;
-  }
-
- -

-The same applies to struct, enum, union. -

- -

-.brace.otb.function.not: OTB is never used for function definitions. -

- -

-.brace.always: Braces are always required after -if, else, switch, -while, do, and for. -

- -

-.brace.always.except: Except that a lone if with no -else is allowed to drop its braces when its body is a single -simple statement. Typically this will be a goto or an -assignment. For example: -

- -
-  if(res != ResOK)
-    goto failStart;
-
- -

-Note in particular that an if with an else must have -braces on both paths. -

- - -

Switch Statements

- -

-.switch: format switch statements like this: -

- -
-  switch(action) {
-    case WIBBLE:
-    case WOBBLE: {
-      int angle;
-      err = move(plate, action, &angle);
-      break;
-    }
-    case QUIESCENT: {
-      err = 0;
-      break;
-    }
-    default: {
-      NOTREACHED;
-      break;
-    }
-  }
-
- -

-The component rules that result in this style are: -

- -

-.switch.two-levels: The switch statement as a whole is a block, and -(for formatting purposes) each case- or default-label starts a nested -block within that. Always use two levels. Do not -try to 'save a level' by outdenting case-labels: it's an anachronism -from when BSD used 8-column indents, and it causes havoc with brace -positioning. -

- -

-.switch.brace: Put braces around every case-clause body. Put the open -brace on the same line as the last case-label (following .brace.otb). Put -the close brace on a line on its own. -

- -

-.switch.break: The last line of every case-clause body, before the -close brace, must be an unconditional jump statement (usually -break, but may be goto, -continue, or return), or if a fall-through -is intended, the comment /* fall-through */. (Note: if -the unconditional jump should never be taken, because of previous -conditional jumps, use NOTREACHED on the line before it). -This rule is to prevent accidental fall-throughs, even if someone makes a editing mistake that causes a conditional jump to be missed. -

- -

-(.switch.break.outside.not: Do not put the break outside the -case-clause braces: there is no need. Placing it on the last line of -the case-clause body is less weird and equally clear.) -

- -

-.switch.default: It is usually a good idea to have a default-clause, -even if all it contains is NOTREACHED and -break. -

- -

-.switch.new-rules: The above rules are simple, consistent, and not -onerous. But they are also new, so existing MPS source code may not -yet follow them. -

- -

-.switch.horrors: There are currently around 5 different formatting -styles for switch statements in MPS source code: this is madness. -Variation is mostly caused by inventive violations of -.switch.two-levels (either case-label outdenting, or something worse: -see root.c), compounded by inventive violations of OTB for the braces -around the case-clause. The following transgressions are deprecated: -

- -
-  switch(action) {
-  case WOBBLE: {   /* BAD: open brace on outdented case-label line! */
-    ...
-  }  /* BAD: outdented close brace! */
-
-  } break;  /* BAD: break sharing line with close brace! */
-
- - -

Formatting Comments

- -

-.comment: There are three types of comments: banners, paragraph comments, and -columnar comments. -

- -

-.comment.banner: Banner comments come at the start of sections. A banner -comment consists of a heading usually composed of a symbol, an em-dash (--) and -an short explanation, followed by English text which is formatted using -conventional text documentation guidelines (see guide.text). The open and -close comment tokens ("/*" and "*/") are placed at the top and bottom of a -column of asterisks. The text is separated from the asterisks by one space. -Place a blank line between the banner comment and the section it comments. For -example: -

- -
-/* BlockStruct --  Block descriptor
- *
- * The pool maintains a descriptor structure for each 
- * contiguous allocated block of memory it manages.  
- * The descriptor is on a simple linked-list of such 
- * descriptors, which is in ascending order of address.
- */
-
-typedef struct BlockStruct {
-
- -

-.comment.para: Paragraph comments come at the start of paragraphs in the code. -A paragraph comment consists of formatted English text, with each line wrapped -by the open and close comment tokens ("/*" and "*/"). (This avoids problems -when cutting and pasting comments.) For example: -

- -
-  /* If the freed area is in the base sentinel then insert */
-  /* the new descriptor after it, otherwise insert before. */
-  if(isBase) {
-
- -

-.comment.para.precede: Paragraph comments, even one-liners, precede the -code to which they apply. -

- -

-.comment.column: Columnar comments appear in a column to the right of the -code. They should be used sparingly, since they clutter the code and make it -hard to edit. Use them on variable declarations and structure, union, or enum -declarations. They should start at least at column 32 (counting from 0, -that is, on a tab-stop), and should be terse -descriptive text. Abandon English sentence structure if this makes the comment -clearer. Don't write more than one line. Here's an example: -

- -
-  typedef struct PoolMVStruct
-  {
-    Pool blockPool;           /* for block descriptors */
-    Pool spanPool;            /* for span descriptors */
-    size_t extendBy;          /* size to extend pool by */
-    size_t avgSize;           /* estimate of allocation size */
-    size_t maxSize;           /* estimate of maximum size */
-    Addr space;               /* total free space in pool */
-    Addr lost;                /* lost when free can't allocate */
-    struct SpanStruct *spans; /* span chain */
-  } PoolMVStruct;
-
- -

Macros

- -

-.macro.careful: Macros in C are a real horror bag, be extra careful. -There's lots that could go here, but proper coverage probably -deserves a separate document. Which isn't written yet. -

- -

-.macro.general: -Do try and follow the other formatting conventions for code -in macro definitions. -

- -

-.macro.backslash: -Backslashes used for continuation lines in macro definitions should be -put on the right somewhere where they will be less in the way. Example: -

- -
-#define RAMP_RELATION(X)                       \
-  X(RampOUTSIDE,        "outside ramp")        \
-  X(RampBEGIN,          "begin ramp")          \
-  X(RampRAMPING,        "ramping")             \
-  X(RampFINISH,         "finish ramp")         \
-  X(RampCOLLECTING,     "collecting ramp")
-
- - -

B. History

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2007-06-04DRJAdopted from -//info.ravenbrook.com/project/mps/doc/2002-06-18/obsolete-mminfo/mminfo/guide/impl/c/format/index.txt -and edited.
2007-06-04DRJChanged .width from 80 to 72. Banned space between "if" and "(". -Required braces on almost everything. Clarified that paragraph comments -precede the code. -
2007-06-13RHSKRemoved .brace.block, because MPS source always uses .brace.otb. -Remove .indent.elseif because it is obvious (ahem) and showing an -example is sufficient. New rules for .switch.*: current MPS practice -is a mess, so lay down a neat new law. -
2007-06-27RHSKAdded .space.function.not. -
2007-07-17DRJAdded .macro.*
- -

C. Copyright and License

- -

This document is copyright © 2002-2005, 2007 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- -
- -

$Id: //info.ravenbrook.com/project/mps/master/index.html#8 $

- -

-Ravenbrook / -Projects / -Memory Pool System -

- -
- - - - diff --git a/mps/design/diag/index.html b/mps/design/diag/index.html deleted file mode 100644 index 723e77d180a..00000000000 --- a/mps/design/diag/index.html +++ /dev/null @@ -1,482 +0,0 @@ - - - - - - - - -Diagnostic feedback - - - - - - - -

-This document contains a guide to MPS -diagnostic feedback, followed by the historical -initial design. -References, History, Copyright and License are -at the end. -

- -

Readership: any MPS developer. Not confidential.

- -
- -

Guide

- - -

Introduction

- -

-Diagnostic feedback is information created by the MPS diagnostic -system for the purpose of helping MPS programmers -and client-code programmers. -

- -

-Such a piece of information is called "a diagnostic". -(See also Parts of the -MPS diagnostic system, below). -

- -

-A diagnostic is not intended to be end-user readable (or visible), -or machine-parseable. -A diagnostic is not intended to be stable from one release to the -next: it may be modified or removed at any time. -

- -

-MPS diagnostic feedback code must do these things: -

-
    -
  1. calculate, store, and propagate data;
  2. -
  3. collate, synthesise, and format it into a - human-useful diagnostic;
  4. -
  5. control (eg. filter) output of diagnostics; -
  6. -
  7. use a channel to get the diagnostic out.
  8. -
- -

-Note: the knowledge/code/logic for constructing the -human-useful message is kept inside normal MPS -source code. This means it is always in-sync with changes -to the MPS. This also means that any external utilities used -to display the messages do not need to understand, or keep in -sync with, the details of what's going inside the MPS. -

- - -

How to see some MPS diagnostic output

- -

-To run the MPS and get diagnostic output from it: -

-
    -
  • Use a variety with diagnostics - compiled-in. Currently, that means - variety.di. See config.h.
  • -
  • Check that the diagnostics you require are generated, - by looking in MPS source for invocations of the appropriate - macro (eg. DIAG_SINGLEF()).
  • -
  • Check that the diagnostics you require will be output, - by looking at the diagnostic filter rules in diag.c.
  • -
  • Run the MPS and client in an environment that supports the - channel used (eg. at a command-line if using WriteF).
  • -
- - -

What is a diagnostic?

- -

A diagnostic has three parts:

-
    -
  • a trigger condition, that causes this diagnostic to be - emitted;
  • -
  • a text tag (eg "TraceStart") which is the name of this - diagnostic; and
  • -
  • a paragraph of human-useful text.
  • -
- -

A diagnostic is emitted by the MPS at a certain -point in time when a certain event happens.

- -

Diagnostics are not nested. Every diagnostic must have a tag. -Each diagnostic should have a unique tag (uniqueness is just -to help the humans; the diagnostic system does not care).

- -

The paragraph of text can be many lines long. It usually -explains what event caused the diagnostic to be emitted, and -commonly also includes the output of some <object>Describe() -methods for various relevant objects. (For example, the TraceStart -diagnostic might call, and include the output generated by, the -TraceDescribe() method).

- - -

How do I control (filter) which diagnostics I see?

- -

All diagnostics are emitted and then filtered according -to the "diagnostic filter rules".

- -

The first level of control is filtering by tag. (For example, -only show TraceStart diagnostics).

- -

The second level of control is filtering by paragraph content. -(For example, only show TraceStart diagnostics where the trace is -started because a nursery generation is full).

- -

The third level of control is filtering by line content. -(For example, only show lines containing the word "whiteSet").

- -

See diag.c for details.

- -

Note: the entire filtering mechanism can be turned -off, so that diagnostics go immediately to mps_lib_stdout, -with no buffering or filtering See diag.c#.filter-disable.

- - - -

How to write a diagnostic

- - -

Improve stateless Describe methods where possible

- -

Where possible, don't put clever code into an event-triggered -diagnostic: put it into a stateless <object>Describe() -method instead, and then call that method when emitting your diagnostic.

- -

For example:

-
FooDescribe(Foo foo, mps_lib_FILE *stream)
-{
-  /* show value of new "quux" field */
-  WriteF(stream, "Foo: $P { quux: $U }\n", foo, foo->quux);
-}
-
-FooWibble(Foo foo)
-{
-  ...
-  DIAG_FIRSTF(( "FooWibble", "Wibbling foo $P", foo, NULL));
-  DIAG( FooDescribe(foo, DIAG_STREAM); );
-  DIAG_END("FooWibble");
-  ...
-}  
-
- -

This is much better, because other people can use your -human-useful output in their diagnostics, or 'live' in a -debugger.

- - -

How to use DIAG_*F output macros

- -

For a simple diagnostic, use DIAG_SINGLEF. This begins the tag, -puts text into the paragraph, and ends the tag immediately.

- -

For a more complex diagnostic, the first call must be DIAG_FIRSTF, -which begins a diag tag.

- -

While a tag is current, you can add text to the diagnostic's -paragraph using DIAG_MOREF, and WriteF( DIAG_STREAM, ... ).

- -

(Note: DIAG_STREAM is not a real standard C library -stream. If you want stream-level access, you may use Stream_fputc() -and Stream_fputs().)

- -

End the tag by calling DIAG_END.

- - -

Compile away in non-diag varieties; no side effects

- -

Wrap non-output code with the DIAG() and DIAG_DECL() macros, to -make sure that non-diag varieties do not execute -diagnostic-generating code.

- -

For complex diagnostic-generating code, it may be cleaner to move -it into a separate local function. Put "_diag" on the end of the -function name (eg. "TraceStart_diag()").

- -

Obviously, diagnostic-generating code must have no side effects. -

- - -

Choosing tags

- -

Tags should be valid C identifiers. Unless you know of a good -reason why not. (Not currently checked).

- -

There's no formal scheme for tag naming, but make it helpful and -— informally — hierarchical, eg. TraceBegin, -TraceStart, TraceEnd, etc. (not BeginTrace, EndTrace, ...).

- - -

Writing good paragraph text

- -

IMPORTANT: Make your diagnostics easy to understand! -Other people will read your diagnostics! -Make them clear and helpful. -Do not make them terse and cryptic. -If you use symbols, print a key in the diagnostic. (If you don't -want to see this the screen clutter, then you can always add a -filter rule to your personal rule set to filter it out).

- - -

Maintaining helpful filter rules

- -

If you add a 'noisy' diagnostic, add a rule to the default -ruleset to turn it off.

- - -

How the MPS diagnostic system works

- - -

Channels

- -

The recommended channel is WriteF to stdout.

- -

-Other possible of future channels might be: -

-
    -
  • printf;
  • -
  • a new type (yet to be defined) of mps_message;
  • -
  • squirt them into the telemetry-log-events system;
  • -
  • telnet.
  • -
- -

-Currently, only printf and WriteF are supported. -See the DIAG_WITH_ macros in mpm.h. -

- -

-You can also use a debugger to call <type>Describe() methods -directly, from within the debugger. -

- -

-Note: it is unfortunate that choice of channel may (for some -channels) also dictate the form of the code that synthesises the -message. (For example, WriteF-style parameter-expansion is not -possible when using the printf channel, because there is no way -to get WriteF to produce its output into a string). This is just -a technical hitch; logically, the code that synthesises a -diagnostic message should not care which channel will be used to -transmit it out of the MPS. -

- - -

Parts of the MPS diagnostic -system

- -

-The following facilities are considered part of the MPS diagnostic -system: -

-
    -
  • the <type>Describe() methods.
  • -
  • the DIAG* macros (DIAG, DIAG_DECL, DIAG_*F, etc); -
  • -
  • the STATISTIC macros (see mpm.h);
  • -
  • the METER macros and meter subsystem;
  • -
- - - - -

-The MPS diagnostic system is separate from the following other MPS -systems: -

-
    -
  • The telemetry-log-events system - (which emits much more data, - in a less human-readable form, requires MPS-aware external - tools, and is more stable from release to release). - In non-diagnostic telemetry varieties, the telemetry-log-events - system - emits events that log all normal MPS actions. In diagnostic - telemetry varieties, it may emit additional events containing - diagnostic information. - Additionally, the telemetry-log-events stream - might in future be available as a channel for emitting - human-readable text diagnostics. - See also design/telemetry. -
  • -
  • The MPS message system - (which is present in all varieties, and - manages asynchronous communication from the MPS to the client - program). However, the MPS message system might in future also - be available as a channel for emitting diagnostics. - See also design/message. -
  • -
- - -
- -

Initial Design

- - -

-See http://info.ravenbrook.com/mail/2007/04/13/13-07-45/0.txt: -"diagnostic feedback from the MPS" by RHSK. -

- -

-Diverse types of diagnostic feedback: -http://info.ravenbrook.com/mail/2007/04/18/10-58-49/0.txt. -

- -

-RHSK 2007-06-28 -

-

-It must be possible to add, modify, or remove diagnostics to affect -diagnostic varieties, without a substantial secondary effect -on non-diagnostic varieties. It is not a requirement that there -be zero effect. -

- -

-This means: -

-
    -
  • for actual output, you must use appropriate DIAG macros - (which compile away to nothing in non-diagnostic varieties); -
  • -
  • for propagating and synthesising data, use appropriate - DIAG macros where it is reasonably clean to do so, such as for - local variables and statements used only for diagnostic output; -
  • -
  • where it is clearer, and without substantial secondary effect, - to include code (such as additional function parameters) in - all varieties, that's okay.
  • -
- -

Note: the MPS diagnostic feedback system was initially developed in -mps/branch/2007-04-18/diag, mps/branch/2007-07-19/gcdiag, and -mps/branch/2007-08-07/diagtag.

- -
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
2007-06-28RHSKCreate.
2007-06-28RHSKTelemetry-log-events system is a possible channel.
2007-06-29RHSKFeedback (not output), each "a diagnostic". - Parts of the system; related systems. Link to initial design - email. -
2007-08-14RHSK(Diag Filtering). Expand section: How to see some MPS - diagnostic output, with what a diagnostic is, and how to - filter it. New section: How to write a diagnostic. - Various minor updates and corrections. -
- - -

C. Copyright and License

- -

This document is copyright © 2007 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/finalize/index.html b/mps/design/finalize/index.html deleted file mode 100644 index 0de530651d7..00000000000 --- a/mps/design/finalize/index.html +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - -Finalization - - - - - - - -
-                              FINALIZATION
-                          design.mps.finalize
-                           incomplete design
-                             drj 1997-02-14
-
-
-OVERVIEW:
-
-Finalization is implemented internally using the Guardian Pool Class 
-(design.mps.poolmrg).  Objects can be registered for finalization using an 
-interface function (called mps_finalize).  Notification of finalization is 
-given to the client via the messaging interface.  PoolClassMRG 
-(design.mps.poolmrg) implements a Message Class which implements the 
-finalization messages.
-
-
-REQUIREMENTS:
-
-.req: Historically only Dylan had requirements
-for finalization, see req.dylan.fun.final.  Now (2003-02-19) Configura
-have requirements for finalization.  Happily they are very similar.
-
-
-ARCHITECTURE:
-
-External Interface
-
-
-.if.register:
-mps_res_t mps_finalize(mps_arena_t arena, mps_addr_t obj);
-
-increases the number of times that the object located at obj has been 
-registered for finalization by one.  The object must have been allocated from 
-the arena (space).  Any finalization messages that are created for this object 
-will appear on the arena's message queue.  The MPS will attempt to finalize the 
-object that number of times.
-
-.if.deregister:
-void mps_definalize(mps_arena_t arena, mps_addr_t obj);
-
-mps_definalize reduces the number of times that the object located at obj has 
-been registered for finalization by one.  It is an error to definalize that has 
-not been registered for finalization.
-
-.if.deregister.not: At the moment (1997-08-20) mps_definalize is not implemented
-
-.if.get-ref:
-void mps_message_finalization_ref(mps_addr_t *mps_addr_return,
-                                  mps_arena_t mps_arena,
-                                  mps_message_t mps_message)
-
-
-mps_message_finalization_ref returns the reference to the finalized object 
-stored in the finalization message.
-
-
-IMPLEMENTATION:
-
-.int.over: Registering an object for finalization corresponds to allocating a 
-reference of rank FINAL to that object.  This reference is allocated in a 
-guardian object in a pool of PoolClassMRG (see design.mps.poolmrg).
-
-.int.arena.struct: The MRG pool used for managing final references is kept in 
-the Arena (Space), referred to as the "final pool".  .int.arena.lazy: The pool 
-is lazily created, it will not be created until the first object is registered 
-for finalization.  .int.arena.flag: There is a flag in the Arena that indicates 
-whether the final pool has been created yet or not.
-
-.int.finalize:
-
-Res ArenaFinalize(Arena arena, Ref addr)
-
-.int.finalize.create: Creates the final pool if it has not been created yet.  
-.int.finalize.alloc: Allocates a guardian in the final pool.  
-.int.finalize.write: Writes a reference to the object into the guardian 
-object.  .int.finalize.all: That's all.  .int.finalize.error: if either the 
-creation of the pool or the allocation of the object fails then the error will 
-be reported back to the caller.  .int.finalize.error.no-unwind: This function 
-does not need to do any unwinding in the error cases because the creation of 
-the pool is not something that needs to be undone.
-
-.int.arena-destroy.empty: ArenaDestroy empties the message queue by calling 
-MessageEmpty.
-
-.int.arena-destroy.final-pool: If the final pool has been created then 
-ArenaDestroy destroys the final pool.
-
-.access: mps_message_finalization_ref needs to access the finalization message 
-to retrieve the reference and then write it to where the client asks.  This 
-must be done carefully, in order to avoid breaking the invariants or creating a 
-hidden root.
-
-.access.invariants: We protect the invariants by using special routines 
-ArenaRead and ArenaPoke to read and write the reference.  This works as long as 
-there's no write-barrier collection.  [Instead of ArenaPoke, we could put in an 
-ArenaWrite that would be identical to ArenaPoke, except for AVERring the 
-invariant (or it can just AVER there are no busy traces unflipped).  When we 
-get write-barrier collection, we could change it to do the real thing, but in 
-the absence of a write-barrier, it's functionally identical to ArenaPoke.  
-Pekka 1997-12-09]
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/fix/index.html b/mps/design/fix/index.html deleted file mode 100644 index fc499b8e966..00000000000 --- a/mps/design/fix/index.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - -The Design of the Generic Fix Function - - - - - - - -
-                 THE DESIGN OF THE GENERIC FIX FUNCTION
-                             design.mps.fix
-                           incomplete design
-                           richard 1995-08-25
-
-
-INTRODUCTION:
-
-Fix is the interface through which the existence of references are communicated 
-from the MPS client to the MPS.  The interface also allows the value of such 
-references to be changed (this is necessary in order to implement a moving 
-memory manager).
-
-
-ARCHITECTURE:
-
-.contract:
-
-.protocol.was-marked: The ScanState has a Bool wasMarked field.  This is used 
-for finalization.
-.protocol.was-marked.set: All pool-specific fix methods must set the wasMarked 
-field in the ScanState that they are passed.
-.protocol.was-marked.meaning: If the pool-specific fix method sets the 
-wasMarked field to FALSE it is indicating the object referred to by the ref 
-(the one that it is supposed to be fixing) has not previously been marked (ie, 
-this is the first reference to this object that has been fixed), and that the 
-object was white (in condemned space).
-.protocol.was-marked.conservative: It is always okay to set the wasMarked field 
-to TRUE.
-.protocol.was-marked.finalizable: PoolMRG (design.mps.poolmrg) uses the value 
-of the wasMarked field to determine whether an object is finalizable.
-
-
-IMPLEMENTATION:
-
-.fix.nailed: In a copying collection, a non-ambiguous fix to a broken heart 
-should be snapped out _even if_ there is a RankAMBIG ref to same object (i.e., 
-even if the broken heart is nailed); the RankAMBIG reference must either be 
-stale (no longer in existence) or bogus.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-21RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/index.html b/mps/design/index.html deleted file mode 100644 index 01b2c363545..00000000000 --- a/mps/design/index.html +++ /dev/null @@ -1,667 +0,0 @@ - - - - - - - - -Product Design Documents - - - - - -
- -

-Ravenbrook / -Projects / -Memory Pool System / -Master Product Sources -

- -

Memory Pool System Project

- -
- - -

Product Design Documents

- -
-Richard Brooksby, -Ravenbrook Limited, -2002-05-23 -
- -
- - -

1. Introduction

- - -

This is the catalogue of design documents of the Memory Pool System product.

- -

This is not a complete set of design documents for the MPS. We have many hundreds of documents, many of which contain confidential information. We are sorting through these and will include more as time goes on. We have tried to select the key documents for inclusion in the open source release, by including those documents referenced by the source code.

- -

This document will be modified as the product is developed.

- -

The readership of this document is the product developers.

- -

This document is not confidential.

- - -

2. Designs

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
alloc-frame/ Design of the MPS allocation frame protocol
arena/ The design of the MPS arena
arenavm/ Virtual memory arena
bt/ Bit tables
buffer/ Allocation buffers and allocation points
cbs/ Design for coalescing block structure
check/ Design of checking in MPS
class-interface/ Design of the pool class interface
collection/ The collection framework
config/ The design of MPS configuration
critical-path The critical path through the MPS
cstyle/ Coding standard: how C source code should be formatted
diag/ The design of MPS diagnostic feedback
finalize/ Finalization
fix/ The Design of the Generic Fix Function
interface-c/ The design of the Memory Pool System interface to C
io/ The design of the MPS i/o subsystem
lib/ The design of the Memory Pool System library interface
lock/ The design of the lock module
locus/ The design for the locus manager
message/ MPS to client message protocol
message-gc/ Messages sent when garbage collection begins or ends
object-debug/ Debugging Features for Client Objects
pool/ The design of the pool and pool class mechanisms
poolamc/ The design of the automatic mostly-copying memory pool class
poolams/ The design of the automatic mark-and-sweep pool class
poolawl/ Automatic weak linked
poollo/ Leaf object pool class
poolmfs/ The design of the manual fixed small memory pool class
poolmrg/ Guardian poolclass
poolmv/ The design of the manual variable memory pool class
poolmvt/ The design of a new manual-variable memory pool class
poolmvff/ Design of the manually-managed variable-size first-fit pool
prot/ Generic design of the protection module
protan/ ANSI implementation of protection module
protli/ Linux implementation of protection module
protocol/ The design for protocol inheritance in MPS
protsu/ SunOS 4 implementation of protection module
pthreadext/ Design of the Posix thread extensions for MPS
reservoir/ The design of the low-memory reservoir
ring/ The design of the ring data structure
root/ The design of the root manager
scan/ The design of the generic scanner
seg/ The design of the MPS segment data structure
shield/ Shield abstraction: separate control of collector access and mutator (client) access to memory
sig/ The design of the Memory Pool System signature system
splay/ Design of splay trees
sso1al/ Stack scanner for Digital Unix / Alpha systems
telemetry/ The design of the MPS telemetry mechanism
tests/ The design of MPS internal tests
thread-manager/ The design of the MPS thread manager
thread-safety/ Thread Safety in the MPS
trace/ Tracer
type/ The design of the general MPS types
version-library/ Design of the MPS library version mechanism
version/ Design of MPS software versions
vm/ The design of the virtual mapping interface
vman/ ANSI fake VM
vmo1/ VM Module on DEC Unix
vmso/ VM Design for Solaris
writef/ The design of the MPS writef function
- - -

A. References

- - - -

B. Document History

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2002-05-23RBCreated empty catalogue based on P4DTI design document catalogue.
2002-06-07RBAdded a bunch of design documents referenced by the source code.
2002-06-21NBRemove P4DTI reference, which doesn't fit here. Maybe one day we'll have a corporate design document procedure.
2002-06-24 RB Added fix, object-debug, thread-manager, and thread-safety.
2007-02-08 RHSK Added message-gc and shield.
2007-06-12 RHSK Added cstyle.
2007-06-28 RHSK Added diag.
2008-12-04 RHSK Added tests.
2008-12-10 RHSK Correct description of message-gc: gc begin or end.
2012-09-14 RB Added link to critical-path
- - -

C. Licence

- -

This document is copyright © 2002, 2007, 2008 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - - diff --git a/mps/design/interface-c/index.html b/mps/design/interface-c/index.html deleted file mode 100644 index 4d0b67fe87b..00000000000 --- a/mps/design/interface-c/index.html +++ /dev/null @@ -1,376 +0,0 @@ - - - - - - - - -The design of the Memory Pool System interface to C - - - - - - - -
-          THE DESIGN OF THE MEMORY POOL SYSTEM INTERFACE TO C
-                         design.mps.interface.c
-                             incomplete doc
-                           richard 1996-07-29
-
-INTRODUCTION
-
-
-Scope
-
-.scope: This document is the design for the Memory Pool System (MPS) interface 
-to the C Language, impl.h.mps.
-
-
-Background
-
-.bg: See mail.richard.1996-07-24.10-57.
-
-
-Document History
-
-.hist.0: The first draft of this document was generated in response to 
-review.impl.h.mps.10 which revealed the lack of a detailed design document and 
-also the lack of conventions for external interfaces.  The aim of the draft was 
-to record this information, even if it isn't terribly well structured.
-
-
-ANALYSIS
-
-
-Goals
-
-.goal.c: The file impl.h.mps is the C external interface to the MPS.  It is the 
-default interface between client code written in C and the MPS.  .goal.cpp: 
-impl.h.mps is not specifically designed to be an interface to C++, but should 
-be usable from C++.
-
-
-Requirements
-
-.req: The interface must provide an interface from client code written in C to 
-the functionality of the MPS required by the product (see req.product), Dylan 
-(req.dylan), and the Core RIP (req.epcore).
-
-mps.h may not include internal MPS header files such as "pool.h" etc.
-
-It is essential that the interface cope well with change, in order to avoid 
-restricting possible future MPS developments.  This means that the interface 
-must be "open ended" in its definitions.  This accounts for some of the 
-apparently tortuous methods of doing things (fmt_A, for example).  The 
-requirement is that the MPS should be able to add new functionality, or alter 
-the implementation of existing functionality, without affecting existing client 
-code.  A stronger requirement is that the MPS should be able to change without 
-_recompiling_ client code.  This is not always possible.
-
-[.naming.global wqas presumable done in response to an unwritten requirement 
-regarding the use of the name spaces in C, perhaps something like 
-".req.name.iso: The interface shall not conflict in terms of naming with any 
-interfaces specified by ISO C and all reasonable future versions" and 
-".req.name.general: The interface shall use a documented and reasonably small 
-portion of the namespace so that clients can interoperate easily"  drj 
-1998-10-01]
-
-
-ARCHITECTURE
-
-.fig.arch: The architecture of the MPS Interface
-
-
-
-Just behind mps.h is the file mpsi.c, the "MPS interface layer" which does the 
-job of converting types and checking parameters before calling through to the 
-MPS proper, using internal MPS methods.
-
-
-GENERAL CONVENTIONS
-
-
-.naming: The external interface names should adhere to the documented interface 
-conventions; these are found in doc.mps.ref-man.if-conv(0).naming.  
-(paraphrased/recreated here)  .naming.unixy: The external interface does not 
-follow the same naming conventions as the internal code.  The interface is 
-designed to resemble a more conventional C, Unix, or Posix naming convention.  
-.naming.case: Identifiers are in lower case, except non-function-like macros, 
-which are in upper case.  .naming.global: All publicised identifiers are 
-prefixed "mps_" or "MPS_".  .naming.all: All identifiers defined by the MPS 
-should begin "mps_" or "MPS_" or "_mps_".  .naming.type: Types are suffixed 
-"_t".  .naming.struct: Structure types and tags are suffixed "_s".  
-.naming.union: Unions types and tags are suffixed "_u".
-
-.naming.scope: The naming conventions apply to all identifiers (see ISO C 
-clause 6.1.2); this includes names of functions, variables, types (through 
-typedef), structure and union tags, enumeration members, structure and union 
-members, macros, macro parameters, labels.  .naming.scope.labels: labels (for 
-goto statements) should be rare, only in special block macros and probably not 
-even then.  .naming.scope.other: The naming convention would also extend to 
-enumeration types and parameters in functions prototypes but both of those are 
-prohibited from having names in an interface file.
-
-.type.gen: The interface defines memory addresses as "void *" and sizes as 
-"size_t" for compatibility with standard C (in particular, with malloc etc.).  
-These types must be binary compatible with the internal types "Addr" and "Size" 
-respectively.  Note that this restricts the definitions of the internal types 
-"Addr" and "Size" when the MPS is interfaced with C, but does not restrict the 
-MPS in general.
-
-.type.opaque: Opaque types are defined as pointers to structures which are 
-never defined.  These types are cast to the corresponding internal types in 
-mpsi.c.
-
-.type.trans:  Some transparent structures are defined.  The client is expected 
-to read these, or poke about in them, under restrictions which should be 
-documented.  The most important is probably the allocation point (mps_ap_s) 
-which is part of allocation buffers.  The transparent structures must be binary 
-compatible with corresponding internal structures.  For example, the fields of 
-mps_ap_s must correspond with APStruct internally.  This is checked by mpsi.c 
-in mps_check().
-
-.type.pseudo: Some pseudo-opaque structures are defined.  These only exist so 
-that code can be inlined using macros.  The client code shouldn't mess with 
-them.  The most important case of this is the scan state (mps_ss_s) which is 
-accessed by the in-line scanning macros, MPS_SCAN_* and MPS_FIX*.
-
-.type.enum: There should be no enumeration types in the interface.  Note that 
-enum specifiers (to declare integer constants) are fine as long as no type is 
-declared.  See guide.impl.c.misc.enum.type.
-
-.type.fun: Whenever function types or derived function types (such as pointer 
-to function) are declared a prototype should be used and the parameters to the 
-function should not be named.  This includes the case where you are declaring 
-the prototype for an interface function.  .type.fun.example: So use "extern 
-mps_res_t mps_alloc(mps_addr_t *, mps_pool_t, size_t, ...);" rather than 
-"extern mps_res_t mps_alloc(mps_addr_t *addr_return, mps_pool_t pool , size_t 
-size, ...);"  and "typedef mps_addr_t (*mps_fmt_class_t)(mps_addr_t);" rather 
-then "typedef mps_addr_t (*mps_fmt_class_t)(mps_addr_t object);".  See 
-guide.impl.c.misc.prototype.parameters.
-
-
-Checking
-
-.check.space: When the space needs to be recovered from a parameter it is check 
-using AVER(CHECKT(Foo, foo)) before any attempt to access FooSpace(foo).  
-CHECKT (impl.h.assert) performs simple thread-safe checking of foo, so it can 
-be called outside of SpaceEnter/SpaceLeave.  [perhaps this should be a special 
-macro.  "AVER(CHECKT(" can look like the programmer made a mistake.  drj 
-1998-11-05]
-
-.check.types: We use definitions of types in both our external interface and 
-our internal code, and we want to make sure that they are compatible.  (The 
-external interface changes less often and hides more information.)  At first, 
-we were just checking their sizes, which wasn't very good, but I've come up 
-with some macros which check the assignment compatibility of the types too.  
-This is a sufficiently useful trick that I thought I'd send it round.  It may 
-be useful in other places where types and structures need to be checked for 
-compatibility at compile time.
-
-These macros don't generate warnings on the compilers I've tried.
-
-This macro checks the assignment compatibility of two lvalues.  The hack is 
-that it uses sizeof to guarantee that the assignments have no effect.
-
-#define check_lvalues(_e1, _e2) \
-  (sizeof((_e1) = (_e2)), sizeof((_e2) = (_e1)), sizeof(_e1) == sizeof(_e2))
-
-This macro checks that two types are compatible and equal in size.  The hack 
-here is that it generates an lvalue for each type by casting zero to a pointer 
-to the type.
-
-#define check_types(_t1, _t2)   check_lvalues(*((_t1 *)0), *((_t2 *)0))
-
-This macro just checks that the offset and size of two fields are the same.
-
-#define check_fields_approx(_s1, _f1, _s2, _f2) \
-  (offsetof(_s1, _f1) == offsetof(_s2, _f2) && \
-   sizeof(((_s1 *)0)->_f1) == sizeof(((_s2 *)0)->_f2))
-
-This macro checks the offset, size, and compatibility of fields.
-
-#define check_fields(_s1, _f1, _s2, _f2) \
-  (check_lvalues(((_s1 *)0)->_f1, ((_s2 *)0)->_f2) && \
-   check_fields_approx(_s1, _f1, _s2, _f2))
-
-
-Binary Compatibility Issues
-
-As in Enumeration types are not allowed (see mail.richard.1995-09-08.09-28).
-
-There are two main aspects to run-time compatibility: binary interface and 
-protocol.  The binary interface is all the information needed to correctly use 
-the library, and includes external symbol linkage, calling conventions, type 
-representation compatibility, structure layouts, etc.  The protocol is how the 
-library is actually used by the client code -- whether this is called before 
-that -- and determines the semantic correctness of the client with respect to 
-the library.
-
-The binary interface is determined completely by the header file and the 
-target.  The header file specifies the external names and the types, and the 
-target platform specifies calling conventions and type representation.  There 
-is therefore a many-to-one mapping between the header file version and the 
-binary interface.
-
-The protocol is determined by the implementation of the library.
-
-  
-Constraints
-
-.cons: The MPS C Interface constrains the MPS in order to provide useful memory 
-management services to a C or C++ program.
-
-.cons.addr: The interface constrains the MPS address type, Addr 
-(design.mps.type.addr), to being the same as C's generic pointer type, void *, 
-so that the MPS can manage C objects in the natural way.
-
-.pun.addr: We pun the type of mps_addr_t (which is void *) into Addr (an 
-incomplete type, see design.mps.type.addr).  This happens in the call to the 
-scan state's fix function, for example.
-
-.cons.size: The interface constrains the MPS size type, Size 
-(design.mps.type.size), to being the same as C's size type, size_t, so that the 
-MPS can manage C objects in the natural way.
- 
-.pun.size: We pun the type of size_t in mps.h into Size in the MPM, as an 
-argument to the format methods.  We assume this works.
-
-.cons.word: The MPS assumes that Word (design.mps.type.word) and Addr 
-(design.mps.type.addr) are the same size, and the interface constrains Word to 
-being the same size as C's generic pointer type, void *.
-
-
-NOTES
-
-The file mpstd.h is the MPS target detection header.  It decodes
-preprocessor symbols which are predefined by build environments in order to
-determine the target platform, and then defines uniform symbols, such as
-MPS_ARCH_I3, for use internally by the MPS.
-
-There is a design document for the mps interface, design.mps.interface, but
-it was written before we had the idea of having a C interface layer.  It is
-quite relevant, though, and could be updated.  We should use it during the
-review.
-
-All exported identifiers and file names should begin with mps_ or mps so
-that they don't clash with other systems.
-
-We should probably have a specialized set of rules and a special checklist
-for this interface.
-
-.fmt.extend: This paragraph should be an explanation of why mps_fmt_A is so 
-called.  The underlying reason is future extensibility.
-
-.thread-safety: Most calls through this interface lock the space and therefore 
-make the MPM single-threaded.  In order to do this they must recover the space 
-from their parameters.  Methods such as ThreadSpace() must therefore be 
-callable when the space is _not_ locked.  These methods are tagged with the tag 
-of this note.
-
-.lock-free: Certain functions inside the MPM are thread-safe and do not need to 
-be serialized by using locks.  They are marked with the tag of this note.
-
-.form: Almost all functions in this implementation simply cast their arguments 
-to the equivalent internal types, and cast results back to the external type, 
-where necessary.  Only exceptions are noted in comments.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/io/index.html b/mps/design/io/index.html deleted file mode 100644 index d7cc7992e8c..00000000000 --- a/mps/design/io/index.html +++ /dev/null @@ -1,494 +0,0 @@ - - - - - - - - -The design of the MPS i/o subsystem - - - - - - - -
-                  THE DESIGN OF THE MPS I/O SUBSYSTEM
-                             design.mps.io
-                           incomplete design
-                           richard 1996-08-30
-
-INTRODUCTION
-
-.intro: This document is the design of the MPS I/O Subsystem, a part of the 
-plinth.
-
-.readership: This document is intended for MPS developers.
-
-
-History
-
-.hist.1: Document created from paper notes by Richard Brooksby, 1996-08-30.
-
-.hist.2: Updated with mail.richard.1997-05-30.16-13 and subsequent discussion 
-in the Pool Hall at Longstanton.  (See also mail.drj.1997-06-05.15-20.)  
-richard 1997-06-10
-
-
-Background
-
-.bg: This design is partly based on the design of the Internet User Datagram 
-Protocol (UDP).  Mainly I used this to make sure I hadn't left out anything 
-which we might need.
-
-
-PURPOSE
-
-.purpose: The purpose of the MPS I/O Subsystem is to provide a means to 
-measure, debug, control, and test a memory manager build using the MPS.
-
-.purpose.measure: Measurement consists of emitting data which can be collected 
-and analysed in order to improve the attributes of application program, quite 
-possibly by adjusting parameters of the memory manager (see overview.mps.usage).
-
-.purpose.control: Control means adjusting the behaviour of the MM dynamically.  
-For example, one might want to adjust a parameter in order to observe the 
-effect, then transfer that adjustment to the client application later.
-
-.purpose.test: Test output can be used to ensure that the memory manager is 
-behaving as expected in response to certain inputs.
-
-
-REQUIREMENTS
-
-
-General
-
-.req.fun.non-hosted: The MPM must be a host-independent system.
-
-.req.attr.host: It should be easy for the client to set up the MPM for a 
-particular host (such as a washing machine).
-
-
-Functional
-
-.req.fun.measure: The subsystem must allow the MPS to transmit quantitative 
-measurement data to an external tool so that the system can be tuned.
-
-.req.fun.debug: The subsystem must allow the MPS to transmit qualitative 
-information about its operation to an external tool so that the system can be 
-debugged.
-
-.req.fun.control: The subsystem must allow the MPS to receive control 
-information from an external tool so that the system can be adjusted while it 
-is running.
-
-.req.dc.env.no-net: The subsystem should operate in environments where there is 
-no networking available.
-
-.req.dc.env.no-fs: The subsystem should operate in environments where there is 
-no filesystem available.
-
-
-ARCHITECTURE
-
-.arch.diagram:
-
- - I/O Architecture Diagram 
-
-.arch.int: The I/O Interface is a C function call interface by which the MPM 
-sends and receives "messages" to and from the hosted I/O module.
-
-.arch.module: The modules are part of the MPS but not part of the freestanding 
-core system (see design.mps.exec-env).  The I/O module is responsible for 
-transmitting those messages to the external tools, and for receiving messages 
-from external tools and passing them to the MPM.
-
-.arch.module.example: For example, the "file implementation" might just 
-send/write telemetry messages into a file so that they can be received/read 
-later by an off-line measurement tool.
-
-.arch.external: The I/O Interface is part of interface to the freestanding core 
-system (see design.mps.exec-env).  This is so that the MPS can be deployed in a 
-freestanding environment, with a special I/O module.  For example, if the MPS 
-is used in a washing machine the I/O module could communicate by writing output 
-to the seven-segment display.
-
-
-Example Configurations
-
-.example.telnet: This shows the I/O Subsystem communicating with a telnet 
-client over a TCP/IP connection.  In this case, the I/O Subsystem is 
-translating the I/O Interface into an interactive text protocol so that the 
-user of the telnet client can talk to the MM.
-
-
-
-.example.file: This shows the I/O Subsystem dumping measurement data into a 
-file which is later read and analysed.  In this case the I/O Subsystem is 
-simply writing out binary in a format which can be decoded.
-
-
-
-.example.serial: This shows the I/O Subsystem communicating with a graphical 
-analysis tool over a serial link.  This could be useful for a developer who has 
-two machines in close proximity and no networking support.
-
-.example.local: In this example the application is talking directly to the I/O 
-Subsystem.  This is useful when the application is a reflective development 
-environment (such as MLWorks) which wants to observe its own behaviour.
-
-
- - MPS I/O Configuration Diagrams 
-
-
-
-INTERFACE
-
-.if.msg: The I/O interface is oriented around opaque binary "messages" which 
-the I/O module must pass between the MPM and external tools.  The I/O module 
-need not understand or interpret the contents of those messages.
-
-.if.msg.opaque: The messages are opaque in order to minimize the dependency of 
-the I/O module on the message internals.  It should be possible for clients to 
-implement their own I/O modules for unusual environments.  We do not want to 
-reveal the internal structure of our data to the clients.  Nor do we want to 
-burden them with the details of our protocols.  We'd also like their code to be 
-independent of ours, so that we can expand or change the protocols without 
-requiring them to modify their modules.
-
-.if.msg.dgram: Neither the MPM nor the external tools should assume that the 
-messages will be delivered in finite time, exactly once, or in order.  This 
-will allow the I/O modules to be implemented using unreliable transport layers 
-such as the Internet User Datagram Protocl (UDP).  It will also give the I/O 
-module the freedom to drop information rather than block on a congested 
-network, or stop the memory manager when the disk is full, or similar events 
-which really shouldn't cause the memory manager to stop working.  The protocols 
-we need to implement at the high level can be design to be robust against 
-lossage without much difficulty.
-
-
-I/O Module State
-
-.if.state: The I/O module may have some internal state to preserve.  The I/O 
-Interface defines a type for this state, "mps_io_t", a pointer to an incomplete 
-structure "mps_io_s".  The I/O module is at liberty to define this structure.
-
-  typedef struct mps_io_s *mps_io_t;
-
-
-Message Types
-
-.if.type: The I/O module must be able to deliver messages of several different 
-types.  It will probably choose to send them to different destinations based on 
-their type: telemetry to the measurement tool, debugging output to the 
-debugger, etc.
-
-  typedef int mps_io_type_t;
-  enum {
-    MPS_IO_TYPE_TELEMETRY,
-    MPS_IO_TYPE_DEBUG
-  };
-
-
-Limits
-
-.if.message-max: The interface will define an unsigned integral constant 
-"MPS_IO_MESSAGE_MAX" which will be the maximum size of messages that the MPM 
-will pass to "mps_io_send" (.if.send) and the maximum size it will expect to 
-receive from "mps_io_receive".
-
-
-Interface Set-up and Tear-down
-
-.if.create: The MPM will call "mps_io_create" to set up the I/O module.  On 
-success, this function should return "MPS_RES_OK".  It may also initialize 
-"*mps_io_r" to a "state" value which will be passed to subsequent calls through 
-the interface.
-
-  extern mps_res_t mps_io_create(mps_io_t *mps_io_r);
-
-.if.destroy: The MPM will call "mps_io_destroy" to tear down the I/O module, 
-after which it guarantees that the state value "mps_io" will not be used 
-again.  The "state" parameter is the state previously returned by 
-"mps_io_create" (.if.create).
-
-  extern void mps_io_destroy(mps_io_t mps_io);
-
-
-Message Send and Receive
-
-.if.send: The MPM will call "mps_io_send" when it wishes to send a message to a 
-destination.  The "state" parameter is the state previously returned by 
-"mps_io_create" (.if.create).  The "type" parameter is the type (.if.type) of 
-the message.  The "message" parameter is a pointer to a buffer containing the 
-message, and "size" is the length of that message, in bytes.  The I/O module 
-must make an effort to deliver the message to the destination, but is not 
-expected to guarantee delivery.  The function should return "MPS_RES_IO" only 
-if a serious error occurs that should cause the MPM to return with an error to 
-the client application.  Failure to deliver the message does not count.  
-[Should there be a timeout parameter?  What are the timing constraints?  
-mps_io_send shouldn't block.]
-
-  extern mps_res_t mps_io_send(mps_io_t state,
-                               mps_io_type_t type,
-                               void *message,
-                               size_t size);
-
-.if.receive: The MPM will call "mps_io_receive" when it wants to see if a 
-message has been sent to it.  The "state" parameter is the state previously 
-returned by "mps_io_create" (.if.create).  The "buffer_o" parameter is a 
-pointer to a value which should be updated with a pointer to a buffer 
-containing the message received.  The "size_o" parameter is a pointer to a 
-value which should be updated with the length of the message received.  If 
-there is no message ready for receipt, the length returned should be zero.  
-(Should we be able to receive truncated messages?  How can this be done neatly?)
-
-  extern mps_res_t mps_io_receive(mps_io_t state,
-                                  void **buffer_o,
-                                  size_t *size_o);
-
-
-I/O MODULE IMPLEMENTATIONS
-
-
-Routeing
-
-The I/O module must decide where to send the various messages.  A file-based 
-implementation could put them in different files based on their types.  A 
-network-based implementation must decide how to address the messages.  In 
-either case, any configuration must either be statically compiled into the 
-module, or else read from some external source such as a configuration file.
-
-
-NOTES
-
-The external tools should be able to reconstruct stuff from partial info.  For 
-example, you come across a fragment of an old log containing just a few old 
-messages.  What can you do with it?
-
-Here's some completely untested code which might do the job for UDP.
-
----
-
-#include "mpsio.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <errno.h>
-
-typedef struct mps_io_s {
-  int sock;
-  struct sockaddr_in mine;
-  struct sockaddr_in telemetry;
-  struct sockaddr_in debugging;
-} mps_io_s;
-
-static mps_bool_t inited = 0;
-static mps_io_s state;
-
-
-mps_res_t mps_io_create(mps_io_t *mps_io_o)
-{
-  int sock, r;
-  
-  if(inited)
-    return MPS_RES_LIMIT;
-
-  state.mine = /* setup somehow from config */;
-  state.telemetry = /* setup something from config */;
-  state.debugging = /* setup something from config */;
-
-  /* Make a socket through which to communicate. */  
-  sock = socket(AF_INET, SOCK_DGRAM, 0);
-  if(sock == -1) return MPS_RES_IO;
-
-  /* Set socket to non-blocking mode. */
-  r = fcntl(sock, F_SETFL, O_NDELAY);
-  if(r == -1) return MPS_RES_IO;
-
-  /* Bind the socket to some UDP port so that we can receive messages. */
-  r = bind(sock, (struct sockaddr *)&state.mine, sizeof(state.mine));
-  if(r == -1) return MPS_RES_IO;
-
-  state.sock = sock;
-  
-  inited = 1;
-
-  *mps_io_o = &state;
-  return MPS_RES_OK;
-}
-
-
-void mps_io_destroy(mps_io_t mps_io)
-{
-  assert(mps_io == &state);
-  assert(inited);
-  
-  (void)close(state.sock);
-
-  inited = 0;
-}
-
-
-mps_res_t mps_io_send(mps_io_t mps_io, mps_type_t type,
-                      void *message, size_t size)
-{
-  struct sockaddr *toaddr;
-
-  assert(mps_io == &state);
-  assert(inited);
-
-  switch(type) {
-    MPS_IO_TYPE_TELEMETRY:
-    toaddr = (struct sockaddr *)&state.telemetry;
-    break;
-    
-    MPS_IO_TYPE_DEBUGGING:
-    toaddr = (struct sockaddr *)&state.debugging;
-    break;
-    
-    default:
-    assert(0);
-    return MPS_RES_UNIMPL;
-  }
-
-  (void)sendto(state.sock, message, size, 0, toaddr, sizeof(*toaddr));
-
-  return MPS_RES_OK;
-}
-
-
-mps_res_t mps_io_receive(mps_io_t mps_io,
-                         void **message_o, size_t **size_o)
-{
-  int r;
-  static char buffer[MPS_IO_MESSAGE_MAX];
-
-  assert(mps_io == &state);
-  assert(inited);
-  
-  r = recvfrom(state.sock, buffer, sizeof(buffer), 0, NULL, NULL);
-  if(r == -1)
-    switch(errno) {
-      /* Ignore interrupted system calls, and failures due to lack */
-      /* of resources (they might go away.) */
-      case EINTR: case ENOMEM: case ENOSR:
-      r = 0;
-      break;
-      
-      default:
-      return MPS_RES_IO;
-    }
-
-  *message_o = buffer;
-  *size_o = r;
-  return MPS_RES_OK;
-}
-
-
-ATTACHMENTS
-   "O Architecture Diagram"
-   "O Configuration Diagrams"
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/lib/index.html b/mps/design/lib/index.html deleted file mode 100644 index 53501c8416b..00000000000 --- a/mps/design/lib/index.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - -The design of the Memory Pool System library interface - - - - - - - -
-         THE DESIGN OF THE MEMORY POOL SYSTEM LIBRARY INTERFACE
-                             design.mps.lib
-                           incomplete design
-                           richard 1996-09-03
-
-INTRODUCTION
-
-.intro: This document is the design of the MPS Library Interface, a part of the 
-plinth.
-
-.readership: Any MPS developer.  Any clients that are prepared to read this in 
-order to get documentation.
-
-
-GOALS
-
-.goal: The goals of the MPS library interface are:
-
-.goal.host: To control the dependency of the MPS on the hosted ISO C library so 
-that the core MPS remains freestanding (see design.mps.exec-env).
-
-.goal.free: To allow the core MPS convenient access to ISO C functionality that 
-is provided on freestanding platforms (see design.mps.exec-env.std.com.free).
-
-
-DESCRIPTION
-
-
-Overview
-
-.overview.access: The core MPS needs to access functionality that could be 
-provided by an ISO C hosted environment.
-
-.overview.hosted: The core MPS must not make direct use of any facilities in 
-the hosted environment (design.mps.exec-env).  However, it is sensible to make 
-use of them when the MPS is deployed in a hosted environment.
-
-.overview.hosted.indirect: The core MPS does not make any direct use of hosted 
-ISO C library facilities.  Instead, it indirects through the MPS Library 
-Interface, impl.h.mpslib.
-
-.overview.free: The core MPS can make direct use of freestanding ISO C library 
-facilities and does not need to include any of the header files <limits.h>, 
-<stdarg.h>, and <stddef.h> directly.
-
-.overview.complete: The MPS Library Interface can be considered as the complete 
-"interface to ISO" (in that it provides direct access to facilities that we get 
-in a freestanding environment and equivalents of any functionality we require 
-from the hosted environment).
-
-.overview.provision.client: In a freestanding environment the client is 
-expected to provide functions meeting this interface to the MPS.
-
-.overview.provision.hosted: In a hosted environment, impl.c.mpsliban may be 
-used.  It just maps impl.h.mpslib directly onto the ISO C library equivalents.
-
-
-
- - MPS Library Interface Diagram 
-
-
-Outside the Interface
-
-We provide impl.c.mpsliban to the client, for two reasons:
-
-  1. he can use it to connect the MPS to the ISO C library if it exists,
-
-  2. as an example of an implementation of the MPS Library Interface.
-
-
-IMPLEMENTATION
-
-.impl: The MPS Library Interface comprises a header file impl.h.mpslib 
-(mpslib.h) and some documentation.
-
-.impl.decl: The header file defines the interface to definitions which parallel 
-those parts of the non-freestanding ISO headers which are used by the MPS.
-
-.impl.include: The header file also includes the freestanding headers 
-<limits.h>, <stdarg.h>, and <stddef.h> (and not <float.h>, though perhaps it 
-should).
-
-
-NOTES
-
-.doc: User doc in doc.mps.guide.interface and doc.mps.guide.appendix-plinth.
-
-ATTACHMENT
-   "MPS Library Interface Diagram"
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/lock/index.html b/mps/design/lock/index.html deleted file mode 100644 index 11dfd923322..00000000000 --- a/mps/design/lock/index.html +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - - - -The design of the lock module - - - - - - - -
-                     THE DESIGN OF THE LOCK MODULE
-                            design.mps.lock
-                              draft design
-                             dsm 1995-11-21
-
-PURPOSE
-
-.purpose: Support the locking needs of the thread-safe design. In particular:
-- Recursive locks
-- Binary locks
-- Recursive "global" lock that need not be allocated or initialized by the 
-client
-- Binary "global" lock that need not be allocated or initialized by the client
-
-.context: The MPS has to be able to operate in a multi-threaded environment.  
-The thread-safe design (design.mps.thread-safety) requires client-allocatable 
-binary locks, a global binary lock and a global recursive lock.  An interface 
-to client-allocatable recursive locks is also present to support any potential 
-use, because of historic requirements, and because the implementation will 
-presumably be necessary anyway for the global recursive lock. 
-
-
-BACKGROUND
-
-.need: In an environment where multiple threads are accessing shared data.  The 
-threads which access data which is shared with other threads need to cooperate 
-with those threads to maintain consistency.  Locks provide a simple mechanism 
-for doing this.
-
-.ownership: A lock is an object which may be "owned" by a single thread at a 
-time.  By claiming ownership of a lock before executing some piece of code a 
-thread can guarantee that no other thread owns the lock during execution of 
-that code.  If some other thread holds a claim on a lock, the thread trying to 
-claim the lock will suspend until the lock is released by the owning thread.
-
-.data: A simple way of using this behaviour is to associate a lock with a 
-shared data structure.  By claiming that lock around accesses to the data, a 
-consistent view of the structure can be seen by the accessing thread.  More 
-generally any set of operations which are required to be mutually exclusive may 
-be performed so by using locks.
-
-
-OVERVIEW
-
-.adt: There is an ADT "Lock" which points to a locking structure "LockStruct".  
-This structure is opaque to any client, although an interface is provided to 
-supply the size of the structure for any client wishing to make a new lock.  
-The lock is not allocated by the module as allocation itself may require 
-locking.  LockStruct is implementation specific.
-
-.simple-lock: There are facilities for claiming and releasing locks.  "Lock" is 
-used for both binary and recursive locking.
-
-.global-locks: "Global" locks are so called because they are used to protect 
-data in a global location (such as a global variable). The lock module provides 
-2 global locks; one recursive and one binary.  There are facilities for 
-claiming and releasing both of these locks. These global locks have the 
-advantage that they need not be allocated or atomically initialized by the 
-client, so they may be used for locking the initialization of the allocator 
-itself.  The binary global lock is intended to protect mutable data, possibly 
-in conjunction with other local locking strategies.  The recursive global lock 
-is intended to protect static read-only data during one-off initialization.  
-See design.mps.thread-safety.
-
-.deadlock: This module does not provide any deadlock protection.  Clients are 
-responsible for avoiding deadlock by using traditional strategies such as 
-ordering of locks.  (See design.mps.thread-safety.deadlock.)
-
-.single-thread: In the single-threaded configuration, locks are not needed and 
-the claim/release interfaces defined to be no-ops.
-
-
-DETAILED DESIGN
-
-.interface: The interface comprises the following functions:
-
-- LockSize
-  Return the size of a LockStruct for allocation purposes.
-
-- LockInit / LockFinish
-  After initialisation the lock is not owned by any thread.  This must also be 
-the case before finalisation.
-[ref convention?]
-
-- LockClaim / LockRelease
-  LockClaim: claims ownership of a lock that was previously not held by current 
-thread.
-  LockRelease: releases ownership of a lock that is currently owned.
-
-- LockClaimRecursive / LockReleaseRecursive
-  LockClaimRecursive: remembers the previous state of the lock with respect to 
-the current thread and claims the lock (if not already held).
-  LockReleaseRecursive: restores the previous state of the lock stored by 
-corresponding LockClaimRecursive call.
-
-- LockClaimGlobal / LockReleaseGlobal
-  LockClaimGlobal: claims ownership of the binary global lock which was 
-previously not held by current thread.
-  LockReleaseGlobal: releases ownership of the binary global lock that is 
-currently owned.
-
-- LockClaimGlobalRecursive / LockReleaseGlobalRecursive
-  LockClaimGlobalRecursive: remembers the previous state of the recursive 
-global lock with respect to the current thread and claims the lock (if not 
-already held).
-  LockReleaseGlobalRecursive: restores the previous state of the recursive 
-global lock stored by corresponding LockClaimGlobalRecursive call.
-
-.impl.recursive: For recursive claims, the list of previous states can be 
-simply implemented by keeping a count of the number of claims made by the 
-current thread so far.  In multi-threaded implementation below this is handled 
-by the operating system.  A count is still kept and used to check correctness.
-
-.impl.global: The binary and recursive global locks may actually be implemented 
-using the same mechanism as normal locks.
-
-.impl.ansi: Single-Threaded Generic Implementation
-- single-thread
-- no need for locking
-- locking structure contains count
-- provides checking in debug version
-- otherwise does nothing except keep count of claims
-
-.impl.win32: Win32 Implementation
-- supports Win32's threads
-- uses Critical Sections [ref?]
-- locking structure contains a Critical Section
-- both recursive and non-recursive calls use same Windows function
-- also performs checking
-
-.impl.linux: LinuxThreads Implementation (possibly suitable for all PThreads 
-implementations)
-- supports LinuxThreads threads, which are an implementation of PThreads. (see 
-<URL:http://pauillac.inria.fr/~xleroy/linuxthreads/>)
-- locking structure contains a mutex, initialized to check for recursive locking
-- locking structure contains a count of the number of active claims
-- non-recursive locking calls pthread_mutex_lock and expects success
-- recursive locking calls pthread_mutex_lock and expects either success or 
-EDEADLK (indicating a recursive claim).
-- also performs checking
-
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/locus/index.html b/mps/design/locus/index.html deleted file mode 100644 index bd4177e1158..00000000000 --- a/mps/design/locus/index.html +++ /dev/null @@ -1,645 +0,0 @@ - - - - - - - - -The MPS Locus Manager - - - - - - - -

This document contains a guide to the MPS locus manager, followed by the historical initial design. References, History, Copyright and License are at the end.

- -
- -

Guide

- -

Readership: any MPS developer. Not confidential.

- - -

The MPS manages three main resources:

-
    -
  • storage;
  • -
  • address-space;
  • -
  • time.
  • -
- -

Management of arena address-space

- -

The locus manager manages address-space at the arena level.

- -

[Tucker was right: mail.ptw.1998-11-02.14-25. RHSK 2007-04-24].

- -

When a pool wants some address-space, it expresses some preferences to the locus manager. The locus manager and the arena (working together) try to honour these preferences, and decide what address-space the pool gets.

- -

Preferences are expressed by the SegPref argument to SegAlloc().

- -

Note that, when they call SegAlloc(), pools are asking for address-space and writeable storage simultaneously, in a single call. There is currently no way for pools to 'reserve' address space without requesting storage.

- - -

Why is it important to manage address-space?

- - -

Trace differentiability

- -

Carefully chosen addresses are used by reference tracing systems (ie. automatic pools), to:

-
    -
  • categorise objects into clumps;
  • -
  • summarise and cheaply find references between clumps.
  • -
- -

Different clumps will become worth collecting at different times (the classic example, of course, is generations in a generational collector). For these partial collections to be efficient, it must be cheap to keep these clumps differentiable, cheap to condemn (Whiten) a particular clump, and cheap to find a good conservative approximation to all inward references to a clump (both initially to construct the Grey set, and to make scanning the Grey set efficient).

- -

This is what the MPS zone mechanism is all about.

- -

The locus manager manages the mapping from clumps to zones.

- -

To specify a clump, pools use the "SegPrefGen" tag to SegPrefExpress. [The name is misleading: generations are only one sort of clump. RHSK 2007-04-24]

- - -

Prevent address-space fragmentation (within arena)

- -

Address-space is not infinite.

- -

In some use-cases, the MPS is required to remain efficient when using very nearly all available address-space and storage. (For example, with the client-arena class, where the only address-space available is that of the storage available).

- -

Even with the VM arena class, typical storage sizes (in the year 2007) can make 32-bit address-space constrained: the problem may have Order(4GB) size, which leaves little 'spare' address-space.

- -

Address-space fragmentation incurs failure when there is no way to allocate a big block of address-space. The big block may be requested via the MPS (by the client), or by something else in the same process, such as a 3rd-party graphics library, image library, etc.

- -

Address-space fragmentation incurs cost when:

-
    -
  • desired large-block requests (such as for buffering) are denied, causing them to be re-requested as a smaller block, or as several smaller blocks;
  • -
  • possible operating-system costs in maintaining a fragmented mapping?
  • -
- - -

Prevent storage fragmentation (within tracts and segments)

- -

Storage is not infinite: it is allocated in multiples of a fixed-size tract. Small lonely objects, each retaining a whole tract, cause storage fragmentation.

- -

Non-moving pools manage this fragmentation with placement strategies that use:

-
    -
  • co-located death (in space and time);
  • -
  • segment merging and splitting.
  • -
- -

These pool-level strategies always care about contiguity of object storage. They also often care about the ordering of addresses, because pool code uses an address-ordered search when choosing where to place a new object. For these two reasons, the address chosen (by the locus manager and arena) for new tracts is important.

- -

Certain specialised pools, and/or some client programs that use them, have carefully tuned segment sizes, positioning, and search order. Be careful: seemingly inconsequential changes can catastrophically break this tuning.

- -

Pools can specify a preference for High and Low ends of address-space, which implies a search-order. Pools could also specify clumping, using either SegPrefGen or SegPrefZoneSet.

- - -

Discovering the layout

- -

The locus manager is not given advance notice of how much address-space will be required with what preferences. Instead, the locus manager starts with an empty 'layout', and adapts it as more requests come in over time. It is attempting to 'discover' a suitable layout by successive refinement. This is ambitious.

- - -
- -

Initial Design

- -
-                    THE DESIGN FOR THE LOCUS MANAGER
-                            design.mps.locus
-                           incomplete design
-                           gavinm 1998-02-27
-
-INTRODUCTION
-
-.intro: The locus manager coordinates between the pools and takes the burden of 
-having to be clever about tract/group placement away from the pools, preserving 
-trace differentiability and contiguity where appropriate.
-
-.source: mail.gavinm.1998-02-05.17-52(0), mail.ptw.1998-02-05.19-53(0), 
-mail.pekka.1998-02-09.13-58(0), and mail.gavinm.1998-02-09.14-05(0).
-
-
-Document History
-
-.hist.0: Originally written as part of change.dylan.box-turtle.170569.  Much 
-developed since.  gavinm 1998-02-27
-
-.hist.1: Pekka wrote the real requirements after some discussion.  pekka 
-1998-10-28
-
-.hist.2: Pekka deleted Gavin's design and wrote a new one.  pekka 1998-12-15
-
-
-DEFINITIONS
-
-.note.cohort: We use the word "cohort" in its usual sense here, but we're 
-particularly interested in cohorts that have properties relevant to tract 
-placement.  It is such cohorts that the pools will try to organize using the 
-services of the locus manager.  Typical properties would be trace 
-differentiability or (en masse) death-time
-predictability.  Typical cohorts would be instances of a non-generational pool, 
-or generations of a collection strategy.
-
-.def.trace.differentiability: Objects (and hence tracts) that are collected, 
-may or may not have "trace differentiability" from each other, depending on 
-their placement in the different zones.  Objects (or pointers to them) can also 
-have trace differentiability (or not) from non-pointers in ambiguous 
-references; in practice, we will be worried about low integers, that may appear 
-to be in zones 0 or -1.
-
-
-REQUIREMENTS
-
-.req.cohort: Tract allocations must specify the cohort they allocate in.  These 
-kind of cohorts will be called loci, and they will have such attributes as are 
-implied by the other requirements.  Critical.
-
-.req.counter.objects: As a counter-requirement, pools are expected to manage 
-objects.  Objects the size of a tract allocation request (segment-sized) are 
-exceptional.  Critical.  .req.counter.objects.just: This means the locus 
-manager is not meant to solve the problems of allocating large objects, and it 
-isn't required to know what goes on in pools.
-
-.req.contiguity: Must support a high level of contiguity within cohorts when 
-requested.  This means minimizing the number of times a cohort is made aware of 
-discontiguity.  Essential (as we've effectively renegotiated this in SW, down 
-to a vague hope that certain critical cohorts are not too badly fragmented).  
-.req.contiguity.just: TSBA.
-
-.req.contiguity.specific: It should be possible to request another allocation 
-next to a specific tract on either side (or an extension in that direction, as 
-the case may be).  Such a request can fail, if there's no space there.  Nice.  
-[IWBN to have one for "next to the largest free block".]
-
-.req.differentiable: Must support the trace differentiability of segments that 
-may be condemned separately.  Due to the limited number of zones, it must be 
-possible to place several cohorts into the same zone.  Essential.
-
-.req.differentiable.integer: It must be possible to place collectable 
-allocations so that they are trace-differentiable from small integers.  
-Essential.
-
-.req.disjoint: Must support the disjointness of pages that have different VM 
-properties (such as mutable/immutable, read-only/read-write, and different 
-lifetimes).  Optional.  [I expect the implementation will simply work at page 
-or larger granularity, so the problem will not arise, but Tucker insisted on 
-stating this as a requirement.  pekka 1998-10-28]
-
-.req.low-memory: The architecture of the locus manager must not prevent the 
-design of efficient applications that often use all available memory.  
-Critical.  .req.low-memory.expl: This basically says it must be designed to 
-perform well in low-memory conditions, but that there can be configurations 
-where it doesn't do as well, as long as this is documented for the application 
-programmer.  Note that it doesn't say all applications are efficient, only that 
-if you manage to design an otherwise efficient application, the locus manager 
-will not sink it.
-
-.req.address: Must conserve address space in VM arenas to a reasonable extent.  
-Critical.
-
-.req.inter-pool: Must support the association of sets of tracts in different 
-pools into one cohort.  Nice.
-
-.req.ep-style: Must support the existing EP-style of allocation whereby 
-allocation is from one end of address space either upwards or downwards (or a 
-close approximation thereto with the same behavior).  .req.ep-style.just: We 
-cannot risk disrupting a policy with well-known properties when this technology 
-is introduced.
-
-.req.attributes: There should be a way to inform the locus manager about 
-various attributes of cohorts that might be useful for placement: deathtime, 
-expected total size, [more in the future].  Optional.  [It's a given that the 
-cohorts must then have these attributes, within the limits set in the contract 
-of the appropriate interface.]  .req.attributes.action: The locus manager 
-should use the attributes to guide its placement decisions.  Nice.
-
-.req.blacklisting: There should be a way of maintaining at least one blacklist 
-for pages (or some other small unit), that can not/should not be allocated to 
-collectable pools.  [How to do blacklist breaking for ambiguous refs?]  
-Optional.
-
-.req.hysteresis: There should be a way to indicate which cohorts fluctuate in 
-size and by how much, to guide the arena hysteresis to hold on to suitable 
-pages.  Optional.
-
-
-ANALYSIS
-
-.anal.sw: Almost any placement policy would be an improvement on the current SW 
-one.
-
-.anal.cause-and-effect: The locus manager doesn't usually need to know _why_ 
-things need to be differentiable, disjoint, contiguous, etc.  Abstracting the 
-reason away from the interface makes it more generic, more likely to have 
-serendipitous new uses.  Attributes described by a quantity (deathtime, size, 
-etc.) are an exception to this, because we can't devise a common measure.
-
-.anal.stable: The strategy must be stable: it must avoid repeated 
-recomputation, especially the kind that switches between alternatives with a 
-short period (repeated "bites" out the same region or flip-flopping between two 
-regions).
-
-.anal.fragmentation: There's some call to avoid fragmentation in cohorts that 
-don't need strict contiguity, but this is not a separate requirement, since 
-fragmentation is a global condition, and can only be ameliorated if there's a 
-global strategy that clumps allocations together.  .anal.deathtime: Cohorts 
-with good death-time clumping of their objects could use some locality of tract 
-allocation, because it increases the chances of creating large holes in the 
-address space (for other allocation to use).  OTOH. many cohorts will not do 
-multiple frees in short succession, or at least cannot reasonably be predicted 
-to do so.  This locality is not contiguity, nor is it low fragmentation, it's 
-just the requirement to place the new tracts next to the tract where the last 
-object was allocated in the cohort.  Note that the placement of objects is 
-under the control of the pool, and the locus manager will not know it, 
-therefore this requirement should be pursued by requesting allocation next to a 
-particular tract (which we already have a requirement for).
-
-.anal.asymmetrical: The strategy has to be asymmetrical with respect to cohorts 
-growing and shrinking.  The reason of this asymmetry is that it can choose 
-where to grow, but it cannot choose where to shrink (except in a small way by 
-growing with good locality).
-
-
-INTERFACE
-
-.interface.locus: A cohort will typically reside on multiple tracts (and the 
-pools will avoid putting objects of other cohorts on them), so there should be 
-an interface to describe the properties of the cohort, and associate each 
-allocation request with the cohort.  We shall call such an object, created to 
-represent a cohort, a locus (pl. loci).
-
-.interface.locus.pool: Loci will usually be created by the pool that uses it.  
-Some of the locus attributes will be inherited from client-specified pool 
-attributes [this means there will be additional pool attributes].
-
-.interface.detail: This describes interface in overview; for details, see 
-implementation section and code, or user doc.
-
-
-Loci
-
-.function.create: A function to create a locus:
-  Res LocusCreate(Locus *locusReturn, LocusAttrs attrs, ZoneGroup zg, 
-LocusAllocDesc adesc)
-where adesc contains the information about the allocation sequences in the 
-locus, zg is used for zone differentiability, and attrs encodes the following:
-  .locus.contiguity: A locus can be contiguous.  This means performing as 
-required in .req.contiguity, non-contiguous allocations can be freely placed 
-anywhere (but efficiency dictates that similar allocations are placed close 
-together and apart from others).
-  .locus.blacklist: Allocations in the locus will avoid blacklisted pages (for 
-collectable segments).
-  .locus.zero: Allocations in the locus are zero-filled.
-  [Other attributes will be added, I'm sure.]
-
-.interface.zone-group: The locus can be made a member of a zone group.  Passing 
-ZoneGroupNONE means it's not a member of any group (allocations will be placed 
-without regard to zone, except to keep them out of stripes likely to be needed 
-for some group).  [I propose no mechanism for managing zone groups at this 
-time, since it's only used internally for one purpose.  pekka 2000-01-17]
-
-.interface.size: An allocation descriptor (LocusAllocDesc) contains various 
-descriptions of how the locus will develop over time (inconsistent 
-specifications are forbidden, of course):
-  .interface.size.typical-alloc: Size of a typical allocation in this locus, in 
-bytes.  This will mainly affect the grouping of non-contiguous loci.
-  .interface.size.large-alloc: Typical large allocation that the manager should 
-try to allow for (this allows some relief from .req.counter.objects), in 
-bytes.  This will mainly affect the size of gaps that will be allotted 
-adjoining this locus.
-  .interface.size.direction: Direction of growth: up/down/none.  Only useful if 
-the locus is contiguous.
-  .interface.size.lifetime: Some measure of the lifetime of tracts (not 
-objects) in the cohort.  [Don't know the details yet, probably only useful for 
-placing similar cohorts next to each other, so the details don't actually 
-matter.  pekka 2000-01-17]
-  .interface.size.deathtime: Some measure of the deathtime of tracts (not 
-objects) in the cohort.  [Ditto.  pekka 2000-01-17]
-
-.function.init: LocusInit is like LocusCreate, but without the allocation.  
-This is the usual i/f, since most loci are embedded in a pool or something.
-
-.function.alloc: ArenaAlloc to take a locus arg.  ArenaAllocHere is like it, 
-plus it takes a tract and a specification to place the new allocation 
-immediately above/below a given tract; if that is not possible, it returns 
-ResFAIL (this will make it useful for realloc functionality).
-
-.function.set-total: A function to tell the arena the expected number of 
-(non-miscible client) loci, and of zone groups:
-  ArenaSetTotalLoci(Arena arena, Size nLoci, Size nZoneGroups)
-
-
-Peaks
-
-.function.peak.create: A function to create a peak:
- mps_res_t mps_peak_create(mps_peak_t*, mps_arena_t)
-A newly-created peak is open, and will not be used to guide the strategy of the 
-locus manager.
-
-.function.peak.add: A function to add a description of the state of one pool 
-into the peak:
-  mps_res_t mps_peak_describe_pool(mps_peak_t, mps_pool_t, mps_size_desc_t)
-Calling this function again for the same peak and pool instance will replace 
-the earlier description.  .function.peak.add.size: The size descriptor contains 
-a total size in bytes or % of arena size [@@@@is this right?].  
-.function.peak.add.remove: Specifying a NULL size will remove the pool from the 
-peak.  The client is not allowed to destroy a pool that is mentioned in any 
-peak; it must be first removed from the peak, or the peak must be destroyed.  
-This is to ensure that the client adjusts the peaks in a manner that makes 
-sense to the application; the locus manager can't know how to do that.
-
-.function.peak.close: A function to indicate that all the significant pools 
-have been added to the peak, and it can now be used to guide the locus manager:
- mps_res_t mps_peak_close(mps_peak_t)
-For any pool not described in the peak, the locus manager will take its current 
-size at any given moment as the best prediction of its size at the peak.  
-.function.peak.close.after: It is legal to add more descriptions to the peak 
-after closing, but this will reopen the peak, and it will have to be closed 
-before the locus manager will use it again.  The locus manager uses the 
-previous closed state of the peak, while this is going on.
-
-.function.peak.destroy: A function to destroy a peak:
- void mps_peak_destroy(mps_peak_t)
-
-.interface.ep-style: This satisfies .req.ep-style by allowing SW to specify 
-zero size for most pools (which will cause them to be place next to other loci 
-with the same growth direction).  [Not sure this is good enough, but we'll try 
-it first.  pekka 2000-01-17]
-
-
-ARCHITECTURE
-
-Data Objects
-
-.arch.locus: To represent the cohorts, we have locus objects.  Usually a locus 
-is embedded in a pool instance, but generations are separate loci.
-
-.arch.locus.attr: contiguity, blacklist, zg, current region, @@@@
-
-.arch.locus.attr.exceptional: The client can define a typical large allocation 
-for the locus.  Requests substantially larger than that are deemed exceptional.
-
-.arch.zone-group: To satisfy .req.condemn, we offer zone groups.  Each locus 
-can be a member of a zone group, and the locus manager will attempt to place 
-allocations in this locus in different zones from all the other zone groups.  A 
-zone-group is represented as @@@@.
-
-.arch.page-table: A page table is maintained by the arena, as usual to track 
-association between tracts, pools and segments, and mapping status for VM 
-arenas.
-
-.arch.region: All of the address space is divided into disjoint regions, 
-represented by region objects.  These objects store their current limits, and 
-high and low watermarks of currently allocated tracts (we hope there's usually 
-a gap of empty space between regions).  The limits are actually quite porous 
-and flexible.
-
-.arch.region.assoc: Each region is associated with one contiguous locus or any 
-number of non-contiguous loci (or none).  We call the first kind of region 
-"contiguous".  .arch.locus.assoc: Each locus remembers all regions where it has 
-tracts currently, excepting the badly-placed allocations (see below).  It is 
-not our intention that any locus would have very many, or that loci that share 
-regions would have any reason to stop doing do.
-
-.arch.region.more: Various quantities used by the placement computation are 
-also stored in the regions and the loci.  Regions are created (and destroyed) 
-by the placement recomputation.  Regions are located in stripes (if it's a 
-zoned region), but they can extend into neighboring stripes if an exceptionally 
-large tract allocation is requested (to allow for large objects).
-
-.arch.chunk: Arenas may allocate more address space in additional chunks, which 
-may be disjoint from the existing chunks.  Inter-chunk space will be 
-represented by dummy regions.  There are also sentinel regions at both ends of 
-the address space.
-
-
-Overview of Strategy
-
-.arch.strategy.delay: The general strategy is to delay placement decisions 
-until they have to be made, but no later.
-
-.arch.strategy.delay.until: Hence, the locus manager only makes placement 
-decisions when an allocation is requested (frees and other operations might set 
-a flag to cause the next allocation to redecide).  This also allows the client 
-to change the peak and pool configuration in complicated ways without causing a 
-lot of recomputation, by doing all the changes without allocating in the middle 
-(unless the control pool needs more space because of the changes).
-
-.arch.strategy.normal: While we want the placement to be sophisticated, we do 
-not believe it is worth the effort to consider all the data at each 
-allocation.  Hence, allocations are usually just placed in one of the regions 
-used previously (see .arch.alloc) without reconsidering the issues.
-
-.arch.strategy.normal.limit: However, the manager sets precautionary limits on 
-the regions to ensure that the placement decisions are revisited when an 
-irrevocable placement is about to be made.
-
-.arch.strategy.create: The manager doesn't create new regions until they are 
-needed for allocation (but it might compute where they could be placed to 
-accommodate a peak).
-
-
-Allocation
-
-.arch.alloc: Normally, each allocation to a locus is placed in its current 
-region.  New regions are only sought when necessary to fulfill an allocation 
-request or when there is reason to think the situation has changed 
-significantly (see .arch.significant).
-
-.arch.alloc.same: An allocation is first attempted next to the previous 
-allocation in the same locus, respecting growth direction.  If that is not 
-possible, a good place in the current region is sought.  .arch.alloc.same.hole: 
-ATM, for finding a good place within a region, we just use the current 
-algorithm, limited to the region.  In future, the placement within regions will 
-be more clever.
-
-.arch.alloc.extend: If there's no adequate hole in the current region and the 
-request is not exceptional, the neighboring regions are examined to see if the 
-region could be extended at one border.  (This will basically only be done if 
-the neighbor has shrunk since the last placement recomputation, because the 
-limit was set on sophisticated criteria, and should not be changed without 
-justification.)   .arch.alloc.extend.here: When an allocation is requested next 
-to a specific tract (ArenaAllocHere), we try to extend a little harder [at 
-least for change_size, perhaps not for locality].
-
-.arch.alloc.other: If no way can be found to allocate in the current region, 
-other regions used for this locus are considered in the same way, to see if 
-space can be found there.  [Or probably look at other regions before trying to 
-extend anything?]
-
-.arch.alloc.recompute: When no region of this locus has enough space for the 
-request, or when otherwise required, region placement is recomputed to find a 
-new region for the request (which might be the same region, after extension).
-
-.arch.alloc.current: This region where the allocation was placed then becomes 
-the current region for this locus, except when the request was exceptional, or 
-when the region chosen was "bad" (see @@@@).
-
-.arch.significant: Significant changes to the parameters affecting placement 
-are deemed to have happened at certain client calls and when the total 
-allocation has changed substantially since the last recomputation.  Such 
-conditions set a flag that causes the next allocation to recompute even if its 
-current region is not full [possibly second-guess the decision to recompute 
-after some investigation of the current state?].
-
-
-Deallocation
-
-.arch.free: Deallocation simply updates the counters in the region and the 
-locus.  For some loci, it will make the region of the deallocation the current 
-region.
-.arch.free.remove: If a region becomes entirely empty, it is deleted (and the 
-neighbors limits might be adjusted [quite tricky to get right, this]).
-
-
-Region Placement Recomputation
-
-.arch.gap: When doing placement computations, we view the arena as a sequence 
-of alternating region cores and gaps (which can be small, even zero-sized).  
-Initially, we'll take the core of a region to be the area between the high and 
-low watermark, but in the future we might be more flexible about that.  [Edge 
-determination is actually a worthwhile direction to explore.]
-
-.arch.reach: The gap between two cores could potentially end up being allocated 
-to either region, if they grow in that direction, or one or neither, if they 
-don't.  The set of states that the region assignment could reach by assigning 
-the gaps to their neighbors is called the reach of the current configuration.
-
-.arch.placement.object: The object of the recomputation is to find a 
-configuration of regions that is not too far from the current configuration and 
-that keeps all the peaks inside its reach; if that is not possible, keep the 
-nearest ones in the reach and then minimize the total distance from the rest.
-
-.arch.placement.hypothetical: The configurations that are considered will 
-include hypothetical placements for new regions for loci that cannot fit in 
-their existing regions at the peak.  This is necessary to avoid choosing a bad 
-alternative.
-
-.arch.placement.interesting: The computation will only consider new regions of 
-loci that are deemed interesting, i.e., far from their peak state.  This will 
-reduce the computational burden and avoid jittering near a peak.
-
-[details missing]
-
-
-IMPLEMENTATION
-
-[missing]
-
-
-NOTES
-
-.idea.change: Even after the first segment, be prepared to change your mind, if 
-by the second segment a lot of new loci have been created.
-
-.distance: If the current state is far from a peak, there's time to reassign 
-regions and for free space to appear (in fact, under the steady arena 
-assumption, enough free space _will_ appear).
-
-.clear-pool: Need to have a function to deallocate all objects in a pool, so 
-that PoolDestroy won't have to be used for that purpose.
-
-
- -
- -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
2007-04-24RHSKadd Guide: Manage arena address-space, why, discover layout.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002, 2007 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/message-gc/index.html b/mps/design/message-gc/index.html deleted file mode 100644 index 22835b31226..00000000000 --- a/mps/design/message-gc/index.html +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - -GC Messages - - - - - -
- -

-Ravenbrook / -Projects / -Memory Pool System / -Master Product Sources / -Design Documents -

- -

Memory Pool System Project

- -
- -

GC Messages

- -
-Richard Kistruck, -Ravenbrook Limited, -2008-12-19 -
- -
-(previous version: David Jones, -Ravenbrook Limited, -2003-02-17) -
- -
- -

Design of MPS GC messages:

-
    -
  • mps_message_type_gc_start();
  • -
  • mps_message_type_gc().
  • -
-

They are called "trace start" and "trace end" messages in this document and in most MPS source code.

- -

Readership: any MPS developer. Not confidential.

- -

(For a guide to the MPS message system in general, see <design/message>.)

- - -

Introduction

- -

The MPS posts a trace start message (_gc_start) near the start of every trace (but after calculating the condemned set, so we can report how large it is).

- -

The MPS posts a trace end message (_gc) near the end of every trace.

- -

These messages are extremely flexible: they can hold arbitrary additional data simply by writing new accessor functions. If there is more data to report at either of these two events, then there is a good argument for adding it into these existing messages.

- -

(Note: in previous versions of this design document, there was a partial unimplemented design for a "_gc_generation" message. I would argue that this would not have been a good design, because managing and collating multiple messages is much more complex for both MPS and client than using a single message. RHSK 2008-12-19.)

- - -

Purpose

- -

The purpose of these messages is to allow the client program to be aware of GC activity, in order to:

-
    -
  • adjust its own behaviour programmatically;
  • -
  • show or report GC activity in some appropriate 'custom' way, such as an in-client display, in a log file, etc. The main message content should be intelligible and helpful to client-developers (with help from MPS staff if necessary). There may be extra content that is only meaningful to MPS staff, to help us diagnose client problems.
  • -
- -

While there is some overlap with the Diagnostic Feedback system, the main contrasts are that these GC messages are present in release builds, are stable from release to release, and are designed to be parsed by the client program.

- - -

Names and Parts

- -

Here's a helpful list of the names used in the GC message system:

- -

Implementation is mostly in the source file "traceanc.c" (trace ancillary).

- -

The "_gc_start" message is implemented internally by the "trace start" message. The principal names are:

- -
-Internal names:
-  trace start
-  TraceStartMessage, tsMessage (struct *)
-  arena->tsMessage[ti]
-  MessageTypeGCSTART (enum)
-
-External names:
-  mps_message_type_gc_start (enum macro)
-  MPS_MESSAGE_TYPE_GC_START (enum)
-
- - -

The "_gc" message is implemented internally by the "trace end" message. The principal names are:

- -
-Internal names:
-  trace end
-  TraceMessage, tMessage (struct *)
-  arena->tMessage[ti]
-  MessageTypeGC (enum)
-
-External names:
-  mps_message_type_gc (enum macro)
-  MPS_MESSAGE_TYPE_GC (enum)
-
- -

Note: the names of these messages are unconventional; they should properly be called "gc (or trace) begin" and "gc (or trace) end". But it's much too late to change them now. RHSK 2008-12-15

- -

Collectively, the trace-start and trace-end messages are called the "trace id messages", and they are managed by the following functions:

- -
-Internal names:
-  TraceIdMessagesCheck
-  TraceIdMessagesCreate
-  TraceIdMessagesDestroy
-
- -

The currently supported message-field accessor methods are:

- -
-External names:
-  mps_message_gc_start_why
-  mps_message_gc_live_size
-  mps_message_gc_condemned_size
-  mps_message_gc_not_condemned_size
-
- -

These are documented in the Reference Manual.

- - -

Lifecycle

- -

Overview: for each trace id, pre-allocate a pair of start/end messages (with ControlAlloc). Then, when a trace runs using that trace id, fill-in and post these messages. As soon as the trace has posted both messages, immediately pre-allocate a new pair of messages, which wait in readiness for the next trace to use that trace id.

- - -

Requirements

- -

.no-start-alloc: Should avoid attempting to allocate memory at trace start time.

- -

.no-start-alloc.why: There may be no free memory at trace start time. Client would still like to hear about collections in those circumstances.

- -

.queue: Must support a client that enables, but does not promptly get, GC messages. Ungot messages must remain queued, and the client must be able to get them later without loss. It is not acceptable to stop issuing GC messages for subsequent collections merely because messages from previous collections have not yet been got.

- -

.queue.why: This is because there is simply no reasonable way for a client to guarantee that it always promptly collects GC messages.

- -

.match: Start and end messages should always match up: never post one of the messages but fail to post the matching one.

- -

.match.why: This makes client code much simpler -- it does not have to handle mismatching messages.

- -

.errors-not-direct: Errors (such as a ControlAlloc failure) cannot be reported directly to the client, because collections often happen automatically, without an explicit client call to the MPS interface.

- -

.multi-trace: Up to TraceLIMIT traces may be running, and emitting start/end messages, simultaneously.

- -

.early: Nice to tell client as much as possible about the collection in the start message, if we can.

- -

.similar: Start and end messages are conceptually similar -- it is quite okay, and may be helpful to the client, for the same datum (for example: the reason why the collection occurred) to be present in both the start and end message.

- - -

Storage

- -

For each trace-id (.multi-trace) - a pair (.match) - of start/end messages is -dynamically allocated (.queue) -in advance (.no-start-alloc). -Messages are allocated in the control pool using ControlAlloc.

- -

(Previous implementations of the trace start message used static allocation. This does not satisfy .queue. See also job001570. RHSK 2008-12-15.)

- -

Pointers to these messages are stored in tsMessage[ti] and tMessage[ti] arrays in the ArenaStruct.

- -

(We must not keep the pre-allocated messages, or pointers to them, in the TraceStructs: the memory for TraceStructs is statically allocated, but the values in them are re-initialised by TraceCreate each time the trace id is used, so the TraceStructs are invalid (that is: to be treated as random uninitialised memory) when not being used by a trace. See also job001989. RHSK 2008-12-15.)

- - -

Creating and Posting

- -

At ArenaCreate time we TRACE_SET_ITER to initialise the tsMessage[ti] and tMessage[ti] pointers to NULL, and then (when the control pool is ready) TRACE_SET_ITER calling TraceIdMessagesCreate. This performs the initial pre-allocation of the trace start/end messages for each trace id. Allocation failure is not tolerated here: it makes ArenaCreate fail with an error code, because the arena is deemed to be unreasonably small.

- -

When a trace is running using trace id ti, it finds a pre-allocated message via tsMessage[ti] or tMessage[ti] in the ArenaStruct, fills-in and posts the message, and nulls-out the pointer. (If the pointer was null, no message is sent; see below). The message is now reachable only from the arena message queue (but the control pool also knows about it).

- -

When the trace completes, it calls TraceIdMessagesCreate for its trace id. This performs the ongoing pre-allocation of the trace start/end messages for the next use of this trace id. The expectation is that, after a trace has completed, some memory will have been reclaimed, and the ControlAllocs will succeed.

- -

But allocation failure here is permitted: if it happens, both the start and the end messages are freed (if present). This means that, for the next collection using this trace id, neither a start nor an end message will be sent (.match). There is no direct way to report this failure to the client (.errors-not-direct), so we just increment the "droppedMessages" counter in the ArenaStruct. Currently this counter is never reported to the client (except in diagnostic varieties).

- - -

Getting and Discarding

- -

If the client has not enabled that message type, the message is discarded immediately when posted, calling ControlFree and reclaiming the memory.

- -

If the client has enabled but never gets the message, it remains on the message queue until ArenaDestroy. Theoretically these messages could accumulate forever until they exhaust memory. This is intentional: the client should not enable a message type and then never get it!

- -

Otherwise, when the client gets a message, it is dropped from the arena message queue: now only the client (and the control pool) hold references to it. The client must call mps_message_discard once it has finished using the message. This calls ControlFree and reclaims the memory.

- -

If the client simply drops its reference, the memory will not be reclaimed until ArenaDestroy. This is intentional: the control pool is not garbage-collected.

- - -

Final Clearup

- -

Final clearup is performed at ArenaDestroy, as follows:

-
-
Unused and unsent pre-allocated messages (one per trace id):
-
Freed with TRACE_SET_ITER calling TraceIdMessagesDestroy which calls the message Delete functions (and thereby ControlFree) on anything left in tsMessage[ti] and tMessage[ti].
- -
Ungot messages:
-
Freed by emptying the arena message queue with MessageEmpty.
- -
Got but undiscarded messages:
-
Freed by destroying the control pool.
-
- - -

Testing

- -

The main test is "zmess.c". See notes there.

- -

Various other tests, including "amcss.c", also collect and report mps_message_type_gc and/or mps_message_type_gc_start.

- - -

Coverage

- -

Current tests do not check:

-
    -
  • The less common why-codes (reasons why a trace starts). These should be added to zmess.c.
  • -
- - -

A. References

- - - -

B. Document History

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2003-02-17DRJCreated.
2006-12-07RHSKRemove mps_message_type_gc_generation (not implemented).
2007-02-08RHSKMove historically interesting requirements for mps_message_type_gc_generation (not implemented) to the end of the doc.
2008-12-19RHSKComplete re-write, for new GC message lifecycle. See job001989. (Previous version was //info.ravenbrook.com/project/mps/master/design/message-gc/index.html#2).
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002, 2006-2007, 2008 Ravenbrook Limited. All rights -reserved. This is an open source license. Contact Ravenbrook for -commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met:

- -
    - -
  1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information -on how to obtain complete source code for the this software and any -accompanying software that uses this software. The source code must -either be included in the distribution or be available for no more -than the cost of distribution plus a nominal fee, and must be freely -redistributable under reasonable conditions. For an executable file, -complete source code means the source code for all modules it contains. It -does not include source code for modules or files that typically accompany -the major components of the operating system on which the executable -file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/message/index.html b/mps/design/message/index.html deleted file mode 100644 index 8f6a1707592..00000000000 --- a/mps/design/message/index.html +++ /dev/null @@ -1,637 +0,0 @@ - - - - - - - - -MPS to Client Message Protocol - - - - - -
- -

-Ravenbrook / -Projects / -Memory Pool System / -Master Product Sources / -Design Documents -

- -

Memory Pool System Project

- -
- -

MPS to Client Message Protocol

- -
- -

This document contains a guide to the MPS to Client Message Protocol, followed by the historical initial design. References, History, Copyright and License are at the end.

- -
- -

Guide

- -

Readership: any MPS developer. Not confidential.

- -

Introduction

- -

Messages are used when the MPS needs to asynchronously send information to the client. Currently, messages are used to signal:

-
    -
  • finalization ("_finalization" message);
  • -
  • trace start ("_gc_start" message);
  • -
  • trace end ("_gc" message).
  • -
- -

The Originator of the message is some part of the MPS. For example, the finalization system (see poolmrg.c) is the originator of finalization messages, sent to the client when an object is no longer exactly reachable.

- -

The MPS's Message-system (message.c) keeps messages that have been posted and are awaiting collection by the client in an arena-wide queue -- these are "queued messages".

- -

The Client:

-
    -
  1. periodically calls mps_message_poll() and/or mps_message_get() to get a message from the MPS Message queue;
  2. -
  3. calls accessor functions (eg. mps_message_finalization_ref()) to read data out of the message;
  4. -
  5. calls mps_message_discard() when it has finished using the message.
  6. -
- -

The design is intended to support two alternative models of Client:

-
    -
  • a client with a central function that Gets all messages, and dispatches them to the various parts of the Client;
  • -
  • a client with no such central function, but instead several parts which each Get only the message types they are interested in.
  • -
- - -

The Message-system

- -

The Message-system does just two things:

-
    -
  • class-based method dispatch on any valid message (methods: Delete, slot accessors);
  • -
  • queue for messages that have been Posted but not yet Got.
  • -
- -

Note that message type is now an attribute of a message class: each class implements exactly one type. (But multiple different classes, such as for several different pool classes, may all implement a single common message type).

- - -

How to Originate a Message

- -

Any part of the MPS can be a message Originator. Any struct can be a message, as long as it:

-
    -
  • contains an embedded MessageStruct (used by the Message-system for housekeeping);
  • -
  • makes appropriate MessageInit() and MessageFinish() calls (for its embedded MessageStruct);
  • -
  • has a Delete() function, to be called when the Client calls mps_message_discard();
  • -
  • has appropriate accessor functions.
  • -
- -

The Originator must define a message class, which is simply a struct containing the Delete and accessor functions, and a few other bits of housekeeping. The Originator may wish to define a new message type too.

- -

Here's an example of a message. Notice the embedded MessageStruct:

-
typedef struct TraceStartMessageStruct {
-  Sig sig;
-  char why[TRACE_START_MESSAGE_WHY_LEN];
-  MessageStruct messageStruct;
-} TraceStartMessageStruct;
-
- -

The Originator allocates storage for messages. It is important to consider how to handle the case where this allocation fails because of insufficient free memory. Here are some sensible allocation strategies:

-
    -
  • Pre-allocate the struct when creating the subject it will refer to. The message is then ready to post at any time. This is ideal for subjects that the client creates explicitly, because failure to allocate the message makes the whole operation fail and report a non-OK result code. This approach only allows a fixed number of messages over the entire lifetime of the subject. (Used for finalization messages).

  • -
  • Allocate the struct from control pool (with ControlAlloc) immediately before posting, and free it (with ControlFree) in the Delete method. Must cope with failure to allocate.

  • -
  • Allocate the struct from control pool (with ControlAlloc) long in advance of posting. This is needed for messages that are likely to be emitted when memory is low, such as trace start messages. Must cope with failure to allocate. (Used for trace start and trace end messages).

  • -
- -

Note: Originators should not re-use message structs. Each message should be dynamically allocated, posted once, queued for as long as the client wants, and then freed when the client discards it. Otherwise the Originator is imposing a limit on the maximum number of ungot (queued) messages, which therefore requires the client to either get the messages 'promptly', or risk losing messages. But typically there is no way for the client to reliably meet this promptness constraint. (Note also that the MPS message system does not distinguish between unsent and received states). See also job001570.

- -

If a message cannot be allocated, the Originator should report an error code if possible. If not possible, for example because the message is about an operation that was not explicitly requested by the Client, then there is a "droppedMessages" counter in the arena. Increment this. It's not great, but what else can you do?

- -

It is good design to make the Client's life as easy as possible by making message behaviour as simple as possible. Ideally, make sure that messages will never be dropped. If there is a set of messages that make sense together (eg trace start and trace end), then ideally make sure that the set is 'all or nothing' -- either all messages will be sent, or all will be dropped. Where logical, add new accessors to an existing message, instead of creating a new message type. All this simplifies the code the Client has to write: Client code that has to rendezvous several messages with one another is tricky to write and tricky to test.

- - -

Lifecycle

- -

The normal lifecycle of a Message is:

- -

(alloc Init) unsent (Post) queued (Get) received (Discard Delete Finish free)

- -

The struct is a valid message between Init and Finish. The Originator is permitted to Finish and free an unsent message.

- -

MessagePost() simply links the struct into the message queue (using a RingStruct inside the MessageStruct): no copying occurs. The message is now queued, and MessageOnQueue() returns true. The Originator must not free a queued message.

- -

When the client calls mps_message_get(), the Message-system simply unlinks the message from the queue. The message is now received, and is in use by the client. The Originator must not free or change a received message, because the Client would then have a reference to freed memory, or would see inconsistent data.

- -

When the Client calls mps_message_discard(), the Message-system calls through to the Originator-supplied Delete method. The Originator calls Finish and free.

- -

Abnormal lifecycles

- -

If the Client has not enabled messages of this type (with mps_message_type_enable), Posting the message immediately Discards it, which calls the Delete method:

- -

(alloc Init) unsent (Post Discard Delete Finish free) -- client did not enable this message type

- -

Therefore whenever an Originator calls MessagePost(), beware:

-
    -
  • it must be safe to call the Originator's Delete method;
  • -
  • the delete may deallocate and unmap the message, so the Originator must not use its reference to the message any more.
  • -
- -

If the client has enabled but never gets the message, it remains on the message queue until ArenaDestroy. Theoretically these messages could accumulate forever until they exhaust memory. This is intentional: the client should not enable a message type and then never get it!

- -

(alloc Init) unsent (Post) queued (ArenaDestroy Discard Delete Finish free) -- client never gets message

- -

Messages can also be dropped from the queue if the client calls mps_message_type_disable() when there are already some messages of that type queued:

- -

(alloc Init) unsent (Post) queued (_type_disable Discard Delete Finish free) -- client disables this message type

- -

If the client simply drops its reference without calling mps_message_discard (this is a client error), the memory will not be reclaimed until ArenaDestroy. This is intentional: the control pool is not garbage-collected:

- -

(alloc Init) unsent (Post) queued (Get) received (ArenaDestroy free) -- client never discards message

- - -

Future ideas

- -

Shrinking MessageStruct

- -

(Because every finalised object requires a MessageStruct, so it would be nice to keep it small).

- -

The field Clock postedClock could be implemented and stored by only those message types that use it. A bit messy though.

- - -
- -

Initial Design

- -
-                     MPS TO CLIENT MESSAGE PROTOCOL
-                           design.mps.message
-                             incomplete doc
-                             drj 1997-02-13
-
-INTRODUCTION
-
-.readership: Any MPS developer.
-
-.intro: The MCMP provides a means by which clients can receive messages from 
-the MPS asynchronously.  Typical messages may be low memory notification (or in 
-general low utility), finalization notification, soft-failure notification.  
-There is a general assumption that it should not be disastrous for the MPS 
-client to ignore messages, but that it is probably in the clients best interest 
-to not ignore messages.  The justification for this is that the MPS cannot 
-force the MPS client to read and act on messages, so no message should be 
-critical [bogus, since we cannot force clients to check error codes either - 
-Pekka 1997-09-17].
-
-.contents: This document describes the design of the external and internal 
-interfaces and concludes with a sketch of an example design of an internal 
-client.  The example is that of implementing finalization using PoolMRG.
-
-
-REQUIREMENTS
-
-.req: The MPS/Client message protocol will be used for implementing 
-finalization (see design.mps.finalize and req.dylan.fun.final).  It will also 
-be used for implementing the notification of various conditions (possibly 
-req.dylan.prot.consult is relevant here).
-
-
-INTERFACE
-
-
-External Interface
-
-.if.queue:
-
-Messages are presented as a single queue per arena.  Various functions are 
-provided to inspect the queue and inspect messages in it (see below).
-
-
-Functions
-
-.if.fun:
-
-The following functions are provided:
-
-.if.fun.poll: Poll.  Sees whether there are any messages pending.
-
-mps_bool_t mps_message_poll(mps_arena_t arena);
-
-Returns 1 only if there is a message on the queue of arena.  Returns 0 
-otherwise.
-
-.if.fun.enable: Enable.  Enables the flow of messages of a certain type.
-
-void mps_message_type_enable(mps_arena_t arena, mps_message_type_t type);
-
-Enables the specified message type.  The queue of messages of a arena will 
-contain only messages whose types have been enabled.  Initially all message 
-types are disabled.  Effectively this function allows the client to declare to 
-the MPS what message types the client understands.  The MPS does not generate 
-any messages of a type that hasn't been enabled.  This allows the MPS to add 
-new message types (in subsequent releases of a memory manager) without 
-confusing the client.  The client will only be receiving the messages if they 
-have explicitly enabled them (and the client presumably only enables message 
-types when they have written the code to handle them).
-
-.if.fun.disable: Disable.  Disables the flow of messages of a certain type.
-
-void mps_message_type_disable(mps_arena_t arena, mps_message_type_t type);
-
-The antidote to mps_message_type_enable.  Disables the specified message type.  
-Flushes any existing messages of that type on the queue, and stops any further 
-generation of messages of that type. This permits clients to dynamically 
-decline interest in a message type, which may help to avoid a memory leak or 
-bloated queue when the messages are only required temporarily. 
-
-.if.fun.get: begins a message "transaction".
-
-mps_bool_t mps_message_get(mps_message_t *message_return, mps_arena_t arena, 
-mps_message_type_t type);
-
-If there is a message of the specified type on the queue then the first such 
-message will be removed from the queue and a handle to it will be returned to 
-the client in *messageReturn; in this case the function will return TRUE.  
-Otherwise it will return FALSE.  Having obtained a handle on a message in this 
-way, the client can use the type-specific accessors to find out about the 
-message.  When the client is done with the message the client should call 
-mps_message_discard; failure to do so will result in a resource leak.
-
-.if.fun.discard: ends a message "transaction".
-
-void mps_message_discard(mps_arena_t arena, mps_message_t message);
-
-Indicates to the MPS that the client is done with this message and its 
-resources may be reclaimed.
-
-.if.fun.type.any: Determines the type of a message in the queue
-
-mps_bool_t mps_message_queue_type(mps_message_type_t *type_return, mps_arena_t 
-arena);
-
-Returns 1 only if there is a message on the queue of arena, and in this case 
-updates *type_return to be the type of a message in the queue.  Otherwise 
-returns 0.
-
-.if.fun.type: Determines the type of a message (that has already been got).
-
-mps_message_type_t mps_message_type(mps_arena_t arena, mps_message_t message)
-
-Return the type of the message.  Only legal when inside a message transaction 
-(i.e. after mps_message_get and before mps_message_discard).  Note that the 
-type will be the same as the type that the client passed in the call to 
-mps_message_get.
-
-
-Types of messages
-
-.type: The type governs the "shape" and meaning of the message.
-
-.type.int: Types themselves will just be a scalar quantity, an integer.
-
-.type.semantics: A type indicates the semantics of the message.  
-.type.semantics.interpret: The semantics of a message are interpreted by the 
-client by calling various accessor methods on the message.  .type.accessor: The 
-type of a message governs which accessor methods are legal to apply to the 
-message.
-
-.type.example: Some example types:
-
-.type.finalization: There will be a finalization type.  The type is abstractly: 
-FinalizationMessage(Ref).
-
-.type.finalization.semantics: A finalization message indicates that an object 
-has been discovered to be finalizable (see design.mps.poolmrg.def.final.object 
-for a definition of finalizable).  .type.finalization.ref: There is an accessor 
-to get the reference of the finalization message (i.e. a reference to the 
-object which is finalizable) called mps_message_finalization_ref.  
-.type.finalization.ref.scan: Note that the reference returned should be stored 
-in scanned memory.
-
-
-.compatibility:
-
-Compatibility issues
-
-.compatibility.future.type-new: Notice that message of a type that the client 
-doesn't understand are not placed on the queue, therefore the MPS can introduce 
-new types of message and existing client will still function and will not leak 
-resources.  This has been achieved by getting the client to declare the types 
-that the client understands (with mps_message_type_enable, .if.fun.enable).
-
-.compatibility.future.type-extend: The information available in a message of a 
-given type can be extended by providing more accessor methods.  Old clients 
-won't get any of this information but that's okay.
-
-
-Internal Interface
-
-
-.message.instance: Messages are instances of Message Classes.  
-.message.concrete: Concretely a Message is represented by a MessageStruct.  A 
-MessageStruct has the usual signature field (see design.mps.sig).  A 
-MessageStruct has a type field which defines its type, a ring node, which is 
-used to attach the message to the queue of pending messages, a class field, 
-which identifies a MessageClass object.  .message.intent: The intention is that 
-a MessageStruct will be embedded in some richer object which contains 
-information relevant to that specific type of message.
-
-.message.type:
-
-typedef struct MessageStruct *Message;
-
-.message.struct:
-
-struct MessageStruct {
-  Sig sig;
-  MessageType type;
-  MessageClass class;
-  RingStruct node;
-} MessageStruct;
-
-
-.class: A message class is an encapsulation of methods.  It encapsulates 
-methods that are applicable to all types of messages (generic) and methods that 
-are applicable to messages only of a certain type (type-specific).  
-.class.concrete: Concretely a message class is represented by a 
-MessageClassStruct (a struct).  Clients of the Message module are expected to 
-allocate storage for and initialise the MessageClassStruct.  It is expected 
-that such storage will be allocated and initialised statically.
-
-.class.one-type: A message class implements exactly one message type.  
-The identifier for this type is stored in the "type" field of the 
-MessageClassStruct.  Note that the converse is not true: a single 
-message type may be implemented by two (or more) different message 
-classes (for example: for two pool classes that require different 
-implementations for that message type).
-
-BEGIN OBSOLETE SECTION "class-not-type".
-[.class.not-type.not: It used to be the case that message classes and message 
-types were completely distinct.  This was never used and was unnecessary.  It 
-was removed by making message-type an attribute of the implementing 
-message-class, ie. moving the type field out of MessageStruct and into 
-MessageClassStruct.  RHSK 2008-11-24.]
-.class.not-type: Note that message classes and message types are distinct.  
-.class.not-type.why: (see also mail.drj.1997-07-15.10-33(0) from which this is 
-derived)  This allows two different implementations (ie classes) of messages 
-with the same meaning (ie type).  This may be necessary because the (memory) 
-management of the messages may be different in the two implemtations (which is 
-bogus).  The case of having one class implement two types is not expected to be 
-so useful.  .class.not-type.why.not: It's all pretty feeble justification 
-anyway.
-END OBSOLETE SECTION "class-not-type"
-
-.class.methods.generic: The generic methods are:
-
-delete - used when the message is destroyed (by the client calling 
-mps_message_discard).  The class implementation should finish the message (by 
-calling MessageFinish) and storage for the message should be reclaimed (if 
-applicable).
-
-.class.methods.specific: 
-
-The type specific methods are:
-
-.class.methods.specific.finalization:
-
-Specific to MessageTypeFinalization
-
-finalizationRef - returns a reference to the finalizable object represented by 
-this message.
-
-.class.methods.specific.collectionstats:
-
-Specific to MessageTypeCollectionStats
-
-collectionStatsLiveSize - returns the number of bytes (of objects) that were 
-condemned but survived.
-
-collectionStatsCondemnedSize - returns the number of bytes condemned in the 
-collection.
-
-collectionStatsNotCondemnedSize - returns the the number of bytes (of objects) 
-that are subject to a GC policy (ie collectable) but were not condemned in the 
-collection.
-
-
-.class.type:
-
-typedef struct MessageClassStruct *MessageClass;
-
-.class.sig.double: The MessageClassStruct has a signature field at both ends.  
-This is so that if the MessageClassStruct changes size (by adding extra methods 
-for example) then any static initializers will generate errors from the 
-compiler (there will be a type error causes by initialising a non-sig type 
-field with a sig) unless the static initializers are changed as well.
-
-.class.struct:
-
-typedef struct MessageClassStruct {
-  Sig sig;                      /* design.mps.sig */
-  const char *name;             /* Human readable Class name */
-
-  /* generic methods */
-  MessageDeleteMethod delete;   /* terminates a message */
-
-  /* methods specific to MessageTypeFinalization */
-  MessageFinalizationRefMethod finalizationRef;
-
-  /* methods specific to MessageTypeCollectionStats */
-  MessageCollectionStatsLiveSizeMethod collectionStatsLiveSize;
-  MessageCollectionStatsCondemnedSizeMethod collectionStatsCondemnedSize;
-  MessageCollectionStatsNotCondemnedSizeMethod collectionStatsNotCondemnedSize;
-
-  Sig endSig;                   /* design.mps.message.class.sig.double */
-} MessageClassStruct;
-
-
-.space.queue: The arena structure is augmented with a structure for managing 
-for queue of pending messages.  This is a ring in the ArenaStruct.
-
-struct ArenaStruct
-{
-  ...
-  RingStruct messageRing;
-  ...
-}
-
-
-Functions
-
-.fun.init:
-/* Initializes a message */
-void MessageInit(Arena arena, Message message, MessageClass class);
-
-Initializes the MessageStruct pointed to by message.  The caller of this 
-function is expected to manage the store for the MessageStruct.
-
-.fun.finish:
-/* Finishes a message */
-void MessageFinish(Message message);
-
-Finishes the MessageStruct pointed to by message.  The caller of this function 
-is expected to manage the store for the MessageStruct.
-
-.fun.post:
-/* Places a message on the client accessible queue */
-void MessagePost(Arena arena, Message message);
-
-This function places a message on the queue of a arena.  .fun.post.precondition
-: Prior to calling the function the node field of the message must be a 
-singleton.  After the call to the function the message will be available for 
-MPS client to access.  After the call to the function the message fields must 
-not be manipulated except from the message's class's method functions (i.e., 
-you mustn't poke about with the node field in particular).
-
-.fun.empty:
-void MessageEmpty(Arena arena);
-
-Empties the message queue.  This function has the same effect as discarding all 
-the messages on the queue.  After calling this function there will be no 
-messages on the queue.  .fun.empty.internal-only: This functionality is not 
-exposed to clients.  We might want to expose this functionality to our clients 
-in the future.
-
-
-
-
-Message Life Cycle
-
-.life: A message will be allocated by a client of the message module, it will 
-be initialised by calling MessageInit.  The client will eventually post the 
-message on the external queue (in fact most clients will create a message and 
-then immediately post it).  The message module may then apply any of the 
-methods to the message.  The message module will eventually destroy the message 
-by applying the Delete method to it.
-
-
-EXAMPLES
-
-
-Finalization
-
-[possibly out of date, see design.mps.finalize and design.mps.poolmrg instead 
--- drj 1997-08-28]
-
-This subsection is a sketch of how PoolMRG will use Messages for finalization 
-(see design.mps.poolmrg).
-
-PoolMRG has guardians (see design.mps.poolmrg.guardian), guardians are used to 
-manage final references and detect when an object is finalizable.
-
-The link part of a guardian will include a MessageStruct.
-
-The MessageStruct is allocated when the final reference is created (which is 
-when the referred to object is registered for finalization).  This avoids 
-allocating at the time when the message gets posted (which might be a tricky, 
-undesirable, or impossible, time to allocate).
-
-PoolMRG has two queues: the entry queue, and the exit queue.  The entry 
-queue will use a ring; the exit queue of MRG will simply be the 
-external message queue.
-
-[The evil hack of 'borrowing' MessageStruct's ring node for the entry 
-queue was removed from the code ages ago, so I've removed the account 
-of it from this text too.  RHSK 2006-12-11]
-
-MRG Message class
-
-del - frees both the link part and the reference part of the guardian.
-
-
- -
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
2006-10-25RHSKCreated guide.
2006-12-11RHSKMore on lifecycle; unmention evil hack in initial design.
2008-12-19RHSKSimplify and clarify lifecycle. Remove description of and deprecate re-use of messages.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002, 2006, 2008 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/object-debug/index.html b/mps/design/object-debug/index.html deleted file mode 100644 index 10a5e57f3b1..00000000000 --- a/mps/design/object-debug/index.html +++ /dev/null @@ -1,452 +0,0 @@ - - - - - - - - -Debugging Features for Client Objects - - - - - - - -
-                 DEBUGGING FEATURES FOR CLIENT OBJECTS
-                        design.mps.object-debug
-                             incomplete doc
-                            pekka 1998-09-10
-
-INTRODUCTION
-
-.intro: This is the design for all the various debugging features that MPS 
-clients (and sometimes MPS developers) can use to discover what is happening to 
-their objects and the memory space.
-
-.readership: MPS developers.
-
-
-Document History
-
-.hist.0: The first draft merely records all the various ideas about 
-fenceposting that came up in discussions in June, July and September 1998.  
-This includes the format wrapping idea from mail.ptw.1998-06-19.21-13(0).  
-pekka 1998-09-10
-
-
-OVERVIEW
-
-.over.fenceposts: In its current state, this document mostly talks about 
-fenceposts, straying a little into tagging where theses features have an effect 
-on each other.  [There exist other documents that list other required features, 
-and propose interfaces and implementations.  These will eventually be folded 
-into this one.  pekka 1998-09-10]
-
-
-REQUIREMENTS
-
-.req.fencepost: Try to detect overwrites and underwrites of allocated blocks by 
-adding fenceposts (source req.product.??? VC++, req.epcore.fun.debug.support).  
-.req.fencepost.size: The fenceposts should be at least 4 bytes on either side 
-or 8 bytes if on one side only, with an adjustable content (although VC++ only 
-has 4 bytes with pattern 0xFDFDFDFD, having unwisely combined the 
-implementation with other debug features).
-
-.req.fencepost.check: There should be a function to check all the fenceposts 
-(source req.epcore.fun.debug.support).
-
-.req.free-block: Try to detect attempts to write and read free blocks.
-
-.req.walk: There should be a way to map ("walk") a user function over all 
-allocated objects (except PS VM objects), possibly only in a separate debugging 
-variety/mode (source req.epcore.fun.debug.support).
-
-.req.tag: There should be a way to store at least a word of user data (a "tag", 
-borrowing the SW term) with every object in debugging mode, to be used in 
-memory dumps (source req.product.??? VC++).  .req.tag.walk: The walking 
-function (as required by .req.walk) should have access to this data (source 
-req.epcore.fun.debug.support).
-
-.req.dump.aver: It must be possible to perform a memory dump after an AVER has 
-fired (naturally, if the information required for the dump has been corrupted, 
-it will fail, as softly as possible).  (source @@@@)
-
-[There are more, especially about memory dumps and allocation locations.  pekka 
-1998-09-10]
-
-
-SOLUTION IDEAS
-
-.note.assumptions: I've tried not to assume anything about the coincidence of 
-manual/automatic, formatted/unformatted, and ap/mps_alloc.  I think those 
-questions deserve to be decided on their own merits. instead of being 
-constrained by a debug feature.
-
-.fence.content.repeat: The content of a fencepost could be specified as a 
-byte/word which used repeatedly to fill the fencepost.  
-.fence.content.template: The content could be given as a template which is of 
-the right size and is simply copied onto the fencepost.
-
-.fence.walk: .req.fencepost.check requires the ability to find all the 
-allocated objects.  In formatted pools, this is not a problem.  In unformatted 
-pools, we could use the walker.  It's a feasible strategy to bet that any pool 
-that might have to support fenceposting will also have a walking requirement.  
-.fence.tag: Fenceposting also needs to keep track which objects have 
-fenceposts. unless we manage to do them all.  It would be easiest to put this 
-in the tags.
-
-.fence.check.object: A function to check the fenceposts on a given object would 
-be nice.
-
-.fence.ap: AP's could support fenceposting transparently by having a mode where 
-mps_reserve always goes out-of-line and fills in the fenceposts (the pool's 
-BufferFill method isn't involved).  This would leave the MPS with more freedom 
-of implementation, especially when combined with some of the other ideas.  We 
-think doing a function call for every allocation is not too bad for debugging.
-
-.fence.outside-ap: We could also let the client insert their own fenceposts 
-outside the MPS allocation mechanism.  Even if fenceposting were done like 
-this, we'd still want it to be an MPS feature, so we'd offer sample C macros 
-for adding the size of the fencepost and filling in the fencepost pattern.  
-Possibly something like this (while we could still store the parameters in the 
-pool or ap, there seems little point in doing so in this case, and having them 
-as explicit parameters to the macros allows the client to specify constants to 
-gain effiency):
-  #define mps_add_fencepost(size, fp_size)
-  #define mps_fill_fenceposts(obj, size, fp_size, fp_pattern)
-The client would need to supply their own fencepost checking function, 
-obviously, but again we could offer one that matches the sample macros.
-
-.fence.tail-only: In automatic pools, the presence of a fencepost at the head 
-of the allocated block results in the object reference being an internal 
-pointer.  This means that the format or the pool would need to know about 
-fenceposting and convert between references and pointers.  This would slow down 
-the critical path when fenceposting is used.  This can be ameliorated by 
-putting a fencepost at the tail of
-the block only: this obviates the internal pointer problem and could provide 
-almost the same degree of checking (provided the size was twice as large), 
-especially in copying pools, where there are normally no gaps between allocated 
-blocks.  In addition to the inescapable effects on allocation and freeing 
-(including copying and reclaim thereunder), only scanning would have to know 
-about fenceposts.  .fence.tail-only.under: Walking over all the objects in the 
-pool would be necessary to detect underwrites, as one couldn't be sure that 
-there is a fencepost before any given object (or where it's located exactly).  
-If the pool were doing the checking, it could be sure: it would know about 
-alignments and it could put fenceposts in padding objects (free blocks will 
-have them because they were once allocated) so there'd be one on either side of 
-any object (except at the head of a segment, which is not a major problem, and 
-could be fixed by adding a padding object at the beginning of every segment).  
-This requires some cleverness to avoid splinters smaller than the fencepost 
-size, but it can be done.
-
-.fence.wrapper: On formatted pools, fenceposting could be implemented by 
-"wrapping" the client-supplied format at creation time.  The wrapper can handle 
-the conversion from the fenceposted object and back.  This will be invisible to 
-the client and gives the added benefit that the wrapper can validate fenceposts 
-on every format operation, should it desire.  That is, the pool would see the 
-fenceposts as part of the client object, but the client would only see its 
-object; the format wrapper would translate between the two.  Note that hiding 
-the fenceposts from scan methods, which are required to take a contiguous range 
-of objects, is a bit complicated.  .fence.client-format: The MPS would supply 
-such a wrapper, but clients could also be allowed to write their own 
-fenceposted formats (provided they coordinate with allocation, see below).  
-This would make scanning fenceposted segments more efficient.
-
-.fence.wrapper.variable: Furthermore, you could create different classes of 
-fencepost within a pool, because the fencepost itself could have a variable 
-format.  For instance, you might choose to have the fencepost be minimal (1-2 
-words) for small objects, and more detailed/complex for large objects 
-(imagining that large objects are likely vector-ish and subject to overruns).  
-You could get really
-fancy and have the fencepost class keyed to the object class (e.g., different 
-AP's create different classes of fenceposting).
-
-.fence.wrapper.alloc: Even with a wrapped format, allocation and freeing would 
-still have know about the fenceposts.  If allocation points are used, either 
-MPS-side (.fence.ap) or client-side (.fence.outside-ap) fenceposting could be 
-used, with the obvious modifications.  .fence.wrapper.alloc.format: We could 
-add three format methods, to adjust the pointer and the size for alloc and 
-free, to put down the fenceposts during alloc, and to check them; to avoid 
-slowing down all allocation, this would require some MOPping to make the format 
-class affect the choice of the alloc and free methods (see 
-mail.pekka.1998-06-11.18-18).  .fence.wrapper.alloc.size: We could just 
-communicate the size of the fenceposts between the format and the allocation 
-routines, but then you couldn't use variable fenceposts 
-(.fence.wrapper.variable).  [All this applies to copying and reclaim
-in a straight-forward manner, I think.]
-
-.fence.pool.wrapper: Pools can be wrapped as well.  This could be a natural way 
-to represent/implement the fenceposting changes to the Alloc and Free methods.  
-[@@@@alignment]
-
-.fence.pool.new-class: We could simply offer a debugging version of each pool 
-class (e.g., mps_pool_class_mv_debug).  As we have seen, debugging features 
-have synergies which make it advantageous to have a coordinated implementation, 
-so splitting them up would not just complicate the client interface, it would 
-also be an implementation problem; we can turn features on or off with pool 
-init parameters.
-
-.fence.pool.abstract: We could simply use pool init parameters only to control 
-all debugging features (optargs would be useful here).  While there migh be 
-subclasses and wrappers internally, the client would only see a single pool 
-class; in the internal view, this would be an abstract class, and the 
-parameters would determine which concrete class actually gets instantiated.
-
-.tag.out-of-line: It would be nice if tags were stored out-of-line, so they can 
-be used to study allocation patterns and fragmentation behaviours.  Such an  
-implementation of tagging could also easily be shared among several pools.
-
-
-ARCHITECTURE
-
-.pool: The implementation is at the pool level, because pools manage allocated 
-objects.  A lot of the code will be generic, naturally, but the data structures 
-and the control interfaces attach to pools.  In particular, clients will be 
-able to use tagging and fenceposting separately on each pool.
-
-.fence.size: Having fenceposts of adjustable size and pattern is quite useful.  
-We feel that restricting the size to an integral multiple of the [pool or 
-format?] alignment is harmless and simplifies the implementation enormously.
-
-.fence.template: We use templates (.fence.content.template) to fill in the 
-fenceposts, but we do not give any guarantees about the location of the 
-fenceposts, only that they're properly aligned.  This leaves us the opportunity 
-to do tail-only fenceposting, if we choose.
-
-.fence.slop: [see impl.c.dbgpool.FenceAlloc @@@@]
-
-.fence.check.free: We check the fenceposts when freeing an object.
-
-.unified-walk: Combine the walking and tagging requirements (.req.tag.walk and 
-@@@@) into a generic facility for walking and tagging objects with just one 
-interface and one name: tagging.  Also combine the existing formatted object 
-walker into this metaphor, but allowing the format and tag parameters of the 
-step function be optional [this part has not been implemented yet  pekka 
-1998-09-10].
-
-.init: It simplifies the implementation of both tagging and fenceposting if 
-they are always on, so that we don't have to keep track of which objects have 
-been fenceposted and which have not, and don't have to have three kinds of 
-tags: for user data, for fenceposting, and for both.  So we determine this at 
-pool init time (and let fenceposting turn on tagging, if necessary).
-
-.pool-parameters: Fencepost templates and tag formats are passed in as pool 
-parameters.
-
-.modularity: While a combined generic implementation of tags and fenceposts is 
-provided, it is structured so that each part of it could be implemented by a 
-pool-specific mechanism with a minimum of new protocol.  [This will be 
-improved, when we figure out formatted pools -- they don't need tags for 
-fenceposting.]
-
-.out-of-space: If there's no room for tags, we will not dip into the reservoir, 
-just fail to allocate the tag.  If the alloc call had a reservoir permit, we 
-let it succeed even without a tag, and just make sure the free method will not 
-complain if it can't find a tag.  If the call didn't have a reservoir permit, 
-we free the block allocated for the object and fail the allocation, so that the 
-client gets a chance
-to do whatever low-memory actions they might want to do.  [Should this depend 
-on whether there is anything in the reservoir?]  This breaks the 1-to-1 
-relationship between tags and objects, so some checks cannot be made, but we do 
-count the "lost" tags.
-
-[need to hash out how to do fenceposting in formatted pools]
-
-
-Client interface
-
-.interface.fenceposting:
-
-.interface.fenceposting.check: A function to check all fenceposts in a pool 
-(AVERs if a problem is found)
-  void mps_pool_check_fenceposts(mps_pool_t pool);
-
-[from here on, these are tentative and incomplete]
-
-.interface.fenceposting.format: A function to wrap a format (class) to provide 
-fenceposting
-
-  mps_res_t mps_fmt_fencepost_wrap(mps_fmt_t *format_return,
-                                   mps_arena_t arena,
-                                   mps_fmt_t format,
-                                   [fp parameters])
-
-.interface.fenceposting.add: A format method to adjust size of a block about to 
-be allocted to allow for fenceposts
-
-  void (*mps_fmt_adjust_fencepost_t)(size_t *size_io)
-
-.interface.fenceposting.add: A format method to add a fencepost around a block 
-about to be allocated [the NULL method adds a tail fencepost]
-
-  void (*mps_fmt_put_fencepost_t)(mps_addr_t * addr_io, size_t size)
-
-.interface.fenceposting.add: A format method to check the fenceposts around an 
-object [the NULL method checks tails]
-
-  mps_bool_t (*mps_fmt_check_fenceposts_t)(mps_addr_t)
-
-.interface.fenceposting.pool: A function to wrap a pool class to provide 
-fenceposting (note absence of arena parameter)
-
-  mps_class_t mps_debug_class(mps_class_t class)
-
-.interface.tags.alloc: Three functions to replace existing mps_alloc 
-(request.???.??? proposes to remove the varargs)
-
-  mps_res_t mps_alloc(mps_addr_t *, mps_pool_t, size_t);
-  mps_res_t mps_alloc_dbg(mps_addr_t *, mps_pool_t, size_t, ...);
-  mps_res_t mps_alloc_dbg_v(mps_addr_t *, mps_pool_t, size_t,
-                            va_list);
-
-.interface.tags.walker: Functions to walk all the allocated objects in a pool 
-or an arena (only client pools in this case), format and tag_data can be NULL 
-(tag_data really wants to be void *, not mps_addr_t, because it's stored 
-together with the internal tag data in an MPS internal pool)
-
-  void (*mps_objects_step_t)(mps_addr_t addr, size_t size, mps_fmt_t format,
-                             mps_pool_t pool, void *tag_data, void *p)
-
-  void mps_pool_walk(mps_arena_t arena, mps_pool_t pool,
-                     mps_objects_step_t step, void *p)
-
-  void mps_arena_walk(mps_arena_t arena, mps_objects_step_t step, void *p)
-
-
-Examples
-
-.example.debug-alloc:
-
-#define MPS_ALLOC_DBG(res_io, addr_io, pool, size)
-  MPS_BEGIN
-    static mps_tag_A_s _ts = { __FILE__, __LINE__ };
-
-    *res_io = mps_alloc(addr_io, pool, size, _ts_)
-  MPS_END
-
-
-IMPLEMENTATION
-
-.new-pool: The client interface to control fenceposting consists of the new 
-classes mps_pool_class_mv_debug, mps_pool_class_epdl_debug, and 
-mps_pool_class_epdr_debug, and their new init parameter of type 
-mps_pool_debug_option_s.  [This is a temporary solution, to get it out without 
-writing lots of new interface.  pekka 1998-09-10]
-
-.new-pool.impl: The debug pools are implemented using the "class wrapper" 
-EnsureDebugClass, which produces a subclass with modified init, finish, alloc, 
-and free methods.  These methods are implemented in the generic debug class 
-code (impl.c.dbgpool), and are basically wrappers around the superclass methods 
-(invoked through the pool->class->super field).  To find the data stored in the 
-class for the debugging features, they use the debugMixin method provided by 
-the subclass.  So to make a debug subclass, three things should be provided: a 
-structure definition of the instance containing a PoolDebugMixinStruct, a pool 
-class function that uses
-EnsureDebugClass, and a debugMixin method that locates the PoolDebugMixinStruct 
-within an instance.
-
-.tags.splay: The tags are stored in a splay tree of tags allocated from a 
-subsidiary MFS pool.  The client needs to specify the (maximum) size of the 
-client data in a tag, so that the pool can be created.
-
-[Lots more should be said, eventually.  pekka 1998-09-10]
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 2001 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/pool/index.html b/mps/design/pool/index.html deleted file mode 100644 index 0d13918b02a..00000000000 --- a/mps/design/pool/index.html +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - -The design of the pool and pool class mechanisms - - - - - - - -
-            THE DESIGN OF THE POOL AND POOL CLASS MECHANISMS
-                            design.mps.pool
-                             incomplete doc
-                           richard 1996-07-31
-
-- This document must derive the requirements for pool.c etc. from the 
-architecture.
-
-
-
-.def.outer-structure: The "outer structure" (of a pool) is a C object of type 
-PoolXXXStruct or the type struct PoolXXXStruct itself.
-.def.generic-structure: The "generic structure" is a C object of type 
-PoolStruct (found embedded in the outer-structure) or the type struct 
-PoolStruct itself.
-
-.align: When initialised, the pool gets the default alignment (ARCH_ALIGN).
-
-.no: If a pool class doesn't implement a method, and doesn't expect it to be 
-called, it should use a non-method (PoolNo*) which will cause an assertion 
-failure if they are reached. 
-
-.triv: If a pool class supports a protocol but does not require any more than a 
-trivial implementation, it should use a trivial method (PoolTriv*) which will 
-do the trivial thing.
-
-.outer-structure.sig: It is good practice to put the signature for the outer 
-structure at the end (of the structure).  This is because there's already one 
-at the beginning (in the poolStruct) so putting it at the end gives some extra 
-fencepost checking.
-
-REQUIREMENTS
-
-[Placeholder]
-
-.req.fix: PoolFix must be fast.
-
-
-OTHER
-
-Interface in mpm.h
-Types in mpmst.h
-See also design.mps.poolclass
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poolamc/index.html b/mps/design/poolamc/index.html deleted file mode 100644 index ae004183ae0..00000000000 --- a/mps/design/poolamc/index.html +++ /dev/null @@ -1,770 +0,0 @@ - - - - - - - - -MPS AMC pool class - - - - - - - -

This document contains a guide to the MPS AMC pool class, followed by the historical initial design. References, History, Copyright and License are at the end.

- -
- -

Guide

- -

Readership: any MPS developer. Not confidential.

- -

Introduction

-

The AMC pool class is a general-purpose automatic (collecting) pool class. It is intended for most client objects. AMC is "Automatic, Mostly Copying": it preserves objects by copying, except when an ambiguous reference 'nails' the object in place. It is generational. Chain: specify capacity and mortality of generations 0..N-1. Survivors from N-1 get promoted into an arena-wide topGen (often anachronistically called the "dynamic" generation). -

- -

Design documentation for AMC is rather incomplete. There is some in the wiki.

- - -

AMC Seg States

- -

AMC Segs are in one of three states: "mobile", "boarded", or "stuck" [This is new terminology, not used in the initial design, and not yet widespread in the source code -- RHSK 2009-09-14]. Segs are normally "mobile": all objects on the seg are un-nailed, and thus may be preserved by copying. An ambiguous reference to any address within an AMC seg makes that seg "boarded": a nailboard is allocated to record ambiguous refs ("nails"), but un-nailed objects on the seg are still preserved by copying. Stuck segments only occur in emergency tracing: a discovery fix to an object in a mobile segment is recorded in the only non-allocating way available: by making the entire segment "stuck".

- - -

Pads

- -

(See also job001809 and job001811, and mps/branch/2009-03-31/padding)

- -

A pad is logically a trivial client object. Pads are created by the MPS asking the client's format code to create them, to fill up a space in a seg. Thereafter, the pad appears to the MPS as a normal client object (that is: the MPS cannot distinguish a pad from a client object).

- -

AMC creates pads for three reasons: buffer empty, LSP, or NMR. (LSP pads are new with job001811).

- -

Buffer empty pads are made by AMCBufferEmpty whenever it detaches a non-empty buffer from an AMC segment. Buffer detachment is most often caused because the buffer is too small for the current buffer reserve request (which may be either a client requested or a forwarding allocation). Detachment may happen for other reasons, such as trace flip.

- -

LSP pads (Large Segment Padding) are made by AMCBufferFill when the requested fill size is 'large' (see "The LSP payoff calculation" below). AMCBufferFill fills the buffer to exactly the size requested by the current buffer reserve operation; that is: it does not round up to the whole segment size. This prevents subsequent small objects being placed in the same segment as a single very large object. If the buffer fill size is less than the segment size, AMCBufferFill fills any remainder with an LSP pad.

- -

NMR pads (Non-Mobile Reclaim) are made by amcReclaimNailed, when performing reclaim on a non-mobile (that is: either boarded or stuck) segment:

- -

The more common NMR scenario is reclaim of a boarded seg after a non-emergency trace. Ambiguous refs into the seg are recorded as nails. Subsequent exact refs to a nailed object do nothing further, but exact refs that do not match a nail cause preserve-by-copy and leave a forwarding object. Unreachable objects are not touched during the scan+fix part of the trace. On reclaim, only nailed objects need to be preserved; others (namely forwarding pointers and unreachable objects) are replaced by an NMR pad. (Note that a BE or LSP pad appears to be an unreachable object, and is therefore overwritten by an NMR pad).

- -

The less common NMR scenario is after emergency tracing. Boarded segs still occur; they may have nailed objects from ambiguous refs, forwarding objects from pre-emergency exact fixes, nailed objects from mid-emergency exact fixes, and unpreserved objects; reclaim is as in the non-emergency case. Stuck segs may have forwarding objects from pre-emergency exact fixes, objects from mid-emergency fixes, and unreachable objects -- but the latter two are not distinguishable because there is no nailboard. On reclaim, all objects except forwarding pointers are preserved; each forwarding object is replaced by an NMR pad.

- -

If amcReclaimNailed finds no objects to be preserved then it calls SegFree (new with job001809).

- - -

Placement Pads are okay

- -

Placement Pads are the BE and LSP pads created in "to-space" when placing objects into segments. This wasted space is an expected space-cost of AMC's naive (but time-efficient) approach to placement of objects into segments. This is normally not a severe problem. (The worst case is a client that always requests ArenaAlign()+1 byte objects: this has a nearly 100% overhead).

- - -

Retained Pads could be a problem

- -

Retained Pads are the NMR pads stuck in "from-space": non-mobile segments that were condemned but have preserved-in-place objects cannot be freed by amcReclaimNailed. The space around the preserved objects is filled with NMR pads.

- -

In the worst case, retained pads could waste an enormous amount of space! A small (1 byte) object could retain a multi-page segment for as long as the ambiguous reference persists; that is: indefinitely. Imagine a 256-page (1 MiB) segment containing a very large object followed by a handful of small objects. An ambiguous ref to one of the small objects will unfortunately cause the entire 256-page seg to be retained, mostly as an NMR pad; this is a massive overhead of wasted space.

- -

AMC mitigates this worst-case behaviour, by treating large segments specially.

- - -

Small, Medium, and Large Segments

- -

AMC categorises segments as "small" (1 page), "medium" (several pages), or "large" (>= AMCLargeSegPAGES pages):

- -
      pages = SegSize(seg) / ArenaAlign(arena);
-      if(pages == 1) {
-        /* small */
-      } else if(pages < AMCLargeSegPAGES) {
-        /* medium */
-      } else {
-        /* large */
-      }
- -

AMCLargeSegPAGES is currently 8 -- see "The LSP payoff calculation" below.

- -

AMC might treat "Large" segments specially, in two ways:

-
    -
  • .large.single-reserve: A large segment is only used for a single (large) buffer reserve request; the remainder of the segment (if any) is immediately padded with an LSP pad.
  • -
  • .large.lsp-no-retain: Nails to such an LSP pad do not cause AMCReclaimNailed to retain the segment.
  • -
- -

.large.single-reserve is implemented. See job001811.

- -

.large.lsp-no-retain is NOT currently implemented.

- -

The point of .large.lsp-no-retain would be to avoid retention of the (large) segment when there is a spurious ambiguous reference to the LSP pad at the end of the segment. Such an ambiguous reference might happen naturally and repeatably if the preceding large object is an array, the array is accessed by an ambiguous element pointer (eg. on the stack), and the element pointer ends up pointing just off the end of the large object (as is normal for sequential element access in C) and remains with that value for a while. (Such an ambiguous reference could also occur by chance, eg. by coincidence with an int or float, or when the stack grows to include old unerased values).

- -

Implementing .large.lsp-no-retain is a little tricky. A pad is indistinguishable from a client object, so AMC has no direct way to detect, and safely ignore, the final LSP object in the seg. If AMC could guarantee that the single buffer reserve (.large.single-reserve) is only used for a single object, then AMCReclaimNailed could honour a nail at the start of a large seg and ignore all others; this would be extremely simple to implement. But AMC cannot guarantee this, because in the MPS Allocation Point Protocol the client is permitted to make a large buffer reserve and then fill it with many small objects. In such a case, AMC must honour all nails (if the buffer reserve request was an exact multiple of ArenaAlign), or all nails except to the last object (if there was a remainder filled with an LSP pad). Because an LSP pad cannot be distinguished from a client object, and the requested allocation size is not recorded, AMC cannot distinguish these two conditions at reclaim time. Therefore AMC must record whether or not the last object in the seg is a pad, in order to ignore nails to it. This could be done by adding a flag to AMCSegStruct. (This can be done without increasing the structure size, by making the "Bool new;" field smaller than its current 32 bits.)

- - -

The LSP payoff calculation

- -

The job001811 LSP fix treats large segments differently. Without it, after allocating a very large object (in a new very large multi-page segment), MPS would happily place subsequent small objects in any remaining space at the end of the segment. This would risk pathological fragmentation: if these small objects were systematically preserved by ambiguous refs, enormous NMR pads would be retained along with them.

- -

The payoff calculation is a bit like deciding whether or not to purchase insurance. For single-page and medium-sized segments, we go ahead and use the remaining space for subsequent small objects. This is equivalent to choosing not to purchase insurance. If the small objects were to be preserved by ambiguous refs, the retained NMR pads would be big, but not massive. We expect such ambiguous refs to be uncommon, so we choose to live with this slight risk of bad fragmentation. The benefit is that the remaining space is used.

- -

For large segments, we decide that the risk of using the remainder is just too great, and the benefit too small, so we throw it away as an LSP pad. This is equivalent to purchasing insurance: we choose to pay a known small cost every time, to avoid risking an occasional disaster.

- -

To decide what size of segment counts as "large", we must decide how much uninsured risk we can tolerate, versus how much insurance cost we can tolerate. The likelihood of ambiguous references retaining objects is entirely dependent on client behaviour. However, as a sufficient 'one size fits all' policy, I (RHSK 2009-09-14) have judged that segments smaller than 8 pages long do not need to be treated as large: the insurance cost to 'play safe' would be considerable (wasting up to 1 page of remainder per 7 pages of allocation), and the fragmentation overhead risk is not that great (at most 8 times worse than the unavoidable minimum). So AMCLargeSegPAGES is defined as 8 in config.h. As long as the assumption that most segments are not ambiguously referenced remains correct, I expect this policy will be satisfactory.

- -

To verify that this threshold is acceptable for a given client, poolamc.c calculates metrics; see "Feedback about retained pages" below. If this one-size-fits-all approach is not satisfactory, AMCLargeSegPAGES could be made a client-tunable parameter.

- - -

Retained pages

- -

The reasons why a segment and its pages might be retained are:

-
    -
  1. ambiguous ref to first-obj: unavoidable page retention (only the mutator can reduce this, if they so wish, by nulling out ambig refs);
  2. -
  3. ambiguous ref to rest-obj: tuning MPS LSP policy could mitigate this, reducing the likelihood of rest-objs being co-located with large first-objs;
  4. -
  5. ambiguous ref to final pad: implementing .large.lsp-no-retain could mitigate this;
  6. -
  7. ambiguous ref to other (NMR) pad: hard to mitigate, as pads are indistinguishable from client objects;
  8. -
  9. emergency trace;
  10. -
  11. non-object-aligned ambiguous ref: fixed by job001809;
  12. -
  13. other reason (eg. buffered at flip): not expected to be a problem.
  14. -
- -

(This list puts the reasons that are more 'obvious' to the client programmer first, and the more obscure reasons last).

- - -

Feedback about retained pages

- -

(New with job001811). AMC now accumulates counts of pages condemned and retained during a trace, in categories according to size and reason for retention, and emits diagnostic at trace-end via the pool->class->traceEnd method. See comments on the PageRetStruct in poolamc.c. These page-based metrics are not as precise as actually counting the size of objects, but they require much less intrusive code to implement, and should be sufficient to assess whether AMC's page retention policies and behaviour are acceptable.

- -
- -

Initial Design

- -
-      THE DESIGN OF THE AUTOMATIC MOSTLY-COPYING MEMORY POOL CLASS
-                           design.mps.poolamc
-                           incomplete design
-                           richard 1995-08-25
-
-INTRODUCTION
-
-.intro: This is the design of the AMC Pool Class.  AMC stands for Automatic 
-Mostly-Copying.  This design is highly fragmentory and some may even be 
-sufficiently old to be misleading.
-
-.readership: The intended readership is any MPS developer.
-
-
-OVERVIEW
-
-.overview: This class is intended to be the main pool class used by Harlequin 
-Dylan.  It provides garbage collection of objects (hence "automatic").  It uses 
-generational copying algorithms, but with some facility for handling small 
-numbers of ambiguous references.  Ambiguous references prevent the pool from 
-copying objects (hence "mostly copying").  It provides incremental collection.
-
-[ lot of this design is awesomely old -- drj 1998-02-04]
-
-
-DEFINITIONS
-
-.def.grain: Grain.  An quantity of memory which is both aligned to the pool's 
-alignment and equal to the pool's alignment in size.  IE the smallest amount of 
-memory worth talking about.
-
-
-DESIGN
-
-Segments
-
-.seg.class: AMC allocates segments of class AMCSegClass, which is a subclass of 
-GCSegClass. Instances contain a segTypeP field, which is of type int*. .seg.gen
-: AMC organizes the segments it manages into generations.  .seg.gen.map: Every 
-segment is in exactly one generation. .seg.gen.ind: The segment's segTypeP 
-field indicates which generation (that the segment is in) (an AMCGenStruct see 
-blah below).  .seg.typep: The segTypeP field actually points to either the type 
-field of a generation or to the type field of a nail board.  
-.seg.typep.distinguish: The type field (which can be accessed in either case) 
-determines whether the segTypeP field is pointing to a generation or to a nail 
-board.  .seg.gen.get: The map from segment to generation is implemented by 
-AMCSegGen which deals with all this.
-
-
-Fixing and Nailing
-
-[.fix.nail.* are placeholders for design rather than design really-- drj 
-1998-02-04]
-.fix.nail:
-
-.nailboard: AMC uses a nail board structure for recording ambiguous references 
-to segments.  A nail board is a bit table with one bit per grain in the 
-segment.  .nailboard.create: Nail boards are allocated dynamically whenever a 
-segment becomes newly ambiguously referenced.  .nailboard.destroy: They are 
-deallocated during reclaim.  Ambiguous fixes simply set the appropriate bit in 
-this table.  This table is used by subsequent scans and reclaims in order to 
-work out what objects were marked.
-
-.nailboard.emergency: During emergency tracing two things relating to nail 
-boards happen that don't normally: .nailboard.emergency.nonew: Nail boards 
-aren't allocated when we have new ambiguous references to segments 
-(.nailbaord.emergency.nonew.justify: We could try and allocate a nail board, 
-but we're in emergency mode so short of memory so it's unlikely to succeed, and 
-there would be additional code for yet another error path which complicates 
-things); .nailboard.emergency.exact: nail boards are used to record exact 
-references in order to avoid copying the objects.  .nailboard.hyper-c
-onservative: Not creating new nail boards (.nailboard.emergency.nonew above) 
-means that when we have a new reference to a segment during emergency tracing 
-then we nail the entire segment and preserve everything in place.
-
-.fix.nail.states:
-
-Partition the segment states into 4 sets:
-  white segment and not nailed (and has no nail board)
-  white segment and nailed and has no nail board
-  white segment and nailed and has nail board
-  the rest
-
-.fix.nail.why: A segment is recorded as being nailed when either there is an 
-ambiguous reference to it, or there is an exact reference to it and the object 
-couldn't be copied off the segment (because there wasn't enough memory to 
-allocate the copy).  In either of these cases reclaim cannot simply destroy the 
-segment (usually the segment will not be destroyed because it will have live 
-objects on it, though see .nailboard.limitations.middle below).  If the segment 
-is nailed then we might be using a nail board to mark objects on the segment.  
-However, we cannot guarantee that being nailed implies a nail board, because we 
-might not be able to allocate the nail board.  Hence all these states actually 
-occur in practice.
-
-.fix.nail.distinguish: The nailed bits in the segment descriptor (SegStruct) 
-are used to record whether a segment is nailed or not.  The segTypeP field of 
-the segment either points to (the "type" field of) an AMCGen or to an 
-AMCNailBoard, the type field can be used to determine which of these is the 
-case.  (see .seg.typep above).
-
-.nailboard.limitations.single: Just having a single nail board per segment 
-prevents traces from improving on the findings of each other: a later trace 
-could find that a nailed object is no longer nailed or even dead.  Until the 
-nail board is discarded, that is.  .nailboard.limitations.middle: An ambiguous 
-reference into the middle of an object will cause the segment to survive, even 
-if there are no surviving objects on it.  .nailboard.limitations.reclaim: 
-AMCReclaimNailed could cover each block of reclaimed objects between two nailed 
-objects with a single padding object, speeding up further scans.
-
-
-Emergency Tracing
-
-.emergency.fix: AMCFixEmergency is at the core of AMC's emergency tracing 
-policy (unsurprisingly).  AMCFixEmergency chooses exactly one of three options: 
-a) use the existing nail board structure to record the fix, b) preserve and 
-nail the segment in its entirety, c) snapout an exact (or high rank) pointer to 
-a broken heart to the broken heart's forwarding pointer.  If the rank of the 
-reference is AMBIG then it either does a) or b) depending on wether there is an 
-existing nail board or not.  Otherwise (the rank is exact or higher) if there 
-is a broken heart it is used to snapout the pointer.  Otherwise it is as for an 
-AMBIG ref (we either do a) or b)).
-
-.emergency.scan: This is basically as before, the only complication is that 
-when scanning a nailed segment we may need to do multiple passes, as 
-FixEmergency may introduce new marks into the nail board.
-
-
-Buffers
-
-.buffer.class: AMC uses buffer of class AMCBufClass (a subclass of SegBufClass) 
-.buffer.gen: Each buffer allocates into exactly one generation.  .buffer.field.gen: 
-AMCBuf buffer contain a gen field which points to the generation that the 
-buffer allocates into.  .buffer.fill.gen: AMCBufferFill uses the generation 
-(obtained from the gen field) to initialise the segment's segTypeP field which 
-is how segments get allocated in that generation.
-
-.buffer.condemn: We condemn buffered segments, but not the contents of the 
-buffers themselves, because we can't reclaim uncommitted buffers (see 
-design.mps.buffer for details).  If the segment has a forwarding buffer on it, 
-we detach it [why? @@@@ forwarding buffers are detached because they used to 
-cause objects on the same segment to not get condemned, hence caused retention 
-of garbage.  Now that we condemn the non-buffered portion of buffered segments 
-this is probably unnecessary -- drj 1998-06-01  But it's probably more 
-efficient than keeping the buffer on the segment, because then the other stuff 
-gets nailed -- pekka 1998-07-10].  If the segment has a mutator buffer on it, 
-we nail the buffer.  If the buffer cannot be nailed, we give up condemning, 
-since nailing the whole segment would make it survive anyway.  The scan methods 
-skip over buffers and fix methods don't do anything to things that have already 
-been nailed, so the buffer is effectively black.
-
-
-AMCStruct
-
-.struct: AMCStruct is the pool class AMC instance structure.  .struct.pool: 
-Like other pool class instances, it contains a PoolStruct containing the 
-generic pool fields.
-
-.struct.format: The "format" field points to a Format structure describing the 
-object format of objects allocated in the pool.  The field is intialized by 
-AMCInit from a parameter, and thereafter it is not changed until the pool is 
-destroyed.  [actually the format field is in the generic PoolStruct these 
-days.  drj 1998-09-21]
-
-[lots more fields here]
-
-
-
-Generations
-
-.gen: Generations partition the segments that a pool manages (see .seg.gen.map 
-above).  .gen.collect: Generations are more or less the units of condemnation 
-in AMC.  And also the granularity for forwarding (when copying objects during a 
-collection): all the objects which are copied out of a generation use the same 
-forwarding buffer for allocating the new copies, and a forwarding buffer 
-results in allocation in exactly one generation.
-
-.gen.rep: Generations are represented using an AMCGenStruct structure.  
-
-.gen.create: All the generation are create when the pool is created (during 
-AMCInitComm).
-
-.gen.manage.ring: An AMC's generations are kept on a ring attached to the 
-AMCStruct (the genRing field).  .gen.manage.array: They are also kept in an 
-array which is allocated when the pool is created and attached to the AMCStruct 
-(the gens field holds the number of generations, the gen field points to an 
-array of AMCGen).  [it seems to me that we could probably get rid of the ring 
--- drj 1998-09-22]
-
-.gen.number: There are AMCTopGen + 2 generations in total.  "normal" 
-generations numbered from 0 to AMCTopGen inclusive and an extra "ramp" 
-generation (see .gen.ramp below).
-
-.gen.forward: Each generation has an associated forwarding buffer (stored in 
-the "forward" field of AMCGen).  This is the buffer that is used to forward 
-objects out of this generation.  When a generation is created in AMCGenCreate, 
-its forwarding buffer has a NULL p field, indicating that the forwarding buffer 
-has no generation to allocate in.  The collector will assert out (in 
-AMCBufferFill where it checks that buffer->p is an AMCGen) if you try to 
-forward an object out of such a generation.  .gen.forward.setup: All the 
-generation's forwarding buffer's are associated with generations when the pool 
-is created (just after the generations are created in AMCInitComm).
-
-
-Ramps
-
-.ramp: Ramps usefully implement the begin/end
-mps_alloc_pattern_ramp interface.
-
-.gen.ramp: To implement ramping
-(request.dylan.170423), AMC uses a special "ramping mode", where
-promotions are redirected.  One generation is designated the "ramp
-generation" (amc->rampGen in the code).
-
-.gen.ramp.ordinary:
-Ordinarily, that is whilst not ramping, objects are promoted into the
-ramp generation from younger generations and are promoted out to older
-generations.  The generation that the ramp generation ordinarily promotes
-into is designated the "after-ramp generation" (amc->afterRampGen).
-
-.gen.ramp.particular: As of 2002-02-06
-the ramp generation is the second oldest generation and the after-ramp
-generation is the oldest generation.
-
-.gen.ramp.possible:
-(Old design notes) In alternative designs it might be possible to make
-the ramp generation a special generation that is only promoted into
-during ramping (AMCRampGenFollows), however, this is not done.
-
-.gen.ramp.ramping:
-The ramp generation is promoted into itself during ramping mode;
-
-.gen.ramp.after:
-after this mode ends, the ramp generation is promoted into the
-after-ramp generation as usual.  .gen.ramp.after.once: Care is taken to
-ensure that there is at least one collection where stuff is promoted
-from the ramp generation to the after-ramp generation even if ramping
-mode is immediately re-entered.
-
-.ramp.mode: This behaviour
-is controlled in a slightly convoluted manner by a state machine.
-The rampMode field of the pool forms an important part of the state of
-the machine.
-
-There are five states:
-  outside, begin, ramping, finish, collecting
-
-These appear in the code as RampOUTSIDE, and so on.
-
-.ramp.state.cycle.usual: The usual
-progression of states is a cycle:
-outside -> begin -> ramping -> finish -> collecting -> outside.
-
-.ramp.count: The pool just
-counts the number of ap's that have begun ramp mode (and not ended).
-No state changes occur unless this count goes from 0 to 1 (entering
-ramping) or from 1 to 0 (leaving ramping).  In other words, all nested
-ramps are ignored (see code in AMCRampBegin and AMCRampEnd).
-
-.ramp.state.invariants: In states
-collecting and outside the count must be 0.  In states begin and ramping
-the count must be > 0.  In state finish the count is not constrained
-(but it must be >= 0 anyway).
-
-.ramp.begin: When the count goes
-up from zero, the states moves from collecting or outside to begin; if
-the state is finish then no transition takes place (it cannot be in
-state begin or ramping).
-
-.ramp.begin.leave:
-We can leave the begin state to either the state outside or the state
-ramping.  .ramp.begin.leave.outside: We go to outside if the count drops
-to 0 before a collection starts.  This shortcuts the usual cycle of
-states for small enough ramps.  .ramp.begin.leave.ramping: We enter the
-ramping state if a collection starts that condemns the ramp generation
-(pedantically when a new GC begins, and a segment in the ramp generation is
-condemned we leave the begin state, see AMCWhiten).  At this point
-we switch the forwarding generations to forward in the ramping way (.gen.ramp);
-the pool enters ramping mode.  (This assumes that each generation is
-condemned together with all lower generations.)
-
-.ramp.end: After the ramp count goes
-back to zero, the pool enters the finish state if it was in the ramping
-state, or shortcuts the usual cycle by going to the outside state if it
-was in the begin state.  If it was already in the finish state then it
-stay there.  It can't be in any other state.
-
-.ramp.finish: We stay in
-the finish state until we do a GC that condemns the ramp generation,
-and we ensure that such a GC will promote from the ramp generation to
-the after-ramp generation.  In fact, the next new GC should collect the
-ramp generation because we jig the benefits to ensure that [is this
-true? drj 2002-03-06].
-
-.ramp.finish.leave:
-We leave this state when the GC starts the condemn phase and we enter
-collecting state.  At this point the forwarding generations are also
-switched so that the ramp generation promotes into the after-ramp
-generation.
-
-.ramp.collecting.leave: We leave the
-collecting state when the GC enters reclaim (specifically, when a segment
-in the ramp generation is reclaimed).  Ordinarily we enter the outside
-state, but if the client has increased the ramp count then we go directly
-to the begin state.  The forwarding generations are not switched until
-we leave this state, ensuring that we perform a whole collection with
-the ramp generation promoting to the after-ramp generation.
-
-.ramp.collect-all
-There are two flavours of ramp collections: the normal one that collects
-the ramp generation and the younger ones, and the collect-all flavour that
-does a full GC (this is a hack for producing certain Dylan statistics).
-The collection will be of collect-all flavour, if any of the RampBegins
-during the corresponding rank asked for that.  Ramp beginnings and
-collections are asynchronous, so we need two fields to implement this
-behaviour: collectAll to indicate whether the ramp collection that is
-about to start should be collect-all, and collectAllNext to keep track
-of whether the current ramp has any requests for it.
-
-
-
-Headers
-
-.header: AMC supports a fixed-size header on objects, with the client pointers 
-pointing after the header, rather than the base of the memory block.  See 
-format documentation for details of the interface.  .header.client: The code 
-mostly deals in client pointers, only computing the base and limit of a block 
-when these are needed (such as when an object is copied).  In several places, 
-the code gets a block of some sort, a segment or a buffer, and creates a client 
-pointer by adding the header length (pool->format->headerLength).  .header.fix: 
-There are two versions of the fix method, due to its criticality, with 
-(AMCHeaderFix) and without (AMCFix)  headers.  The correct one is selected in 
-AMCInitComm, and placed in the pool's fix field.  This is the main reason why 
-fix methods dispatch through the instance, rather than the class like all other 
-methods.
-
-
-OLD AND AGING NOTES BELOW HERE:
-
-
-AMCFinish
-
-.finish:
-
-.finish.forward:
-   103    /* If the pool is being destroyed it is OK to destroy */
-   104    /* the forwarding buffers, as the condemned set is about */
-   105    /* to disappear. */
-
-
-AMCBufferEmpty
-
-.flush: Removes the connexion between a buffer and a group, so that the group 
-is no longer buffered, and the buffer is reset and will cause a refill when 
-next used.
-
-.flush.pad: The group is padded out with a dummy object so that it appears full.
-
-.flush.expose: The buffer needs exposing before writing the padding object onto 
-it.  If the buffer is being used for forwarding it might already be exposed, in 
-this case the segment attached to it must be covered when it leaves the 
-buffer.   See .fill.expose.
-
-.flush.cover: The buffer needs covering whether it was being used for 
-forwarding or not.  See .flush.expose.
-
-
-AMCBufferFill
-
-.fill:
-   185   * Reserve was called on an allocation buffer which was reset,
-   186   * or there wasn't enough room left in the buffer.  Allocate a group
-   187   * for the new object and attach it to the buffer.
-   188   *
-.fill.expose:
-   189   * .fill.expose: If the buffer is being used for forwarding it may
-   190   * be exposed, in which case the group attached to it should be
-   191   * exposed.  See .flush.cover.
-
-
-AMCBufferTrip
-
-.trip:
-   239   * A flip occurred between a reserve and commit on a buffer, and
-   240   * the buffer was "tripped" (limit set to zero).  The object wasn't
-   241   * scanned, and must therefore be assumed to be invalid, so the
-   242   * reservation must be rolled back. This function detaches the
-   243   * buffer from the group completely.  The next allocation in the
-   244   * buffer will cause a refill, and reach AMCFill.
-
-
-AMCBufferFinish
-
-.buffer-finish:
-   264   * Called from BufferDestroy, this function detaches the buffer
-   265   * from the group it's attached to, if any.
-
-
-AMCFix
-
-.fix:
-   281   * fix an ambiguous reference to the pool
-   282   *
-   283   * Ambiguous references lock down an entire segment by removing it
-   284   * from old-space and also marking it grey for future scanning.
-   285   *
-   286   * fix an exact, final, or weak reference to the pool
-   287   *
-   288   * These cases are merged because the action for an already
-   289   * forwarded object is the same in each case.  After that
-   290   * situation is checked for, the code diverges.
-   291   *
-   292   * Weak references are either snapped out or replaced with
-   293   * ss->weakSplat as appropriate.
-   294   *
-   295   * Exact and final references cause the referenced object to be copied t
-o
-   296   * new-space and the old copy to be forwarded (broken-heart installed)
-   297   * so that future references are fixed up to point at the new copy.
-   298   *
-   299   * .fix.exact.expose: In order to allocate the new copy the
-   300   * forwarding buffer must be exposed.  This might be done more
-   301   * efficiently outside the entire scan, since it's likely to happen
-   302   * a lot.
-   303   *
-   304   * .fix.exact.grey: The new copy must be at least as grey as the old 
-one,
-   305   * as it may have been grey for some other collection.
-
-
-AMCGrey
-
-.grey:
-   453   * Turns everything in the pool which is not condemned for a trace
-   454   * grey.
-
-
-AMCSegScan
-
-.seg-scan:
-   485   * .seg-scan.blacken: One a group is scanned it is turned black, i.e.
-   486   * the ti is removed from the grey TraceSet.  However, if the
-   487   * forwarding buffer is still pointing at the group it could
-   488   * make it grey again when something is fixed, and cause the
-   489   * group to be scanned again.  We can't tolerate this at present,
-   490   * the the buffer is flushed.  The solution might be to scan buffers
-   491   * explicitly.
-
-.seg-scan.loop:
-   505    /* While the group remains buffered, scan to the limit of */
-   506    /* initialized objects in the buffer.  Either it will be reached, */
-   507    /* or more objects will appear until the segment fills up and the */
-   508    /* buffer moves away. */
-
-.seg-scan.finish:
-   520    /* If the group is unbuffered, or becomes so during scanning */
-   521    /* (e.g. if the forwarding buffer gets flushed) then scan to */
-   522    /* the limit of the segment. */
-
-.seg-scan.lower:
-   540    /* The segment is no longer grey for this collection, so */
-   541    /* it no longer needs to be shielded. */
-
-
-AMCScan
-
-.scan:
-   556   * Searches for a group which is grey for the trace and scans it.
-   557   * If there aren't any, it sets the finished flag to true.
-
-
-AMCReclaim
-
-.reclaim:
-   603   * After a trace, destroy any groups which are still condemned for the
-   604   * trace, because they must be dead.
-   605   *
-   606   * .reclaim.grey: Note that this might delete things which are grey
-   607   * for other collections.  This is OK, because we have conclusively
-   608   * proved that they are dead -- the other collection must have
-   609   * assumed they were alive.  There might be a problem with the
-   610   * accounting of grey groups, however.
-   611   *
-   612   * .reclaim.buf: If a condemned group still has a buffer attached, we
-   613   * can't destroy it, even though we know that there are no live objects
-   614   * there.  Even the object the mutator is allocating is dead, because
-   615   * the buffer is tripped.
-
-
-AMCAccess
-
-.access:
-   648   * This is effectively the read-barrier fault handler.
-   649   *
-   650   * .access.buffer: If the page accessed had and still has the
-   651   * forwarding buffer attached, then trip it.  The group will now
-   652   * be black, and the mutator needs to access it.  The forwarding
-   653   * buffer will be moved onto a fresh grey page.
-   654   *
-   655   * .access.error: @@@@ There really ought to be some error recovery.
-   656   *
-   657   * .access.multi: @@@@ It shouldn't be necessary to scan more than
-   658   * once.  Instead, should use a multiple-fix thingy.  This would
-   659   * require the ScanState to carry a _set_ of traces rather than
-   660   * just one.
-
-
-OLD NOTES
-
-
-Group Scanning
-  
-
-
- -
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
2009-08-11RHSKFix HTML duplicated anchor names (caused by auto-conversion to HTML).
2009-08-11RHSKPrepend Guide, using design/template-with-guide.html.
2009-09-14RHSKGuide covers: seg states; pads; retained pages.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002, 2009 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poolams/index.html b/mps/design/poolams/index.html deleted file mode 100644 index f5acb18270b..00000000000 --- a/mps/design/poolams/index.html +++ /dev/null @@ -1,534 +0,0 @@ - - - - - - - - -The design of the automatic mark-and-sweep pool class - - - - - - - -
-         THE DESIGN OF THE AUTOMATIC MARK-AND-SWEEP POOL CLASS
-                           design.mps.poolams
-                              draft design
-                            pekka 1997-08-14
-
-
-INTRODUCTION
-
-.intro: This is the design of the AMS pool class.
-
-.readership: MM developers.
-
-.source: design.mps.buffer, design.mps.trace, design.mps.scan,
-design.mps.action and design.mps.class-interface [none of these were
-actually used -- pekka 1998-04-21].  No requirements doc [we need a
-req.mps that captures the commonalities between the products -- pekka
-1998-01-27].
-
-
-Document History
-
-.hist.0: Nick Barnes wrote down some notes on the implementation
-1997-08-14.  Pekka P. Pirinen wrote the first draft design 1998-01-27.
-
-.hist.1: Pekka edited on the basis of review.design.mps.poolams.0, and
-redesigned the colour representation (results mostly in
-analysis.non-moving-colour(0)).
-
-.hist.2: Described subclassing and allocation policy.  pekka
-1999-01-04
-
-.hist.3: New colour encoding scheme.  pekka 2002-01-11
-
-
-OVERVIEW
-
-.overview: This document describes the design of the AMS pool class.
-The AMS pool is a proof-of-concept design for a mark-sweep pool in the
-MPS.  It's not meant to be efficient, but it could serve as a model
-for an implementation of a more advanced pool (such as EPVM).
-
-
-REQUIREMENTS
-
-.req.mark-sweep: The pool must use a mark-and-sweep GC algorithm.
-
-.req.colour: The colour representation should be as efficient as
-possible.
-
-.req.incremental: The pool must support incremental GC.
-
-.req.ambiguous: The pool must support ambiguous references to objects
-in it (but ambiguous references into the middle of an object do not
-preserve the object).
-
-.req.format: The pool must be formatted, for generality.
-
-.req.correct: The design and the implementation should be simple
-enough to be seen to be correct.
-
-.req.simple: Features not related to mark-and-sweep GC should
-initially be implemented as simply as possible, in order to save
-development effort.
-
-.not-req.grey: We haven't figured out how buffers ought to work with a
-grey mutator, so we use .req.correct to allow us to design a pool that
-doesn't work in that phase.  This is acceptable as long as we haven't
-actually implemented grey mutator collection.
-
-
-ARCHITECTURE
-
-Subclassing
-
-.subclass: Since we expect to have many mark-and-sweep pools, we build
-in some protocol for subclasses to modify various aspects of the
-behaviour.  Notably there's a subclassable segment class, and a
-protocol for performing iteration.
-
-
-Allocation
-
-.align: We divide the segments in grains, each the size of the format
-alignment.  .alloc-bit-table: We keep track of allocated grains using
-a bit table.  This allows a simple implementation of allocation and
-freeing using the bit table operators, satisfying .req.simple, and can
-simplify the GC routines. Eventually, this should use some
-sophisticated allocation technique suitable for non-moving automatic
-pools.
-
-.buffer: We use buffered allocation, satisfying .req.incremental.  The
-AMC buffer technique is reused, although it is not suitable for
-non-moving pools, but req.simple allows us to do that for now.
-
-.extend: If there's no space in any existing segment, a new segment is
-allocated.  The actual class is allowed to decide the size of the new
-segment.
-
-.no-alloc: Do not support PoolAlloc, because we can't support
-one-phase allocation for a scannable pool (unless we disallow
-incremental collection).  For exact details, see design.mps.buffer.
-
-.no-free: Do not support PoolFree, because automatic pools don't need
-explicit free and having it encourages clients to use it (and
-therefore to have dangling pointers, double frees, etc.)
-
-
-Colours
-
-.colour: Objects in a segment which is _not_ condemned (for some
-trace) take their colour (for this trace) from the segment.
-.colour.object: Since we need to implement a non-copying GC, we keep
-track of the colour of each object in a condemned segment separately.
-For this, we use bit tables with a bit for each grain.  This format is
-fast to access, has better locality than mark bits in the objects
-themselves, and allows cheap interoperation with the allocation bit
-table.  .colour.encoding: As to the details, we follow
-analysis.non-moving-colour(3), implementing both the alloc-white
-sharing option described in
-analysis.non-moving-colour.constraint.reclaim.white-free-bit and the
-vanilla three-table option, because the former cannot work with
-interior pointers.  However, the colour encoding in both is the same.
-
-.ambiguous.middle: We will allow ambiguous references into the middle
-of an object (as required by .req.ambiguous), using the trick in
-analysis.non-moving-colour.interior.ambiguous-only to speed up
-scanning.  .interior-pointer: Note that non-ambiguous interior
-pointers are outlawed.
-
-.colour.alloc: Objects are allocated black.  This is the most
-efficient alternative for traces in the black mutator phase, and
-.not-req.grey means that's sufficient.  [Some day, we need to think
-about allocating grey or white during the grey mutator phase.]
-
-
-Scanning
-
-.scan.segment: The tracer protocol requires (for segment barrier hits)
-that there is a method for scanning a segment and turning all grey
-objects on it black.  This cannot be achieved with a single sequential
-sweep over the segment, since objects that the sweep has already
-passed may become grey as later objects are scanned.  .scan.graph: For
-a non-moving GC, it is more efficient to trace along the reference
-graph than segment by segment [it would also allow passing type
-information from fix to scan].  Currently, the tracer doesn't offer
-this option when it's polling for work.
-
-.scan.stack: Tracing along the reference graph cannot be done by
-recursive descent, because we can't guarantee that the stack won't
-overflow.  We can, however, maintain an explicit stack of things to
-trace, and fall back on iterative methods (.scan.iter) when it
-overflows and can't be extended.
-
-.scan.iter: As discussed in .scan.segment, when scanning a segment, we
-need to ensure that there are no grey objects in the segment when the
-scan method returns.  We can do this by iterating a sequential scan
-over the segment until nothing is grey (see .marked.scan for details).
-.scan.iter.only: Some iterative method is needed as a fallback for the
-more advanced methods, and as this is the simplest way of implementing
-the current tracer protocol, we will start by implementing it as the
-only scanning method.
-
-.scan.buffer: We do not scan between ScanLimit and Limit of a buffer
-(see .iteration.buffer), as usual [design.mps.buffer should explain
-why this works, but doesn't.  Pekka 1998-02-11].
-
-.fix.to-black: When fixing a reference to a white object, if the
-segment does not refer to the white set, the object cannot refer to
-the white set, and can therefore be marked as black immediately
-(rather than grey).
-
-
-IMPLEMENTATION
-
-Colour
-
-.colour.determine: Following the plan in .colour, if SegWhite(seg)
-includes the trace, the colour of an object is given by the bit
-tables.  Otherwise if SegGrey(seg) includes the trace, all the objects
-are grey.  Otherwise all the objects are black.
-
-.colour.bits: As we only have searches for runs of zero bits, we use
-two bit tables, the non-grey and non-white tables, but this is hidden
-beneath a layer of macros talking about grey and white in positive
-terms.
-
-.colour.single: We have only implemented a single set of mark and scan
-tables, so we can only condemn a segment for one trace at a time.
-This is checked for in condemnation.  If we want to do overlapping
-white sets, each trace needs its own set of tables.
-
-.colour.check: The
-grey&non-white state is illegal, and free objects must be white as
-explained in analysis.non-moving-colour.contraint.reclaim.
-
-
-Iteration
-
-.iteration: Scan, reclaim and other operations need to iterate over
-all objects in a segment.  We abstract this into a single iteration
-function, even though we no longer use it for reclaiming and rarely
-for scanning.
-
-.iteration.buffer: Iteration skips directly from ScanLimit to Limit of
-a buffer.  This is because this area may contain partially-initialized
-and uninitialized data, which cannot be processed.  [ScanLimit is used
-for reasons which are not documented in design.mps.buffer.]  Since the
-iteration skips the buffer, callers need to take the appropriate
-action, if any, on it.
-
-
-Scanning Algorithm
-
-.marked: Each segment has a 'marksChanged' flag, indicating whether
-anything in it has been made grey since the last scan iteration
-(.scan.iter) started.  This flag only concerns the colour of objects
-with respect to the trace for which the segment is condemned, as this
-is the only trace for which objects in the segment are being made grey
-by fixing.  Note that this flag doesn't imply that there are grey
-objects in the segment, because the grey objects might have been
-subsequently scanned and blackened.
-
-.marked.fix: The marksChanged flag is set TRUE by AMSFix when an
-object is made grey.
-
-.marked.scan: AMSScan must blacken all grey objects on the segment, so
-it must iterate over the segment until all grey objects have been
-seen.  Scanning an object in the segment might grey another one
-(.marked.fix), so the scanner iterates until this flag is FALSE,
-setting it to FALSE before each scan.  It is safe to scan the segment
-even if it contains nothing grey.
-
-.marked.scan.fail: If the format scanner returns failure (see
-protocol.mps.scanning [is that the best reference?]), we abort the
-scan in the middle of a segment.  So in this case the marksChanged
-flag is set back to TRUE, because we may not have blackened all grey
-objects.
-
-.marked.unused: The marksChanged flag is meaningless unless the
-segment is condemned.  We make it FALSE in these circumstances.
-
-.marked.condemn: Condemnation makes all objects in a segment either
-black or white, leaving nothing grey, so it doesn't need to set the
-marksChanged flag which must already be FALSE.
-
-.marked.reclaim: When a segment is reclaimed, it can contain nothing
-marked as grey, so the marksChanged flag must already be FALSE.
-
-.marked.blacken: When the tracer decides not to scan, but to call
-PoolBlacken, we know that any greyness can be removed.  AMSBlacken
-does this and resets the marksChanged flag, if it finds that the
-segment has been condemned.
-
-.marked.clever: AMS could be clever about not setting the marksChanged
-flag, if the fixed object is ahead of the current scan pointer.  It
-could also keep low- and high-water marks of grey objects, but we
-don't need to implement these improvements at first.
-
-
-Allocation
-
-.buffer-init: We take one init arg to set the Rank on the buffer, just
-to see how it's done.
-
-.no-bit: As an optimization, we won't use the alloc bit table until
-the first reclaim on the segment.  Before that, we just keep a
-high-water mark.
-
-.fill: AMSBufferFill takes the simplest approach: it iterates over the
-segments in the pool, looking for one which can be used to refill the
-buffer.  .fill.colour: The objects allocated from the new buffer must
-be black for all traces (.colour.alloc), so putting it on a black
-segment (meaning one where neither SegWhite(seg) nor SegGrey(seg)
-include the trace, see .colour.determine) is obviously OK.  White
-segments (where SegWhite(seg) includes the trace) are also fine, as we
-can use the colour tables to make it black.  At first glance, it seems
-we can't put it on a segment that is grey but not white for some trace
-(one where SegWhite(seg) doesn't include the trace, but SegGrey(seg)
-does), because the new objects would become grey as the buffer's
-ScanLimit advanced.  However, in many configurations, the mutator
-would hit a barrier as soon as it started initializing the object,
-which would flip the buffer. In fact, the current (2002-01)
-implementation of buffers assumes buffers are black, so they'd better.
-.fill.colour.reclaim: In fact, putting a buffer on a condemned segment
-will screw up the accounting in AMCReclaim, so it's disallowed.
-
-.fill.slow: AMSBufferFill gets progressively slower as more segments
-fill up, as it laboriously checks whether the buffer can be refilled
-from each segment, by inspecting the allocation bit map.  This is
-helped a bit by keeping count of free grains in each segment, but it
-still spends a lot of time iterating over all the full segments
-checking the free size.  Obviously, this can be much improved (we
-could keep track of the largest free block in the segment and in the
-pool, or we could keep the segments in some more efficient structure,
-or we could have a real free list structure).
-
-.fill.extend: If there's no space in any existing segment, the segSize
-method is called to decide the size of the new segment to allocate.
-If that fails, the code tries to allocate a segment that's just large
-enough to satisfy the request.
-
-.empty: AMSBufferEmpty makes the unused space free, since there's no
-reason not to.  We have to adjust the colour tables as well, since
-these grains were black and now they need to be white (or at least
-encoded -G and W).
-
-.reclaim.empty.buffer: Segments which after reclaim only contain a
-buffer could be destroyed by trapping the buffer, but there's no point
-to this.
-
-
-Initialization
-
-.init: The initialization method AMSInit() takes three additional
-arguments: the format of objects allocated in the pool, the chain that
-controls GC timing, and a flag for supporting ambiguous references.
-.init.share: If support for ambiguity is required, the shareAllocTable
-flag is reset to indicate the pool uses three separate bit tables,
-otherwise it is set and the pool shares a table for non-white and
-alloc (see .colour.encoding).
-
-.init.align: The pool alignment is set equal to the format alignment
-(see design.mps.align).
-
-.init.internal: Subclasses call AMSInitInternal() to avoid the
-problems of sharing va_list and emitting a superfluous PoolInitAMS
-event.
-
-
-Condemnation
-
-.condemn.buffer: Buffers are not condemned, instead they are coloured
-black, to make sure that the objects allocated will be black,
-following .colour.alloc (or, if you wish, because buffers are ignored
-like free space, so need the same encoding).
-
-
-Reclaim
-
-.reclaim: Reclaim uses either of analysis.non-moving-colour
-.constraint.reclaim.white-free-bit (just reuse the non-white table as
-the alloc table) or
-analysis.non-moving-colour.constraint.reclaim.free-bit (copy it),
-depending on the shareAllocTable flag (as set by
-.init.share). However, bit table still has to be iterated over to
-count the free grains.  Also, in a debug pool, each white block has to
-be splatted.
-
-
-Segment Merging and Splitting
-
-.split-merge: We provide methods for splitting and merging AMS
-segments.  The pool implementation doesn't cause segments to be split
-or merged - but a subclass might want to do this (see
-.stress.split-merge).  The methods serve as an example of how to
-implement this facility.
-
-.split-merge.constrain: There are some additional constraints on what
-segments may be split or merged:
-
-.split-merge.constrain.align: Segments may only be split or merged at
-an address which is aligned to the pool alignment as well as to the
-arena alignment. .split-merge.constrain.align.justify: This constraint
-is implied by the design of allocation and colour tables, which cannot
-represent segments starting at unaligned addresses.  The constraint
-only arises if the pool alignment is larger than the arena alignment.
-There's no requirement to split segments at unaligned addresses.
-
-.split-merge.constrain.empty: The higher segment must be empty. That
-is, the higher segment passed to SegMerge must be empty, and the
-higher segment returned by SegSplit must be
-empty. .split-merge.constrain.empty.justify: This constraint makes the
-code significantly simpler.  There's no requirement for a more complex
-solution at the moment (as the purpose is primarily pedagogic).
-
-.split-merge.fail: The split and merge methods are not proper
-anti-methods for each other (see
-design.mps.seg.split-merge.fail.anti.no).  Methods will not reverse
-the side-effects of their counterparts if the allocation of the colour
-and allocation bit tables should fail.  Client methods which over-ride
-split and merge should not be written in such a way that they might
-detect failure after calling the next method, unless they have reason
-to know that the bit table allocations will not fail.
-
-
-TESTING
-
-.stress: There's a stress test, MMsrc!amsss.c, that does 800 kB of
-allocation, enough for about three GCs.  It uses a modified Dylan
-format, and checks for corruption by the GC.  Both ambiguous and exact
-roots are tested.
-
-.stress.split-merge: There's also a stress test for segment splitting
-and merging, MMsrc!segsmss.c.  This is similar to amsss.c - but it
-defines a subclass of AMS, and causes segments to be split and merged.
-Both buffered and non-buffered segments are split / merged.
-
-
-NOTES
-
-.addr-index.slow: Translating from an address to and from a grain
-index in a segment uses macros such as AMS_INDEX and AMS_INDEX_ADDR.
-These are slow because they call SegBase on every translation - we
-could cache that.
-
-.grey-mutator: To enforce the restriction set in .not-req.grey we
-check that all the traces are flipped in AMSScan.  It would be good to
-check in AMSFix as well, but we can't do that, because it's called
-during the flip, and we can't tell the difference between the flip and
-the grey mutator phases with the current tracer interface.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
2002-06-20NBRe-imported from Global Graphics.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poolawl/index.html b/mps/design/poolawl/index.html deleted file mode 100644 index 999b2347cf7..00000000000 --- a/mps/design/poolawl/index.html +++ /dev/null @@ -1,577 +0,0 @@ - - - - - - - - -Automatic weak linked - - - - - - - -
-                         AUTOMATIC WEAK LINKED
-                           design.mps.poolawl
-                             incomplete doc
-                             drj 1997-03-11
-
-INTRODUCTION
-
-.readership: Any MPS developer
-
-.intro: The AWL (Automatic Weak Linked) pool is used to manage Dylan Weak 
-Tables (see req.dylan.fun.weak).  Currently the design is specialised for Dylan 
-Weak Tables, but it could be generalised in the future.
-
-
-
-REQUIREMENTS
-
-See req.dylan.fun.weak.
-
-See meeting.dylan.1997-02-27(0) where many of the requirements for this pool 
-were first sorted out.
-
-Must satisfy request.dylan.170123.
-
-.req.obj-format: Only objects of a certain format need be supported.  This 
-format is a subset of the Dylan Object Format.  The pool uses the first slot in 
-the fixed part of an object to store an association.  See 
-mail.drj.1997-03-11.12-05
-
-
-DEFINITIONS
-
-.def.grain: alignment grain, grain.  A grain is a range of addresses where both 
-the base and the limit of the range are aligned and the size of range is equal 
-to the (same) alignment.  In this context the alignment is the pool's alignment 
-(pool->alignment).  The grain is the unit of allocation, marking, scanning, etc.
-
-
-OVERVIEW
-
-.overview:
-.overview.ms: The pool is mark and sweep.  .overview.ms.justify: Mark-sweep 
-pools are slightly easier to write (than moving pools), and there are no 
-requirements (yet) that this pool be high performance or moving or anything 
-like that.  .overview.alloc: It is possible to allocate weak or exact objects 
-using the normal reserve/commit AP protocol.  .overview.alloc.justify: 
-Allocation of both weak and exact objects is required to implement Dylan Weak 
-Tables.  Objects are formatted; the pool uses format A.  .overview.scan: The 
-pool handles the scanning of weak objects specially so that when a weak 
-reference is deleted the corresponding reference in an associated object is 
-deleted.  The associated object is determined by using information stored in 
-the object itself (see .req.obj-format).
-
-
-INTERFACE
-
-.if.init: The init method takes one extra parameter in the vararg list.  This 
-parameter should have type Format and be a format object that describes the 
-format of the objects to be allocated in this pool.  The format should support 
-scan and skip methods.  There is an additional restriction on the layout of 
-objects, see .req.obj-format.
-
-.if.buffer: The BufferInit method takes one extra parameter in the vararg 
-list.  This parameter should be either RankEXACT or RankWEAK.  It determines 
-the rank of the objects allocated using that buffer.
-
-
-DATASTRUCTURES
-
-.sig: This signature for this pool will be 0x519bla3l (SIGPooLAWL)
-
-.poolstruct: The class specific pool structure is
-struct AWLStruct {
-  PoolStruct poolStruct;
-  Format format;
-  Shift alignShift;
-  ActionStruct actionStruct;
-  double lastCollected;
-  Serial gen;
-  Sig sig;
-}
-.poolstruct.format: The format field is used to refer to the object format.  
-The object format is passed to the pool during pool creation.
-.poolstruct.alignshift: The alignShift field is the SizeLog2 of the pool's 
-alignment.  It is computed and initialised when a pool is created.  It is used 
-to compute the number of alignment grains in a segment which is the number of 
-bits need in the segment's mark and alloc bit table (see .awlseg.bt, 
-.awlseg.mark, and .awlseg.alloc below). @@ clarify
-.poolstruct.actionStruct: Contains an Action which is used to participate in 
-the collection benefit protocol.  See .fun.benefit AWLBenefit below for a 
-description of the algorithm used for determining when to collect.
-.poolstruct.lastCollected: Records the time (using the mutator total allocation 
-clock, ie that returned by ArenaMutatorAllocSize) of the most recent call to 
-either AWLInit or AWLTraceBegin for this pool.  So this is the time of the 
-beginning of the last collection of this pool.  Actually this isn't true 
-because the pool can be collected without AWLTraceBegin being called (I think) 
-as it will get collected by being in the same zone as another pool/generation 
-that is being collected (which it does arrange to be, see the use of the gen 
-field in .poolstruct.gen below and .fun.awlsegcreate.where below).
-.poolstruct.gen: This part of the mechanism by which the pool arranges to be in 
-a particular zone and arranges to be collected simultaneously with other 
-cohorts in the system.  gen is the generation that is used in expressing a 
-generation preference when allocating a segment.  The intention is that this 
-pool will get collected simultaneously with any other segments that are also 
-allocated using this generation preference (when using the VM arena, generation 
-preferences get mapped more or less to zones, each generation to a unique set 
-of zones in the ideal case).  Whilst AWL is not generational it is expected 
-that this mechanism will arrange for it to be collected simultaneously with 
-some particular generation of AMC.
-.poolstruct.gen.1: At the moment the gen field is set for all AWL pools to be 1.
-
-.awlseg: The pool defines a segment class AWLSegClass, which is a subclass of 
-GCSegClass (see design.mps.seg.over.hierarchy.gcseg). All segments allocated by 
-the pool are instances of this class, and are of type AWLSeg, for which the 
-structure is
-struct AWLSegStruct {
-  GCSegStruct gcSegStruct; 
-  BT mark;
-  BT scanned;
-  BT alloc;
-  Count grains;
-  Count free;
-  Count singleAccesses;
-  AWLStatSegStruct stats;
-  Sig sig;
-}
-
-.awlseg.bt: The mark, alloc, and scanned fields are bit-tables (see 
-design.mps.bt).  Each bit in the table corresponds to a a single alignment 
-grain in the pool.
-.awlseg.mark: The mark bit table is used to record mark bits during a trace.  
-Condemn (see .fun.condemn below) sets all the bits of this table to zero.  Fix 
-will read and set bits in this table.  Currently there is only one mark bit 
-table.  This means that the pool can only be condemned for one trace.  
-.awlseg.mark.justify: This is simple, and can be improved later when we want to 
-run more than one trace.
-.awlseg.scanned: The scanned bit-table is used to note which objects have been 
-scanned.  Scanning (see .fun.scan below) a segment will find objects that are 
-marked but not scanned, scan each object found and set the corresponding bits 
-in the scanned table.
-.awlseg.alloc: The alloc bit table is used to record which portions of a 
-segment have been allocated.  Ranges of bits in this table are set when a 
-buffer is attached to the segment.  When a buffer is flushed (ie AWLBufferEmpty 
-is called) from the segment, the bits corresponding to the unused portion at 
-the end of the buffer are reset.
-.awlseg.alloc.invariant: A bit is set in the alloc table <=> (the corresponding 
-address is currently being buffered || the corresponding address lies within 
-the range of an allocated object).
-.awlseg.grains: The grains field is the number of grains that fit in the 
-segment.  Strictly speaking this is not necessary as it can be computed from 
-SegSize and awl's alignment, however, precalculating it and storing it in the 
-segment makes the code simpler by avoiding lots of repeated calculations.
-.awlseg.free: A conservative estimate of the number of free grains in the 
-segment.  It is always guaranteed to be >= the number of free grains in the 
-segment, hence can be used during allocation to quickly pass over a segment.  
-Maintained by blah and blah.  @@@@ Unfinished obviously.
-
-
-FUNCTIONS
-
-
-@@ How will pool collect?  It needs an action structure.
-
-External
-
-.fun.init:
-
-Res AWLInit(Pool pool, va_list arg);
-
-AWLStruct has four fields, each one needs initializing.
-
-.fun.init.poolstruct: The poolStruct field has already been initialized by 
-generic code (impl.c.pool).
-.fun.init.format: The format will be copied from the argument list, checked, 
-and written into this field.
-.fun.init.alignshift: The alignShift will be computed from the pool alignment 
-and written into this field.
-.fun.init.sig: The sig field will be initialized with the signature for this 
-pool.
-
-.fun.finish:
-
-Res AWLFinish(Pool pool);
-
-Iterates over all segments in the pool and destroys each segment (by calling 
-SegFree).
-Overwrites the sig field in the AWLStruct.  Finishing the generic pool 
-structure is done by the generic pool code (impl.c.pool).
-
-.fun.alloc:
-
-PoolNoAlloc will be used, as this class does not implement alloc.
-
-.fun.free:
-
-PoolNoFree will be used, as this class does not implement free.
-
-.fun.fill:
-
-Res AWLBufferFill(Seg *segReturn, Addr *baseReturn, Pool pool, Buffer buffer, 
-Size size);
-
-This zips round all the the segments applying AWLSegAlloc to each segment that 
-has the same rank as the buffer.  AWLSegAlloc attempts to find a free range, if 
-it finds a range then it may be bigger than the actual request, in which case 
-the remainder can be used to "fill" the rest of the buffer.  If no free range 
-can be found in an existing segment then a new segment will be created (which 
-is at least large enough).  The range of buffered addresses is marked as 
-allocated in the segment's alloc table.
-
-.fun.empty:
-
-void AWLBufferEmpty(Pool pool, Buffer buffer);
-
-Locates the free portion of the buffer, that is the memory between the init and 
-the limit of the buffer and records these locations as being free in the 
-relevant alloc table.  The segment that the buffer is pointing at (which 
-contains the alloc table that needs to be dinked with) is available via 
-BufferSeg.
-
-.fun.benefit: The benefit returned is the total amount of mutator allocation 
-minus the lastRembemberedSize minus 10 Megabytes, so the pool becomes an 
-increasingly good candidate for collection at a constant (mutator allocation) 
-rate, crossing the 0 line when there has been 10Mb of allocation since the 
-(beginning of the) last collection.  So it gets collected approximately every 
-10Mb of allocation.  Note that it will also get collected by virtue of being in 
-the same zone as some AMC generation (assuming there are instantiated AMC 
-pools), see .poolstruct.gen above.
-
-.fun.condemn:
-
-Res AWLCondemn(Pool pool, Trace trace, Seg seg);
-
-The current design only permits each segment to be condemned for one trace (see 
-.awlseg.mark).  This function checks that the segment is not condemned for any 
-trace (seg->white == TraceSetEMPTY).  The segment's mark bit-table is reset, 
-and the whiteness of the seg (seg->white) has the current trace added to it.
-
-
-.fun.grey:
-
-void AWLGrey(Pool pool, Trace trace, Seg seg);
-
-if the segment is not condemned for this trace the segment's mark table is set 
-to all 1s and the segment is recorded as being grey.
-
-.fun.scan:
-
-Res AWLScan(ScanState ss, Pool pool, Seg seg);
-
-.fun.scan.overview: The scanner performs a number of passes over the segment, 
-scanning each marked and unscanned (grey) object that is finds.  
-.fun.scan.overview.finish: It keeps perform a pass over the segment until it is 
-finished.  .fun.scan.overview.finish.condition: A condition for finishing is 
-that no new marks got placed on objects in this segment during the pass.  
-.fun.scan.overview.finish.approximation: We use an even stronger condition for 
-finishing that assumes that scanning any object may introduce marks onto this 
-segment.  It is finished when a pass results in scanning no objects (ie all 
-objects were either unmarked or both marked and scanned).
-
-.fun.scan.overview.finished-flag: There is a flag called 'finished' which keeps 
-track of whether we should finish or not.  We only ever finish at the end of a 
-pass.  At the beginning of a pass the flag is set.  During a pass if any 
-objects are scanned then the finished flags is reset.  At the end of a pass if 
-the finished flag is still set then we are finished.  No more passes take place 
-and the function returns.
-
-.fun.scan.pass:  A pass consists of a setup phase and a repeated phase.
-
-.fun.scan.pass.buffer: The following assumes that in the general case the 
-segment is buffered; if the segment is not buffered then the actions that 
-mention buffers are not taken (they are unimportant if the segment is not 
-buffered).
-
-.fun.scan.pass.p: The pass uses a cursor called 'p' to progress over the 
-segment.  During a pass p will increase from the base address of the segment to 
-the limit address of the segment.  When p reaches the limit address of the 
-segment, the pass in complete.
-
-.fun.scan.pass.setup: p initially points to the base address of the segment.
-
-.fun.scan.pass.repeat:  The following comprises the repeated phase.  The 
-repeated phase is repeated until the pass completion condition is true (ie p 
-has reached the limit of the segment, see .fun.scan.pass.p above and 
-.fun.scan.pass.repeat.complete below).
-
-.fun.scan.pass.repeat.complete: if p is equal to the segment's limit then we 
-are done.  We proceed to check whether any further passes need to be performed 
-(see .fun.scan.pass.more below).
-
-.fun.scan.pass.repeat.free: if !alloc(p) (the grain is free) then increment p 
-and return to the beginning of the loop.
-
-.fun.scan.pass.repeat.buffer: if p is equal to the buffer's ScanLimit (see 
-BufferScanLimit), then set p equal to the buffer's Limit (use BufferLimit) and 
-return to the beginning of the loop.
-
-.fun.scan.pass.repeat.object-end: The end of the object is located using the 
-format->skip method.
-
-.fun.scan.pass.repeat.object: if (mark(p) && !scanned(p)) then the object 
-pointed at is marked but not scanned, which means we must scan it, otherwise we 
-must skip it.  .fun.scan.pass.repeat.object.dependent: To scan the object the 
-object we first have to determine if the object has a dependent object (see 
-.req.obj-format).  .fun.scan.pass.repeat.object.dependent.expose: If it has a 
-dependent object then we must expose the segment that the dependent object is 
-on (only if the dependent object actually points to MPS managed memory) prior 
-to scanning and cover the segment subsequent to scanning.  
-.fun.scan.pass.repeat.object.dependent.summary: The summary of the dependent 
-segment must be set to RefSetUNIV to reflect the fact that we are allowing it 
-to be written to (and we don't know what gets written to the segment).  
-.fun.scan.pass.repeat.object.scan: The object is then scanned by calling the 
-format's scan method with base and limit set to the beginning and end of the 
-object (.fun.scan.scan.improve.single: A scan1 format method would make it 
-slightly simpler here).  Then the finished flag is cleared and the bit in the 
-segment's scanned table is set.
-
-.fun.scan.pass.repeat.advance: p is advanced past the object and we return to 
-the beginning of the loop.
-
-.fun.scan.pass.more:  At the end of a pass the finished flag is examined.  
-.fun.scan.pass.more.not: If the finished flag is set then we are done (see 
-.fun.scan.overview.finished-flag above), AWLScan returns.  
-.fun.scan.pass.more.so: Otherwise (the finished flag is reset) we perform 
-another pass (see .fun.scan.pass above).
-
-
-.fun.fix:
-
-Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO);
-
-ss->wasMarked is set to TRUE (clear compliance with 
-design.mps.fix.protocol.was-marked.conservative).
-
-If the rank (ss->rank) is RankAMBIG then fix returns immediately unless the 
-reference is aligned to the pool alignment.
-
-If the rank (ss->rank) is RankAMBIG then fix returns immediately unless the 
-referenced grain is allocated.
-
-The bit in the marked table corresponding to the referenced grain will be 
-read.  If it is already marked then fix returns.  Otherwise (the grain is 
-unmarked), ss->wasMarked is set to FALSE, the remaining actions depend on 
-whether the rank (ss->rank) is Weak or not.  If the rank is weak then the 
-reference is adjusted to 0 (see design.mps.weakness) and fix returns.  If the 
-rank is something else then the mark bit corresponding to the referenced grain 
-is set, and the segment is greyed using TraceSegGreyen.
-
-Fix returns.
-
-
-.fun.reclaim:
-
-void AWLReclaim(Pool pool, Trace trace, Seg seg);
-
-This iterates over all allocated objects in the segment and frees objects that 
-are not marked.
-When this iteration is complete the marked array is completely reset.
-
-p point to base of segment
-
-while(p < SegLimit(seg) {
-  if(!alloc(p)) { ++p;continue;}
-  q = skip(p) (ie q points to just past the object pointed at by p)
-  if !marked(p) free(p, q); free(p, q) consists of resetting the bits in the 
-alloc table from p to q-1 inclusive.
-  p = q
-}
-
-Reset the entire marked array using BTResRange.
-
-.fun.reclaim.improve.pad: Consider filling free ranges with padding objects.  
-Now reclaim doesn't need to check that the objects are allocated before 
-skipping them.  There may be a corresponding change for scan as well.
-
-
-.fun.describe:
-
-Res AWLDescribe(Pool pool, mps_lib_FILE *stream);
-
-
-Internal:
-
-.fun.awlsegcreate:
-
-Res AWLSegCreate(AWLSeg *awlsegReturn, Size size);
-
-Creates a segment of class AWLSegClass of size at least size.  
-.fun.awlsegcreate.size.round: size is rounded up to an ArenaAlign before 
-requesting the segment.  .fun.awlsegcreate.size.round.justify: The arena 
-requires that all segment sizes are aligned to the ArenaAlign.  
-.fun.awlsegcreate.where: The segment is allocated using a generation 
-preference, using the generation number stored in the AWLStruct (the gen 
-field), see .poolstruct.gen above.  
-
-.fun.awlseginit:
-
-Res awlSegInit(Seg seg, Pool pool, Addr base, Size size, 
-               Bool reservoirPermit, va_list args)
-
-Init method for AWLSegClass, called for SegAlloc whenever an AWLSeg is created 
-(see .fun.awlsegcreate above). .fun.awlseginit.tables: The segment's mark 
-scanned and alloc tables (see .awlseg.bt above) are allocated and initialised.  
-The segment's grains field is computed and stored.
-
-.fun.awlsegfinish:
-
-void awlSegFinish(Seg seg);
-
-Finish method for AWLSegClass, called from SegFree. Will free the segment's 
-tables (see .awlseg.bt).
-
-.fun.awlsegalloc:
-
-Bool AWLSegAlloc(Addr *baseReturn, Addr *limitReturn, AWLSeg awlseg, AWL awl, 
-Size size);
-
-Will search for a free block in the segment that is at least size bytes long.  
-The base address of the block is returned in *baseReturn, the limit of the 
-entire free block (which must be at least as large size and may be bigger) is 
-returned in *limitReturn.  The requested size is converted to a number of 
-grains, BTFindResRange is called to find a run of this length in the alloc 
-bit-table (.awlseg.alloc).  The return results (if it is successful) from 
-BTFindResRange are in terms of grains, they are converted back to addresses 
-before returning the relevant values from this function.
-
-.fun.dependent-object:
-
-Bool AWLDependentObject(Addr *objReturn, Addr parent);
-
-This function abstracts the association between an object and its linked 
-dependent (see .req.obj-format).  It currently assumes that objects are Dylan 
-Object formatted according to design.dylan.container (see 
-analysis.mps.poolawl.dependent.abstract for suggested improvements).  An object 
-has a dependent object iff the 2nd word of the object (ie (((Word *)parent)[1]) 
-) is non-NULL.  The dependent object is the object referenced by the 2nd word 
-and must be a valid object.
-This function assumes objects are in Dylan Object Format (see 
-design.dylan.container).  It will check that the first word looks like a dylan 
-wrapper pointer.  It will check that the wrapper indicates that the wrapper has 
-a reasonable format (namely at least one fixed field).
-If the second word is NULL it will return FALSE.
-If the second word is non-NULL then the contents of it will be assigned to 
-*objReturn, and it will return TRUE.
-
-
-TEST
-
-must create dylan objects.
-must create dylan vectors with at least one fixed field.
-must allocate weak thingies.
-must allocate exact tables.
-must link tables together.
-must populate tables with junk.
-some junk must die.
-
-Use an LO pool and an AWL pool.
-3 buffers.  One buffer for the LO pool, one exact buffer for the AWL pool, one 
-weak buffer for the AWL pool.
-
-Initial test will allocate one object from each buffer and then destroy all 
-buffers and pools and exit
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poollo/index.html b/mps/design/poollo/index.html deleted file mode 100644 index ee851ede7b6..00000000000 --- a/mps/design/poollo/index.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - - - -Leaf object pool class - - - - - - - -
-                         LEAF OBJECT POOL CLASS
-                           design.mps.poollo
-                             incomplete doc
-                             drj 1997-03-07
-
-INTRODUCTION
-
-.readership: Any MPS developer.
-
-.intro: The Leaf Object Pool Class (LO for short) is a pool class developed for 
-DylanWorks.  It is designed to manage objects that have no references (leaf 
-objects) such as strings, bit tables, etc.  It is a garbage collected pool (in 
-that objects allocated in the pool are automatically reclaimed when they are 
-discovered to be unreachable.
-
-[Need to sort out issue of alignment.  Currently lo grabs alignment from 
-format, almost certainly "ought" to use the greater of the format alignment and 
-the MPS_ALIGN value -- @@ drj 1997-07-02]
-
-DEFINITIONS
-
-.def.leaf: A "leaf" object is an object that contains no references, or an 
-object all of whose references refer to roots.  That is, any references that 
-the object has must refer to a priori alive objects that are guaranteed not to 
-move, hence the references do not need fixing.
-
-.def.grain: A grain (of some alignment) is a contiguous aligned area of memory 
-of the smallest size possible (which is the same size as the alignment).
-
-
-REQUIREMENTS
-
-.req.source: See req.dylan.fun.obj.alloc and req.dylan.prot.ffi.access.
-
-.req.leaf: The pool must manage formatted leaf objects (see .def.leaf above for 
-a definition).  This is intended to encompass Dylan and C leaf objects.  Dylan 
-leaf objects have a reference to their wrapper, but are still leaf objects (in 
-the sense of .def.leaf) because the wrapper will be a root.
-
-.req.nofault: The memory containing objects managed by the pool must not be 
-protected.  The client must be allowed to access these objects without using 
-the MPS trampoline (the exception mechanism, q.v.).
-
-
-OVERVIEW
-
-.overview:
-.overview.ms: The LO Pool is a non-moving mark-and-sweep collector.  
-.overview.ms.justify: mark-and-sweep pools are simpler than moving pools.  
-.overview.alloc: Objects are allocated in the pool using the reserve commit 
-protocol on allocation points.  .overview.format: The pool is formatted.  The 
-format of the objects in the pool is specified at instantiation time, using an 
-format object derived from a format A variant (using variant A is overkill, see 
-.if.init below) (see design.mps.format for excuse about calling the variant 
-'variant A').
-
-
-INTERFACE
-
-.if.init:
-.if.init.args: The init method for this class takes one extra parameter in the 
-vararg parameter list.  .if.init.format: The extra parameter should be an 
-object of type Format and should describe the format of the objects that are to 
-be allocated in the pool.  .if.init.format.use: The pool uses the skip and 
-alignment slots of the format.  The skip method is used to determine the length 
-of objects (during reclaim).  The alignment field is used to determine the 
-granularity at which memory should be managed.  .if.init.format.a: Currently 
-only format variant A is supported though clearly that is overkill as only 
-skip and alignment are used.
-
-
-DATASTRUCTURES
-
-.sig:  The signature for the LO Pool Class is 0x51970b07 (SIGLOPOoL).
-
-.poolstruct: The class specific pool structure is:
-typedef struct LOStruct {
-  PoolStruct poolStruct;        /* generic pool structure */
-  Format format;                /* format for allocated objects */
-  Shift alignShift;
-  Sig sig;                      /* impl.h.misc.sig */
-} LOStruct;
-
-.poolstruct.format: This is the format of the objects that are allocated in the 
-pool.
-
-.poolstruct.alignShift: This is shift used in alignment computations.  It is 
-SizeLog2(pool->alignment).  It can be used on the right of a shift operator (<< 
-or >>) to convert between a number of bytes and a number of grains.
-
-.loseg: Every segment is an instance of segment class LOSegClass, a subclass of 
-GCSegClass, and is an object of type LOSegStruct.  
-
-.loseg.purpose: The purpose of the LOSeg structure is to associate the bit 
-tables used for recording allocation and mark information with the segment.
-
-.loseg.decl:  The declaration of the structure is as follows:
-
-typedef struct LOSegStruct {
-  GCSegStruct gcSegStruct;  /* superclass fields must come first */
-  LO lo;                    /* owning LO */
-  BT mark;                  /* mark bit table */
-  BT alloc;                 /* alloc bit table */
-  Count free;               /* number of free grains */
-  Sig sig;                  /* impl.h.misc.sig */
-} LOSegStruct;
-
-.loseg.sig: The signature for a loseg is 0x519705E9 (SIGLOSEG).
-
-.loseg.lo: The lo field points to the LO structure that owns this segment.
-
-.loseg.bit:  Bit Tables (see design.mps.bt) are used to record allocation and 
-mark information.  This is relatively straightforward, but might be inefficient 
-in terms of space in some circumstances.
-
-.loseg.mark: This is a Bit Table that is used to mark objects during a trace.  
-Each grain in the segment is associated with 1 bit in this table.  When LOFix 
-(see .fun.fix below) is called the address is converted to a grain within the 
-segment and the corresponding bit in this table is set.
-
-.loseg.alloc: This is a Bit Table that is used to record which addresses are 
-allocated.  Addresses that are allocated and are not buffered have their 
-corresponding bit in this table set.  If a bit in this table is reset then 
-either the address is free or is being buffered.
-
-.loseg.diagram: The following diagram is now obsolete. It's also not very 
-interesting - but I've left the sources in case anyone ever gets around to 
-updating it. tony 1999-12-16
-
-
-
-
-FUNCTIONS
-
-
-External
-
-.fun.init:
-
-.fun.destroy:
-
-.fun.buffer-fill:
-
-[explain way in which buffers interact with the alloc table and how it could be 
-improved]
-
-.fun.buffer-empty:
-
-.fun.condemn:
-
-.fun.fix:
-
-static Res LOFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
-
-[sketch]
-Fix treats references of most ranks much the same.  There is one mark table 
-that records all marks.  A reference of rank RankAMBIG is first checked to see 
-if it is aligned to the pool alignment and discarded if not.  The reference is 
-converted to a grain number within the segment (by subtracting the segments' 
-base from the reference and then dividing by the grain size).  The bit (the one 
-corresponding to the grain number) is set in the mark table.  Exception, for a 
-weak reference (rank is RankWEAK) the mark table is checked and the reference 
-is fixed to 0 if this address has not been marked otherwise nothing happens.  
-Note that there is no check that the reference refers to a valid object 
-boundary (which wouldn't be a valid check in the case of ambiguous references 
-anyway).
-
-.fun.reclaim:
-
-static void LOReclaim(Pool pool, Trace trace, Seg seg)
-
-LOReclaim derives the loseg from the seg, and calls loSegReclaim (see 
-.fun.segreclaim below).
-
-
-Internal
-
-.fun.segreclaim:
-
-static void loSegReclaim(LOSeg loseg, Trace trace)
-
-[sketch]
-for all the contiguous allocated regions in the segment it locates the 
-boundaries of all the objects in that region by repeatedly skipping (calling 
-format->skip) from the beginning of the region (the beginning of the region is 
-guaranteed to coincide with the beginning of an object).  For each object it 
-examines the bit in the mark bit table that corresponds to the beginning of the 
-object.  If that bit is set then the object has been marked as a result of a 
-previous call to LOFix, the object is preserved by doing nothing.  If that bit 
-is not set then the object has not been marked and should be reclaimed; the 
-object is reclaimed by resetting the appropriate range of bits in the segment's 
-free bit table.
-
-[special things happen for buffered segments]
-
-[explain how the marked variable is used to free segments]
-
-ATTACHMENT
-   "LOGROUP.CWK"
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poolmfs/index.html b/mps/design/poolmfs/index.html deleted file mode 100644 index 94d7a6eb1be..00000000000 --- a/mps/design/poolmfs/index.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - -The design of the manual fixed small memory pool class - - - - - - - -
-         THE DESIGN OF THE MANUAL FIXED SMALL MEMORY POOL CLASS
-                           design.mps.poolmfs
-                           incomplete design
-                           richard 1996-11-07
-
-
-OVERVIEW:
-
-MFS stands for "Manual Fixed Small".  The MFS Pool Class manages objects that 
-are of a fixed size.  It is intended to only manage small objects efficiently.  
-Storage is recycled manually by the client programmer.
-
-A particular instance of an MFS Pool can manage objects only of a single size, 
-but different instances can manage objects of different sizes.  The size of 
-object that an instance can manage is declared when the instance is created.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poolmrg/index.html b/mps/design/poolmrg/index.html deleted file mode 100644 index 43f539a2670..00000000000 --- a/mps/design/poolmrg/index.html +++ /dev/null @@ -1,628 +0,0 @@ - - - - - - - - -Guardian poolclass - - - - - - - -
-                           GUARDIAN POOLCLASS
-                           design.mps.poolmrg
-                             incomplete doc
-                             drj 1997-02-03
-
-INTRODUCTION
-
-.readership: Any MPS developer.
-
-.intro: This is the design of the Guardian PoolClass.  The Guardian PoolClass 
-is part of the MPS.  The Guardian PoolClass is internal to the MPS (has no 
-client interface) and is used to implement finalization.
-
-.source: Some of the techniques in paper.dbe93 ("Guardians in a 
-Generation-Based Garbage Collector") were used in this design.  Some analysis 
-of this design (including various improvements and some more in-depth 
-justification) is in analysis.mps.poolmrg.  That document should be understood 
-before changing this document.
-
-It is also helpful to look at design.mps.finalize and design.mps.message.
-
-
-GOALS
-
-.goal.final: The Guardian Pool should support all requirements pertaining to 
-finalization.
-
-
-REQUIREMENTS
-
-.req: We have only one requirement pertaining to finalization:
-
-req.dylan.fun.finalization: Support the Dylan language-level implementation of 
-finalized objects: objects are registered, and are finalized in random order 
-when they would otherwise have died.  Cycles are broken at random places.  
-There is no guarantee of promptness.
-
-.req.general: However, finalization is a very common piece of functionality 
-that is provided by (sophisticated) memory managers, so we can expect other 
-clients to request this sort of functionality.
-
-.anti-req: Is it required that the Guardian Pool return unused segments to the 
-arena? (PoolMFS does not do this) (PoolMRG will not do this in its initial 
-implementation)
-
-
-TERMINOLOGY
-
-.def.mrg: MRG: The Pool Class's identifier will be MRG.  This stands for 
-"Manual Rank Guardian".  The pool is manually managed and implements guardians 
-for references of a particular rank (currently just final).
-
-.def.final.ref: final reference: A reference of rank final (see 
-design.mps.type.rank).
-
-.def.final.object: finalizable object: An object is finalizable with respect to 
-a final reference if, since the creation of that reference, there was a point 
-in time when no references to the object of lower (that is, stronger) rank were 
-reachable from a root.
-
-.def.final.object.note: Note that this means an object can be finalizable even 
-if it is now reachable from the root via exact references.  
-
-.def.finalize: finalize: To finalize an object is to notify the client that the 
-object is finalizable.  The client is presumed to be interested in this 
-information (typically it will apply some method to the object).
-
-.def.guardian: guardian: An object allocated in the Guardian Pool.  A guardian 
-contains exactly one final reference, and some fields for the pool's internal 
-use.  Guardians are used to implement a finalization mechanism.
-
-
-OVERVIEW
-
-.over: The Guardian Pool Class is a PoolClass in the MPS.  It is intended to 
-provide the functionality of "finalization".
-
-.over.internal: The Guardian PoolClass is internal to the MPM, it is not 
-intended to have a client interface.  Clients are expected to access the 
-functionality provided by this pool (finalization) using a separate MPS 
-finalization interface (design.mps.finalize).
-
-.over.one-size: The Guardian Pool manages objects of a single certain size, 
-each object contains a single reference of rank final.
-
-.over.one-size.justify: This is all that is necessary to meet our requirements 
-for finalization.  Whenever an object is registered for finalization, it is 
-sufficient to create a single reference of rank final to it.
-
-.over.queue: A pool maintains a queue of live guardian objects, called (for 
-historical reasons) the "entry" queue.  .over.queue.free: The pool also 
-maintains a queue of free guardian objects called the "free" queue.  
-.over.queue.exit.not: There used to be an "exit" queue, but this is now 
-historical and there shouldn't be any current references to it. 
-
-.over.alloc: When guardians are allocated, they are placed on the entry queue. 
-Guardians on the entry queue refer to objects that have not yet been shown to 
-be finalizable (either the object has references of lower rank than final to 
-it, or the MPS has not yet got round to determining that the object is 
-finalizable).  .over.message.create: When a guardian is discovered to refer to 
-a finalizable object it is removed from the entry queue and becomes a message 
-on the space's queue of messages.  .over.message.deliver: When the MPS client 
-receives the message the message system arranges for the message to be 
-destroyed and the pool reclaims the storage associated with the 
-guardian/message.
-
-.over.scan: When the pool is scanned at rank final each reference will be 
-fixed.  If the reference is to an object that was in old arena (before the 
-fix), then the object must now be finalizable.  In this case the containing 
-guardian will be removed from the entry queue and posted as a message.
-
-.over.scan.justify: The scanning process is a crucial step necessary for 
-implementing finalization.  It is the means by which the MPS detects that 
-objects are finalizable.
-
-.over.message: PoolClassMRG implements a MessageClass (see 
-design.mps.message).  All the messages are of one MessageType.  This type is 
-MessageTypeFinalization.  Messages are created when objects are discovered to 
-be finalizable and destroyed when the MPS client has received the message.
-
-.over.message.justify: Messages provide a means for the MPS to communicate with 
-its client.  Notification of finalization is just such a communication.  
-Messages allow the MPS to inform the client of finalization events when it is 
-convenient for the MPS to do so (i.e. not in PageFault context).
-
-.over.manual: Objects in the Guardian Pool are manually managed.  
-.over.manual.alloc: They are allocated (by ArenaFinalize when objects are 
-registered for finalization.  .over.manual.free: They are freed when the 
-associated message is destroyed.
-.over.manual.justify: The lifetime of a guardian object is very easy to 
-determine so manual memory management is appropriate.
-
-
-PROTOCOLS
-
-
-Object Registration
-
-.protocol.register: There is a protocol by which objects can be registered for 
-finalization.  This protocol is handled by the arena module on behalf of 
-finalization.  see design.mps.finalize.int.finalize.
-
-
-Finalizer Execution
-
-.protocol.finalizer: If an object is proven to be finalizable then a message to 
-this effect will eventually be posted.  A client can receive the message, 
-determine what to do about it, and do it.  Typically this would involve calling 
-the finalization method for the object, and deleting the message.  Once the 
-message is deleted, the object may become recyclable.
-
-
-Setup / Destroy
-
-.protocol.life: An instance of PoolClassMRG is needed in order to support 
-finalization, it is called the "final" pool and is attached to the arena (see 
-design.mps.finalize.int.arena.struct).  .protocol.life.birth: The final pool is 
-created lazily by ArenaFinalize.  .protocol.life.death: The final pool is 
-destroyed during ArenaDestroy.
-
-
-DATA STRUCTURES
-
-.guardian:
-
-The guardian
-
-.guardian.over: A guardian is an object used to manage the references and other 
-datastructures that are used by the pool in order to keep track of which 
-objects are registered for finalization, which ones have been finalized, and so 
-on.  .guardian.state: A guardian can be in one of four states: 
-.guardian.state.enum: The states are Free, Prefinal, Final, PostFinal (referred 
-to as MRGGuardianFree, etc. in the implementation).  .guardian.state.free: The 
-guardian is free, meaning that it is on the free list for the pool and 
-available for allocation.  .guardian.state.prefinal: The guardian is allocated, 
-and refers to an object that has not yet been discovered to be finalizable.  
-.guardian.state.final: The guardian is allocated, and refers to an object that 
-has been shown to be finalizable; this state corresponds to the existence of a 
-message.  .guardian.state.postfinal: This state is only used briefly and is 
-entirely internal to the pool; the guardian enters this state just after the 
-associated message has been destroyed (which happens when the client receives 
-the message) and will be freed immediately (whereupon it will enter the Free 
-state).  This state is used for checking only (so that MRGFree can check that 
-only guardians in this state are being freed).
-
-.guardian.life-cycle: Guardians go through the following state life-cycle:
-
-Free -> Prefinal -> Final -> Postfinal -> Free.
-
-.guardian.two-part: A guardian is a structure consisting abstractly of a link 
-part and a reference part.  Concretely, the link part will be a LinkPartStruct, 
-and the reference part will be a Word.  The link part is used by the pool, the 
-reference part forms the object visible to clients of the pool.  The reference 
-part is the reference of Rank FINAL that refers to objects registered for 
-finalization and is how the MPS detects finalizable objects.  
-.guardian.two-part.union: The LinkPartStruct is a discriminated union of a 
-RingStruct and a MessageStruct.  The RingStruct is used when the guardian is 
-either Free or Prefinal.  The MessageStruct is used when the guardian is 
-Final.  Neither part of the union is used when the guardian is in the Postfinal 
-state.
-.guardian.two-part.justify: This may seem a little profligate with space, but 
-this is okay as we are not required to make finalization extremely space 
-efficient.
-
-.guardian.parts.separate: The two parts will be stored in separate segments.  
-.guardian.parts.separate.justify: This is so that the data structures the pool 
-uses to manage the objects can be separated from the objects themselves.  This 
-avoids the pool having to manipulate data structures that are on shielded 
-segments (analysis.mps.poolmrg.hazard.shield).
-
-.guardian.assoc: The nth (from the beginning of the segment) ref part in one 
-segment will correspond with the nth link part in another segment.  The 
-association between the two segments will be managed by the additional fields 
-in pool-specific segment subclasses (see .mrgseg).  .guardian.ref: Guardians 
-that are either Prefinal or Final are live and have valid references (possibly 
-NULL) in their ref parts.  Guardians that are free are dead and always have 
-NULL in their ref parts (see .free.overwrite and .scan.free)  
-.guardian.ref.free: When freeing an object, it is a pointer to the reference 
-part that will be passed (internally in the pool).
-
-.guardian.init: Guardians are initialized when the pool is grown 
-(.alloc.grow).  The initial state has the ref part NULL and the link part is 
-attached to the free ring.  Freeing an object returns a guardian to its initial 
-state.
-
-.poolstruct:
-The Pool structure, MRGStruct will have
-
-.poolstruct.entry: the head of the entry queue.
-
-.poolstruct.exit: the head of the exit queue.
-
-.poolstruct.free: a free list.
-
-.poolstruct.rings: The entry queue, the exit queue, and the free list will all 
-use Rings.  Each Ring will be maintained using the link part of the guardian.  
-.poolstruct.rings.justify: This is because Rings are convenient to use and are 
-well tested.  It is possible to implement all three lists using a singly linked 
-list, but the saving is certainly not worth making at this stage.
-
-.poolstruct.refring: a ring of "ref" segments in use for links or messages (see 
-.mrgseg.ref.mrgring below).
-
-.poolstruct.extend: a precalculated extendby field (see .init.extend).  This 
-value is used to determine how large a segment should be requested from the 
-Arena for the reference part segment when the pool needs to grow (see 
-.alloc.grow.size).  .poolstruct.extend.justify: Calculating a reasonable value 
-for this once and remembering it simplifies the allocation (.alloc.grow).
-
-.poolstruct.init: poolstructs are initialized once for each pool instance by 
-MRGInit (.init).  The initial state has all the rings initialized to singleton 
-rings, and the extendBy field initialized to some value (see .init.extend).
-
-.mrgseg:
-
-The pool defines two segment subclasses: MRGRefSegClass and MRGLinkSegClass. 
-Segments of the former class will be used to store the ref parts of guardians, 
-segments of the latter will be used to store the link parts of guardians (see 
-.guardian.two-part). Segments are always allocated in pairs, with one of each 
-class (by function MRGSegPairCreate).  Each segment contains a link to its pair.
-
-.mrgseg.ref: MRGRefSegClass is a subclass of GCSegClass. Instances are of type 
-MRGRefSeg, and contain: 
-
-.mrgseg.ref.mrgring: a field for the ring of ref part segments in the pool.
-
-.mrgseg.ref.linkseg: a pointer to the paired link segment.
-
-.mrgseg.ref.grey: a set describing the greyness of the segment for each trace.
-
-.mrgseg.ref.init: A segment is created and initialized once every time the pool 
-is grown (.alloc.grow).  The initial state has the segment ring node 
-initialized and attached to the pool's segment ring, the linkseg field points 
-to the relevant link segment, the grey field is initialized such that the 
-segment is not grey for all traces.
-
-.mrgseg.link: MRGLinkSegClass is a subclass of SegClass. Instances are of type 
-MRGLinkSeg, and contain: 
-
-.mrgseg.link.refseg: a pointer to the paired ref segment. This may be NULL 
-during initialization, while the pairing is being established.
-
-.mrgseg.link.init: The initial state has the linkseg field pointing to the 
-relevant ref segment.
-
-
-FUNCTIONS
-
-.check: MRGCheck
-
-  Will check the signatures, the class, and each field of the MRGStruct.  Each 
-field is checked as being appropriate for its type.  .check.justify: There are 
-no non-trivial invariants that can be easily checked.
-
-.alloc: [these apply to MRGRegister now. - Pekka 1997-09-19]
-
-.alloc.grow: If the free list is empty then two new segments will be allocated 
-and the free list filled up from them (note that the reference fields of the 
-new guardians will need to be overwritten with NULL, see .free.overwrite)  
-.alloc.grow.size: The size of the reference part segment will be the pool's 
-extendBy (.poolstruct.extend) value.  The link part segment will be whatever 
-size is necessary to accommodate N link parts, where N is the number of 
-reference parts that fit in the reference part segment.  
-
-.alloc.error: If any of the requests for more resource (there are two; one for 
-each of two segments) fail then the successful requests will be retracted and 
-the result code from the failing request will be returned.
-
-.alloc.pop: MRGAlloc will pop a ring node off the free list, and add it to the 
-entry queue.
-
-.free: MRGFree
-
-  MRGFree will remove the guardian from the message queue and add it to the 
-free list.  .free.push: The guardian will simply be added to the front of the 
-free list (i.e. no keeping the free list in address order or anything like 
-that).  .free.inadequate: No attempt will be made to return unused free 
-segments to the Arena (although see analysis.mps.poolmrg.improve.free.* for 
-suggestions).
-
-.free.overwrite:
-  MRGFree also writes over the reference with NULL.  .free.overwrite.justify: 
-This is so that when the segment is subsequently scanned (.scan.free), the 
-reference that used to be in the object is not accidentally fixed.
-
-.init: MRGInit
-
-  Has to initialize the two queues, the free ring, the ref ring, and the 
-extendBy field.  .init.extend: The extendBy field is initialized to one 
-ArenaAlign() (usually a page).  .init.extend.justify: This is adequate as the 
-pool is not expected to grow very quickly.
-
-.finish: MRGFinish
-
-  Iterate over all the segments, returning all the segments to the Arena.
-
-.scan: MRGScan
-
-.scan.trivial: Scan will do nothing (i.e. return immediately) if the tracing 
-rank is anything other than final.  [This optimization is missing.  
-impl.c.trace.scan.conservative is not a problem because there are no faults on 
-these segs, because there are no references into them.  But that's why 
-TraceScan can't do it.  - Pekka 1997-09-19]  .scan.trivial.justify:  If the 
-rank is lower than final then scanning is detrimental, it will only delay 
-finalization.  If the rank is higher than final there is nothing to do, the 
-pool only contains final references.
-
-.scan.guardians: Scan will iterate over all guardians in the segment.  Every 
-guardian's reference will be fixed (.scan.free: note that guardians that are on 
-the free list have NULL in their reference part).  .scan.wasold: If the object 
-referred to had not been fixed previously (i.e. was unmarked) then the object 
-is not referenced by a reference of a lower rank (than FINAL) and hence is 
-finalizable.  .scan.finalize: The guardian will be finalized.  This entails 
-moving the guardian from state Prefinal to Final; it is removed from the entry 
-queue and initialized as a message and posted on the arena's message queue.  
-.scan.finalize.idempotent: In fact this will only happen if the guardian has 
-not already been finalized (which is determined by examining the state of the 
-guardian).
-
-.scan.unordered: Because scanning occurs a segment at a time, the order in 
-which objects are finalized is "random" (it cannot be predicted by considering 
-only the references between objects registered for finalization).  See 
-analysis.mps.poolmrg.improve.semantics for how this can be improved.  
-.scan.unordered.justify: Unordered finalization is all that is required.
-
-(see analysis.mps.poolmrg.improve.scan.nomove for a suggested improvement that 
-avoids redundant unlinking and relinking).
-
-.describe: MRGDescribe
-
-  Will print out the usual blurb.
-  Will iterate along each of the entry and exit queues and printout the 
-guardians in each.  The location of the guardian and the value of the reference 
-in it will be printed out.
-
-.functions.unused: BufferInit, BufferFill, BufferEmpty, BufferFinish, 
-TraceBegin, Condemn, Fix, Reclaim, TraceEnd, Benefit.
-
-  All of these will be unused.
-
-.functions.trivial: The Grey method of the pool class will be PoolTrivGrey, 
-this pool has no further bookkeeping to perform for grey segments.
-
-
-TRANSGRESSIONS
-
-.trans.no-finish: The MRG pool does not trouble itself to tidy up its internal 
-rings properly when being destroyed.
-
-.trans.free-seg: No attempt is made to release free segments to the arena.  A 
-suggested strategy for this is as follows:
-  - Add a count of free guardians to each segment, and maintain it in 
-appropriate places.
-  - Add a free segment ring to the pool.
-  - In MRGRefSegScan, if the segment is entirely free, don't scan it, but 
-instead detach its links from the free ring, and move the segment to the free 
-segment ring.
-  - At some appropriate point (such as the end of MRGAlloc), destroy free 
-segments.
-  - In MRGAlloc, if there are no free guardians, check the free segment ring 
-before creating a new pair of segments.
-Note that this algorithm would give some slight measure of segment hysteresis.  
-It is not the place of the pool to support general segment hysteresis.
-
-
-FUTURE
-
-.future.array: In future, for speed or simplicity, this pool could be rewritten 
-to use an array.  See mail.gavinm.1997-09-04.13-08(0).
-
-
-TESTS
-
-.test: [This section is utterly out of date. -- Pekka 1997-09-19] The test 
-impl.c.finalcv is similar to the weakness test (see design.mps.weakness, 
-impl.c.weakcv [???]).
-
-
-Functionality
-
-  This is the functionality to be tested:
-
-  .fun.alloc: Can allocate objects.
-
-  .fun.free: Can free objects that were allocated.
-
-  .prot.write: Can write a reference into an allocated object.
-
-  .prot.read: Can read the reference from an allocated object.
-
-  .promise.faithful: A reference stored in an allocated object will continue to 
-refer to the same object.
-
-  .promise.live: A reference stored in an allocated object will preserve the 
-object referred to.
-
-  .promise.unreachable: Any objects referred to in finalization messages are 
-not (at the time of reading the message) reachable via a chain of ambiguous or 
-exact references.  (we will not be able to test this at first as there is no 
-messaging interface)
-
-  .promise.try: The Pool will make a "good faith" effort to finalize objects 
-that are not reachable via a chain of ambiguous or exact references.
-
-
-Attributes
-
-  The following attributes will be tested:
-
-.attr.none: There are no attribute requirements.
-
-
-Implementation
-
-[New test]
-new test will simply allocate a number of objects in the AMC pool and finalize 
-each one, throwing away the reference to the objects.  Churn.
-
-  .test.mpm: The test will use the MPM interface (impl.h.mpm).  
-.test.mpm.justify: This is because it is not intended to provide an MPS 
-interface to this pool directly, and the MPS interface to finalization has not 
-been written yet (impl.h.mps).  .test.mpm.change: Later on it may use the MPS 
-interface, in which case, where the following text refers to allocating objects 
-in the MRG pool it will need adjusting.
-
-  .test.two-pools: The test will use two pools, an AMC pool, and an MRG pool.
-
-  .test.alloc: A number of objects will be allocated in the MRG pool.  
-.test.free: They will then be freed.  This will test .fun.alloc and .fun.free, 
-although not very much.
-
-  .test.rw.a: An object, 'A', will be allocated in the AMC pool, a reference to 
-it will be kept in a root.  .test.rw.alloc: A number of objects will be 
-allocated in the MRG pool.  .test.rw.write: A reference to A will be written 
-into each object.  .test.rw.read: The reference in each object will be read and 
-checked to see if it refers to A.  .test.rw.free: All the objects will be 
-freed.  .test.rw.drop: The reference to A will be dropped.  This will test 
-.prot.write and .prot.read.
-
-  .test.promise.fl.alloc: A number of objects will be allocated in the AMC 
-pool.  .test.promise.fl.tag: Each object will be tagged uniquely.  
-.test.promise.fl.refer: a reference to it will be stored in an object allocated 
-in the MRG pool.  .test.promise.fl.churn: A large amount of garbage will be 
-allocated in the AMC pool.  Regularly, whilst this garbage is being allocated, 
-a check will be performed that all the objects allocated in the MRG pool refer 
-to valid objects and that they still refer to the same objects.  All objects 
-from the MRG pool will then be freed (thus dropping all references to the AMC 
-objects).  This will test .promise.faithful and .promise.live.
-
-  .test.promise.ut.not: The following part of the test has not implemented.  
-This is because the messaging system has not yet been implemented.
-  .test.promise.ut.alloc: A number of objects will be allocated in the AMC 
-pool.  .test.promise.ut.refer: Each object will be referred to by a root and 
-also referred to by an object allocated in the MRG pool.  .test.promise.ut.drop
-: References to a random selection of the objects from the AMC pool will be 
-deleted from the root.  .test.promise.ut.churn: A large amount of garbage will 
-be allocated in the AMC pool.  .test.promise.ut.message: The message interface 
-will be used to receive finalization messages.  .test.promise.ut.final.check: 
-For each finalization message received it will check that the object referenced 
-in the message is not referred to in the root.  .test.promise.ut.nofinal.check: 
-After some amount of garbage has been allocated it will check to see if any 
-objects are not in the root and haven't been finalized.  This will test 
-.promise.unreachable and .promise.try.
-
-
-NOTES
-
-
-.access.inadequate: PoolAccess will scan segments at Rank Exact.  Really it 
-should be scanned at whatever the minimum rank of all grey segments is (the 
-trace rank phase), however there is no way to find this out.  As a consequence 
-we will sometimes scan pages at Rank exact when the pages could have been 
-scanned at Rank final.  This means that finalization of some objects may 
-sometimes get delayed.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poolmv/index.html b/mps/design/poolmv/index.html deleted file mode 100644 index 6c3f4b61a10..00000000000 --- a/mps/design/poolmv/index.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - -The design of the manual variable memory pool class - - - - - - - -
-          THE DESIGN OF THE MANUAL VARIABLE MEMORY POOL CLASS
-                           design.mps.poolmv
-                           incomplete design
-                           richard 1995-08-25
-
-
-IMPLEMENTATION:
-
-.lost: It is possible for MV to "lose" memory when freeing an objects.  This 
-happens when an extra block descriptor is needed (ie the interior of a block is 
-being freed) and the call to allocate the block fails.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poolmvff/index.html b/mps/design/poolmvff/index.html deleted file mode 100644 index b707c1a1a25..00000000000 --- a/mps/design/poolmvff/index.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - -Design of the manually-managed variable-size first-fit pool - - - - - - - -
-      DESIGN OF THE MANUALLY-MANAGED VARIABLE-SIZE FIRST-FIT POOL
-                          design.mps.poolmvff
-                             incomplete doc
-                           gavinm 1998-09-09
-
-INTRODUCTION
-
-.intro: The pool was created in a response to a belief that EPDL/EPDR's first 
-fit policy is beneficial for some classes of client behaviour, but the 
-performance of a linear free list was unacceptable.  This pool implements a 
-first (or last) fit policy for variable-sized manually-managed objects, with 
-control over first/last, segment preference high/low, and slot fit low/high.
-
-
-Document History
-
-.hist.0: GavinM wrote a list of methods and function plus some notes 1998-09-09.
-
-.hist.1: Added overview, removed bogus ArenaEnter design, and described 
-buffered allocation.  pekka 1999-01-06
-
-.hist.2: Modified for the "Sunset On Segments" redesign of segments. Buffered 
-allocation is no longer limited to segment boundaries.
-
-OVERVIEW
-
-.over: This pool implements certain variants of the address-ordered first-fit 
-policy.  The implementation allows allocation across segment boundaries.  
-.over.buffer: Buffered allocation is also supported, but in that case, the 
-buffer-filling policy is worst-fit.  Buffered and unbuffered allocation can be 
-used at the same time, but in that case, the first ap must be created before 
-any allocations. .over.buffer.class: The pool uses the simplest buffer class, 
-BufferClass. This is appropriate since these buffers don't attach to segments, 
-and hence don't constrain buffered regions to lie within segment boundaries. 
-.over.segments: The pool uses the simplest segment class (SegClass). There's no 
-need for anything more complex.
-
-
-METHODS
-
-.method: The MVFF pool supports the following methods:
-
-.method.init: Res MVFFInit(Pool pool, va_list arg) 
-  This takes six vararg parameters:
-  - extendBy -- the segment size;
-  - avgSize -- the average object size;
-  - alignment -- the alignment of allocations and frees (must be at least 
-sizeof(void*));
-  - slotHigh -- whether to allocate objects at the end of free blocks found, as 
-opposed to at the start (for unbuffered allocation);
-  - arenaHigh -- whether to express SegPrefHIGH to the arena, as opposed to 
-SegPrefLOW;
-  - firstFit -- whether to use the suitable block of lowest address, as opposed 
-to the highest (for unbuffered allocation).
-.method.init.epdl: To simulate the EPDL pool, specify extendBy, avgSize, and 
-maxSize as normal, and use slotHigh=FALSE, arenaHigh=FALSE, firstFit=TRUE.  
-.method.init.epdr: To simulate the EPDL pool, specify extendBy, avgSize, and 
-maxSize as normal, and use slotHigh=TRUE, arenaHigh=TRUE, firstFit=TRUE.  
-.method.init.other: The performance characteristics of other combinations are 
-unknown.
-
-.method.finish: The PoolFinish method,
-
-.method.alloc: Alloc and Free methods are supported, implementing the policy 
-set by the pool params (see .method.init).
-
-.method.describe: The usual describe method.
-
-.method.buffer: The buffer methods implement a worst-fit fill strategy.
-
-
-EXTERNAL FUNCTIONS
-
-.function: MVFF supports the following external functions:
-
-.function.free-size: size_t mps_mvff_free_size(mps_pool_t pool)
-  This function returns the total size of free space in segments allocated to 
-the MVFF pool instance.
-
-.function.size: size_t mps_mvff_size(mps_pool_t pool)
-  This function returns the total memory used by pool segments, whether free or 
-allocated.
-
-.function.class: mps_class_t mps_class_mvff(void)
-  This function returns the class object for the pool class, to be used in pool 
-creation.
-
-
-IMPLEMENTATION
-
-.impl.free-list: The pool stores its free list in a CBS (see design.mps.cbs).  
-It uses the CBS's mayUseInline facility to avoid running out of memory to store 
-the free this.  This is the reason for the alignment restriction above.
-
-
-
-DETAILS
-
-.design.seg-size: When adding a segment, we use extendBy as the segment size 
-unless the object won't fit, in which case we use the object size (in both 
-cases we align up).
-
-.design.seg-fail: If allocating a segment fails, we try again with a segment 
-size just large enough for the object we're allocating.  This is in response to 
-request.mps.170186.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/poolmvt/index.html b/mps/design/poolmvt/index.html deleted file mode 100644 index 1a24b8ffc9a..00000000000 --- a/mps/design/poolmvt/index.html +++ /dev/null @@ -1,873 +0,0 @@ - - - - - - - - -The design of a new manual-variable memory pool class - - - - - - - -
-         THE DESIGN OF A NEW MANUAL-VARIABLE MEMORY POOL CLASS
-                           design.mps.poolmvt
-                              draft design
-                       P T Withington 1998-02-13
-
-
-INTRODUCTION:
-
-This is a second-generation design for a pool that manually manages
-variable-sized objects. It is intended as a replacement for poolmv (except in
-its control pool role) and poolepdl, and it is intended to satisfy the
-requirements of the Dylan "misc" pool and the product malloc/new drop-in
-replacement.
-
-[This form should include these fields, rather than me having to create them
-"by hand"]
-
-.readership: MM developers
-
-.source: req.dylan(6), req.epcore(16), req.product(2)
-
-.background: design.mps.poolmv(0), design.mps.poolepdl(0),
-design.product.soft.drop(0), paper.wil95(1), paper.vo96(0), paper.grun92(1),
-paper.beck82(0), mail.ptw.1998-02-25.22-18(0)
-
-.hist.-1: Initial email discussion mail.ptw.1998-02-04.21-27(0), ff.
-.hist.0: Draft created 1998-02-13 by P. T. Withington from email RFC
-mail.ptw.1998-02-12.03-36, ff.
-.hist.1: Revised 1998-04-01 in response to email RFC
-mail.ptw.1998-03-23.20-43(0), ff.
-.hist.2: Revised 1998-04-15 in response to email RFC
-mail.ptw.1998-04-13.21-40(0), ff.
-.hist.3: Erroneously incremented version number
-.hist.4: Revised 1998-05-06 in response to review review.design.mps.poolmv2.2
-(0)
-
-
-DEFINITIONS
-
-.def.alignment: Alignment is a constraint on an object's address, typically to
-be a power of 2 (see also, glossary.alignment )
-
-.def.bit-map: A bitmap is a boolean-valued vector (see also, glossary.bitmap ).
-
-.def.block: A block is a contiguous extent of memory.  In this document, block
-is used to mean a contiguous extent of memory managed by the pool for the pool
-client, typically a subset of a segment (compare with .def.segment).
-
-.def.cartesian-tree: A cartesian tree is a binary tree ordered by two keys
-(paper.stephenson83(0)).
-
-.def.crossing-map: A mechanism that supports finding the start of an object
-from any address within the object, typically only required on untagged
-architectures (see also, glossary.crossing.map ).
-
-.def.footer: A block of descriptive information describing and immediately
-following another block of memory (see also .def.header).
-
-.def.fragmentation: Fragmented memory is memory reserved to the program but not
-usable by the program because of the arrangement of memory already in use (see
-also, glossary.fragmentation ).
-
-.def.header: A block of descriptive information describing and immediately
-preceding another block of memory (see also, glossary.in-band.header ).
-
-.def.in-band: From "in band signalling", when descriptive information about a
-data structure is stored in the data structure itself (see also,
-glossary.in-band.header ).
-
-.def.out-of-band: When descriptive information about a data structure is stored
-separately from the structure itself (see also, glossary.out-of-band.header ).
-
-.def.refcount: A refcount is a count of the number of users of an object (see
-also, glossary.reference.count ).
-
-.def.segment: A segment is a contiguous extent of memory.  In this document,
-segment is used to mean a contiguous extent of memory managed by the MPS arena
-(design.mps.arena(1)) and subdivided by the pool to provide blocks (see
-.def.block) to its clients.
-
-.def.splay-tree: A splay tree is a self-adjusting binary tree (paper.st85(0),
-paper.sleator96(0)).
-
-.def.splinter: A splinter is a fragment of memory that is too small to be
-useful (see also, glossary.splinter )
-
-.def.subblock: A subblock is a contiguous extent of memory.  In this document,
-subblock is used to mean a contiguous extent of memory manage by the client for
-its own use, typically a subset of a block (compare with .def.block).
-
-
-ABBREVIATIONS
-
-.abbr.abq: ABQ = Available Block Queue
-
-.abbr.ap: AP = Allocation Point
-
-.abbr.cbs: CBS = Coalescing Block Structure
-
-.abbr.mps: MPS = Memory Pool System
-
-.abbr.mv: MV = Manual-Variable
-
-.abbr.ps: PS = PostScript
-
-
-
-OVERVIEW:
-
-mvt is intended to satisfy the requirements of the clients that need
-manual-variable pools, improving on the performance of the existing
-manual-variable pool implementations, and reducing the duplication of code that
-currently exists. The expected clients of mvt are: Dylan (currently for its
-misc pool), EP (particularly the dl pool, but all pools other than the PS
-object pool), and Product (initially the malloc/new pool, but also other manual
-pool classes).
-
-
-REQUIREMENTS:
-
-.req.cat: Requirements are categorized per guide.req(2).
-
-.req.risk: req.epcore(16) is known to be obsolete, but the revised document has
-not yet been accepted.
-
-
-Critical Requirements
-
-.req.fun.man-var: The pool class must support manual allocation and freeing of
-variable-sized blocks (source: req.dylan.fun.misc.alloc,
-req.epcore.fun.{dl,gen,tmp,stat,cache,trap}.{alloc,free},
-req.product.fun.{malloc,new,man.man}).
-
-.non-req.fun.gc: There is not a requirement that the pool class support
-formatted objects, scanning, or collection objects; but it should not be
-arbitrarily precluded.
-
-.req.fun.align: The pool class must support aligned allocations to
-client-specified alignments.  An individual instance need only support a single
-alignment; multiple instances may be used to support more than one alignment
-(source: req.epcore.attr.align).
-
-.req.fun.reallocate: The pool class must support resizing of allocated blocks
-(source req.epcore.fun.dl.promise.free, req.product.dc.env.{ansi-c,cpp}).
-
-.non-req.fun.reallocate.in-place: There is not a requirement blocks must be
-resized in place (where possible); but it seems like a good idea.
-
-.req.fun.thread: Each instance of the pool class must support multiple threads
-of allocation (source req.epcore.fun.dl.multi, req.product.dc.env.{ansi-c,cpp}).
-
-.req.attr.performance: The pool class must meet or exceed performance of
-"competitive" allocators (source: rec.epcore.attr.{run-time,tp},
-req.product.attr.{mkt.eval, perform}).  [Dylan does not seem to have any
-requirement that storage be allocated with a particular response time or
-throughput, just so long as we don't block for too long. Clearly there is a
-missing requirement.]
-
-.req.attr.performance.time: By inference, the time overhead must be competetive.
-
-.req.attr.performance.space: By inference, the space overhead must be
-competetive.
-
-.req.attr.reliability: The pool class must have "rock-solid reliability"
-(source: req.dylan.attr.rel.mtbf, req.epcore.attr.rel, req.product.attr.rel).
-
-.req.fun.range: The pool class must be able to manage blocks ranging in size
-from 1 byte to all of addressable memory
-(req.epcore.attr.{dl,gen,tmp,stat,cache,trap}.obj.{min,max}.  The range
-requirement may be satisfied by multiple instances each managing a particular
-client-specified subrange of sizes.  [Dylan has requirements
-req.dylan.attr.{capacity,obj.max}, but no requirement that such objects reside
-in a manual pool.]
-
-.req.fun.debug: The pool class must support debugging erroneous usage by client
-programs (source: req.epcore.fun.{dc.variety, debug.support},
-req.product.attr.{mkt.eval,perform}).  Debugging is permitted to incur
-additional overhead.
-
-.req.fun.debug.boundaries: The pool class must support checking for accesses
-outside the boundaries of live objects.
-
-.req.fun.debug.log: The pool class must support logging of all allocations and
-deallocations.
-
-.req.fun.debug.enumerate: The pool class must support examining all allocated
-objects.
-
-.req.fun.debug.free: The pool class must support detecting incorrect,
-overlapping, and double frees.
-
-.req.fun.tolerant: The pool class must support tolerance of erroneous usage
-(source req.product.attr.use.level.1).
-
-
-Essential Requirements
-
-.req.fun.profile: The pool class should support memory usage profiling (source:
-req.product.attr.{mkt.eval, perform}).
-
-.req.attr.flex: The pool class should be flexible so that it can be tuned to
-specific allocation and freeing patterns (source:
-req.product.attr.flex,req.epcore.attr.{dl,cache,trap}.typ).  The flexibility
-requirement may be satisfied by multiple instances each optimizing a specific
-pattern.
-
-.req.attr.adapt: The pool class should be adaptive so that it can accommodate
-changing allocation and freeing patterns (source:
-req.epcore.fun.{tmp,stat}.policy, req.product.attr.{mkt.eval,perform}).
-
-
-Nice Requirements
-
-.req.fun.suballocate: The pool class may support freeing of any aligned,
-contiguous subset of an allocated block (source req.epcore.fun.dl.free.any,
-req.product.attr.{mkt.eval,perform}).
-
-
-
-
-ARCHITECTURE:
-
-.arch.overview: The pool has several layers: client allocation is by Allocation
-Points (APs). .arch.overview.ap: APs acquire storage from the pool
-available-block queue (ABQ). .arch.overview.abq: The ABQ holds blocks of a
-minimum configurable size: "reuse size".  .arch.overview.storage: The ABQ
-acquires storage from the arena or from the coalescing-block structure (CBS).
-.arch.overview.storage.contiguous: The arena storage is requested to be
-contiguous to maximize opportunities for coalescing (Loci will be used when
-available). .arch.overview.cbs: The CBS holds blocks freed by the client until,
-through coalescing, they have reached the reuse size, at which point they are
-made available on the ABQ.
-
-.arch.ap: The pool will use allocation points as the allocation interface to
-the client. .arch.ap.two-phase: Allocation points will request blocks from the
-pool and suballocate those blocks (using the existing AP, compare and
-increment, 2-phase mechanism) to satisfy client requests. .arch.ap.fill: The
-pool will have a configurable "fill size" that will be the preferred size block
-used to fill the allocation point. .arch.ap.fill.size: The fill size should be
-chosen to amortize the cost of refill over a number of typical reserve/commit
-operations, but not so large as to exceed the typical object population of the
-pool. .arch.ap.no-fit: When an allocation does not fit in the remaining space
-of the allocation point, there may be a remaining fragment.
-.arch.ap.no-fit.sawdust: If the fragment is below a configurable threshold
-(minimum size), it will be left unused (but returned to the CBS so it will be
-reclaimed when adjacent objects are freed); .arch.ap.no-fit.splinter:
-otherwise, the remaining fragment will be (effectively) returned to the head of
-the available-block queue, so that it will be used as soon as possible (i.e.,
-by objects of similar birthdate). .arch.ap.no-fit.oversize: If the requested
-allocation exceeds the fill size it is treated exceptionally (this may indicate
-the client has either misconfigured or misused the pool and should either
-change the pool configuration or create a separate pool for these exceptional
-objects for best performance). .arch.ap.no-fit.oversize.policy: Oversize blocks
-are assumed to have exceptional lifetimes, hence are allocated to one side and
-do not participate in the normal storage recycling of the pool.
-.arch.ap.refill.overhead: If reuse size is small, or becomes small due to
-.arch.adapt, all allocations will effectively be treated exceptionally (the AP
-will trip and a oldest-fit block will be chosen on each allocation).  This mode
-will be within a constant factor in overhead of an unbuffered pool.
-
-.arch.abq: The available block queue holds blocks that have coalesced
-sufficiently to reach reuse size.  arch.abq.reuse.size: A multiple of the
-quantum of virtual memory is used as the reuse size (.anal.policy.size).
-.arch.abq.fifo: It is a FIFO queue (recently coalesced blocks go to the tail of
-the queue, blocks are taken from the head of the queue for reuse).
-.arch.abq.delay-reuse: By thus delaying reuse, coalescing opportunities are
-greater. .arch.abq.high-water: It has a configurable high water mark, which
-when reached will cause blocks at the head of the queue to be returned to the
-arena, rather than reused. .arch.abq.return: When the MPS supports it, the pool
-will be able to return free blocks from the ABQ to the arena on demand.
-.arch.return.segment: arch.abq.return can be guaranteed to be able to return a
-segment by setting reuse size to twice the size of the segments the pool
-requests from the arena.
-
-.arch.cbs: The coalescing block structure holds blocks that have been freed by
-the client. .arch.cbs.optimize: The data structure is optimized for coalescing.
-.arch.cbs.abq: When a block reaches reuse size, it is added to the ABQ.
-.arch.cbs.data-structure: The data structures are organized so that a block can
-be on both the CBS and ABQ simultaneously to permit additional coalescing, up
-until the time the block is removed from the ABQ and assigned to an AP.
-
-.arch.fragmentation.internal: Internal fragmentation results from The pool will
-request large segments from the arena to minimize the internal fragmentation
-due to objects not crossing segment boundaries.
-
-.arch.modular: The architecture will be modular, to allow building variations
-on the pool by assembling different parts. .arch.modular.example: For example,
-it should be possible to build pools with any of the freelist mechanisms, with
-in-band or out-of-band storage (where applicable), that do or do not support
-derived object descriptions, etc.
-
-.arch.modular.initial: The initial architecture will use
-.mech.freelist.splay-tree for the CBS, .sol.mech.storage.out-of-band,
-.sol.mech.desc.derived, and .sol.mech.allocate.buffer.
-
-.arch.segregate: The architecture will support segregated allocation through
-the use of multiple allocation points. The client will choose the appropriate
-allocation point either at run time, or when possible, at compile time.
-
-.arch.segregate.initial: The initial architecture will segregate allocations
-into two classes: large and small. This will be implemented by creating two
-pools with different parameters.
-
-.arch.segregate.initial.choice: The initial architecture will provide glue code
-to choose which pool to allocate from at run time. If possible this glue code
-will be written in a way that a good compiler can optimize the selection of
-pool at compile time. Eventually this glue code should be subsumed by the
-client or generated automatically by a tool.
-
-.arch.debug: Debugging features such as tags, fenceposts, types, creators will
-be implemented in a layer above the pool and APs.  A generic pool debugging
-interface will be developed to support debugging in this outer layer.
-
-.arch.debug.initial: The initial architecture will have counters for
-objects/bytes allocated/freed and support for detecting overlapping frees.
-
-.arch.dependency.loci: The architecture depends on the arena being able to
-efficiently provide segments of varying sizes without excessive fragmentation.
-The locus mechanism should satisfy this dependency. (See .anal.strategy.risk)
-
-.arch.dependency.mfs: The architecture internal data structures depend on
-efficient manual management of small, fixed-sized objects (2 different sizes).
-The MFS pool should satisfy this dependency.
-
-.arch.contingency: Since the strategy we propose is new, it may not work.
-.arch.contingency.pathalogical: In particular, pathological allocation patterns
-could result in fragmentation such that no blocks recycle from the CBS to ABQ.
-.arch.contingency.fallback: As a fallback, there will be a pool creation
-parameter for a high water mark for the CBS.
-.arch.contingency.fragmentation-limit: When the free space in the CBS as a
-percentage of all the memory managed by the pool (a measure of fragmentation)
-reaches that high water mark, the CBS will be searched oldest-fit before
-requesting additional segments from the arena. .arch.contingency.alternative:
-We also plan to implement .mech.freelist.cartesian-tree as an alternative CBS,
-which would permit more efficient searching of the CBS.
-
-.arch.parameters: The architecture supports several parameters so that multiple
-pools may be instantiated and tuned to support different object cohorts. The
-important parameters are: reuse size, minimum size, fill size, ABQ high water
-mark, CBS fragmentation limit (see .arch.contingency.fragmentation-limit).
-.arch.parameters.client-visible: The client-visible parameters of the pool are
-the minimum object size, the mean object size, the maximum object size, the
-reserve depth and fragmentation limit.  The minimum object size determines when
-a splinter is kept on the head of the ABQ (.arch.ap.no-fit.splinter).  The
-maximum object size determines the fill size (.arch.ap.fill-size) and hence
-when a block is allocated exceptionally (.arch.ap.no-fit.oversize). The mean
-object size is the most likely object size.  The reserve depth is a measure of
-the hysteresis of the object population.  The mean object size, reserve depth
-and, maximum object size are used to determine the size of the ABQ
-(.arch.abq.high-water).  The fragmentation limit is used to determine when
-contingency mode is used to satisfy an allocation request (.arch.contingency).
-
-.arch.adapt: We believe that an important adaptation to explore is tying the
-reuse size inversely to the fragmentation (as measured in
-.arch.contingency.fragmentation-limit). .arch.adapt.reuse: By setting reuse
-size low when fragmentation is high, smaller blocks will be available for
-reuse, so fragmentation should diminish. .arch.adapt.overhead: This will result
-in higher overhead as the AP will need to be refilled more often, so reuse size
-should be raised again as fragmentation diminishes. .arch.adapt.oldest-fit: In
-the limit, if reuse size goes to zero, the pool will implement a "oldest-fit"
-policy: the oldest free block of sufficient size will be used for each
-allocation.
-
-.arch.adapt.risk: This adaptation is an experimental policy and should not be
-delivered to clients until thoroughly tested.
-
-
-
-
-
-ANALYSIS:
-
-.anal.discard: We have discarded many traditional solutions based on experience
-and analysis in paper.wil95(1). In particular, managing the free list as a
-linear list arranged by address or size and basing policy on searching such a
-linear list in a particular direction, from a particular starting point, using
-fit and/or immediacy as criteria. We believe that none of these solutions is
-derived from considering the root of the problem to be solved (as described in
-.strategy), although their behavior as analyzed by Wilson gives several
-insights.
-
-.anal.strategy: For any program to run in the minimum required memory (with
-minimal overhead -- we discard solutions such as compression for now),
-fragmentation must be eliminated. To eliminate fragmentation, simply place
-blocks in memory so that they die "in order" and can be immediately coalesced.
-This ideal is not achievable, but we believe we can find object attributes that
-correlate with deathtime and exploit them to approximate the ideal. Initially
-we believe birth time and type (as approximated by size) will be useful
-attributes to explore.
-
-.anal.strategy.perform: To meet .req.attr.performance, the implementation of
-.sol.strategy must be competitive in both time and space.
-
-.anal.strategy.risk: The current MPS segment substrate can cause internal
-fragmentation which an individual pool can do nothing about. We expect that
-request.epcore.170193.sugg.loci will be implemented to remove this risk.
-
-.anal.policy: Deferred coalescing, when taken to the extreme will not minimize
-the memory consumption of a program, as no memory would ever be reused. Eager
-reuse appears to lead to more fragmentation, whereas delayed reuse appears to
-reduce fragmentation (paper.wil95(1)). The systems studied by Wilson did not
-directly address deferring reuse. Our proposed policy is to reuse blocks when
-they reach a (configurable) size. We believe that this policy along with the
-policy of segregating allocations by death time, will greatly reduce
-fragmentation. .anal.policy.risk: This policy could lead to pathologic behavior
-if allocations cannot be successfully segregated.
-
-.anal.policy.allocate.segregate: This policy has some similarities to
-CustomAlloc (paper.grun92(1)). CustomAlloc segregates objects by size classes,
-and then within those classes chooses a different allocator depending on
-whether that size class has a stable or unstable population. Classes with
-stable population recycle storage within the class, whereas classes with
-unstable populations return their storage to the general allocation pool for
-possible reuse by another class. CustomAlloc, however, requires profiling the
-application and tuning the allocator according to those profiles. Although we
-intend to support such tuning, we do not want to require it.
-
-.anal.policy.reallocate: For reallocation, .fun.suballocate can be used to free
-the remainder if a block is made smaller. Doing so will cause the freed block
-to obey .sol.policy.allocate [i.e., the freed block will not be treated
-specially, it will be subject to the normal policy on reuse]. Copying can be
-used if a block is made larger. paper.vo96(0) reports success in
-over-allocating a block the first time it is resized larger, presumably because
-blocks that are resized once tend to be resized again and over-allocating may
-avoid a subsequent copy. If each object that will be reallocated can be given
-its own allocation point until its final reallocation, the allocation point can
-be used to hold released or spare storage.
-
-.anal.policy.size: We believe that this will take advantage of the underlying
-virtual memory system's ability to compact the physical memory footprint of the
-program by discarding free fragments that align with the virtual memory
-quantum.  (In a VM system one can approximate compaction by sparse mapping.  If
-every other page of a segment is unused, the unused pages can be unmapped,
-freeing up physical memory that can be mapped to a new contiguous vm range.)
-
-.anal.mech.freelist: The literature (paper.grun92(1), paper.vo96(0)) indicate
-that .sol.freelist.cartesian-tree provides a space-efficient implementation at
-some cost in speed. .sol.freelist.splay-tree is faster but less
-space-efficient. .sol.freelist.bitmap is unstudied. Many of the faster
-allocators maintain caches of free blocks by size to speed allocation of
-"popular" sizes. We intend to initially explore not doing so, as we believe
-that policy ultimately leads to fragmentation by mixing objects of varying
-death times. Instead we intend to use a free list mechanism to support fast
-coalescing, deferring reuse of blocks until a minimum size has been reached.
-
-anal.mech.allocate.optimize-small: Wilson (paper.wil95(1)) notes that small
-blocks typically have short lifetimes and that overall performance is improved
-if you optimize the management of small blocks, e.g.,
-sol.mech.allocate.lookup-table for all small blocks.  We believe that
-.sol.mech.allocate.buffer does exactly that.
-
-.anal.mech.allocate.optimize-new: Wilson (paper.wil95(1)) reports some benefit
-from "preserving wilderness", that is, when a block of memory must be requested
-from the system to satisfy an allocation, only the minimum amount of that block
-is used, the remainder is preserved (effectively by putting it at the tail of
-the free list). This mechanism may or may not implement .sol.policy.allocate.
-We believe a better mechanism is to choose to preserve or not, based on
-.sol.policy.allocate.
-
-
-
-
-IDEAS:
-
-.sol: Many solution ideas for manual management of variable-sized memory blocks
-are enumerated by paper.wil95(1). Here we list the most promising, and some of
-our own.
-
-
-Strategy
-
-.sol.strategy: To run a program in the minimal required memory, with minimal
-overhead, utilize memory efficiently. Memory becomes unusable when fragmented.
-Strategy is to minimize fragmentation. So place blocks where they won't cause
-fragmentation later.
-
-.sol.strategy.death: objects that will die together (in time) should be
-allocated together (in space); thus they will coalesce, reducing fragmentation.
-
-.sol.strategy.death.birth: assume objects allocated near each other in time
-will have similar deathtimes (paper.beck82(0))
-.sol.strategy.death.type: assume objects of different type may have different
-deathtimes, even if born together
-.sol.strategy.death.predict: find and use program features to predict deathtimes
-
-.sol.strategy.reallocate: reallocation implies rebirth, or at least a change in
-lifetime
-
-.sol.strategy.debug: as much of the debugging functionality as possible should
-be implemented as a generally available MPS utility; the pool will provide
-support for debugging that would be expensive or impossible to allocate outside
-the pool
-
-
-Policy
-
-[Policy is an implementable decision procedure, hopefully approximating the
-strategy.]
-
-.sol.policy.reuse: defer reusing blocks, to encourage coalescing
-.sol.policy.split: when a block is split to satisfy an allocation, use the
-remainder as soon as possible
-.sol.policy.size: prevent .policy.reuse from consuming all of memory by
-choosing a (coalesced) block for reuse when it reaches a minimum size
-.sol.policy.size.fixed: use the quantum of virtual memory (e.g., one page) as
-minimum size
-.sol.policy.size.tune: allow tuning minimum size
-.sol.policy.size.adapt: adaptively change minimum size
-.sol.policy.allocate: allocate objects with similar birthdate and lifetime
-together
-.sol.policy.allocate.segregate: segregate allocations by type
-.sol.policy.allocate.segregate.size: use size as a substitute for type
-.sol.policy.allocate.segregate.tune: permit tuning of segregation
-.sol.policy.allocate.segregate.adapt: adaptively segregate allocations
-
-.sol.policy.reallocate: implement reallocation in a central mechanism outside
-of the pool, create a generic pool interface in support of same.
-
-.sol.policy.debug: implement a pool debugging interface
-.sol.policy.debug.counters: implement debugging counters in the pool that are
-queried with a generic interface
-.sol.policy.debug.verify: implement debugging error returns on overlapping frees
-
-
-Mechanism
-
-[Mechanisms are algorithms or data structures used to implement policy.]
-
-.sol.mech.free-list: mechanisms that can be used to describe the free list
-
-.sol.mech.free-list.cartesian-tree: Using address and size as keys supports
-fast coalescing of adjacent blocks and fast searching for optimal-sized blocks.
-Unfortunately, because the shape of the tree is constrained by the second key,
-it can become unbalanced. This data structure is used in the SunOS 4.1 malloc
-(paper.grun92(1)).
-.sol.mech.free-list.splay-tree: The amortized cost of a splay tree is
-competitive with balanced binary trees in the worst case, but can be
-significantly better for regular patterns of access because recently-accessed
-keys are moved to the root of the tree and hence can be re-accessed quickly.
-This data structure is used in the System Vr4 malloc (paper.vo96(0)). (For a
-complete analysis of the splay tree algorithm time bounds see paper.st85(0).)
-.sol.mech.free-list.bit-map: Using address as an index and fix-sized blocks,
-the booleans can represent whether a block is free or not. Adjacent blocks can
-be used to construct larger blocks. Efficient algorithms for searching for runs
-in a vector are known. This data structure is used in many file system disk
-block managers.
-.sol.mech.free-list.refcount: A count of the number of allocated but not freed
-subblocks of a block can be used to determine when a block is available for
-reuse. This is an extremely compact data structure, but does not support
-subblock reuse.
-.sol.mech.free-list.hybrid: Bitmaps appear suited particularly to managing
-small, contiguous blocks. The tree structures appear suited particularly to
-managing varying-sized, discontiguous blocks. A refcount can be very efficient
-if objects can be placed accurately according to death time. A hybrid mechanism
-may offer better performance for a wider range of situations.
-
-.sol.mech.storage: methods that can be used to store the free list description
-
-.sol.mech.storage.in-band: The tree data structures are amenable to being
-stored in the free blocks themselves, minimizing the space overhead of
-management. To do so imposes a minimum size on free blocks and reduces the
-locality of the data structure.
-.sol.mech.storage.out-of-band: The bit-map data structure must be stored
-separately.
-
-.sol.mech.desc: for an allocated block to be freed, its base and bound must be
-known
-
-.sol.mech.desc.derived: Most clients can supply the base of the block. Some
-clients can supply the bound.
-.sol.mech.desc.in-band: When the bound cannot be supplied, it can be stored as
-an in-band "header". If neither the base nor bound can be supplied (e.g., the
-client may only have an interior pointer to the block), a header and footer may
-be required.
-.sol.mech.desc.out-of-band: In un-tagged architectures, it may be necessary to
-store the header and footer out-of-band to distinguish them from client data.
-Out-of-band storage can improve locality and reliability. Any of the free-list
-structures can also be used to describe allocated blocks out-of-band.
-.sol.mech.desc.crossing-map: An alternative for untagged architectures is to
-store a "crossing map" which records an encoding of the start of objects and
-then store the descriptive information in-band.
-
-.sol.mech.allocate: mechanisms that can be used to allocate blocks (these
-typically sit on top of a more general free-list manager)
-
-.sol.mech.allocate.lookup-table: Use a table of popular sizes to cache free
-blocks of those sizes.
-.sol.mech.allocate.buffer: Allocate from contiguous blocks using compare and
-increment.
-.sol.mech.allocate.optimize-small: Use a combination of techniques to ensure
-the time spent managing a block is small relative to the block's lifetime;
-assume small blocks typically have short lifetimes.
-.sol.mech.allocate.optimize-new: When "virgin" memory is acquired from the
-operating system to satisfy a request, try to preserve it (i.e., use only what
-is necessary)
-.sol.mech.allocate.segregate.size: use size as a substitute for type
-
-.sol.mech.reallocate: use .req.fun.suballocate to return unused memory when a
-block shrinks, but differentiate this from an erroneous overlapping free by
-using separate interfaces.
-
-
-
-
-IMPLEMENTATION:
-
-The implementation consists of the following separable modules:
-
-
-Coalescing Block Structure
-
-.impl.c.cbs: The initial implementation will use .sol.mech.free-list.splay-tree
-and sol.mech.storage.out-of-band. For locality, this storage should be managed
-as a linked free list of splay nodes suballocated from blocks acquired from a
-pool shared by all CBS's. Must support creation and destruction of an empty
-tree. Must support search, insert and delete by key of type Addr.  Must support
-finding left and right neighbors of a failed search for a key. Must support
-iterating over the elements of the tree with reasonable efficiency. Must
-support storing and retrieving a value of type Size associated with the key.
-Standard checking and description should be provided. See design.mps.splay(0)
-and design.mps.cbs(0).
-
-
-Available Block Queue
-
-.impl.c.abq: The initial implementation will be a queue of fixed size
-(determined at pool creation time from the high water mark). Must support
-creation and destruction of an empty queue. Must support insertion at the head
-or tail of the queue (failing if full), peeking at the head of the queue, and
-removal of the head (failing if empty) or any element of the queue (found by a
-search). Standard checking and description should be provided.
-
-
-Pool Implementation
-
-.impl.c: The initial implementation will use the above modules to implement a
-buffered pool. Must support creation and destruction of the pool. Creation
-takes parameters: minimum size, mean size, maximum size, reserve depth and
-fragmentation limit. Minimum, mean, and maximum size are used to calculate the
-internal fill and reuse sizes. Reserve depth and mean size are used to
-calculate the ABQ high water mark.  Fragmentation limit is used to set the CBS
-contingency mode.  Must support buffer initialization, filling and emptying.
-Must support freeing. Standard checking and description should be provided.
-[Eventually, it should support scanning, so it can be used with collected
-pools, but no manual pool currently does.]
-
-.impl.c.future: The implementation should not preclude "buffered free"
-(mail.ptw.1997-12-05.19-07(0), ff.) being added in the future.
-
-.impl.c.parameters: The pool parameters are calculated as follows from the
-input parameters: minimum, mean, and maximum size are taked directly from the
-parameters.  .impl.c.parameter.fill-size: The fill size is set to the maximum
-size times the reciprocal of the fragmentation limit, aligned to the arena
-alignment.  .imple.c.parameter.reuse-size: The reuse size is set to twice the
-fill size (see .arch.abq.return.segment, .impl.c.free.merge.segment).
-.impl.c.parameter.abq-limit: The ABQ high-water limit is set to the reserve
-depth times the mean size (that is, the queue should hold as many reuse blocks
-as would take to cover the population hysteresis if the population consisted
-solely of mean-sized blocks, see .arch.abq.high-water).
-.impl.c.parameter.avail-limit: The CBS high-water limit is implemented by
-comparing the available free space to an "available limit".  The available
-limit is updated each time a segment is allocated from or returned to the arena
-by setting it to the total size of the pool times the fragmentation limit
-divide vy 100 (see .arch.contingency.fallback).
-
-.impl.c.ap.fill: An AP fill request will be handled as follows:
-o If the request is larger than fill size, attempt to request a segment from
-the arena sufficient to satisfy the request
-o Use any previously returned splinter (from .impl.c.ap.empty), if large enough
-o Attempt to retrieve a free block from the head of the ABQ (removing it from
-ABQ and CBS if found).
-o If above fragmentation limit, attempt to find a block on the CBS, using
-oldest-fit search
-o Attempt to request a segment of fill size from the arena
-o Attempt to find a block on the CBS, using oldest-fit search
-o Otherwise, fail
-
-.impl.c.ap.empty: An AP empty request will be handled as follows:
-o If remaining free is less than min size, return it to the CBS
-o If the remaining free is larger than any previous splinter, return that
-splinter to the CBS and save this one for use by a subsequent fill
-o Otherwise return the remaining block to the CBS
-
-.impl.c.free: When blocks are returned to the CBS a search is made for adjacent
-blocks that can be merged. If not, the block is simply inserted in the CBS. If
-a merge occurs between two blocks on the ABQ, the ABQ must be adjusted to
-reflect the merge. .impl.c.free.exception: Exceptional blocks are returned
-directly to the arena.
-
-.impl.c.free.merge: If a merge occurs and the merged block is larger than reuse
-size:
-o If the ABQ is full, remove the block at the head of the ABQ from the ABQ and
-CBS and return it to the arena(*)
-o Insert the newly merged block at the tail of the ABQ, leaving it on the CBS
-for further merging
-
-.impl.c.free.merge.segment: (*) Merged blocks may not align with arena
-segments. If necessary, return the interior segments of a block to the arena
-and return the splinters to the CBS.  .impl.c.free.merge.segment.reuse: If the
-reuse size (the size at which blocks recycle from the CBS to the ABQ) is at
-least twice the fill size (the size of segments the pool allocates from the
-arena), we can guarantee that there will always be a returnable segment in
-every ABQ block. .impl.c.free.merge.segment.overflow: If the reuse size is set
-smaller (see .arch.adapt), there may not be a returnable segment in an ABQ
-block, in which case the ABQ has "overflowed".  Whenever this occurs, the ABQ
-will be refilled by searching the CBS for dropped reusable blocks when needed.
-
-.impl.c.free.merge.segment.risk: The current segment structure does not really
-support what we would like to do.  Loci should do better:  support reserving
-contiguous address space and mapping/unmapping any portion of that address
-space.
-
-.impl.c.free.merge.alternative: Alternatively, if the MPS segment substrate
-permitted mapping/unmapping of pages, the pool could use very large segments
-and map/unmap pages as needed.
-
-
-AP Dispatch
-
-.impl.c.multiap: The initial implementation will be a glue layer that selects
-among several AP's for allocation according to the predicted deathtime (as
-approximated by size) of the requested allocation. Each AP will be filled from
-a pool instance tuned to the range of object sizes expected to be allocated
-from that AP. [For bonus points provide an interface that creates a batch of
-pools and AP's according to some set of expected object sizes. Eventually
-expand to understand object lifetimes and general lifetime prediction keys.]
-
-impl.c.multiap.sample-code: This glue code is not properly part of the pool or
-MPS interface.  It is a layer on top of the MPS interface, intended as sample
-code for unsophisticated clients.  Sophisticated clients will likely want to
-choose among multiple AP's more directly.
-
-
-
-
-TESTING:
-
-.test.component: Components .impl.c.splay, .impl.c.cbs, and .impl.c.abq will be
-subjected to individual component tests to verify their functionality.
-
-.test.regression: All tests applied to poolmv (design.mps.poolmv(0)) and
-poolepdl (design.mps.poolepdl(0)) will be applied to poolmvt to ensure that mvt
-is at least as functional as the pools it is replacing.
-
-.test.qa: Once poolmvt is integrated into the MPS, the standard MPS QA tests
-will be applied to poolmvt prior to each release.
-
-.test.customer: Customer acceptance tests will be performed on a per-customer
-basis before release to that customer (cf., proc.release.epcore(2).test)
-
-
-TEXT:
-
-Possible tweaks (from mail.pekka.1998-04-15.13-10(0)):
-
-1. Try to coalesce splinters returned from AP's with the front (or any) block
-on the ABQ.
-2. Sort ABQ in some other way to minimize splitting/splinters. E.g., proximity
-to recently allocated blocks.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/prot/index.html b/mps/design/prot/index.html deleted file mode 100644 index fc9a1984091..00000000000 --- a/mps/design/prot/index.html +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - -Generic design of the protection module - - - - - - - -
-                GENERIC DESIGN OF THE PROTECTION MODULE
-                            design.mps.prot
-                             incomplete doc
-                             drj 1997-04-02
-
-INTRODUCTION
-
-.readership: Any MPS developer.
-
-.intro: This is the generic design of the Protection Module.  The protection 
-module provides protection services to other parts of the MPS.  It is expected 
-that different operating systems will have different implementations of this 
-module.
-
-
-INTERFACE
-
-.if.setup:
-
-void ProtSetup(void);
-
-ProtSetup will be called exactly once (per process).  It will be called as part 
-of the initialization of the first space that is created.  It should arrange 
-for the setup and initialization of any datastructures or services that are 
-necessary in order to implement the protection module.  (On UNIX it expected 
-that it will install a signal handler, on Windows it will do nothing)
-
-.if.set:
-
-void ProtSet(Addr base, Addr limit, AccessSet mode)
-
-ProtSet should set the protection of the memory between base and limit, 
-including base, but not including limit (ie the half-open interval 
-[base,limit)) to that specified by mode.
-The mode parameter should have the AccessWrite bit set if write accesses to the 
-page are to be forbidden, and should have the AccessRead bit set if read 
-accesses to the page are to be forbidden.  A request to forbid read accesses 
-(ie AccessRead is set) may also forbid write accesses, but read accesses will 
-not be forbidden unless AccessRead is set.
-
-.if.tramp:
-
-void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), void *p, size_t 
-s);
-
-.if.sync:
-
-void ProtSync(Space space);
-
-ProtSync is called to ensure that the actual protection of each segment (as 
-determined by the OS) is in accordance with the segments's pm field.
-
-.if.context-type:
-
-typedef struct MutatorFaultContextStruct *MutatorFaultContext;
-
-This abstract type is implemented by the protection module (impl.c.prot*).  It 
-represents the continuation of the mutator which is restored after a mutator 
-fault has been handled.  The functions ProtCanStepInstruction (.if.canstep 
-below) and ProtStepInstruction (.if.step below) inspect and manipulate the 
-context.
-
-.if.canstep:
-
-Bool ProtCanStepInstruction(MutatorFaultContext context);
-
-Examines the context to determine whether the protection module can single-step 
-the instruction which is causing the fault. Should return TRUE if and only if 
-the instruction can be single-stepped (ie ProtStepInstruction can be called).
-
-.if.step:
-
-Bool Res ProtStepInstruction(MutatorFaultContext context);
-
-Single-steps the instruction which is causing the fault.  This function should 
-only be called if ProtCanStepInstruction applied to
-the context returned TRUE.  It should return ResUNIMPL if the instruction 
-cannot be single-stepped.  It should return ResOK if the
-instruction is single-stepped.
-
-The mutator context will be updated by the emulation/execution of the 
-instruction such that resuming the mutator will not cause the
-instruction which was causing the fault to be executed.
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/protan/index.html b/mps/design/protan/index.html deleted file mode 100644 index 87aa9700252..00000000000 --- a/mps/design/protan/index.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - -ANSI implementation of protection module - - - - - - - -
-                ANSI IMPLEMENTATION OF PROTECTION MODULE
-                           design.mps.protan
-                             incomplete doc
-                             drj 1997-03-19
-
-INTRODUCTION
-
-.readership: Any MPS developer
-
-.intro: This is the design for the ANSI implementation of the Protection Module.
-
-
-REQUIREMENTS
-
-.req.test: This module is required for testing.  Particularly on platforms 
-where no real implementation of the protection module exists.
-
-.req.rapid-port: This module is required for rapid porting.  It should enable a 
-developer to port a minimally useful configuration of the MPS to new platforms 
-very quickly.
-
-
-OVERVIEW
-
-.overview: Most of the functions in the module do nothing.  The exception is 
-ProtSync which traverses over all segments in the arena and simulates an access 
-to each segment that has any protection on it.  This means that this module 
-depends on certain fields in the segment structure.
-
-.overview.noos: No operating system specific (or even ANSI hosted specific) 
-code is in this module.  It can therefore be used on any platform, particularly 
-where no real implementation of the module exists.  It satisfies .req.test and 
-.req.rapid-port in this way.
-
-
-FUNCTIONS
-
-.fun.protsetup:
-
-ProtSetup
-
-Does nothing as there is nothing to do (under UNIX we might expect the 
-Protection Module to install one or more signal handlers at this pointer, but 
-that is not appropriate for the ANSI implementation).  Of course, we can't 
-have an empty function body, so there is a NOOP; here.
-
-.fun.sync:
-
-ProtSync
-
-.fun.sync.what:
-ProtSync is called to ensure that the actual protection of each segment (as 
-determined by the OS) is in accordance with the segments's pm field.  In the 
-ANSI implementation we have no way of changing the protection of a segment, so 
-instead we generate faults on all protected segments in the assumption that 
-that will remove the protection on segments.
-
-.fun.sync.how:
-Continually loops over all the segments until it finds that all segments have 
-no protection.  .sync.seg: If it finds a segment that is protected then 
-PoolAccess is called on that segment's pool and with that segment.  The call to 
-PoolAccess is wrapped with a ShieldEnter and ShieldLeave thereby giving the 
-pool the illusion that the fault was generated outside the MM.  This depends on 
-being able to determine the protection of a segment (using the pm field), on 
-being able to call ShieldEnter and ShieldLeave, and on being able to call 
-PoolAccess.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/protli/index.html b/mps/design/protli/index.html deleted file mode 100644 index d73849882c4..00000000000 --- a/mps/design/protli/index.html +++ /dev/null @@ -1,268 +0,0 @@ - - - - - - - - -Linux implementation of protection module - - - - - - - -
-               LINUX IMPLEMENTATION OF PROTECTION MODULE
-                           design.mps.protli
-                             incomplete doc
-                            tony 2000-02-03
-
-INTRODUCTION
-
-.readership: Any MPS developer
-
-.intro: This is the design of the Linux implementation of the protection 
-module.  It makes use of various services provided by Linux. It is intended to 
-work with LinuxThreads.
-
-
-REQUIREMENTS
-
-.req.general: Required to implement the general protection interface defined in 
-design.mps.prot.if.*.
-
-
-MISC
-
-.improve.sigvec: Note 1 of ProtSetup notes that we can't honour the sigvec(2) 
-entries of the next handler in the chain.  What if when we want to pass on the 
-signal instead of calling the handler we call sigvec with the old entry and use 
-kill to send the signal to ourselves and then restore our handler using sigvec 
-again. [need more detail and analysis here].
-
-
-DATASTRUCTURES
-
-.data.signext: This is static.  Because that is the only communications channel 
-available to signal handlers. [write a little more here]
-
-
-FUNCTIONS
-
-.fun.setup: ProtSetup installs a signal handler for the signal SIGSEGV to catch 
-and handle protection faults (this handler is the function sigHandle, see 
-.fun.sighandle). The previous handler is recorded (in the variable sigNext, see 
-.data.signext) so that it can be reached from sigHandle if it fails to handle 
-the fault. .fun.setup.problem: The problem with this approach is that we can't 
-honour the wishes of the sigvec(2) entry for the previous handler (in terms of 
-masks in particular).
-
-.fun.set: ProtSet uses mprotect to adjust the protection for pages. 
-void ProtSet(Addr base, Addr limit, AccessSet mode)
-
-.fun.set.convert: The requested protection (which is expressed in the mode 
-parameter, see design.mps.prot.if.set) is translated into an OS protection.  If 
-read accesses are to be forbidden then all accesses are forbidden, this is done 
-by setting the protection of the page to PROT_NONE.  If write accesses are to 
-be forbidden (and not read accesses) then write accesses are forbidden and read 
-accesses are allowed, this is done by setting the protection of the page to 
-PROT_READ|PROT_EXEC.  Otherwise (all access are okay), the protection is set to 
-PROT_READ|PROT_WRITE|PROT_EXEC.
-
-.fun.set.assume.mprotect: We assume that the call to mprotect always succeeds.  
-.fun.set.assume.mprotect: This is because we should always call the function 
-with valid arguments (aligned, references to mapped pages, and with an access 
-that is compatible with the access of the underlying object).
-
-.fun.sync: ProtSync does nothing in this implementation as ProtSet sets the 
-protection without any delay.
-void ProtSync(Space space);
-
-.fun.tramp: The protection trampoline is trivial under Linux, as there is 
-nothing that needs to be done in the dynamic context of the mutator in  order 
-to catch faults.  (Contrast this with Win32 Structured Exception Handling.)
-void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), void *p, size_t 
-s);
-
-
-THREADS
-
-.threads: The design must operate in a multi-threaded environment (with 
-LinuxThreads) and cooperate with the Linux support for locks (see 
-design.mps.lock) and the thread suspension mechanism (see design.mps.pthreadext
-).
-
-.threads.suspend: The SIGSEGV signal handler does not mask out any signals, so 
-a thread may be suspended while the handler is active, as required by the 
-design (see design.mps.pthreadext.req.suspend.protection). The signal handlers 
-simply nest at top of stack. 
-
-.threads.async: POSIX (and hence Linux) imposes some restrictions on signal 
-handler functions (see design.mps.pthreadext.anal.signal.safety). Basically the 
-rules say the behaviour of almost all POSIX functions inside a signal handler 
-is undefined, except for a handful of functions which are known to be 
-"async-signal safe". However, if it's known that the signal didn't happen 
-inside a POSIX function, then it is safe to call arbitrary POSIX functions 
-inside a handler.
-
-.threads.async.protection: If the signal handler is invoked because of an MPS 
-access, then we know the access must have been caused by client code (because 
-the client is not allowed to permit access to protectable memory to arbitrary 
-foreign code [need a reference for this]). In these circumstances, it's OK to 
-call arbitrary POSIX functions inside the handler.
-
-.threads.async.other: If the signal handler is invoked for some other reason 
-(i.e. one we are not prepared to handle) then there is less we can say about 
-what might have caused the SEGV. In general it is not safe to call arbitrary 
-POSIX functions inside the handler in this case.
-
-.threads.async.choice: The signal handler calls ArenaAccess to determine 
-whether the SEGV was the result of an MPS access. ArenaAccess will claim 
-various MPS locks (i.e. the arena ring lock and some arena locks). The code 
-calls no other POSIX functions in the case where the SEGV is not an MPS access. 
-The locks are implemented as mutexes and are claimed by calling 
-pthread_mutex_lock, which is not defined to be async-signal safe. 
-.threads.async.choice.ok: However, despite the fact that PThreads documentation 
-doesn't define the behaviour of pthread_mutex_lock in these circumstances, we 
-expect the LinuxThreads implementation will be well-behaved unless the SEGV 
-occurs while while in the process of locking or unlocking one of the MPS locks 
-(see .threads.async.linux-mutex). But we can assume that a SEGV will not happen 
-then (because we use the locks correctly, and generally must assume that they 
-work). Hence we conclude that it is OK to call ArenaAccess directly from the 
-signal handler.
-
-.threads.async.linux-mutex: A study of the LinuxThreads source code reveals 
-that mutex lock and unlock functions are implemented as a spinlock (using a 
-locked compare-and-exchange instruction) with a backup suspension mechanism 
-using sigsuspend. On locking, the spinlock code performs a loop which examines 
-the state of the lock, and then atomically tests that the state is unchanged 
-while attempting to modify it. This part of the code is reentrant (and hence 
-async-signal safe). Eventually, when locking, the spinlock code may need to 
-block, in which case it calls sigsuspend waiting for the manager thread to 
-unblock it. The unlocking code is similar, except that this code may need to 
-release another thread, in which case it calls kill. sigsuspend and kill are 
-both defined to be async-signal safe by POSIX. In summary, the mutex locking 
-functions use primitives which are entirely async-signal safe. They perform 
-side-effects which modify the fields of the lock structure only. This code may 
-be safely invoked inside a signal handler unless the interrupted function is in 
-the process of manipulating the fields of that lock structure.
-
-.threads.async.improve: In future it would be preferable to not have to assume 
-reentrant mutex locking and unlocking functions. By making the assumption we 
-also assume that the implementation of mutexes in LinuxThreads will not be 
-completely re-designed in future (which is not wise for the long term). An 
-alternative approach would be necessary anyway when supporting another platform 
-which doesn't offer reentrant locks (if such a platform does exist). 
-.threads.async.improve.how: We could avoid the assumption if we had a means of 
-testing whether an address lies within an arena chunk without the need to claim 
-any locks. Such a test might actually be possible. For example, arenas could 
-update a global datastructure describing the ranges of all chunks, using atomic 
-updates rather than locks; the handler code would be allowed to read this 
-without locking. However, this is somewhat tricky; a particular consideration 
-is that it's not clear when it's safe to deallocate stale portions of the 
-datastructure. 
-
-.threads.sig-stack: We do not handle signals on a separate signal stack. 
-Separate signal stacks apparently don't work properly with Pthreads.
-
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/protocol/index.html b/mps/design/protocol/index.html deleted file mode 100644 index f3b76e664b7..00000000000 --- a/mps/design/protocol/index.html +++ /dev/null @@ -1,554 +0,0 @@ - - - - - - - - -The design for protocol inheritance in MPS - - - - - - - -
-               THE DESIGN FOR PROTOCOL INHERITANCE IN MPS
-                          design.mps.protocol
-                             incomplete doc
-                            tony 1998-10-12
-
-INTRODUCTION
-
-.intro: This document explains the design of the support for class inheritance 
-in MPS.  It is not yet complete.  It describes support for single inheritance 
-of classes.  Future extensions will describe multiple inheritance and the 
-relationship between instances and classes.
-
-.readership: This document is intended for any MM developer.
-
-.hist.0: Written by Tony 1998-10-12
-
-
-PURPOSE
-
-.purpose.code-maintain: The purpose of the protocol inheritance design is to 
-ensure that the MPS code base can make use of the benefits of OO class 
-inheritance to maximize code reuse, minimize code maintenance and minimize the 
-use of "boiler plate" code. 
-
-.purpose.related: For related discussion, see mail.tony.1998-08-28.16-26(0), 
-mail.tony.1998-09-01.11-38(0), mail.tony.1998-10-06.11-03(0) & other messages 
-in the same threads.
-
-
-REQUIREMENTS
-
-.req.implicit: The object system should provide a means for classes to inherit 
-the methods of their direct superclasses implicitly for all functions in the 
-protocol without having to write any explicit code for each inherited function. 
-
-.req.override: There must additionally be a way for classes to override the 
-methods of their superclasses. 
-
-.req.next-method: As a result of .req.implicit, classes cannot make static 
-assumptions about methods used by direct superclasses.  The object system must 
-provide a means for classes to extend (not just replace) the behaviour of 
-protocol functions, such as a mechanism for invoking the "next-method".
-
-.req.ideal.extend: The object system must provide a standard way for classes to 
-implement the protocol supported by they superclass and additionally add new 
-methods of their own which can be specialized by subclasses.
-
-.req.ideal.multiple-inheritance: The object system should support multiple 
-inheritance such that sub-protocols can be "mixed in" with several classes 
-which do not themselves support identical protocols.
-
-
-OVERVIEW
-
-.overview.root: We start with the root of all conformant class hierarchies, 
-which is called "ProtocolClass".  ProtocolClass is an "abstract" class (i.e. it 
-has no direct instances, but it is intended to have subclasses).  To use Dylan 
-terminology, instances of its subclasses are "general" instances of 
-ProtocolClass.  They look as follows:-
-
-     Instance Object                    Class Object
-
-     --------------------              --------------------
-     |     sig          |    |-------->|    sig           |
-     --------------------    |         --------------------
-     |     class        |----|         |    superclass    |
-     --------------------              --------------------
-     |     ...          |              |    coerceInst    |
-     --------------------              --------------------
-     |     ...          |              |    coerceClass   |
-     --------------------              --------------------
-     |                  |              |     ...          |
-
-.overview.inherit: Classes inherit the protocols supported by their 
-superclasses.  By default they have the same methods as the class(es) from 
-which they inherit.  .overview.inherit.specialize: Classes may specialize the 
-behaviour of their superclass.  They do this by by overriding methods or other 
-fields in the class object. 
-
-.overview.extend: Classes may extend the protocols supported by their 
-superclasses by adding new fields for methods or other data.
-
-.overview.sig.inherit: Classes will contain (possibly several) signatures.  
-Classes must not specialize (i.e. override) the signature(s) they inherit from 
-their superclass(es).
-
-.overview.sig.extend: If a class definition extends a protocol, it is normal 
-policy for the class definition to include a new signature as the last field in 
-the class object.
-
-.overview.coerce-class: Each class contains a coerceClass field.  This contains 
-a method which can find the part of the class object which implements the 
-protocols of a supplied superclass argument (if, indeed, the argument IS a 
-superclass).  This function may be used for testing subclass/superclass 
-relationships, and it also provides support for multiple inheritance.
-
-.overview.coerce-inst: Each class contains a coerceInst field.  This contains a 
-method which can find the part of an instance object which contains the 
-instance slots of a supplied superclass argument (if, indeed, the argument IS a 
-superclass). This function may be used for testing whether an object is an 
-instance of a given class, and it also provides support for multiple 
-inheritance.
-
-.overview.superclass: Each class contains a superclass field.  This enables 
-classes to call "next-method", as well as enabling the coercion functions.
-
-.overview.next-method: A specialized method in a class can make use of an 
-overridden method from a superclass by accessing the method from the 
-appropriate field in the superclass object and calling it.  The superclass may 
-be accessed indirectly from the class's "Ensure" function when it is statically 
-known (see .overview.access).  This permits "next-method" calls, and is fully 
-scalable in that it allows arbitrary length method chains.  The SUPERCLASS 
-macro helps with this (see .int.static-superclass). 
-
-.overview.next-method.naive: In some cases it is necessary to write a method 
-which is designed to specialize an inherited method, needs to call the 
-next-method, and yet the implementation doesn't have static knowledge of the 
-superclass.  This might happen because the specialized method is designed to be 
-reusable by many class definitions.  The specialized method can usually locate 
-the class object from one of the parameters passed to the method.  It can then 
-access the superclass through the "superclass" field of the class, and hence 
-call the next method.  This technique has some limitations and doesn't support 
-longer method chains.  It is also dependent on none of the class definitions 
-which use the method having any subclasses.
-
-.overview.access: Classes must be initialized by calls to functions, since it 
-is these function calls which copy properties from superclasses.  Each class 
-must provide an "Ensure" function, which returns the canonical copy of the 
-class.  The canonical copy may reside in static storage, but no MPS code may 
-refer to that static storage by name.
-
-.overview.naming: There are some strict naming conventions which must be 
-followed when defining and using classes.  The use is obligatory because it is 
-assumed by the macros which support the definition and inheritance mechanism.  
-For every class SomeClass, we insist upon the following naming conventions:-
-
-  SomeClassStruct  - names the type of the structure for the protocol class.  
-                     This might be a typedef which aliases the type to the 
-                     type of the superclass, but if the class has extended 
-                     the protocols of the superclass the it will be a type which
-                     contains the new class fields.
-
-  SomeClass        - names the type *SomeClassStruct.
-                     This might be a typedef which aliases the type to the 
-                     type of the superclass, but if the class has extended 
-                     the protocols of the superclass then it will be a type 
-which
-                     contains the new class fields.
-
-  EnsureSomeClass  - names the function that returns the initialized 
-                     class object.
-
-
-
-INTERFACE
-
-Class Definition
-
-.int.define-class: Class definition is performed by the macro 
-DEFINE_CLASS(className, var).  A call to the macro must be followed by a body 
-of initialization code in braces {}.  The parameter className is used to name 
-the class being defined.  The parameter var is used to name a local variable of 
-type className, which is defined by the macro; it refers to the canonical 
-storage for the class being defined.  This variable may be used in the 
-initialization code.  (The macro doesn't just pick a name implicitly because of 
-the danger of a name clash with other names used by the programmer).  A call to 
-DEFINE_CLASS(SomeClass, var) does the following:
-Defines the EnsureSomeClass function.
-Defines some static storage for the canonical class object
-Defines some other things to ensure the class gets initialized exactly once
-
-.int.define-alias-class: A convenience macro DEFINE_ALIAS_CLASS is provided 
-which both performs the class definition and defines the types SomeClass and 
-SomeClass struct as aliases for some other class types.  This is particularly 
-useful for classes which simply inherit, and don't extend protocols.  The macro 
-call DEFINE_ALIAS_CLASS(className, superName, var) is exactly equivalent to the 
-following:
-  typedef superName className;
-  typedef superNameStruct classNameStruct;
-  DEFINE_CLASS(className, var)
-
-.int.define-special: If classes are particularly likely to be subclassed 
-without extension, the class implementor may choose to provide a convenience 
-macro which expands into DEFINE_ALIAS_CLASS with an appropriate name for the 
-superclass.  For example, there might be a macro for defining pool classes such 
-that the macro call DEFINE_POOL_CLASS(className, var) is exactly equivalent to 
-the macro call DEFINE_ALIAS_CLASS(className, PoolClass, var).  It may also be 
-convenient to define a static superclass accessor macro at the same time (see 
-.int.static-superclass.special).
-
-
-Single Inheritance
-
-.int.inheritance: Class inheritance details must be provided in the class 
-initialization code (see .int.define-class).  Inheritance is performed by the 
-macro INHERIT_CLASS(thisClassCoerced, parentClassName).  A call to this macro 
-will make the class being defined a direct subclass of ParentClassName by 
-ensuring that all the fields of the parent class are copied into thisClass, and 
-setting the superclass field of thisClass to be the parent class object.  The 
-parameter thisClassCoerced must be of type parentClassName.  If the class 
-definition defines an alias class (see .int.define-alias-class), then the 
-variable named as the second parameter to DEFINE_CLASS will be appropriate to 
-pass to INHERIT_CLASS.
-
-
-Specialization
-
-.int.specialize: Class specialization details must be given explicitly in the 
-class initialization code (see .int.define-class).  This must happen AFTER the 
-inheritance details are given (see .int.inheritance).
-
-
-Extension
-
-.int.extend: To extend the protocol when defining a new class, a new type must 
-be defined for the class structure.  This must embed the structure for the 
-primarily inherited class as the first field of the structure.  Class extension 
-details must be given explicitly in the class initialization code (see 
-.int.define-class).  This must happen AFTER the inheritance details are given 
-(see .int.inheritance).
-
-
-Introspection
-
-.introspect.c-lang: The design includes a number of introspection functions for 
-dynamically examining class relationships.  These functions are polymorphic and 
-accept arbitrary subclasses of ProtocolClass.  C doesn't support such 
-polymorphism.  So although these have the semantics of functions (and could be 
-implemented as functions in another language with compatible calling 
-conventions) they are actually implemented as macros.  The macros are named as 
-method-style macros despite the fact that this arguably contravenes 
-guide.impl.c.macro.method.  The justification for this is that this design is 
-intended to promote the use of polymorphism, and it breaks the abstraction for 
-the users to need to be aware of what can and can't be expressed directly in C 
-function syntax.  These functions all end in "Poly" to identify them as 
-polymorphic functions.
-
-.int.superclass: ProtocolClassSuperclassPoly(class) is an introspection 
-function which returns the direct superclass of class object class.
-
-.int.static-superclass: SUPERCLASS(className) is an introspection macro which 
-returns the direct superclass given a class name, which must (obviously) be 
-statically known.  The macro expands into a call to the ensure function for the 
-class name, so this must be in scope (which may require a forward 
-declaration).  The macro is useful for next-method calls (see 
-.overview.next-method).  The superclass is returned with type ProtocolClass so 
-it may be necessary to cast it to the type for the appropriate subclass. 
-
-.int.static-superclass.special: Implementors of classes which are designed to 
-be subclassed without extension may choose to provide a convenience macro which 
-expands into SUPERCLASS along with a type cast.  For example, there might be a 
-macro for finding pool superclasses such that the macro call 
-POOL_SUPERCLASS(className) is exactly equivalent to 
-(PoolClass)SUPERCLASS(className).  It's convenient to define these macros 
-alongside the convenience class definition macro (see .int.define-special).
-
-.int.class: ClassOfPoly(inst) is an introspection function which returns the 
-class of which inst is a direct instance.
-
-.int.subclass: IsSubclassPoly(sub, super) is an introspection function which 
-returns a boolean indicating whether sub is a subclass of super.  I.e., it is a 
-predicate for testing subclass relationships.
-
-
-Multiple inheritance
-
-.int.mult-inherit: Multiple inheritance involves an extension of the protocol 
-(see .int.extend) and also multiple uses of the single inheritance mechanism 
-(see .ini.inheritance).  It also requires specialized methods for coerceClass 
-and coerceInst to be written (see .overview.coerce-class & 
-.overview.coerce-inst).  Documentation on support for multiple inheritance is 
-under construction.  This facility is not currently used.  The basic idea is 
-described in mail.tony.1998-10-06.11-03(0).
-
-
-Protocol guidelines
-
-.guide.fail: When designing an extensible function which might fail, the design 
-must permit the correct implementation of the failure-case code.  Typically, a 
-failure might occur in any method in the chain.  Each method is responsible for 
-correctly propagating failure information supplied by superclass methods and 
-for managing it's own failures. 
-
-.guide.fail.before-next: Dealing with a failure which is detected before any 
-next-method call is made is similar to a fail case in any non-extensible 
-function.  See .example.fail below. 
-
-.guide.fail.during-next: Dealing with a failure returned from a next-method 
-call is also similar to a fail case in any non-extensible function.  See 
-.example.fail below. 
-
-.guide.fail.after-next: Dealing with a failure which is detected after the next 
-methods have been successfully invoked is more complex.  If this scenario is 
-possible, the design must include an "anti-function", and each class must 
-ensure that it provides a method for the anti-method which will clean up any 
-resources which are claimed after a successful invocation of the main method 
-for that class.  Typically the anti-function would exist anyway for clients of 
-the protocol (e.g. "finish" is an anti-function for "init").  The effect of the 
-next-method call can then be cleaned up by calling the anti-method for the 
-superclass.  See .example.fail below. 
-
-
-Example
-
-.example.inheritance: The following example class definition shows both 
-inheritance and specialization.  It shows the definition of the class 
-EPDRPoolClass, which inherits from EPDLPoolClass and has specialized values of 
-the name, init & alloc fields.  The type EPDLPoolClass is an alias (typedef) 
-for PoolClass.
-
-typedef EPDLPoolClass EPDRPoolClass;
-typedef EPDLPoolClassStruct EPDRPoolClassStruct;
-
-DEFINE_CLASS(EPDRPoolClass, this)
-{
-  INHERIT_CLASS(this, EPDLPoolClass);
-  this->name = "EPDR";
-  this->init = EPDRInit;
-  this->alloc = EPDRAlloc;
-}
-
-
-.example.extension: The following (hypothetical) example class definition shows 
-inheritance, specialization and also extension.  It shows the definition of the 
-class EPDLDebugPoolClass, which inherits from EPDLPoolClass, but also 
-implements a method for checking properties of the pool.
-
-typedef struct EPDLDebugPoolClassStruct {
-  EPDLPoolClassStruct epdl;
-  DebugPoolCheckMethod check;
-  Sig sig;
-} EPDLDebugPoolClassStruct;
-
-typedef EPDLDebugPoolClassStruct *EPDLDebugPoolClass;
-
-DEFINE_CLASS(EPDLDebugPoolClass, this)
-{
-  EPDLPoolClass epdl = &this->epdl;
-  INHERIT_CLASS(epdl, EPDLPoolClass);
-  epdl->name = "EPDLDBG";
-  this->check = EPDLDebugCheck;
-  this->sig = EPDLDebugSig;
-}
-
-.example.fail: The following example shows the implementation of failure-case 
-code for an "init" method, making use of the "finish" anti-method:-
-
-static Res mySegInit(Seg seg, Pool pool, Addr base, Size size, 
-                     Bool reservoirPermit, va_list args)
-{
-  SegClass super;
-  MYSeg myseg;
-  OBJ1 obj1;
-  Res res;
-  Arena arena;
-
-  AVERT(Seg, seg);
-  myseg = SegMYSeg(seg);
-  AVERT(Pool, pool);
-  arena = PoolArena(pool);
-
-  /* Ensure the pool is ready for the segment */
-  res = myNoteSeg(pool, seg);
-  if(res != ResOK)
-    goto failNoteSeg;
-
-  /* Initialize the superclass fields first via next-method call */
-  super = (SegClass)SUPERCLASS(MYSegClass);
-  res = super->init(seg, pool, base, size, reservoirPermit, args);
-  if(res != ResOK)
-    goto failNextMethods;
-
-  /* Create an object after the next-method call */
-  res = ControlAlloc(&obj1, arena, sizeof(OBJ1Struct), reservoirPermit);
-  if(res != ResOK)
-    goto failObj1;
-
-  myseg->obj1 = obj1
-  return ResOK;
-
-failObj1:
-  /* call the anti-method for the superclass */
-  super->finish(seg);
-failNextMethods:
-  /* reverse the effect of myNoteSeg */
-  myUnnoteSeg(pool, seg);
-failNoteSeg:
-  return res;
-}
-
-
-IMPLEMENTATION
-
-.impl.derived-names: The DEFINE_CLASS macro derives some additional names from 
-the class name as part of it's implementation.  These should not appear in the 
-source code - but it may be useful to know about this for debugging purposes.  
-For each class definition for class SomeClass, the macro defines the following:
-
-extern SomeClass EnsureSomeClass(void);  /* The class accessor function. 
-See.overview.naming */
-static Bool protocolSomeClassGuardian;  /* A boolean which indicates whether 
-the class has been initialzed yet */
-static void protocolEnsureSomeClass(SomeClass); /* A function called by 
-EnsureSomeClass. All the class initialization code is actually in this function 
-*/
-static SomeClassStruct protocolSomeClassStruct; /* Static storage for the 
-canonical class object */
-  
-
-.impl.init-once: Class objects only behave according to their definition after 
-they have been initialized, and class protocols may not be used before 
-initialization has happened.  The only code which is allowed to see a class 
-object in a partially initialized state is the initialization code itself -- 
-and this must take care not to pass the object to any other code which might 
-assume it is initialized. Once a class has been initialized, the class might 
-have a client.  The class must not be initialized again when this has happened, 
-because the state is not necessarily consistent in the middle of an 
-initialization function.  The initialization state for each class is stored in 
-a boolean "guardian" variable whose name is derived from the class name (see 
-.impl.derived-names).  This ensures the initialization happens only once.  The 
-path through the EnsureSomeClass function should be very fast for the common 
-case when this variable is TRUE, and the class has already been initialized, as 
-the canonical static storage can simply be returned in that case.  However, 
-when the value of the guardian is FALSE, the class is not initialized.  In this 
-case, a call to EnsureSomeClass must first execute the initialization code and 
-then set the guardian to TRUE.  However, this must happen atomically (see 
-.impl.init-lock).
-
-.impl.init-lock: There would be the possibility of a race condition if 
-EnsureSomeClass were called concurrently on separate threads before SomeClass 
-has been initialized.  The class must not be initialized more than once, so the 
-sequence test-guard, init-class, set-guard must be run as a critical region.  
-It's not sufficient to use the arena lock to protect the critical region, 
-because the class object might be shared between multiple arenas.  The 
-DEFINE_CLASS macro uses a global recursive lock instead.  The lock is only 
-claimed after an initial unlocked access of the guard variable shows that the 
-class in not initialized.  This avoids any locking overhead for the common case 
-where the class is already initialized.  This lock is provided by the lock 
-module -- see design.mps.lock(0).
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/protsu/index.html b/mps/design/protsu/index.html deleted file mode 100644 index 3260f55e903..00000000000 --- a/mps/design/protsu/index.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - - -SunOS 4 implementation of protection module - - - - - - - -
-              SUNOS 4 IMPLEMENTATION OF PROTECTION MODULE
-                           design.mps.protsu
-                             incomplete doc
-                             drj 1997-03-20
-
-INTRODUCTION
-
-.readership: Any MPS developer
-
-.intro: This is the design of the SunOS 4 implementation of the protection 
-module.  It is intended to be used only in SunOS 4 (os.su).  It makes use of 
-various services provided by SunOS 4.
-
-[largely unwritten]
-
-REQUIREMENTS
-
-.req.general: Required to implement the general protection interface defined in 
-design.mps.prot.if.*.
-
-
-OVERVIEW
-
-[uses mprotect]
-
-MISC
-
-.improve.sig-stack: Currently we do not handle signals on a separate signal 
-stack.  If we handled signals on our own stack then we could guarantee not to 
-run out of stack while we were handling the signal.  This would be useful (it 
-may even be required).  We would have to use sigvec(2) rather than signal(3) 
-(set the SV_ONSTACK flag and use sigstack(2)).  This has drawbacks as the 
-signal stack is not grown automatically, so we would have to to frig the stacks 
-back if we wanted to pass on the signal to some other handler as that handler 
-may require arbitrary amounts of stack.
-
-.improve.sigvec: Note 1 of ProtSetup notes that we can't honour the sigvec(2) 
-entries of the next handler in the chain.  What if when we want to pass on the 
-signal instead of calling the handler we call sigvec with the old entry and use 
-kill to send the signal to ourselves and then restore our handler using sigvec 
-again.  ramble ramble. [need more detail and analysis here].
-
-assume mprotect never fails and why.  [We also need a policy here]
-
-DATASTRUCTURES
-
-.data.signext: This is static.  Because that is the only communications channel 
-available to signal handlers. [write a little more here]
-
-
-FUNCTIONS
-
-.fun.setup:
-
-ProtSetup
-
-The setup involves installing a signal handler for the signal SIGSEGV to catch 
-and handle protection faults (this handler is the function sigHandle, see 
-.fun.sighandle). The previous handler is recorded (in the variable sigNext, see 
-.data.signext) so that it can be reached from sigHandle if it fails to handle 
-the fault.
-
-The problem with this approach is that we can't honor the wishes of the 
-sigvec(2) entry for the previous handler (in terms of masks in particular).
-
-Obviously it would be okay to always chain the previous signal handler onto 
-sigNext, however in the case where the previous handler is the one we've just 
-installed (ie, sigHandle) then it is not necessary to chain the handler, so we 
-don't.
-
-.fun.set:
-
-void ProtSet(Addr base, Addr limit, AccessSet mode)
-
-.fun.set.convert: The requested protection (which is expressed in the mode 
-parameter, see design.mps.prot.if.set) is translated into an OS protection.  If 
-read accesses are to be forbidden then all accesses are forbidden, this is done 
-by setting the protection of the page to PROT_NONE.  If write access are to be 
-forbidden (and not read accesses) then write accesses are forbidden and read 
-accesses are allowed, this is done by setting the protection of the page to 
-PROT_READ|PROT_EXEC.  Otherwise (all access are okay), the protection is set to 
-PROT_READ|PROT_WRITE|PROT_EXEC.
-
-.fun.set.assume.mprotect: We assume that the call to mprotect always succeeds.  
-.fun.set.assume.mprotect: This is because we should always call the function 
-with valid arguments (aligned, references to mapped pages, and with an access 
-that is compatible with the access of the underlying object).
-
-.fun.sync:
-
-void ProtSync(Space space);
-
-This does nothing in this implementation as ProtSet sets the protection without 
-any delay.
-
-.fun.tramp:
-
-void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), void *p, size_t 
-s);
-
-The protection trampoline is trivial under SunOS, as there is nothing that 
-needs to be done in the dynamic context of the mutator in  order to catch 
-faults.  (Contrast this with Win32 Structured Exception Handling.)
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/pthreadext/index.html b/mps/design/pthreadext/index.html deleted file mode 100644 index f7c6e18c152..00000000000 --- a/mps/design/pthreadext/index.html +++ /dev/null @@ -1,387 +0,0 @@ - - - - - - - - -Design of the Posix thread extensions for MPS - - - - - - - -
-             DESIGN OF THE POSIX THREAD EXTENSIONS FOR MPS
-                         design.mps.pthreadext
-                               draft doc
-                            tony 2000-02-01
-
-INTRODUCTION
-
-.readership: Any MPS developer.
-
-.intro: This is the design of the Pthreads extension module, which provides 
-some low-level threads support for use by MPS (notably suspend and resume).
-
-
-DEFINITIONS
-
-.pthreads: The term "Pthreads" means an implementation of the POSIX 
-1003.1c-1995 thread standard. (Or the Single UNIX Specification, Version 2, aka 
-USV2 or UNIX98.)
-
-.context: The "context" of a thread is a (platform-specific) OS-defined 
-structure which describes the current state of the registers for that thread.
-
-
-REQUIREMENTS
-
-.req.suspend: A means to suspend threads, so that they don't make any progress. 
-.req.suspend.why: Needed by the thread manager so that other threads registered 
-with an arena can be suspended (see design.mps.thread-manager).  Not directly 
-provided by Pthreads.
-
-.req.resume: A means to resume suspended threads, so that they are able to make 
-progress again.  .req.resume.why: Needed by the thread manager.  Not directly 
-provided by Pthreads.
-
-.req.suspend.multiple: Allow a thread to be suspended on behalf of one arena 
-when it has already been suspended on behalf of one or more other arenas. 
-.req.suspend.multiple.why: The thread manager contains no design for 
-cooperation between arenas to prevent this.
-
-.req.resume.multiple: Allow requests to resume a thread on behalf of each arena 
-which had previously suspended the thread.  The thread must only be resumed 
-when requests from all such arenas have been received.  
-.req.resume.multiple.why: A thread manager for an arena must not permit a 
-thread to make progress before it explicitly resumes the thread.
-
-.req.suspend.context: Must be able to access the context for a thread when it 
-is suspended.
-
-.req.suspend.protection: Must be able to suspend a thread which is currently 
-handling a protection fault (i.e., an arena access).  Such a thread might even 
-own an arena lock.
-
-.req.legal: Required to use Pthreads / POSIX APIs in a legal manner.
-
-
-
-ANALYSIS
-
-
-.anal.suspend: Thread suspension is inherently asynchronous.  MPS needs to be 
-able to suspend another thread without prior knowledge of the code that thread 
-is running.  (I.e., we can't rely on cooperation between threads.)  The only 
-asynchronous communication available on POSIX is via signals - so the suspend 
-and resume mechanism must ultimately be built from signals.
-
-.anal.signal.safety: POSIX imposes some restrictions on what a signal handler 
-function might do when invoked asynchronously (see 
-<URL:http://www.opengroup.org/onlinepubs/007908799/xsh/sigaction.html>, and 
-search for the string "reentrant").  In summary, a small number of POSIX 
-functions are defined to be "async-signal safe", which means they may be 
-invoked without restriction in signal handlers.  All other POSIX functions are 
-considered to be unsafe.  Behaviour is undefined if an unsafe function is 
-interrupted by a signal and the signal handler then proceeds to call another 
-unsafe function.  See mail.tony.1999-08-24.15-40(0)and followups for some 
-further analysis.
-
-.anal.signal.safety.implication: Since we can't assume that we won't attempt to 
-suspend a thread while it is running an unsafe function, we must limit the use 
-of POSIX functions in the suspend signal handler to those which are designed to 
-be "async-signal safe".  One of the few such functions related to 
-synchronization is sem_post.
-
-.anal.signal.example: An example of how to suspend threads in POSIX was posted 
-to newsgroup comp.programming.threads in August 1999.  The code that was posted 
-was written by David Butenhof, and may be found here:
-
-Some further discussion about the code in the newsgroup is recorded here:
-
-
-.anal.signal.linux-hack: In the current implementation of Linux Pthreads, it 
-would be possible to implement suspend/resume using SIGSTOP and SIGCONT.  This 
-is, however, nonportable and will probably stop working on Linux at some point.
-
-.anal.component: There is no known way to meet the requirements above in a way 
-which cooperates with another component in the system which also provides its 
-own mechanism to suspend and resume threads.  The best bet for achieving this 
-is to provide the functionality in shared low-level component which may be used 
-by MPS and other clients.  This will require some discussion with other 
-potential clients and/or standards bodies.  .anal.component:  NB., such 
-cooperation is actually a requirement for Dylan (req.dylan.dc.env.self), though 
-this is not a problem, since all the Dylan components share the MPS mechanism.
-
-
-
-INTERFACE
-
-.if.pthreadext.abstract: A thread is represented by the abstract type 
-PThreadext. A PThreadext object corresponds directly with a PThread (of type 
-pthread_t). There may be more than one PThreadext object for the same PThread.
-
-.if.pthreadext.structure: The structure definition of PThreadext 
-(PThreadextStruct) is exposed by the interface so that it may be embedded in a 
-client datastructure (e.g. ThreadStruct). This means that all storage 
-management can be left to the client (which is important because there might be 
-multiple arenas involved). Clients may not access the fields of a 
-PThreadextStruct directly.
-
-.if.init: Initializes a PThreadext object for a thread with the given id:
-void PThreadextInit(PThreadext pthreadext, pthread_t id)
-
-.if.check: Checks a PThreadext object for consistency:
-Bool PThreadextCheck(PThreadext pthreadext)
-Note that this function takes the mutex, so it must not be called with the 
-mutex held (doing so will probably deadlock the thread).
-
-.if.suspend: Suspends a PThreadext object (puts it into a suspended state). 
-Meets .req.suspend.*. The object must not already be in a suspended state. If 
-the function returns ResOK, the context of the thread is returned in 
-contextReturn, and the corresponding PThread will not make any progress until 
-it is resumed:
-Res PThreadextSuspend(PThreadext pthreadext, struct sigcontext **contextReturn)
-
-.if.resume: Resumes a PThreadext object. Meets .req.resume.*. The object must 
-already be in a suspended state. Puts the object into a non-suspended state. 
-Permits the corresponding PThread to make progress again, (although that might 
-not happen immediately if there is another suspended PThreadext object 
-corresponding to the same thread):
-Res PThreadextResume(PThreadext pthreadext)
-
-.if.finish: Finishes a PThreadext object:
-void PThreadextFinish(PThreadext pthreadext)
-
-
-IMPLEMENTATION
-
-
-.impl.pthreadext: The structure definition for a PThreadext object is:
-typedef struct PThreadextStruct {
-  Sig sig;                         /* design.mps.sig */
-  pthread_t id;                    /* Thread ID */
-  struct sigcontext *suspendedScp; /* sigcontext if suspended */
-  RingStruct threadRing;           /* ring of suspended threads */
-  RingStruct idRing;               /* duplicate suspensions for id */
-} PThreadextStruct;
-
-.impl.field.id: The id field shows which PThread the object corresponds to.
-
-.impl.field.scp: The suspendedScp field contains the context when in a 
-suspended state. Otherwise it is NULL.
-
-.impl.field.threadring: The threadRing field is used to chain the object onto 
-the suspend ring when it is in the suspended state (see .impl.suspend-ring). 
-When not in a suspended state, this ring is single.
-
-.impl.field.idring: The idRing field is used to group the object with other 
-objects corresponding to the same PThread (same id field) when they are in the 
-suspended state. When not in a suspended state, or when this is the only 
-PThreadext object with this id in the suspended state, this ring is single.
-
-.impl.global.suspend-ring: The module maintains a global suspend-ring - a ring 
-of PThreadext objects which are in a suspended state.  This is primarily so 
-that it's possible to determine whether a thread is curently suspended anyway 
-because of another PThreadext object, when a suspend attempt is made.
-
-.impl.global.victim: The module maintains a global variable which is used to 
-indicate which PThreadext is the current victim during suspend operations. This 
-is used to communicate information between the controlling thread and the 
-thread being suspended (the victim). The variable has value NULL at other times.
-
-.impl.static.mutex: We use a lock (mutex) around the suspend and resume 
-operations. This protects the state data (suspend-ring etc. see impl.global.*). 
-Since only one thread can be suspended at a time, there's no possibility of two 
-arenas suspending each other by concurrently suspending each other's threads.
-
-.impl.static.semaphore: We use a semaphore to synchronize between the 
-controlling and victim threads during the suspend operation. See .impl.suspend 
-and .impl.suspend-handler).
-
-.impl.static.init: The static data and global variables of the module are 
-initialized on the first call to PThreadextSuspend, using pthread_once to avoid 
-concurrency problems. We also enable the signal handlers at the same time (see 
-.impl.suspend-handler and .impl.resume-handler).
-
-.impl.suspend: PThreadextSuspend first ensures the module is initialized (see 
-.impl.static.init). After this, it claims the mutex (see .impl.static.mutex). 
-It then checks to see whether thread of the target PThreadext object has 
-already been suspended on behalf of another PThreadext object. It does this by 
-iterating over the suspend ring. 
-
-.impl.suspend.already-suspended: If another object with the same id is found on 
-the suspend ring, then the thread is already suspended. The context of the 
-target object is updated from the other object, and the other object is linked 
-into the idRing of the target. 
-
-.impl.suspend.not-suspended: If the thread is not already suspended, then we 
-forcibly suspend it using a technique similar to Butenhof's (see 
-.anal.signal.example): First we set the victim variable (see 
-.impl.global.victim) to indicate the target object. Then we send the signal 
-PTHREADEXT_SIGSUSPEND to the thread (see .impl.signals), and wait on the 
-semaphore for it to indicate that it has received the signal and updated the 
-victim variable with the context. If either of these operations fail (e.g. 
-because of thread termination) we unlock the mutex and return ResFAIL.
-
-.impl.suspend.update: Once we have ensured that the thread is definitely 
-suspended, we add the target PThreadext object to the suspend ring, unlock the 
-mutex, and return the context to the caller.
-
-.impl.suspend-handler: The suspend signal handler is invoked in the target 
-thread during a suspend operation, when a PTHREADEXT_SIGSUSPEND signal is sent 
-by the controlling thread (see .impl.suspend.not-suspended). The handler 
-determines the context (received as a parameter, although this may be 
-platform-specific) and stores this in the victim object (see 
-.impl.global.victim). The handler then masks out all signals except the one 
-that will be received on a resume operation (PTHREADEXT_SIGRESUME) and 
-synchronizes with the controlling thread by posting the semaphore. Finally the 
-handler suspends until the resume signal is received (using sigsuspend).
-
-.impl.resume: PThreadextResume first claims the mutex (see .impl.static.mutex). 
-It then checks to see whether thread of the target PThreadext object has also 
-been suspended on behalf of another PThreadext object (in which case the id 
-ring of the target object will not be single). 
-
-.impl.resume.also-suspended: If the thread is also suspended on behalf of 
-another PThreadext, then the target object is removed from the id ring. 
-
-.impl.resume.not-also: If the thread is not also suspended on behalf of another 
-PThreadext, then the thread is resumed using the technique proposed by Butenhof 
-(see .anal.signal.example). I.e. we send it the signal PTHREADEXT_SIGRESUME 
-(see .impl.signals) and expect it to wake up. If this operation fails (e.g. 
-because of thread termination) we unlock the mutex and return ResFAIL.
-
-.impl.resume.update: Once the target thread is in the appropriate state, we 
-remove the target PThreadext object from the suspend ring, set its context to 
-NULL and unlock the mutex.
-
-.impl.resume-handler: The resume signal handler is invoked in the target thread 
-during a resume operation, when a PTHREADEXT_SIGRESUME signal is sent by the 
-controlling thread (see .impl.resume.not-also). The resume signal handler 
-simply returns. This is sufficient to unblock the suspend handler, which will 
-have been blocking the thread at the time of the signal. The Pthreads 
-implementation ensures that the signal mask is restored to the value it had 
-before the signal handler was invoked.
-
-.impl.finish: PThreadextFinish supports the finishing of objects in the 
-suspended state, and removes them from the suspend ring and id ring as 
-necessary. It must claim the mutex for the removal operation (to ensure 
-atomicity of the operation). Finishing of suspended objects is supported so 
-that clients can dispose of resources if a resume operation fails (which 
-probably means that the PThread has terminated).
-
-.impl.signals: The choice of which signals to use for suspend and restore 
-operations may need to be platform-specific. Some signals are likely to be 
-generated and/or handled by other parts of the application and so should not be 
-used (e.g. SIGSEGV). Some implementations of PThreads use some signals for 
-themselves, so they may not be used; e.g. LinuxThreads uses SIGUSR1 and SIGUSR2 
-for its own purposes. The design abstractly names the signals 
-PTHREADEXT_SIGSUSPEND and PTHREAD_SIGRESUME, so that they may be easily mapped 
-to appropriate real signal values. Candidate choices are SIGXFSZ and SIGPWR.
-
-
-ATTACHMENTS
-   "posix.txt"
-   "susp.c"
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/reservoir/index.html b/mps/design/reservoir/index.html deleted file mode 100644 index 039fb17e082..00000000000 --- a/mps/design/reservoir/index.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - -The design of the low-memory reservoir - - - - - - - -
-                 THE DESIGN OF THE LOW-MEMORY RESERVOIR
-                          design.mps.reservoir
-                           incomplete design
-                            tony 1998-07-30
-
-
-INTRODUCTION:
-
-The low-memory reservoir provides client support for implementing handlers for 
-low-memory situations which allocate.  The reservoir is implemented inside the 
-arena as a pool of unallocatable segments.
-
-
-OVERVIEW:
-
-This is just a placeholder at the moment.
-
-
-ARCHITECTURE:
-
-.adt: The reservoir interface looks (almost) like an abstract data type of type 
-Reservoir.  It's not quite abstract because the arena embeds the structure of 
-the reservoir (of type ReservoirStruct) into its own structure, for simplicity 
-of initialization.
-
-.align: The reservoir is implemented as a pool of available tracts, along with 
-a size and limit which must always be aligned to the arena alignment.  The size 
-corresponds to the amount of memory currently maintained in the reservoir.  The 
-limit is the maximum amount that it is desired to maintain.
-
-.wastage: When the reservoir limit is set by the client, the actual limit 
-should be increased by an arena alignment amount for every active mutator 
-buffer.
-
-.really-empty: When the reservoir limit is set to 0, assume that the client 
-really doesn't have a need for a reservoir at all.  In this case, the client 
-won't even want an allowance to be made for wastage in active buffers.
-
-
-IMPLEMENTATION:
-
-.interface: The following functions comprise the interface to the reservoir 
-module:
-
-
-.interface.check: ReservoirCheck checks the reservoir for consistency:
-extern Bool ReservoirCheck(Reservoir reservoir);
-
-.interface.init: ReservoirInit initializes the reservoir and its associated 
-pool, setting the size and limit to 0:
-extern Res ReservoirInit(Reservoir reservoir, Arena arena);
-
-.interface.finish: ReservoirFinish de-initializes the reservoir and its 
-associated pool:
-extern void ReservoirFinish (Reservoir reservoir);
-
-.interface.limit: ReservoirLimit returns the limit of the reservoir:
-extern Size ReservoirLimit(Reservoir reservoir);
-
-.interface.set-limit: ReservoirSetLimit sets the limit of the reservoir, making 
-an allowance for wastage in mutator buffers:
-extern void ReservoirSetLimit(Reservoir reservoir, Size size);
-
-.interface.available: ReservoirAvailable returns the available size of the 
-reservoir:
-extern Size ReservoirAvailable(Reservoir reservoir);
-
-.interface.ensure-full: ReservoirEnsureFull attempts to fill the reservoir with 
-memory from the arena, until it is full:
-extern Res ReservoirEnsureFull(Reservoir reservoir);
-
-.interface.deposit: ReservoirDeposit attempts to fill the reservoir with memory 
-in the supplied range, until it is full.  This is called by the arena from 
-ArenaFree if the reservoir is not known to be full.  Any memory which is not 
-added to the reservoir (because the reservoir is full) is freed via the arena 
-class's free method.
-extern void ReservoirDeposit(Reservoir reservoir, Addr base, Size size);
-
-.interface.withdraw: ReservoirWithdraw attempts to allocate memory of the 
-specified size to the specified pool to the reservoir.  If no suitable memory 
-can be found it returns ResMEMORY. 
-extern Res ReservoirWithdraw(Addr *baseReturn, Tract *baseTractReturn,
-                             Reservoir reservoir, Size size, Pool pool);
-
-.interface.withdraw.align: Currently, ReservoirWithdraw can only withdraw 
-memory in chunks of the size of the arena alignment.  This is because the 
-reservoir doesn't attempt to coalesce adjacent memory blocks.  This deficiency 
-should be fixed in the future.
-
-.pool: The memory managed by the reservoir is owned by the reservoir pool.  
-This memory is never sub-allocated.  Each tract belonging to the pool is linked 
-onto a list.  The head of the list is in the Reservoir object.  Links are 
-stored in the TractP fields of each tract object.
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/ring/index.html b/mps/design/ring/index.html deleted file mode 100644 index c3e859937b0..00000000000 --- a/mps/design/ring/index.html +++ /dev/null @@ -1,267 +0,0 @@ - - - - - - - - -The design of the ring data structure - - - - - - - -
-                 THE DESIGN OF THE RING DATA STRUCTURE
-                            design.mps.ring
-                             incomplete doc
-                           richard 1996-09-26
-
-INTRODUCTION
-
-.source: rings are derived from the earlier use of Deques.  See 
-design.mps.deque.
-
-
-DESCRIPTION
-
-.def.ring: Rings are circular doubly-linked lists of ring "nodes".  The nodes 
-are fields of structures which are the "elements" of the ring.
-
-Ring node structures (RingStruct) are in-lined in the structures on the ring, 
-like this:
-
-  typedef struct FooStruct *Foo;     /* the element type */
-  typedef struct FooStruct {         /* the element structure */
-    int baz, bim;
-    RingStruct ring;                 /* the ring node */
-    float bip, bop;
-  } FooStruct;
-
-This arrangement means that they do not need to be managed separately.  This is 
-especially useful in avoiding re-entrancy and bootstrapping problems in the 
-memory manager.  Rings also provide flexible insertion and deletion because the 
-entire ring can be found from any node.
-
-In the MPS, rings are used to connect a "parent" structure (such as a Space) to 
-a number of "child" structures (such as Pools), as shown in .fig.ring (note the 
-slight abuse of naming convention (in that barRing is not called 
-barRingStruct)).
-
-.fig.ring: A ring of Bar objects owned by a Foo object.
-
-
-
-.fig.empty: An empty ring of Bar objects owned by a Foo object.
-
-
-.def.singleton: A "singleton" ring is a ring containing one node, whose 
-previous and next nodes are itself (see .fig.single).
-
-.fig.single: A singleton Bar object not on any ring.
-
-
-.fig.elt: How RING_ELT gets a parent pointer from a node pointer.
-
-
- - Ring Diagrams 
-
-INIT / FINISH
-
-.init: Rings are initialized with the RingInit function.  They are initialized 
-to be a singleton ring (.def.singleton).
-
-.finish: Rings are finished with the RingFinish function.  A ring must be a 
-singleton ring before it can be finished (it is an error to attempt to finish a 
-non-singleton ring).
-
-
-ITERATION
-
-.for: A macro is used for iterating over the elements in a ring.  This macro is 
-called RING_FOR.  RING_FOR takes three arguments, the first is an iteration 
-variable: "node", the second is the "parent" element in the ring: "ring", the 
-third is a variable used by the iterator for working state (it holds a pointer 
-to the next node): "next".  All arguments must be of type Ring.  The "node" and 
-"next" variables must be declared and in scope already.  All elements except 
-for the "parent" element are iterated over.  The macro expands to a for 
-statement.  During execution of the loop, the "node" variable (the first 
-argument to the macro) will be the value of successive elements in the Ring (at 
-the beginning of the statement in the body of the loop).  .for.error: It is an 
-error (possibly unchecked) for the "node" and "next" variables to be modified 
-except implicitly by using this iterator.  .for.safe: It is safe to delete the 
-current node during the iteration.
-
-.for.ex:
-
-An example:
-
-Ring node, nextNode;
-RING_FOR(node, &foo->barRing, nextNode) {
-  Bar bar = RING_ELT(Bar, FooRing, node);
-  frob(bar);
-}
-
-.for.ex.elt: Notice the idiomatic use of RING_ELT which is almost universal 
-when using RING_FOR.
-
-
-SUBCLASS
-
-.elt: RING_ELT is a macro that converts a pointer to a ring structure to a 
-pointer to the enclosing parent structure.
-RING_ELT has three arguments which are, in order:
-type, the type of a pointer to the enclosing structure,
-field, the name of the ring structure field within it,
-ring, the ring node.
-The result is a pointer to the enclosing structure.
-
-[ Why does RING_ELT not use PARENT or even offsetof?  Apparently it's so that 
-it can cope with arrays of rings.  GavinM 1997-04-15]
- 
-
-APPEND / REMOVE
-
-.append: RingAppend appends a singleton ring to a ring (such that the newly 
-added element will be last in the iteration sequence).
-
-.insert: RingInsert adds a singleton rung to a ring (such that the newly added 
-element will be first in the
-iteration sequence).
-
-.remove: RingRemove removes an element from a ring, the newly removed element 
-becomes a singleton ring.  It is an error for the element to already be a 
-singleton.
-
-.improve.join:  it would be possible to add a RingJoin operation.  This is not 
-done as it is not required.
-
-
-NAMING
-
-.naming: By convention, when one structure Foo contains one ring of Bar 
-structures, the field is Foo is usually known as barRing, and the field in Bar 
-is known as fooRing.  If the Foo structure contains more than one ring of Bar 
-structures, then they will have names such as spongRing and frobRing.
-
-
-DEQUES
-
-This section documents where rings differ significantly from deques.
-
-.head: Deques used a distinguished head structure for the head of the ring.  
-Rings still have a separate head structure, but it is not distinguished by type.
-
-
-DEFECTS
-
-This section documents known defects with the current design.
-
-.app_for.misuse: It is easy to pass RingAppend and RING_FOR the arguments in 
-the wrong order as all the arguments have the same type.  see .head.
-
-.check.improve: There is no method for performing a full integrity check.  This 
-could be added.
-
-ATTACHMENT
-   "Ring Diagrams"
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/root/index.html b/mps/design/root/index.html deleted file mode 100644 index 7e820b3f637..00000000000 --- a/mps/design/root/index.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - -The design of the root manager - - - - - - - -
-                     THE DESIGN OF THE ROOT MANAGER
-                            design.mps.root
-                           incomplete design
-                           richard 1995-08-25
-
-INTRODUCTION
-
-.intro:
-
-.readership:
-
-
-BASICS
-
-.root.def: The root node of the object graph is the node which defines whether 
-objects are accessible, and the place from which the mutator acts to change the 
-graph.  In the MPS, a root is an object which describes part of the root node.  
-The root node is the total of all the roots attached to the space.  [Note that 
-this combines two definitions of root: the accessibility is what defines a root 
-for tracing (see analysis.tracer.root.* and the mutator action for barriers 
-(see analysis.async-gc.root).  pekka 1998-03-20]
-
-.root.repr: Functionally, roots are defined by their scanning functions.  Roots 
-_could_ be represented as function closures, i.e. a pointer to a C function and 
-some auxiliary fields.  The most general variant of roots is just that.  
-However, for reasons of efficiency, some special variants are separated out.
-
-
-DETAILS
-
-
-Creation
-
-.create: A root becomes "active" as soon as it is created.
-
-.create.col: The root inherits its colour from the mutator, since it can only 
-contain references copied there by the mutator from somewhere else.  If the 
-mutator is grey for a trace when a root is created then that root will be used 
-to determine accessibility for that trace.  More specifically, the root will be 
-scanned when that trace flips.
-
-
-Destruction
-
-.destroy: It's OK to destroy a root at any time, except perhaps concurrently 
-with scanning it, but that's prevented by the arena lock.  If a root is 
-destroyed the references in it become invalid and unusable.
-
-
-Invariants
-
-.inv.white: Roots are never white for any trace, because they cannot be 
-condemned.
-
-.inv.rank: Roots always have a single rank.  A root without ranks would be a 
-root without references, which would be pointless.  The tracer doesn't support 
-multiple ranks in a single colour.
-
-
-Scanning
-
-.method: Root scanning methods are provided by the client so that the MPS can 
-locate and scan the root set.  See protocol.mps.root for details.  [There are 
-some more notes about root methods in meeting.qa.1996-10-16.]
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/scan/index.html b/mps/design/scan/index.html deleted file mode 100644 index 5660b936378..00000000000 --- a/mps/design/scan/index.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - -The design of the generic scanner - - - - - - - -
-                   THE DESIGN OF THE GENERIC SCANNER
-                            design.mps.scan
-                           incomplete design
-                           richard 1995-08-25
-
-SUMMARIES
-
-Scanned Summary
-
-.summary.subset: The summary of reference seens by scan (ss.unfixedSummary) is 
-a subset of the summary previously computed (SegSummary).
-
-There are two reasons that it is not an equality relation:  
-
-1. If the segment has had objects forwarded onto it then its summary will get 
-unioned with the summary of the segment that the object was forwarded from.  
-This may increase the summary.  The forwarded object of course may have a 
-smaller summary (if such a thing were to be computed) and so subsequent 
-scanning of the segment may reduce the summary.  (The forwarding process may 
-erroneously introduce zones into the destination's summary).  
-
-2. A write barrier hit will set the summary to RefSetUNIV.  
-
-The reason that ss.unfixedSummary is always a subset of the previous summary is 
-due to an "optimization" which has not been made in TraceFix.  See 
-impl.c.trace.fix.fixed.all.
-
-
-Partial Scans
-
-.clever-summary: With enough cleverness, it's possible to have partial scans of 
-condemned segments contribute to the segment summary.  [We had a system which 
-nearly worked -- see MMsrc(MMdevel_poolams at 1997/08/14 13:02:55 BST), but it 
-did not handle the situation in which a segment was not under the write barrier 
-when it was condemned.]
-
-.clever-summary.acc: Each time we partially scan a segment, we accumulate the 
-post-scan summary of the scanned objects into a field in the group, called 
-'summarySoFar'.  The post-scan summary is (summary \ white) U fixed.
-
-.clever-summary.acc.condemn: The cumulative summary is only meaningful while 
-the segment is condemned.  Otherwise it is set to RefSetEMPTY (a value which we 
-can check).
-
-.clever-summary.acc.reclaim: Then when we reclaim the segment, we set the 
-segment summary to the cumulative summary, as it is a post-scan summary of all 
-the scanned objects.
-
-.clever-summary.acc.other-trace: If the segment is scanned by another trace 
-while it is condemned, the cumulative summary must be set to the post-scan 
-summary of this scan (otherwise it becomes out-of-date).
-
-.clever-summary.scan: The scan summary is expected to be a summary of all 
-scanned references in the segment.  We don't know this accurately until we've 
-scanned everything in the segment.  So we add in the segment summary each time.
-
-.clever-summary.scan.fix: TraceScan also expects the scan state fixed summary 
-to include the post-scan summary of all references which were white.  Since we 
-don't scan all white references, we need to add in an approximation to the 
-summary of all white references which we didn't scan.  This is the intersection 
-of the segment summary and the white summary.
-
-.clever-summary.wb: If the cumulative summary is smaller than the mutator's 
-summary, a write-barrier is needed to prevent the mutator from invalidating it. 
- This means that sometimes we'd have to put the segment under the write-barrier 
-at condemn [this is not an operation currently available to pool class 
-implementations pekka 1998-02-26], which might not be very efficient.
-
-.clever-summary.method.wb: We need a new pool class method, called when the 
-write barrier is hit (or possibly any barrier hit).  The generic method will do 
-the usual TraceAccess work, the trivial method will do nothing.
-
-.clever-summary.acc.wb: When the write barrier is hit, we need to correct the 
-cumulative summary to the mutator summary.  This is approximated by setting the 
-summary to RefSetUNIV.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/seg/index.html b/mps/design/seg/index.html deleted file mode 100644 index ba22b21a10f..00000000000 --- a/mps/design/seg/index.html +++ /dev/null @@ -1,386 +0,0 @@ - - - - - - - - -The design of the MPS segment data structure - - - - - - - -
-              THE DESIGN OF THE MPS SEGMENT DATA STRUCTURE
-                             design.mps.seg
-                           incomplete design
-                             drj 1997-04-03
-
-INTRODUCTION
-
-.intro: This document describes the MPS Segment data structure.
-
-
-Document History
-
-.hist.2: The initial draft (replacing various notes in revisions 0 and 1) was 
-drafted by Richard Brooksby <richard> on 1997-04-03 as part of editing 
-MMsrc!seg.c(MMdevel_action2.1).
-
-.hist.3: Rewritten to separate segments and tracts, following 
-mail.tony.1998-11-02.10-26.  tony 1999-04-16
-
-OVERVIEW
-
-.over.segments: Segments are the basic units of tracing and shielding.  The MPM 
-also uses them as units of scanning and colour, although pool classes may 
-subdivide segments and be able to maintain colour on a finer grain (down to the 
-object level, for example).
-
-.over.objects: The mutator's objects are stored in segments.  Segments are 
-contiguous blocks of memory managed by some pool.  .segments.pool: The 
-arrangement of objects within a segment is determined by the class of the pool 
-which owns the segment. The pool is associated with the segment indirectly via 
-the first tract of the segment.
-
-.over.memory: The relationship between segments and areas of memory is 
-maintained by the segment module.  Pools acquire tracts from the arena, and 
-release them back to the arena when they don't need them any longer. The 
-segment module can associate contiguous tracts owned by the same pool with a 
-segment. The segment module provides the methods SegBase, SegLimit, and SegSize 
-which map a segment onto the addresses of the memory block it represents.
-
-.over.hierarchy: The Segment datastructure is designed to be subclassable (see 
-design.mps.protocol). The basic segment class (Seg) supports colour and 
-protection for use by the tracer, as well as support for a pool ring, and all 
-generic segment functions. Clients may use Seg directly, but will most probably 
-want to use a subclass with additional properties.
-
-.over.hierarchy.gcseg: The segment module provides GCSeg - a subclass of Seg 
-which has full support for GC including buffering and the ability to be linked 
-onto the grey ring.
-
-DATA STRUCTURE
-
-
-typedef struct SegStruct {      /* segment structure */
-  Sig sig;                      /* impl.h.misc.sig */
-  SegClass class;               /* segment class structure */
-  Tract firstTract;             /* first tract of segment */
-  RingStruct poolRing;          /* link in list of segs in pool */
-  Addr limit;                   /* limit of segment */
-  unsigned depth : SHIELD_DEPTH_WIDTH; /* see impl.c.shield.def.depth */
-  AccessSet pm : AccessMAX;     /* protection mode, impl.c.shield */
-  AccessSet sm : AccessMAX;     /* shield mode, impl.c.shield */
-  TraceSet grey : TRACE_MAX;    /* traces for which seg is grey */
-  TraceSet white : TRACE_MAX;   /* traces for which seg is white */
-  TraceSet nailed : TRACE_MAX;  /* traces for which seg has nailed objects */
-  RankSet rankSet : RankMAX;    /* ranks of references in this seg */
-} SegStruct;
-
-
-typedef struct GCSegStruct {    /* GC segment structure */
-  SegStruct segStruct;          /* superclass fields must come first */
-  RingStruct greyRing;          /* link in list of grey segs */
-  RefSet summary;               /* summary of references out of seg */
-  Buffer buffer;                /* non-NULL if seg is buffered */
-  Sig sig;                      /* design.mps.sig */
-} GCSegStruct;
-
-
-.field.rankSet: The "rankSet" field represents the set of ranks of the 
-references in the segment.  It is initialized to empty by SegInit.  
-.field.rankSet.single: The Tracer only permits one rank per segment [ref?] so 
-this field is either empty or a singleton.  .field.rankSet.empty: An empty 
-rankSet indicates that there are no references.  If there are no references in 
-the segment then it cannot contain black or grey references.  
-.field.rankSet.start: If references are stored in the segment then it must be 
-updated, along with the summary (.field.summary.start).
-
-.field.depth: The "depth" field is used by the Shield (impl.c.shield) to manage 
-protection of the segment.  It is initialized to zero by SegInit.
-
-.field.sm: The "sm" field is used by the Shield (impl.c.shield) to manage 
-protection of the segment.  It is initialized to AccessSetEMPTY by SegInit.
-
-.field.pm: The "pm" field is used by the Shield (impl.c.shield) to manage 
-protection of the segment.  It is initialized to AccessSetEMPTY by SegInit.  
-The field is used by both the shield and the ANSI fake protection 
-(impl.c.protan).
-
-.field.black: The "black" field is the set of traces for which there may be 
-black objects (i.e. objects containing references, but no references to white 
-objects) in the segment.  More precisely, if there is a black object for a 
-trace in the segment then that trace will appear in the "black" field.  It is 
-initialized to TraceSetEMPTY by SegInit.
-
-.field.grey: The "grey" field is the set of traces for which there may be grey 
-objects (i.e containing references to white objects) in the segment.  More 
-precisely, if there is a reference to a white object for a trace in the segment 
-then that trace will appear in the "grey" field.  It is initialized to 
-TraceSetEMPTY by SegInit.
-
-.field.white: The "white" field is the set of traces for which there may be 
-white objects in the segment.  More precisely, if there is a white object for a 
-trace in the segment then that trace will appear in the "white" field.  It is 
-initialized to TraceSetEMPTY by SegInit.
-
-.field.summary: The "summary" field is an approximation to the set of all 
-references in the segment.  If there is a reference R in the segment, then 
-RefSetIsMember(summary, R) is TRUE.  The summary is initialized to RefSetEMPTY 
-by SegInit.  .field.summary.start: If references are stored in the segment then 
-it must be updated, along with rankSet (.field.rankSet.start).
-
-.field.buffer: The "buffer" field is either NULL, or points to the descriptor 
-structure of the buffer which is currently allocating in the segment.  The 
-field is initialized to NULL by SegInit.  .field.buffer.owner: This buffer must 
-belong to the same pool as the segment, because only that pool has the right to 
-attach it.
-
-INTERFACE
-
-Splitting and Merging
-
-.split-and-merge: There is support for splitting and merging segments, to give 
-pools the flexibility to rearrange their tracts among segments as they see fit.
-
-.split: Segments may be split with the function SegSplit
-
-Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at,
-             Bool withReservoirPermit, ...);
-
-If successful, segment "seg" is split at address "at", yielding two segments 
-which are returned in segLoReturn and segHiReturn for the low and high segments 
-respectively. The base of the low segment is the old base of "seg". The limit 
-of the low segment is "at". The base of the high segment is "at". This limit of 
-the high segment is the old limit of "seg". "seg" is effectively destroyed 
-during this operation (actually, it might be reused as one of the returned 
-segments). Segment subclasses may make use of the optional arguments; the 
-built-in classes do not.
-
-.split.invariants: The client must ensure some invariants are met before 
-calling SegSplit:
-
-.split.inv.align: "at" must be appropriately aligned to the arena alignment, 
-and lie between the base and limit of "seg". Justification: the split segments 
-cannot be represented if this is not so.
-
-.split.inv.buffer: If "seg" is attached to a buffer, the buffered region must 
-not include address "at". Justification: the segment module is not in a 
-position to know how (or whether) a pool might wish to split a buffer. This 
-permits the buffer to remain attached to just one of the returned segments.
-
-.split.state: Except as noted above, the segments returned have the same 
-properties as "seg". I.e. their colour, summary, rankset, nailedness etc. are 
-set to the values of "seg".
-
-.merge: Segments may be merged with the function SegMerge
-
-Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi,
-             Bool withReservoirPermit, ...);
-
-If successful, segments "segLo" and "segHi" are merged together, yielding a 
-segment which is returned in mergedSegReturn. "segLo" and "segHi" are 
-effectively destroyed during this operation (actually, one of them might be 
-reused as the merged segment). Segment subclasses may make use of the optional 
-arguments; the built-in classes do not.
-
-.merge.invariants: The client must ensure some invariants are met before 
-calling SegMerge:
-
-.merge.inv.abut: The limit of "segLo" must be the same as the base of "segHi". 
-Justification: the merged segment cannot be represented if this is not so.
-
-.merge.inv.buffer: One or other of "segLo" and "segHi" may attached to a 
-buffer, but not both. Justification: the segment module does not support 
-attachment of a single seg to 2 buffers.
-
-.merge.inv.similar: "segLo" and "segHi" must be sufficiently similar. Two 
-segments are sufficiently similar if they have identical values for each of the 
-following fields: class, sm, grey, white, nailed, rankSet. Justification: there 
-is no single choice of behaviour for cases where these fields are not 
-identical. The pool class must make it's own choices about this if it wishes to 
-permit more flexible merging. If so, it should be a simple matter for the pool 
-to arrange for the segments to look sufficiently similar before calling 
-SegMerge.
-
-.merge.state: The merged segment will share the same state as "segLo" and 
-"segHi" for those fields which are identical (see .merge.inv.similar). The 
-summary will be the union of the summaries of "segLo" and "segHi".
-
-
-EXTENSIBILITY
-
-Splitting and Merging
-
-.method.split: Segment subclasses may extend the support for segment splitting 
-by defining their own "split" method.
-
-Res segSplit(Seg seg, Seg segHi, 
-             Addr base, Addr mid, Addr limit,
-             Bool withReservoirPermit, va_list args)
-
-On entry, "seg" is a segment with region [base,limit), "segHi" is 
-uninitialized, "mid" is the address at which the segment is to be split. The 
-method is responsible for destructively modifying "seg" and initializing 
-"segHi" so that on exit "seg" is a segment with region [base,mid) and segHi is 
-a segment with region [mid,limit). Usually a method would only directly modify 
-the fields defined for the segment subclass. This might involve allocation, 
-which may use the reservoir if "withReservoirPermit" is TRUE. 
-.method.split.next: A split method should always call the next method, either 
-before or after any class-specific code (see design.mps.protocol
-.overview.next-method).
-
-.method.merge: Segment subclasses may extend the support for segment merging by 
-defining their own "merge" method.
-
-Res segMerge(Seg seg, Seg segHi, 
-             Addr base, Addr mid, Addr limit,
-             Bool withReservoirPermit, va_list args)
-
-On entry, "seg" is a segment with region [base,mid), "segHi" is a segment with 
-region [mid,limit), The method is responsible for destructively modifying "seg" 
-and finishing "segHi" so that on exit "seg" is a segment with region 
-[base,limit) and segHi is garbage. Usually a method would only modify the 
-fields defined for the segment subclass. This might involve allocation, which 
-may use the reservoir if "withReservoirPermit" is TRUE. .method.merge.next: A 
-merge method should always call the next method, either before or after any 
-class-specific code (see design.mps.protocol.overview.next-method).
-
-.split-merge.shield: Split and merge methods may assume that the segments they 
-are manipulating are not in the shield cache. .split-merge.shield.flush: The 
-shield cache is flushed before any split or merge methods are invoked. 
-.split-merge.shield.re-flush: If a split or merge method performs an operation 
-on a segment which might cause the segment to be cached, the method must flush 
-the shield cache before returning or calling another split or merge method.
-
-.split-merge.fail: Split and merge methods might fail, in which case segments 
-"seg" and "segHi" must be equivalently valid and configured at exit as they 
-were according to the entry conditions. It's simplest if the failure can be 
-detected before calling the next method (e.g. by allocating any objects early 
-in the method). .split-merge.fail.anti: If it's not possible to detect failure 
-before calling the next method, the appropriate anti-method must be used (see 
-design.mps.protocol.guide.fail.after-next). Split methods are anti-methods for 
-merge methods, and vice-versa. .split-merge.fail.anti.constrain: In general, 
-care should be taken when writing split and merge methods to ensure that they 
-really are anti-methods for each other. The anti-method must not fail if the 
-initial method succeeded. The anti-method should reverse any side effects of 
-the initial method, except where it's known to be safe to avoid this (see 
-.split-merge.fail.summary for an example of a safe case).  
-.split-merge.fail.anti.no: If this isn't possible (it might not be) then the 
-methods won't support after-next failure. This fact should be documented, if 
-the methods are intended to support further specialization. Note that using 
-va_arg with the "args" parameter is sufficient to make it impossible to reverse 
-all side effects.
-
-.split-merge.fail.summary: The segment summary might not be restored exactly 
-after a failed merge operation. Each segment would be left with a summary which 
-is the union of the original summaries (see .merge.state). This increases the 
-conservatism in the summaries, but is otherwise safe.
-
-.split-merge.unsupported: Segment classes need not support segment merging at 
-all. The function SegClassMixInNoSplitMerge is supplied to set the split and 
-merge methods to unsupporting methods that will report an error in checking 
-varieties.
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/shield/index.html b/mps/design/shield/index.html deleted file mode 100644 index 8a8136f7855..00000000000 --- a/mps/design/shield/index.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - -MPS Shield - - - - - - - -

This document contains a guide to the MPS Shield. There is no historical initial design, but in its place there are some early ideas and discussions: initial ideas. References, History, Copyright and License are at the end.

- -
- -

Guide

- -

Readership: any MPS developer. Not confidential.

- -

Introduction

- -

For incremental collection, we need separate control of collector access and mutator (client) access to memory. (The collector must be able to incrementally scan objects, without the mutator being able to see them yet).

- -

Unfortunately common OSs do not support different access levels (protection maps) for different parts of the same process.

- -

The MPS Shield is an abstraction that does extra work to overcome this limitation, and give the rest of the MPS the illusion that we can control collector and mutator access separately.

- - -

Control of mutator access: Raise, Lower, Suspend, Resume

- -

The MPS uses ShieldRaise and ShieldLower to forbid or permit the mutator access to object memory (that is, memory allocated by MPS):

- -

ShieldRaise(mode) prevents the mutator accessing the memory in the specified mode (read, write, or both).

- -

ShieldLower(mode) allows the mutator to access the memory in the specified mode (read, write, or both).

- -

If the mutator attempts an access that hits a shield, the MPS gets a barrier hit (aka fault, interrupt, exception, etc), quickly does some necessary work, and then makes the access succeed.

- - -

Some objects (eg. registers) cannot be hardware protected: the only way to prevent mutator access to them is to halt all mutator threads. The MPS uses ShieldSuspend and ShieldResume to do this.

- - -

Control of collector access: Enter, Leave, Expose, Cover

- -

When the collector wants to access object memory (that is, memory allocated by MPS), it must call ShieldEnter, then wrap any accesses with a ShieldExpose / ShieldCover pair, and finally call ShieldLeave.

- -

ShieldEnter and ShieldLeave are done by ArenaEnter and ArenaLeave (approximately) -- so the shield is always entered when we are within MPS code (approximately).

- -

ShieldExpose might for example be called around:

-
    -
  • format-scan (when Scanning);
  • -
  • format-skip (when marking grains in a non-moving Fix);
  • -
  • format-isMoved, AddrCopy (aka memcpy), and format-move (during a copying Fix);
  • -
  • format-pad (during reclaim).
  • -
- -

Note that there is no need to call ShieldExpose when accessing pool management memory such as bit tables etc. This is not object memory, is never (legally) accessed by the mutator, and so is never shielded.

- -

On common OSs, the only way to allow collector access is to allow access from the whole process, including the mutator. So if the shield is asked to allow collector access but deny mutator access, it will halt all mutator threads to prevent any mutator access. The MPS Shield performs suspension and restart; normal collector code does not need to worry about it.

- -

Collector code can make multiple sequential, overlapping, or nested calls to ShieldExpose on the same segment. (Each must be balanced by a ShieldCover before ShieldLeave is called). A usage count is maintained in seg->depth: a positive "depth" means a positive number of outstanding reasons why the segment must be exposed to the collector. When the usage count reaches zero, there is no longer any reason the segment should be unprotected, and the Shield could re-instate hardware protection.

- -

However, as a performance-improving hysteresis, the Shield defers re-protection, maintaining a cache of the last 16 times a segment no longer had a reason to be collector-accessible. Presence in the cache counts as a 'reason': segments in the cache have seg->depth increased by one. As segments get pushed out of the cache, or at ShieldLeave, this artificial 'reason' is decremented from seg->depth, and (if depth is now zero) the deferred reinstatement of hardware protection happens.

- -

So whenever hardware protection is temporarily removed to allow collector access, there is a 'nurse' that will ensure this protection is re-established: the nurse is either the balancing ShieldCover call in collector code, or an entry in the shield cache.

- -

[Why is there a fixed-size cache? This is not the simple approach! All we need is a chain of segs that might need their hardware protection to be sync'd with their shield mode. Head in the shield, and one pointer in each seg struct. I guess we try hard to avoid bloating SegStruct (to maintain residency in the processor cache). But is 16 the right size? A cache-miss wastes two kernel calls. RHSK 2006-12-19]

- -

[Also, I don't like the cache code. For example, why does ShieldFlush break out early if arena->shDepth is 0? This should never happen until the cache is completely flushed, ie. we have reached shCacheLimit. Why does ShieldFlush not reset shCacheLimit? Why does flush() silently accept NULL cache entries? RHSK 2006-12-19]

- -

[Also, why is seg->depth never checked for overflow? It is only a 4-bit-wide bit field, currently. RHSK 2006-12-19]

- -
- -

Initial Ideas

- -

There never was an initial design document.

- -

See this very helpful - overview of protected tracing - . - Note that this overview is old, and the details may be inaccurate.

- -

See - idea.shield - .

- -
- - -

A. References

- - - - -

B. Document History

- - -
-  2006-12-19  RHSK  Created: Guide, plus links to initial ideas.
-  2007-01-04  RHSK  Minor text changes for clarity.
-  2007-01-12  RHSK  ShieldEnter/Leave done by ArenaEnter/Leave
-
- - -

C. Copyright and License

- -

This document is copyright © 2006-2007 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/sig/index.html b/mps/design/sig/index.html deleted file mode 100644 index b6d7d399c77..00000000000 --- a/mps/design/sig/index.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - -The design of the Memory Pool System signature system - - - - - - - -
-         THE DESIGN OF THE MEMORY POOL SYSTEM SIGNATURE SYSTEM
-                             design.mps.sig
-                           incomplete design
-                           richard 1995-08-25
-
-
-TESTING:
-
-.test.uniq: The unix command
-sed -n '/^#define [a-zA-Z]*Sig/s/[^(]*(/(/p' *.[ch]| sort| uniq -c
-will display all signatures defined in the mps along with a count of how many 
-times they are defined.  If any counts are greater than 1, then the same 
-signature value is being used for different signatures.  This is undesirable 
-and the problem should be investigated.  People not using unix may still find 
-the RE useful.
-
-
-TEXT:
-
-Signatures are magic numbers which are written into structures
-when they are created and invalidated (by overwriting with
-SigInvalid) when they are destroyed.  They provide a limited form
-of run-time type checking and dynamic scope checking.
-
-Signature values should be transliterations of the corresponding words into 
-hex, as guide.hex.trans.  The first three hex digits should be the 
-transliteration of "SIG".
-
-
- -

Note: for the transliterations, see -guide.hex.trans -(not currently available outside Ravenbrook).

- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
2009-01-27RHSKLink to guide.hex.trans.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/splay/index.html b/mps/design/splay/index.html deleted file mode 100644 index c28c008614f..00000000000 --- a/mps/design/splay/index.html +++ /dev/null @@ -1,905 +0,0 @@ - - - - - - - - -Design of splay trees - - - - - - - -
-                         DESIGN OF SPLAY TREES
-                            design.mps.splay
-                               draft doc
-                           gavinm 1998-05-01
-
-INTRODUCTION
-
-.intro: This document explains the design of impl.c.splay, an implementation of 
-Splay Trees, including its interface and implementation.
-
-.readership: This document is intended for any MM developer.
-
-.source: The primary sources for this design are paper.st85(0) and 
-paper.sleator96(0).  Also as CBS is a client, design.mps.cbs.  As PoolMVFF is 
-an indirect client, design.mps.poolmvff(1). Also, as PoolMV2 is an 
-(obsolescent?) indirect client, design.mps.poolmv2.  
-
-.background: The following background documents influence the design: 
-guide.impl.c.adt(0).
-
-
-Document History
-
-.hist.0: Written by GavinM 1998-05-01, made draft 1998-05-27.
-
-.hist.1: Added client properties.  GavinM 1998-09-09
-
-.hist.2: Polished for review (chiefly adding a DEFINITIONS section).  drj 
-1999-03-10
-
-.hist.3: Edited after review. tony 1999-03-31
-
-
-OVERVIEW
-
-.overview: Splay trees are a form of binary tree where each access brings the 
-accessed element (or the nearest element) to the root of the tree.  The 
-restructuring of the tree caused by the access gives excellent amortised 
-performance, as the splay tree adapts its shape to usage patterns.  Unused 
-nodes have essentially no time overhead.  For a cute animation of splay trees, 
-see <URL:http://langevin.usc.edu/BST/SplayTree-Example.html>.
-
-
-DEFINITIONS
-
-.def.splay-tree: A "Splay Tree" is a self-adjusting binary tree as described in 
-paper.st85(0), paper.sleator96(0).
-
-.def.node: A "node" is used in the typical datastructure sense to mean an 
-element of a tree (see also .type.splay.node).
-
-.def.key:  A "key" is a value associated with each node; the keys are totally 
-ordered by a client provided comparator. 
-
-.def.comparator: A "comparator" is a function that compares keys to determine 
-their ordering (see also .type.splay.compare.method).
-
-.def.successor: Node N1 is the "successor" of node N2 if N1 and N2 are both in 
-the same tree, and the key of N1 immediately follows the key of N2 in the 
-ordering of all keys for the tree.
-
-.def.left-child: Each node N contains a "left child", which is a (possibly 
-empty) sub-tree of nodes. The key of N is ordered after the keys of all nodes 
-in this sub-tree.
-
-.def.right-child: Each node N contains a "right child", which is a (possibly 
-empty) sub-tree of nodes. The key of N is ordered before the keys of all nodes 
-in this sub-tree.
-
-.def.neighbour: A node N which has key Kn is a "neighbour" of a key K if either 
-Kn is the first key in the total order which compares greater than K or if Kn 
-is the last key in the total order which compares less than K.
-
-.def.first: A node is the "first" node in a set of nodes if its key compares 
-less than the keys of all other nodes in the set.
-
-.def.last: A node is the "last" node in a set of nodes if its key compares 
-greater than the keys of all other nodes in the set.
-
-.def.client-property: A "client property" is a value that the client may 
-associate with each node in addition to the key (a block size, for example).  
-This splay tree implementation provides support for efficiently finding the 
-first or last nodes with suitably large client property values.  See also .prop 
-below.
-
-
-REQUIREMENTS
-
-.req: These requirements are drawn from those implied by design.mps.poolmv2, 
-design.mps.poolmvff(1), design.mps.cbs(2) and general inferred MPS requirements.
-
-.req.order: Must maintain a set of abstract keys which is totally ordered for a 
-comparator.
-
-.req.tree: The keys must be associated with nodes arranged in a Splay Tree.
-
-.req.splay: Common operations must balance the tree by splaying it, to achieve 
-low amortized cost (see paper.st85(0)).
-
-.req.add: Must be able to add new members. This is a common operation.
-
-.req.remove: Must be able to remove members. This is a common operation.
-
-.req.locate: Must be able to locate a member, given a key. This is a common 
-operation.
-
-.req.neighbours: Must be able to locate the neighbouring members (in order) of 
-a non-member, given a key (see .def.neighbour).  This is a common operation.
-
-.req.iterate: Must be able to iterate over all members in order with reasonable 
-efficiency. 
-
-.req.protocol: Must support detection of protocol violations.
-
-.req.debug: Must support debugging of clients.
-
-.req.stack: Must do all non-debugging operations with stack usage bounded by a 
-constant size.
-
-.req.adapt: Must adapt to regularities in usage pattern, for better performance.
-
-.req.property: Must permit a client to associate a client property (such as a 
-size) with each node in the tree.
-
-.req.property.change: Must permit a client to dynamically reassign client 
-properties to nodes in the tree.  This is a common operation.
-
-.req.property.find: Must support rapid finding of the first and last nodes 
-which have a suitably large value for their client property.  This is a common 
-operation.
-
-.req.root: Must be able to find the root of a splay tree (if one exists).
-
-
-EXTERNAL TYPES
-
-.type.splay.tree: SplayTree is the type of the main object at the root of the 
-splay tree.  It is intended that the SplayTreeStruct can be embedded in another 
-structure (see .usage.client-tree for an example).  No convenience functions 
-are provided for allocation or deallocation.
-  typedef struct SplayTreeStruct SplayTreeStruct, *SplayTree;
-
-.type.splay.node: SplayNode is the type of a node of the splay tree.  
-SplayNodeStruct contains no fields to store the key associated with the node, 
-or the client property. Again, it is intended that the SplayNodeStruct can be 
-embedded in another structure, and that this is how the association will be 
-made (see .usage.client-node for an example).  No convenience functions are 
-provided for allocation or deallocation.
-  typedef struct SplayNodeStruct SplayNodeStruct, *SplayNode;
-
-.type.splay.compare.method: SplayCompareMethod is a pointer to a function with 
-the following prototype:
-  Compare compare(void *key, SplayNode node);
-The function is required to compare the key with the key the client associates 
-with that splay tree node, and return the appropriate Compare value (see 
-.usage.compare for an example). The function compares a key with a node, rather 
-than a pair of keys or nodes as might seem more obvious. This is because the 
-details of the mapping between nodes and keys is left to the client (see 
-.type.splay.node), and the splaying operations compare keys with nodes (see 
-.impl.splay).
-
-.type.splay.node.describe.method: SplayNodeDescribeMethod is a pointer to a 
-function with the following prototype:
-  Res nodeDescribe(SplayNode node, mps_lib_FILE *stream)
-The function is required to write (via WriteF) a client-oriented representation 
-of the splay node.  The output should be non-empty, short, and without return 
-characters.  This is provided for debugging purposes only.
-
-.type.splay.test.node.method: SplayTestNodeMethod is a pointer to a function 
-with the following prototype:
-  Bool testNode(SplayTree tree, SplayNode node, void *closureP, unsigned long 
-closureS);
-The function is required to determine whether the node itself meets some client 
-determined property (see .prop and .usage.test.node for an example). Parameters 
-closureP and closureS describe the environment for the function (see 
-.function.splay.find.first and .function.splay.find.last).
-
-.type.splay.test.tree.method: SplayTestTreeMethod is a pointer to a function 
-with the following prototype:
-  Bool testTree(SplayTree tree, SplayNode node, void *closureP, unsigned long 
-closureS);
-The function is required to determine whether any of the nodes in the sub-tree 
-rooted at the given node meet some client determined property (see .prop and 
-.usage.test.tree for an example).  In particular, it must be a precise (not 
-conservative) indication of whether there are any nodes in the sub-tree for 
-which the testNode method (see .type.splay.test.node.method) would return TRUE. 
-Parameters closureP and closureS describe the environment for the function (see 
-.function.splay.find.first and .function.splay.find.last).
-
-.type.splay.update.node.method: SplayUpdateNodeMethod is a pointer to a 
-function with the following prototype:
-  void updateNode(SplayTree tree, SplayNode node, SplayNode leftChild, 
-SplayNode rightChild);
-The function is required to update any client datastructures associated with a 
-node to maintain some client determined property (see .prop) given that the 
-children of the node have changed.  If the node does not have one or both 
-children, then NULL will be passed as the relevant parameter.  (See 
-.usage.callback for an example)
-
-
-EXTERNAL FUNCTIONS
-
-.function.no-thread: The interface functions are not designed to be either 
-thread-safe or re-entrant. Clients of the interface are responsible for 
-synchronization, and for ensuring that client-provided methods invoked by the 
-splay module (.type.splay.compare.method, .type.splay.test.node.method, 
-.type.splay.test.tree.method, .type.splay.update.node.method) do not call 
-functions of the splay module.
-
-.function.splay.tree.check: This is a check function for the SplayTree type 
-(see guide.impl.c.adt.method.check & design.mps.check(0)):
-  Bool SplayTreeCheck(SplayTree tree);
-
-.function.splay.node.check: This is a check function for the SplayNode type 
-(see guide.impl.c.adt.method.check & design.mps.check(0)):
-  Bool SplayNodeCheck(SplayNode node);
-
-.function.splay.tree.init: This function initialises a SplayTree  (see 
-guide.impl.c.adt.method.init).  It requires a compare method that defines a 
-total ordering on nodes (see .req.order); the effect of supplying a compare 
-method that does not implement a total ordering is undefined.  It also requires 
-an updateNode method, which will be used to keep client properties up to date 
-when the tree structure changes; the value SplayTrivUpdateNode may be used for 
-this method if there is no need to maintain client properties.  (See 
-.usage.initialization for an example use).
-  void SplayTreeInit(SplayTree tree, SplayCompareMethod compare, 
-SplayUpdateNodeMethod updateNode);
-
-.function.splay.tree.finish: This function clears the fields of a SplayTree  
-(see guide.impl.c.adt.method.finish).  Note that it does not attempt to finish 
-or deallocate any associated SplayNode objects; clients wishing to destroy a 
-non-empty SplayTree must first explicitly descend the tree and call 
-SplayNodeFinish on each node from the bottom up.
-  void SplayTreeFinish(SplayTree tree);
-
-.function.splay.node.init: This function initialises a SplayNode  (see 
-guide.impl.c.adt.method.init).
-  void SplayNodeInit(SplayNode node);
-
-.function.splay.node.finish: This function clears the fields of a SplayNode  
-(see guide.impl.c.adt.method.finish).  Note that it does not attempt to finish 
-or deallocate any referenced SplayNode objects (see.function.splay.tree.finish).
-  void SplayNodeFinish(SplayNode node);
-
-.function.splay.root: This function returns the root node of the tree, if any 
-(see .req.root).  If the tree is empty, FALSE is returned and *nodeReturn is 
-not changed.  Otherwise, TRUE is returned and *nodeReturn is set to the root.
-  Bool SplayRoot(SplayNode *nodeReturn, SplayTree tree);
-
-.function.splay.tree.insert: This function is used to insert into a splay tree 
-a new node which is associated with the supplied key (see .req.add).  It first 
-splays the tree at the key.  If an attempt is made to insert a node that 
-compares CompareEQUAL to an existing node in the tree, then ResFAIL will be 
-returned and the node will not be inserted.   (See .usage.insert for an example 
-use).
-  Res SplayTreeInsert(SplayTree tree, SplayNode node, void *key);
-
-.function.splay.tree.delete: This function is used to delete from a splay tree 
-a node which is associated with the supplied key (see .req.remove).  If the 
-tree does not contain the given node, or the given node does not compare 
-CompareEQUAL with the given key, then ResFAIL will be returned, and the node 
-will not be deleted.  The function first splays the tree at the given key.    
-(See .usage.delete for an example use).
-  Res SplayTreeDelete(SplayTree tree, SplayNode node, void *key);
-
-.function.splay.tree.search: This function searches the splay tree for a node 
-that compares CompareEQUAL to the given key (see .req.locate).  It splays the 
-tree at the key.  It returns ResFAIL if there is no such node in the tree, 
-otherwise *nodeReturn will be set to the node.
-  Res SplayTreeSearch(SplayNode *nodeReturn, SplayTree tree, void *key);
-
-.function.splay.tree.neighbours: This function searches a splay tree for the 
-two nodes that are the neighbours of the given key (see .req.neighbours).  It 
-splays the tree at the key.  *leftReturn will be the neighbour which compares 
-less than the key if such a neighbour exists; otherwise it will be NULL.  
-*rightReturn will be the neighbour which compares greater than the key if such 
-a neighbour exists; otherwise it will be NULL.  The function returns ResFAIL if 
-any node in the tree compares CompareEQUAL with the given key.    (See 
-.usage.insert for an example use).
- Res SplayTreeNeighbours(SplayNode *leftReturn, SplayNode *rightReturn, 
-SplayTree tree, void *key);
-
-.function.splay.tree.first: This function splays the tree at the first node, 
-and returns that node (see .req.iterate).  The supplied key should compare 
-CompareLESS with all nodes in the tree.  It will return NULL if the tree has no 
-nodes. 
-  SplayNode SplayTreeFirst(SplayTree tree, void *zeroKey);
-
-.function.splay.tree.next: This function receives a node and key and returns 
-the successor node to that node (see .req.iterate).  This function is intended 
-for use in iteration when the received node will be the current root of the 
-tree, but is robust against being interspersed with other splay operations 
-(provided the old node still exists).  The supplied key must compare 
-CompareEQUAL to the supplied node.  Note that use of this function rebalances 
-the tree for each node accessed. If many nodes are accessed as a result of 
-multiple uses, the resultant tree will be generally well balanced. But if the 
-tree was previously beneficially balanced for a small working set of accesses, 
-then this local optimization will be lost. (see .future.parent).
-  SplayNode SplayTreeNext(SplayTree tree, SplayNode oldNode, void *oldKey);
-
-.function.splay.tree.describe: This function prints (using WriteF) to the 
-stream a textual representation of the given splay tree, using nodeDescribe to 
-print client-oriented representations of the nodes (see .req.debug).
-  Res SplayTreeDescribe(SplayTree tree, mps_lib_FILE *stream, 
-SplayNodeDescribeMethod nodeDescribe);
-
-.function.splay.find.first: SplayFindFirst finds the first node in the tree 
-that satisfies some client property (as determined by the testNode and testTree 
-methods) (see .req.property.find).  closureP and closureS are arbitrary values, 
-and are passed to the testNode and testTree methods which may use the values as 
-closure environments.  If there is no satisfactory node, then FALSE is 
-returned, otherwise *nodeReturn is set to the node.   (See .usage.delete for an 
-example use).
-  Bool SplayFindFirst(SplayNode *nodeReturn, SplayTree tree, 
-SplayTestNodeMethod testNode, SplayTestTreeMethod testTree, void *closureP, 
-unsigned long closureS);
-
-.function.splay.find.last: SplayFindLast finds the last node in the tree that 
-satisfies some client property (as determined by the testNode and testTree 
-methods) (see .req.property.find).  closureP and closureS are arbitrary values, 
-and are passed to the testNode and testTree methods which may use the values as 
-closure environments.  If there is no satisfactory node, then FALSE is 
-returned, otherwise *nodeReturn is set to the node. 
-  Bool SplayFindFirst(SplayNode *nodeReturn, SplayTree tree, 
-SplayTestNodeMethod testNode, SplayTestTreeMethod testTree, void *closureP, 
-unsigned long closureS);
-
-.function.splay.node.refresh: SplayNodeRefresh must be called whenever the 
-client property (see .prop) at a node changes (see .req.property.change).  It 
-will call the updateNode method on the given node, and any other nodes that may 
-require update.  The client key for the node must also be supplied; the 
-function splays the tree at this key.   (See .usage.insert for an example use).
-  void SplayNodeRefresh(SplayTree tree, SplayNode node, void *key);
-
-
-CLIENT-DETERMINED PROPERTIES
-
-.prop: To support .req.property.find, this splay tree implementation provides 
-additional features to permit clients to cache maximum (or minimum) values of 
-client properties for all the nodes in a subtree.  The splay tree 
-implementation uses the cached values as part of SplayFindFirst and 
-SplayFindLast via the testNode and testTree methods.  The client is free to 
-choose how to represent the client property, and how to compute and store the 
-cached value. 
-
-.prop.update: The cached values depend upon the topology of the tree, which may 
-vary as a result of operations on the tree.  The client is given the 
-opportunity to compute new cache values whenever necessary, via the updateNode 
-method (see .function.splay.tree.init). This happens whenever the tree is 
-restructured. The client may use the SplayNodeRefresh method to indicate that 
-the client attributes at a node have changed (see .req.property.change). A call 
-to SplayNodeRefresh splays the tree at the specified node, which may provoke 
-calls to the updateNode method as a result of the tree restructuring.  The 
-updateNode method will also be called whenever a new splay node is inserted 
-into the tree. 
-
-.prop.example: For example, if implementing an address ordered tree of free 
-blocks using a splay tree, a client might choose to use the base address of 
-each block as the key for each node, and the size of each block as the client 
-property. The client can then maintain as a cached value in each node the size 
-of the largest block in the subtree rooted at that node. This will permit a 
-fast search for the first or last block of at least a given size. See 
-.usage.callback for an example updateNode method for such a client.
-
-.prop.ops: The splay operations must cause client properties for nodes to be 
-updated in the following circumstances:- (.impl.* for details):
-
-.prop.ops.rotate: rotate left, rotate right -- We need to update the value at 
-the original root, and the new root, in that order.
-
-.prop.ops.link: link left, link right -- We know that the line of right descent 
-from the root of the left tree and the line of left descent from the root of 
-the right tree will both need to be updated.  This is performed at the assembly 
-stage. (We could update these chains every time we do a link left or link right 
-instead, but this would be less efficient)
-
-.prop.ops.assemble: assemble -- This operation also invalidates the lines of 
-right and left descent of the left and right trees respectively which need to 
-be updated (see below).  It also invalidates the root which must be updated 
-last.
-
-.prop.ops.assemble.reverse: To correct the chains of the left and right trees 
-without requiring stack or high complexity, we use a judicious amount of 
-pointer reversal.
-
-.prop.ops.assemble.traverse: During the assembly, after the root's children 
-have been transplanted, we correct the chains of the left and right trees.  For 
-the left tree, we traverse the right child line, reversing pointers, until we 
-reach the node that was the last node prior to the transplantation of the 
-root's children.  Then we update from that node back to the left tree's root, 
-restoring pointers.  Updating the right tree is the same, mutatis mutandis. 
-(See .future.reverse for an alternative approach).
-
-
-USAGE
-
-.usage: Here's a simple example of a client which uses a splay tree to 
-implement an address ordered tree of free blocks. The significant client usages 
-of the splay tree interface might look as follows:-
-
-.usage.client-tree: Tree structure to embed a SplayTree (see .type.splay.tree):
-typedef struct FreeTreeStruct {
-  SplayTreeStruct splayTree;  /* Embedded splay tree */
-  /* no obvious client fields for this simple example */
-} FreeTreeStruct;
-
-.usage.client-node: Node structure to embed a SplayNode (see .type.splay.node):
-typedef struct FreeBlockStruct {
-  SplayNodeStruct splayNode; /* embedded splay node */
-  Addr base;                 /* base address of block is also the key */
-  Size size;                 /* size of block is also the client property */
-  Size maxSize;              /* cached value for maximum size in subtree */
-} FreeBlockStruct;
-
-.usage.callback: updateNode callback method (see 
-.type.splay.update.node.method):
-void FreeBlockUpdateNode(SplayTree tree, SplayNode node,
-                         SplayNode leftChild, SplayNode rightChild)
-{
-  /* Compute the maximum size of any block in this subtree. */
-  /* The value to cache is the maximum of the size of this block, */
-  /* the cached value for the left subtree (if any) and the cached */
-  /* value of the right subtree (if any) */
-
-  FreeBlock freeNode = FreeBlockOfSplayNode(node);
-
-  Size maxSize = freeNode.size;
- 
-  if(leftChild != NULL) {
-    FreeBlock leftNode = FreeBlockOfSplayNode(leftChild);
-    if(leftNode.maxSize > maxSize)
-      maxSize = leftNode->maxSize;
-  }
- 
-  if(rightChild != NULL) {
-    FreeBlock rightNode = FreeBlockOfSplayNode(rightChild);
-    if(rightNode.maxSize > maxSize)
-      maxSize = rightNode->maxSize;
-  }
- 
-  freeNode->maxSize = maxSize;
-}
-
-.usage.compare: Comparison function (see .type.splay.compare.method):
-Compare FreeBlockCompare(void *key, SplayNode node) {
-  Addr base1, base2, limit2;
-  FreeBlock freeNode = FreeBlockOfSplayNode(node);
-
-  base1 = (Addr *)key;
-  base2 = freeNode->base;
-  limit2 = AddrAdd(base2, freeNode->size);
-
-  if (base1 < base2) 
-    return CompareLESS;
-  else if (base1 >= limit2)
-    return CompareGREATER;
-  else
-    return CompareEQUAL;
-}
-
-.usage.test.tree: Test tree function (see .type.splay.test.tree.method):
-Bool FreeBlockTestTree(SplayTree tree, SplayNode node
-                       void *closureP, unsigned long closureS) {
-  /* Closure environment has wanted size as value of closureS. */
-  /* Look at the cached value for the node to see if any */
-  /* blocks in the subtree are big enough. */
-
-  Size size = (Size)closureS;
-  FreeBlock freeNode = FreeBlockOfSplayNode(node);
-  return freeNode->maxSize >= size;
-}
-
-.usage.test.node: Test node function (see .type.splay.test.node.method):
-Bool FreeBlockTestNode(SplayTree tree, SplayNode node
-                       void *closureP, unsigned long closureS) {
-  /* Closure environment has wanted size as value of closureS. */
-  /* Look at the size of the node to see if is big enough. */
-
-  Size size = (Size)closureS;
-  FreeBlock freeNode = FreeBlockOfSplayNode(node);
-  return freeNode->size >= size;
-}
-
-.usage.initialization: Client's initialization function (see 
-.function.splay.tree.init):
-void FreeTreeInit(FreeTree tree) {
-  /* Initialize the embedded splay tree. */
-  SplayTreeInit(&tree->splayTree, FreeBlockCompare, FreeBlockUpdateNode);
-}
-
-.usage.insert: Client function to add a new free block into the tree, merging 
-it with an existing block if possible:
-void FreeTreeInsert(FreeTree tree, Addr base, Addr limit) {
-  SplayTree splayTree = &tree->splayTree;
-  SplayNode leftNeighbour, rightNeighbour;
-  void *key = (void *)base;  /* use the base of the block as the key */
-  Res res;
-
-  /* Look for any neighbouring blocks. (.function.splay.tree.neighbours) */
-  res = SplayTreeNeighbours(&leftNeighbour, &rightNeighbour, 
-                            splayTree, key);
-  AVER(res == ResOK);  /* this client doesn't duplicate free blocks */
-
-  /* Look to see if the neighbours are contiguous. */
-
-  if (leftNeighbour != NULL && 
-      FreeBlockLimitOfSplayNode(leftNeighbour) == base) {
-    /* Inserted block is contiguous with left neighbour, so merge it. */
-    /* The client housekeeping is left as an exercise to the reader. */
-    /* This changes the size of a block, which is the client */
-    /* property of the splay node. See .function.splay.node.refresh */
-    SplayNodeRefresh(tree, leftNeighbour, key);
-
-  } else if (rightNeighbour != NULL && 
-             FreeBlockBaseOfSplayNode(rightNeighbour) == limit) {
-    /* Inserted block is contiguous with right neighbour, so merge it. */
-    /* The client housekeeping is left as an exercise to the reader. */
-    /* This changes the size of a block, which is the client */
-    /* property of the splay node. See .function.splay.node.refresh */
-    SplayNodeRefresh(tree, rightNeighbour, key);
-
-  } else {
-    /* Not contiguous - so insert a new node */
-    FreeBlock newBlock = (FreeBlock)allocate(sizeof(FreeBlockStruct));
-    splayNode = &newBlock->splayNode;
-
-    newBlock->base = base;
-    newBlock->size = AddrOffset(base, limit);
-    SplayNodeInit(splayNode);  /* .function.splay.node.init */
-    /* .function.splay.tree.insert */
-    res = SplayTreeInsert(splayTree, splayNode, key);
-    AVER(res == ResOK);  /* this client doesn't duplicate free blocks */
-  }
-}
-
-.usage.delete: Client function to allocate the first block of a given size in 
-address order. For simplicity, this allocates the entire block:
-Bool FreeTreeAllocate(Addr *baseReturn, Size *sizeReturn,
-                      FreeTree tree, Size size) {
-  SplayTree splayTree = &tree->splayTree;
-  SplayNode splayNode;
-  Bool found;
-
-  /* look for the first node of at least the given size. */
-  /* closureP parameter is not used. See .function.splay.find.first.  */
-  found = SplayFindFirst(&splayNode, splayTree,
-                         FreeBlockTestNode, FreeBlockTestTree,
-                         NULL, (unsigned long)size);
-
-  if (found) {
-    FreeBlock freeNode = FreeBlockOfSplayNode(splayNode);
-    Void *key = (void *)freeNode->base;  /* use base of block as the key */
-    Res res;
-
-    /* allocate the block */
-    *baseReturn = freeNode->base;
-    *sizeReturn = freeNode->size;
-
-    /* remove the node from the splay tree - .function.splay.tree.delete */
-    res = SplayTreeDelete(splayTree, splayNode, key);
-    AVER(res == ResOK);  /* Must be possible to delete node */
-
-    /* Delete the block */
-    deallocate(freeNode, (sizeof(FreeBlockStruct));
-
-    return TRUE;
-
-  } else {
-    /* No suitable block */
-    return FALSE;
-  }
-}
-
-
-IMPLEMENTATION
-
-.impl: For more details of how splay trees work, see paper.st85(0). For more 
-details of how to implement operations on splay trees, see paper.sleator96(0). 
-Here we describe the operations involved.
-
-
-Top-Down Splaying
-
-.impl.top-down: The method chosen to implement the splaying operation is called 
-"top-down splay". This is described as "procedure top-down splay" in 
-paper.st85(0) - although the implementation here additionally permits attempts 
-to access items which are not known to be in the tree. Top-down splaying is 
-particularly efficient for the common case where the location of the node in a 
-tree is not known at the start of an operation. Tree restructuring happens as 
-the tree is descended, whilst looking for the node.
-
-.impl.splay: The key to the operation of the splay tree is the internal 
-function SplaySplay.  It searches the tree for a node with a given key and 
-returns whether it suceeded.  In the process, it brings the found node, or an 
-arbitrary neighbour if not found, to the root of the tree.  This 
-"bring-to-root" operation is performed top-down during the search, and it is 
-not the simplest possible bring-to-root operation, but the resulting tree is 
-well-balanced, and will give good amortised cost for future calls to 
-SplaySplay. (See paper.st85(0))
-
-.impl.splay.how: To perform this top-down splay, the tree is broken into three 
-parts, a left tree, a middle tree and a right tree. We store the left tree and 
-right tree in the right and left children respectively of a "sides" node to 
-eliminate some boundary conditions.  The initial condition is that the middle 
-tree is the entire splay tree, and the left and right trees are empty.  We also 
-keep pointers to the last node in the left tree, and the first node in the 
-right tree.  Note that, at all times, the three trees are each validly ordered, 
-and they form a partition with the ordering left, middle, right.  The splay is 
-then performed by comparing the middle tree with the following six cases, and 
-performing the indicated operations, until none apply.  
-
-.impl.splay.cases: Note that paper.st85(0)(Fig. 3) describes only 3 cases: zig, 
-zig-zig and zig-zag. The additional cases described here are the symmetric 
-variants which are respectively called zag, zag-zag and zag-zig. In the 
-descriptions of these cases, "root" is the root of the middle tree; node->left 
-is the left child of node; node->right is the right child of node. The 
-comparison operators (<, >, ==) are defined to compare a key and a node in the 
-obvious way by comparing the supplied key with the node's associated key.
-
-.impl.splay.zig: The "zig" case is where key < root, and either:
-  - key == root->left; 
-  - key < root->left && root->left->left == NULL; or
-  - key > root->left && root->left->right == NULL.
-
-The operation for the zig case is: link right (see .impl.link.right)
-
-.impl.splay.zag: The "zag" case is where key > root, and either:
-  - key == root->right; 
-  - key < root->right && root->right->left == NULL; or
-  - key > root->right && root->right->right == NULL.
-
-The operation for the zag case is: link left (see .impl.link.left)
-
-.impl.splay.zig.zig: The "zig-zig" case is where key < root && key < root->left 
-&& root->left->left != NULL.  The operation for the zig-zig case is: rotate 
-right (see .impl.rotate.right) followed by link right (see .impl.link.right).
-
-.impl.splay.zig.zag: The "zig-zag" case is where key < root && key > root->left 
-&& root->left->right != NULL.  The operation for the zig-zag case is: link 
-right (see .impl.link.right) followed by link left (see .impl.link.left).
-
-.impl.splay.zag.zig: The "zag-zig" case is where key > root && key < 
-root->right && root->right->left != NULL.  The operation for the zag-zig case 
-is: link left (see .impl.link.left) followed by link right (see 
-.impl.link.right).
-
-.impl.splay.zag.zag: The "zag-zag" case is where key > root && key > 
-root->right && root->right->right != NULL.  The operation for the zag-zag case 
-is: rotate left (see .impl.rotate.left) followed by link left (see 
-.impl.link.left).
-
-.impl.splay.terminal.null: A special terminal case is when root == NULL.  This 
-can only happen at the beginning, and cannot arise from the operations above.  
-In this case, the splay operation must return NULL, and "not found".
-
-.impl.splay.terminal.found: One typical terminal case is when key == root.  
-This case is tested for at the beginning, in which case "found" is returned 
-immediately. If this case happens as a result of other operations, the splay 
-operation is complete, the three trees are assembled (see .impl.assemble), and 
-"found" is returned.
-
-.impl.splay.terminal.not-found: The other typical terminal cases are:
-  - key < root && root->left == NULL; and 
-  - key > root && root->right == NULL.  
-In these cases, the splay operation is complete, the three trees are assembled 
-(see .impl.assemble), and "not found" is returned.
-
-.impl.rotate.left: The "rotate left" operation (see paper.st85(0) Fig. 1) 
-rearranges the middle tree as follows (where any of sub-trees A, B and C may be 
-empty):
-.impl.rotate.right: The "rotate right" operation (see paper.st85(0) Fig. 1) 
-rearranges the middle tree as follows (where any of sub-trees A, B and C may be 
-empty):
-.impl.link.left: The "link left" operation (see paper.st85(0) Fig. 11a for 
-symmetric variant) rearranges the left and middle trees as follows (where any 
-of sub-trees A, B, L and R may be empty):
-
-
-The last node of the left tree is now x.
-
-.impl.link.right: The "link right" operation (see paper.st85(0) Fig. 11a) 
-rearranges the middle and right trees as follows (where any of sub-trees A, B, 
-L and R may be empty):
-The first node of the right tree is now x.
-
-
-.impl.assemble: The "assemble" operation (see paper.st85(0) Fig. 12) merges the 
-left and right trees with the middle tree as follows (where any of sub-trees A, 
-B, L and R may be empty):
-
-
-
-Top-Level Operations
-
-.impl.insert: SplayTreeInsert: (See paper.sleator96(0), chapter 4, function 
-insert). If the tree has no nodes, [how does it smell?] add the inserted node 
-and we're done; otherwise splay the tree around the supplied key.  If the splay 
-successfully found a matching node, return failure.  Otherwise, add the 
-inserted node as a new root, with the old (newly splayed, but non-matching) 
-root as its left or right child as appropriate, and the opposite child of the 
-old root as the other child of the new root.
-
-.impl.delete: SplayTreeDelete: (See paper.sleator96(0), chapter 4, function 
-delete). Splay the tree around the supplied key.  Check that the newly splayed 
-root is the same node as given by the caller, and that it matches the key; 
-return failure if not.  If the given node (now at the root) has fewer than two 
-children, replace it (as root), with the non-null child or null.  Otherwise, 
-set the root of the tree to be the left child (arbitrarily) of the node to be 
-deleted, and splay around the same key.  The new root will be the last node in 
-the sub-tree and will have a null right child; this is set to be the right 
-child of the node to be deleted.
-
-.impl.search: SplayTreeSearch: Splay the node around the supplied key.  If the 
-splay found a matching node, return it; otherwise return failure.
-
-.impl.neighbours: SplayTreeNeighbours: Splay the tree around the supplied key.  
-If the splay found a matching node, return failure.  Otherwise, determine 
-whether the (non-matching) found node is the left or right neighbour of the key 
-(by comparison with the key).  Set the tree root to be the right or left child 
-of that first neighbour respectively, and again splay the tree around the 
-supplied key.  The new root will be the second neighbour, and will have a null 
-left or right child respectively.  Set this null child to be the first 
-neighbour.  Return the two neighbours.
-
-.impl.neighbours.note: Note that it would be possible to implement 
-SplayTreeNeighbours with only one splay, and then a normal binary tree search 
-for the left or right neighbour of the root.  This would be a cheaper 
-operation, but would give poorer amortised cost if the call to 
-SplayTreeNeighbours typically precedes a call to SplayTreeInsert (which is 
-expected to be a common usage pattern - see .usage.insert). It's also possible 
-to implement SplayTreeNeighbours by simply keeping track of both neighbours 
-during a single splay. This has about the same cost as a single splay, and 
-hence about the same amortised cost if the call to SplayTreeNeighbours typically precedes a call to 
-SplayTreeInsert.
-
-.impl.next: SplayTreeNext: Splay the tree around the supplied oldKey. During 
-iteration the "old node" found is probably already at the root, in which case 
-this will be a null operation with little cost.  If this old node has no right 
-child, return NULL. Otherwise, split the tree into a right tree (which contains 
-just the right child of the old node) and a left tree (which contains the old 
-node, its left child and no right child). The next node is the first node in 
-the right tree. Find this by splaying the right tree around oldKey (which is 
-known to compare CompareLESS than any keys in the right tree). Rejoin the full 
-tree, using the right tree as the root and setting the left child of root to be 
-the left tree. Return the root of this tree.
-
-TESTING
-
-.test: There is no plan to test splay trees directly.  It is believed that the 
-testing described in design.mps.cbs.test will be sufficient to test this 
-implementation.
-
-
-ERROR HANDLING
-
-.error: This module detects and reports most common classes of protocol error.  
-The cases it doesn't handle will result in undefined behaviour and probably 
-cause an AVER to fire.  These are:
-
-.error.bad-pointer: Passing an invalid pointer in place of a SplayTree or 
-SplayNode.
-
-.error.bad-compare: Initialising a SplayTree with a compare function that is 
-not a valid compare function, or which doesn't implement a total ordering on 
-splay nodes.
-
-.error.bad-describe: Passing an invalid describe method to SplayTreeDescribe.
-
-.error.out-of-stack: Stack exhaustion under SplayTreeDescribe.
-
-
-FUTURE
-
-.future.tree: It would be possible to split the splay tree module into two: one 
-that implements binary trees; and one that implements splay trees on top of a 
-binary tree.
-
-.future.parent: The iterator could be made more efficient (in an amortized 
-sense) if it didn't splay at each node.  To implement this (whilst meeting 
-.req.stack) we really need parent pointers from the nodes.  We could use the 
-(first-child, right-sibling/parent) trick described in paper.st85 to implement 
-this, at a slight cost to all other tree operations, and an increase in code 
-complexity.  paper.st85 doesn't describe how to distinguish the first-child 
-between left-child and right-child, and the right-sibling/parent between 
-right-sibling and parent.  One could either use the comparator to make these 
-distinctions, or steal some bits from the pointers.
-
-.future.reverse: The assembly phase could be made more efficient if the link 
-left and link right operations were modified to add to the left and right trees 
-with pointers reversed. This would remove the need for the assembly phase to 
-reverse them.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/sso1al/index.html b/mps/design/sso1al/index.html deleted file mode 100644 index 475f04385af..00000000000 --- a/mps/design/sso1al/index.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - -Stack scanner for Digital Unix / Alpha systems - - - - - - - -
-             STACK SCANNER FOR DIGITAL UNIX / ALPHA SYSTEMS
-                           design.mps.sso1al
-                               draft doc
-                             drj 1997-03-27
-
-INTRODUCTION
-
-.readership: Any MPS developer.
-
-.intro: This is the design for Stack Scanner module that runs on DIGITAL UNIX / 
-Alpha systems (See os.o1 and arch.al).  The design adheres to the general 
-design and interface described (probably not described actually) in 
-design.mps.ss.
-
-.source.alpha: book.digital96 (Alpha Architecture Handbook) describes the Alpha 
-Architecture independently of any particular implementation.  The instruction 
-mnemonics and the semantics for each instruction are specified in that document.
-.source.as: 
-<URL:http://www.partner.digital.com/www-swdev/pages/Home/TECH/documents/Digital_
-UNIX/V4.0/AA-PS31D-TET1_html/TITLE.html> (Assembly Language Programmer's Guide) 
-describes the assembler syntax and assembler directives.  It also summarises 
-the calling conventions used.  Chapters 1 and 6 were especially useful, 
-especially chapter 6.
-.source.convention: 
-<URL:http://www.partner.digital.com/www-swdev/pages/Home/TECH/documents/Digital_
-UNIX/V4.0/AA-PY8AC-TET1_html/TITLE.html> (Calling Standard for Alpha Systems) 
-describes the calling conventions used for Digital Alpha systems.  Chapter 2 was 
-useful.  But the whole document was not used as much as the previous 2 
-documents.
-
-
-DEFINITIONS
-
-.def.saved: Saved Register.  A saved register is one whose value is defined to 
-be preserved across a procedure call according to the Calling Standard.  They 
-are $9-$15, $26, and $30.  $30 is the stack pointer.
-.def.non-saved: Non-Saved Register.  A non-save register is a register that is 
-assumed to be modified across a procedure call according to the Calling 
-Standard.
-.def.tos: Top of Stack.  The top of stack is the youngest portion of the stack.
-.def.bos: Bottom of Stack.  The bottom of stack is the oldest portion of the 
-stack.
-.def.base: Base.  Of a range of addresses, the base is the lowest address in 
-the range.
-.def.limit: Limit.  Of a range of addresses, the limit is "one past" the 
-highest address in the range.
-
-
-OVERVIEW
-
-.overview: The registers and the stack need to be scanned.  This is achieved by 
-storing the contents of the registers into a frame at the top of the stack and 
-then passing the base and limit of the stack region, including the newly 
-created frame, to the function TraceScanAreaTagged.  TraceScanAreaTagged 
-performs the actual scanning and fixing.
-
-
-DETAIL DESIGN
-
-Functions
-
-.fun.stackscan:
-
-Res StackScan(ScanState ss, Addr *StackBot);
-
-.fun.stackscan.asm: The function is written in assembler.  
-.fun.stackscan.asm.justify: This is because the machine registers need to be 
-examined, and it is only possible to access the machine registers using 
-assembler.
-.fun.stackscan.entry: On entry to this procedure all the non-saved (temporary) 
-registers that contain live pointers must have been saved in some root (usually 
-the stack) by the mutator (otherwise it would lose the values).  Therefore only 
-the saved registers need to be stored by this procedure.
-.fun.stackscan.assume.saved: We assume that all the saved registers are roots.  
-This is conservative since some of the saved registers might not be used.
-.fun.stackscan.frame: A frame is be created on the top of the stack.  
-.fun.stackscan.frame.justify: This frame is used to store the saved registers 
-into so that they can be scanned.
-.fun.stackscan.save: All the saved registers, apart from $30 the stack pointer, 
-are to be stored in the frame.  .fun.stackscan.save.justify: This is so that 
-they can be scanned.  The stack pointer itself is not scanned as the stack is 
-assumed to be a root (and therefore a priori alive).
-.fun.stackscan.call: TraceScanAreaTagged is called with the current stack 
-pointer as the base and the (passed in) StackBot as the limit of the region to 
-be scanned.   .fun.stackscan.call.justify: This function does the actual 
-scanning.  The Stack on Alpha systems grows down so the stack pointer (which 
-points to the top of the stack) is lower in memory than the bottom of the stack.
-.fun.stackscan.return: The return value from TraceScanAreaTagged is used as the 
-return value for StackScan.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/telemetry/index.html b/mps/design/telemetry/index.html deleted file mode 100644 index 81f61cedf93..00000000000 --- a/mps/design/telemetry/index.html +++ /dev/null @@ -1,506 +0,0 @@ - - - - - - - - -The design of the MPS telemetry mechanism - - - - - - - -
-               THE DESIGN OF THE MPS TELEMETRY MECHANISM
-                          design.mps.telemetry
-                           incomplete design
-                           richard 1997-07-07
-
-
-INTRODUCTION:
-
-This documents the design of the telemetry mechanism within the MPS.
-
-.readership: This document is intended for any MPS developer.
-
-.source: Various meetings and brainstorms, including 
-meeting.general.1997-03-04(0), mail.richard.1997-07-03.17-01(0), 
-mail.gavinm.1997-05-01.12-40(0).
-
-
-Document History
-
-.hist.0: 1997-04-11  GavinM  Rewritten
-
-.hist.1: 1997-07-07  GavinM  Rewritten again after discussion in Pool Hall.
-
-
-OVERVIEW:
-
-Telemetry permits the emission of events from the MPS.  These can be used to 
-drive a graphical tool, or to debug, or whatever.  The system is flexible and 
-robust, but doesn't require heavy support from the client.
-
-
-REQUIREMENTS:
-
-.req.simple: It must be possible to generate code both for the MPS and any tool 
-without using complicated build tools.
-
-.req.open: We must not constrain the nature of events before we are certain of 
-what we want them to be.
-
-.req.multi: We must be able to send events to multiple streams.
-
-.req.share: It must be possible to share event descriptions between the MPS and 
-any tool.
-
-.req.version: It must be possible to version the set of events so that any tool 
-can detect whether it can understand the MPS.
-
-.req.back: Tools should be able to understand older and newer version of the 
-MPS, so far as is appropriate.
-
-.req.type: It must be possible to transmit a rich variety of types to the tool, 
-including doubles, and strings.
-
-.req.port: It must be possible to transmit and receive events between different 
-platforms.
-
-.req.control: It must be possible to control whether and what events are 
-transmitted at least at a coarse level.
-
-.req.examine: There should be a cheap means to examine the contents of logs.
-
-.req.pm: The event mechanism should provide for post mortem to detect what 
-significant events led up to death.
-
-.req.perf: Events should not have a significant effect on performance when 
-unwanted.
-
-.req.small: Telemetry streams should be small.
-
-.req.avail: Events should be available in all varieties, subject to performance 
-requirements.
-
-.req.impl: The plinth support for telemetry should be easy to write and 
-flexible.
-
-.req.robust: The telemetry protocol should be robust against some forms of 
-corruption, e.g. packet loss.
-
-.req.intern: It should be possible to support string-interning.
-
-
-ARCHITECTURE:
-
-.arch: Event annotations are scattered throughout the code, but there is a 
-central registration of event types and properties.  Events are written to a 
-buffer via a specialist structure, and are optionally written to the plinth.  
-Events can take any number of parameters of a range of types, indicated as a 
-format both in the annotation and the the registry.
-
-
-ANALYSIS:
-
-.anal: The proposed order of development, with summary of requirements impact 
-is as follows:
-
-                        v      c e 
-               s        e      o x             r  i
-               i   m  s r      n a      s  a   o  n
-               m o u  h s t  p t m    p m  v i b  t b
-               p p l  a i y  o r i    e a  a m u  e a
-               l e t  r o p  r o n  p r l  i p s  r c
-               e n i  e n e  t l e  m f l  l l t  n k
-
-.sol.format    0 0 0  0 0 +  0 0 0  0 0 0  0 0 0  0 0  Merged.
-.sol.struct    0 0 0  0 0 +  0 0 0  0 + -  0 0 0  0 0  Merged.
-.sol.string    0 0 0  0 0 +  0 0 0  0 0 0  0 0 0  + 0  Merged.
-.sol.relation  + 0 0  + 0 0  0 0 +  0 0 +  0 0 0  0 0  Merged.
-.sol.dumper    0 0 0  0 0 0  0 0 +  0 0 0  0 0 0  0 0  Merged.
-.sol.kind      0 - 0  0 0 0  0 + 0  + 0 0  0 0 0  0 0  Merged.
-.sol.control   0 0 0  0 0 0  0 + 0  0 + 0  0 0 0  0 0  Merged.
-
-.sol.variety   0 0 0  0 0 0  0 0 0  + + 0  + 0 0  0 0
-
-[ Not yet ordered. ]
-
-.sol.buffer    0 0 0  0 0 0  0 + 0  + + 0  0 0 0  0 0
-.sol.traceback 0 0 0  0 0 0  0 0 0  + 0 0  0 0 0  0 0
-.sol.client    0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  + 0
-.sol.head      0 0 0  0 0 0  + 0 0  0 0 0  0 0 0  0 0
-.sol.version   0 0 0  0 + 0  0 0 0  0 0 0  0 0 0  0 +
-.sol.exit      0 0 0  0 0 0  0 0 0  + 0 0  0 0 0  0 0
-.sol.block     0 0 0  0 0 0  0 0 0  0 + -  0 0 +  0 0 
-.sol.code      0 0 0  0 0 0  0 0 0  0 0 +  0 0 0  0 +
-.sol.msg       0 0 +  0 0 0  + 0 0  0 0 0  0 + +  0 0
-
-.file-format: One of the objectives of this plan is to minimise the impact of 
-the changes to the log file format.  This is to be achieved firstly by 
-completing all necessary support before changes are initiated, and secondly by 
-performing all changes at the same time.
-
-
-IDEAS:
-
-.sol.format: Event annotations indicate the types of their arguments, e.g. 
-EVENT_WD for a Word, and a double.  (.req.type)
-
-.sol.struct: Copy event data into a structure of the appropriate type, e.g. 
-EventWDStruct.  (.req.type, .req.perf, but not .req.small because of padding)
-
-.sol.string: Permit at most one string per event, at the end, and use the char 
-[1] hack, and specialised code; deduce the string length from the event length 
-and also NUL-terminate  (.req.type, .req.intern)
-
-.sol.buffer: Enter all events initially into internal buffers, and 
-conditionally send them to the message stream. (.req.pm, .req.control, 
-.req.perf)
-
-.sol.variety: In optimized varieties, have internal events (see .sol.buffer) 
-for a subset of events and no external events; in normal varieties have all 
-internal events, and the potential for external events.  (.req.avail, .req.pm, 
-.req.perf)
-
-.sol.kind: Divide events by some coarse type into around 6 groups, probably 
-related to frequency.  (.req.control, .req.pm, but not .req.open)
-
-.sol.control: Hold flags to determine which events are emitted externally.  
-(.req.control, .req.perf)
-
-.sol.dumper: Write a simple tool to dump event logs as text.  (.req.examine)
-
-.sol.msg: Redesign the plinth interface to send and receive messages, based on 
-any underlying IPC mechanism, e.g. append to file, TCP/IP, messages, shared 
-memory.  (.req.robust, .req.impl, .req.port, .req.multi)
-
-.sol.block: Buffer the events and send them as fixed size blocks, commencing 
-with a timestamp, and ending with padding.  (.req.robust, .req.perf, but not 
-.req.small)
-
-.sol.code: Commence each event with two bytes of event code, and two bytes of 
-length.  (.req.small, .req.back)
-
-.sol.head: Commence each event stream with a platform-independent header block 
-giving information about the session, version (see .sol.version), and file 
-format; file format will be sufficient to decode the (platform-dependent) rest 
-of the file.  (.req.port)
-
-.sol.exit: Provide a mechanism to flush events in the event of graceful sudden 
-death.  (.req.pm)
-
-.sol.version: Maintain a three part version number for the file comprising 
-major (incremented when the format of the entire file changes (other than 
-platform differences)), median (incremented when an existing event changes its 
-form or semantics), and minor (incremented when a new event type is added); 
-tools should normally fail when the median or major is unsupported.  
-(.req.version, .req.back)
-
-.sol.relation: Event types will be defined in terms of a relation specifying 
-their name, code, optimised behaviour (see .sol.variety), kind (see .sol.kind), 
-and format (see .sol.format); both the MPS and tool can use this by suitable 
-#define hacks.  (.req.simple. .req.share, .req.examine, .req.small (no format 
-information in messages))
-
-.sol.traceback: Provide a mechanism to output recent events (see .sol.buffer) 
-as a form of backtrace when AVERs fire or from a debugger, or whatever. 
-(.req.pm)
-
-.sol.client: Provide a mechanism for user events.  (.req.intern)
-
-
-
-IMPLEMENTATION:
-
-Annotation
-
-.annot: An event annotation is of the form:
-  EVENT3(FooCreate, pointer, address, word);
-
-.annot.string: If there is a string in the format, it must be the last 
-parameter (and hence there can be only one).  There is currrently a maximum 
-string length, defined by EventMaxStringLength in impl.h.eventcom.
-
-.annot.type: The event type should be given as the first parameter to the event 
-macro, as registered in impl.h.eventdef.
-
-.annot.param: The parameters of the event should be given as the remaining 
-parameters of the event macro, in order as indicated in the event parameters definition in impl.h.eventdef.
-
-
-Registration
-
-.reg: All event types and parameters should
-be registered in impl.h.eventdef, in the form of a higher-order list
-macros.
-
-.reg.just: This use of a higher-order macros enables great flexibility in the use of 
-this file.
-
-.reg.rel: The event type registration is of the form:
-  EVENT(X, FooCreate, 0x1234, TRUE, Arena)
-
-.reg.type: The first parameter of the relation is the event type.  This needs 
-no prefix, and should correspond to that used in the annotation.
-
-.reg.code: The second parameter is the event code, a 16-bit value used to 
-represent this event type.  Codes should not be re-used for new event types, to allow interpretation of event
-log files of all ages.
-
-.reg.always: The third parameter is a boolean value indicating whether this 
-event type should be implemented in all varieties.  See .control.buffer.  
-Unless your event is on the critical path (typically per reference or per 
-object), you will want this to be TRUE.
-
-.reg.kind: The fourth parameter is a kind keyword indicating what category this 
-event falls into.  See .control.  The possible values are:
-  Arena -- per space or arena or global
-  Pool -- pool-related
-  Trace -- per trace or scan
-  Seg -- per segment
-  Ref -- per reference or fix
-  Object -- per object or allocation
-  User -- invoked by the user through the MPS interface
-This list can be seen in impl.h.eventcom.
-
-[.reg.doc: Add a docstring column.  RB 2012-09-03]
-
-.reg.params: The event parameters registration is of the form:
-
-  #define EVENT_FooCreate_PARAMS(PARAM, X) \
-    PARAM(X,  0, P, firstParamPointer) \
-    PARAM(X,  1, U, secondParamUnsigned)
-
-.reg.param.index: The first column is the index, and must start at zero
-and increase by one for each row.
-
-.reg.param.sort: The second column is the parameter "sort", which, when
-appended to EventF, yields a type for the parameter.  It is a letter from the following list:
-  P -- void *
-  A -- Addr
-  W -- Word
-  U -- unsigned int
-  S -- char *
-  D -- double
-  B -- Bool
-The corresponding event parameter must be assignment compatible with the type.
-
-.param.types: When an event has parameters whose type is not in the above 
-list, use the following guidelines: All C pointer types not representing 
-strings use P; Size, Count, Index use W; others should be obvious.
-
-.reg.param.name: The third column is the parameter name.  It should be a valid C identifier
-and is used for debugging display and human readable output.
-
-[.reg.param.doc: Add a docstring column.  RB 2012-09-03]
-
-.reg.dup: It is permissible for the one event type to be used for more than one 
-annotation.  There are generally two reasons for this:
-  - Variable control flow for successful function completion;
-  - Platform/Otherwise-dependent implementations of a function.
-Note that all annotations for one event type must have the same format (as 
-implied by .reg.format).
-
-
-Control
-
-.control: There are two types of event control, buffer and output.
-
-.control.buffer: Buffer control affects whether particular events implemented 
-at all, and is controlled statically by variety using the always value (see 
-.reg.always) for the event type.  The hot variety does compiles out annotations
-with always=FALSE.  The cool variety does not, so always buffers a complete
-set of events.
-
-.control.output: Output control affects whether events written to the internal 
-buffer are output via the plinth.  This is set on a per-kind basis (see 
-.reg.kind), using a control bit table stored in EventKindControl.  By default, 
-all event kinds are off.  You may switch some kinds on using a 
-debugger.
-
-For example, to enable Pool events using gdb (see impl.h.eventcom for numeric 
-codes):
-
-    rb@silverbird$ gdb ./xci3gc/cool/amcss
-    (gdb) break GlobalsInit
-    (gdb) run
-    ...
-    (gdb) print EventKindControl |= 2
-    $2 = 2
-    (gdb) continue
-    ...
-    (gdb) quit
-    rb@silverbird$ ./xci3gc/cool/eventcnv -v | sort | head
-    0000178EA03ACF6D PoolInit                9C1E0    9C000 0005E040
-    0000178EA03C2825 PoolInitMFS             9C0D8    9C000     1000        C
-    0000178EA03C2C27 PoolInitMFS             9C14C    9C000     1000       44
-    0000178EA03C332C PoolInitMV              9C080    9C000     1000       20    10000
-    0000178EA03F4DB4 BufferInit             2FE2C4   2FE1B0        0
-    0000178EA03F4EC8 BufferInitSeg          2FE2C4   2FE1B0        0
-    0000178EA03F57DA AMCGenCreate           2FE1B0   2FE288
-    0000178EA03F67B5 BufferInit             2FE374   2FE1B0        0
-    0000178EA03F6827 BufferInitSeg          2FE374   2FE1B0        0
-    0000178EA03F6B72 AMCGenCreate           2FE1B0   2FE338
-
-.control.env: The initial value of EventKindControl is read from the C environment
-when the ANSI Plinth is used, and so event output can be controlled like this:
-
-  MPS_TELEMETRY_CONTROL=127 amcss
-
-or like this
-
-  MPS_TELEMETRY_CONTROL="Pool Arena" amcss
-
-where the variable is set to a space-separated list of names defined by EventKindENUM.
-
-.control.just: These controls are coarse, but very cheap.
-
-.control.external: The MPS interface function mps_telemetry_control
-can be used to change EventKindControl.
-
-.control.tool: The tools will be able to control EventKindControl.
-
-
-Debugging
-
-.debug.buffer: Each event kind is logged in a separate buffer, EventBuffer[kind].
-
-.debug.buffer.reverse: The events are logged in reverse order from the top of the buffer, with the last logged
-event at EventLast[kind].  This allows recovery of the list of recent events using the event->any.size field.
-
-.debug.dump: The contents of all buffers can be dumped with the EventDump function from a debugger, e.g.
-
-  gdb> print EventDump(mps_lib_get_stdout())
-
-.debug.describe: Individual events can be described with the EventDescribe function, e.g.
-
-  gdb> print EventDescribe(EventLast[3], mps_lib_get_stdout())
-
-.debug.core: The event buffers are preserved in core dumps and can be used
-to work out what the MPS was doing before a crash.  Since the kinds correspond
-to frequencies, ancient events may still be available in some buffers, even
-if they have been flushed to the output stream.  Some digging may be required.
-
-
-Dumper Tool
-
-.dumper: A primitive dumper tool is available in impl.c.eventcnv.  For details, 
-see guide.mps.telemetry.
-
-
-Allocation Replayer Tool
-
-.replayer: A tool for replaying an allocation sequence from a log is available 
-in impl.c.replay.  For details, see design.mps.telemetry.replayer.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
2012-09-03RBRemoved basic untruths and added some discussion of debugging, though this starts to resemble a manual rather than a design document, and needs to be reworked.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/template-with-guide.html b/mps/design/template-with-guide.html deleted file mode 100644 index 56ed9a8e5dc..00000000000 --- a/mps/design/template-with-guide.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - -MODULE_LONG_NAME - - - - - - - -

This document contains a guide to the MODULE_LONG_NAME, followed by the historical initial design. References, History, Copyright and License are at the end.

- -
- -

Guide

- -

Readership: any MPS developer. Not confidential.

- -

Introduction

-

- ....etc.... -

- - -
- -

Initial Design

- - -
-                           MODULE_LONG_NAME
-                           design.mps.MODULE
-                            incomplete doc
-                             ....etc....
-
-
-
- -
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - -
2007-03-22RHSKCreate template for design docs with a prefixed Guide.
- - -

C. Copyright and License

- -

This document is copyright © 2007 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/tests/index.html b/mps/design/tests/index.html deleted file mode 100644 index db92950b18b..00000000000 --- a/mps/design/tests/index.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - -MPS Internal Tests - - - - - - - -

This document contains a guide to the MPS Internal Tests. There is no historical initial design, but there is a placeholder for early ideas and discussions: initial ideas. References, History, Copyright and License are at the end.

- -
- -

Guide

- -

Readership: any MPS developer. Not confidential.

- -

zmess.c

- -

Tests message lifecycle, and finalization (by using finalization messages).

- - -

zcoll.c

- -

Tests collection scheduling, and collection feedback.

- - -

Finalization Tests

- -

There are three main ones:

-
-
finalcv.c
-
Oldest. Registers a few objects (for finalization) and pseudorandomly makes them unreachable, deregisters them, etc. Churns to provoke minor (nursery) collection.
-
finaltest.c
-
Uses newer fmtdytst facilities. Creates a large binary tree, and registers every node. Drops top ref, requests collection, and counts the messages.
-
fin1658a.c -- deleted
-
[Subsumed into and replaced by zmess.c, 2009-02-17]. fin1658a.c was a single-issue test: see job001658. Drops refs and requests collection. Verifies that all non-E-reachable registered objects are finalized in a single collection, even if there are >1 segs of poolmrg guardians.
-
- -

There's also expt825.c, which verifies that protection expose/remember works correctly for poolmrg (scanned but not GC'd segs); see job000825.

- -
- -

Initial Ideas

- -

There never was an initial design document. This is a placeholder for links to early ideas and discussions.

- -
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - - - - - - - - - -
2008-12-04RHSKCreate. Describe finalization tests.
2010-03-03RHSKCorrection: it's fin1658a.c and job001658, not 1638.
2010-03-03RHSKAdd zmess.c, zcoll.c. zmess.c subsumes and replaces fin1658a.c.
- - -

C. Copyright and License

- -

This document is copyright © 2008, 2010 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/thread-manager/index.html b/mps/design/thread-manager/index.html deleted file mode 100644 index c9450d963fa..00000000000 --- a/mps/design/thread-manager/index.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - - -The design of the MPS thread manager - - - - - - - -
-                  THE DESIGN OF THE MPS THREAD MANAGER
-                       design.mps.thread-manager
-                           incomplete design
-                           richard 1995-11-20
-
-PURPOSE
-
-The Thread Manager handles various thread-related functions required by the 
-MPS.  These are:
-
-  - stack scanning
-
-  - suspension and resumption of the mutator threads
-
-CONTEXT
-
-The barrier requires suspension and resumption of threads in order to ensure 
-that the collector has exclusive access to part of memory.  
-[design.mps.barrier.@@@]
-
-Stack scanning is provided as a service to the client.  [Link?@@@]
-
-OVERVIEW
-
-Each thread is represented by an object of type "Thread".  The Thread type is 
-implemented as an ADT.  A deque of Thread objects is maintained in the Space.  
-The Thread object contains OS dependent information about the thread -- 
-information necessary for manipulating the thread and for scanning the thread 
-context.  Thread "registration" adds or removes the current thread to the 
-Thread deque in the Space.
-
-DETAILED DESIGN
-
-Stack Scan
-This is a module providing a stack scanning function.  The scanning is arch/os 
-dependent.  Typically the function will push the save registers (those 
-preserved across function calls) which plausibly contain pointers (not FP/debug 
-registers) and call TraceScanStack on the appropriate range.
-
-Thread Interface
-
-- Register/Deregister
-  register returns "Thread"
-
-- Suspend/Resume
-  suspends registered threads which are not the current thread
-
-- ThreadDequeScan
-  ambiguously scans the stacks and root registers of all threads.  The exact 
-definition is os/arch dependent
-
-Single-Threaded Generic Implementation
-
-- single thread
-- Suspend/Resume do nothing because there are no other threads.
-- registration records stack base only.
-- ThreadDequeScan calls StackScan
-
-Win32 Implementation
-- supports multiple threads
-- structured exception style faults are expected
-- suspend/resume loop over threads and call Win32 suspend/resume
-- registration records information for current thread
-  - stack base for current thread
-  - Win32 "handle" with SUSPEND/RESUME and GET CONTEXT access to the thread.  
-This handle is needed as parameter to
-    - Suspend/ResumeThread
-    - ThreadGetContext
-  - Win32 ThreadId this is so that the current thread may be identified.
-- stack scanning is Win32 specific
-  - ThreadDequeScan uses GetThreadContext for other threads, giving root 
-registers and the stack pointer
-  - The thread's registers are dumped into the CONTEXT structure and fixed in 
-memory.
-  - scan the stack (getting sp from CONTEXT)
-  - ThreadDequeScan calls StackScan to do the current thread.  The current 
-thread is different because GetContext doesn't work on it.   (The context would 
-not necessarily have the values which were in the saved registers on entry to 
-the MM).
-
-ISSUES
-
-Scanning after Exceptions
-StackScan relies on the non-preserved registers having been pushed on the 
-stack.  If we want to scan after a fault we must make sure that these registers 
-are either already stored on the stack, or, have an extra function to do this 
-explicitly.
-
-Multiple Registration
-It is not clear whether a thread should be allowed to be registered multiple 
-times.  We do not provide a mechanism for knowing whether a thread is already 
-registered with a space.
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-21RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/thread-safety/index.html b/mps/design/thread-safety/index.html deleted file mode 100644 index a701c7f58cb..00000000000 --- a/mps/design/thread-safety/index.html +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - -Thread Safety in the MPS - - - - - - - -
-                        THREAD SAFETY IN THE MPS
-                        design.mps.thread-safety
-                           incomplete design
-                             dsm 1995-10-03
-
-
-INTRODUCTION:
-
-This describes how Thread Safety is achieved in the MPS
-
-
-OVERVIEW:
-
-The MPS is expected to run in an environment with multiple threads all calling 
-into the MPS.  The initial approach is very simple.  Some of the code is known 
-to operate with exclusive access to the data it manipulates, so this code is 
-safe.  For the rest of the code, shared data structures are locked by the use 
-of a single binary lock (design.mps.lock(0)) per arena.  This lock is claimed 
-on entry to the MPS and released on exit from it.  So there is at most a single 
-thread (per arena) running "inside" the MPS at a time.
-
-
-REQUIREMENTS:
-
-.req.mt: Code must work correctly in presence of multiple threads all calling 
-into the MPS.
-
-.req.perf: Performance should not be unreasonably hindered.
-
-
-ARCHITECTURE:
-
-.arch.arena: Arena Lock: no shared data between arenas
-.arch.global.binary: Global binary lock: protects mutable data shared between 
-arenas - i.e. the arena ring, see design.mps.arena.static.ring.lock.
-.arch.global.recursive: Global recursive lock: protects static data which must 
-be initialized once - e.g. pool classes, see design.mps.protocol.impl.init-lock
-.
-.arch.other: Other: data not shared
-.arch.static: static data: sigs: shared-non-mutable always inited to same thing.
-
-.arena-entry: Each arena has a single lock.
-Externally visible calls fall into two categories.
-Simple: arena lock not held.  Lock is claimed on entry, and released on exit.
-Recall: These are callable only after a call-back from the MPS.  In this case a 
-arena lock is already held.
-
-.interface: The definition of the interface should guarantee safe use of calls 
-(from a locking point of view).  For example, a buffer must be exclusive to a 
-thread.
-
-.buffers: The buffer code is designed not to need a lock in the fast case.  A 
-lock is only claimed on the exceptional reserve, trip and commit cases (fill 
-and trip?).  A buffer contains references to shared data (via pool field).  
-Accessing this shared data must involve a lock.  
-
-.deadlock: A strict ordering is required between the global and arena locks to 
-prevent deadlock. The binary global lock may not be claimed while either the 
-arena or recursive global lock is held; the arena lock may not be claimed while 
-the recursive global lock is held. Each arena lock is independent of all other 
-arena locks; i.e. a thread may not attempt to claim more than one arena lock at 
-a time.
-
-
-
-ANALYSIS:
-
-.anal.simple: To have the code functioning correctly it should be easy to 
-change correctly.  So a simple approach is desirable.  We have to also ensure 
-that performance is not unreasonably downgraded.  
-
-Performance cost of Locking
-
-.lock-cost:  The cost of locking in performance terms are:
-.lock-cost.overhead: the overhead of claiming and releasing locks.
-.lock-cost.pause: the pauses caused by one thread being blocked on another 
-thread.
-.lock-cost.wait: the time wasted by one thread being blocked on another thread.
-
-.anal.perf.signif: .lock-cost.pause is significant if there are MPS functions 
-that take a long time.  Using more locks, e.g. having a lock per pool as well 
-as a lock per arena, is a way of decreasing the locking conflict between 
-threads (.lock-cost.pause and .lock-cost.wait).  However this could increase 
-.lock-cost.overhead significantly.
-
-.anal.perf.work: But all MPS functions imply a small work-load unless a 
-collection is taking place.  In the case of a collection, in practice and 
-certainly in the near future, all threads will most likely be suspended while 
-the collection work is going on.  (The pages being scanned will need to be 
-unprotected which implies the mutator will have to be stopped.)  We also have 
-to remember that unless we are running on genuine multiprocessor 
-.lock-cost.wait is irrelevant.
-
-.anal.perf.alloc: During typical use we expect that it is allocation that is 
-the most frequent activity.  Allocation buffers (design.mps.buffer) are 
-designed to allow allocation in concurrent threads without needing a lock.  So 
-the most significant time a thread spends in the MPS will be on a buffer-fill 
-or during a collection.  The next most significant use is likely to be buffer 
-create and deletion, as a separate buffer will be required for each thread.
-
-.anal.perf.lock: So overall the performance cost of locking is, I estimate, 
-most significantly the overhead of calling the locking functions.  Hence it 
-would be undesirable from a performance point of view to have more than one 
-lock.
-
-Recursive vs Binary locks
-
-.anal.reentrance: The simplest way to lock the code safely is to define which 
-code runs inside or outside the lock.  Calling from the outside to the inside 
-implies a lock has to be claimed.  Returning means the lock has to be 
-released.  Control flow from outside to outside and from inside to inside needs 
-no locking action.  To implement this a function defined on the external 
-interface needs to claim the lock on entry and release it on exit.  Our code 
-currently uses some external functions with the lock already held.  There are 
-two ways to implement this:
-
-.recursive: Each external function claims a recursive lock.
-+ simple
-- have to worry about locking depth
-- extra locking overhead on internal calls of external functions
-
-.binary: Each external function claims a binary lock.  Replace each internal 
-call of an external function with a call to a newly defined internal one.
-- more code
-+ slightly easier to reason about
-
-.anal.strategy: It seems that the .recursive strategy is the easiest to 
-implement first, but could be evolved into a .binary strategy.  (That evolution 
-has now happened.  tony 1999-08-31).
-
-
-
-
-
-IDEAS:
-
-.sol.arena-lock: Lock per arena which locks all MPS structures associated with 
-the arena, except allocation buffers.
-
-.sol.init: Shared static data may not be changed.  It is initialised before 
-being read, and if re-initalised the values written must be identical to those 
-already there.  Essentially only read-only shared static data is allowed.
-
-.sol.fine-grain: Use finer grained locks, e.g. a lock per per pool instance.  
-Arena lock locks only operations on arena.  Pool locks are claimed per pool.  
-An ordering on pool instances would avoid deadlock.
-
-.sol.global: Use global locks for genuinely global data which must be updated 
-dynamically. An ordering between global and arena locks would avoid deadlock.
-
-
-
-IMPLEMENTATION:
-
-Use MPS locks (design.mps.lock) to do locking.
-
-Locking Functions
-
-ArenaEnter/ArenaLeave are used to claim and release the arena lock.  To 
-implement this:
-- there is a lock for every arena. The arena class init function allocates the 
-lock as well as the arena itself.
-- ArenaInit LockInits the lock and initializes the pointer to it from the arena.
-- ArenaDestroy LockFinishs it.
-- ArenaEnter function for claiming the lock
-- ArenaLeave function for releasing the lock
-
-Shared and Non-Shared Data
-
-non-shared data is data for which no other thread has a handle on it.
-shared-non-mutable data is data which is never changed after initialisation.  
-It may be re-initialised, if re-initialisation does not change its value.
-atomically updatable data is data which is not locked, but may be shared 
-because it is in a consistent state before and after an update.
-
-A function is "safe" if it may safely execute without exclusive access to the 
-data it manipulates.
-
-A "safe" function may:
-- call other safe functions
-- manipulate non-shared data
-- read shared-non-mutable data
-- claim the arena lock around code which may manipulate shared data in the 
-arena.
-
-For each function in the external MPS interface either
-- the function ArenaEnter on entry and ArenaLeave on exit
-- the function uses PoolArena to identify the arena, before claiming the lock
-- the function uses BufferPool & PoolArena to identify the arena, before 
-claiming the lock
-- the function is not defined as external but is listed for explicitness.
-- only claim the lock in otherwise unsafe situations (buffer code)????
-- the function may be called externally but only in a situation where the arena 
-lock is already held
-- the function is the unique accessor of its data.
-
-So PoolArena and BufferPool must be "safe".
-pool->arena is shared-non-mutable
-buffer->pool is shared-non-mutable
-
-Validation
-
-We have to be careful about validation.  Any function that is called from a 
-arena-safe function without the arena-lock held, must itself be safe, or 
-manipulating non-shared data.
-For example calling PoolIsValid before claiming the lock would be wrong if 
-PoolIsValid is unsafe.  Defining it to be safe would involve locking it, which 
-if done in all similar situations would be very expensive.
-
-Possibly remove validation from accessor methods; replace with sig check and 
-isvalid calls in callers of accessor functions.
-
-Annotations?:
-  safe
-  non-shared
-  shared-non-mutable
-
-Safe functions:
-
-Arena
-  ArenaCreate      no shared data; no lock; calls LockInit
-  ArenaDestroy     no shared data; no lock (should only finish arena after 
-use); calls LockFinish
-  ArenaDescribe    lock
-
-Root
-For the purposes of locking this module can be thought of as external.  
-  RootCreate       calls create
-  RootCreateTable  calls create
-  create           lock
-  RootDestroy      lock
-  RootDescribe     lock
-
-will be attached to arena, can lock now.
-
-
-Pool               
-  PoolCreate / PoolCreateV   lock (Create calls CreateV which locks).
-  PoolDestroy      lock
-  PoolAlloc        lock
-  PoolFree         lock
-  PoolArena        accesses shared-non-mutable data only
-  PoolDescribe     lock
-
-Format
-  FormatCreate   lock
-  FormatDestroy  lock
-
-Buffer
-  BufferCreate   lock
-  BufferDestroy  lock
-  BufferFill     lock
-  BufferTrip     lock
-  BufferPool     accesses shared-non-mutable data only
-  BufferDescribe lock
-  BufferCommit   "unsafe": buffer may be used by single thread only. (but safe 
-wrt arena)
-  BufferReserve  "unsafe": also
-
-
-PoolClass      -- only shared data is static and non-mutable
-  PoolClass
-  PoolClassAMC
-  PoolClassMV
-  PoolClassMFS
-
-Sig            -- as with PoolClasses, relies on static data reinitialised to 
-constant value
-
-Collect
-  Collect           lock
-
-Thread
-  ThreadRegister    lock
-  ThreadDeregister  lock
-
-
-
-
- -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-21RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © #YEAR# Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/trace/index.html b/mps/design/trace/index.html deleted file mode 100644 index 9ecf34392b5..00000000000 --- a/mps/design/trace/index.html +++ /dev/null @@ -1,326 +0,0 @@ - - - - - - - - -Tracer - - - - - - - -

Status

- -

This document is currently a mixture of very old design notes (the -preformatted section immediately following) and some newer stuff. It -doesn't yet form anything like a complete picture. -

- -
-                                 TRACER
-                            design.mps.trace
-                           incomplete design
-                             drj 1996-09-25
-
-
-ARCHITECTURE:
-
-.instance.limit: There will be a limit on the number of traces that can be 
-created at any one time.  This effectively limits the number of concurrent 
-traces.  This limitation is expressed in the symbol TRACE_MAX [currently set to 
-1, see request.mps.160020 "Multiple traces would not work"  drj 1998-06-15].
-
-.rate: [see mail.nickb.1997-07-31.14-37].  [Now revised?  See 
-request.epcore.160062 and change.epcore.minnow.160062.  drj 1998-06-15]
-
-.exact.legal: Exact references should either point outside the arena (to 
-non-managed address space) or to a tract allocated to a pool.  Exact references 
-that are to addresses which the arena has reserved but hasn't allocated memory 
-to are illegal (the exact reference couldn't possibly refer to a real object).  
-Depending on the future semantics of PoolDestroy we might need to adjust our 
-strategy here.  See mail.dsm.1996-02-14.18-18 for a strategy of coping 
-gracefully with PoolDestroy.  We check that this is the case in the fixer.  It 
-may be sensible to make this check CRITICAL in certain configurations.
-
-.fix.fixed.all: ss->fixedSummary is accumulated (in the fixer) for all the 
-pointers whether or not they are genuine references.  We could accumulate fewer 
-pointers here; if a pointer fails the TractOfAddr test then we know it isn't a 
-reference, so we needn't accumulate it into the fixed summary.  The design 
-allows this, but it breaks a useful post-condition on scanning (if the 
-accumulation of ss->fixedSummary was moved the accuracy of ss->fixedSummary 
-would vary according to the "width" of the white summary).  See 
-mail.pekka.1998-02-04.16-48 for improvement suggestions.
-
-
-ANALYSIS:
-
-.fix.copy-fail: Fixing can always succeed, even if copying the referenced 
-object has failed (due to lack of memory, for example), by backing off to 
-treating a reference as ambiguous.  Assuming that fixing an ambiguous reference 
-doesn't allocate memory (which is no longer true for AMC for example).  See 
-request.dylan.170560 for a slightly more sophisticated way to proceed when you 
-can no longer allocate memory for copying.
-
-
-IDEAS:
-
-.flip.after: To avoid excessive barrier impact on the mutator immediately after 
-flip, we could scan during flip other objects which are "near" the roots, or 
-otherwise known to be likely to be accessed in the near future.
-
-
-IMPLEMENTATION:
-
-Speed
-
-.fix: The fix path is critical to garbage collection speed.  Abstractly fix is 
-applied to all the references in the non-white heap and all the references in 
-the copied heap.  Remembered sets cut down the number of segments we have to 
-scan.  The zone test cuts down the number of references we call fix on.  The 
-speed of the remainder of the fix path is still critical to system 
-performance.  Various modifications to and aspects of the system are concerned 
-with maintaining the speed along this path.
-
-.fix.tractofaddr: TractOfAddr is called on every reference that passes the zone 
-test and is on the critical path, to determine whether the segment is white. 
-There is no need to examine the segment to perform this test, since whiteness 
-information is duplicated in tracts, specifically to optimize this test.  
-TractOfAddr itself is a simple class dispatch function (which dispatches to the 
-arena class's TractOfAddr method).  Inlining the dispatch and inlining the 
-functions called by VMTractOfAddr makes a small but noticable difference to the 
-speed of the dylan compiler.
-
-.fix.noaver: AVERs in the code add bulk to the code (reducing I-cache efficacy) 
-and add branches to the path (polluting the branch pedictors) resulting in a 
-slow down.  Removing all the AVERs from the fix path improves the overall speed 
-of the dylan compiler by as much as 9%.
-
-.fix.nocopy: AMCFix used to copy objects by using the format's copy method.  
-This involved a function call (through an indirection) and in dylan_copy a call 
-to dylan_skip (to recompute the length) and call to memcpy with general 
-parameters.  Replacing this with a direct call to memcpy removes these 
-overheads and the call to memcpy now has aligned parameters.  The call to 
-memcpy is inlined by the (C) compiler.  This change results in a 4-5% speed-up 
-in the dylan compiler.
-
-.reclaim: Because the reclaim phase of the trace (implemented by TraceReclaim) 
-examines every segment it is fairly time intensive.  rit's profiles presented 
-in request.dylan.170551 show a gap between the two varieties variety.hi and 
-variety.wi.
-
-.reclaim.noaver: Converting AVERs in the loops of TraceReclaim, PoolReclaim, 
-AMCReclaim (LOReclaim? AWLReclaim) will result in a noticeable speed 
-improvement [insert actual speed improvement here].
-
-
- -

Life cycle of a trace object

- -

TraceCreate creates a trace in state TraceINIT

- -

Some segments get condemned (made white).

- -

TraceStart gets called which:

- -
    - -
  • Derives an initial reference partition based on the existing - white set. The white zone set and the segments' summaries are used to - create an initial grey set.

  • - -
  • emits a GCStart message.

  • - -
  • initialises trace->rate by estimating the required scanning - rate

  • - -
  • moves the trace into the state TraceUNFLIPPED

  • - -
  • immediately calls traceFlip which flips the trace and moves - it into state TraceFLIPPED.

  • - -
- -

Whilst a trace is alive every so often its -traceQuantum method gets invoked (via -TracePoll) in order to do a quantum of tracing work. -traceQuantum is responsible for ticking through the trace's -top-level state machine. Most of the interesting work, the tracing, -happens in the TraceFLIPPED state.

- -

The trace transitions through its states in the following sequence: -TraceINIT -> -(TraceUNFLIPPED) -> TraceFLIPPED -> -TraceRECLAIM -> TraceFINISHED.

- -

Whilst TraceUNFLIPPED appears in the code, no trace does -any work in this state; all traces are immediately flipped to be in the -TraceFLIPPED state (see above).

- -

Once the trace is in the TraceFINISHED state it performs -no more work and it can be safely destroyed. Generally the callers of -traceQuantum will destroy the trace.

- -

Making Progress - Scanning Grey Segments

- -

Most of the interesting work of a trace, the actual tracing, happens -in the TraceFLIPPED state (work would happen in -the TraceUNFLIPPED state, but that is not implemented).

- -

The tracer makes progress by choosing a grey segment to scan, and -scanning it. The actual scanning is performed by pools.

- -

Note that at all times a reference partition is maintained.

- -

The order in which the trace scans things determines the semantics of -certain types of references (in particular, weak and final references). -Or, to put it another way the desired semantics of weak and final -references impose certain restrictions on the order in which the trace -can scan things.

- -

The tracer uses a system of reference ranks (or just -ranks) so that it can impose an order on its scanning work. The ranks -are ordered.

- -

The tracer proceeds band by band. The first band is all objects it -can reach by following references of the first rank. The second band is -all subsequent objects it can reach by following references of the -second and first ranks. The third band is all subsequent objects it can -reach by following references of the third, second, and first ranks. -And so on. The description of the tracer working like this originated -in an e-mail message from RHSK [RHSK -2007-06-25].

- -

A trace keep track of which band it is tracing. This is returned by -the TraceBand method. Keeping this band information helps -it implement the semantics of finalization and weakness. The band used -to not be explicitly stored, but this hindered the implementation of -good finalization semantics (essentially in some circumstances -finalization messages were delayed by at least one collection cycle, see -job001658).

- -

The band is used when selecting a grey segment to scan (the selection -occurs in traceFindGrey). The tracer attempts to first -find segments whose rank is the current band, then segments whose rank -is previous to the current band, and so on. If there are no segments -found then the current band is exhausted and the current band is -incremented to the next rank. When the current band is moved through -all the ranks in this fashion there is no more tracing to be done. -

- - -

A. References

- - - - - - - - - - - - -
[RHSK 2007-06-25]"the semantics of rank-based tracing"; - RHSK; - <URL: http://info.ravenbrook.com/mail/2007/06/25/11-35-57/0.txt>; - 2007-06-25. -
- - -

B. Document History

- - - - - - - - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
2007-07-02DRJAdded notes on tracer progress
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/type/index.html b/mps/design/type/index.html deleted file mode 100644 index 18beaa9591f..00000000000 --- a/mps/design/type/index.html +++ /dev/null @@ -1,515 +0,0 @@ - - - - - - - - -The design of the general MPS types - - - - - - - -
-                  THE DESIGN OF THE GENERAL MPS TYPES
-                            design.mps.type
-                             incomplete doc
-                           richard 1996-10-23
-
-INTRODUCTION
-
-.intro:
-
-See impl.h.mpmtypes.
-
-
-RATIONALE
-
-Some types are declared to resolve a point of design, such as the best type to 
-use for array indexing.
-
-Some types are declared so that the intention of code is clearer.  For example, 
-Byte is necessarily unsigned char, but it's better to say Byte in your code if 
-it's what you mean.
-
-
-CONCRETE TYPES
-
-
-Bool
-
-.bool: The Bool type is mostly defined so that the intention of code is 
-clearer.  In C, boolean expressions evaluate to int, so Bool is in fact an 
-alias for int.
-
-.bool.value: Bool has two values, TRUE and FALSE. These are defined to be 1 and 
-0 respectively, for compatibility with C boolean expressions (so one may set a 
-Bool to the result of a C boolean expression). 
-
-.bool.use: Bool is a type which should be used when a boolean value is 
-intended, for example, as the result of a function.  Using a boolean type in C 
-is a tricky thing.  Non-zero values are "true" (when used as control 
-conditions) but are not all equal to TRUE.  Use with care.
-
-.bool.check: BoolCheck simply checks whether the argument is TRUE (1) or FALSE 
-(0).
-
-.bool.check.inline: The inline macro version of BoolCheck casts the int to 
-unsigned and checks that it is <= 1.  This is safe, well-defined, uses the 
-argument exactly once, and generates reasonable code.  
-.bool.check.inline.smaller: In fact we can expect that the "inline" version of 
-BoolCheck to be smaller than the equivalent function call (on intel for 
-example, a function call will be 3 instructions (total 9 bytes), the inline 
-code for BoolCheck will be 1 instruction (total 3 bytes) (both sequences not 
-including the test which is the same length in either case)).  
-.bool.check.inline.why: As well as being smaller (see 
-.bool.check.inline.smaller) it is faster.  On 1998-11-16 drj compared 
-w3i3mv\hi\amcss.exe running with and without the macro for BoolCheck on the PC 
-Aaron.  "With" ran in 97.7% of the time (averaged over 3 runs).
-
-
-Res
-
-.res: Res is the type of result codes.  A result code indicates the success or 
-failure of an operation, along with the reason for failure.  Like Unix error 
-codes, the meaning of the code depends on the call that returned it.  These 
-codes are just broad categories with mnemonic names for various sorts of 
-problems.
-
-ResOK: The operation succeeded.  Return parameters may only be updated if OK is 
-returned, otherwise they must be left untouched.
-ResFAIL: Something went wrong which doesn't fall into any of the other 
-categories.  The exact meaning depends on the call.  See documentation.
-ResRESOURCE: A needed resource could not be obtained.  Which resource depends 
-on the call.  See also MEMORY, which is a special case of this.
-ResMEMORY: Needed memory (committed memory, not address space) could not be 
-obtained.
-ResLIMIT: An internal limitation was reached.  For example, the maximum number 
-of somethings was reached.  We should avoid returning this by not including 
-static limitations in our code, as far as possible. (See rule.impl.constrain 
-and rule.impl.limits.)
-ResUNIMPL: The operation, or some vital part of it, is unimplemented.  This 
-might be returned by functions which are no longer supported, or by operations 
-which are included for future expansion, but not yet supported.
-ResIO: An I/O error occurred.  Exactly what depends on the function.
-ResCOMMIT_LIMIT: The arena's commit limit would have been exceeded as a result 
-of allocation.
-ResPARAM: An invalid parameter was passed.  Normally reserved for parameters 
-passed from the client.
-
-.res.use: Res should be returned from any function which might fail.  Any other 
-results of the function should be passed back in "return" parameters (pointers 
-to locations to fill in with the results).  [This is documented elsewhere, I 
-think -- richard].res.use.spec: The most specific code should be returned.
-
-
-Fun
-
-.fun: Fun is the type of a pointer to a function about which nothing more is 
-known.
-
-.fun.use: Fun should be used where it's necessary to handle a function without 
-calling it in a polymorphic way.  For example, if you need to write a function 
-g which passes another function f through to a third function h, where h knows 
-the real type of f but g doesn't.
-
-
-Word
-
-.word: Word is an unsigned integral type which matches the size of the machine 
-word, i.e. the natural size of the machine registers and addresses.
-
-.word.use: It should be used where an unsigned integer is required that might 
-range as large as the machine word.
-
-.word.source: Word is derived from the macro MPS_T_WORD which is declared in 
-impl.h.mpstd according to the target platform.
-
-.word.conv.c: Word is converted to mps_word_t in the MPS C Interface.
-
-
-Byte
-
-.byte: Byte is an unsigned integral type corresponding to the unit in which 
-most sizes are measured, and also the units of sizeof().
-
-.byte.use: Byte should be used in preference to char or unsigned char wherever 
-it is necessary to deal with bytes directly.
-
-.byte.source: Byte is a just pedagogic version of unsigned char, since char is 
-the unit of sizeof().
-
-
-Index
-
-.index: Index is an unsigned integral type which is large enough to hold any 
-array index.
-
-.index.use: Index should be used where the maximum size of the array cannot be 
-statically determined.  If the maximum size can be determined then the smallest 
-unsigned integer with a large enough range may be used instead.
-
-
-Count
-
-.count: Count is an unsigned integral type which is large enough to hold the 
-size of any collection of objects in the MPS.
-
-.count.use: Count should be used for a number of objects (control or managed) 
-where the maximum number of objects cannot be statically determined. If the 
-maximum number can be statically determined then the smallest unsigned integer 
-with a large enough range may be used instead (although Count may be preferable 
-for clarity).  [ Should Count be used to count things that aren't represented 
-by objects (e.g. a level)?  I would say yes.  gavinm 1998-07-21 ] [Only where 
-it can be determined that the maximum count is less than the number of 
-objects.  pekka 1998-07-21]
-
-
-Accumulation
-
-.accumulation: Accumulation is an arithmetic type which is large enough to hold 
-accumulated totals of objects of bytes (e.g. total number of objects allocated, 
-total number of bytes allocated).
-
-.accumulation.type: Currently it is double, but reason for the interface is so 
-that we can more easily change it if we want to (if we decide we need more 
-accuracy for example).
-
-.accumulation.use: Currently the only way to use an Accumulation is to reset it 
-(AccumulatorReset) and accumulate (Accumulate) amounts into it.  There is no 
-way to read it at the moment, but that's okay, because no one seems to want to.  
-.accumulation.future: Probably we should have methods which return the 
-accumulation into an unsigned long, and also a double; these functions should 
-return bools to indicate whether the accumulation can fit in the requested 
-type.  Possibly we could have functions which returned scaled accumulations 
-(e.g. AccumulatorScale(a, d) would divide the Accumulation a by double d and 
-return the double result if the result fitted into a double).
-
-
-Addr
-
-.addr: Addr is the type used for "managed addresses", that is, addresses of 
-objects managed by the MPS.
-
-.addr.def: Addr is defined as struct AddrStruct *, but AddrStruct is never 
-defined.  This means that Addr is always an incomplete type, which prevents 
-accidental dereferencing, arithmetic, or assignment to other pointer types.
-
-.addr.use: Addr should be used whenever the code needs to deal with addresses.  
-It should not be used for the addresses of memory manager data structures 
-themselves, so that the memory manager remains amenable to working in a 
-separate address space.  Be careful not to confuse Addr with void *.
-
-.addr.ops: Limited arithmetic is allowed on addresses using AddrAdd and 
-AddrOffset (impl.c.mpm).  Addresses may also be compared using the relational 
-operators ==, !=, <, <=, >, and >=.  .addr.ops.mem: We need efficient operators 
-similar to memset, memcpy, and memcmp on Addr; these are called AddrSet, 
-AddrCopy, and AddrComp.  When Addr is compatible with void *, these are 
-implemented through the mps_lib_mem* functions in the plinth (impl.h.mpm) [and 
-in fact, no other implementation exists at present, pekka 1998-09-07].
-
-.addr.conv.c: Addr is converted to mps_addr_t in the MPS C Interface.  
-mps_addr_t is defined to be the same as void *, so using the MPS C Interface 
-confines the memory manager to the same address space as the client data.
-
-
-Size
-
-.size: Size is an unsigned integral type large enough to hold the size of any 
-object which the MPS might manage.
-
-.size.byte: Size should hold a size calculated in bytes.  Warning: This may not 
-be true for all existing code.
-
-.size.use: Size should be used whenever the code needs to deal with the size of 
-managed memory or client objects.  Is should not be used for the sizes of the 
-memory manager's own data structures, so that the memory manager is amenable to 
-working in a separate address space.  Be careful not to confuse it with size_t.
-
-.size.ops: [Size operations?]
-
-.size.conv.c: Size is converted to size_t in the MPS C Interface.  This 
-constrains the memory manager to the same address space as the client data.
-
-
-Align
-
-.align: Align is an unsigned integral type which is used to represent the 
-alignment of managed addresses.  All alignments are positive powers of two.  
-Align is large enough to hold the maximum possible alignment.
-
-.align.use: Align should be used whenever the code needs to deal with the 
-alignment of a managed address.
-
-.align.conv.c: Align is converted to mps_align_t in the MPS C Interface.
-
-
-Shift
-
-.shift: Shift is an unsigned integral type which can hold the amount by which a 
-Word can be shifted.  It is therefore large enough to hold the word width (in 
-bits).
-
-.shift.use: Shift should be used whenever a shift value (the right-hand operand 
-of the << or >> operators) is intended, to make the code clear.  It should also 
-be used for structure fields which have this use.
-
-.shift.conv.c: Shift is converted to mps_shift_t in the MPS C Interface.
-
-
-Ref
-
-.ref: Ref is a reference to a managed object (as opposed to any old managed 
-address).  Ref should be used where a reference is intended.
-
-[This isn't too clear -- richard]
-
-
-RefSet
-
-.refset: RefSet is a conservative approximation to a set of references.  See 
-design.mps.refset.
-
-
-Rank
-
-.rank: Rank is an enumeration which represents the rank of a reference.  The 
-ranks are:
-
-RankAMBIG (0): the reference is ambiguous, i.e. must be assumed to be a 
-reference, and not update in case it isn't;
-RankEXACT (1): the reference is exact, and refers to an object;
-RankFINAL (2): the reference is exact and final, so special action is required 
-if only final or weak references remain to the object;
-RankWEAK (3): the reference is exact and weak, so should be deleted if only 
-weak references remain to the object.
-
-Rank is stored with segments and roots, and passed around.
-
-Rank is converted to mps_rank_t in the MPS C Interface.
-
-The ordering of the ranks is important.  It is the order in which the 
-references must be scanned in order to respect the properties of references of 
-the ranks.  Therefore they are declared explicitly with their integer values.
-
-[Could Rank be a short?]
-
-[This documentation should be expanded and moved to its own document, then 
-referenced from the implementation more thoroughly.]
-
-
-Epoch
-
-.epoch: An Epoch is a count of the number of flips that the mutator have 
-occurred.  [Is it more general than that?]  It is used in the implementation of 
-location dependencies (LDs).
-
-Epoch is converted to mps_word_t in the MPS C Interface, as a field of mps_ld_s.
-
-
-TraceId
-
-.traceid: A TraceId is an unsigned integer which is less than TRACE_MAX.  Each 
-running trace has a different TraceId which is used to index into tables and 
-bitfields used to remember the state of that trace.
-
-
-TraceSet
-
-.traceset: A TraceSet is a bitset of TraceIds, represented in the obvious way, 
-i.e.
-
-  member(ti, ts) <=> (2^ti & ts) != 0
-
-TraceSets are used to represent colour in the Tracer.  [Expand on this.]
-
-
-AccessSet
-
-.access-set: An AccessSet is a bitset of Access modes, which are AccessREAD and 
-AccessWRITE.  AccessNONE is the empty AccessSet. 
-
-
-Attr
-
-.attr: Pool attributes. A bitset of pool or pool class attributes, which are:
-
-  AttrFMT: the pool contains formatted objects;
-
-  AttrSCAN: the pool contains references and must be scanned for GC;
-
-  AttrPM_NO_READ: the pool may not be read protected;
-
-  AttrPM_NO_WRITE: the pool may not be write protected;
-
-  AttrALLOC: the pool supports the PoolAlloc interface;
-
-  AttrFREE: the pool supports the PoolFree interface;
-
-  AttrBUF: the pool supports the allocation buffer interface;
-
-  AttrBUF_RESERVE: the pool suppors the reserve/commit protocol on allocation 
-buffers;
-
-  AttrBUF_ALLOC: the pool supports the alloc protocol on allocation buffers;
-
-  AttrGC: the pool is garbage collecting, i.e. parts may be reclaimed;
-
-  AttrINCR_RB: the pool is incremental requiring a read barrier;
-
-  AttrINCR_WB: the pool is incremental requiring a write barrier.
-
-There is an attribute field in the pool class (PoolClassStruct) which declares 
-the attributes of that class.  These attributes are only used for consistency 
-checking at the moment. [no longer true that they are only used for consistency 
-checking -- drj 1998-05-07]
-
-
-RootVar
-
-.rootvar: The type RootVar is the type of the discriminator for the union 
-within RootStruct.
-
-
-Serial
-
-.serial: A Serial is a number which is assigned to a structure when it is 
-initialized.  The serial number is taken from a field in the parent structure, 
-which is incremented.  Thus, every instance of a structure has a unique "name" 
-which is a path of structures from the global root.  For example:
-
-  space[3].pool[5].buffer[2]
-
-Why?  Consistency checking, debugging, and logging.  Not well thought out.
-
-
-Compare
-
-.compare: Compare is the type of tri-state comparison values.  
-
-CompareLESS: Indicates that a value compares less than another value. 
-CompareEQUAL: Indicates that two value compares the same 
-CompareGREATER: Indicates that a value compares greater than another value. 
-
-
-ULongest
-
-.ulongest: ULongest is the longest unsigned integer on the platform.  (We used to use "unsigned long" but this assumption is violated by 64-bit Windows.)  This type should be used for calculations where any integer might be passed.  Notably, it is used in WriteF to print any integer.
-
-
-ABSTRACT TYPES
-
-.adts: The following types are abstract data types, implemented as pointers to 
-structures.  For example, Ring is a pointer to a RingStruct.  They are 
-described elsewhere [where?].
-
-  Ring, Buffer, AP, Format, LD, Lock, Pool, Space, PoolClass, Trace,
-  ScanState, Seg, Arena, VM, Root, Thread.
-
-
-POINTERS
-
-.pointer: The type Pointer is the same as "void *", and exists to sanctify 
-functions such as PointerAdd.
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/version-library/index.html b/mps/design/version-library/index.html deleted file mode 100644 index 07cef14472e..00000000000 --- a/mps/design/version-library/index.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - -Design of the MPS library version mechanism - - - - - - - -
-              DESIGN OF THE MPS LIBRARY VERSION MECHANISM
-                       design.mps.version-library
-                             incomplete doc
-                             drj 1998-08-19
-
-INTRODUCTION
-
-.intro: This describes the design of a mechanism to be used to determine the 
-version (that is, product, version, and release) of an MPS library.
-
-
-READERSHIP
-
-.readership: Any MPS developer.
-
-
-SOURCE
-
-.source: Various requirements demand such a mechanism.  See 
-request.epcore.160021: There is no way to tell which version and release of the 
-MM one is using.
-
-
-OVERVIEW
-
-.overview: See design.mps.version for discussion and design of versions of 
-other aspects of the software.  This document concentrates on a design for 
-determining which version of the library one has linked with.  There are two 
-aspects to the design, allowing humans to determine the version of an MPS 
-library, and allowing programs to determine the version of an MPS library.  
-Only the former is currently designed (a method for humans to determine which 
-version of an MPS library is being used).
-
-.overview.impl: The overall design is to have a distinctive string compiled 
-into the library binary.  Various programs and tools will be able to extract 
-the string and display it.  The string will identify the version of the MPS 
-begin used.
-
-
-ARCHITECTURE
-
-.arch.structure: The design consists of 3 components:
-
-.arch.string: A string embedded into any delivered library binaries (which will 
-encode the necessary information).
-
-.arch.proc: A process by which the string is modified appropriately whenever 
-releases are made.
-
-.arch.tool: A tool and its documentation (it is expected that standard tools 
-can be used).  The tool will be used to extract the version string from a 
-delivered library or an executable linked with the library.
-
-.arch.not-here: Only the string component (:arch.string) is directly described 
-here.  The other components are described elsewhere.  (where?)
-
-The string will contain information to identify the following items:
-.arch.string.platform: the platform being used.
-.arch.string.product: the name of the product.
-.arch.string.variety: the variety of the product.
-.arch.string.version: the version and release of the product.
-
-
-IMPLEMENTATION
-
-.impl.file: The string itself is a declared C object in the file version.c 
-(impl.c.version).  It consists of a concatenation of various strings which are 
-defined in other modules.
-
-.impl.variety: The string containing the name of the variety is the expansion 
-of the macro MPS_VARIETY_STRING defined by config.h (impl.h.config).
-
-.impl.product: The string containing the name of the product is the expansion 
-of the macro MPS_PROD_STRING defined by config.h (impl.h.config).
-
-.impl.platform: The string containing the name of the platform is the expansion 
-of the macro MPS_PF_STRING defined by mpstd.h (impl.h.mpstd).
-
-.impl.date: The string contains the date and time of compilation by using the 
-__DATE__ and __TIME__ macros defined by ISO C (ISO C clause 6.8.8).
-
-.impl.version: The string contains the version and release of the product.  
-This is by the expansion of the macro MPS_RELEASE which is defined in this 
-module (version.c).
-
-.impl.usage: To make a release, the MPS_RELEASE macro (see 
-impl.c.version.release) is edited to contain the release name (e.g., 
-"release.epcore.brisling"), and then changed back immediately after the release 
-checkpoint is made.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/version/index.html b/mps/design/version/index.html deleted file mode 100644 index 70903c1a0fe..00000000000 --- a/mps/design/version/index.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - -Design of MPS software versions - - - - - - - -
-                    DESIGN OF MPS SOFTWARE VERSIONS
-                           design.mps.version
-                             incomplete doc
-                             drj 1998-08-19
-
-INTRODUCTION
-
-.intro: This is the design of the support in the MPS for describing and 
-inspecting versions.
-
-OVERVIEW
-
-.overview: There different sorts of version under consideration: Versions of 
-the (MPS) library used (linked with), versions of the interface used (header 
-files in C) when compiling the client's program, versions of the documentation 
-used when the client was writing the program.  There are issues of programmatic 
-and human access to these versions.
-
-.overview.split: The design is split accordingly.  See 
-design.mps.version-library for the design of a system for determining the 
-version of the library one is using.  And other non-existent documents for the 
-others.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/vm/index.html b/mps/design/vm/index.html deleted file mode 100644 index ec27f38268c..00000000000 --- a/mps/design/vm/index.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - -The design of the virtual mapping interface - - - - - - - -
-              THE DESIGN OF THE VIRTUAL MAPPING INTERFACE
-                             design.mps.vm
-                           incomplete design
-                           richard 1998-05-11
-
-.intro: This the design of the VM interface.  The VM interface provides a 
-simple, low-level, operating-system independent interface to address-space.  
-Each call to VMCreate() reserves (from the operating-system) a single 
-contiguous range of addresses, and returns a VMStruct thereafter used to manage 
-this address-space.  The VM interface has separate implementations for each 
-platform that supports it (at least conceptually, in practice some of them may 
-be the same).  The VM module provides a mechanism to reserve large (relative to 
-the amount of RAM) amounts of address space, and functions to map (back with 
-RAM) and unmap portions of this address space.
-
-.motivation: The VM is used by the VM Arena Class.  It provides the basic 
-substrate to provide sparse address maps.  Sparse address maps have at least 
-two uses: to encode information into the address of an object which is used in 
-tracing (the Zone Test) to speed things up; to avoid fragmentation at the 
-segment level and above (since the amount of address space reserved is large 
-compared to the RAM, the hope is that there will also be enough address space 
-somewhere to fit any particular segment in).
-
-
-DEFINITIONS
-
-.def.reserve: The "reserve" operation: Exclusively reserve a portion of the 
-virtual address space without arranging RAM or backing store for the virtual 
-addresses.  The intention is that no other component in the process will make 
-use of the reserved virtual addresses, but in practice this may entail assuming 
-a certain amount of cooperation.  When reserving address space, the requester 
-simply asks for a particular size, not a particular range of virtual 
-addresses.  Accessing (read/write/execute) reserved addresses is illegal unless 
-those addresses have been mapped.
-
-.def.map: The "map" operation: Arrange that a specified portion of the virtual 
-address space is mapped from the swap, effectively allocating RAM and/or swap 
-space for a particular range of addresses.  If successful, accessing the 
-addresses is now legal.  Only reserved addresses should be mapped.
-
-.def.unmap: The "unmap" operation: The inverse of the map operation.  Arrange 
-that a specified portion of the virtual address space is no longer mapped, 
-effectively freeing up the RAM and swap space that was in use.  Accessing the 
-addresses is now illegal.  The addresses return to the reserved state.
-
-.def.vm: "VM" stands for Virtual Memory.  Various meanings: A processor 
-architecture's virtual space and structure; The generic idea / interface / 
-implementation of the MPS VM module; The C structure (struct VMStruct) used to 
-encapsulate the functionality of the MPS VM module; An instance of such a 
-structure.
-
-.def.vm.mps: In the MPS, a "VM" is a VMStruct, providing access to the single 
-contiguous range of address-space that was reserved (from the operating-system) 
-when VMCreate was called.
-
-
-INTERFACE
-
-.if.create: Res VMCreate(VM *VMReturn, Size size)
-
-VMCreate is responsible both for allocating a VMStruct and for reserving an 
-amount of virtual address space.  A VM is created and a pointer to it is 
-returned in the return parameter VMReturn.  This VM has at least size bytes of 
-virtual memory reserved.  If there's not enough space to allocate the VM, 
-ResMEMORY is returned.  If there's not enough address space to reserve a block 
-of the given size, ResRESOURCE is returned.  The reserved virtual memory can be 
-mapped and unmapped using VMMap and VMUnmap.
-
-
-.if.destroy: void VMDestroy(VM vm)
-
-A VM is destroyed by calling VMDestroy.  Any address space that was mapped 
-through this VM is unmapped.
-
-
-[lots of interfaces missing here]
-
-
-NOTES
-
-.diagram:
-
-
-
-.testing: It is important to test that a VM implementation will work in extreme 
-cases.  .testing.large: It must be able to reserve a large address space.  
-Clients will want multi-GB spaces, more than that OSs will allow.  If they ask 
-for too much, mps_arena_create (and hence VMCreate) must fail in a predictable 
-way.  .testing.larger: It must be possible to allocate in a large space; 
-sometimes commiting will fail, because there's not enough space to replace the 
-"reserve" mapping.  See request.epcore.160201 for details.  .testing.lots: It 
-must be possible to have lots of mappings.  The OS must either combine adjacent 
-mappings or have lots of space in the kernel tables.  See request.epcore.160117 
-for ideas on how to test this.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/vman/index.html b/mps/design/vman/index.html deleted file mode 100644 index 6441cddbd42..00000000000 --- a/mps/design/vman/index.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - -ANSI fake VM - - - - - - - -
-                              ANSI FAKE VM
-                            design.mps.vman
-                             incomplete doc
-                             drj 1996-11-07
-
-.intro: The ANSI fake VM is an implementation of the MPS VM interface (see 
-design.mps.vm) using services provided by the ANSI C Library (standard.ansic.7) 
-(malloc and free as it happens).
-
-.align: The VM is aligned to VMAN_ALIGN (defined in impl.h.mpmconf) by adding 
-VMAN_ALIGN to the requested size, mallocing a block that large, then rounding 
-the pointer to the base of the block.  vm->base is the aligned pointer, 
-vm->block is the pointer returned by malloc (used when during VMDestroy).
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/vmo1/index.html b/mps/design/vmo1/index.html deleted file mode 100644 index cfa2a88b8ee..00000000000 --- a/mps/design/vmo1/index.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - -VM Module on DEC Unix - - - - - - - -
-                         VM MODULE ON DEC UNIX
-                            design.mps.vmo1
-                             incomplete doc
-                             drj 1997-03-25
-
-INTRODUCTION
-
-.readership: Any MPS developer.
-
-.intro: This is the design of the VM Module for DEC UNIX (aka OSF/1 os.o1).  In 
-general aspects (including interface) the design is as for design.mps.vm.
-
-DETAILS
-
-Functions
-
-.fun.unmap:
-
-VMUnmap
-
-It "unmaps" a region by replacing the existing mapping with a mapping using the 
-vm->none_fd file descriptor (see mumble mumble, VMCreate), and protection set 
-to PROT_NONE (ie no access).  .fun.unmap.justify: Replacing the mapping in this 
-way means that the address space is still reserved and will not be used by 
-calls to mmap (perhaps in other libraries) which specify MAP_VARIABLE.  
-.fun.unmap.offset: The offset for this mapping is the offset of the region 
-being unmapped in the VM; this gives the same effect as if there was one 
-mapping of the vm->none_fd from the base to the limit of the VM (but "behind" 
-all the other mappings that have been created).  .fun.unmap.offset.justify: If 
-this is not done (if for example the offset is always specified as 0) then the 
-VM will cause the kernel to create a new file reference for each mapping 
-created with VMUnmap; eventually the kernel refuses the mmap call because it 
-can't create a new file reference.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/vmso/index.html b/mps/design/vmso/index.html deleted file mode 100644 index 3faf7d6146c..00000000000 --- a/mps/design/vmso/index.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - -VM Design for Solaris - - - - - - - -
-                         VM DESIGN FOR SOLARIS
-                            design.mps.vmso
-                             incomplete doc
-                             drj 1998-05-08
-
-INTRODUCTION
-
-.intro: This is the design for the VM implementation on Solaris 2.x (see os.so 
-for OS details).  The implementation is in MMsrc!vmso.c (impl.c.vm).  The 
-design follows the design for and implements the contract of the generic VM 
-interface (design.mps.vm).  To summarize: The VM module provides a mechanism to 
-reserve large (relative to the amount of RAM) amounts of address space, and 
-functions to map (back with RAM) and unmap portions of this address space.
-
-.source: Much of the implementation (and hence the design) was inherited from 
-the SunOS4 implementation.  Not that there's any design for that.  You'll find 
-the mmap(2) (for the system call mmap) and the zero(7d) (for the device 
-/dev/zero) man pages useful as well.  The generic interface and some generic 
-design is in design.mps.vm.
-
-
-DEFINITIONS
-
-.def: See design.mps.vm.def.* for definitions common to all VMs.
-
-
-OVERVIEW
-
-.over: The system calls mmap and munmap are used to access the underlying 
-functionality.  They are used in slightly unusual ways, typically to overcome 
-baroque features or implementation details of the OS.  .over.reserve: In order 
-to reserve address space, a mapping to a file (/etc/passwd as it happens) is 
-created with no protection allowed.  .over.map: In order to map memory, a 
-mapping to /dev/zero is created.  .over.destroy: When the VM is destroyed, 
-munmap is used to remove all the mappings previously created.
-
-
-IMPLEMENTATION
-
-.impl.create: VMCreate
-
-.impl.create.vmstruct: Enough pages to hold the VMStruct are allocated by 
-creating a mapping to /dev/zero (a read/write private mapping), and using 
-initializing the memory as a VMStruct.  .impl.create.reserve: The size 
-parameter is rounded up to page size and this amount of address space is 
-reserved.  The address space is reserved by creating a shared mapping to 
-/etc/passwd with no access allowed (prot argument is PROT_NONE, flags argument 
-is MAP_SHARED).  .impl.create.reserve.mmap.justify: mmap gives us a flexible 
-way to allocate address space without interfering with any other component in 
-the process.  Because we don't specify MAP_FIXED we are guaranteed to get a 
-range of addresses that are not in use.  Other components must cooperate by not 
-attempting to create mappings specifying MAP_FIXED and an address in the range 
-that the MPS has reserved.  .impl.create.reserve.passwd.justify: Mapping 
-/etc/passwd like this worked on SunOS4 (so this implementation inherited it).  
-Mapping /dev/zero with prot=PROT_NONE and flags=MAP_PRIVATE does not work 
-because Solaris gratuitously allocates swap (even though you can't use the 
-memory).  .impl.create.reserve.improve: However, it would appears that ORing in 
-MAP_NORESERVE mapping /dev/zero will reserve address space without allocating 
-swap, so this might be worth trying.  I.e., with prot=PROT_NONE, 
-flags=MAP_PRIVATE|MAP_NORESERVE.  However the following caveat comes from the 
-original implementation: "Experiments have shown that attempting to reserve 
-address space by mapping /dev/zero results in swap being reserved.  This 
-appears to be a bug, so we work round it by using /etc/passwd, the only file we 
-can think of which is pretty much guaranteed to be around."  So that might not 
-work after all.
-
-.impl.map: VMMap
-
-.impl.map.zero: A mapping to /dev/zero is created at the relevant addresses 
-(overriding the map to /etc/passwd that was previously in place for those 
-addresses).  The prot argument is specified as PROT_READ|PROT_WRITE|PROT_EXEC 
-(so that any access is allowed), the flags argument as MAP_PRIVATE|MAP_FIXED 
-(MAP_PRIVATE means that the mapping is not shared with child processes (child 
-processes will have a mapping, but changes to the memory will not be shared).  
-MAP_FIXED guarantees that we get the mapping at the specified address).  The 
-zero(7d) man page documents this as a way to create a "zero-initialized unnamed 
-memory object".  .impl.map.error: If there's not enough swap space for the 
-mapping, mmap will return EAGAIN, not ENOMEM, although you might not think so 
-from the man page.
-
-
-.impl.unmap: VMUnmap
-
-.impl.unmap.reserve: The relevant addresses are returned to the reserved state 
-by creating a mapping to /etc/passwd (overriding the map /dev/zero that was 
-previously in place for those addresses).  As for VMCreate (see 
-.impl.create.reserve above) the prot argument is PROT_NONE, but the flags 
-argument has the addition MAP_FIXED flags (so is MAP_SHARED|MAP_FIXED).  
-.impl.unmap.reserve.offset: The offset argument is specified to be the offset 
-of the addresses being unmapped from the base of the reserved VM area.  
-.impl.unmap.reserve.offset.justify: Not specifying the offset like this makes 
-Solaris create a separate mapping (in the kernel) each time Unmap is used, 
-eventually the call to mmap will fail.  Specifying offset like this does not 
-cause Solaris to create any extra mappings, the existing mapping to /etc/passwd 
-gets reused.
-
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/design/writef/index.html b/mps/design/writef/index.html deleted file mode 100644 index 509eeb805b3..00000000000 --- a/mps/design/writef/index.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - -The design of the MPS writef function - - - - - - - -
-                 THE DESIGN OF THE MPS WRITEF FUNCTION
-                           design.mps.writef
-                               draft doc
-                           richard 1996-10-18
-
-INTRODUCTION
-
-.intro: This document describes the WriteF function, which allows formatted 
-output in a manner similar to ANSI C printf, but allows the MPM to operate in a 
-freestanding environment (see design.mps.exec-env).
-
-.background: The documents design.mps.exec-env and design.mps.lib describe the 
-design of
-the library interface and the reason that it exists.
-
-
-DESIGN
-
-.no-printf: There is no dependency on printf has been removed.  The MPM only 
-depends on fputc and fputs, via the Library Interface (design.mps.lib).  This 
-makes it much easier to deploy the MPS in a freestanding environment.  This is 
-achieved by implementing our own internal output routines in mpm.c.
-
-Our output requirements are few, so the code is short.  The only output 
-function which should be used in the rest of the MPM is WriteF, which is 
-similar to fprintf:
-
-  Res WriteF(mps_lib_FILE *stream, ...);
-
-WriteF expects a format string followed by zero or more items to insert into 
-the output, followed by another format string, more items, etc., then a NULL 
-format string, e.g.
-
-  WriteF(stream,
-         "Hello: $A\n", address,
-         "Spong: $U ($S)\n", number, string,
-         NULL);
-
-This makes Describe methods much easier to do, e.g.:
-
-  WriteF(stream,
-         "Buffer $P ($U) {\n", (WriteFP)buffer, (WriteFU)buffer->serial,
-         "  base $A  init $A  alloc $A  limit $A\n",
-         (WriteFA)buffer->base, (WriteFA)buffer->ap.init, 
-         (WriteFA)buffer->ap.alloc, (WriteFA)buffer->ap.limit,
-         "  Pool $P\n",        (WriteFP)buffer->pool,
-         "  Seg $P\n",         (WriteFP)buffer->seg,
-         "  rank $U\n",        (WriteFU)buffer->rank,
-         "  alignment $W\n",   (WriteFW)buffer->alignment,
-         "  grey $B\n",        (WriteFB)buffer->grey,
-         "  shieldMode $B\n",  (WriteFB)buffer->shieldMode,
-         "  p $P  i $U\n",     (WriteFP)buffer->p, (WriteFU)buffer->i,
-         "} Buffer $P ($U)\n", (WriteFP)buffer, (WriteFU)buffer->serial,
-         NULL);
-
-.types: For each format $X that WriteF supports, there is a type defined in 
-impl.h.mpmtypes WriteFX which is the promoted version of that type.  These are 
-provided both to ensure promotion and to avoid any confusion about what type 
-should be used in a cast.  It is easy to check the casts against the formats to 
-ensure that they correspond.  .types.future: It is possibly that this type set 
-or similar may be used in future in some generalisation of varargs in the MPS.
-
-.formats: The formats supported are as follows.
-
-  code    name        type            example rendering
-
-  $A      address     Addr            9EF60010
-  $P      pointer     void *          9EF60100
-  $F      function    void *(*)()     9EF60100 (may be plaform-specific length 
-and format)
-  $S      string      char *          hello
-  $C      character   char            x
-  $W      word        ULongest        00109AE0
-  $U      decimal     ULongest        42
-  $B      binary      ULongest        00000000000000001011011110010001
-  $$      dollar      -               $
-
-Note that WriteFC is an int, because that is the default promotion of a char 
-(see .types).
-
-.snazzy: We should resist the temptation to make WriteF an incredible snazzy 
-output engine.  We only need it for Describe methods and assertion messages.  
-At the moment it's a very simple bit of code -- let's keep it that way.
-
-.f: The F code is used for function pointers.  They are currently printed as a 
-hexadecimal string of the appropriate length for the platform, and may one day 
-be extended to include function name lookup.
-
-
- - -

A. References

- - - - -

B. Document History

- - - - - - - - - - - - - -
2002-06-07RBConverted from MMInfo database design document.
- - -

C. Copyright and License

- -

This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.

- -

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- -
    - -
  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. - -
  3. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  4. - -
  5. Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.
  6. - -
- -

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

- - -
- - - - - - diff --git a/mps/example/scheme/Makefile.in b/mps/example/scheme/Makefile.in deleted file mode 100644 index 1abce708838..00000000000 --- a/mps/example/scheme/Makefile.in +++ /dev/null @@ -1,8 +0,0 @@ -# example/scheme/Makefile -- Makefile for the MPS Scheme example -# -# $Id$ - -CFLAGS = @CFLAGS@ - -scheme: scheme.c - $(CC) $(CFLAGS) -o scheme -I ../../code scheme.c ../../code/mps.c diff --git a/mps/example/scheme/scheme.c b/mps/example/scheme/scheme.c deleted file mode 100644 index cf0929ad002..00000000000 --- a/mps/example/scheme/scheme.c +++ /dev/null @@ -1,3048 +0,0 @@ -/* scheme.c -- SCHEME INTERPRETER EXAMPLE FOR THE MEMORY POOL SYSTEM - * - * $Id$ - * Copyright (c) 2001-2012 Ravenbrook Limited. See end of file for license. - * - * This is a toy interpreter for a subset of the Scheme programming - * language . - * It is by no means the best or even the right way to implement Scheme, - * but it serves the purpose of showing how the Memory Pool System can be - * used as part of a programming language run-time system. - * - * To try it out, "make scheme" then - * - * $ ./scheme - * (define (triangle n) (if (eqv? n 0) 0 (+ n (triangle (- n 1))))) - * (define (church n f a) (if (eqv? n 0) a (church (- n 1) f (f a)))) - * (church 1000 triangle 0) - * - * This won't produce interesting results but it will cause a garbage - * collection cycles. Note that there's never any waiting for the MPS. - * THAT'S THE POINT. - * - * To find the code that's particularly related to the MPS, search for %%MPS. - * - * By the way, this interpreter originally just used `malloc` to allocate - * and had no garbage collector. Adapting it to use the MPS took - * approximately two hours (for an MPS developer :). - * - * - * MPS TO DO LIST - * - make the symbol table weak to show how to use weak references - * - make Scheme ports finalized to show how to use finalization - * - add Scheme operators for talking to the MPS, forcing GC etc. - * - cross-references to documentation - * - make an mps_perror - * - * - * SCHEME TO DO LIST - * - unbounded integers, other number types. - * - do, named let. - * - Quasiquote implementation is messy. - * - Lots of library. - * - \#foo unsatisfactory in read and print - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mps.h" -#include "mpsavm.h" -#include "mpscamc.h" - - -/* LANGUAGE EXTENSION */ - -#define unless(c) if(!(c)) -#define LENGTH(array) (sizeof(array) / sizeof(array[0])) - - -/* CONFIGURATION PARAMETERS */ - - -#define SYMMAX ((size_t)255) /* max length of a symbol */ -#define MSGMAX ((size_t)255) /* max length of error message */ -#define STRMAX ((size_t)255) /* max length of a string */ - - -/* DATA TYPES */ - - -/* obj_t -- scheme object type - * - * obj_t is a pointer to a union, obj_u, which has members for - * each scheme representation. - * - * The obj_u also has a "type" member. Each representation - * structure also has a "type" field first. ANSI C guarantees - * that these type fields correspond [section?]. - * - * Objects are allocated by allocating one of the representation - * structures and casting the pointer to it to type obj_t. This - * allows objects of different sizes to be represented by the - * same type. - * - * To access an object, check its type by reading TYPE(obj), then - * access the fields of the representation, e.g. - * if(TYPE(obj) == TYPE_PAIR) fiddle_with(CAR(obj)); - */ - -typedef union obj_u *obj_t; - -typedef obj_t (*entry_t)(obj_t env, obj_t op_env, obj_t operator, obj_t rands); - -typedef int type_t; -enum { - TYPE_PAIR, - TYPE_INTEGER, - TYPE_SYMBOL, - TYPE_SPECIAL, - TYPE_OPERATOR, - TYPE_STRING, - TYPE_PORT, - TYPE_PROMISE, - TYPE_CHARACTER, - TYPE_VECTOR, - TYPE_FWD2, /* two-word broken heart */ - TYPE_FWD, /* three-words and up broken heart */ - TYPE_PAD1 /* one-word padding object */ -}; - -typedef struct type_s { - type_t type; -} type_s; - -typedef struct pair_s { - type_t type; /* TYPE_PAIR */ - obj_t car, cdr; /* first and second projections */ -} pair_s; - -typedef struct symbol_s { - type_t type; /* TYPE_SYMBOL */ - size_t length; /* length of symbol string (excl. NUL) */ - char string[1]; /* symbol string, NUL terminated */ -} symbol_s; - -typedef struct integer_s { - type_t type; /* TYPE_INTEGER */ - long integer; /* the integer */ -} integer_s; - -typedef struct special_s { - type_t type; /* TYPE_SPECIAL */ - char *name; /* printed representation, NUL terminated */ -} special_s; - -typedef struct operator_s { - type_t type; /* TYPE_OPERATOR */ - char *name; /* printed name, NUL terminated */ - entry_t entry; /* entry point -- see eval() */ - obj_t arguments, body; /* function arguments and code */ - obj_t env, op_env; /* closure environments */ -} operator_s; - -typedef struct string_s { - type_t type; /* TYPE_STRING */ - size_t length; /* number of chars in string */ - char string[1]; /* string, NUL terminated */ -} string_s; - -typedef struct port_s { - type_t type; /* TYPE_PORT */ - obj_t name; /* name of stream */ - FILE *stream; -} port_s; - -typedef struct character_s { - type_t type; /* TYPE_CHARACTER */ - char c; /* the character */ -} character_s; - -typedef struct vector_s { - type_t type; /* TYPE_VECTOR */ - size_t length; /* number of elements */ - obj_t vector[1]; /* vector elements */ -} vector_s; - - -/* fwd, fwd2, pad1 -- MPS forwarding and padding objects %%MPS - * - * These object types are here to satisfy the MPS Format Protocol - * for format variant "A". See [type mps_fmt_A_s in the reference - * manual](../../reference/index.html#mps_fmt_A_s). - * - * The MPS needs to be able to replace any object with forwarding object - * or [broken heart](http://www.memorymanagement.org/glossary/b.html#broken.heart) - * and since the smallest normal object defined above is two words long, - * we have two kinds of forwarding objects: FWD2 is exactly two words - * long, and FWD stores a size for larger objects. There are cleverer - * ways to do this with bit twiddling, of course. - * - * The MPS needs to be able to pad out any area of memory that's a - * multiple of the pool alignment. We've chosen an single word alignment - * for this interpreter, so we have to have a special padding object, PAD1, - * for single words. For larger objects we can just use forwarding objects - * with NULL in their `fwd` fields. See `obj_isfwd` for details. - * - * See obj_pad, obj_fwd etc. to see how these are used. - */ - -typedef struct fwd2_s { - type_t type; /* TYPE_FWD2 */ - obj_t fwd; /* forwarded object */ -} fwd2_s; - -typedef struct fwd_s { - type_t type; /* TYPE_FWD */ - obj_t fwd; /* forwarded object */ - size_t size; /* total size of this object */ -} fwd_s; - -typedef struct pad1_s { - type_t type; /* TYPE_PAD1 */ -} pad1_s; - - -typedef union obj_u { - type_s type; /* one of TYPE_* */ - pair_s pair; - symbol_s symbol; - integer_s integer; - special_s special; - operator_s operator; - string_s string; - port_s port; - character_s character; - vector_s vector; - fwd2_s fwd2; - fwd_s fwd; -} obj_s; - - -/* structure macros */ - -#define TYPE(obj) ((obj)->type.type) -#define CAR(obj) ((obj)->pair.car) -#define CDR(obj) ((obj)->pair.cdr) -#define CAAR(obj) CAR(CAR(obj)) -#define CADR(obj) CAR(CDR(obj)) -#define CDAR(obj) CDR(CAR(obj)) -#define CDDR(obj) CDR(CDR(obj)) -#define CADDR(obj) CAR(CDDR(obj)) -#define CDDDR(obj) CDR(CDDR(obj)) -#define CDDAR(obj) CDR(CDAR(obj)) -#define CADAR(obj) CAR(CDAR(obj)) - - -/* GLOBAL DATA */ - - -/* total -- total allocated bytes */ - -static size_t total; - - -/* symtab -- symbol table %%MPS - * - * The symbol table is a hash-table containing objects of TYPE_SYMBOL. - * When a string is "interned" it is looked up in the table, and added - * only if it is not there. This guarantees that all symbols which - * are equal are actually the same object. - * - * The symbol table is simply a malloc'd array of obj_t pointers. Since - * it's outside the MPS and refers to objects we want the MPS to keep - * alive, it must be declared to the MPS as a root. Search for - * occurrences of `symtab_root` to see how this is done. - */ - -static obj_t *symtab; -static size_t symtab_size; -static mps_root_t symtab_root; - - -/* special objects %%MPS - * - * These global variables are initialized to point to objects of - * TYPE_SPECIAL by main. They are used as markers for various - * special purposes. - * - * These static global variable refer to object allocated in the `obj_pool` - * and so they must also be declared to the MPS as roots. - * See `globals_scan`. - */ - -static obj_t obj_empty; /* (), the empty list */ -static obj_t obj_eof; /* end of file */ -static obj_t obj_error; /* error indicator */ -static obj_t obj_true; /* #t, boolean true */ -static obj_t obj_false; /* #f, boolean false */ -static obj_t obj_undefined; /* undefined result indicator */ -static obj_t obj_tail; /* tail recursion indicator */ - - -/* predefined symbols - * - * These global variables are initialized to point to interned - * objects of TYPE_SYMBOL. They have special meaning in the - * Scheme language, and are used by the evaluator to parse code. - */ - -static obj_t obj_quote; /* "quote" symbol */ -static obj_t obj_quasiquote; /* "quasiquote" symbol */ -static obj_t obj_lambda; /* "lambda" symbol */ -static obj_t obj_begin; /* "begin" symbol */ -static obj_t obj_else; /* "else" symbol */ -static obj_t obj_unquote; /* "unquote" symbol */ -static obj_t obj_unquote_splic; /* "unquote-splicing" symbol */ - - -/* error handler - * - * The error_handler variable is initialized to point at a - * jmp_buf to which the "error" function longjmps if there is - * any kind of error during evaluation. It can be set up by - * any enclosing function that wants to catch errors. There - * is a default error handler in main, in the read-eval-print - * loop. The error function also writes an error message - * into "error_message" before longjmping, and this can be - * displayed to the user when catching the error. - * - * [An error code should also be passed so that the error can - * be decoded by enclosing code.] - */ - -static jmp_buf *error_handler; -static char error_message[MSGMAX+1]; - - -/* MPS globals %%MPS - * - * These are global variables holding MPS values for use by the - * interpreter. In a more sophisticated integration some of these might - * be thread local. See `main` for where these are set up. - * - * `arena` is the global state of the MPS, and there's usually only one - * per process. - * - * `obj_pool` is the memory pool in which the Scheme objects are allocated. - * It is an instance of the Automatic Mostly Copying (AMC) pool class, which - * is a general-purpose garbage collector for use when there are formatted - * objects in the pool, but ambiguous references in thread stacks and - * registers. - * - * `obj_ap` is an Allocation Point that allows fast in-line non-locking - * allocation in a memory pool. This would usually be thread-local, but - * this interpreter is single-threaded. See `make_pair` etc. for how this - * is used with the reserve/commit protocol. - */ - -static mps_arena_t arena; /* the arena */ -static mps_pool_t obj_pool; /* pool for ordinary Scheme objects */ -static mps_ap_t obj_ap; /* allocation point used to allocate objects */ - - -/* SUPPORT FUNCTIONS */ - - -/* error -- throw an error condition - * - * The "error" function takes a printf-style format string - * and arguments, writes the message into error_message and - * longjmps to *error_handler. There must be a setjmp at - * the other end to catch the condition and display the - * message. - */ - -static void error(char *format, ...) -{ - va_list args; - - assert(error_handler != NULL); - - va_start(args, format); - vsprintf(error_message, format, args); - va_end(args); - - longjmp(*error_handler, 1); -} - - -/* make_* -- object constructors %%MPS - * - * Each object type has a function here that allocates an instance of - * that type. - * - * These functions illustrate the two-phase MPS Allocation Point - * Protocol with `reserve` and `commmit`. This protocol allows very fast - * in-line allocation without locking, but there is a very tiny chance that - * the object must be re-initialized. In nearly all cases, however, it's - * just a pointer bump. - * - * NOTE: We could reduce duplicated code here using macros, but we want to - * write these out because this is code to illustrate how to use the - * protocol. - */ - -#define ALIGN(size) \ - (((size) + sizeof(mps_word_t) - 1) & ~(sizeof(mps_word_t) - 1)) - -static obj_t make_pair(obj_t car, obj_t cdr) -{ - obj_t obj; - mps_addr_t addr; - /* When using the allocation point protocol it is up to the client - code to ensure that all requests are for aligned sizes, because in - nearly all cases `mps_reserve` is just an increment to a pointer. */ - size_t size = ALIGN(sizeof(pair_s)); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - if (res != MPS_RES_OK) error("out of memory in make_pair"); - obj = addr; - obj->pair.type = TYPE_PAIR; - CAR(obj) = car; - CDR(obj) = cdr; - /* `mps_commit` returns false on very rare occasions (when an MPS epoch - change has happened since reserve) but in those cases the object must - be re-initialized. It's therefore important not to do anything you - don't want to repeat between reserve and commit. Also, the shorter - the time between reserve and commit, the less likely commit is to - return false. */ - } while(!mps_commit(obj_ap, addr, size)); - total += sizeof(pair_s); - return obj; -} - -static obj_t make_integer(long integer) -{ - obj_t obj; - mps_addr_t addr; - size_t size = ALIGN(sizeof(integer_s)); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - if (res != MPS_RES_OK) error("out of memory in make_integer"); - obj = addr; - obj->integer.type = TYPE_INTEGER; - obj->integer.integer = integer; - } while(!mps_commit(obj_ap, addr, size)); - total += sizeof(integer_s); - return obj; -} - -static obj_t make_symbol(size_t length, char string[]) -{ - obj_t obj; - mps_addr_t addr; - size_t size = ALIGN(offsetof(symbol_s, string) + length+1); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - if (res != MPS_RES_OK) error("out of memory in make_symbol"); - obj = addr; - obj->symbol.type = TYPE_SYMBOL; - obj->symbol.length = length; - memcpy(obj->symbol.string, string, length+1); - } while(!mps_commit(obj_ap, addr, size)); - total += size; - return obj; -} - -static obj_t make_string(size_t length, char string[]) -{ - obj_t obj; - mps_addr_t addr; - size_t size = ALIGN(offsetof(string_s, string) + length+1); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - if (res != MPS_RES_OK) error("out of memory in make_string"); - obj = addr; - obj->string.type = TYPE_STRING; - obj->string.length = length; - memcpy(obj->string.string, string, length+1); - } while(!mps_commit(obj_ap, addr, size)); - total += size; - return obj; -} - -static obj_t make_special(char *string) -{ - obj_t obj; - mps_addr_t addr; - size_t size = ALIGN(sizeof(special_s)); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - if (res != MPS_RES_OK) error("out of memory in make_special"); - obj = addr; - obj->special.type = TYPE_SPECIAL; - obj->special.name = string; - } while(!mps_commit(obj_ap, addr, size)); - total += sizeof(special_s); - return obj; -} - -static obj_t make_operator(char *name, - entry_t entry, obj_t arguments, - obj_t body, obj_t env, obj_t op_env) -{ - obj_t obj; - mps_addr_t addr; - size_t size = ALIGN(sizeof(operator_s)); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - if (res != MPS_RES_OK) error("out of memory in make_operator"); - obj = addr; - obj->operator.type = TYPE_OPERATOR; - obj->operator.name = name; - obj->operator.entry = entry; - obj->operator.arguments = arguments; - obj->operator.body = body; - obj->operator.env = env; - obj->operator.op_env = op_env; - } while(!mps_commit(obj_ap, addr, size)); - total += sizeof(operator_s); - return obj; -} - -static obj_t make_port(obj_t name, FILE *stream) -{ - obj_t obj; - mps_addr_t addr; - size_t size = ALIGN(sizeof(port_s)); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - if (res != MPS_RES_OK) error("out of memory in make_operator"); - obj = addr; - obj->port.type = TYPE_PORT; - obj->port.name = name; - obj->port.stream = stream; - } while(!mps_commit(obj_ap, addr, size)); - total += sizeof(port_s); - return obj; -} - -static obj_t make_character(char c) -{ - obj_t obj; - mps_addr_t addr; - size_t size = ALIGN(sizeof(character_s)); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - if (res != MPS_RES_OK) error("out of memory in make_character"); - obj = addr; - obj->character.type = TYPE_CHARACTER; - obj->character.c = c; - } while(!mps_commit(obj_ap, addr, size)); - total += sizeof(character_s); - return obj; -} - -static obj_t make_vector(size_t length, obj_t fill) -{ - obj_t obj; - mps_addr_t addr; - size_t size = ALIGN(offsetof(vector_s, vector) + length * sizeof(obj_t)); - do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); - size_t i; - if (res != MPS_RES_OK) error("out of memory in make_vector"); - obj = addr; - obj->vector.type = TYPE_VECTOR; - obj->vector.length = length; - for(i = 0; i < length; ++i) - obj->vector.vector[i] = fill; - } while(!mps_commit(obj_ap, addr, size)); - total += size; - return obj; -} - - -/* getnbc -- get next non-blank char from stream */ - -static int getnbc(FILE *stream) -{ - int c; - do - c = getc(stream); - while(isspace(c)); - return c; -} - - -/* isealpha -- test for "extended alphabetic" char - * - * Scheme symbols may contain any "extended alphabetic" - * character (see section 2.1 of R4RS). This function - * returns non-zero if a character is in the set of - * extended characters. - */ - -static int isealpha(int c) -{ - return strchr("+-.*/<=>!?:$%_&~^", c) != NULL; -} - - -/* hash -- hash a string to an unsigned long - * - * This hash function was derived (with permission) from - * Paul Haahr's hash in the most excellent rc 1.4. - */ - -static unsigned long hash(const char *s) { - char c; - unsigned long h=0; - - do { - c=*s++; if(c=='\0') break; else h+=(c<<17)^(c<<11)^(c<<5)^(c>>1); - c=*s++; if(c=='\0') break; else h^=(c<<14)+(c<<7)+(c<<4)+c; - c=*s++; if(c=='\0') break; else h^=(~c<<11)|((c<<3)^(c>>1)); - c=*s++; if(c=='\0') break; else h-=(c<<16)|(c<<9)|(c<<2)|(c&3); - } while(c); - - return h; -} - - -/* find -- find entry for symbol in symbol table - * - * Look for a symbol matching the string in the symbol table. - * If the symbol was found, returns the address of the symbol - * table entry which points to the symbol. Otherwise it - * either returns the address of a NULL entry into which the - * new symbol should be inserted, or NULL if the symbol table - * is full. - */ - -static obj_t *find(char *string) { - unsigned long i, h; - - h = hash(string) & (symtab_size-1); - i = h; - do { - if(symtab[i] == NULL || - strcmp(string, symtab[i]->symbol.string) == 0) - return &symtab[i]; - i = (i+h+1) & (symtab_size-1); - } while(i != h); - - return NULL; -} - - -/* rehash -- double size of symbol table */ - -static void rehash(void) { - obj_t *old_symtab = symtab; - unsigned old_symtab_size = symtab_size; - mps_root_t old_symtab_root = symtab_root; - unsigned i; - mps_res_t res; - - symtab_size *= 2; - symtab = malloc(sizeof(obj_t) * symtab_size); - if(symtab == NULL) error("out of memory"); - - /* Initialize the new table to NULL so that "find" will work. */ - for(i = 0; i < symtab_size; ++i) - symtab[i] = NULL; - - /* Once the symbol table is initialized with scannable references (NULL - in this case) we must register it as a root before we copy objects - across from the old symbol table. The MPS might be moving objects - in memory at any time, and will arrange that both copies are updated - atomically to the mutator (this interpreter). */ - res = mps_root_create_table(&symtab_root, arena, mps_rank_exact(), 0, - (mps_addr_t *)symtab, symtab_size); - if(res != MPS_RES_OK) error("Couldn't register new symtab root"); - - for(i = 0; i < old_symtab_size; ++i) - if(old_symtab[i] != NULL) { - obj_t *where = find(old_symtab[i]->symbol.string); - assert(where != NULL); /* new table shouldn't be full */ - assert(*where == NULL); /* shouldn't be in new table */ - *where = old_symtab[i]; - } - - mps_root_destroy(old_symtab_root); - free(old_symtab); -} - -/* union-find string in symbol table, rehashing if necessary */ -static obj_t intern(char *string) { - obj_t *where; - - where = find(string); - - if(where == NULL) { - rehash(); - where = find(string); - assert(where != NULL); /* shouldn't be full after rehash */ - } - - if(*where == NULL) /* symbol not found in table */ - *where = make_symbol(strlen(string), string); - - return *where; -} - - -static void print(obj_t obj, unsigned depth, FILE *stream) -{ - switch(TYPE(obj)) { - case TYPE_INTEGER: { - fprintf(stream, "%ld", obj->integer.integer); - } break; - - case TYPE_SYMBOL: { - fputs(obj->symbol.string, stream); - } break; - - case TYPE_SPECIAL: { - fputs(obj->special.name, stream); - } break; - - case TYPE_PORT: { - assert(TYPE(obj->port.name) == TYPE_STRING); - fprintf(stream, "#[port \"%s\"]", - obj->port.name->string.string); - } break; - - case TYPE_STRING: { - size_t i; - putc('"', stream); - for(i = 0; i < obj->string.length; ++i) { - char c = obj->string.string[i]; - switch(c) { - case '\\': fputs("\\\\", stream); break; - case '"': fputs("\\\"", stream); break; - default: putc(c, stream); break; - } - } - putc('"', stream); - } break; - - case TYPE_PROMISE: { - assert(CAR(obj) == obj_true || CAR(obj) == obj_false); - fprintf(stream, "#[%sevaluated promise ", - CAR(obj) == obj_false ? "un" : ""); - print(CDR(obj), depth - 1, stream); - putc(']', stream); - } break; - - case TYPE_PAIR: { - if(TYPE(CAR(obj)) == TYPE_SYMBOL && - TYPE(CDR(obj)) == TYPE_PAIR && - CDDR(obj) == obj_empty) { - if(CAR(obj) == obj_quote) { - putc('\'', stream); - if(depth == 0) - fputs("...", stream); - else - print(CADR(obj), depth - 1, stream); - break; - } - if(CAR(obj) == obj_quasiquote) { - putc('`', stream); - if(depth == 0) - fputs("...", stream); - else - print(CADR(obj), depth - 1, stream); - break; - } - if(CAR(obj) == obj_unquote) { - putc(',', stream); - if(depth == 0) - fputs("...", stream); - else - print(CADR(obj), depth - 1, stream); - break; - } - if(CAR(obj) == obj_unquote_splic) { - fputs(",@", stream); - if(depth == 0) - fputs("...", stream); - else - print(CADR(obj), depth - 1, stream); - break; - } - } - putc('(', stream); - if(depth == 0) - fputs("...", stream); - else { - for(;;) { - print(CAR(obj), depth - 1, stream); - obj = CDR(obj); - if(TYPE(obj) != TYPE_PAIR) break; - putc(' ', stream); - } - if(obj != obj_empty) { - fputs(" . ", stream); - print(obj, depth - 1, stream); - } - } - putc(')', stream); - } break; - - case TYPE_VECTOR: { - fputs("#(", stream); - if(depth == 0) - fputs("...", stream); - else { - size_t i; - for(i = 0; i < obj->vector.length; ++i) { - if(i > 0) putc(' ', stream); - print(obj->vector.vector[i], depth - 1, stream); - } - } - putc(')', stream); - } break; - - case TYPE_OPERATOR: { - fprintf(stream, "#[operator \"%s\" %p %p ", - obj->operator.name, - (void *)obj, - (void *)obj->operator.entry); - if(depth == 0) - fputs("...", stream); - else { - print(obj->operator.arguments, depth - 1, stream); - putc(' ', stream); - print(obj->operator.body, depth - 1, stream); - putc(' ', stream); - print(obj->operator.env, depth - 1, stream); - putc(' ', stream); - print(obj->operator.op_env, depth - 1, stream); - } - putc(']', stream); - } break; - - case TYPE_CHARACTER: { - fprintf(stream, "#\\%c", obj->character.c); - } break; - - default: - assert(0); - abort(); - } -} - - -static obj_t read_integer(FILE *stream, int c) -{ - long integer = 0; - - do { - integer = integer*10 + c-'0'; - c = getc(stream); - } while(isdigit(c)); - ungetc(c, stream); - - return make_integer(integer); -} - - -static obj_t read_symbol(FILE *stream, int c) -{ - int length = 0; - char string[SYMMAX+1]; - - do { - string[length++] = tolower(c); - c = getc(stream); - } while(length < SYMMAX && (isalnum(c) || isealpha(c))); - - if(isalnum(c) || isealpha(c)) - error("read: symbol too long"); - - string[length] = '\0'; - - ungetc(c, stream); - - return intern(string); -} - - -static obj_t read_string(FILE *stream, int c) -{ - int length = 0; - char string[STRMAX+1]; - - for(;;) { - c = getc(stream); - if(c == EOF) - error("read: end of file during string"); - if(c == '"') break; - if(length >= STRMAX) - error("read: string too long"); - if(c == '\\') { - c = getc(stream); - switch(c) { - case '\\': break; - case '"': break; - case 'n': c = '\n'; break; - case 't': c = '\t'; break; - case EOF: - error("read: end of file in escape sequence in string"); - default: - error("read: unknown escape '%c'", c); - } - } - string[length++] = c; - } - - string[length] = '\0'; - - return make_string(length, string); -} - - -static obj_t read(FILE *stream); - - -static obj_t read_quote(FILE *stream, int c) -{ - return make_pair(obj_quote, make_pair(read(stream), obj_empty)); -} - - -static obj_t read_quasiquote(FILE *stream, int c) -{ - return make_pair(obj_quasiquote, make_pair(read(stream), obj_empty)); -} - - -static obj_t read_unquote(FILE *stream, int c) -{ - c = getc(stream); - if(c == '@') - return make_pair(obj_unquote_splic, make_pair(read(stream), obj_empty)); - ungetc(c, stream); - return make_pair(obj_unquote, make_pair(read(stream), obj_empty)); -} - - -static obj_t read_list(FILE *stream, int c) -{ - obj_t list, new, end; - - list = obj_empty; - - for(;;) { - c = getnbc(stream); - if(c == ')' || c == '.') break; - ungetc(c, stream); - new = make_pair(read(stream), obj_empty); - if(list == obj_empty) { - list = new; - end = new; - } else { - CDR(end) = new; - end = new; - } - } - - if(c == '.') { - if(list == obj_empty) - error("read: unexpected dot"); - CDR(end) = read(stream); - c = getnbc(stream); - } - - if(c != ')') - error("read: expected close parenthesis"); - - return list; -} - - -static obj_t list_to_vector(obj_t list) -{ - size_t i; - obj_t l, vector; - i = 0; - l = list; - while(TYPE(l) == TYPE_PAIR) { - ++i; - l = CDR(l); - } - if(l != obj_empty) - return obj_error; - vector = make_vector(i, obj_undefined); - i = 0; - l = list; - while(TYPE(l) == TYPE_PAIR) { - vector->vector.vector[i] = CAR(l); - ++i; - l = CDR(l); - } - return vector; -} - - -static obj_t read_special(FILE *stream, int c) -{ - c = getnbc(stream); - switch(tolower(c)) { - case 't': return obj_true; - case 'f': return obj_false; - case '\\': { /* character (R4RS 6.6) */ - c = getc(stream); - if(c == EOF) - error("read: end of file reading character literal"); - return make_character(c); - } - case '(': { /* vector (R4RS 6.8) */ - obj_t list = read_list(stream, c); - obj_t vector = list_to_vector(list); - if(vector == obj_error) - error("read: illegal vector syntax"); - return vector; - } - } - error("read: unknown special '%c'", c); - return obj_error; -} - - -static obj_t read(FILE *stream) -{ - int c; - - c = getnbc(stream); - if(c == EOF) return obj_eof; - - if(isdigit(c)) - return read_integer(stream, c); - - switch(c) { - case '\'': return read_quote(stream, c); - case '`': return read_quasiquote(stream, c); - case ',': return read_unquote(stream, c); - case '(': return read_list(stream, c); - case '#': return read_special(stream, c); - case '"': return read_string(stream, c); - case '-': case '+': { - int next = getc(stream); - if(isdigit(next)) { - obj_t integer = read_integer(stream, next); - if(c == '-') - integer->integer.integer = -integer->integer.integer; - return integer; - } - ungetc(next, stream); - } break; /* fall through to read as symbol */ - } - - if(isalpha(c) || isealpha(c)) - return read_symbol(stream, c); - - error("read: illegal char '%c'", c); - return obj_error; -} - - -/* lookup_in_frame -- look up a symbol in single frame - * - * Search a single frame of the environment for a symbol binding. - */ - -static obj_t lookup_in_frame(obj_t frame, obj_t symbol) -{ - while(frame != obj_empty) { - assert(TYPE(frame) == TYPE_PAIR); - assert(TYPE(CAR(frame)) == TYPE_PAIR); - assert(TYPE(CAAR(frame)) == TYPE_SYMBOL); - if(CAAR(frame) == symbol) - return CAR(frame); - frame = CDR(frame); - } - return obj_undefined; -} - - -/* lookup -- look up symbol in environment - * - * Search an entire environment for a binding of a symbol. - */ - -static obj_t lookup(obj_t env, obj_t symbol) -{ - obj_t binding; - while(env != obj_empty) { - assert(TYPE(env) == TYPE_PAIR); - binding = lookup_in_frame(CAR(env), symbol); - if(binding != obj_undefined) - return binding; - env = CDR(env); - } - return obj_undefined; -} - - -/* define -- define symbol in environment - * - * In Scheme, define will actually rebind (i.e. set) a symbol in the - * same frame of the environment, or add a binding if it wasn't already - * set. This has the effect of making bindings local to functions - * (see how entry_interpret adds an empty frame to the environments), - * allowing recursion, and allowing redefinition at the top level. - * See R4R2 section 5.2 for details. - */ - -static void define(obj_t env, obj_t symbol, obj_t value) -{ - obj_t binding; - assert(TYPE(env) == TYPE_PAIR); /* always at least one frame */ - binding = lookup_in_frame(CAR(env), symbol); - if(binding != obj_undefined) - CDR(binding) = value; - else - CAR(env) = make_pair(make_pair(symbol, value), CAR(env)); -} - - -static obj_t eval(obj_t env, obj_t op_env, obj_t exp); - -static obj_t eval(obj_t env, obj_t op_env, obj_t exp) -{ - for(;;) { - obj_t operator; - obj_t result; - - /* self-evaluating */ - if(TYPE(exp) == TYPE_INTEGER || - (TYPE(exp) == TYPE_SPECIAL && exp != obj_empty) || - TYPE(exp) == TYPE_STRING || - TYPE(exp) == TYPE_CHARACTER) - return exp; - - /* symbol lookup */ - if(TYPE(exp) == TYPE_SYMBOL) { - obj_t binding = lookup(env, exp); - if(binding == obj_undefined) - error("eval: unbound symbol \"%s\"", exp->symbol.string); - return CDR(binding); - } - - if(TYPE(exp) != TYPE_PAIR) { - error("eval: unknown syntax"); - return obj_error; - } - - /* apply operator or function */ - if(TYPE(CAR(exp)) == TYPE_SYMBOL) { - obj_t binding = lookup(op_env, CAR(exp)); - if(binding != obj_undefined) { - operator = CDR(binding); - assert(TYPE(operator) == TYPE_OPERATOR); - result = (*operator->operator.entry)(env, op_env, operator, CDR(exp)); - goto found; - } - } - operator = eval(env, op_env, CAR(exp)); - unless(TYPE(operator) == TYPE_OPERATOR) - error("eval: application of non-function"); - result = (*operator->operator.entry)(env, op_env, operator, CDR(exp)); - - found: - if (!(TYPE(result) == TYPE_PAIR && CAR(result) == obj_tail)) - return result; - - env = CADR(result); - op_env = CADDR(result); - exp = CAR(CDDDR(result)); - } -} - - -/* OPERATOR UTILITIES */ - - -/* eval_list -- evaluate list of expressions giving list of results - * - * eval_list evaluates a list of expresions and yields a list of their - * results, in order. If the list is badly formed, an error is thrown - * using the message given. - */ - -static obj_t eval_list(obj_t env, obj_t op_env, obj_t list, char *message) -{ - obj_t result, end, pair; - result = obj_empty; - while(list != obj_empty) { - if(TYPE(list) != TYPE_PAIR) - error(message); - pair = make_pair(eval(env, op_env, CAR(list)), obj_empty); - if(result == obj_empty) - result = pair; - else - CDR(end) = pair; - end = pair; - list = CDR(list); - } - return result; -} - - -/* eval_args1 -- evaluate some operator arguments - * - * See eval_args and eval_args_rest for usage. - */ - -static obj_t eval_args1(char *name, obj_t env, obj_t op_env, - obj_t operands, unsigned n, va_list args) -{ - unsigned i; - for(i = 0; i < n; ++i) { - unless(TYPE(operands) == TYPE_PAIR) - error("eval: too few arguments to %s", name); - *va_arg(args, obj_t *) = eval(env, op_env, CAR(operands)); - operands = CDR(operands); - } - return operands; -} - - -/* eval_args -- evaluate operator arguments without rest list - * - * eval_args evaluates the first "n" expressions from the list of - * expressions in "operands", returning the rest of the operands - * unevaluated. It puts the results of evaluation in the addresses - * passed in the vararg list. If the operands list is badly formed - * an error is thrown using the operator name passed. For example: - * - * eval_args("foo", env, op_env, operands, 2, &arg1, &arg2); - */ - -static void eval_args(char *name, obj_t env, obj_t op_env, - obj_t operands, unsigned n, ...) -{ - va_list args; - va_start(args, n); - operands = eval_args1(name, env, op_env, operands, n, args); - unless(operands == obj_empty) - error("eval: too many arguments to %s", name); - va_end(args); -} - - -/* eval_args_rest -- evaluate operator arguments with rest list - * - * eval_args_rest evaluates the first "n" expressions from the list of - * expressions in "operands", then evaluates the rest of the operands - * using eval_list and puts the result at *restp. It puts the results - * of evaluating the first "n" operands in the addresses - * passed in the vararg list. If the operands list is badly formed - * an error is thrown using the operator name passed. For example: - * - * eval_args_rest("foo", env, op_env, operands, &rest, 2, &arg1, &arg2); - */ - -static void eval_args_rest(char *name, obj_t env, obj_t op_env, - obj_t operands, obj_t *restp, unsigned n, ...) -{ - va_list args; - va_start(args, n); - operands = eval_args1(name, env, op_env, operands, n, args); - va_end(args); - *restp = eval_list(env, op_env, operands, "eval: badly formed argument list"); -} - - -/* eval_tail -- return an object that will cause eval to loop - * - * Rather than calling `eval` an operator can return a special object that - * causes a calling `eval` to loop, avoiding using up a C stack frame. - * This implements tail recursion (in a simple way). - */ - -static obj_t eval_tail(obj_t env, obj_t op_env, obj_t exp) -{ - return make_pair(obj_tail, - make_pair(env, - make_pair(op_env, - make_pair(exp, - obj_empty)))); -} - - -/* eval_body -- evaluate a list of expressions, returning last result - * - * This is used for the bodies of forms such as let, begin, etc. where - * a list of expressions is allowed. - */ - -static obj_t eval_body(obj_t env, obj_t op_env, obj_t operator, obj_t body) -{ - for (;;) { - if (TYPE(body) != TYPE_PAIR) - error("%s: illegal expression list", operator->operator.name); - if (CDR(body) == obj_empty) - return eval_tail(env, op_env, CAR(body)); - (void)eval(env, op_env, CAR(body)); - body = CDR(body); - } -} - - -/* BUILT-IN OPERATORS */ - - -/* entry_interpret -- interpreted function entry point - * - * When a function is made using lambda (see entry_lambda) an operator - * is created with entry_interpret as its entry point, and the arguments - * and body of the function. The entry_interpret function evaluates - * the operands of the function and binds them to the argument names - * in a new frame added to the lambda's closure environment. It then - * evaluates the body in that environment, executing the function. - */ - -static obj_t entry_interpret(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t arguments, fun_env, fun_op_env; - - assert(TYPE(operator) == TYPE_OPERATOR); - - /* Make a new frame so that bindings are local to the function. */ - /* Arguments will be bound in this new frame. */ - fun_env = make_pair(obj_empty, operator->operator.env); - fun_op_env = make_pair(obj_empty, operator->operator.op_env); - - arguments = operator->operator.arguments; - while(operands != obj_empty) { - if(arguments == obj_empty) - error("eval: function applied to too many arguments"); - if(TYPE(arguments) == TYPE_SYMBOL) { - define(fun_env, arguments, - eval_list(env, op_env, operands, "eval: badly formed argument list")); - operands = obj_empty; - arguments = obj_empty; - } else { - assert(TYPE(arguments) == TYPE_PAIR && - TYPE(CAR(arguments)) == TYPE_SYMBOL); - define(fun_env, - CAR(arguments), - eval(env, op_env, CAR(operands))); - operands = CDR(operands); - arguments = CDR(arguments); - } - } - if(arguments != obj_empty) - error("eval: function applied to too few arguments"); - - return eval_tail(fun_env, fun_op_env, operator->operator.body); -} - - -/* entry_quote -- return operands unevaluated - * - * In Scheme, (quote foo) evaluates to foo (i.e. foo is not evaluated). - * See R4RS 4.1.2. The reader expands "'x" to "(quote x)". - */ - -static obj_t entry_quote(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - unless(TYPE(operands) == TYPE_PAIR && - CDR(operands) == obj_empty) - error("%s: illegal syntax", operator->operator.name); - return CAR(operands); -} - - -/* entry_define -- bind a symbol in the top frame of the environment - * - * In Scheme, "(define )" evaluates expressions - * and binds it to symbol in the top frame of the environment (see - * R4RS 5.2). This code also allows the non-essential syntax for - * define, "(define ( ) )" as a short-hand for - * "(define (lambda () ))". - */ - -static obj_t entry_define(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t symbol, value; - unless(TYPE(operands) == TYPE_PAIR && - TYPE(CDR(operands)) == TYPE_PAIR && - CDDR(operands) == obj_empty) - error("%s: illegal syntax", operator->operator.name); - if(TYPE(CAR(operands)) == TYPE_SYMBOL) { - symbol = CAR(operands); - value = eval(env, op_env, CADR(operands)); - } else if(TYPE(CAR(operands)) == TYPE_PAIR && - TYPE(CAAR(operands)) == TYPE_SYMBOL) { - symbol = CAAR(operands); - value = eval(env, op_env, - make_pair(obj_lambda, - make_pair(CDAR(operands), CDR(operands)))); - } else - error("%s: applied to binder", operator->operator.name); - define(env, symbol, value); - return symbol; -} - - -/* entry_if -- one- or two-armed conditional - * - * "(if )" and "(if )". - * See R4RS 4.1.5. - */ - -static obj_t entry_if(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t test; - unless(TYPE(operands) == TYPE_PAIR && - TYPE(CDR(operands)) == TYPE_PAIR && - (CDDR(operands) == obj_empty || - (TYPE(CDDR(operands)) == TYPE_PAIR && - CDDDR(operands) == obj_empty))) - error("%s: illegal syntax", operator->operator.name); - test = eval(env, op_env, CAR(operands)); - /* Anything which is not #f counts as true [R4RS 6.1]. */ - if(test != obj_false) - return eval_tail(env, op_env, CADR(operands)); - if(TYPE(CDDR(operands)) == TYPE_PAIR) - return eval_tail(env, op_env, CADDR(operands)); - return obj_undefined; -} - - -/* entry_cond -- general conditional - * - * "(cond ( ...) ( ...) ... [(else ...)])" - */ - -static obj_t entry_cond(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - unless(TYPE(operands) == TYPE_PAIR) - error("%s: illegal syntax", operator->operator.name); - while(TYPE(operands) == TYPE_PAIR) { - obj_t clause = CAR(operands); - obj_t result; - unless(TYPE(clause) == TYPE_PAIR && - TYPE(CDR(clause)) == TYPE_PAIR) - error("%s: illegal clause syntax", operator->operator.name); - if(CAR(clause) == obj_else) { - unless(CDR(operands) == obj_empty) - error("%s: else clause must come last", operator->operator.name); - result = obj_true; - } else - result = eval(env, op_env, CAR(clause)); - if(result != obj_false) { - if (CDR(clause) == obj_empty) - return result; - return eval_body(env, op_env, operator, CDR(clause)); - } - operands = CDR(operands); - } - return obj_undefined; -} - - -/* entry_and -- (and ...) */ - -static obj_t entry_and(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t test; - if (operands == obj_empty) - return obj_true; - do { - if (TYPE(operands) != TYPE_PAIR) - error("%s: illegal syntax", operator->operator.name); - if (CDR(operands) == obj_empty) - return eval_tail(env, op_env, CAR(operands)); - test = eval(env, op_env, CAR(operands)); - operands = CDR(operands); - } while (test != obj_false); - return test; -} - - -/* entry_or -- (or ...) */ - -static obj_t entry_or(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t test; - if (operands == obj_empty) - return obj_false; - do { - if (TYPE(operands) != TYPE_PAIR) - error("%s: illegal syntax", operator->operator.name); - if (CDR(operands) == obj_empty) - return eval_tail(env, op_env, CAR(operands)); - test = eval(env, op_env, CAR(operands)); - operands = CDR(operands); - } while (test == obj_false); - return test; -} - - -/* entry_let -- (let ) */ -/* TODO: Too much common code with let* */ - -static obj_t entry_let(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t inner_env, bindings; - unless(TYPE(operands) == TYPE_PAIR && - TYPE(CDR(operands)) == TYPE_PAIR) - error("%s: illegal syntax", operator->operator.name); - inner_env = make_pair(obj_empty, env); /* TODO: common with interpret */ - bindings = CAR(operands); - while(TYPE(bindings) == TYPE_PAIR) { - obj_t binding = CAR(bindings); - unless(TYPE(binding) == TYPE_PAIR && - TYPE(CAR(binding)) == TYPE_SYMBOL && - TYPE(CDR(binding)) == TYPE_PAIR && - CDDR(binding) == obj_empty) - error("%s: illegal binding", operator->operator.name); - define(inner_env, CAR(binding), eval(env, op_env, CADR(binding))); - bindings = CDR(bindings); - } - if(bindings != obj_empty) - error("%s: illegal bindings list", operator->operator.name); - return eval_body(inner_env, op_env, operator, CDR(operands)); -} - - -/* entry_let_star -- (let* ) */ -/* TODO: Too much common code with let */ - -static obj_t entry_let_star(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t inner_env, bindings; - unless(TYPE(operands) == TYPE_PAIR && - TYPE(CDR(operands)) == TYPE_PAIR) - error("%s: illegal syntax", operator->operator.name); - inner_env = make_pair(obj_empty, env); /* TODO: common with interpret */ - bindings = CAR(operands); - while(TYPE(bindings) == TYPE_PAIR) { - obj_t binding = CAR(bindings); - unless(TYPE(binding) == TYPE_PAIR && - TYPE(CAR(binding)) == TYPE_SYMBOL && - TYPE(CDR(binding)) == TYPE_PAIR && - CDDR(binding) == obj_empty) - error("%s: illegal binding", operator->operator.name); - define(inner_env, CAR(binding), eval(inner_env, op_env, CADR(binding))); - bindings = CDR(bindings); - } - if(bindings != obj_empty) - error("%s: illegal bindings list", operator->operator.name); - return eval_body(inner_env, op_env, operator, CDR(operands)); -} - - -/* entry_letrec -- (letrec ) */ -/* TODO: Too much common code with let and let* */ - -static obj_t entry_letrec(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t inner_env, bindings; - unless(TYPE(operands) == TYPE_PAIR && - TYPE(CDR(operands)) == TYPE_PAIR) - error("%s: illegal syntax", operator->operator.name); - inner_env = make_pair(obj_empty, env); /* TODO: common with interpret */ - bindings = CAR(operands); - while(TYPE(bindings) == TYPE_PAIR) { - obj_t binding = CAR(bindings); - unless(TYPE(binding) == TYPE_PAIR && - TYPE(CAR(binding)) == TYPE_SYMBOL && - TYPE(CDR(binding)) == TYPE_PAIR && - CDDR(binding) == obj_empty) - error("%s: illegal binding", operator->operator.name); - define(inner_env, CAR(binding), obj_undefined); - bindings = CDR(bindings); - } - if(bindings != obj_empty) - error("%s: illegal bindings list", operator->operator.name); - bindings = CAR(operands); - while(TYPE(bindings) == TYPE_PAIR) { - obj_t binding = CAR(bindings); - define(inner_env, CAR(binding), eval(inner_env, op_env, CADR(binding))); - bindings = CDR(bindings); - } - return eval_body(inner_env, op_env, operator, CDR(operands)); -} - - -/* entry_do -- (do (( ) ...) ( ...) ...) */ - -static obj_t entry_do(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - error("%s: unimplemented", operator->operator.name); - return obj_error; -} - - -/* entry_delay -- (delay ) */ - -static obj_t entry_delay(obj_t env, obj_t op_env, obj_t operator, obj_t operands) -{ - obj_t promise; - unless(TYPE(operands) == TYPE_PAIR && - CDR(operands) == obj_empty) - error("%s: illegal syntax", operator->operator.name); - promise = make_pair(obj_false, - make_operator("anonymous promise", - entry_interpret, obj_empty, - CAR(operands), env, op_env)); - TYPE(promise) = TYPE_PROMISE; - return promise; -} - - -/* entry_quasiquote -- (quasiquote