From e77136ef881d43abc97f23232c656165ad28be07 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 9 Oct 2012 10:46:58 +0100 Subject: [PATCH] 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/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/critical-path.txt | 391 --- mps/example/scheme/Makefile.in | 8 - mps/example/scheme/scheme.c | 3048 ---------------- mps/license.txt | 83 - 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/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 - 685 files changed, 134412 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/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/critical-path.txt 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/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/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/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/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/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